Modify SquashFS 4 to use the new "zlib" crypto module as a proof-of-concept for the partial decompression CRYPTO API enhancements. Note: Patch against squashfs-2.6.git, as SquashFS is not yet in mainline Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@xxxxxxxxxxx> --- Kconfig | 3 +- squashfs/block.c | 67 +++++++++++++++++++++++++++------------------- squashfs/squashfs_fs_sb.h | 4 ++ squashfs/super.c | 20 ++++++++----- 4 files changed, 58 insertions(+), 36 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index 1d7a5f9..8eebe53 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -934,7 +934,8 @@ config CRAMFS config SQUASHFS tristate "SquashFS 4.0 - Squashed file system support" depends on BLOCK - select ZLIB_INFLATE + select CRYPTO + select CRYPTO_ZLIB help Saying Y here includes support for SquashFS 4.0 (a Compressed Read-Only File System). Squashfs is a highly compressed read-only diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index da5f88b..9a681cb 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c @@ -32,7 +32,7 @@ #include <linux/mutex.h> #include <linux/string.h> #include <linux/buffer_head.h> -#include <linux/zlib.h> +#include <linux/crypto.h> #include "squashfs_fs.h" #include "squashfs_fs_sb.h" @@ -150,7 +150,8 @@ int squashfs_read_data(struct super_block *sb, void *buffer, } if (compressed) { - int zlib_err = 0; + int error = 0; + struct comp_request req; /* * Uncompress block. @@ -158,8 +159,8 @@ int squashfs_read_data(struct super_block *sb, void *buffer, mutex_lock(&msblk->read_data_mutex); - msblk->stream.next_out = buffer; - msblk->stream.avail_out = srclength; + req.next_out = buffer; + req.avail_out = srclength; for (bytes = 0; k < b; k++) { avail = min(c_byte - bytes, msblk->devblksize - offset); @@ -168,16 +169,19 @@ int squashfs_read_data(struct super_block *sb, void *buffer, if (!buffer_uptodate(bh[k])) goto release_mutex; - 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; if (k == 0) { - 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); + error = crypto_comp_decompress_init(msblk->tfm, + &req); + if (error && error != -EAGAIN) { + ERROR("crypto_comp_decompress_init " + "returned unexpected result %d, " + "srclength %d, avail_in %u, " + "avail_out %u\n", + error, srclength, req.avail_in, + req.avail_out); goto release_mutex; } @@ -186,15 +190,25 @@ int squashfs_read_data(struct super_block *sb, void *buffer, brelse(bh[k]); continue; } + + } else { + error = crypto_comp_decompress_update(msblk->tfm, + &req); + if (error) { + ERROR("crypto_comp_decompress_update " + "returned unexpected result %d, " + "srclength %d, avail_in %u, " + "avail_out %u\n", + error, srclength, req.avail_in, + req.avail_out); + goto release_mutex; + } } - zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); - if (zlib_err != Z_OK && 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); + if (req.avail_in) { + ERROR("crypto_comp_decompress_* did not " + "consume all input data (%u left)\n", + req.avail_in); goto release_mutex; } @@ -203,16 +217,15 @@ int squashfs_read_data(struct super_block *sb, void *buffer, brelse(bh[k]); } - if (zlib_err != Z_STREAM_END) - 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); + error = crypto_comp_decompress_final(msblk->tfm, &req); + if (error) { + ERROR("crypto_comp_decompress_final returned " + "unexpected result %d, srclength %d, avail_in " + "%u, avail_out %u\n", + error, srclength, req.avail_in, req.avail_out); goto release_mutex; } - bytes = msblk->stream.total_out; + bytes = req.next_out - buffer; mutex_unlock(&msblk->read_data_mutex); } else { /* diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h index 18e5af4..769bbef 100644 --- a/fs/squashfs/squashfs_fs_sb.h +++ b/fs/squashfs/squashfs_fs_sb.h @@ -23,6 +23,8 @@ * squashfs_fs_sb.h */ +#include <linux/crypto.h> + #include "squashfs_fs.h" struct squashfs_cache_entry { @@ -63,7 +65,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_comp *tfm; __le64 *inode_lookup_table; long long inode_table; long long directory_table; diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 44f94aa..38e0535 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -35,13 +35,17 @@ #include <linux/pagemap.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/zlib.h> +#include <linux/crypto.h> #include "squashfs_fs.h" #include "squashfs_fs_sb.h" #include "squashfs_fs_i.h" #include "squashfs.h" + +#define SQUASHFS_CRYPTO_ALG "zlib" + + static struct file_system_type squashfs_fs_type; static struct super_operations squashfs_super_ops; @@ -86,9 +90,11 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) } msblk = sb->s_fs_info; - msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); - if (msblk->stream.workspace == NULL) { - ERROR("Failed to allocate zlib workspace\n"); + msblk->tfm = crypto_alloc_comp(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; goto failure; } @@ -284,14 +290,14 @@ failed_mount: kfree(msblk->inode_lookup_table); kfree(msblk->fragment_index); kfree(msblk->id_table); - vfree(msblk->stream.workspace); + crypto_free_comp(msblk->tfm); kfree(sb->s_fs_info); sb->s_fs_info = NULL; kfree(sblk); return err; failure: - vfree(msblk->stream.workspace); + crypto_free_comp(msblk->tfm); kfree(sb->s_fs_info); sb->s_fs_info = NULL; return -ENOMEM; @@ -333,7 +339,7 @@ static void squashfs_put_super(struct super_block *sb) kfree(sbi->id_table); kfree(sbi->fragment_index); kfree(sbi->meta_index); - vfree(sbi->stream.workspace); + crypto_free_comp(sbi->tfm); kfree(sb->s_fs_info); sb->s_fs_info = NULL; } 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: Geert.Uytterhoeven@xxxxxxxxxxx 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 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html