2009-01-13 15:59:53

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH/RFC 0/7] Partial (de)compression API


The following patch series adds support for partial (de)compression to the
CRYPTO API, and modifies SquashFS 4 to use this:
[1] crypto: compress - Add pcomp interface
[2] crypto: testmgr - Add support for the pcomp interface
[3] crypto: api - Add type init function to crypto_tfm
[4] crypto: api - Export pcomp through comp
[5] crypto: deflate - switch to pcomp
[6] crypto: testmgr - swith deflate test to pcomp
[7] squashfs: Make SquashFS 4 use the new pcomp crypto interface

The backwards-compatibility layer has been tested with IPComp and UBIFS.

Changes since last version (2008-12-17):
- Model the "pcomp" crypto interface on the new crypto types,
- Remove the comp_request parameter from *_{,de}compress_init(),
- Update for recent Squashfs changes (Squashfs is now in mainline).

Thanks for your comments!

crypto/Kconfig | 6 +-
crypto/Makefile | 2 +
crypto/api.c | 20 ++-
crypto/deflate.c | 350 ++++++++++++++++++++++++++----------
crypto/pcompress.c | 203 +++++++++++++++++++++
crypto/testmgr.c | 185 +++++++++++++++++++-
crypto/testmgr.h | 33 ++++-
fs/Kconfig | 3 +-
fs/squashfs/block.c | 81 +++++----
fs/squashfs/squashfs_fs_sb.h | 2 +-
fs/squashfs/super.c | 36 +++-
include/crypto/compress.h | 147 +++++++++++++++
include/crypto/internal/compress.h | 29 +++
include/linux/crypto.h | 9 +-
14 files changed, 953 insertions(+), 153 deletions(-)

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-01-13 15:59:52

by Geert Uytterhoeven

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

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

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index a75f11f..aad718f 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,157 @@ 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_pcomp_setup(tfm, ctemplate[i].params);
+ 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_pcomp_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_pcomp_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_pcomp_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_pcomp_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_pcomp_setup(tfm, dtemplate[i].params);
+ 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_pcomp_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_pcomp_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_pcomp_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_pcomp_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 +1166,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..81b7eb0 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,13 @@ struct comp_testvec {
char output[COMP_BUF_SIZE];
};

+struct pcomp_testvec {
+ const void *params;
+ 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-01-13 15:59:52

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] crypto: api - Add type init function to crypto_tfm

Add a type init function to crypto_tfm, so transforms can override the default
action of calling the algorithm's cra_init() method.

This will be used by the "comp" compatibility layer for the "pcomp" type, which
needs to call the algorithm's setup() method, in addition to the cra_init()
method.

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/api.c | 20 ++++++++++++++++----
include/linux/crypto.h | 1 +
2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/crypto/api.c b/crypto/api.c
index 9975a7b..939512a 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -379,8 +379,14 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
if (err)
goto out_free_tfm;

- if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
- goto cra_init_failed;
+ if (!tfm->exit) {
+ if (tfm->init)
+ err = tfm->init(tfm);
+ else if (alg->cra_init)
+ err = alg->cra_init(tfm);
+ if (err)
+ goto cra_init_failed;
+ }

goto out;

@@ -476,8 +482,14 @@ struct crypto_tfm *crypto_create_tfm(struct crypto_alg *alg,
if (err)
goto out_free_tfm;

- if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
- goto cra_init_failed;
+ if (!tfm->exit) {
+ if (tfm->init)
+ err = tfm->init(tfm);
+ else if (alg->cra_init)
+ err = alg->cra_init(tfm);
+ if (err)
+ goto cra_init_failed;
+ }

goto out;

diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 61b483a..34db6a6 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -484,6 +484,7 @@ struct crypto_tfm {
struct rng_tfm rng;
} crt_u;

+ int (*init)(struct crypto_tfm *tfm);
void (*exit)(struct crypto_tfm *tfm);

struct crypto_alg *__crt_alg;
--
1.6.0.4


2009-01-13 15:59:55

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] crypto: testmgr - swith deflate test to pcomp

