2009-02-25 13:43:18

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH 0/6] Partial (de)compression Crypto API


Hi Herbert,

The following patch series adds support for partial (de)compression to the
CRYPTO API, and modifies SquashFS 4 to use this:

- [1] netlink: Move netlink attribute parsing support to lib/
- [2] crypto: compress - Add pcomp interface
- [3] crypto: testmgr - Add support for the pcomp interface
- [4] crypto: new zlib crypto module, using pcomp
- [5] crypto: testmgr - add zlib test
- [6] squashfs: Make SquashFS 4 use the new pcomp crypto interface

The patches are based on:
linux-2.6.git + cryptodev-2.6.git

Changes since last version (2009-02-18):
- Use netlink attributes for the (de)compression setup parameters
- Move netlink attribute parsing support to lib/, enabled by CONFIG_NLATTR

David, Phillip: can I please have your ack?

If nobody objects, please apply.

Thanks!

With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 · RPR Brussels
Fortis · BIC GEBABEBB · IBAN BE41293037680010


2009-02-25 13:43:19

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH 1/6] netlink: Move netlink attribute parsing support to lib/

Netlink attribute parsing may be used even if CONFIG_NET is not set.
Move it from net/netlink to lib and control its inclusion based on the new
config symbol CONFIG_NLATTR, which is selected by CONFIG_NET.

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: [email protected]
---
lib/Kconfig | 6 ++++++
lib/Makefile | 2 ++
net/netlink/attr.c => lib/nlattr.c | 0
net/Kconfig | 1 +
net/netlink/Makefile | 2 +-
5 files changed, 10 insertions(+), 1 deletions(-)
rename net/netlink/attr.c => lib/nlattr.c (100%)

diff --git a/lib/Kconfig b/lib/Kconfig
index 03c2c24..cea9e30 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -174,4 +174,10 @@ config DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
bool "Disable obsolete cpumask functions" if DEBUG_PER_CPU_MAPS
depends on EXPERIMENTAL && BROKEN

+#
+# Netlink attribute parsing support is select'ed if needed
+#
+config NLATTR
+ bool
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 32b0e64..b2c09da 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -84,6 +84,8 @@ obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o

obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o

+obj-$(CONFIG_NLATTR) += nlattr.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h

diff --git a/net/netlink/attr.c b/lib/nlattr.c
similarity index 100%
rename from net/netlink/attr.c
rename to lib/nlattr.c
diff --git a/net/Kconfig b/net/Kconfig
index cdb8fde..eab40a4 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -4,6 +4,7 @@

menuconfig NET
bool "Networking support"
+ select NLATTR
---help---
Unless you really know what you are doing, you should say Y here.
The reason is that some programs need kernel networking support even
diff --git a/net/netlink/Makefile b/net/netlink/Makefile
index e3589c2..bdd6ddf 100644
--- a/net/netlink/Makefile
+++ b/net/netlink/Makefile
@@ -2,4 +2,4 @@
# Makefile for the netlink driver.
#

-obj-y := af_netlink.o attr.o genetlink.o
+obj-y := af_netlink.o genetlink.o
--
1.6.0.4


2009-02-25 13:43:20

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH 4/6] crypto: new zlib crypto module, using pcomp

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: James Morris <[email protected]>
---
crypto/Kconfig | 9 +
crypto/Makefile | 1 +
crypto/zlib.c | 378 +++++++++++++++++++++++++++++++++++++++++++++
include/crypto/compress.h | 20 +++
4 files changed, 408 insertions(+), 0 deletions(-)
create mode 100644 crypto/zlib.c

diff --git a/crypto/Kconfig b/crypto/Kconfig
index c00c985..8845eff 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -743,6 +743,15 @@ config CRYPTO_DEFLATE

You will most probably want this if using IPSec.

+config CRYPTO_ZLIB
+ tristate "Zlib compression algorithm"
+ select CRYPTO_PCOMP
+ select ZLIB_INFLATE
+ select ZLIB_DEFLATE
+ select NLATTR
+ help
+ This is the zlib algorithm.
+
config CRYPTO_LZO
tristate "LZO compression algorithm"
select CRYPTO_ALGAPI
diff --git a/crypto/Makefile b/crypto/Makefile
index 8de194f..836a764 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
obj-$(CONFIG_CRYPTO_SEED) += seed.o
obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o
obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o
obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
diff --git a/crypto/zlib.c b/crypto/zlib.c
new file mode 100644
index 0000000..33609ba
--- /dev/null
+++ b/crypto/zlib.c
@@ -0,0 +1,378 @@
+/*
+ * Cryptographic API.
+ *
+ * Zlib algorithm
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * Based on deflate.c, which is
+ * Copyright (c) 2003 James Morris <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * FIXME: deflate transforms will require up to a total of about 436k of kernel
+ * memory on i386 (390k for compression, the rest for decompression), as the
+ * current zlib kernel code uses a worst case pre-allocation system by default.
+ * This needs to be fixed so that the amount of memory required is properly
+ * related to the winbits and memlevel parameters.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/zlib.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+#include <linux/slab.h>
+
+#include <crypto/internal/compress.h>
+
+#include <net/netlink.h>
+
+
+struct zlib_ctx {
+ struct z_stream_s comp_stream;
+ struct z_stream_s decomp_stream;
+ int decomp_windowBits;
+};
+
+
+static void zlib_comp_exit(struct zlib_ctx *ctx)
+{
+ struct z_stream_s *stream = &ctx->comp_stream;
+
+ if (stream->workspace) {
+ zlib_deflateEnd(stream);
+ vfree(stream->workspace);
+ stream->workspace = NULL;
+ }
+}
+
+static void zlib_decomp_exit(struct zlib_ctx *ctx)
+{
+ struct z_stream_s *stream = &ctx->decomp_stream;
+
+ if (stream->workspace) {
+ zlib_inflateEnd(stream);
+ kfree(stream->workspace);
+ stream->workspace = NULL;
+ }
+}
+
+static int zlib_init(struct crypto_tfm *tfm)
+{
+ return 0;
+}
+
+static void zlib_exit(struct crypto_tfm *tfm)
+{
+ struct zlib_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ zlib_comp_exit(ctx);
+ zlib_decomp_exit(ctx);
+}
+
+
+static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
+ unsigned int len)
+{
+ struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &ctx->comp_stream;
+ struct nlattr *tb[ZLIB_COMP_MAX + 1];
+ size_t workspacesize;
+ int ret;
+
+ ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL);
+ if (ret)
+ return ret;
+
+ zlib_comp_exit(ctx);
+
+ workspacesize = zlib_deflate_workspacesize();
+ stream->workspace = vmalloc(workspacesize);
+ if (!stream->workspace)
+ return -ENOMEM;
+
+ memset(stream->workspace, 0, workspacesize);
+ ret = zlib_deflateInit2(stream,
+ tb[ZLIB_COMP_LEVEL]
+ ? nla_get_u32(tb[ZLIB_COMP_LEVEL])
+ : Z_DEFAULT_COMPRESSION,
+ tb[ZLIB_COMP_METHOD]
+ ? nla_get_u32(tb[ZLIB_COMP_METHOD])
+ : Z_DEFLATED,
+ tb[ZLIB_COMP_WINDOWBITS]
+ ? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
+ : MAX_WBITS,
+ tb[ZLIB_COMP_MEMLEVEL]
+ ? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
+ : DEF_MEM_LEVEL,
+ tb[ZLIB_COMP_STRATEGY]
+ ? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
+ : Z_DEFAULT_STRATEGY);
+ if (ret != Z_OK) {
+ vfree(stream->workspace);
+ stream->workspace = NULL;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int zlib_compress_init(struct crypto_pcomp *tfm)
+{
+ int ret;
+ struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &dctx->comp_stream;
+
+ ret = zlib_deflateReset(stream);
+ if (ret != Z_OK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int zlib_compress_update(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &dctx->comp_stream;
+
+ pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+ stream->next_in = req->next_in;
+ stream->avail_in = req->avail_in;
+ stream->next_out = req->next_out;
+ stream->avail_out = req->avail_out;
+
+ ret = zlib_deflate(stream, Z_NO_FLUSH);
+ switch (ret) {
+ case Z_OK:
+ break;
+
+ case Z_BUF_ERROR:
+ pr_debug("zlib_deflate could not make progress\n");
+ return -EAGAIN;
+
+ default:
+ pr_debug("zlib_deflate failed %d\n", ret);
+ return -EINVAL;
+ }
+
+ pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ stream->avail_in, stream->avail_out,
+ req->avail_in - stream->avail_in,
+ req->avail_out - stream->avail_out);
+ req->next_in = stream->next_in;
+ req->avail_in = stream->avail_in;
+ req->next_out = stream->next_out;
+ req->avail_out = stream->avail_out;
+ return 0;
+}
+
+static int zlib_compress_final(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &dctx->comp_stream;
+
+ pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+ stream->next_in = req->next_in;
+ stream->avail_in = req->avail_in;
+ stream->next_out = req->next_out;
+ stream->avail_out = req->avail_out;
+
+ ret = zlib_deflate(stream, Z_FINISH);
+ if (ret != Z_STREAM_END) {
+ pr_debug("zlib_deflate failed %d\n", ret);
+ return -EINVAL;
+ }
+
+ pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ stream->avail_in, stream->avail_out,
+ req->avail_in - stream->avail_in,
+ req->avail_out - stream->avail_out);
+ req->next_in = stream->next_in;
+ req->avail_in = stream->avail_in;
+ req->next_out = stream->next_out;
+ req->avail_out = stream->avail_out;
+ return 0;
+}
+
+
+static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params,
+ unsigned int len)
+{
+ struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &ctx->decomp_stream;
+ struct nlattr *tb[ZLIB_DECOMP_MAX + 1];
+ int ret = 0;
+
+ ret = nla_parse(tb, ZLIB_DECOMP_MAX, params, len, NULL);
+ if (ret)
+ return ret;
+
+ zlib_decomp_exit(ctx);
+
+ ctx->decomp_windowBits = tb[ZLIB_DECOMP_WINDOWBITS]
+ ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS])
+ : DEF_WBITS;
+
+ stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+ if (!stream->workspace)
+ return -ENOMEM;
+
+ ret = zlib_inflateInit2(stream, ctx->decomp_windowBits);
+ if (ret != Z_OK) {
+ kfree(stream->workspace);
+ stream->workspace = NULL;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int zlib_decompress_init(struct crypto_pcomp *tfm)
+{
+ int ret;
+ struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &dctx->decomp_stream;
+
+ ret = zlib_inflateReset(stream);
+ if (ret != Z_OK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int zlib_decompress_update(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &dctx->decomp_stream;
+
+ pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+ stream->next_in = req->next_in;
+ stream->avail_in = req->avail_in;
+ stream->next_out = req->next_out;
+ stream->avail_out = req->avail_out;
+
+ ret = zlib_inflate(stream, Z_SYNC_FLUSH);
+ switch (ret) {
+ case Z_OK:
+ case Z_STREAM_END:
+ break;
+
+ case Z_BUF_ERROR:
+ pr_debug("zlib_inflate could not make progress\n");
+ return -EAGAIN;
+
+ default:
+ pr_debug("zlib_inflate failed %d\n", ret);
+ return -EINVAL;
+ }
+
+ pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ stream->avail_in, stream->avail_out,
+ req->avail_in - stream->avail_in,
+ req->avail_out - stream->avail_out);
+ req->next_in = stream->next_in;
+ req->avail_in = stream->avail_in;
+ req->next_out = stream->next_out;
+ req->avail_out = stream->avail_out;
+ return 0;
+}
+
+static int zlib_decompress_final(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
+ struct z_stream_s *stream = &dctx->decomp_stream;
+
+ pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out);
+ stream->next_in = req->next_in;
+ stream->avail_in = req->avail_in;
+ stream->next_out = req->next_out;
+ stream->avail_out = req->avail_out;
+
+ if (dctx->decomp_windowBits < 0) {
+ ret = zlib_inflate(stream, Z_SYNC_FLUSH);
+ /*
+ * Work around a bug in zlib, which sometimes wants to taste an
+ * extra byte when being used in the (undocumented) raw deflate
+ * mode. (From USAGI).
+ */
+ if (ret == Z_OK && !stream->avail_in && stream->avail_out) {
+ const void *saved_next_in = stream->next_in;
+ u8 zerostuff = 0;
+
+ stream->next_in = &zerostuff;
+ stream->avail_in = 1;
+ ret = zlib_inflate(stream, Z_FINISH);
+ stream->next_in = saved_next_in;
+ stream->avail_in = 0;
+ }
+ } else
+ ret = zlib_inflate(stream, Z_FINISH);
+ if (ret != Z_STREAM_END) {
+ pr_debug("zlib_inflate failed %d\n", ret);
+ return -EINVAL;
+ }
+
+ pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
+ stream->avail_in, stream->avail_out,
+ req->avail_in - stream->avail_in,
+ req->avail_out - stream->avail_out);
+ req->next_in = stream->next_in;
+ req->avail_in = stream->avail_in;
+ req->next_out = stream->next_out;
+ req->avail_out = stream->avail_out;
+ return 0;
+}
+
+
+static struct pcomp_alg zlib_alg = {
+ .compress_setup = zlib_compress_setup,
+ .compress_init = zlib_compress_init,
+ .compress_update = zlib_compress_update,
+ .compress_final = zlib_compress_final,
+ .decompress_setup = zlib_decompress_setup,
+ .decompress_init = zlib_decompress_init,
+ .decompress_update = zlib_decompress_update,
+ .decompress_final = zlib_decompress_final,
+
+ .base = {
+ .cra_name = "zlib",
+ .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS,
+ .cra_ctxsize = sizeof(struct zlib_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_init = zlib_init,
+ .cra_exit = zlib_exit,
+ }
+};
+
+static int __init zlib_mod_init(void)
+{
+ return crypto_register_pcomp(&zlib_alg);
+}
+
+static void __exit zlib_mod_fini(void)
+{
+ crypto_unregister_pcomp(&zlib_alg);
+}
+
+module_init(zlib_mod_init);
+module_exit(zlib_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Zlib Compression Algorithm");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/include/crypto/compress.h b/include/crypto/compress.h
index b7d2287..86163ef 100644
--- a/include/crypto/compress.h
+++ b/include/crypto/compress.h
@@ -30,6 +30,26 @@ struct comp_request {
unsigned int avail_out; /* bytes available at next_out */
};

+enum zlib_comp_params {
+ ZLIB_COMP_LEVEL = 1, /* e.g. Z_DEFAULT_COMPRESSION */
+ ZLIB_COMP_METHOD, /* e.g. Z_DEFLATED */
+ ZLIB_COMP_WINDOWBITS, /* e.g. MAX_WBITS */
+ ZLIB_COMP_MEMLEVEL, /* e.g. DEF_MEM_LEVEL */
+ ZLIB_COMP_STRATEGY, /* e.g. Z_DEFAULT_STRATEGY */
+ __ZLIB_COMP_MAX,
+};
+
+#define ZLIB_COMP_MAX (__ZLIB_COMP_MAX - 1)
+
+
+enum zlib_decomp_params {
+ ZLIB_DECOMP_WINDOWBITS = 1, /* e.g. DEF_WBITS */
+ __ZLIB_DECOMP_MAX,
+};
+
+#define ZLIB_DECOMP_MAX (__ZLIB_DECOMP_MAX - 1)
+
+
struct crypto_pcomp {
struct crypto_tfm base;
};
--
1.6.0.4


2009-02-25 13:43:20

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH 5/6] crypto: testmgr - add zlib test

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/Kconfig | 1 +
crypto/tcrypt.c | 6 ++-
crypto/testmgr.c | 15 ++++++
crypto/testmgr.h | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 158 insertions(+), 1 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 8845eff..632330d 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -91,6 +91,7 @@ config CRYPTO_MANAGER2
select CRYPTO_AEAD2
select CRYPTO_HASH2
select CRYPTO_BLKCIPHER2
+ select CRYPTO_PCOMP

config CRYPTO_GF128MUL
tristate "GF(2^128) multiplication functions (EXPERIMENTAL)"
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 28a45a1..c3c9124 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -53,7 +53,7 @@ static char *check[] = {
"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt",
"camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320",
- "lzo", "cts", NULL
+ "lzo", "cts", "zlib", NULL
};

static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc,
@@ -661,6 +661,10 @@ static void do_test(int m)
tcrypt_test("ecb(seed)");
break;

+ case 44:
+ tcrypt_test("zlib");
+ break;
+
case 100:
tcrypt_test("hmac(md5)");
break;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index e750357..b50c3c6 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2018,6 +2018,21 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}
}
+ }, {
+ .alg = "zlib",
+ .test = alg_test_pcomp,
+ .suite = {
+ .pcomp = {
+ .comp = {
+ .vecs = zlib_comp_tv_template,
+ .count = ZLIB_COMP_TEST_VECTORS
+ },
+ .decomp = {
+ .vecs = zlib_decomp_tv_template,
+ .count = ZLIB_DECOMP_TEST_VECTORS
+ }
+ }
+ }
}
};

diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index c517e43..526f00a 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -15,6 +15,9 @@
#ifndef _CRYPTO_TESTMGR_H
#define _CRYPTO_TESTMGR_H

+#include <linux/netlink.h>
+#include <linux/zlib.h>
+
#include <crypto/compress.h>

#define MAX_DIGEST_SIZE 64
@@ -8361,6 +8364,7 @@ struct pcomp_testvec {
* Deflate test vectors (null-terminated strings).
* Params: winbits=-11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL.
*/
+
#define DEFLATE_COMP_TEST_VECTORS 2
#define DEFLATE_DECOMP_TEST_VECTORS 2

@@ -8436,6 +8440,139 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
},
};

+#define ZLIB_COMP_TEST_VECTORS 2
+#define ZLIB_DECOMP_TEST_VECTORS 2
+
+static const struct {
+ struct nlattr nla;
+ int val;
+} deflate_comp_params[] = {
+ {
+ .nla = {
+ .nla_len = NLA_HDRLEN + sizeof(int),
+ .nla_type = ZLIB_COMP_LEVEL,
+ },
+ .val = Z_DEFAULT_COMPRESSION,
+ }, {
+ .nla = {
+ .nla_len = NLA_HDRLEN + sizeof(int),
+ .nla_type = ZLIB_COMP_METHOD,
+ },
+ .val = Z_DEFLATED,
+ }, {
+ .nla = {
+ .nla_len = NLA_HDRLEN + sizeof(int),
+ .nla_type = ZLIB_COMP_WINDOWBITS,
+ },
+ .val = -11,
+ }, {
+ .nla = {
+ .nla_len = NLA_HDRLEN + sizeof(int),
+ .nla_type = ZLIB_COMP_MEMLEVEL,
+ },
+ .val = MAX_MEM_LEVEL,
+ }, {
+ .nla = {
+ .nla_len = NLA_HDRLEN + sizeof(int),
+ .nla_type = ZLIB_COMP_STRATEGY,
+ },
+ .val = Z_DEFAULT_STRATEGY,
+ }
+};
+
+static const struct {
+ struct nlattr nla;
+ int val;
+} deflate_decomp_params[] = {
+ {
+ .nla = {
+ .nla_len = NLA_HDRLEN + sizeof(int),
+ .nla_type = ZLIB_DECOMP_WINDOWBITS,
+ },
+ .val = -11,
+ }
+};
+
+static struct pcomp_testvec zlib_comp_tv_template[] = {
+ {
+ .params = &deflate_comp_params,
+ .paramsize = sizeof(deflate_comp_params),
+ .inlen = 70,
+ .outlen = 38,
+ .input = "Join us now and share the software "
+ "Join us now and share the software ",
+ .output = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56"
+ "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51"
+ "\x28\xce\x48\x2c\x4a\x55\x28\xc9"
+ "\x48\x55\x28\xce\x4f\x2b\x29\x07"
+ "\x71\xbc\x08\x2b\x01\x00",
+ }, {
+ .params = &deflate_comp_params,
+ .paramsize = sizeof(deflate_comp_params),
+ .inlen = 191,
+ .outlen = 122,
+ .input = "This document describes a compression method based on the DEFLATE"
+ "compression algorithm. This document defines the application of "
+ "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+ .output = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04"
+ "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09"
+ "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8"
+ "\x24\xdb\x67\xd9\x47\xc1\xef\x49"
+ "\x68\x12\x51\xae\x76\x67\xd6\x27"
+ "\x19\x88\x1a\xde\x85\xab\x21\xf2"
+ "\x08\x5d\x16\x1e\x20\x04\x2d\xad"
+ "\xf3\x18\xa2\x15\x85\x2d\x69\xc4"
+ "\x42\x83\x23\xb6\x6c\x89\x71\x9b"
+ "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f"
+ "\xed\x62\xa9\x4c\x80\xff\x13\xaf"
+ "\x52\x37\xed\x0e\x52\x6b\x59\x02"
+ "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98"
+ "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a"
+ "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79"
+ "\xfa\x02",
+ },
+};
+
+static struct pcomp_testvec zlib_decomp_tv_template[] = {
+ {
+ .params = &deflate_decomp_params,
+ .paramsize = sizeof(deflate_decomp_params),
+ .inlen = 122,
+ .outlen = 191,
+ .input = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04"
+ "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09"
+ "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8"
+ "\x24\xdb\x67\xd9\x47\xc1\xef\x49"
+ "\x68\x12\x51\xae\x76\x67\xd6\x27"
+ "\x19\x88\x1a\xde\x85\xab\x21\xf2"
+ "\x08\x5d\x16\x1e\x20\x04\x2d\xad"
+ "\xf3\x18\xa2\x15\x85\x2d\x69\xc4"
+ "\x42\x83\x23\xb6\x6c\x89\x71\x9b"
+ "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f"
+ "\xed\x62\xa9\x4c\x80\xff\x13\xaf"
+ "\x52\x37\xed\x0e\x52\x6b\x59\x02"
+ "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98"
+ "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a"
+ "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79"
+ "\xfa\x02",
+ .output = "This document describes a compression method based on the DEFLATE"
+ "compression algorithm. This document defines the application of "
+ "the DEFLATE algorithm to the IP Payload Compression Protocol.",
+ }, {
+ .params = &deflate_decomp_params,
+ .paramsize = sizeof(deflate_decomp_params),
+ .inlen = 38,
+ .outlen = 70,
+ .input = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56"
+ "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51"
+ "\x28\xce\x48\x2c\x4a\x55\x28\xc9"
+ "\x48\x55\x28\xce\x4f\x2b\x29\x07"
+ "\x71\xbc\x08\x2b\x01\x00",
+ .output = "Join us now and share the software "
+ "Join us now and share the software ",
+ },
+};
+
/*
* LZO test vectors (null-terminated strings).
*/
--
1.6.0.4


2009-02-25 13:43:19

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH 2/6] crypto: compress - Add pcomp interface

The current "comp" crypto interface supports one-shot (de)compression only,
i.e. the whole data buffer to be (de)compressed must be passed at once, and
the whole (de)compressed data buffer will be received at once.
In several use-cases (e.g. compressed file systems that store files in big
compressed blocks), this workflow is not suitable.
Furthermore, the "comp" type doesn't provide for the configuration of
(de)compression parameters, and always allocates workspace memory for both
compression and decompression, which may waste memory.

To solve this, add a "pcomp" partial (de)compression interface that provides
the following operations:
- crypto_compress_{init,update,final}() for compression,
- crypto_decompress_{init,update,final}() for decompression,
- crypto_{,de}compress_setup(), to configure (de)compression parameters
(incl. allocating workspace memory).

The (de)compression methods take a struct comp_request, which was mimicked
after the z_stream object in zlib, and contains buffer pointer and length
pairs for input and output.

The setup methods take an opaque parameter pointer and length pair. Parameters
are supposed to be encoded using netlink attributes, whose meanings depend on
the actual (name of the) (de)compression algorithm.

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/Kconfig | 4 +
crypto/Makefile | 2 +
crypto/pcompress.c | 97 ++++++++++++++++++++++++++++
include/crypto/compress.h | 125 ++++++++++++++++++++++++++++++++++++
include/crypto/internal/compress.h | 28 ++++++++
include/linux/crypto.h | 1 +
6 files changed, 257 insertions(+), 0 deletions(-)
create mode 100644 crypto/pcompress.c
create mode 100644 include/crypto/compress.h
create mode 100644 include/crypto/internal/compress.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index a83ce04..c00c985 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -75,6 +75,10 @@ config CRYPTO_RNG2
tristate
select CRYPTO_ALGAPI2

+config CRYPTO_PCOMP
+ tristate
+ select CRYPTO_ALGAPI2
+
config CRYPTO_MANAGER
tristate "Cryptographic algorithm manager"
select CRYPTO_MANAGER2
diff --git a/crypto/Makefile b/crypto/Makefile
index 46b08bf..8de194f 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -25,6 +25,8 @@ crypto_hash-objs += ahash.o
crypto_hash-objs += shash.o
obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o

+obj-$(CONFIG_CRYPTO_PCOMP) += pcompress.o
+
cryptomgr-objs := algboss.o testmgr.o

obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
diff --git a/crypto/pcompress.c b/crypto/pcompress.c
new file mode 100644
index 0000000..ca9a4af
--- /dev/null
+++ b/crypto/pcompress.c
@@ -0,0 +1,97 @@
+/*
+ * Cryptographic API.
+ *
+ * Partial (de)compression operations.
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/crypto.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+
+#include <crypto/compress.h>
+
+#include "internal.h"
+
+
+static int crypto_pcomp_init(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+ return 0;
+}
+
+static unsigned int crypto_pcomp_extsize(struct crypto_alg *alg,
+ const struct crypto_type *frontend)
+{
+ return alg->cra_ctxsize;
+}
+
+static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm,
+ const struct crypto_type *frontend)
+{
+ return 0;
+}
+
+static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
+ __attribute__ ((unused));
+static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ seq_printf(m, "type : pcomp\n");
+}
+
+static const struct crypto_type crypto_pcomp_type = {
+ .extsize = crypto_pcomp_extsize,
+ .init = crypto_pcomp_init,
+ .init_tfm = crypto_pcomp_init_tfm,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_pcomp_show,
+#endif
+ .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_MASK,
+ .type = CRYPTO_ALG_TYPE_PCOMPRESS,
+ .tfmsize = offsetof(struct crypto_pcomp, base),
+};
+
+struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type,
+ u32 mask)
+{
+ return crypto_alloc_tfm(alg_name, &crypto_pcomp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_pcomp);
+
+int crypto_register_pcomp(struct pcomp_alg *alg)
+{
+ struct crypto_alg *base = &alg->base;
+
+ base->cra_type = &crypto_pcomp_type;
+ base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+ base->cra_flags |= CRYPTO_ALG_TYPE_PCOMPRESS;
+
+ return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_pcomp);
+
+int crypto_unregister_pcomp(struct pcomp_alg *alg)
+{
+ return crypto_unregister_alg(&alg->base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_pcomp);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Partial (de)compression type");
+MODULE_AUTHOR("Sony Corporation");
diff --git a/include/crypto/compress.h b/include/crypto/compress.h
new file mode 100644
index 0000000..b7d2287
--- /dev/null
+++ b/include/crypto/compress.h
@@ -0,0 +1,125 @@
+/*
+ * Compress: Compression algorithms under the cryptographic API.
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CRYPTO_COMPRESS_H
+#define _CRYPTO_COMPRESS_H
+
+#include <linux/crypto.h>
+
+
+struct comp_request {
+ const void *next_in; /* next input byte */
+ void *next_out; /* next output byte */
+ unsigned int avail_in; /* bytes available at next_in */
+ unsigned int avail_out; /* bytes available at next_out */
+};
+
+struct crypto_pcomp {
+ struct crypto_tfm base;
+};
+
+struct pcomp_alg {
+ int (*compress_setup)(struct crypto_pcomp *tfm, void *params,
+ unsigned int len);
+ int (*compress_init)(struct crypto_pcomp *tfm);
+ int (*compress_update)(struct crypto_pcomp *tfm,
+ struct comp_request *req);
+ int (*compress_final)(struct crypto_pcomp *tfm,
+ struct comp_request *req);
+ int (*decompress_setup)(struct crypto_pcomp *tfm, void *params,
+ unsigned int len);
+ int (*decompress_init)(struct crypto_pcomp *tfm);
+ int (*decompress_update)(struct crypto_pcomp *tfm,
+ struct comp_request *req);
+ int (*decompress_final)(struct crypto_pcomp *tfm,
+ struct comp_request *req);
+
+ struct crypto_alg base;
+};
+
+extern struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type,
+ u32 mask);
+
+static inline struct crypto_tfm *crypto_pcomp_tfm(struct crypto_pcomp *tfm)
+{
+ return &tfm->base;
+}
+
+static inline void crypto_free_pcomp(struct crypto_pcomp *tfm)
+{
+ crypto_destroy_tfm(tfm, crypto_pcomp_tfm(tfm));
+}
+
+static inline struct pcomp_alg *__crypto_pcomp_alg(struct crypto_alg *alg)
+{
+ return container_of(alg, struct pcomp_alg, base);
+}
+
+static inline struct pcomp_alg *crypto_pcomp_alg(struct crypto_pcomp *tfm)
+{
+ return __crypto_pcomp_alg(crypto_pcomp_tfm(tfm)->__crt_alg);
+}
+
+static inline int crypto_compress_setup(struct crypto_pcomp *tfm,
+ void *params, unsigned int len)
+{
+ return crypto_pcomp_alg(tfm)->compress_setup(tfm, params, len);
+}
+
+static inline int crypto_compress_init(struct crypto_pcomp *tfm)
+{
+ return crypto_pcomp_alg(tfm)->compress_init(tfm);
+}
+
+static inline int crypto_compress_update(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->compress_update(tfm, req);
+}
+
+static inline int crypto_compress_final(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->compress_final(tfm, req);
+}
+
+static inline int crypto_decompress_setup(struct crypto_pcomp *tfm,
+ void *params, unsigned int len)
+{
+ return crypto_pcomp_alg(tfm)->decompress_setup(tfm, params, len);
+}
+
+static inline int crypto_decompress_init(struct crypto_pcomp *tfm)
+{
+ return crypto_pcomp_alg(tfm)->decompress_init(tfm);
+}
+
+static inline int crypto_decompress_update(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->decompress_update(tfm, req);
+}
+
+static inline int crypto_decompress_final(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->decompress_final(tfm, req);
+}
+
+#endif /* _CRYPTO_COMPRESS_H */
diff --git a/include/crypto/internal/compress.h b/include/crypto/internal/compress.h
new file mode 100644
index 0000000..178a888
--- /dev/null
+++ b/include/crypto/internal/compress.h
@@ -0,0 +1,28 @@
+/*
+ * Compress: Compression algorithms under the cryptographic API.
+ *
+ * Copyright 2008 Sony Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CRYPTO_INTERNAL_COMPRESS_H
+#define _CRYPTO_INTERNAL_COMPRESS_H
+
+#include <crypto/compress.h>
+
+extern int crypto_register_pcomp(struct pcomp_alg *alg);
+extern int crypto_unregister_pcomp(struct pcomp_alg *alg);
+
+#endif /* _CRYPTO_INTERNAL_COMPRESS_H */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 29729b8..ec29fa2 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -40,6 +40,7 @@
#define CRYPTO_ALG_TYPE_SHASH 0x00000009
#define CRYPTO_ALG_TYPE_AHASH 0x0000000a
#define CRYPTO_ALG_TYPE_RNG 0x0000000c
+#define CRYPTO_ALG_TYPE_PCOMPRESS 0x0000000f

#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c
--
1.6.0.4


2009-02-25 13:43:20

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH 3/6] crypto: testmgr - Add support for the pcomp interface

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/testmgr.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
crypto/testmgr.h | 10 +++
2 files changed, 193 insertions(+), 0 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index a75f11f..e750357 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -72,6 +72,13 @@ struct comp_test_suite {
} comp, decomp;
};

+struct pcomp_test_suite {
+ struct {
+ struct pcomp_testvec *vecs;
+ unsigned int count;
+ } comp, decomp;
+};
+
struct hash_test_suite {
struct hash_testvec *vecs;
unsigned int count;
@@ -86,6 +93,7 @@ struct alg_test_desc {
struct aead_test_suite aead;
struct cipher_test_suite cipher;
struct comp_test_suite comp;
+ struct pcomp_test_suite pcomp;
struct hash_test_suite hash;
} suite;
};
@@ -898,6 +906,159 @@ out:
return ret;
}