Change the tests for the "deflate" crypto module from the "comp" to the "pcomp"
test framework.

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

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index aad718f..f102796 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1404,9 +1404,9 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}, {
.alg = "deflate",
- .test = alg_test_comp,
+ .test = alg_test_pcomp,
.suite = {
- .comp = {
+ .pcomp = {
.comp = {
.vecs = deflate_comp_tv_template,
.count = DEFLATE_COMP_TEST_VECTORS
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 81b7eb0..8b98d2e 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -15,6 +15,7 @@
#ifndef _CRYPTO_TESTMGR_H
#define _CRYPTO_TESTMGR_H

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

#define MAX_DIGEST_SIZE 64
@@ -8360,11 +8361,27 @@ struct pcomp_testvec {
* Deflate test vectors (null-terminated strings).
* Params: winbits=-11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL.
*/
+
+static const struct deflate_comp_params deflate_comp_params = {
+ .enable_comp = 1,
+ .windowBits = -11,
+ .level = Z_DEFAULT_COMPRESSION,
+ .method = Z_DEFLATED,
+ .memLevel = MAX_MEM_LEVEL,
+ .strategy = Z_DEFAULT_STRATEGY
+};
+
+static const struct deflate_comp_params deflate_decomp_params = {
+ .enable_decomp = 1,
+ .windowBits = -11,
+};
+
#define DEFLATE_COMP_TEST_VECTORS 2
#define DEFLATE_DECOMP_TEST_VECTORS 2

-static struct comp_testvec deflate_comp_tv_template[] = {
+static struct pcomp_testvec deflate_comp_tv_template[] = {
{
+ .params = &deflate_comp_params,
.inlen = 70,
.outlen = 38,
.input = "Join us now and share the software "
@@ -8375,6 +8392,7 @@ static struct comp_testvec deflate_comp_tv_template[] = {
"\x48\x55\x28\xce\x4f\x2b\x29\x07"
"\x71\xbc\x08\x2b\x01\x00",
}, {
+ .params = &deflate_comp_params,
.inlen = 191,
.outlen = 122,
.input = "This document describes a compression method based on the DEFLATE"
@@ -8399,8 +8417,9 @@ static struct comp_testvec deflate_comp_tv_template[] = {
},
};

-static struct comp_testvec deflate_decomp_tv_template[] = {
+static struct pcomp_testvec deflate_decomp_tv_template[] = {
{
+ .params = &deflate_decomp_params,
.inlen = 122,
.outlen = 191,
.input = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04"
@@ -8423,6 +8442,7 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
"compression algorithm. This document defines the application of "
"the DEFLATE algorithm to the IP Payload Compression Protocol.",
}, {
+ .params = &deflate_decomp_params,
.inlen = 38,
.outlen = 70,
.input = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56"
--
1.6.0.4


2009-01-13 15:59:59

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] crypto: deflate - switch to pcomp

Change the "deflate" crypto module from the "comp" to the "pcomp" interface.

Signed-off-by: Geert Uytterhoeven <[email protected]>
Cc: James Morris <[email protected]>
---
crypto/Kconfig | 2 +-
crypto/deflate.c | 350 ++++++++++++++++++++++++++++++++------------
include/crypto/compress.h | 12 ++
3 files changed, 267 insertions(+), 97 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 740e3bc..36547fc 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -709,7 +709,7 @@ comment "Compression"

config CRYPTO_DEFLATE
tristate "Deflate compression algorithm"
- select CRYPTO_ALGAPI
+ select CRYPTO_PCOMP
select ZLIB_INFLATE
select ZLIB_DEFLATE
help
diff --git a/crypto/deflate.c b/crypto/deflate.c
index 9128da4..0bb2619 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -1,14 +1,15 @@
-/*
+/*
* Cryptographic API.
*
- * Deflate algorithm (RFC 1951), implemented here primarily for use
- * by IPCOMP (RFC 3173 & RFC 2394).
+ * Deflate algorithm (RFC 1951), implemented here for use
+ * by e.g. IPCOMP (RFC 3173 & RFC 2394).
*
* Copyright (c) 2003 James Morris <[email protected]>
- *
+ * 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; either version 2 of the License, or (at your option)
+ * 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
@@ -16,17 +17,10 @@
* 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.
- *
- * The default winbits of 11 should suit most packets, and it may be something
- * to configure on a per-tfm basis in the future.
- *
- * Currently, compression history is not maintained between tfm calls, as
- * it is not needed for IPCOMP and keeps the code simpler. It can be
- * implemented if someone wants it.
*/
+
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/crypto.h>
#include <linux/zlib.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
@@ -34,11 +28,14 @@
#include <linux/net.h>
#include <linux/slab.h>

+#include <crypto/internal/compress.h>
+
#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
#define DEFLATE_DEF_WINBITS 11
#define DEFLATE_DEF_MEMLEVEL MAX_MEM_LEVEL

struct deflate_ctx {
+ struct deflate_comp_params params;
struct z_stream_s comp_stream;
struct z_stream_s decomp_stream;
};
@@ -47,24 +44,27 @@ static int deflate_comp_init(struct deflate_ctx *ctx)
{
int ret = 0;
struct z_stream_s *stream = &ctx->comp_stream;
+ size_t workspacesize;

- stream->workspace = vmalloc(zlib_deflate_workspacesize());
- if (!stream->workspace ) {
+ workspacesize = zlib_deflate_workspacesize();
+ stream->workspace = vmalloc(workspacesize);
+ if (!stream->workspace) {
ret = -ENOMEM;
goto out;
}
- memset(stream->workspace, 0, zlib_deflate_workspacesize());
- ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED,
- -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
- Z_DEFAULT_STRATEGY);
+ memset(stream->workspace, 0, workspacesize);
+ ret = zlib_deflateInit2(stream, ctx->params.level, ctx->params.method,
+ ctx->params.windowBits, ctx->params.memLevel,
+ ctx->params.strategy);
if (ret != Z_OK) {
ret = -EINVAL;
goto out_free;
}
-out:
+out:
return ret;
out_free:
vfree(stream->workspace);
+ stream->workspace = NULL;
goto out;
}

@@ -74,11 +74,11 @@ static int deflate_decomp_init(struct deflate_ctx *ctx)
struct z_stream_s *stream = &ctx->decomp_stream;

stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
- if (!stream->workspace ) {
+ if (!stream->workspace) {
ret = -ENOMEM;
goto out;
}
- ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS);
+ ret = zlib_inflateInit2(stream, ctx->params.windowBits);
if (ret != Z_OK) {
ret = -EINVAL;
goto out_free;
@@ -87,34 +87,35 @@ out:
return ret;
out_free:
kfree(stream->workspace);
+ stream->workspace = NULL;
goto out;
}

static void deflate_comp_exit(struct deflate_ctx *ctx)
{
- zlib_deflateEnd(&ctx->comp_stream);
- vfree(ctx->comp_stream.workspace);
+ struct z_stream_s *stream = &ctx->comp_stream;
+
+ if (stream->workspace) {
+ zlib_deflateEnd(stream);
+ vfree(stream->workspace);
+ stream->workspace = NULL;
+ }
}

static void deflate_decomp_exit(struct deflate_ctx *ctx)
{
- zlib_inflateEnd(&ctx->decomp_stream);
- kfree(ctx->decomp_stream.workspace);
+ struct z_stream_s *stream = &ctx->decomp_stream;
+
+ if (stream->workspace) {
+ zlib_inflateEnd(stream);
+ kfree(stream->workspace);
+ stream->workspace = NULL;
+ }
}

static int deflate_init(struct crypto_tfm *tfm)
{
- struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
- int ret;
-
- ret = deflate_comp_init(ctx);
- if (ret)
- goto out;
- ret = deflate_decomp_init(ctx);
- if (ret)
- deflate_comp_exit(ctx);
-out:
- return ret;
+ return 0;
}

static void deflate_exit(struct crypto_tfm *tfm)
@@ -125,103 +126,260 @@ static void deflate_exit(struct crypto_tfm *tfm)
deflate_decomp_exit(ctx);
}

-static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int *dlen)
+static int deflate_setup(struct crypto_tfm *tfm, const void *params)
{
- int ret = 0;
+ struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
+ const struct deflate_comp_params *zparams = params;
+ int ret;
+
+ deflate_comp_exit(ctx);
+ deflate_decomp_exit(ctx);
+
+ ctx->params = *zparams;
+
+ if (zparams->enable_comp) {
+ ret = deflate_comp_init(ctx);
+ if (ret)
+ return ret;
+ }
+
+ if (zparams->enable_decomp) {
+ ret = deflate_decomp_init(ctx);
+ if (ret) {
+ deflate_comp_exit(ctx);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+
+static int deflate_compress_init(struct crypto_tfm *tfm)
+{
+ int ret;
struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
struct z_stream_s *stream = &dctx->comp_stream;

ret = zlib_deflateReset(stream);
- if (ret != Z_OK) {
- ret = -EINVAL;
- goto out;
+ if (ret != Z_OK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int deflate_compress_update(struct crypto_tfm *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct deflate_ctx *dctx = crypto_tfm_ctx(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;
}

- stream->next_in = (u8 *)src;
- stream->avail_in = slen;
- stream->next_out = (u8 *)dst;
- stream->avail_out = *dlen;
+ 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 deflate_compress_final(struct crypto_tfm *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct deflate_ctx *dctx = crypto_tfm_ctx(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) {
- ret = -EINVAL;
- goto out;
+ pr_debug("zlib_deflate failed %d\n", ret);
+ return -EINVAL;
}
- ret = 0;
- *dlen = stream->total_out;
-out:
- return ret;
+
+ 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 deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int *dlen)
+
+static int deflate_decompress_init(struct crypto_tfm *tfm)
{
-
- int ret = 0;
+ int ret;
struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
struct z_stream_s *stream = &dctx->decomp_stream;

ret = zlib_inflateReset(stream);
- if (ret != Z_OK) {
- ret = -EINVAL;
- goto out;
- }
+ if (ret != Z_OK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int deflate_decompress_update(struct crypto_tfm *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+ struct z_stream_s *stream = &dctx->decomp_stream;

- stream->next_in = (u8 *)src;
- stream->avail_in = slen;
- stream->next_out = (u8 *)dst;
- stream->avail_out = *dlen;
+ 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);
- /*
- * 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) {
- u8 zerostuff = 0;
- stream->next_in = &zerostuff;
- stream->avail_in = 1;
- ret = zlib_inflate(stream, Z_FINISH);
+ 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 deflate_decompress_final(struct crypto_tfm *tfm,
+ struct comp_request *req)
+{
+ int ret;
+ struct deflate_ctx *dctx = crypto_tfm_ctx(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->params.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) {
- ret = -EINVAL;
- goto out;
+ pr_debug("zlib_inflate failed %d\n", ret);
+ return -EINVAL;
}
- ret = 0;
- *dlen = stream->total_out;
-out:
- return ret;
+
+ 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 crypto_alg alg = {
- .cra_name = "deflate",
- .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
- .cra_ctxsize = sizeof(struct deflate_ctx),
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(alg.cra_list),
- .cra_init = deflate_init,
- .cra_exit = deflate_exit,
- .cra_u = { .compress = {
- .coa_compress = deflate_compress,
- .coa_decompress = deflate_decompress } }
+
+static const struct deflate_comp_params deflate_default_params = {
+ .enable_comp = 1,
+ .enable_decomp = 1,
+ .windowBits = -DEFLATE_DEF_WINBITS,
+ .level = DEFLATE_DEF_LEVEL,
+ .method = Z_DEFLATED,
+ .memLevel = DEFLATE_DEF_MEMLEVEL,
+ .strategy = Z_DEFAULT_STRATEGY
+};
+
+static struct pcomp_alg alg = {
+ .setup = deflate_setup,
+ .compress_init = deflate_compress_init,
+ .compress_update = deflate_compress_update,
+ .compress_final = deflate_compress_final,
+ .decompress_init = deflate_decompress_init,
+ .decompress_update = deflate_decompress_update,
+ .decompress_final = deflate_decompress_final,
+
+ .default_params = &deflate_default_params,
+ .base = {
+ .cra_name = "deflate",
+ .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS,
+ .cra_ctxsize = sizeof(struct deflate_ctx),
+ .cra_init = deflate_init,
+ .cra_exit = deflate_exit,
+ }
};

static int __init deflate_mod_init(void)
{
- return crypto_register_alg(&alg);
+ return crypto_register_pcomp(&alg);
}

static void __exit deflate_mod_fini(void)
{
- crypto_unregister_alg(&alg);
+ crypto_unregister_pcomp(&alg);
}

module_init(deflate_mod_init);
module_exit(deflate_mod_fini);

MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP");
+MODULE_DESCRIPTION("Deflate Compression Algorithm");
MODULE_AUTHOR("James Morris <[email protected]>");

diff --git a/include/crypto/compress.h b/include/crypto/compress.h
index 8b3e816..c4798fe 100644
--- a/include/crypto/compress.h
+++ b/include/crypto/compress.h
@@ -30,6 +30,18 @@ struct comp_request {
unsigned int avail_out; /* bytes available at next_out */
};

+struct deflate_comp_params {
+ unsigned int enable_comp:1;
+ unsigned int enable_decomp:1;
+ /* common (de)compression (deflate and inflate) parameters */
+ int windowBits; /* e.g. MAX_WBITS or DEF_WBITS */
+ /* compression only (deflate) parameters */
+ int level; /* e.g. Z_DEFAULT_COMPRESSION */
+ int method; /* e.g. Z_DEFLATED */
+ int memLevel; /* e.g. DEF_MEM_LEVEL */
+ int strategy /* e.g. Z_DEFAULT_STRATEGY */;
+};
+
struct pcomp_alg {
int (*setup)(struct crypto_tfm *tfm, const void *params);
int (*compress_init)(struct crypto_tfm *tfm);
--
1.6.0.4


2009-01-13 15:59:58

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] crypto: api - Export pcomp through comp

Allow "pcomp" algorithms to be used through the old "comp" interface, by
implementing one-shot (de)compression on top of the partial (de)compression
interface.

As the old "comp" interface doesn't support the configuration of
(de)compression parameters by the user, each algorithm must provide a set of
default parameters through pcomp_alg.default_params.

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
crypto/pcompress.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
include/crypto/compress.h | 3 +
include/linux/crypto.h | 7 ++-
3 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/crypto/pcompress.c b/crypto/pcompress.c
index b9e3724..8026d12 100644
--- a/crypto/pcompress.c
+++ b/crypto/pcompress.c
@@ -32,8 +32,117 @@
#include "internal.h"


+static int crypto_init_compat(struct crypto_tfm *tfm)
+{
+ struct pcomp_alg *alg = __crypto_pcomp_alg(tfm->__crt_alg);
+ int error;
+
+ error = alg->base.cra_init(tfm);
+ if (error)
+ return error;
+
+ error = alg->setup(tfm, alg->default_params);
+ if (error)
+ pr_debug("pcomp_alg.setup failed %d\n", error);
+
+ return error;
+}
+
+static int crypto_compress_compat(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst,
+ unsigned int *dlen)
+{
+ struct pcomp_alg *alg = __crypto_pcomp_alg(tfm->__crt_alg);
+ struct comp_request req;
+ int error;
+
+ pr_debug("src = %p, slen = %u, dst = %p, dlen = %u\n", src, slen, dst,
+ *dlen);
+
+ error = alg->compress_init(tfm);
+ if (error) {
+ pr_debug("pcomp_alg.compress_init failed %d\n", error);
+ return error;
+ }
+
+ req.next_in = src;
+ req.avail_in = slen;
+ req.next_out = dst;
+ req.avail_out = *dlen;
+
+ error = alg->compress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_debug("pcomp_alg.compress_update failed %d\n", error);
+ return error;
+ }
+
+ error = alg->compress_final(tfm, &req);
+ if (error) {
+ pr_debug("pcomp_alg.compress_final failed %d\n", error);
+ return error;
+ }
+
+ *dlen -= req.avail_out;
+
+ return 0;
+}
+
+static int crypto_decompress_compat(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst,
+ unsigned int *dlen)
+{
+ struct pcomp_alg *alg = __crypto_pcomp_alg(tfm->__crt_alg);
+ struct comp_request req;
+ int error;
+
+ pr_debug("src = %p, slen = %u, dst = %p, dlen = %u\n", src, slen, dst,
+ *dlen);
+
+ error = alg->decompress_init(tfm);
+ if (error) {
+ pr_debug("pcomp_alg.decompress_init failed %d\n", error);
+ return error;
+ }
+
+ req.next_in = src;
+ req.avail_in = slen;
+ req.next_out = dst;
+ req.avail_out = *dlen;
+
+ error = alg->decompress_update(tfm, &req);
+ if (error && (error != -EAGAIN || req.avail_in)) {
+ pr_debug("pcomp_alg.decompress_update failed %d\n", error);
+ return error;
+ }
+
+ error = alg->decompress_final(tfm, &req);
+ if (error) {
+ pr_debug("pcomp_alg.decompress_final failed %d\n", error);
+ return error;
+ }
+
+ *dlen -= req.avail_out;
+
+ return 0;
+}
+
+static int crypto_init_pcomp_ops_compat(struct crypto_tfm *tfm)
+{
+ struct compress_tfm *ops = &tfm->crt_compress;
+
+ tfm->init = crypto_init_compat;
+
+ ops->cot_compress = crypto_compress_compat;
+ ops->cot_decompress = crypto_decompress_compat;
+
+ return 0;
+}
+
static int crypto_init_pcomp_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
+ if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_COMPRESS)
+ return crypto_init_pcomp_ops_compat(tfm);
+
return 0;
}

diff --git a/include/crypto/compress.h b/include/crypto/compress.h
index a6493b9..8b3e816 100644
--- a/include/crypto/compress.h
+++ b/include/crypto/compress.h
@@ -44,6 +44,9 @@ struct pcomp_alg {
struct comp_request *req);

struct crypto_alg base;
+
+ /* for backwards-compatibility with compress_alg only */
+ const void *default_params;
};

struct crypto_pcomp {
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 34db6a6..bb0905b 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -30,7 +30,6 @@
*/
#define CRYPTO_ALG_TYPE_MASK 0x0000000f
#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
-#define CRYPTO_ALG_TYPE_COMPRESS 0x00000002
#define CRYPTO_ALG_TYPE_AEAD 0x00000003
#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004
#define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005
@@ -40,11 +39,13 @@
#define CRYPTO_ALG_TYPE_SHASH 0x00000009
#define CRYPTO_ALG_TYPE_AHASH 0x0000000a
#define CRYPTO_ALG_TYPE_RNG 0x0000000c
+#define CRYPTO_ALG_TYPE_COMPRESS 0x0000000e
#define CRYPTO_ALG_TYPE_PCOMPRESS 0x0000000f

#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c
#define CRYPTO_ALG_TYPE_BLKCIPHER_MASK 0x0000000c
+#define CRYPTO_ALG_TYPE_COMPRESS_MASK 0x0000000e

#define CRYPTO_ALG_LARVAL 0x00000010
#define CRYPTO_ALG_DEAD 0x00000020
@@ -1297,7 +1298,7 @@ static inline struct crypto_comp *crypto_alloc_comp(const char *alg_name,
{
type &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_COMPRESS;
- mask |= CRYPTO_ALG_TYPE_MASK;
+ mask |= CRYPTO_ALG_TYPE_COMPRESS_MASK;

return __crypto_comp_cast(crypto_alloc_base(alg_name, type, mask));
}
@@ -1316,7 +1317,7 @@ static inline int crypto_has_comp(const char *alg_name, u32 type, u32 mask)
{
type &= ~CRYPTO_ALG_TYPE_MASK;
type |= CRYPTO_ALG_TYPE_COMPRESS;
- mask |= CRYPTO_ALG_TYPE_MASK;
+ mask |= CRYPTO_ALG_TYPE_COMPRESS_MASK;

return crypto_has_alg(alg_name, type, mask);
}
--
1.6.0.4


2009-01-13 15:59:55

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] 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_pcomp_compress_{init,update,final}() for compression,
- crypto_pcomp_decompress_{init,update,final}() for decompression,
- crypto_pcomp_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 method takes an opaque parameter pointer, whose meaning depends 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 | 94 +++++++++++++++++++++++++
include/crypto/compress.h | 132 ++++++++++++++++++++++++++++++++++++
include/crypto/internal/compress.h | 29 ++++++++
include/linux/crypto.h | 1 +
6 files changed, 262 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 8dde4fc..740e3bc 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..b9e3724
--- /dev/null
+++ b/crypto/pcompress.c
@@ -0,0 +1,94 @@
+/*
+ * Cryptographic API.
+ *
+ * Partial 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#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_init_pcomp_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+ return 0;
+}
+
+static unsigned int crypto_pcomp_ctxsize(struct crypto_alg *alg, u32 type,
+ u32 mask)
+{
+ return alg->cra_ctxsize;
+}
+
+static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm,
+ const struct crypto_type *frontend)
+{
+ if (frontend->type != CRYPTO_ALG_TYPE_PCOMPRESS)
+ return -EINVAL;
+ 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 = {
+ .ctxsize = crypto_pcomp_ctxsize,
+ .init = crypto_init_pcomp_ops,
+ .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),
+};
+
+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..a6493b9
--- /dev/null
+++ b/include/crypto/compress.h
@@ -0,0 +1,132 @@
+/*
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#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 pcomp_alg {
+ int (*setup)(struct crypto_tfm *tfm, const void *params);
+ int (*compress_init)(struct crypto_tfm *tfm);
+ int (*compress_update)(struct crypto_tfm *tfm,
+ struct comp_request *req);
+ int (*compress_final)(struct crypto_tfm *tfm,
+ struct comp_request *req);
+ int (*decompress_init)(struct crypto_tfm *tfm);
+ int (*decompress_update)(struct crypto_tfm *tfm,
+ struct comp_request *req);
+ int (*decompress_final)(struct crypto_tfm *tfm,
+ struct comp_request *req);
+
+ struct crypto_alg base;
+};
+
+struct crypto_pcomp {
+ struct crypto_tfm base;
+};
+
+static inline struct crypto_pcomp *__crypto_pcomp_cast(struct crypto_tfm *tfm)
+{
+ return (struct crypto_pcomp *)tfm;
+}
+
+static inline struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name,
+ u32 type, u32 mask)
+{
+ type &= ~CRYPTO_ALG_TYPE_MASK;
+ type |= CRYPTO_ALG_TYPE_PCOMPRESS;
+ mask |= CRYPTO_ALG_TYPE_MASK;
+
+ return __crypto_pcomp_cast(crypto_alloc_base(alg_name, type, 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_free_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_pcomp_setup(struct crypto_pcomp *tfm,
+ const void *params)
+{
+ return crypto_pcomp_alg(tfm)->setup(crypto_pcomp_tfm(tfm), params);
+}
+
+static inline int crypto_pcomp_compress_init(struct crypto_pcomp *tfm)
+{
+ return crypto_pcomp_alg(tfm)->compress_init(crypto_pcomp_tfm(tfm));
+}
+
+static inline int crypto_pcomp_compress_update(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->compress_update(crypto_pcomp_tfm(tfm),
+ req);
+}
+
+static inline int crypto_pcomp_compress_final(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->compress_final(crypto_pcomp_tfm(tfm),
+ req);
+}
+
+static inline int crypto_pcomp_decompress_init(struct crypto_pcomp *tfm)
+{
+ return crypto_pcomp_alg(tfm)->decompress_init(crypto_pcomp_tfm(tfm));
+}
+
+static inline int crypto_pcomp_decompress_update(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->decompress_update(crypto_pcomp_tfm(tfm),
+ req);
+}
+
+static inline int crypto_pcomp_decompress_final(struct crypto_pcomp *tfm,
+ struct comp_request *req)
+{
+ return crypto_pcomp_alg(tfm)->decompress_final(crypto_pcomp_tfm(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..db2f264
--- /dev/null
+++ b/include/crypto/internal/compress.h
@@ -0,0 +1,29 @@
+/*
+ * 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _CRYPTO_INTERNAL_COMPRESS_H
+#define _CRYPTO_INTERNAL_COMPRESS_H
+
+#include <crypto/compress.h>
+
+int crypto_register_pcomp(struct pcomp_alg *alg);
+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 3bacd71..61b483a 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-01-13 15:59:59

by Geert Uytterhoeven

[permalink] [raw]
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/Kconfig | 3 +-
fs/squashfs/block.c | 81 ++++++++++++++++++++++++------------------
fs/squashfs/squashfs_fs_sb.h | 2 +-
fs/squashfs/super.c | 36 ++++++++++++++----
4 files changed, 77 insertions(+), 45 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index 51307b0..6636018 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -935,7 +935,8 @@ config CRAMFS
config SQUASHFS
tristate "SquashFS 4.0 - Squashed file system support"
depends on BLOCK
- select ZLIB_INFLATE
+ select CRYPTO
+ select CRYPTO_DEFLATE
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..959e993 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,57 @@ 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_pcomp_decompress_init(msblk->tfm);
+ if (error) {
+ ERROR("crypto_pcomp_decompress_init "
+ "returned %d, srclength %d\n",
+ error, srclength);
goto release_mutex;
}
- zlib_init = 1;
+ decomp_init = 1;
+ }
+
+ produced = req.avail_out;
+ error = crypto_pcomp_decompress_update(msblk->tfm,
+ &req);
+ if (error) {
+ ERROR("crypto_pcomp_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_pcomp_decompress_final(msblk->tfm, &req);
+ if (error) {
+ ERROR("crypto_pcomp_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 a0466d7..e6c4a1b 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -36,11 +36,17 @@
#include <linux/module.h>
#include <linux/zlib.h>

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

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

@@ -74,6 +80,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
unsigned short flags;
unsigned int fragments;
u64 lookup_table_start;
+ struct deflate_comp_params params;
int err;

TRACE("Entered squashfs_fill_superblock\n");
@@ -85,16 +92,29 @@ 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);
+ msblk->tfm = NULL;
+ err = -ENOMEM;
+ goto failure;
+ }
+
+ params.enable_comp = 0;
+ params.enable_decomp = 1;
+ params.windowBits = DEF_WBITS;
+ err = crypto_pcomp_setup(msblk->tfm, &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;
}

@@ -283,17 +303,17 @@ 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);
kfree(sb->s_fs_info);
sb->s_fs_info = NULL;
- return -ENOMEM;
+ return err;
}


@@ -332,7 +352,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-01-14 03:16:17

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

Hi Geert:

On Tue, Jan 13, 2009 at 04:59:40PM +0100, Geert Uytterhoeven wrote:
> 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.

Thanks for the patch-set!

> diff --git a/crypto/pcompress.c b/crypto/pcompress.c
> new file mode 100644
> index 0000000..b9e3724
> --- /dev/null
> +++ b/crypto/pcompress.c
> @@ -0,0 +1,94 @@
> +/*
> + * Cryptographic API.
> + *
> + * Partial 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, write to the Free Software Foundation,
> + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
> + */
> +
> +#define pr_fmt(fmt) "%s: " fmt, __func__

This appears to be unused?

> +static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm,
> + const struct crypto_type *frontend)
> +{
> + if (frontend->type != CRYPTO_ALG_TYPE_PCOMPRESS)
> + return -EINVAL;

This is my fault. The check is redundant so you can remove it.
I'll kill it in shash too.

> +struct pcomp_alg {
> + int (*setup)(struct crypto_tfm *tfm, const void *params);

Actually I was thinking of separate alloc functions for compress
and decompress so that

1) We know what the user wants to do without every algorithm
reinventing their own signalling for it;

2) The parameters can be separated.

Also, this is something that we'll potentially export to user-space,
so we need to ensure that it is invariant to word length.

So something like this would be good

int (*setup_comp)(struct crypto_pcomp *tfm, const void *params,
unsigned int length);
int (*setup_decomp)(struct crypto_pcomp *tfm, const void *params,
unsigned int length);

The actual parameters should be formatted using the netlink helpers
(nla_*). So each parameter that you want to set should show up as
a netlink attribute. If a paramter is absent then you'd just use
the default, etc.

> + int (*compress_init)(struct crypto_tfm *tfm);

That should be struct crypto_pcomp.

> +static inline struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name,
> + u32 type, u32 mask)
> +{
> + type &= ~CRYPTO_ALG_TYPE_MASK;
> + type |= CRYPTO_ALG_TYPE_PCOMPRESS;
> + mask |= CRYPTO_ALG_TYPE_MASK;
> +
> + return __crypto_pcomp_cast(crypto_alloc_base(alg_name, type, mask));
> +}

That's the old way to allocate tfm's which won't work since pcomp
is using the new type API. You should do it the way that shash
does it.

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-01-14 15:01:36

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

Hi Herbert,

On Wed, 14 Jan 2009, Herbert Xu wrote:
> On Tue, Jan 13, 2009 at 04:59:40PM +0100, Geert Uytterhoeven wrote:
> > 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.
>
> Thanks for the patch-set!
>
> > diff --git a/crypto/pcompress.c b/crypto/pcompress.c
> > new file mode 100644
> > index 0000000..b9e3724
> > --- /dev/null
> > +++ b/crypto/pcompress.c
> > @@ -0,0 +1,94 @@
> > +/*
> > + * Cryptographic API.
> > + *
> > + * Partial 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, write to the Free Software Foundation,
> > + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
> > + */
> > +
> > +#define pr_fmt(fmt) "%s: " fmt, __func__
>
> This appears to be unused?

It's used by the pr_*() macros in <linux/kernel.h>.

Since commit d091c2f58ba32029495a933b721e8e02fbd12caa ("Add 'pr_fmt()' format
modifier to pr_xyz macros."), this is the new way to have a common prefix in
all printed output.

> > +static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm,
> > + const struct crypto_type *frontend)
> > +{
> > + if (frontend->type != CRYPTO_ALG_TYPE_PCOMPRESS)
> > + return -EINVAL;
>
> This is my fault. The check is redundant so you can remove it.
> I'll kill it in shash too.

Ok, removed.

> > +struct pcomp_alg {
> > + int (*setup)(struct crypto_tfm *tfm, const void *params);
>
> Actually I was thinking of separate alloc functions for compress
> and decompress so that

For compatibility with crypto_comp, we also need an alloc function for both
compress and decompress, so that makes 3 alloc functions.

That would also solve the issue where there's hardware support for e.g.
decompression, but not for compression.

> 1) We know what the user wants to do without every algorithm
> reinventing their own signalling for it;

I guess you want to use the flags to indicate compress/decompress/both?
Unfortunately I'm still struggling to fully understand the type/mask handling,
so I would appreciate it if you could give me a hint how to handle that.

> 2) The parameters can be separated.

OK.

> Also, this is something that we'll potentially export to user-space,
> so we need to ensure that it is invariant to word length.
>
> So something like this would be good
>
> int (*setup_comp)(struct crypto_pcomp *tfm, const void *params,
> unsigned int length);
> int (*setup_decomp)(struct crypto_pcomp *tfm, const void *params,
> unsigned int length);

I assume "length" is the size of the passed params, so the algorithms can
return -EINVAL if they're passed the wrong size?

> The actual parameters should be formatted using the netlink helpers
> (nla_*). So each parameter that you want to set should show up as
> a netlink attribute. If a paramter is absent then you'd just use
> the default, etc.

I'll look into the netlink formatting...

> > + int (*compress_init)(struct crypto_tfm *tfm);
>
> That should be struct crypto_pcomp.

OK, I updated all pcomp_alg operations to take crypto_pcomp pointers instead of
crypto_tfm pointers.

> > +static inline struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name,
> > + u32 type, u32 mask)
> > +{
> > + type &= ~CRYPTO_ALG_TYPE_MASK;
> > + type |= CRYPTO_ALG_TYPE_PCOMPRESS;
> > + mask |= CRYPTO_ALG_TYPE_MASK;
> > +
> > + return __crypto_pcomp_cast(crypto_alloc_base(alg_name, type, mask));
> > +}
>
> That's the old way to allocate tfm's which won't work since pcomp
> is using the new type API. You should do it the way that shash
> does it.

I tried to do this, but stumbled across a dependency problem: as
crypto_alloc_tfm() needs a pointer to crypto_pcomp_type(), crypto_alloc_pcomp()
can no longer be static inline, and must be moved to crypto/pcompress.c.

However, pcompress can be a module, while testmgr (which uses
crypto_alloc_pcomp()) seems to be always builtin.

Ah, CRYPTO_MANAGER2 has to select CRYPTO_PCOMP. OK.

Thanks for your review!

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-01-14 16:45:38

by Jaswinder Singh

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Tue, Jan 13, 2009 at 9:29 PM, Geert Uytterhoeven
<[email protected]> wrote:
> +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_pcomp_setup(struct crypto_pcomp *tfm,
> + const void *params)
> +{
> + return crypto_pcomp_alg(tfm)->setup(crypto_pcomp_tfm(tfm), params);
> +}
> +
> +static inline int crypto_pcomp_compress_init(struct crypto_pcomp *tfm)
> +{
> + return crypto_pcomp_alg(tfm)->compress_init(crypto_pcomp_tfm(tfm));
> +}
> +
> +static inline int crypto_pcomp_compress_update(struct crypto_pcomp *tfm,
> + struct comp_request *req)
> +{
> + return crypto_pcomp_alg(tfm)->compress_update(crypto_pcomp_tfm(tfm),
> + req);
> +}
> +
> +static inline int crypto_pcomp_compress_final(struct crypto_pcomp *tfm,
> + struct comp_request *req)
> +{
> + return crypto_pcomp_alg(tfm)->compress_final(crypto_pcomp_tfm(tfm),
> + req);
> +}
> +
> +static inline int crypto_pcomp_decompress_init(struct crypto_pcomp *tfm)
> +{
> + return crypto_pcomp_alg(tfm)->decompress_init(crypto_pcomp_tfm(tfm));
> +}
> +
> +static inline int crypto_pcomp_decompress_update(struct crypto_pcomp *tfm,
> + struct comp_request *req)
> +{
> + return crypto_pcomp_alg(tfm)->decompress_update(crypto_pcomp_tfm(tfm),
> + req);
> +}
> +
> +static inline int crypto_pcomp_decompress_final(struct crypto_pcomp *tfm,
> + struct comp_request *req)
> +{
> + return crypto_pcomp_alg(tfm)->decompress_final(crypto_pcomp_tfm(tfm),
> + req);
> +}

Can you please use expressive but short names ?

Thanks

--
JSR

2009-01-14 16:54:54

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Wed, 14 Jan 2009, Jaswinder Singh Rajput wrote:
> On Tue, Jan 13, 2009 at 9:29 PM, Geert Uytterhoeven
> <[email protected]> wrote:
> > +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_pcomp_setup(struct crypto_pcomp *tfm,
> > + const void *params)
> > +{
> > + return crypto_pcomp_alg(tfm)->setup(crypto_pcomp_tfm(tfm), params);
> > +}
> > +
> > +static inline int crypto_pcomp_compress_init(struct crypto_pcomp *tfm)
> > +{
> > + return crypto_pcomp_alg(tfm)->compress_init(crypto_pcomp_tfm(tfm));
> > +}
> > +
> > +static inline int crypto_pcomp_compress_update(struct crypto_pcomp *tfm,
> > + struct comp_request *req)
> > +{
> > + return crypto_pcomp_alg(tfm)->compress_update(crypto_pcomp_tfm(tfm),
> > + req);
> > +}
> > +
> > +static inline int crypto_pcomp_compress_final(struct crypto_pcomp *tfm,
> > + struct comp_request *req)
> > +{
> > + return crypto_pcomp_alg(tfm)->compress_final(crypto_pcomp_tfm(tfm),
> > + req);
> > +}
> > +
> > +static inline int crypto_pcomp_decompress_init(struct crypto_pcomp *tfm)
> > +{
> > + return crypto_pcomp_alg(tfm)->decompress_init(crypto_pcomp_tfm(tfm));
> > +}
> > +
> > +static inline int crypto_pcomp_decompress_update(struct crypto_pcomp *tfm,
> > + struct comp_request *req)
> > +{
> > + return crypto_pcomp_alg(tfm)->decompress_update(crypto_pcomp_tfm(tfm),
> > + req);
> > +}
> > +
> > +static inline int crypto_pcomp_decompress_final(struct crypto_pcomp *tfm,
> > + struct comp_request *req)
> > +{
> > + return crypto_pcomp_alg(tfm)->decompress_final(crypto_pcomp_tfm(tfm),
> > + req);
> > +}
>
> Can you please use expressive but short names ?

I admit they're quite long. But they're similar to the ones in use for the
already existing crypto modules.

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-01-14 17:08:56

by Jaswinder Singh

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Wed, Jan 14, 2009 at 10:24 PM, Geert Uytterhoeven
<[email protected]> wrote:
> On Wed, 14 Jan 2009, Jaswinder Singh Rajput wrote:
>> On Tue, Jan 13, 2009 at 9:29 PM, Geert Uytterhoeven
>> <[email protected]> wrote:
>> > +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_pcomp_setup(struct crypto_pcomp *tfm,
>> > + const void *params)
>> > +{
>> > + return crypto_pcomp_alg(tfm)->setup(crypto_pcomp_tfm(tfm), params);
>> > +}
>> > +
>> > +static inline int crypto_pcomp_compress_init(struct crypto_pcomp *tfm)
>> > +{
>> > + return crypto_pcomp_alg(tfm)->compress_init(crypto_pcomp_tfm(tfm));
>> > +}
>> > +
>> > +static inline int crypto_pcomp_compress_update(struct crypto_pcomp *tfm,
>> > + struct comp_request *req)
>> > +{
>> > + return crypto_pcomp_alg(tfm)->compress_update(crypto_pcomp_tfm(tfm),
>> > + req);
>> > +}
>> > +
>> > +static inline int crypto_pcomp_compress_final(struct crypto_pcomp *tfm,
>> > + struct comp_request *req)
>> > +{
>> > + return crypto_pcomp_alg(tfm)->compress_final(crypto_pcomp_tfm(tfm),
>> > + req);
>> > +}
>> > +
>> > +static inline int crypto_pcomp_decompress_init(struct crypto_pcomp *tfm)
>> > +{
>> > + return crypto_pcomp_alg(tfm)->decompress_init(crypto_pcomp_tfm(tfm));
>> > +}
>> > +
>> > +static inline int crypto_pcomp_decompress_update(struct crypto_pcomp *tfm,
>> > + struct comp_request *req)
>> > +{
>> > + return crypto_pcomp_alg(tfm)->decompress_update(crypto_pcomp_tfm(tfm),
>> > + req);
>> > +}
>> > +
>> > +static inline int crypto_pcomp_decompress_final(struct crypto_pcomp *tfm,
>> > + struct comp_request *req)
>> > +{
>> > + return crypto_pcomp_alg(tfm)->decompress_final(crypto_pcomp_tfm(tfm),
>> > + req);
>> > +}
>>
>> Can you please use expressive but short names ?
>
> I admit they're quite long. But they're similar to the ones in use for the
> already existing crypto modules.
>

But I am expecting better results from you ;-)

Thanks
--
JSR

2009-01-15 03:05:31

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Wed, Jan 14, 2009 at 04:01:34PM +0100, Geert Uytterhoeven wrote:
>
> It's used by the pr_*() macros in <linux/kernel.h>.
>
> Since commit d091c2f58ba32029495a933b721e8e02fbd12caa ("Add 'pr_fmt()' format
> modifier to pr_xyz macros."), this is the new way to have a common prefix in
> all printed output.

But you don't actually print anything out in the module :)

> For compatibility with crypto_comp, we also need an alloc function for both
> compress and decompress, so that makes 3 alloc functions.

Couldn't crypto_comp just call both alloc functions? I don't see
why we need a third function.

> > 1) We know what the user wants to do without every algorithm
> > reinventing their own signalling for it;
>
> I guess you want to use the flags to indicate compress/decompress/both?
> Unfortunately I'm still struggling to fully understand the type/mask handling,
> so I would appreciate it if you could give me a hint how to handle that.

No, I mean that whether you want compression or decompression
is signified by the which function you're calling. If you want
to do both then you call both.

> I assume "length" is the size of the passed params, so the algorithms can
> return -EINVAL if they're passed the wrong size?

Well with the netlink parameters these can have variable lengths
depending on how many parameters the user supplies.

> > > +static inline struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name,
> > > + u32 type, u32 mask)
> > > +{
> > > + type &= ~CRYPTO_ALG_TYPE_MASK;
> > > + type |= CRYPTO_ALG_TYPE_PCOMPRESS;
> > > + mask |= CRYPTO_ALG_TYPE_MASK;
> > > +
> > > + return __crypto_pcomp_cast(crypto_alloc_base(alg_name, type, mask));
> > > +}
> >
> > That's the old way to allocate tfm's which won't work since pcomp
> > is using the new type API. You should do it the way that shash
> > does it.
>
> I tried to do this, but stumbled across a dependency problem: as
> crypto_alloc_tfm() needs a pointer to crypto_pcomp_type(), crypto_alloc_pcomp()
> can no longer be static inline, and must be moved to crypto/pcompress.c.

Ah yes because crypto_comp is one of the original types that's
still built-in. Because there are so few compression users and
algorithms (exactly 3 if you include null compression), I think
we can dispense with the compatibility stuff altogether since
we'll likely rip out fairly soon anyway.

So just create the new type, readd deflate using the new type
alongside the existing deflate algorithm. The system is capable
of supporting two algorithms of the same name with different types.

Then once the other algorithm (lzo) is taken care of and all the
users are converted I'll just kill the old type and algorithms.

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-01-15 10:55:00

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

Hi Herbert,

On Thu, 15 Jan 2009, Herbert Xu wrote:
> On Wed, Jan 14, 2009 at 04:01:34PM +0100, Geert Uytterhoeven wrote:
> > It's used by the pr_*() macros in <linux/kernel.h>.
> >
> > Since commit d091c2f58ba32029495a933b721e8e02fbd12caa ("Add 'pr_fmt()' format
> > modifier to pr_xyz macros."), this is the new way to have a common prefix in
> > all printed output.
>
> But you don't actually print anything out in the module :)

But there are pr_debug()s ;-)

> > For compatibility with crypto_comp, we also need an alloc function for both
> > compress and decompress, so that makes 3 alloc functions.
>
> Couldn't crypto_comp just call both alloc functions? I don't see
> why we need a third function.
>
> > > 1) We know what the user wants to do without every algorithm
> > > reinventing their own signalling for it;
> >
> > I guess you want to use the flags to indicate compress/decompress/both?
> > Unfortunately I'm still struggling to fully understand the type/mask handling,
> > so I would appreciate it if you could give me a hint how to handle that.
>
> No, I mean that whether you want compression or decompression
> is signified by the which function you're calling. If you want
> to do both then you call both.

By "both alloc function", do you mean the .setup_comp() and .setup_decomp()
functions? If yes, then I understand.

(Yesterday, I thought you meant to have separate alloc functions instead of the
one crypto_alloc_pcomp())

> > I assume "length" is the size of the passed params, so the algorithms can
> > return -EINVAL if they're passed the wrong size?
>
> Well with the netlink parameters these can have variable lengths
> depending on how many parameters the user supplies.

IC.

> > > > +static inline struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name,
> > > > + u32 type, u32 mask)
> > > > +{
> > > > + type &= ~CRYPTO_ALG_TYPE_MASK;
> > > > + type |= CRYPTO_ALG_TYPE_PCOMPRESS;
> > > > + mask |= CRYPTO_ALG_TYPE_MASK;
> > > > +
> > > > + return __crypto_pcomp_cast(crypto_alloc_base(alg_name, type, mask));
> > > > +}
> > >
> > > That's the old way to allocate tfm's which won't work since pcomp
> > > is using the new type API. You should do it the way that shash
> > > does it.
> >
> > I tried to do this, but stumbled across a dependency problem: as
> > crypto_alloc_tfm() needs a pointer to crypto_pcomp_type(), crypto_alloc_pcomp()
> > can no longer be static inline, and must be moved to crypto/pcompress.c.
>
> Ah yes because crypto_comp is one of the original types that's
> still built-in. Because there are so few compression users and
> algorithms (exactly 3 if you include null compression), I think
> we can dispense with the compatibility stuff altogether since
> we'll likely rip out fairly soon anyway.
>
> So just create the new type, readd deflate using the new type
> alongside the existing deflate algorithm. The system is capable
> of supporting two algorithms of the same name with different types.
>
> Then once the other algorithm (lzo) is taken care of and all the
> users are converted I'll just kill the old type and algorithms.

I doubt whether it's a good idea to drop the compatibility soon, as the
underlying LZO library in the kernel doesn't support partial (de)compression,
and needs significant rework to do so.

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-01-16 04:27:54

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Thu, Jan 15, 2009 at 11:54:53AM +0100, Geert Uytterhoeven wrote:
>
> But there are pr_debug()s ;-)

Well they must've turned invisible in the copy I received :)

> By "both alloc function", do you mean the .setup_comp() and .setup_decomp()
> functions? If yes, then I understand.

Yes.

> (Yesterday, I thought you meant to have separate alloc functions instead of the
> one crypto_alloc_pcomp())

No we want a single tfm for this.

If we ever get hardware that can handle only one of the two
operations we can always implement software fallbacks as we
do for hashing and encryption.

> I doubt whether it's a good idea to drop the compatibility soon, as the
> underlying LZO library in the kernel doesn't support partial (de)compression,
> and needs significant rework to do so.

Yes but LZO has exactly one user (ubifs) in the kernel and it can
stick to the current interface until we convert it over. It's
just not worth the extra work to help a single user.

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-02-05 16:24:54

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

Hi Herbert,

On Thu, 15 Jan 2009, Herbert Xu wrote:
> On Wed, Jan 14, 2009 at 04:01:34PM +0100, Geert Uytterhoeven wrote:
> > On Wed, 14 Jan 2009, Herbert Xu wrote:
> > > Also, this is something that we'll potentially export to user-space,
> > > so we need to ensure that it is invariant to word length.
> > >
> > > So something like this would be good
> > >
> > > int (*setup_comp)(struct crypto_pcomp *tfm, const void *params,
> > > unsigned int length);
> > > int (*setup_decomp)(struct crypto_pcomp *tfm, const void *params,
> > > unsigned int length);
> >
> > I assume "length" is the size of the passed params, so the algorithms can
> > return -EINVAL if they're passed the wrong size?
> >
> > > The actual parameters should be formatted using the netlink helpers
> > > (nla_*). So each parameter that you want to set should show up as
> > > a netlink attribute. If a paramter is absent then you'd just use
> > > the default, etc.
>
> > I assume "length" is the size of the passed params, so the algorithms can
> > return -EINVAL if they're passed the wrong size?
>
> Well with the netlink parameters these can have variable lengths
> depending on how many parameters the user supplies.

How can this be exported to userspace?
How does this variable length parameter passing work? Do you have an example?
Nothing in crypto/ seems to already use nla_*?

> Ah yes because crypto_comp is one of the original types that's
> still built-in. Because there are so few compression users and
> algorithms (exactly 3 if you include null compression), I think
> we can dispense with the compatibility stuff altogether since
> we'll likely rip out fairly soon anyway.
>
> So just create the new type, readd deflate using the new type
> alongside the existing deflate algorithm. The system is capable
> of supporting two algorithms of the same name with different types.

While the core of the crypto system supports two algorithms of the same name
with different types, the testmgr doesn't.

As I removed the backwards-compatility layer at your request, I'll use "zlib"
for the name of the new module. It's more flexible than the fixed "deflate"
one anyway.

Is this OK for you?

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-10 06:18:26

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Thu, Feb 05, 2009 at 05:24:51PM +0100, Geert Uytterhoeven wrote:
>
> > Well with the netlink parameters these can have variable lengths
> > depending on how many parameters the user supplies.
>
> How can this be exported to userspace?
> How does this variable length parameter passing work? Do you have an example?

See how we use it for rtnetlink, e.g., in net/ipv4/ip_gre.c.

> Nothing in crypto/ seems to already use nla_*?

Well we don't have a user-space API yet :) But checkout the
discussions on this list.

> While the core of the crypto system supports two algorithms of the same name
> with different types, the testmgr doesn't.

I was lazy :) But really it isn't too hard to add a type field to
the array in testmgr. We don't even have to add it for existing
entries (except for the ones that you're trying to replace, i.e.,
deflate).

> As I removed the backwards-compatility layer at your request, I'll use "zlib"
> for the name of the new module. It's more flexible than the fixed "deflate"
> one anyway.
>
> Is this OK for you?

Hmm, I think we need to have it stay as deflate if we're to make
an easy transition for existing users (e.g., IPsec).

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-02-12 15:19:42

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Tue, 10 Feb 2009, Herbert Xu wrote:
> On Thu, Feb 05, 2009 at 05:24:51PM +0100, Geert Uytterhoeven wrote:
> > > Well with the netlink parameters these can have variable lengths
> > > depending on how many parameters the user supplies.
> >
> > How can this be exported to userspace?
> > How does this variable length parameter passing work? Do you have an example?
>
> See how we use it for rtnetlink, e.g., in net/ipv4/ip_gre.c.
>
> > Nothing in crypto/ seems to already use nla_*?
>
> Well we don't have a user-space API yet :) But checkout the
> discussions on this list.

I'm sorry, but this is a totally separate change, so I'm not going to do it
right now.

> > While the core of the crypto system supports two algorithms of the same name
> > with different types, the testmgr doesn't.
>
> I was lazy :) But really it isn't too hard to add a type field to
> the array in testmgr. We don't even have to add it for existing
> entries (except for the ones that you're trying to replace, i.e.,
> deflate).

Are you sure about that? Shouldn't all the call sites to tcrypt_test() get a
type parameter, too?

> > As I removed the backwards-compatility layer at your request, I'll use "zlib"
> > for the name of the new module. It's more flexible than the fixed "deflate"
> > one anyway.
> >
> > Is this OK for you?
>
> Hmm, I think we need to have it stay as deflate if we're to make
> an easy transition for existing users (e.g., IPsec).

It's just a matter of replacing the literal "deflate" by "zlib", when switching
net/xfrm/xfrm_algo.c from the old to the new API. As there won't be a
backwards-compatibility layer, the algorithm names don't have to match.

It's much less work than adding crypto types to all parts of the test code...

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-19 04:08:51

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Thu, Feb 12, 2009 at 04:19:40PM +0100, Geert Uytterhoeven wrote:
> On Tue, 10 Feb 2009, Herbert Xu wrote:
> > On Thu, Feb 05, 2009 at 05:24:51PM +0100, Geert Uytterhoeven wrote:
> > > > Well with the netlink parameters these can have variable lengths
> > > > depending on how many parameters the user supplies.
> > >
> > > How can this be exported to userspace?
> > > How does this variable length parameter passing work? Do you have an example?
> >
> > See how we use it for rtnetlink, e.g., in net/ipv4/ip_gre.c.
> >
> > > Nothing in crypto/ seems to already use nla_*?
> >
> > Well we don't have a user-space API yet :) But checkout the
> > discussions on this list.
>
> I'm sorry, but this is a totally separate change, so I'm not going to do it
> right now.

Sorry but I disagree. We're working on the user-space API right
now and having to redo the compression parameters API later because
we didn't take take user-space into account is just not acceptable.

In any case, the nla stuff is not as hard is it looks. It's
going to add tens of lines to the setup code and that's it.

In order to get started, all you need to do is call nla_parse.
You don't even need a policy for the simple attributes.

Please let me know if you need more help in getting nla_parse
going.

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-02-19 09:12:20

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Thu, 19 Feb 2009, Herbert Xu wrote:
> On Thu, Feb 12, 2009 at 04:19:40PM +0100, Geert Uytterhoeven wrote:
> > On Tue, 10 Feb 2009, Herbert Xu wrote:
> > > On Thu, Feb 05, 2009 at 05:24:51PM +0100, Geert Uytterhoeven wrote:
> > > > > Well with the netlink parameters these can have variable lengths
> > > > > depending on how many parameters the user supplies.
> > > >
> > > > How can this be exported to userspace?
> > > > How does this variable length parameter passing work? Do you have an example?
> > >
> > > See how we use it for rtnetlink, e.g., in net/ipv4/ip_gre.c.
> > >
> > > > Nothing in crypto/ seems to already use nla_*?
> > >
> > > Well we don't have a user-space API yet :) But checkout the
> > > discussions on this list.
> >
> > I'm sorry, but this is a totally separate change, so I'm not going to do it
> > right now.
>
> Sorry but I disagree. We're working on the user-space API right
> now and having to redo the compression parameters API later because
> we didn't take take user-space into account is just not acceptable.

OK, I'll give it a try...

> In any case, the nla stuff is not as hard is it looks. It's
> going to add tens of lines to the setup code and that's it.
>
> In order to get started, all you need to do is call nla_parse.
> You don't even need a policy for the simple attributes.
>
> Please let me know if you need more help in getting nla_parse
> going.

IIUC, my setup() routines should decode the parameters using nla_parse()?
And the caller of a setup() routine should encode the data. But how? All the
nla_put*() routines seem to be targeted at skb's.

The only place where nla_parse() is called with a void */length pair is
net/sched/em_meta.c:em_meta_change(). But I can find no place where the actual
TCA_EM_META_* fields are encoded.

Can you please explain? 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-19 10:42:53

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Thu, Feb 19, 2009 at 10:12:18AM +0100, Geert Uytterhoeven wrote:
>
> IIUC, my setup() routines should decode the parameters using nla_parse()?

Right.

> And the caller of a setup() routine should encode the data. But how? All the
> nla_put*() routines seem to be targeted at skb's.

The callers in the kernel should just lay it out on the stack, e.g.,

struct {
struct nlattr foo;
u32 foo_val;
struct nlattr bar;
u32 bar_val;
...
};

Note that the netlink alignment is 4 so u32 doesn't need any padding
though u8/u16 would need padding before the next nlattr. Although
for our purposes u32 should be sufficient.

> The only place where nla_parse() is called with a void */length pair is
> net/sched/em_meta.c:em_meta_change(). But I can find no place where the actual
> TCA_EM_META_* fields are encoded.

For simple things like u32 the format is just header followed by
the u32. See nla_get_u32 for details.

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-02-23 17:32:24

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

Hi Herbert,

On Thu, 19 Feb 2009, Herbert Xu wrote:
> On Thu, Feb 19, 2009 at 10:12:18AM +0100, Geert Uytterhoeven wrote:
> > IIUC, my setup() routines should decode the parameters using nla_parse()?
>
> Right.
>
> > And the caller of a setup() routine should encode the data. But how? All the
> > nla_put*() routines seem to be targeted at skb's.
>
> The callers in the kernel should just lay it out on the stack, e.g.,
>
> struct {
> struct nlattr foo;
> u32 foo_val;
> struct nlattr bar;
> u32 bar_val;
> ...
> };
>
> Note that the netlink alignment is 4 so u32 doesn't need any padding
> though u8/u16 would need padding before the next nlattr. Although
> for our purposes u32 should be sufficient.
>
> > The only place where nla_parse() is called with a void */length pair is
> > net/sched/em_meta.c:em_meta_change(). But I can find no place where the actual
> > TCA_EM_META_* fields are encoded.
>
> For simple things like u32 the format is just header followed by
> the u32. See nla_get_u32 for details.

Is the below (on top of my last patch series) what you have in mind?

Notes:
- I had to drop the `const' from the `params' pointers of
pcomp_alg.{,de}compress_setup().
Trying to make nla_parse() take const nlattr structures instead seems to
open a big can of worms...
- I should add a dependency of CONFIG_CRYPTO_ZLIB on CONFIG_NET (due to the
need for nla_parse()). However, I don't like that.

Thanks for your comments!

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 4703137..b50c3c6 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -919,7 +919,8 @@ static int test_pcomp(struct crypto_pcomp *tfm,
for (i = 0; i < ctcount; i++) {
struct comp_request req;

- error = crypto_compress_setup(tfm, ctemplate[i].params);
+ 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);
@@ -986,7 +987,8 @@ static int test_pcomp(struct crypto_pcomp *tfm,
for (i = 0; i < dtcount; i++) {
struct comp_request req;

- error = crypto_decompress_setup(tfm, dtemplate[i].params);
+ 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,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 098c033..526f00a 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -15,7 +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
@@ -8351,7 +8353,8 @@ struct comp_testvec {
};

struct pcomp_testvec {
- const void *params;
+ void *params;
+ unsigned int paramsize;
int inlen, outlen;
char input[COMP_BUF_SIZE];
char output[COMP_BUF_SIZE];
@@ -8440,21 +8443,60 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
#define ZLIB_COMP_TEST_VECTORS 2
#define ZLIB_DECOMP_TEST_VECTORS 2

-static const struct zlib_comp_params deflate_comp_params = {
- .level = Z_DEFAULT_COMPRESSION,
- .method = Z_DEFLATED,
- .windowBits = -11,
- .memLevel = MAX_MEM_LEVEL,
- .strategy = Z_DEFAULT_STRATEGY
+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 zlib_decomp_params deflate_decomp_params = {
- .windowBits = -11,
+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 "
@@ -8466,6 +8508,7 @@ static struct pcomp_testvec zlib_comp_tv_template[] = {
"\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"
@@ -8493,6 +8536,7 @@ static struct pcomp_testvec zlib_comp_tv_template[] = {
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"
@@ -8516,6 +8560,7 @@ static struct pcomp_testvec zlib_decomp_tv_template[] = {
"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"
diff --git a/crypto/zlib.c b/crypto/zlib.c
index 77b865d..33609ba 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -33,11 +33,13 @@

#include <crypto/internal/compress.h>

+#include <net/netlink.h>
+

struct zlib_ctx {
- struct zlib_decomp_params decomp_params;
struct z_stream_s comp_stream;
struct z_stream_s decomp_stream;
+ int decomp_windowBits;
};


@@ -77,13 +79,18 @@ static void zlib_exit(struct crypto_tfm *tfm)
}


-static int zlib_compress_setup(struct crypto_pcomp *tfm, const void *params)
+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));
- const struct zlib_comp_params *zparams = params;
struct z_stream_s *stream = &ctx->comp_stream;
+ struct nlattr *tb[ZLIB_COMP_MAX + 1];
size_t workspacesize;
- int ret = 0;
+ int ret;
+
+ ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL);
+ if (ret)
+ return ret;

zlib_comp_exit(ctx);

@@ -93,9 +100,22 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, const void *params)
return -ENOMEM;

memset(stream->workspace, 0, workspacesize);
- ret = zlib_deflateInit2(stream, zparams->level, zparams->method,
- zparams->windowBits, zparams->memLevel,
- zparams->strategy);
+ 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;
@@ -187,22 +207,29 @@ static int zlib_compress_final(struct crypto_pcomp *tfm,
}


-static int zlib_decompress_setup(struct crypto_pcomp *tfm, const void *params)
+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));
- const struct zlib_decomp_params *zparams = params;
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_params = *zparams;
+ 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, zparams->windowBits);
+ ret = zlib_inflateInit2(stream, ctx->decomp_windowBits);
if (ret != Z_OK) {
kfree(stream->workspace);
stream->workspace = NULL;
@@ -277,7 +304,7 @@ static int zlib_decompress_final(struct crypto_pcomp *tfm,
stream->next_out = req->next_out;
stream->avail_out = req->avail_out;

- if (dctx->decomp_params.windowBits < 0) {
+ if (dctx->decomp_windowBits < 0) {
ret = zlib_inflate(stream, Z_SYNC_FLUSH);
/*
* Work around a bug in zlib, which sometimes wants to taste an
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 12ed86d..62be5ae 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -39,6 +39,8 @@

#include <crypto/compress.h>

+#include <net/netlink.h>
+
#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
#include "squashfs_fs_i.h"
@@ -81,7 +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 zlib_decomp_params params = { .windowBits = DEF_WBITS };
+ 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");
@@ -102,7 +113,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
goto failed_pcomp;
}

- err = crypto_decompress_setup(msblk->tfm, &params);
+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
if (err) {
ERROR("Failed to set up decompression parameters\n");
goto failure;
diff --git a/include/crypto/compress.h b/include/crypto/compress.h
index 67ba57d..86163ef 100644
--- a/include/crypto/compress.h
+++ b/include/crypto/compress.h
@@ -30,30 +30,40 @@ struct comp_request {
unsigned int avail_out; /* bytes available at next_out */
};

-struct zlib_comp_params {
- int level; /* e.g. Z_DEFAULT_COMPRESSION */
- int method; /* e.g. Z_DEFLATED */
- int windowBits; /* e.g. MAX_WBITS */
- int memLevel; /* e.g. DEF_MEM_LEVEL */
- int strategy; /* e.g. Z_DEFAULT_STRATEGY */
+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,
};

-struct zlib_decomp_params {
- int windowBits; /* e.g. DEF_WBITS */
+#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;
};

struct pcomp_alg {
- int (*compress_setup)(struct crypto_pcomp *tfm, const void *params);
+ 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, const void *params);
+ 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);
@@ -87,9 +97,9 @@ static inline struct pcomp_alg *crypto_pcomp_alg(struct crypto_pcomp *tfm)
}

static inline int crypto_compress_setup(struct crypto_pcomp *tfm,
- const void *params)
+ void *params, unsigned int len)
{
- return crypto_pcomp_alg(tfm)->compress_setup(tfm, params);
+ return crypto_pcomp_alg(tfm)->compress_setup(tfm, params, len);
}

static inline int crypto_compress_init(struct crypto_pcomp *tfm)
@@ -110,9 +120,9 @@ static inline int crypto_compress_final(struct crypto_pcomp *tfm,
}

static inline int crypto_decompress_setup(struct crypto_pcomp *tfm,
- const void *params)
+ void *params, unsigned int len)
{
- return crypto_pcomp_alg(tfm)->decompress_setup(tfm, params);
+ return crypto_pcomp_alg(tfm)->decompress_setup(tfm, params, len);
}

static inline int crypto_decompress_init(struct crypto_pcomp *tfm)

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 02:56:11

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Mon, Feb 23, 2009 at 06:32:19PM +0100, Geert Uytterhoeven wrote:
>
> Is the below (on top of my last patch series) what you have in mind?

Looks great to me!

> Notes:
> - I had to drop the `const' from the `params' pointers of
> pcomp_alg.{,de}compress_setup().
> Trying to make nla_parse() take const nlattr structures instead seems to
> open a big can of worms...

I don't think that's a big deal.

> - I should add a dependency of CONFIG_CRYPTO_ZLIB on CONFIG_NET (due to the
> need for nla_parse()). However, I don't like that.

Dave has OKed it for the attribute stuff to be moved into lib.
So if you want to tackle that then be my guest :) Otherwise I'll
look into moving 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-02-25 13:26:32

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH] crypto: compress - Add pcomp interface

On Wed, 25 Feb 2009, Herbert Xu wrote:
> On Mon, Feb 23, 2009 at 06:32:19PM +0100, Geert Uytterhoeven wrote:
> >
> > Is the below (on top of my last patch series) what you have in mind?
>
> Looks great to me!

OK.

> > Notes:
> > - I had to drop the `const' from the `params' pointers of
> > pcomp_alg.{,de}compress_setup().
> > Trying to make nla_parse() take const nlattr structures instead seems to
> > open a big can of worms...
>
> I don't think that's a big deal.
>
> > - I should add a dependency of CONFIG_CRYPTO_ZLIB on CONFIG_NET (due to the
> > need for nla_parse()). However, I don't like that.
>
> Dave has OKed it for the attribute stuff to be moved into lib.
> So if you want to tackle that then be my guest :) Otherwise I'll
> look into moving it.

I already have a patch for that. I'll fold the netlink parsing into the
original series and will resubmit.

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