+static int test_pcomp(struct crypto_pcomp *tfm,
+ struct pcomp_testvec *ctemplate,
+ struct pcomp_testvec *dtemplate, int ctcount,
+ int dtcount)
+{
+ const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm));
+ unsigned int i;
+ char result[COMP_BUF_SIZE];
+ int error;
+
+ for (i = 0; i < ctcount; i++) {
+ struct comp_request req;
+
+ error = crypto_compress_setup(tfm, ctemplate[i].params,
+ ctemplate[i].paramsize);
+ if (error) {
+ pr_err("alg: pcomp: compression setup failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ error = crypto_compress_init(tfm);
+ if (error) {
+ pr_err("alg: pcomp: compression init failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ memset(result, 0, sizeof(result));
+
+ req.next_in = ctemplate[i].input;
+ req.avail_in = ctemplate[i].inlen / 2;
+ req.next_out = result;
+ req.avail_out = ctemplate[i].outlen / 2;
+
+ error = crypto_compress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: compression update failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ /* Add remaining input data */
+ req.avail_in += (ctemplate[i].inlen + 1) / 2;
+
+ error = crypto_compress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: compression update failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ /* Provide remaining output space */
+ req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2;
+
+ error = crypto_compress_final(tfm, &req);
+ if (error) {
+ pr_err("alg: pcomp: compression final failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) {
+ pr_err("alg: comp: Compression test %d failed for %s: "
+ "output len = %d (expected %d)\n", i + 1, algo,
+ COMP_BUF_SIZE - req.avail_out,
+ ctemplate[i].outlen);
+ return -EINVAL;
+ }
+
+ if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) {
+ pr_err("alg: pcomp: Compression test %d failed for "
+ "%s\n", i + 1, algo);
+ hexdump(result, ctemplate[i].outlen);
+ return -EINVAL;
+ }
+ }
+
+ for (i = 0; i < dtcount; i++) {
+ struct comp_request req;
+
+ error = crypto_decompress_setup(tfm, dtemplate[i].params,
+ dtemplate[i].paramsize);
+ if (error) {
+ pr_err("alg: pcomp: decompression setup failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ error = crypto_decompress_init(tfm);
+ if (error) {
+ pr_err("alg: pcomp: decompression init failed on test "
+ "%d for %s: error=%d\n", i + 1, algo, error);
+ return error;
+ }
+
+ memset(result, 0, sizeof(result));
+
+ req.next_in = dtemplate[i].input;
+ req.avail_in = dtemplate[i].inlen / 2;
+ req.next_out = result;
+ req.avail_out = dtemplate[i].outlen / 2;
+
+ error = crypto_decompress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: decompression update failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ /* Add remaining input data */
+ req.avail_in += (dtemplate[i].inlen + 1) / 2;
+
+ error = crypto_decompress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: decompression update failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ /* Provide remaining output space */
+ req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2;
+
+ error = crypto_decompress_final(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_err("alg: pcomp: decompression final failed on "
+ "test %d for %s: error=%d\n", i + 1, algo,
+ error);
+ return error;
+ }
+
+ if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) {
+ pr_err("alg: comp: Decompression test %d failed for "
+ "%s: output len = %d (expected %d)\n", i + 1,
+ algo, COMP_BUF_SIZE - req.avail_out,
+ dtemplate[i].outlen);
+ return -EINVAL;
+ }
+
+ if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) {
+ pr_err("alg: pcomp: Decompression test %d failed for "
+ "%s\n", i + 1, algo);
+ hexdump(result, dtemplate[i].outlen);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int alg_test_aead(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask)
{
@@ -1007,6 +1168,28 @@ static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
return err;
}

+static int alg_test_pcomp(const struct alg_test_desc *desc, const char *driver,
+ u32 type, u32 mask)
+{
+ struct crypto_pcomp *tfm;
+ int err;
+
+ tfm = crypto_alloc_pcomp(driver, type, mask);
+ if (IS_ERR(tfm)) {
+ pr_err("alg: pcomp: Failed to load transform for %s: %ld\n",
+ driver, PTR_ERR(tfm));
+ return PTR_ERR(tfm);
+ }
+
+ err = test_pcomp(tfm, desc->suite.pcomp.comp.vecs,
+ desc->suite.pcomp.decomp.vecs,
+ desc->suite.pcomp.comp.count,
+ desc->suite.pcomp.decomp.count);
+
+ crypto_free_pcomp(tfm);
+ return err;
+}
+
static int alg_test_hash(const struct alg_test_desc *desc, const char *driver,
u32 type, u32 mask)
{
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 132953e..c517e43 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -15,6 +15,8 @@
#ifndef _CRYPTO_TESTMGR_H
#define _CRYPTO_TESTMGR_H

+#include <crypto/compress.h>
+
#define MAX_DIGEST_SIZE 64
#define MAX_TAP 8

@@ -8347,6 +8349,14 @@ struct comp_testvec {
char output[COMP_BUF_SIZE];
};

+struct pcomp_testvec {
+ void *params;
+ unsigned int paramsize;
+ int inlen, outlen;
+ char input[COMP_BUF_SIZE];
+ char output[COMP_BUF_SIZE];
+};
+
/*
* Deflate test vectors (null-terminated strings).
* Params: winbits=-11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL.
--
1.6.0.4


2009-02-25 13:43:21

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface

Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression,
instead of calling the underlying zlib library directly. This simplifies e.g.
the addition of support for hardware decompression and different decompression
algorithms.

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: Phillip Lougher <[email protected]>
---
fs/squashfs/Kconfig | 3 +-
fs/squashfs/block.c | 80 +++++++++++++++++++++++------------------
fs/squashfs/squashfs_fs_sb.h | 2 +-
fs/squashfs/super.c | 44 +++++++++++++++++++----
4 files changed, 84 insertions(+), 45 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 25a00d1..18e33a6 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -1,7 +1,8 @@
config SQUASHFS
tristate "SquashFS 4.0 - Squashed file system support"
depends on BLOCK
- select ZLIB_INFLATE
+ select CRYPTO
+ select CRYPTO_ZLIB
help
Saying Y here includes support for SquashFS 4.0 (a Compressed
Read-Only File System). Squashfs is a highly compressed read-only
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index c837dfc..5a3e628 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -32,7 +32,8 @@
#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
-#include <linux/zlib.h>
+
+#include <crypto/compress.h>

#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
@@ -153,7 +154,9 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
}

if (compressed) {
- int zlib_err = 0, zlib_init = 0;
+ int error = 0, decomp_init = 0;
+ struct comp_request req;
+ unsigned int produced = 0;

/*
* Uncompress block.
@@ -161,12 +164,13 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,

mutex_lock(&msblk->read_data_mutex);

- msblk->stream.avail_out = 0;
- msblk->stream.avail_in = 0;
+ req.avail_out = 0;
+ req.avail_in = 0;

bytes = length;
+ length = 0;
do {
- if (msblk->stream.avail_in == 0 && k < b) {
+ if (req.avail_in == 0 && k < b) {
avail = min(bytes, msblk->devblksize - offset);
bytes -= avail;
wait_on_buffer(bh[k]);
@@ -179,50 +183,56 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
continue;
}

- msblk->stream.next_in = bh[k]->b_data + offset;
- msblk->stream.avail_in = avail;
+ req.next_in = bh[k]->b_data + offset;
+ req.avail_in = avail;
offset = 0;
}

- if (msblk->stream.avail_out == 0) {
- msblk->stream.next_out = buffer[page++];
- msblk->stream.avail_out = PAGE_CACHE_SIZE;
+ if (req.avail_out == 0) {
+ req.next_out = buffer[page++];
+ req.avail_out = PAGE_CACHE_SIZE;
}

- if (!zlib_init) {
- zlib_err = zlib_inflateInit(&msblk->stream);
- if (zlib_err != Z_OK) {
- ERROR("zlib_inflateInit returned"
- " unexpected result 0x%x,"
- " srclength %d\n", zlib_err,
- srclength);
+ if (!decomp_init) {
+ error = crypto_decompress_init(msblk->tfm);
+ if (error) {
+ ERROR("crypto_decompress_init "
+ "returned %d, srclength %d\n",
+ error, srclength);
goto release_mutex;
}
- zlib_init = 1;
+ decomp_init = 1;
+ }
+
+ produced = req.avail_out;
+ error = crypto_decompress_update(msblk->tfm, &req);
+ if (error) {
+ ERROR("crypto_decompress_update returned %d, "
+ "srclength %d, avail_in %d, avail_out "
+ "%d\n", error, srclength, req.avail_in,
+ req.avail_out);
+ goto release_mutex;
}
+ produced -= req.avail_out;

- zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
+ length += produced;

- if (msblk->stream.avail_in == 0 && k < b)
+ if (req.avail_in == 0 && k < b)
put_bh(bh[k++]);
- } while (zlib_err == Z_OK);
-
- if (zlib_err != Z_STREAM_END) {
- ERROR("zlib_inflate returned unexpected result"
- " 0x%x, srclength %d, avail_in %d,"
- " avail_out %d\n", zlib_err, srclength,
- msblk->stream.avail_in,
- msblk->stream.avail_out);
- goto release_mutex;
- }

- zlib_err = zlib_inflateEnd(&msblk->stream);
- if (zlib_err != Z_OK) {
- ERROR("zlib_inflateEnd returned unexpected result 0x%x,"
- " srclength %d\n", zlib_err, srclength);
+ } while (bytes || produced);
+
+ produced = req.avail_out;
+ error = crypto_decompress_final(msblk->tfm, &req);
+ if (error) {
+ ERROR("crypto_decompress_final returned %d, srclength "
+ "%d\n", error, srclength);
goto release_mutex;
}
- length = msblk->stream.total_out;
+ produced -= req.avail_out;
+
+ length += produced;
+
mutex_unlock(&msblk->read_data_mutex);
} else {
/*
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index c8c6561..4eae75b 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -64,7 +64,7 @@ struct squashfs_sb_info {
struct mutex read_data_mutex;
struct mutex meta_index_mutex;
struct meta_index *meta_index;
- z_stream stream;
+ struct crypto_pcomp *tfm;
__le64 *inode_lookup_table;
u64 inode_table;
u64 directory_table;
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 071df5b..62be5ae 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -37,11 +37,19 @@
#include <linux/zlib.h>
#include <linux/magic.h>

+#include <crypto/compress.h>
+
+#include <net/netlink.h>
+
#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
#include "squashfs_fs_i.h"
#include "squashfs.h"

+
+#define SQUASHFS_CRYPTO_ALG "zlib"
+
+
static struct file_system_type squashfs_fs_type;
static struct super_operations squashfs_super_ops;

@@ -75,6 +83,16 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
unsigned short flags;
unsigned int fragments;
u64 lookup_table_start;
+ struct {
+ struct nlattr nla;
+ int val;
+ } params = {
+ .nla = {
+ .nla_len = nla_attr_size(sizeof(int)),
+ .nla_type = ZLIB_DECOMP_WINDOWBITS,
+ },
+ .val = DEF_WBITS,
+ };
int err;

TRACE("Entered squashfs_fill_superblock\n");
@@ -86,16 +104,25 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
}
msblk = sb->s_fs_info;

- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
- GFP_KERNEL);
- if (msblk->stream.workspace == NULL) {
- ERROR("Failed to allocate zlib workspace\n");
+ msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(msblk->tfm)) {
+ ERROR("Failed to load %s crypto module\n",
+ SQUASHFS_CRYPTO_ALG);
+ err = PTR_ERR(msblk->tfm);
+ goto failed_pcomp;
+ }
+
+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
+ if (err) {
+ ERROR("Failed to set up decompression parameters\n");
goto failure;
}

sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
if (sblk == NULL) {
ERROR("Failed to allocate squashfs_super_block\n");
+ err = -ENOMEM;
goto failure;
}

@@ -284,17 +311,18 @@ failed_mount:
kfree(msblk->inode_lookup_table);
kfree(msblk->fragment_index);
kfree(msblk->id_table);
- kfree(msblk->stream.workspace);
+ crypto_free_pcomp(msblk->tfm);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
kfree(sblk);
return err;

failure:
- kfree(msblk->stream.workspace);
+ crypto_free_pcomp(msblk->tfm);
+failed_pcomp:
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
- return -ENOMEM;
+ return err;
}


@@ -333,7 +361,7 @@ static void squashfs_put_super(struct super_block *sb)
kfree(sbi->id_table);
kfree(sbi->fragment_index);
kfree(sbi->meta_index);
- kfree(sbi->stream.workspace);
+ crypto_free_pcomp(sbi->tfm);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
}
--
1.6.0.4


2009-02-25 21:59:58

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 1/6] netlink: Move netlink attribute parsing support to lib/

From: Geert Uytterhoeven <[email protected]>
Date: Wed, 25 Feb 2009 14:43:09 +0100

> Netlink attribute parsing may be used even if CONFIG_NET is not set.
> Move it from net/netlink to lib and control its inclusion based on the new
> config symbol CONFIG_NLATTR, which is selected by CONFIG_NET.
>
> Signed-off-by: Geert Uytterhoeven <[email protected]>

Acked-by: David S. Miller <[email protected]>

2009-03-07 10:46:42

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface

On Wed, Feb 25, 2009 at 02:43:14PM +0100, Geert Uytterhoeven wrote:
> Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression,
> instead of calling the underlying zlib library directly. This simplifies e.g.
> the addition of support for hardware decompression and different decompression
> algorithms.
>
> Signed-off-by: Geert Uytterhoeven <[email protected]>
> Cc: Phillip Lougher <[email protected]>

I've applied patches 1-5. I'd like to see an ack on this before
applying it.

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2009-03-08 06:47:56

by Phillip Lougher

[permalink] [raw]
Subject: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface

Herbert Xu wrote:
> On Wed, Feb 25, 2009 at 02:43:14PM +0100, Geert Uytterhoeven wrote:
>> Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression,
>> instead of calling the underlying zlib library directly. This simplifies e.g.
>> the addition of support for hardware decompression and different decompression
>> algorithms.
>>
>> Signed-off-by: Geert Uytterhoeven <[email protected]>
>> Cc: Phillip Lougher <[email protected]>
>
> I've applied patches 1-5. I'd like to see an ack on this before
> applying it.
>

I've not acked it because I've not yet made any decisions as to whether
I want it in Squashfs. Also as Squashfs maintainer I maintain my own
tree of patches to Squashfs, and so I'll prefer to add it to my tree for
subsequent feeding into 2.6.30 once the merge window opens.

I'm fairly agnostic about what decompression library Squashfs uses. The
only thing I care about is cleanliness and usability of the API and
performance. If the crypto API is cleaner or the cryto zlib
implementation is faster than the current zlib implementation then I see
no reason not to move over to it. But, I've seen no performance figures
and the API seems clumsier.

Two API issues of concern (one major, one minor). Both of these relate
to the way Squashfs drives the decompression code, where it repeatedly
calls it supplying additional input/output buffers, rather than using a
"single-shot" approach where it calls the decompression code once
supplying all the necessary input and output buffer space.

1. Minor issue -the lack of a stream.total_out field. The current
zlib_inflate code collects the total number of bytes decompressed over
the multiple calls into the stream.total_out field.

There is clearly no such field available in the cryto API, leading
to the somewhat clumsy need to track it, i.e. it leads to the following
additional code.

+ unsigned int produced = 0;

[snip]

> + length = 0;

[snip]
> + produced = req.avail_out;
> + error = crypto_decompress_update(msblk->tfm, &req);

> + produced -= req.avail_out;
>
> + length += produced;
>

[snip]
> + produced = req.avail_out;
> + error = crypto_decompress_final(msblk->tfm, &req);

> + produced -= req.avail_out;
> +
> + length += produced;


Whereas previously, only the following single line was required:

> - length = msblk->stream.total_out;

2. Major issue - working out loop termination.

It transpires when decompressing from multiple input buffers into
multiple output buffers, determining when the decompressor has consumed
all input buffers and has flushed all output to the output buffers is
difficult.

One might assume loop termination can take place once the decompressor
has consumed all the input data - however, this is insufficient because
the decompressor may exit having consumed all the input data but it
still requires additional output buffer space (stream.avail_in == 0,
stream.avail_out == 0).

This leads to the exit condition (stream.avail_in == 0 &&
stream.avail_out != 0). However, this still isn't sufficient because
the majority of blocks in Squashfs decompress to an exact multiple of
the output buffer, i.e. stream.avail_in == 0 && stream.avail_out == 0 is
true at the end of decompression.

(stream.avail_in == 0 && stream_avail_out == 0) == true may or may not
indicate the end of decompression. In other words the status of the
input/output buffers doesn't give sufficient information as to whether
to terminate the loop or not.

With zlib_inflate this is irrelevant because it supplies a suitable exit
code indicating whether it needs to be called again (Z_OK) or whether
decompression has finished (Z_STREAM_END). This makes loop termination
easy.

My biggest criticism against the cryto changes to Squashfs is
crypto_decompress_update doesn't seem to give this information, leaving
to the clumsy introduction of a check to see if crypto_decompress_update
produced any output data, i.e.:

- } while (zlib_err == Z_OK);
> -

is replaced by:

> + } while (bytes || produced);
> +

This is clearly suboptimal, and always leads to an additional iteration
around the loop. Only once we've iterated over the loop one last time
doing nothing do we decide the decompression has completed.

Not only this, but the loop termination also suffers from a major
unanticipated bug:

The loop termination forces an additional iteration around the loop even
though we've run out of output buffer space.

Consider the usual scenario where we're decompressing a buffer into two
4K pages (pages = 2), and the buffer decompresses to 8K. The final
"real" iteration will have produced != 0 and req.avail_out == 0 (we've
consumed all the output bytes in the last output buffer).

Because produced != 0 we will iterate over the loop again. But because
req.avail_out == 0 we will load req.next_out with a non-existent buffer
(we will fall off the end of the buffer array), i.e.

+ if (req.avail_out == 0) {
> + req.next_out = buffer[page++];
> + req.avail_out = PAGE_CACHE_SIZE;
> }
>

If for any reason crypto_decompress_update produces unexpected output
(perhaps because of corrupted data), we will trigger a kernel oops.

Obviously in the majority of cases (which is why the code works), the
"false" additional iteration doesn't produce any output. But it is
distinctly bad practice to have code in the kernel that in normal
operation passes a bad pointer to crypto_decompress_output, and relies
on its behaviour not to use that bad pointer.

> Thanks,

Currently as it stands I cannot accept the patch into Squashfs for the
above reasons. The code is less optimal, suffers from a major bug, and
has a number of workarounds stemming from what I feel is a less
"featureful" API.

I'm willing to consider moving Squashfs over to the crypto API once my
concerns have been addressed. The promised simplification in the
"addition of support for hardware decompression and different
decompression algorithms" seems quite attractive. But I'm unwilling to
degrade the zlib support in Squashfs for this future promise.

Phillip


2009-03-11 17:59:41

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface

Hi Phillip,

On Sun, 8 Mar 2009, Phillip Lougher wrote:
> Herbert Xu wrote:
> > On Wed, Feb 25, 2009 at 02:43:14PM +0100, Geert Uytterhoeven wrote:
> > > Modify SquashFS 4 to use the new "pcomp" crypto interface for
> > > decompression,
> > > instead of calling the underlying zlib library directly. This simplifies
> > > e.g.
> > > the addition of support for hardware decompression and different
> > > decompression
> > > algorithms.
> > >
> > > Signed-off-by: Geert Uytterhoeven <[email protected]>
> > > Cc: Phillip Lougher <[email protected]>
> >
> > I've applied patches 1-5. I'd like to see an ack on this before
> > applying it.
>
> I've not acked it because I've not yet made any decisions as to whether I want
> it in Squashfs. Also as Squashfs maintainer I maintain my own tree of patches
> to Squashfs, and so I'll prefer to add it to my tree for subsequent feeding
> into 2.6.30 once the merge window opens.

OK.

> I'm fairly agnostic about what decompression library Squashfs uses. The only
> thing I care about is cleanliness and usability of the API and performance.
> If the crypto API is cleaner or the cryto zlib implementation is faster than
> the current zlib implementation then I see no reason not to move over to it.
> But, I've seen no performance figures and the API seems clumsier.

I did not see any noticeable performance impact due to my changes.

> Two API issues of concern (one major, one minor). Both of these relate to the
> way Squashfs drives the decompression code, where it repeatedly calls it
> supplying additional input/output buffers, rather than using a "single-shot"
> approach where it calls the decompression code once supplying all the
> necessary input and output buffer space.
>
> 1. Minor issue -the lack of a stream.total_out field. The current
> zlib_inflate code collects the total number of bytes decompressed over the
> multiple calls into the stream.total_out field.
>
> There is clearly no such field available in the cryto API, leading to the
> somewhat clumsy need to track it, i.e. it leads to the following additional
> code.

If people feel the need for a total_out field, I can add it to struct
comp_request.

BTW, what about total_in, which is also provided by plain zlib's z_stream?
Do people see a need for a similar field?

> 2. Major issue - working out loop termination.
>
> It transpires when decompressing from multiple input buffers into multiple
> output buffers, determining when the decompressor has consumed all input
> buffers and has flushed all output to the output buffers is difficult.

[...]

> With zlib_inflate this is irrelevant because it supplies a suitable exit code
> indicating whether it needs to be called again (Z_OK) or whether decompression
> has finished (Z_STREAM_END). This makes loop termination easy.

Zlib indeed provides such a flag. Other decompression algorithms may not
provide this, and keep on `decompressing' as long as you feed them data.

So while I could add an output flag indicating decompression has finished, it
cannot be more than a mere hint when considering support for multiple
(de)compression algorithms.

> My biggest criticism against the cryto changes to Squashfs is
> crypto_decompress_update doesn't seem to give this information, leaving to the
> clumsy introduction of a check to see if crypto_decompress_update produced any
> output data, i.e.:
>
> - } while (zlib_err == Z_OK);
> > -
>
> is replaced by:
>
> > + } while (bytes || produced);
> > +
>
> This is clearly suboptimal, and always leads to an additional iteration around
> the loop. Only once we've iterated over the loop one last time doing nothing
> do we decide the decompression has completed.

Given the difficulty in determining the finishing of decompression in a generic
way, I don't see a better solution. If no data has been consumed nor produced,
and no -EAGAIN is returned, decompression is finished.

BTW, this is also very similar to reading from a file: read() returns a
non-zero count until the end of the file is reached.

The additional loop also doesn't seem to have any noticeable impact on
performance, though.

> Not only this, but the loop termination also suffers from a major
> unanticipated bug:
>
> The loop termination forces an additional iteration around the loop even
> though we've run out of output buffer space.
>
> Consider the usual scenario where we're decompressing a buffer into two 4K
> pages (pages = 2), and the buffer decompresses to 8K. The final "real"
> iteration will have produced != 0 and req.avail_out == 0 (we've consumed all
> the output bytes in the last output buffer).
>
> Because produced != 0 we will iterate over the loop again. But because
> req.avail_out == 0 we will load req.next_out with a non-existent buffer (we
> will fall off the end of the buffer array), i.e.
>
> + if (req.avail_out == 0) {
> > + req.next_out = buffer[page++];
> > + req.avail_out = PAGE_CACHE_SIZE;
> > }
> >
>
> If for any reason crypto_decompress_update produces unexpected output (perhaps
> because of corrupted data), we will trigger a kernel oops.
>
> Obviously in the majority of cases (which is why the code works), the "false"
> additional iteration doesn't produce any output. But it is distinctly bad
> practice to have code in the kernel that in normal operation passes a bad
> pointer to crypto_decompress_output, and relies on its behaviour not to use
> that bad pointer.

You are right. Hence this needs a check for page < pages, cfr. your recent fix
to survive corrupted file system images. I'll take care of that.

Thanks for your comments!

With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-03-17 12:45:03

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface

On Wed, 25 Feb 2009, Geert Uytterhoeven wrote:
> Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression,
> instead of calling the underlying zlib library directly. This simplifies e.g.
> the addition of support for hardware decompression and different decompression
> algorithms.

This is an updated patch, to accomodate for the recent changes in SquashFS.
---
From 46b8e0ab105e9b414d455c0a7205a7c79f0517e8 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <[email protected]>
Date: Thu, 18 Dec 2008 14:35:22 +0100
Subject: [PATCH] squashfs: Make SquashFS 4 use the new pcomp crypto interface

Modify SquashFS 4 to use the new "pcomp" crypto interface for decompression,
instead of calling the underlying zlib library directly. This simplifies e.g.
the addition of support for hardware decompression and different decompression
algorithms.

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: Phillip Lougher <[email protected]>
---
fs/squashfs/Kconfig | 3 +-
fs/squashfs/block.c | 70 ++++++++++++++++++++++++-----------------
fs/squashfs/squashfs_fs_sb.h | 2 +-
fs/squashfs/super.c | 44 +++++++++++++++++++++-----
4 files changed, 80 insertions(+), 39 deletions(-)

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index 25a00d1..18e33a6 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -1,7 +1,8 @@
config SQUASHFS
tristate "SquashFS 4.0 - Squashed file system support"
depends on BLOCK
- select ZLIB_INFLATE
+ select CRYPTO
+ select CRYPTO_ZLIB
help
Saying Y here includes support for SquashFS 4.0 (a Compressed
Read-Only File System). Squashfs is a highly compressed read-only
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 2a79603..6196821 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -32,7 +32,8 @@
#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
-#include <linux/zlib.h>
+
+#include <crypto/compress.h>

#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
@@ -153,7 +154,9 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
}

if (compressed) {
- int zlib_err = 0, zlib_init = 0;
+ int error = 0, decomp_init = 0;
+ struct comp_request req;
+ unsigned int produced = 0;

/*
* Uncompress block.
@@ -161,12 +164,13 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,

mutex_lock(&msblk->read_data_mutex);

- msblk->stream.avail_out = 0;
- msblk->stream.avail_in = 0;
+ req.avail_out = 0;
+ req.avail_in = 0;

bytes = length;
+ length = 0;
do {
- if (msblk->stream.avail_in == 0 && k < b) {
+ if (req.avail_in == 0 && k < b) {
avail = min(bytes, msblk->devblksize - offset);
bytes -= avail;
wait_on_buffer(bh[k]);
@@ -179,45 +183,53 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
continue;
}

- msblk->stream.next_in = bh[k]->b_data + offset;
- msblk->stream.avail_in = avail;
+ req.next_in = bh[k]->b_data + offset;
+ req.avail_in = avail;
offset = 0;
}

- if (msblk->stream.avail_out == 0 && page < pages) {
- msblk->stream.next_out = buffer[page++];
- msblk->stream.avail_out = PAGE_CACHE_SIZE;
+ if (req.avail_out == 0 && page < pages) {
+ req.next_out = buffer[page++];
+ req.avail_out = PAGE_CACHE_SIZE;
}

- if (!zlib_init) {
- zlib_err = zlib_inflateInit(&msblk->stream);
- if (zlib_err != Z_OK) {
- ERROR("zlib_inflateInit returned"
- " unexpected result 0x%x,"
- " srclength %d\n", zlib_err,
- srclength);
+ if (!decomp_init) {
+ error = crypto_decompress_init(msblk->tfm);
+ if (error) {
+ ERROR("crypto_decompress_init "
+ "returned %d, srclength %d\n",
+ error, srclength);
goto release_mutex;
}
- zlib_init = 1;
+ decomp_init = 1;
+ }
+
+ produced = req.avail_out;
+ error = crypto_decompress_update(msblk->tfm, &req);
+ if (error) {
+ ERROR("crypto_decompress_update returned %d, "
+ "data probably corrupt\n", error);
+ goto release_mutex;
}
+ produced -= req.avail_out;

- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
+ length += produced;

- if (msblk->stream.avail_in == 0 && k < b)
+ if (req.avail_in == 0 && k < b)
put_bh(bh[k++]);
- } while (zlib_err == Z_OK);
+ } while (bytes || produced);

- if (zlib_err != Z_STREAM_END) {
- ERROR("zlib_inflate error, data probably corrupt\n");
+ produced = req.avail_out;
+ error = crypto_decompress_final(msblk->tfm, &req);
+ if (error) {
+ ERROR("crypto_decompress_final returned %d, data "
+ "probably corrupt\n", error);
goto release_mutex;
}
+ produced -= req.avail_out;
+
+ length += produced;

- zlib_err = zlib_inflateEnd(&msblk->stream);
- if (zlib_err != Z_OK) {
- ERROR("zlib_inflate error, data probably corrupt\n");
- goto release_mutex;
- }
- length = msblk->stream.total_out;
mutex_unlock(&msblk->read_data_mutex);
} else {
/*
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index c8c6561..4eae75b 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -64,7 +64,7 @@ struct squashfs_sb_info {
struct mutex read_data_mutex;
struct mutex meta_index_mutex;
struct meta_index *meta_index;
- z_stream stream;
+ struct crypto_pcomp *tfm;
__le64 *inode_lookup_table;
u64 inode_table;
u64 directory_table;
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 681ec0d..2b63f54 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -37,11 +37,19 @@
#include <linux/zlib.h>
#include <linux/magic.h>

+#include <crypto/compress.h>
+
+#include <net/netlink.h>
+
#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
#include "squashfs_fs_i.h"
#include "squashfs.h"

+
+#define SQUASHFS_CRYPTO_ALG "zlib"
+
+
static struct file_system_type squashfs_fs_type;
static struct super_operations squashfs_super_ops;

@@ -75,6 +83,16 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
unsigned short flags;
unsigned int fragments;
u64 lookup_table_start;
+ struct {
+ struct nlattr nla;
+ int val;
+ } params = {
+ .nla = {
+ .nla_len = nla_attr_size(sizeof(int)),
+ .nla_type = ZLIB_DECOMP_WINDOWBITS,
+ },
+ .val = DEF_WBITS,
+ };
int err;

TRACE("Entered squashfs_fill_superblock\n");
@@ -86,16 +104,25 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
}
msblk = sb->s_fs_info;

- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
- GFP_KERNEL);
- if (msblk->stream.workspace == NULL) {
- ERROR("Failed to allocate zlib workspace\n");
+ msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(msblk->tfm)) {
+ ERROR("Failed to load %s crypto module\n",
+ SQUASHFS_CRYPTO_ALG);
+ err = PTR_ERR(msblk->tfm);
+ goto failed_pcomp;
+ }
+
+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
+ if (err) {
+ ERROR("Failed to set up decompression parameters\n");
goto failure;
}

sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
if (sblk == NULL) {
ERROR("Failed to allocate squashfs_super_block\n");
+ err = -ENOMEM;
goto failure;
}

@@ -284,17 +311,18 @@ failed_mount:
kfree(msblk->inode_lookup_table);
kfree(msblk->fragment_index);
kfree(msblk->id_table);
- kfree(msblk->stream.workspace);
+ crypto_free_pcomp(msblk->tfm);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
kfree(sblk);
return err;

failure:
- kfree(msblk->stream.workspace);
+ crypto_free_pcomp(msblk->tfm);
+failed_pcomp:
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
- return -ENOMEM;
+ return err;
}


@@ -333,7 +361,7 @@ static void squashfs_put_super(struct super_block *sb)
kfree(sbi->id_table);
kfree(sbi->fragment_index);
kfree(sbi->meta_index);
- kfree(sbi->stream.workspace);
+ crypto_free_pcomp(sbi->tfm);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
}
--
1.6.0.4


With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-03-17 12:54:05

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface)

On Wed, 11 Mar 2009, Geert Uytterhoeven wrote:
> On Sun, 8 Mar 2009, Phillip Lougher wrote:
> > Two API issues of concern (one major, one minor). Both of these relate to the
> > way Squashfs drives the decompression code, where it repeatedly calls it
> > supplying additional input/output buffers, rather than using a "single-shot"
> > approach where it calls the decompression code once supplying all the
> > necessary input and output buffer space.
> >
> > 1. Minor issue -the lack of a stream.total_out field. The current
> > zlib_inflate code collects the total number of bytes decompressed over the
> > multiple calls into the stream.total_out field.
> >
> > There is clearly no such field available in the cryto API, leading to the
> > somewhat clumsy need to track it, i.e. it leads to the following additional
> > code.
>
> If people feel the need for a total_out field, I can add it to struct
> comp_request.
>
> BTW, what about total_in, which is also provided by plain zlib's z_stream?
> Do people see a need for a similar field?

The patch below (on top of the updated one to convert SquashFS to pcomp) adds
comp_request.total_out, so you don't have to calculate and accumulate the
decompressed output sizes in SquashFS.

Notes:
- This required the addition of a `struct comp_request *' parameter to
crypto_{,de}compress_init()
- Still, there's one of the

produced = req.avail_out;
...
produced -= req.avail_out;

left, as this is part of the logic to discover the end of decompression
(no bytes produced, no error returned).

Perhaps it's better to instead make crypto_{,de}compress_{update,final}()
return the (positive) number of output bytes (of the current step)?

Currently it returns zero (no error) or a negative error value.
That would allow to get rid of both `produced = ... / produced -= ...'
constructs, but the user would have to accumulate the total output size again
(which is not such a big deal, IMHO).

Thanks for your comments!

From e43f85baa75668be4cce340ae98a3b76e66a452a Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <[email protected]>
Date: Mon, 16 Mar 2009 15:53:30 +0100
Subject: [PATCH] crypto: compress - Add comp_request.total_out

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/testmgr.c | 4 ++--
crypto/zlib.c | 12 ++++++++++--
fs/squashfs/block.c | 10 +++-------
include/crypto/compress.h | 17 +++++++++++------
4 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index b50c3c6..2b112ae 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -927,7 +927,7 @@ static int test_pcomp(struct crypto_pcomp *tfm,
return error;
}

- error = crypto_compress_init(tfm);
+ error = crypto_compress_init(tfm, &req);
if (error) {
pr_err("alg: pcomp: compression init failed on test "
"%d for %s: error=%d\n", i + 1, algo, error);
@@ -996,7 +996,7 @@ static int test_pcomp(struct crypto_pcomp *tfm,
return error;
}

- error = crypto_decompress_init(tfm);
+ error = crypto_decompress_init(tfm, &req);
if (error) {
pr_err("alg: pcomp: decompression init failed on test "
"%d for %s: error=%d\n", i + 1, algo, error);
diff --git a/crypto/zlib.c b/crypto/zlib.c
index 33609ba..93ec380 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -125,7 +125,8 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
return 0;
}

-static int zlib_compress_init(struct crypto_pcomp *tfm)
+static int zlib_compress_init(struct crypto_pcomp *tfm,
+ struct comp_request *req)
{
int ret;
struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
@@ -135,6 +136,7 @@ static int zlib_compress_init(struct crypto_pcomp *tfm)
if (ret != Z_OK)
return -EINVAL;

+ req->total_out = 0;
return 0;
}

@@ -173,6 +175,7 @@ static int zlib_compress_update(struct crypto_pcomp *tfm,
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
+ req->total_out = stream->total_out;
return 0;
}

@@ -203,6 +206,7 @@ static int zlib_compress_final(struct crypto_pcomp *tfm,
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
+ req->total_out = stream->total_out;
return 0;
}

@@ -239,7 +243,8 @@ static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params,
return 0;
}

-static int zlib_decompress_init(struct crypto_pcomp *tfm)
+static int zlib_decompress_init(struct crypto_pcomp *tfm,
+ struct comp_request *req)
{
int ret;
struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
@@ -249,6 +254,7 @@ static int zlib_decompress_init(struct crypto_pcomp *tfm)
if (ret != Z_OK)
return -EINVAL;

+ req->total_out = 0;
return 0;
}

@@ -288,6 +294,7 @@ static int zlib_decompress_update(struct crypto_pcomp *tfm,
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
+ req->total_out = stream->total_out;
return 0;
}

@@ -336,6 +343,7 @@ static int zlib_decompress_final(struct crypto_pcomp *tfm,
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
+ req->total_out = stream->total_out;
return 0;
}

diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 6196821..11e19b6 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -168,7 +168,6 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
req.avail_in = 0;

bytes = length;
- length = 0;
do {
if (req.avail_in == 0 && k < b) {
avail = min(bytes, msblk->devblksize - offset);
@@ -194,7 +193,8 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
}

if (!decomp_init) {
- error = crypto_decompress_init(msblk->tfm);
+ error = crypto_decompress_init(msblk->tfm,
+ &req);
if (error) {
ERROR("crypto_decompress_init "
"returned %d, srclength %d\n",
@@ -213,22 +213,18 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
}
produced -= req.avail_out;

- length += produced;
-
if (req.avail_in == 0 && k < b)
put_bh(bh[k++]);
} while (bytes || produced);

- produced = req.avail_out;
error = crypto_decompress_final(msblk->tfm, &req);
if (error) {
ERROR("crypto_decompress_final returned %d, data "
"probably corrupt\n", error);
goto release_mutex;
}
- produced -= req.avail_out;

- length += produced;
+ length = req.total_out;

mutex_unlock(&msblk->read_data_mutex);
} else {
diff --git a/include/crypto/compress.h b/include/crypto/compress.h
index 86163ef..d872c06 100644
--- a/include/crypto/compress.h
+++ b/include/crypto/compress.h
@@ -28,6 +28,7 @@ struct comp_request {
void *next_out; /* next output byte */
unsigned int avail_in; /* bytes available at next_in */
unsigned int avail_out; /* bytes available at next_out */
+ size_t total_out; /* total bytes output so far */
};

enum zlib_comp_params {
@@ -57,14 +58,16 @@ struct crypto_pcomp {
struct pcomp_alg {
int (*compress_setup)(struct crypto_pcomp *tfm, void *params,
unsigned int len);
- int (*compress_init)(struct crypto_pcomp *tfm);
+ int (*compress_init)(struct crypto_pcomp *tfm,
+ struct comp_request *req);
int (*compress_update)(struct crypto_pcomp *tfm,
struct comp_request *req);
int (*compress_final)(struct crypto_pcomp *tfm,
struct comp_request *req);
int (*decompress_setup)(struct crypto_pcomp *tfm, void *params,
unsigned int len);
- int (*decompress_init)(struct crypto_pcomp *tfm);
+ int (*decompress_init)(struct crypto_pcomp *tfm,
+ struct comp_request *req);
int (*decompress_update)(struct crypto_pcomp *tfm,
struct comp_request *req);
int (*decompress_final)(struct crypto_pcomp *tfm,
@@ -102,9 +105,10 @@ static inline int crypto_compress_setup(struct crypto_pcomp *tfm,
return crypto_pcomp_alg(tfm)->compress_setup(tfm, params, len);
}

-static inline int crypto_compress_init(struct crypto_pcomp *tfm)
+static inline int crypto_compress_init(struct crypto_pcomp *tfm,
+ struct comp_request *req)
{
- return crypto_pcomp_alg(tfm)->compress_init(tfm);
+ return crypto_pcomp_alg(tfm)->compress_init(tfm, req);
}

static inline int crypto_compress_update(struct crypto_pcomp *tfm,
@@ -125,9 +129,10 @@ static inline int crypto_decompress_setup(struct crypto_pcomp *tfm,
return crypto_pcomp_alg(tfm)->decompress_setup(tfm, params, len);
}

-static inline int crypto_decompress_init(struct crypto_pcomp *tfm)
+static inline int crypto_decompress_init(struct crypto_pcomp *tfm,
+ struct comp_request *req)
{
- return crypto_pcomp_alg(tfm)->decompress_init(tfm);
+ return crypto_pcomp_alg(tfm)->decompress_init(tfm, req);
}

static inline int crypto_decompress_update(struct crypto_pcomp *tfm,
--
1.6.0.4

With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-03-24 16:33:01

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface))

On Tue, 17 Mar 2009, Geert Uytterhoeven wrote:
> On Wed, 11 Mar 2009, Geert Uytterhoeven wrote:
> > On Sun, 8 Mar 2009, Phillip Lougher wrote:
> > > Two API issues of concern (one major, one minor). Both of these relate to the
> > > way Squashfs drives the decompression code, where it repeatedly calls it
> > > supplying additional input/output buffers, rather than using a "single-shot"
> > > approach where it calls the decompression code once supplying all the
> > > necessary input and output buffer space.
> > >
> > > 1. Minor issue -the lack of a stream.total_out field. The current
> > > zlib_inflate code collects the total number of bytes decompressed over the
> > > multiple calls into the stream.total_out field.
> > >
> > > There is clearly no such field available in the cryto API, leading to the
> > > somewhat clumsy need to track it, i.e. it leads to the following additional
> > > code.
> >
> > If people feel the need for a total_out field, I can add it to struct
> > comp_request.
> >
> > BTW, what about total_in, which is also provided by plain zlib's z_stream?
> > Do people see a need for a similar field?
>
> The patch below (on top of the updated one to convert SquashFS to pcomp) adds
> comp_request.total_out, so you don't have to calculate and accumulate the
> decompressed output sizes in SquashFS.
>
> Notes:
> - This required the addition of a `struct comp_request *' parameter to
> crypto_{,de}compress_init()
> - Still, there's one of the
>
> produced = req.avail_out;
> ...
> produced -= req.avail_out;
>
> left, as this is part of the logic to discover the end of decompression
> (no bytes produced, no error returned).
>
> Perhaps it's better to instead make crypto_{,de}compress_{update,final}()
> return the (positive) number of output bytes (of the current step)?
>
> Currently it returns zero (no error) or a negative error value.
> That would allow to get rid of both `produced = ... / produced -= ...'
> constructs, but the user would have to accumulate the total output size again
> (which is not such a big deal, IMHO).

Here's an alternative patch, which does exactly that.
Phillip, what do you think?

Thanks for your comments!

From be7d630f96a85d3ce48716b8e328563ba217647b Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <[email protected]>
Date: Tue, 24 Mar 2009 17:19:05 +0100
Subject: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()

If crypto_{,de}compress_{update,final}() succeed, return the actual number of
bytes produced instead of zero, so their users don't have to calculate that
theirselves.

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/testmgr.c | 117 ++++++++++++++++++++++++++++++--------------------
crypto/zlib.c | 24 +++++-----
fs/squashfs/block.c | 33 ++++++---------
3 files changed, 95 insertions(+), 79 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index b50c3c6..9cee018 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -914,24 +914,25 @@ static int test_pcomp(struct crypto_pcomp *tfm,
const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm));
unsigned int i;
char result[COMP_BUF_SIZE];
- int error;
+ int res;

for (i = 0; i < ctcount; i++) {
struct comp_request req;
+ unsigned int produced = 0;

- error = crypto_compress_setup(tfm, ctemplate[i].params,
- ctemplate[i].paramsize);
- if (error) {
+ res = crypto_compress_setup(tfm, ctemplate[i].params,
+ ctemplate[i].paramsize);
+ if (res) {
pr_err("alg: pcomp: compression setup failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

- error = crypto_compress_init(tfm);
- if (error) {
+ res = crypto_compress_init(tfm);
+ if (res) {
pr_err("alg: pcomp: compression init failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

memset(result, 0, sizeof(result));
@@ -941,32 +942,37 @@ static int test_pcomp(struct crypto_pcomp *tfm,
req.next_out = result;
req.avail_out = ctemplate[i].outlen / 2;

- error = crypto_compress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_compress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: compression update failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Add remaining input data */
req.avail_in += (ctemplate[i].inlen + 1) / 2;

- error = crypto_compress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_compress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: compression update failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Provide remaining output space */
req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2;

- error = crypto_compress_final(tfm, &req);
- if (error) {
+ res = crypto_compress_final(tfm, &req);
+ if (res < 0) {
pr_err("alg: pcomp: compression final failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ produced += res;

if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) {
pr_err("alg: comp: Compression test %d failed for %s: "
@@ -976,6 +982,13 @@ static int test_pcomp(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ if (produced != ctemplate[i].outlen) {
+ pr_err("alg: comp: Compression test %d failed for %s: "
+ "returned len = %u (expected %d)\n", i + 1,
+ algo, produced, ctemplate[i].outlen);
+ return -EINVAL;
+ }
+
if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) {
pr_err("alg: pcomp: Compression test %d failed for "
"%s\n", i + 1, algo);
@@ -986,21 +999,21 @@ static int test_pcomp(struct crypto_pcomp *tfm,

for (i = 0; i < dtcount; i++) {
struct comp_request req;
+ unsigned int produced = 0;

- error = crypto_decompress_setup(tfm, dtemplate[i].params,
- dtemplate[i].paramsize);
- if (error) {
+ res = crypto_decompress_setup(tfm, dtemplate[i].params,
+ dtemplate[i].paramsize);
+ if (res) {
pr_err("alg: pcomp: decompression setup failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

- error = crypto_decompress_init(tfm);
- if (error) {
+ res = crypto_decompress_init(tfm);
+ if (res) {
pr_err("alg: pcomp: decompression init failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

memset(result, 0, sizeof(result));
@@ -1010,35 +1023,38 @@ static int test_pcomp(struct crypto_pcomp *tfm,
req.next_out = result;
req.avail_out = dtemplate[i].outlen / 2;

- error = crypto_decompress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_decompress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: decompression update failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Add remaining input data */
req.avail_in += (dtemplate[i].inlen + 1) / 2;

- error = crypto_decompress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_decompress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: decompression update failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Provide remaining output space */
req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2;

- error = crypto_decompress_final(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_decompress_final(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: decompression final failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) {
pr_err("alg: comp: Decompression test %d failed for "
@@ -1048,6 +1064,13 @@ static int test_pcomp(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ if (produced != dtemplate[i].outlen) {
+ pr_err("alg: comp: Decompression test %d failed for "
+ "%s: returned len = %u (expected %d)\n", i + 1,
+ algo, produced, dtemplate[i].outlen);
+ return -EINVAL;
+ }
+
if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) {
pr_err("alg: pcomp: Decompression test %d failed for "
"%s\n", i + 1, algo);
diff --git a/crypto/zlib.c b/crypto/zlib.c
index 33609ba..c301573 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -165,15 +165,15 @@ static int zlib_compress_update(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}

static int zlib_compress_final(struct crypto_pcomp *tfm,
@@ -195,15 +195,15 @@ static int zlib_compress_final(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}


@@ -280,15 +280,15 @@ static int zlib_decompress_update(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}

static int zlib_decompress_final(struct crypto_pcomp *tfm,
@@ -328,15 +328,15 @@ static int zlib_decompress_final(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}


diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 6196821..433f065 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -154,9 +154,8 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
}

if (compressed) {
- int error = 0, decomp_init = 0;
+ int res = 0, decomp_init = 0;
struct comp_request req;
- unsigned int produced = 0;

/*
* Uncompress block.
@@ -194,41 +193,35 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
}

if (!decomp_init) {
- error = crypto_decompress_init(msblk->tfm);
- if (error) {
+ res = crypto_decompress_init(msblk->tfm);
+ if (res) {
ERROR("crypto_decompress_init "
"returned %d, srclength %d\n",
- error, srclength);
+ res, srclength);
goto release_mutex;
}
decomp_init = 1;
}

- produced = req.avail_out;
- error = crypto_decompress_update(msblk->tfm, &req);
- if (error) {
+ res = crypto_decompress_update(msblk->tfm, &req);
+ if (res < 0) {
ERROR("crypto_decompress_update returned %d, "
- "data probably corrupt\n", error);
+ "data probably corrupt\n", res);
goto release_mutex;
}
- produced -= req.avail_out;
-
- length += produced;
+ length += res;

if (req.avail_in == 0 && k < b)
put_bh(bh[k++]);
- } while (bytes || produced);
+ } while (bytes || res);

- produced = req.avail_out;
- error = crypto_decompress_final(msblk->tfm, &req);
- if (error) {
+ res = crypto_decompress_final(msblk->tfm, &req);
+ if (res < 0) {
ERROR("crypto_decompress_final returned %d, data "
- "probably corrupt\n", error);
+ "probably corrupt\n", res);
goto release_mutex;
}
- produced -= req.avail_out;
-
- length += produced;
+ length += res;

mutex_unlock(&msblk->read_data_mutex);
} else {
--
1.6.0.4


With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-03-25 10:12:41

by Phillip Lougher

[permalink] [raw]
Subject: Re: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out

Geert Uytterhoeven wrote:
> On Tue, 17 Mar 2009, Geert Uytterhoeven wrote:
>> On Wed, 11 Mar 2009, Geert Uytterhoeven wrote:
>>> On Sun, 8 Mar 2009, Phillip Lougher wrote:
>>>> Two API issues of concern (one major, one minor). Both of these relate to the
>>>> way Squashfs drives the decompression code, where it repeatedly calls it
>>>> supplying additional input/output buffers, rather than using a "single-shot"
>>>> approach where it calls the decompression code once supplying all the
>>>> necessary input and output buffer space.
>>>>
>>>> 1. Minor issue -the lack of a stream.total_out field. The current
>>>> zlib_inflate code collects the total number of bytes decompressed over the
>>>> multiple calls into the stream.total_out field.
>>>>
>>>> There is clearly no such field available in the cryto API, leading to the
>>>> somewhat clumsy need to track it, i.e. it leads to the following additional
>>>> code.
>>> If people feel the need for a total_out field, I can add it to struct
>>> comp_request.
>>>
>>> BTW, what about total_in, which is also provided by plain zlib's z_stream?
>>> Do people see a need for a similar field?
>> The patch below (on top of the updated one to convert SquashFS to pcomp) adds
>> comp_request.total_out, so you don't have to calculate and accumulate the
>> decompressed output sizes in SquashFS.
>>
>> Notes:
>> - This required the addition of a `struct comp_request *' parameter to
>> crypto_{,de}compress_init()
>> - Still, there's one of the
>>
>> produced = req.avail_out;
>> ...
>> produced -= req.avail_out;
>>
>> left, as this is part of the logic to discover the end of decompression
>> (no bytes produced, no error returned).
>>
>> Perhaps it's better to instead make crypto_{,de}compress_{update,final}()
>> return the (positive) number of output bytes (of the current step)?
>>
>> Currently it returns zero (no error) or a negative error value.
>> That would allow to get rid of both `produced = ... / produced -= ...'
>> constructs, but the user would have to accumulate the total output size again
>> (which is not such a big deal, IMHO).
>
> Here's an alternative patch, which does exactly that.
> Phillip, what do you think?
>

From a quick look, it looks OK :-) I'm not ignoring this, but I'm trying to get a release of
the 4.0 tools finished ASAP (now 2.6.29 is out).

Phillip

2009-04-20 06:03:23

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface))

On Tue, Mar 24, 2009 at 05:33:01PM +0100, Geert Uytterhoeven wrote:
>
> Here's an alternative patch, which does exactly that.
> Phillip, what do you think?
>
> Thanks for your comments!
>
> >From be7d630f96a85d3ce48716b8e328563ba217647b Mon Sep 17 00:00:00 2001
> From: Geert Uytterhoeven <[email protected]>
> Date: Tue, 24 Mar 2009 17:19:05 +0100
> Subject: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()
>
> If crypto_{,de}compress_{update,final}() succeed, return the actual number of
> bytes produced instead of zero, so their users don't have to calculate that
> theirselves.
>
> Signed-off-by: Geert Uytterhoeven <[email protected]>

I certainly prefer this version over the other one? Do you want to
submit crypto API portion of this?

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2009-04-20 07:26:19

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface))

On Mon, 20 Apr 2009, Herbert Xu wrote:
> On Tue, Mar 24, 2009 at 05:33:01PM +0100, Geert Uytterhoeven wrote:
> > Here's an alternative patch, which does exactly that.
> > Phillip, what do you think?
> >
> > Thanks for your comments!
> >
> > >From be7d630f96a85d3ce48716b8e328563ba217647b Mon Sep 17 00:00:00 2001
> > From: Geert Uytterhoeven <[email protected]>
> > Date: Tue, 24 Mar 2009 17:19:05 +0100
> > Subject: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()
> >
> > If crypto_{,de}compress_{update,final}() succeed, return the actual number of
> > bytes produced instead of zero, so their users don't have to calculate that
> > theirselves.
> >
> > Signed-off-by: Geert Uytterhoeven <[email protected]>
>
> I certainly prefer this version over the other one? Do you want to
> submit crypto API portion of this?

If you think I should submit it now, I can do it. But I'm still waiting for
Phillip's comments.

With kind regards,

Geert Uytterhoeven
Software Architect

Sony Techsoft Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-04-20 23:45:19

by Phillip Lougher

[permalink] [raw]
Subject: Re: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out

Geert Uytterhoeven wrote:
> On Mon, 20 Apr 2009, Herbert Xu wrote:
>> On Tue, Mar 24, 2009 at 05:33:01PM +0100, Geert Uytterhoeven wrote:
>>> Here's an alternative patch, which does exactly that.
>>> Phillip, what do you think?
>>>
>>> Thanks for your comments!
>>>
>>> >From be7d630f96a85d3ce48716b8e328563ba217647b Mon Sep 17 00:00:00 2001
>>> From: Geert Uytterhoeven <[email protected]>
>>> Date: Tue, 24 Mar 2009 17:19:05 +0100
>>> Subject: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()
>>>
>>> If crypto_{,de}compress_{update,final}() succeed, return the actual number of
>>> bytes produced instead of zero, so their users don't have to calculate that
>>> theirselves.
>>>
>>> Signed-off-by: Geert Uytterhoeven <[email protected]>
>> I certainly prefer this version over the other one? Do you want to
>> submit crypto API portion of this?
>
> If you think I should submit it now, I can do it. But I'm still waiting for
> Phillip's comments.
>

I think I said they looked OK to me. But, I want to do performance tests
to see if there's any performance degradation over vanilla zlib, and see
if they cope gracefully with corrupted filesystems.

Herbert, are the other cryto API patches in linux-next (or any other
git repository)?

Thanks

Phillip

2009-04-21 00:09:16

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out

On Tue, Apr 21, 2009 at 12:45:19AM +0100, Phillip Lougher wrote:
>
> Herbert, are the other cryto API patches in linux-next (or any other
> git repository)?

They should be in Linus's tree.

Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2009-05-05 14:14:29

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{, de}compress_{update, final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out (was: Re: [PATCH 6/6] squashfs: Make SquashFS 4 use the new pcomp crypto interface))

On Mon, 20 Apr 2009, Geert Uytterhoeven wrote:
> On Mon, 20 Apr 2009, Herbert Xu wrote:
> > On Tue, Mar 24, 2009 at 05:33:01PM +0100, Geert Uytterhoeven wrote:
> > > Here's an alternative patch, which does exactly that.
> > > Phillip, what do you think?
> > >
> > > Thanks for your comments!
> > >
> > > >From be7d630f96a85d3ce48716b8e328563ba217647b Mon Sep 17 00:00:00 2001
> > > From: Geert Uytterhoeven <[email protected]>
> > > Date: Tue, 24 Mar 2009 17:19:05 +0100
> > > Subject: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()
> > >
> > > If crypto_{,de}compress_{update,final}() succeed, return the actual number of
> > > bytes produced instead of zero, so their users don't have to calculate that
> > > theirselves.
> > >
> > > Signed-off-by: Geert Uytterhoeven <[email protected]>
> >
> > I certainly prefer this version over the other one? Do you want to
> > submit crypto API portion of this?
>
> If you think I should submit it now, I can do it. But I'm still waiting for
> Phillip's comments.

Phillip, any progress?

If we want to change the API of crypto_{,de}compress_{update,final}(), we
should do it before the release of 2.6.30, and we're already at -rc4...

Thanks!

With kind regards,

Geert Uytterhoeven
Software Architect
Techsoft Centre

Technology and Software Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-05-11 15:35:09

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()

If crypto_{,de}compress_{update,final}() succeed, return the actual number of
bytes produced instead of zero, so their users don't have to calculate that
theirselves.

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
As we're already at 2.6.30-rc5, I do not want to delay any longer this API
change for a new module introduced for 2.6.30.

Herbert, please apply for 2.6.30.
Thanks!

crypto/testmgr.c | 117 ++++++++++++++++++++++++++++++++----------------------
crypto/zlib.c | 24 ++++++------
2 files changed, 82 insertions(+), 59 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index bfee6e9..b55bccc 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -916,24 +916,25 @@ static int test_pcomp(struct crypto_pcomp *tfm,
const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm));
unsigned int i;
char result[COMP_BUF_SIZE];
- int error;
+ int res;

for (i = 0; i < ctcount; i++) {
struct comp_request req;
+ unsigned int produced = 0;

- error = crypto_compress_setup(tfm, ctemplate[i].params,
- ctemplate[i].paramsize);
- if (error) {
+ res = crypto_compress_setup(tfm, ctemplate[i].params,
+ ctemplate[i].paramsize);
+ if (res) {
pr_err("alg: pcomp: compression setup failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

- error = crypto_compress_init(tfm);
- if (error) {
+ res = crypto_compress_init(tfm);
+ if (res) {
pr_err("alg: pcomp: compression init failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

memset(result, 0, sizeof(result));
@@ -943,32 +944,37 @@ static int test_pcomp(struct crypto_pcomp *tfm,
req.next_out = result;
req.avail_out = ctemplate[i].outlen / 2;

- error = crypto_compress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_compress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: compression update failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Add remaining input data */
req.avail_in += (ctemplate[i].inlen + 1) / 2;

- error = crypto_compress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_compress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: compression update failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Provide remaining output space */
req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2;

- error = crypto_compress_final(tfm, &req);
- if (error) {
+ res = crypto_compress_final(tfm, &req);
+ if (res < 0) {
pr_err("alg: pcomp: compression final failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ produced += res;

if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) {
pr_err("alg: comp: Compression test %d failed for %s: "
@@ -978,6 +984,13 @@ static int test_pcomp(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ if (produced != ctemplate[i].outlen) {
+ pr_err("alg: comp: Compression test %d failed for %s: "
+ "returned len = %u (expected %d)\n", i + 1,
+ algo, produced, ctemplate[i].outlen);
+ return -EINVAL;
+ }
+
if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) {
pr_err("alg: pcomp: Compression test %d failed for "
"%s\n", i + 1, algo);
@@ -988,21 +1001,21 @@ static int test_pcomp(struct crypto_pcomp *tfm,

for (i = 0; i < dtcount; i++) {
struct comp_request req;
+ unsigned int produced = 0;

- error = crypto_decompress_setup(tfm, dtemplate[i].params,
- dtemplate[i].paramsize);
- if (error) {
+ res = crypto_decompress_setup(tfm, dtemplate[i].params,
+ dtemplate[i].paramsize);
+ if (res) {
pr_err("alg: pcomp: decompression setup failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

- error = crypto_decompress_init(tfm);
- if (error) {
+ res = crypto_decompress_init(tfm);
+ if (res) {
pr_err("alg: pcomp: decompression init failed on test "
- "%d for %s: error=%d\n", i + 1, algo, error);
- return error;
+ "%d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}

memset(result, 0, sizeof(result));
@@ -1012,35 +1025,38 @@ static int test_pcomp(struct crypto_pcomp *tfm,
req.next_out = result;
req.avail_out = dtemplate[i].outlen / 2;

- error = crypto_decompress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_decompress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: decompression update failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Add remaining input data */
req.avail_in += (dtemplate[i].inlen + 1) / 2;

- error = crypto_decompress_update(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_decompress_update(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: decompression update failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

/* Provide remaining output space */
req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2;

- error = crypto_decompress_final(tfm, &req);
- if (error && (error != -EAGAIN || req.avail_in)) {
+ res = crypto_decompress_final(tfm, &req);
+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
pr_err("alg: pcomp: decompression final failed on "
- "test %d for %s: error=%d\n", i + 1, algo,
- error);
- return error;
+ "test %d for %s: error=%d\n", i + 1, algo, res);
+ return res;
}
+ if (res > 0)
+ produced += res;

if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) {
pr_err("alg: comp: Decompression test %d failed for "
@@ -1050,6 +1066,13 @@ static int test_pcomp(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ if (produced != dtemplate[i].outlen) {
+ pr_err("alg: comp: Decompression test %d failed for "
+ "%s: returned len = %u (expected %d)\n", i + 1,
+ algo, produced, dtemplate[i].outlen);
+ return -EINVAL;
+ }
+
if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) {
pr_err("alg: pcomp: Decompression test %d failed for "
"%s\n", i + 1, algo);
diff --git a/crypto/zlib.c b/crypto/zlib.c
index 33609ba..c301573 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -165,15 +165,15 @@ static int zlib_compress_update(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}

static int zlib_compress_final(struct crypto_pcomp *tfm,
@@ -195,15 +195,15 @@ static int zlib_compress_final(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}


@@ -280,15 +280,15 @@ static int zlib_decompress_update(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}

static int zlib_decompress_final(struct crypto_pcomp *tfm,
@@ -328,15 +328,15 @@ static int zlib_decompress_final(struct crypto_pcomp *tfm,
return -EINVAL;
}

+ ret = req->avail_out - stream->avail_out;
pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
stream->avail_in, stream->avail_out,
- req->avail_in - stream->avail_in,
- req->avail_out - stream->avail_out);
+ req->avail_in - stream->avail_in, ret);
req->next_in = stream->next_in;
req->avail_in = stream->avail_in;
req->next_out = stream->next_out;
req->avail_out = stream->avail_out;
- return 0;
+ return ret;
}


--
1.6.2.4


With kind regards,

Geert Uytterhoeven
Software Architect
Techsoft Centre

Technology and Software Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-05-18 07:16:51

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()

Hi Herbert,

On Mon, 11 May 2009, Geert Uytterhoeven wrote:
> If crypto_{,de}compress_{update,final}() succeed, return the actual number of
> bytes produced instead of zero, so their users don't have to calculate that
> theirselves.
>
> Signed-off-by: Geert Uytterhoeven <[email protected]>
> ---
> As we're already at 2.6.30-rc5, I do not want to delay any longer this API
> change for a new module introduced for 2.6.30.
>
> Herbert, please apply for 2.6.30.
> Thanks!

As I just saw your pull request for Linus, which didn't include this change,
I'm wondering if you plan to apply it for 2.6.30?

Thanks again!

With kind regards,

Geert Uytterhoeven
Software Architect
Techsoft Centre

Technology and Software Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010

2009-05-18 07:22:33

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()

On Mon, May 18, 2009 at 09:16:49AM +0200, Geert Uytterhoeven wrote:
>
> As I just saw your pull request for Linus, which didn't include this change,
> I'm wondering if you plan to apply it for 2.6.30?

Sorry, this is too late for 2.6.30.
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2009-05-27 05:05:24

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Return produced bytes in crypto_{,de}compress_{update,final}()

On Mon, May 11, 2009 at 05:35:08PM +0200, Geert Uytterhoeven wrote:
> If crypto_{,de}compress_{update,final}() succeed, return the actual number of
> bytes produced instead of zero, so their users don't have to calculate that
> theirselves.
>
> Signed-off-by: Geert Uytterhoeven <[email protected]>

Applied to cryptodev, thanks a lot!
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2009-07-28 14:45:19

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH/RFC] crypto: compress - Return produced bytes in crypto_{, de}compress_{update, final}() (was: Re: [PATCH/RFC] crypto: compress - Add comp_request.total_out

On Tue, 21 Apr 2009, Phillip Lougher wrote:
> Geert Uytterhoeven wrote:
> > On Mon, 20 Apr 2009, Herbert Xu wrote:
> > > On Tue, Mar 24, 2009 at 05:33:01PM +0100, Geert Uytterhoeven wrote:
> > > > Here's an alternative patch, which does exactly that.
> > > > Phillip, what do you think?
> > > >
> > > > Thanks for your comments!
> > > >
> > > > >From be7d630f96a85d3ce48716b8e328563ba217647b Mon Sep 17 00:00:00 2001
> > > > From: Geert Uytterhoeven <[email protected]>
> > > > Date: Tue, 24 Mar 2009 17:19:05 +0100
> > > > Subject: [PATCH] crypto: compress - Return produced bytes in
> > > > crypto_{,de}compress_{update,final}()
> > > >
> > > > If crypto_{,de}compress_{update,final}() succeed, return the actual
> > > > number of
> > > > bytes produced instead of zero, so their users don't have to calculate
> > > > that
> > > > theirselves.
> > > >
> > > > Signed-off-by: Geert Uytterhoeven <[email protected]>
> > > I certainly prefer this version over the other one? Do you want to
> > > submit crypto API portion of this?
> >
> > If you think I should submit it now, I can do it. But I'm still waiting for
> > Phillip's comments.
>
> I think I said they looked OK to me. But, I want to do performance tests
> to see if there's any performance degradation over vanilla zlib, and see
> if they cope gracefully with corrupted filesystems.
>
> Herbert, are the other cryto API patches in linux-next (or any other
> git repository)?

(in the mean time, all of this has been in mainline since a while)

Phillip, any news from you?

Thanks!

With kind regards,

Geert Uytterhoeven
Software Architect
Techsoft Centre

Technology and Software Centre Europe
The Corporate Village ? Da Vincilaan 7-D1 ? B-1935 Zaventem ? Belgium

Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: [email protected]
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 ? RPR Brussels
Fortis ? BIC GEBABEBB ? IBAN BE41293037680010