diff options
author | kaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-11-02 09:51:35 +0000 |
---|---|---|
committer | kaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-11-02 09:51:35 +0000 |
commit | 7e8dd669c9aa3a76c7b9855e824cfb2c9290a9fc (patch) | |
tree | 46674e60496abcaeb73c4401a2f25f25a50123e5 | |
parent | f7eef9ce534eedd9323aa9ec2af524c9d12aa0a5 (diff) |
Switch to the squashfs-lzma code from the squashfs-devel git tree.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18267 3c298f89-4303-0410-b956-a3cf2f4a3e73
24 files changed, 3045 insertions, 3040 deletions
diff --git a/target/linux/generic-2.6/config-2.6.30 b/target/linux/generic-2.6/config-2.6.30 index 403cc54d7..8e590b766 100644 --- a/target/linux/generic-2.6/config-2.6.30 +++ b/target/linux/generic-2.6/config-2.6.30 @@ -403,6 +403,7 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_KERNEL is not set # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DECNET is not set +CONFIG_DECOMPRESS_LZMA_NEEDED=y # CONFIG_DEFAULT_AS is not set # CONFIG_DEFAULT_BIC is not set # CONFIG_DEFAULT_CFQ is not set @@ -2059,7 +2060,7 @@ CONFIG_SND_VERBOSE_PROCFS=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 -CONFIG_SQUASHFS_SUPPORT_LZMA=y +CONFIG_SQUASHFS_LZMA=y CONFIG_SQUASHFS_SUPPORT_ZLIB=y # CONFIG_SQUASHFS_VMALLOC is not set CONFIG_SQUASHFS=y diff --git a/target/linux/generic-2.6/config-2.6.31 b/target/linux/generic-2.6/config-2.6.31 index e60f993a1..3b4bed5e4 100644 --- a/target/linux/generic-2.6/config-2.6.31 +++ b/target/linux/generic-2.6/config-2.6.31 @@ -420,6 +420,7 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_KERNEL is not set # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DECNET is not set +CONFIG_DECOMPRESS_LZMA_NEEDED=y # CONFIG_DEFAULT_AS is not set # CONFIG_DEFAULT_BIC is not set # CONFIG_DEFAULT_CFQ is not set @@ -2104,7 +2105,7 @@ CONFIG_SND_VERBOSE_PROCFS=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_SQUASHFS_EMBEDDED is not set CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 -CONFIG_SQUASHFS_SUPPORT_LZMA=y +CONFIG_SQUASHFS_LZMA=y CONFIG_SQUASHFS_SUPPORT_ZLIB=y # CONFIG_SQUASHFS_VMALLOC is not set CONFIG_SQUASHFS=y diff --git a/target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch b/target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch new file mode 100644 index 000000000..33572b890 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch @@ -0,0 +1,113 @@ +From b1af4315d823a2b6659c5b14bc17f7bc61878ef4 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Thu, 6 Aug 2009 15:09:31 -0700 +Subject: [PATCH] bzip2/lzma: remove nasty uncompressed size hack in pre-boot environment + +decompress_bunzip2 and decompress_unlzma have a nasty hack that subtracts +4 from the input length if being called in the pre-boot environment. + +This is a nasty hack because it relies on the fact that flush = NULL only +when called from the pre-boot environment (i.e. +arch/x86/boot/compressed/misc.c). initramfs.c/do_mounts_rd.c pass in a +flush buffer (flush != NULL). + +This hack prevents the decompressors from being used with flush = NULL by +other callers unless knowledge of the hack is propagated to them. + +This patch removes the hack by making decompress (called only from the +pre-boot environment) a wrapper function that subtracts 4 from the input +length before calling the decompressor. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +Cc: "H. Peter Anvin" <hpa@zytor.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + lib/decompress_bunzip2.c | 22 ++++++++++++++++------ + lib/decompress_unlzma.c | 21 ++++++++++++++++----- + 2 files changed, 32 insertions(+), 11 deletions(-) + +--- a/lib/decompress_bunzip2.c ++++ b/lib/decompress_bunzip2.c +@@ -45,9 +45,11 @@ + */ + + +-#ifndef STATIC ++#ifdef STATIC ++#define PREBOOT ++#else + #include <linux/decompress/bunzip2.h> +-#endif /* !STATIC */ ++#endif /* STATIC */ + + #include <linux/decompress/mm.h> + #include <linux/slab.h> +@@ -681,9 +683,7 @@ STATIC int INIT bunzip2(unsigned char *b + set_error_fn(error_fn); + if (flush) + outbuf = malloc(BZIP2_IOBUF_SIZE); +- else +- len -= 4; /* Uncompressed size hack active in pre-boot +- environment */ ++ + if (!outbuf) { + error("Could not allocate output bufer"); + return -1; +@@ -733,4 +733,14 @@ exit_0: + return i; + } + +-#define decompress bunzip2 ++#ifdef PREBOOT ++STATIC int INIT decompress(unsigned char *buf, int len, ++ int(*fill)(void*, unsigned int), ++ int(*flush)(void*, unsigned int), ++ unsigned char *outbuf, ++ int *pos, ++ void(*error_fn)(char *x)) ++{ ++ return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error_fn); ++} ++#endif +--- a/lib/decompress_unlzma.c ++++ b/lib/decompress_unlzma.c +@@ -29,7 +29,9 @@ + *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#ifndef STATIC ++#ifdef STATIC ++#define PREBOOT ++#else + #include <linux/decompress/unlzma.h> + #endif /* STATIC */ + +@@ -543,9 +545,7 @@ STATIC inline int INIT unlzma(unsigned c + int ret = -1; + + set_error_fn(error_fn); +- if (!flush) +- in_len -= 4; /* Uncompressed size hack active in pre-boot +- environment */ ++ + if (buf) + inbuf = buf; + else +@@ -645,4 +645,15 @@ exit_0: + return ret; + } + +-#define decompress unlzma ++#ifdef PREBOOT ++STATIC int INIT decompress(unsigned char *buf, int in_len, ++ int(*fill)(void*, unsigned int), ++ int(*flush)(void*, unsigned int), ++ unsigned char *output, ++ int *posp, ++ void(*error_fn)(char *x) ++ ) ++{ ++ return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn); ++} ++#endif diff --git a/target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch b/target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch new file mode 100644 index 000000000..94096791f --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch @@ -0,0 +1,244 @@ +From 6c4419d997d4431bb62e73475cd6b084e83efbd1 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Tue, 22 Sep 2009 19:25:24 +0100 +Subject: [PATCH] Squashfs: move zlib decompression wrapper code into a separate file + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Makefile | 2 +- + fs/squashfs/block.c | 74 ++---------------------------- + fs/squashfs/squashfs.h | 4 ++ + fs/squashfs/zlib_wrapper.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 118 insertions(+), 71 deletions(-) + create mode 100644 fs/squashfs/zlib_wrapper.c + +--- a/fs/squashfs/Makefile ++++ b/fs/squashfs/Makefile +@@ -4,4 +4,4 @@ + + obj-$(CONFIG_SQUASHFS) += squashfs.o + squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o +-squashfs-y += namei.o super.o symlink.o ++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o +--- a/fs/squashfs/block.c ++++ b/fs/squashfs/block.c +@@ -29,7 +29,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/mutex.h> + #include <linux/string.h> + #include <linux/buffer_head.h> + #include <linux/zlib.h> +@@ -153,72 +152,10 @@ int squashfs_read_data(struct super_bloc + } + + if (compressed) { +- int zlib_err = 0, zlib_init = 0; +- +- /* +- * Uncompress block. +- */ +- +- mutex_lock(&msblk->read_data_mutex); +- +- msblk->stream.avail_out = 0; +- msblk->stream.avail_in = 0; +- +- bytes = length; +- do { +- if (msblk->stream.avail_in == 0 && k < b) { +- avail = min(bytes, msblk->devblksize - offset); +- bytes -= avail; +- wait_on_buffer(bh[k]); +- if (!buffer_uptodate(bh[k])) +- goto release_mutex; +- +- if (avail == 0) { +- offset = 0; +- put_bh(bh[k++]); +- continue; +- } +- +- msblk->stream.next_in = bh[k]->b_data + offset; +- msblk->stream.avail_in = avail; +- offset = 0; +- } +- +- if (msblk->stream.avail_out == 0 && page < pages) { +- msblk->stream.next_out = buffer[page++]; +- msblk->stream.avail_out = PAGE_CACHE_SIZE; +- } +- +- if (!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); +- goto release_mutex; +- } +- zlib_init = 1; +- } +- +- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); +- +- if (msblk->stream.avail_in == 0 && k < b) +- put_bh(bh[k++]); +- } while (zlib_err == Z_OK); +- +- if (zlib_err != Z_STREAM_END) { +- ERROR("zlib_inflate error, data probably corrupt\n"); +- goto release_mutex; +- } +- +- zlib_err = zlib_inflateEnd(&msblk->stream); +- if (zlib_err != Z_OK) { +- ERROR("zlib_inflate error, data probably corrupt\n"); +- goto release_mutex; +- } +- length = msblk->stream.total_out; +- mutex_unlock(&msblk->read_data_mutex); ++ length = zlib_uncompress(msblk, buffer, bh, b, offset, length, ++ srclength, pages); ++ if (length < 0) ++ goto read_failure; + } else { + /* + * Block is uncompressed. +@@ -255,9 +192,6 @@ int squashfs_read_data(struct super_bloc + kfree(bh); + return length; + +-release_mutex: +- mutex_unlock(&msblk->read_data_mutex); +- + block_release: + for (; k < b; k++) + put_bh(bh[k]); +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -70,6 +70,10 @@ extern struct inode *squashfs_iget(struc + unsigned int); + extern int squashfs_read_inode(struct inode *, long long); + ++/* zlib_wrapper.c */ ++extern int zlib_uncompress(struct squashfs_sb_info *, void **, ++ struct buffer_head **, int, int, int, int, int); ++ + /* + * Inodes and files operations + */ +--- /dev/null ++++ b/fs/squashfs/zlib_wrapper.c +@@ -0,0 +1,109 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * zlib_wrapper.c ++ */ ++ ++ ++#include <linux/mutex.h> ++#include <linux/buffer_head.h> ++#include <linux/zlib.h> ++ ++#include "squashfs_fs.h" ++#include "squashfs_fs_sb.h" ++#include "squashfs_fs_i.h" ++#include "squashfs.h" ++ ++int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, ++ struct buffer_head **bh, int b, int offset, int length, int srclength, ++ int pages) ++{ ++ int zlib_err = 0, zlib_init = 0; ++ int avail, bytes, k = 0, page = 0; ++ ++ mutex_lock(&msblk->read_data_mutex); ++ ++ msblk->stream.avail_out = 0; ++ msblk->stream.avail_in = 0; ++ ++ bytes = length; ++ do { ++ if (msblk->stream.avail_in == 0 && k < b) { ++ avail = min(bytes, msblk->devblksize - offset); ++ bytes -= avail; ++ wait_on_buffer(bh[k]); ++ if (!buffer_uptodate(bh[k])) ++ goto release_mutex; ++ ++ if (avail == 0) { ++ offset = 0; ++ put_bh(bh[k++]); ++ continue; ++ } ++ ++ msblk->stream.next_in = bh[k]->b_data + offset; ++ msblk->stream.avail_in = avail; ++ offset = 0; ++ } ++ ++ if (msblk->stream.avail_out == 0 && page < pages) { ++ msblk->stream.next_out = buffer[page++]; ++ msblk->stream.avail_out = PAGE_CACHE_SIZE; ++ } ++ ++ if (!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); ++ goto release_mutex; ++ } ++ zlib_init = 1; ++ } ++ ++ zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); ++ ++ if (msblk->stream.avail_in == 0 && k < b) ++ put_bh(bh[k++]); ++ } while (zlib_err == Z_OK); ++ ++ if (zlib_err != Z_STREAM_END) { ++ ERROR("zlib_inflate error, data probably corrupt\n"); ++ goto release_mutex; ++ } ++ ++ zlib_err = zlib_inflateEnd(&msblk->stream); ++ if (zlib_err != Z_OK) { ++ ERROR("zlib_inflate error, data probably corrupt\n"); ++ goto release_mutex; ++ } ++ ++ mutex_unlock(&msblk->read_data_mutex); ++ return msblk->stream.total_out; ++ ++release_mutex: ++ mutex_unlock(&msblk->read_data_mutex); ++ ++ for (; k < b; k++) ++ put_bh(bh[k]); ++ ++ return -EIO; ++} diff --git a/target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch b/target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch new file mode 100644 index 000000000..857834f21 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch @@ -0,0 +1,317 @@ +From 37c44e85fd49676ec15ccaeea065662c1fbcda7d Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Wed, 23 Sep 2009 19:04:49 +0100 +Subject: [PATCH] Squashfs: Factor out remaining zlib dependencies into separate wrapper file + +Move zlib buffer init/destroy code into separate wrapper file. Also +make zlib z_stream field a void * removing the need to include zlib.h +for most files. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/block.c | 1 - + fs/squashfs/cache.c | 1 - + fs/squashfs/dir.c | 1 - + fs/squashfs/export.c | 1 - + fs/squashfs/file.c | 1 - + fs/squashfs/fragment.c | 1 - + fs/squashfs/id.c | 1 - + fs/squashfs/inode.c | 1 - + fs/squashfs/namei.c | 1 - + fs/squashfs/squashfs.h | 2 + + fs/squashfs/squashfs_fs_sb.h | 2 +- + fs/squashfs/super.c | 14 +++------ + fs/squashfs/symlink.c | 1 - + fs/squashfs/zlib_wrapper.c | 56 ++++++++++++++++++++++++++++++++--------- + 14 files changed, 51 insertions(+), 33 deletions(-) + +--- a/fs/squashfs/block.c ++++ b/fs/squashfs/block.c +@@ -31,7 +31,6 @@ + #include <linux/slab.h> + #include <linux/string.h> + #include <linux/buffer_head.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/cache.c ++++ b/fs/squashfs/cache.c +@@ -51,7 +51,6 @@ + #include <linux/sched.h> + #include <linux/spinlock.h> + #include <linux/wait.h> +-#include <linux/zlib.h> + #include <linux/pagemap.h> + + #include "squashfs_fs.h" +--- a/fs/squashfs/dir.c ++++ b/fs/squashfs/dir.c +@@ -30,7 +30,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/export.c ++++ b/fs/squashfs/export.c +@@ -39,7 +39,6 @@ + #include <linux/vfs.h> + #include <linux/dcache.h> + #include <linux/exportfs.h> +-#include <linux/zlib.h> + #include <linux/slab.h> + + #include "squashfs_fs.h" +--- a/fs/squashfs/file.c ++++ b/fs/squashfs/file.c +@@ -47,7 +47,6 @@ + #include <linux/string.h> + #include <linux/pagemap.h> + #include <linux/mutex.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/fragment.c ++++ b/fs/squashfs/fragment.c +@@ -36,7 +36,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/id.c ++++ b/fs/squashfs/id.c +@@ -34,7 +34,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/inode.c ++++ b/fs/squashfs/inode.c +@@ -40,7 +40,6 @@ + + #include <linux/fs.h> + #include <linux/vfs.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/namei.c ++++ b/fs/squashfs/namei.c +@@ -57,7 +57,6 @@ + #include <linux/slab.h> + #include <linux/string.h> + #include <linux/dcache.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -71,6 +71,8 @@ extern struct inode *squashfs_iget(struc + extern int squashfs_read_inode(struct inode *, long long); + + /* zlib_wrapper.c */ ++extern void *zlib_init(void); ++extern void zlib_free(void *); + extern int zlib_uncompress(struct squashfs_sb_info *, void **, + struct buffer_head **, int, int, int, int, int); + +--- 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; ++ void *stream; + __le64 *inode_lookup_table; + u64 inode_table; + u64 directory_table; +--- a/fs/squashfs/super.c ++++ b/fs/squashfs/super.c +@@ -34,7 +34,6 @@ + #include <linux/pagemap.h> + #include <linux/init.h> + #include <linux/module.h> +-#include <linux/zlib.h> + #include <linux/magic.h> + + #include "squashfs_fs.h" +@@ -86,12 +85,9 @@ static int squashfs_fill_super(struct su + } + 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->stream = zlib_init(); ++ if (msblk->stream == NULL) + goto failure; +- } + + sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); + if (sblk == NULL) { +@@ -291,17 +287,17 @@ failed_mount: + squashfs_cache_delete(msblk->block_cache); + squashfs_cache_delete(msblk->fragment_cache); + squashfs_cache_delete(msblk->read_page); ++ zlib_free(msblk->stream); + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->id_table); +- kfree(msblk->stream.workspace); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + kfree(sblk); + return err; + + failure: +- kfree(msblk->stream.workspace); ++ zlib_free(msblk->stream); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + return -ENOMEM; +@@ -343,10 +339,10 @@ static void squashfs_put_super(struct su + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + squashfs_cache_delete(sbi->read_page); ++ zlib_free(sbi->stream); + kfree(sbi->id_table); + kfree(sbi->fragment_index); + kfree(sbi->meta_index); +- kfree(sbi->stream.workspace); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + } +--- a/fs/squashfs/symlink.c ++++ b/fs/squashfs/symlink.c +@@ -36,7 +36,6 @@ + #include <linux/slab.h> + #include <linux/string.h> + #include <linux/pagemap.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/zlib_wrapper.c ++++ b/fs/squashfs/zlib_wrapper.c +@@ -31,21 +31,51 @@ + #include "squashfs_fs_i.h" + #include "squashfs.h" + ++void *zlib_init() ++{ ++ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); ++ if (stream == NULL) ++ goto failed; ++ stream->workspace = kmalloc(zlib_inflate_workspacesize(), ++ GFP_KERNEL); ++ if (stream->workspace == NULL) ++ goto failed; ++ ++ return stream; ++ ++failed: ++ ERROR("Failed to allocate zlib workspace\n"); ++ kfree(stream); ++ return NULL; ++} ++ ++ ++void zlib_free(void *strm) ++{ ++ z_stream *stream = strm; ++ ++ if (stream) ++ kfree(stream->workspace); ++ kfree(stream); ++} ++ ++ + int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, + struct buffer_head **bh, int b, int offset, int length, int srclength, + int pages) + { + int zlib_err = 0, zlib_init = 0; + int avail, bytes, k = 0, page = 0; ++ z_stream *stream = msblk->stream; + + mutex_lock(&msblk->read_data_mutex); + +- msblk->stream.avail_out = 0; +- msblk->stream.avail_in = 0; ++ stream->avail_out = 0; ++ stream->avail_in = 0; + + bytes = length; + do { +- if (msblk->stream.avail_in == 0 && k < b) { ++ if (stream->avail_in == 0 && k < b) { + avail = min(bytes, msblk->devblksize - offset); + bytes -= avail; + wait_on_buffer(bh[k]); +@@ -58,18 +88,18 @@ int zlib_uncompress(struct squashfs_sb_i + continue; + } + +- msblk->stream.next_in = bh[k]->b_data + offset; +- msblk->stream.avail_in = avail; ++ stream->next_in = bh[k]->b_data + offset; ++ stream->avail_in = avail; + offset = 0; + } + +- if (msblk->stream.avail_out == 0 && page < pages) { +- msblk->stream.next_out = buffer[page++]; +- msblk->stream.avail_out = PAGE_CACHE_SIZE; ++ if (stream->avail_out == 0 && page < pages) { ++ stream->next_out = buffer[page++]; ++ stream->avail_out = PAGE_CACHE_SIZE; + } + + if (!zlib_init) { +- zlib_err = zlib_inflateInit(&msblk->stream); ++ zlib_err = zlib_inflateInit(stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected " + "result 0x%x, srclength %d\n", +@@ -79,9 +109,9 @@ int zlib_uncompress(struct squashfs_sb_i + zlib_init = 1; + } + +- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); ++ zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH); + +- if (msblk->stream.avail_in == 0 && k < b) ++ if (stream->avail_in == 0 && k < b) + put_bh(bh[k++]); + } while (zlib_err == Z_OK); + +@@ -90,14 +120,14 @@ int zlib_uncompress(struct squashfs_sb_i + goto release_mutex; + } + +- zlib_err = zlib_inflateEnd(&msblk->stream); ++ zlib_err = zlib_inflateEnd(stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflate error, data probably corrupt\n"); + goto release_mutex; + } + + mutex_unlock(&msblk->read_data_mutex); +- return msblk->stream.total_out; ++ return stream->total_out; + + release_mutex: + mutex_unlock(&msblk->read_data_mutex); diff --git a/target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch b/target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch new file mode 100644 index 000000000..db2fe538e --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch @@ -0,0 +1,426 @@ +From 327fbf47a419befc6bff74f3ca42d2b6f0841903 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Tue, 6 Oct 2009 04:04:15 +0100 +Subject: [PATCH] Squashfs: add a decompressor framework + +This adds a decompressor framework which allows multiple compression +algorithms to be cleanly supported. + +Also update zlib wrapper and other code to use the new framework. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Makefile | 2 +- + fs/squashfs/block.c | 6 ++-- + fs/squashfs/decompressor.c | 58 ++++++++++++++++++++++++++++++++++++++++++ + fs/squashfs/decompressor.h | 55 +++++++++++++++++++++++++++++++++++++++ + fs/squashfs/squashfs.h | 14 +++++----- + fs/squashfs/squashfs_fs_sb.h | 41 +++++++++++++++-------------- + fs/squashfs/super.c | 45 ++++++++++++++++++------------- + fs/squashfs/zlib_wrapper.c | 17 ++++++++++-- + 8 files changed, 185 insertions(+), 53 deletions(-) + create mode 100644 fs/squashfs/decompressor.c + create mode 100644 fs/squashfs/decompressor.h + +--- a/fs/squashfs/Makefile ++++ b/fs/squashfs/Makefile +@@ -4,4 +4,4 @@ + + obj-$(CONFIG_SQUASHFS) += squashfs.o + squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o +-squashfs-y += namei.o super.o symlink.o zlib_wrapper.o ++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o +--- a/fs/squashfs/block.c ++++ b/fs/squashfs/block.c +@@ -36,7 +36,7 @@ + #include "squashfs_fs_sb.h" + #include "squashfs_fs_i.h" + #include "squashfs.h" +- ++#include "decompressor.h" + /* + * Read the metadata block length, this is stored in the first two + * bytes of the metadata block. +@@ -151,8 +151,8 @@ int squashfs_read_data(struct super_bloc + } + + if (compressed) { +- length = zlib_uncompress(msblk, buffer, bh, b, offset, length, +- srclength, pages); ++ length = squashfs_decompress(msblk, buffer, bh, b, offset, ++ length, srclength, pages); + if (length < 0) + goto read_failure; + } else { +--- /dev/null ++++ b/fs/squashfs/decompressor.c +@@ -0,0 +1,58 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * decompressor.c ++ */ ++ ++#include <linux/types.h> ++#include <linux/mutex.h> ++#include <linux/buffer_head.h> ++ ++#include "squashfs_fs.h" ++#include "squashfs_fs_sb.h" ++#include "squashfs_fs_i.h" ++#include "decompressor.h" ++#include "squashfs.h" ++ ++/* ++ * This file (and decompressor.h) implements a decompressor framework for ++ * Squashfs, allowing multiple decompressors to be easily supported ++ */ ++ ++static const struct squashfs_decompressor squashfs_unknown_comp_ops = { ++ NULL, NULL, NULL, 0, "unknown", 0 ++}; ++ ++static const struct squashfs_decompressor *decompressor[] = { ++ &squashfs_zlib_comp_ops, ++ &squashfs_unknown_comp_ops ++}; ++ ++ ++const struct squashfs_decompressor *squashfs_lookup_decompressor(int id) ++{ ++ int i; ++ ++ for (i = 0; decompressor[i]->id; i++) ++ if (id == decompressor[i]->id) ++ break; ++ ++ return decompressor[i]; ++} +--- /dev/null ++++ b/fs/squashfs/decompressor.h +@@ -0,0 +1,55 @@ ++#ifndef DECOMPRESSOR_H ++#define DECOMPRESSOR_H ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * decompressor.h ++ */ ++ ++struct squashfs_decompressor { ++ void *(*init)(void); ++ void (*free)(void *); ++ int (*decompress)(struct squashfs_sb_info *, void **, ++ struct buffer_head **, int, int, int, int, int); ++ int id; ++ char *name; ++ int supported; ++}; ++ ++static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk) ++{ ++ return msblk->decompressor->init(); ++} ++ ++static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, ++ void *s) ++{ ++ if (msblk->decompressor) ++ msblk->decompressor->free(s); ++} ++ ++static inline int squashfs_decompress(struct squashfs_sb_info *msblk, ++ void **buffer, struct buffer_head **bh, int b, int offset, int length, ++ int srclength, int pages) ++{ ++ return msblk->decompressor->decompress(msblk, buffer, bh, b, offset, ++ length, srclength, pages); ++} ++#endif +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squa + u64, int); + extern int squashfs_read_table(struct super_block *, void *, u64, int); + ++/* decompressor.c */ ++extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); ++ + /* export.c */ + extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, + unsigned int); +@@ -70,14 +73,8 @@ extern struct inode *squashfs_iget(struc + unsigned int); + extern int squashfs_read_inode(struct inode *, long long); + +-/* zlib_wrapper.c */ +-extern void *zlib_init(void); +-extern void zlib_free(void *); +-extern int zlib_uncompress(struct squashfs_sb_info *, void **, +- struct buffer_head **, int, int, int, int, int); +- + /* +- * Inodes and files operations ++ * Inodes, files and decompressor operations + */ + + /* dir.c */ +@@ -94,3 +91,6 @@ extern const struct inode_operations squ + + /* symlink.c */ + extern const struct address_space_operations squashfs_symlink_aops; ++ ++/* zlib_wrapper.c */ ++extern const struct squashfs_decompressor squashfs_zlib_comp_ops; +--- a/fs/squashfs/squashfs_fs_sb.h ++++ b/fs/squashfs/squashfs_fs_sb.h +@@ -52,25 +52,26 @@ struct squashfs_cache_entry { + }; + + struct squashfs_sb_info { +- int devblksize; +- int devblksize_log2; +- struct squashfs_cache *block_cache; +- struct squashfs_cache *fragment_cache; +- struct squashfs_cache *read_page; +- int next_meta_index; +- __le64 *id_table; +- __le64 *fragment_index; +- unsigned int *fragment_index_2; +- struct mutex read_data_mutex; +- struct mutex meta_index_mutex; +- struct meta_index *meta_index; +- void *stream; +- __le64 *inode_lookup_table; +- u64 inode_table; +- u64 directory_table; +- unsigned int block_size; +- unsigned short block_log; +- long long bytes_used; +- unsigned int inodes; ++ const struct squashfs_decompressor *decompressor; ++ int devblksize; ++ int devblksize_log2; ++ struct squashfs_cache *block_cache; ++ struct squashfs_cache *fragment_cache; ++ struct squashfs_cache *read_page; ++ int next_meta_index; ++ __le64 *id_table; ++ __le64 *fragment_index; ++ unsigned int *fragment_index_2; ++ struct mutex read_data_mutex; ++ struct mutex meta_index_mutex; ++ struct meta_index *meta_index; ++ void *stream; ++ __le64 *inode_lookup_table; ++ u64 inode_table; ++ u64 directory_table; ++ unsigned int block_size; ++ unsigned short block_log; ++ long long bytes_used; ++ unsigned int inodes; + }; + #endif +--- a/fs/squashfs/super.c ++++ b/fs/squashfs/super.c +@@ -40,27 +40,35 @@ + #include "squashfs_fs_sb.h" + #include "squashfs_fs_i.h" + #include "squashfs.h" ++#include "decompressor.h" + + static struct file_system_type squashfs_fs_type; + static struct super_operations squashfs_super_ops; + +-static int supported_squashfs_filesystem(short major, short minor, short comp) ++static const struct squashfs_decompressor *supported_squashfs_filesystem(short ++ major, short minor, short id) + { ++ const struct squashfs_decompressor *decompressor; ++ + if (major < SQUASHFS_MAJOR) { + ERROR("Major/Minor mismatch, older Squashfs %d.%d " + "filesystems are unsupported\n", major, minor); +- return -EINVAL; ++ return NULL; + } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { + ERROR("Major/Minor mismatch, trying to mount newer " + "%d.%d filesystem\n", major, minor); + ERROR("Please update your kernel\n"); +- return -EINVAL; ++ return NULL; + } + +- if (comp != ZLIB_COMPRESSION) +- return -EINVAL; ++ decompressor = squashfs_lookup_decompressor(id); ++ if (!decompressor->supported) { ++ ERROR("Filesystem uses \"%s\" compression. This is not " ++ "supported\n", decompressor->name); ++ return NULL; ++ } + +- return 0; ++ return decompressor; + } + + +@@ -85,10 +93,6 @@ static int squashfs_fill_super(struct su + } + msblk = sb->s_fs_info; + +- msblk->stream = zlib_init(); +- if (msblk->stream == NULL) +- goto failure; +- + sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); + if (sblk == NULL) { + ERROR("Failed to allocate squashfs_super_block\n"); +@@ -115,25 +119,25 @@ static int squashfs_fill_super(struct su + goto failed_mount; + } + ++ err = -EINVAL; ++ + /* Check it is a SQUASHFS superblock */ + sb->s_magic = le32_to_cpu(sblk->s_magic); + if (sb->s_magic != SQUASHFS_MAGIC) { + if (!silent) + ERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(sb->s_bdev, b)); +- err = -EINVAL; + goto failed_mount; + } + +- /* Check the MAJOR & MINOR versions and compression type */ +- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major), ++ /* Check the MAJOR & MINOR versions and lookup compression type */ ++ msblk->decompressor = supported_squashfs_filesystem( ++ le16_to_cpu(sblk->s_major), + le16_to_cpu(sblk->s_minor), + le16_to_cpu(sblk->compression)); +- if (err < 0) ++ if (msblk->decompressor == NULL) + goto failed_mount; + +- err = -EINVAL; +- + /* + * Check if there's xattrs in the filesystem. These are not + * supported in this version, so warn that they will be ignored. +@@ -200,6 +204,10 @@ static int squashfs_fill_super(struct su + + err = -ENOMEM; + ++ msblk->stream = squashfs_decompressor_init(msblk); ++ if (msblk->stream == NULL) ++ goto failed_mount; ++ + msblk->block_cache = squashfs_cache_init("metadata", + SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); + if (msblk->block_cache == NULL) +@@ -287,7 +295,7 @@ failed_mount: + squashfs_cache_delete(msblk->block_cache); + squashfs_cache_delete(msblk->fragment_cache); + squashfs_cache_delete(msblk->read_page); +- zlib_free(msblk->stream); ++ squashfs_decompressor_free(msblk, msblk->stream); + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->id_table); +@@ -297,7 +305,6 @@ failed_mount: + return err; + + failure: +- zlib_free(msblk->stream); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + return -ENOMEM; +@@ -339,7 +346,7 @@ static void squashfs_put_super(struct su + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + squashfs_cache_delete(sbi->read_page); +- zlib_free(sbi->stream); ++ squashfs_decompressor_free(sbi, sbi->stream); + kfree(sbi->id_table); + kfree(sbi->fragment_index); + kfree(sbi->meta_index); +--- a/fs/squashfs/zlib_wrapper.c ++++ b/fs/squashfs/zlib_wrapper.c +@@ -30,8 +30,9 @@ + #include "squashfs_fs_sb.h" + #include "squashfs_fs_i.h" + #include "squashfs.h" ++#include "decompressor.h" + +-void *zlib_init() ++static void *zlib_init(void) + { + z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); + if (stream == NULL) +@@ -50,7 +51,7 @@ failed: + } + + +-void zlib_free(void *strm) ++static void zlib_free(void *strm) + { + z_stream *stream = strm; + +@@ -60,7 +61,7 @@ void zlib_free(void *strm) + } + + +-int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, ++static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, + struct buffer_head **bh, int b, int offset, int length, int srclength, + int pages) + { +@@ -137,3 +138,13 @@ release_mutex: + + return -EIO; + } ++ ++const struct squashfs_decompressor squashfs_zlib_comp_ops = { ++ .init = zlib_init, ++ .free = zlib_free, ++ .decompress = zlib_uncompress, ++ .id = ZLIB_COMPRESSION, ++ .name = "zlib", ++ .supported = 1 ++}; ++ diff --git a/target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch b/target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch new file mode 100644 index 000000000..a378c0005 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch @@ -0,0 +1,54 @@ +From 1885ca0a1973944684f252094a703b7c80dfc974 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Wed, 14 Oct 2009 03:58:11 +0100 +Subject: [PATCH] Squashfs: add decompressor entries for lzma and lzo + +Add knowledge of lzma/lzo compression formats to the decompressor +framework. For now these are added as unsupported. Without +these entries lzma/lzo compressed filesystems will be flagged as +having unknown compression which is undesirable. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/decompressor.c | 10 ++++++++++ + fs/squashfs/squashfs_fs.h | 4 +++- + 2 files changed, 13 insertions(+), 1 deletions(-) + +--- a/fs/squashfs/decompressor.c ++++ b/fs/squashfs/decompressor.c +@@ -36,12 +36,22 @@ + * Squashfs, allowing multiple decompressors to be easily supported + */ + ++static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = { ++ NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 ++}; ++ ++static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = { ++ NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 ++}; ++ + static const struct squashfs_decompressor squashfs_unknown_comp_ops = { + NULL, NULL, NULL, 0, "unknown", 0 + }; + + static const struct squashfs_decompressor *decompressor[] = { + &squashfs_zlib_comp_ops, ++ &squashfs_lzma_unsupported_comp_ops, ++ &squashfs_lzo_unsupported_comp_ops, + &squashfs_unknown_comp_ops + }; + +--- a/fs/squashfs/squashfs_fs.h ++++ b/fs/squashfs/squashfs_fs.h +@@ -211,7 +211,9 @@ struct meta_index { + /* + * definitions for structures on disk + */ +-#define ZLIB_COMPRESSION 1 ++#define ZLIB_COMPRESSION 1 ++#define LZMA_COMPRESSION 2 ++#define LZO_COMPRESSION 3 + + struct squashfs_super_block { + __le32 s_magic; diff --git a/target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch b/target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch new file mode 100644 index 000000000..099168134 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch @@ -0,0 +1,42 @@ +From 5f393ede3ddb5dd4cc2a9f243182fac45f1ce10b Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Wed, 14 Oct 2009 04:07:54 +0100 +Subject: [PATCH] Squashfs: add an extra parameter to the decompressor init function + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/decompressor.h | 4 ++-- + fs/squashfs/zlib_wrapper.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/squashfs/decompressor.h ++++ b/fs/squashfs/decompressor.h +@@ -24,7 +24,7 @@ + */ + + struct squashfs_decompressor { +- void *(*init)(void); ++ void *(*init)(struct squashfs_sb_info *); + void (*free)(void *); + int (*decompress)(struct squashfs_sb_info *, void **, + struct buffer_head **, int, int, int, int, int); +@@ -35,7 +35,7 @@ struct squashfs_decompressor { + + static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk) + { +- return msblk->decompressor->init(); ++ return msblk->decompressor->init(msblk); + } + + static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, +--- a/fs/squashfs/zlib_wrapper.c ++++ b/fs/squashfs/zlib_wrapper.c +@@ -32,7 +32,7 @@ + #include "squashfs.h" + #include "decompressor.h" + +-static void *zlib_init(void) ++static void *zlib_init(struct squashfs_sb_info *dummy) + { + z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); + if (stream == NULL) diff --git a/target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch b/target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch new file mode 100644 index 000000000..9fd57970f --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch @@ -0,0 +1,216 @@ +From f49e1efdd179d54e814ff2a8e8f469496583062c Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Tue, 20 Oct 2009 10:54:36 +0100 +Subject: [PATCH] Squashfs: add LZMA compression + +Add support for LZMA compressed filesystems. This is an initial +implementation. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Kconfig | 5 ++ + fs/squashfs/Makefile | 1 + + fs/squashfs/decompressor.c | 4 + + fs/squashfs/lzma_wrapper.c | 151 ++++++++++++++++++++++++++++++++++++++++++++ + fs/squashfs/squashfs.h | 3 + + 5 files changed, 164 insertions(+), 0 deletions(-) + create mode 100644 fs/squashfs/lzma_wrapper.c + +--- a/fs/squashfs/Kconfig ++++ b/fs/squashfs/Kconfig +@@ -26,6 +26,11 @@ config SQUASHFS + + If unsure, say N. + ++config SQUASHFS_LZMA ++ bool "Include support for LZMA compressed file systems" ++ depends on SQUASHFS ++ select DECOMPRESS_LZMA ++ + config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" +--- a/fs/squashfs/Makefile ++++ b/fs/squashfs/Makefile +@@ -5,3 +5,4 @@ + obj-$(CONFIG_SQUASHFS) += squashfs.o + squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o + squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o ++squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o +--- a/fs/squashfs/decompressor.c ++++ b/fs/squashfs/decompressor.c +@@ -50,7 +50,11 @@ static const struct squashfs_decompresso + + static const struct squashfs_decompressor *decompressor[] = { + &squashfs_zlib_comp_ops, ++#ifdef CONFIG_SQUASHFS_LZMA ++ &squashfs_lzma_comp_ops, ++#else + &squashfs_lzma_unsupported_comp_ops, ++#endif + &squashfs_lzo_unsupported_comp_ops, + &squashfs_unknown_comp_ops + }; +--- /dev/null ++++ b/fs/squashfs/lzma_wrapper.c +@@ -0,0 +1,151 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * lzma_wrapper.c ++ */ ++ ++#include <asm/unaligned.h> ++#include <linux/buffer_head.h> ++#include <linux/mutex.h> ++#include <linux/vmalloc.h> ++#include <linux/decompress/unlzma.h> ++ ++#include "squashfs_fs.h" ++#include "squashfs_fs_sb.h" ++#include "squashfs_fs_i.h" ++#include "squashfs.h" ++#include "decompressor.h" ++ ++struct squashfs_lzma { ++ void *input; ++ void *output; ++}; ++ ++/* decompress_unlzma.c is currently non re-entrant... */ ++DEFINE_MUTEX(lzma_mutex); ++ ++/* decompress_unlzma.c doesn't provide any context in its callbacks... */ ++static int lzma_error; ++ ++static void error(char *m) ++{ ++ ERROR("unlzma error: %s\n", m); ++ lzma_error = 1; ++} ++ ++ ++static void *lzma_init(struct squashfs_sb_info *msblk) ++{ ++ struct squashfs_lzma *stream = kzalloc(sizeof(*stream), GFP_KERNEL); ++ if (stream == NULL) ++ goto failed; ++ stream->input = vmalloc(msblk->block_size); ++ if (stream->input == NULL) ++ goto failed; ++ stream->output = vmalloc(msblk->block_size); ++ if (stream->output == NULL) ++ goto failed2; ++ ++ return stream; ++ ++failed2: ++ vfree(stream->input); ++failed: ++ ERROR("failed to allocate lzma workspace\n"); ++ kfree(stream); ++ return NULL; ++} ++ ++ ++static void lzma_free(void *strm) ++{ ++ struct squashfs_lzma *stream = strm; ++ ++ if (stream) { ++ vfree(stream->input); ++ vfree(stream->output); ++ } ++ kfree(stream); ++} ++ ++ ++static int lzma_uncompress(struct squashfs_sb_info *msblk, void **buffer, ++ struct buffer_head **bh, int b, int offset, int length, int srclength, ++ int pages) ++{ ++ struct squashfs_lzma *stream = msblk->stream; ++ void *buff = stream->input; ++ int avail, i, bytes = length, res; ++ ++ mutex_lock(&lzma_mutex); ++ ++ for (i = 0; i < b; i++) { ++ wait_on_buffer(bh[i]); ++ if (!buffer_uptodate(bh[i])) ++ goto block_release; ++ ++ avail = min(bytes, msblk->devblksize - offset); ++ memcpy(buff, bh[i]->b_data + offset, avail); ++ buff += avail; ++ bytes -= avail; ++ offset = 0; ++ put_bh(bh[i]); ++ } ++ ++ lzma_error = 0; ++ res = unlzma(stream->input, length, NULL, NULL, stream->output, NULL, ++ error); ++ if (res || lzma_error) ++ goto failed; ++ ++ /* uncompressed size is stored in the LZMA header (5 byte offset) */ ++ res = bytes = get_unaligned_le32(stream->input + 5); ++ for (i = 0, buff = stream->output; bytes && i < pages; i++) { ++ avail = min_t(int, bytes, PAGE_CACHE_SIZE); ++ memcpy(buffer[i], buff, avail); ++ buff += avail; ++ bytes -= avail; ++ } ++ if (bytes) ++ goto failed; ++ ++ mutex_unlock(&lzma_mutex); ++ return res; ++ ++block_release: ++ for (; i < b; i++) ++ put_bh(bh[i]); ++ ++failed: ++ mutex_unlock(&lzma_mutex); ++ ++ ERROR("lzma decompression failed, data probably corrupt\n"); ++ return -EIO; ++} ++ ++const struct squashfs_decompressor squashfs_lzma_comp_ops = { ++ .init = lzma_init, ++ .free = lzma_free, ++ .decompress = lzma_uncompress, ++ .id = LZMA_COMPRESSION, ++ .name = "lzma", ++ .supported = 1 ++}; ++ +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -94,3 +94,6 @@ extern const struct address_space_operat + + /* zlib_wrapper.c */ + extern const struct squashfs_decompressor squashfs_zlib_comp_ops; ++ ++/* lzma wrapper.c */ ++extern const struct squashfs_decompressor squashfs_lzma_comp_ops; diff --git a/target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch b/target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch new file mode 100644 index 000000000..64705d2a9 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch @@ -0,0 +1,165 @@ +From fdf23ed283bc6ef5c25076ce2065f892120ff556 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Thu, 22 Oct 2009 04:57:38 +0100 +Subject: [PATCH] Squashfs: Make unlzma available to non initramfs/initrd code + +Add a config option DECOMPRESS_LZMA_NEEDED which allows subsystems to +specify they need the unlzma code. Normally decompress_unlzma.c is +compiled with __init and unlzma is not exported to modules. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Kconfig | 1 + + include/linux/decompress/bunzip2_mm.h | 12 ++++++++++++ + include/linux/decompress/inflate_mm.h | 12 ++++++++++++ + include/linux/decompress/mm.h | 3 --- + include/linux/decompress/unlzma_mm.h | 20 ++++++++++++++++++++ + lib/Kconfig | 3 +++ + lib/decompress_bunzip2.c | 1 + + lib/decompress_inflate.c | 1 + + lib/decompress_unlzma.c | 5 ++++- + 9 files changed, 54 insertions(+), 4 deletions(-) + create mode 100644 include/linux/decompress/bunzip2_mm.h + create mode 100644 include/linux/decompress/inflate_mm.h + create mode 100644 include/linux/decompress/unlzma_mm.h + +--- a/fs/squashfs/Kconfig ++++ b/fs/squashfs/Kconfig +@@ -30,6 +30,7 @@ config SQUASHFS_LZMA + bool "Include support for LZMA compressed file systems" + depends on SQUASHFS + select DECOMPRESS_LZMA ++ select DECOMPRESS_LZMA_NEEDED + + config SQUASHFS_EMBEDDED + +--- /dev/null ++++ b/include/linux/decompress/bunzip2_mm.h +@@ -0,0 +1,12 @@ ++#ifndef BUNZIP2_MM_H ++#define BUNZIP2_MM_H ++ ++#ifdef STATIC ++/* Code active when included from pre-boot environment: */ ++#define INIT ++#else ++/* Compile for initramfs/initrd code only */ ++#define INIT __init ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/decompress/inflate_mm.h +@@ -0,0 +1,12 @@ ++#ifndef INFLATE_MM_H ++#define INFLATE_MM_H ++ ++#ifdef STATIC ++/* Code active when included from pre-boot environment: */ ++#define INIT ++#else ++/* Compile for initramfs/initrd code only */ ++#define INIT __init ++#endif ++ ++#endif +--- a/include/linux/decompress/mm.h ++++ b/include/linux/decompress/mm.h +@@ -53,8 +53,6 @@ static void free(void *where) + + #define set_error_fn(x) + +-#define INIT +- + #else /* STATIC */ + + /* Code active when compiled standalone for use when loading ramdisk: */ +@@ -77,7 +75,6 @@ static void free(void *where) + static void(*error)(char *m); + #define set_error_fn(x) error = x; + +-#define INIT __init + #define STATIC + + #include <linux/init.h> +--- /dev/null ++++ b/include/linux/decompress/unlzma_mm.h +@@ -0,0 +1,20 @@ ++#ifndef UNLZMA_MM_H ++#define UNLZMA_MM_H ++ ++#ifdef STATIC ++ ++/* Code active when included from pre-boot environment: */ ++#define INIT ++ ++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED) ++ ++/* Make it available to non initramfs/initrd code */ ++#define INIT ++#include <linux/module.h> ++#else ++ ++/* Compile for initramfs/initrd code only */ ++#define INIT __init ++#endif ++ ++#endif +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -114,6 +114,9 @@ config DECOMPRESS_BZIP2 + config DECOMPRESS_LZMA + tristate + ++config DECOMPRESS_LZMA_NEEDED ++ boolean ++ + # + # Generic allocator support is selected if needed + # +--- a/lib/decompress_bunzip2.c ++++ b/lib/decompress_bunzip2.c +@@ -51,6 +51,7 @@ + #include <linux/decompress/bunzip2.h> + #endif /* STATIC */ + ++#include <linux/decompress/bunzip2_mm.h> + #include <linux/decompress/mm.h> + #include <linux/slab.h> + +--- a/lib/decompress_inflate.c ++++ b/lib/decompress_inflate.c +@@ -22,6 +22,7 @@ + + #endif /* STATIC */ + ++#include <linux/decompress/inflate_mm.h> + #include <linux/decompress/mm.h> + #include <linux/slab.h> + +--- a/lib/decompress_unlzma.c ++++ b/lib/decompress_unlzma.c +@@ -35,6 +35,7 @@ + #include <linux/decompress/unlzma.h> + #endif /* STATIC */ + ++#include <linux/decompress/unlzma_mm.h> + #include <linux/decompress/mm.h> + #include <linux/slab.h> + +@@ -523,7 +524,7 @@ static inline void INIT process_bit1(str + + + +-STATIC inline int INIT unlzma(unsigned char *buf, int in_len, ++STATIC int INIT unlzma(unsigned char *buf, int in_len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, +@@ -656,4 +657,6 @@ STATIC int INIT decompress(unsigned char + { + return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn); + } ++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED) ++EXPORT_SYMBOL(unlzma); + #endif diff --git a/target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch b/target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch deleted file mode 100644 index abad724f5..000000000 --- a/target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch +++ /dev/null @@ -1,280 +0,0 @@ ---- a/crypto/testmgr.c -+++ b/crypto/testmgr.c -@@ -914,24 +914,25 @@ static int test_pcomp(struct crypto_pcom - const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm)); - unsigned int i; - char result[COMP_BUF_SIZE]; -- int error; -+ int res; - - for (i = 0; i < ctcount; i++) { - struct comp_request req; -+ unsigned int produced = 0; - -- error = crypto_compress_setup(tfm, ctemplate[i].params, -- ctemplate[i].paramsize); -- if (error) { -+ res = crypto_compress_setup(tfm, ctemplate[i].params, -+ ctemplate[i].paramsize); -+ if (res) { - pr_err("alg: pcomp: compression setup failed on test " -- "%d for %s: error=%d\n", i + 1, algo, error); -- return error; -+ "%d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } - -- error = crypto_compress_init(tfm); -- if (error) { -+ res = crypto_compress_init(tfm); -+ if (res) { - pr_err("alg: pcomp: compression init failed on test " -- "%d for %s: error=%d\n", i + 1, algo, error); -- return error; -+ "%d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } - - memset(result, 0, sizeof(result)); -@@ -941,32 +942,37 @@ static int test_pcomp(struct crypto_pcom - req.next_out = result; - req.avail_out = ctemplate[i].outlen / 2; - -- error = crypto_compress_update(tfm, &req); -- if (error && (error != -EAGAIN || req.avail_in)) { -+ res = crypto_compress_update(tfm, &req); -+ if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: compression update failed on test " -- "%d for %s: error=%d\n", i + 1, algo, error); -- return error; -+ "%d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } -+ if (res > 0) -+ produced += res; - - /* Add remaining input data */ - req.avail_in += (ctemplate[i].inlen + 1) / 2; - -- error = crypto_compress_update(tfm, &req); -- if (error && (error != -EAGAIN || req.avail_in)) { -+ res = crypto_compress_update(tfm, &req); -+ if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: compression update failed on test " -- "%d for %s: error=%d\n", i + 1, algo, error); -- return error; -+ "%d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } -+ if (res > 0) -+ produced += res; - - /* Provide remaining output space */ - req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2; - -- error = crypto_compress_final(tfm, &req); -- if (error) { -+ res = crypto_compress_final(tfm, &req); -+ if (res < 0) { - pr_err("alg: pcomp: compression final failed on test " -- "%d for %s: error=%d\n", i + 1, algo, error); -- return error; -+ "%d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } -+ produced += res; - - if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) { - pr_err("alg: comp: Compression test %d failed for %s: " -@@ -976,6 +982,13 @@ static int test_pcomp(struct crypto_pcom - return -EINVAL; - } - -+ if (produced != ctemplate[i].outlen) { -+ pr_err("alg: comp: Compression test %d failed for %s: " -+ "returned len = %u (expected %d)\n", i + 1, -+ algo, produced, ctemplate[i].outlen); -+ return -EINVAL; -+ } -+ - if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) { - pr_err("alg: pcomp: Compression test %d failed for " - "%s\n", i + 1, algo); -@@ -986,21 +999,21 @@ static int test_pcomp(struct crypto_pcom - - for (i = 0; i < dtcount; i++) { - struct comp_request req; -+ unsigned int produced = 0; - -- error = crypto_decompress_setup(tfm, dtemplate[i].params, -- dtemplate[i].paramsize); -- if (error) { -+ res = crypto_decompress_setup(tfm, dtemplate[i].params, -+ dtemplate[i].paramsize); -+ if (res) { - pr_err("alg: pcomp: decompression setup failed on " -- "test %d for %s: error=%d\n", i + 1, algo, -- error); -- return error; -+ "test %d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } - -- error = crypto_decompress_init(tfm); -- if (error) { -+ res = crypto_decompress_init(tfm); -+ if (res) { - pr_err("alg: pcomp: decompression init failed on test " -- "%d for %s: error=%d\n", i + 1, algo, error); -- return error; -+ "%d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } - - memset(result, 0, sizeof(result)); -@@ -1010,35 +1023,38 @@ static int test_pcomp(struct crypto_pcom - req.next_out = result; - req.avail_out = dtemplate[i].outlen / 2; - -- error = crypto_decompress_update(tfm, &req); -- if (error && (error != -EAGAIN || req.avail_in)) { -+ res = crypto_decompress_update(tfm, &req); -+ if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: decompression update failed on " -- "test %d for %s: error=%d\n", i + 1, algo, -- error); -- return error; -+ "test %d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } -+ if (res > 0) -+ produced += res; - - /* Add remaining input data */ - req.avail_in += (dtemplate[i].inlen + 1) / 2; - -- error = crypto_decompress_update(tfm, &req); -- if (error && (error != -EAGAIN || req.avail_in)) { -+ res = crypto_decompress_update(tfm, &req); -+ if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: decompression update failed on " -- "test %d for %s: error=%d\n", i + 1, algo, -- error); -- return error; -+ "test %d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } -+ if (res > 0) -+ produced += res; - - /* Provide remaining output space */ - req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2; - -- error = crypto_decompress_final(tfm, &req); -- if (error && (error != -EAGAIN || req.avail_in)) { -+ res = crypto_decompress_final(tfm, &req); -+ if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: decompression final failed on " -- "test %d for %s: error=%d\n", i + 1, algo, -- error); -- return error; -+ "test %d for %s: error=%d\n", i + 1, algo, res); -+ return res; - } -+ if (res > 0) -+ produced += res; - - if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) { - pr_err("alg: comp: Decompression test %d failed for " -@@ -1048,6 +1064,13 @@ static int test_pcomp(struct crypto_pcom - return -EINVAL; - } - -+ if (produced != dtemplate[i].outlen) { -+ pr_err("alg: comp: Decompression test %d failed for " -+ "%s: returned len = %u (expected %d)\n", i + 1, -+ algo, produced, dtemplate[i].outlen); -+ return -EINVAL; -+ } -+ - if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) { - pr_err("alg: pcomp: Decompression test %d failed for " - "%s\n", i + 1, algo); ---- a/crypto/zlib.c -+++ b/crypto/zlib.c -@@ -165,15 +165,15 @@ static int zlib_compress_update(struct c - return -EINVAL; - } - -+ ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", - stream->avail_in, stream->avail_out, -- req->avail_in - stream->avail_in, -- req->avail_out - stream->avail_out); -+ req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; -- return 0; -+ return ret; - } - - static int zlib_compress_final(struct crypto_pcomp *tfm, -@@ -195,15 +195,15 @@ static int zlib_compress_final(struct cr - return -EINVAL; - } - -+ ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", - stream->avail_in, stream->avail_out, -- req->avail_in - stream->avail_in, -- req->avail_out - stream->avail_out); -+ req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; -- return 0; -+ return ret; - } - - -@@ -280,15 +280,15 @@ static int zlib_decompress_update(struct - return -EINVAL; - } - -+ ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", - stream->avail_in, stream->avail_out, -- req->avail_in - stream->avail_in, -- req->avail_out - stream->avail_out); -+ req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; -- return 0; -+ return ret; - } - - static int zlib_decompress_final(struct crypto_pcomp *tfm, -@@ -328,15 +328,15 @@ static int zlib_decompress_final(struct - return -EINVAL; - } - -+ ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n", - stream->avail_in, stream->avail_out, -- req->avail_in - stream->avail_in, -- req->avail_out - stream->avail_out); -+ req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; -- return 0; -+ return ret; - } - - diff --git a/target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch b/target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch deleted file mode 100644 index fc2a731dd..000000000 --- a/target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch +++ /dev/null @@ -1,234 +0,0 @@ ---- a/fs/squashfs/Kconfig -+++ b/fs/squashfs/Kconfig -@@ -1,7 +1,8 @@ - config SQUASHFS - tristate "SquashFS 4.0 - Squashed file system support" - depends on BLOCK -- select ZLIB_INFLATE -+ select CRYPTO -+ select CRYPTO_ZLIB - help - Saying Y here includes support for SquashFS 4.0 (a Compressed - Read-Only File System). Squashfs is a highly compressed read-only ---- 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,8 @@ int squashfs_read_data(struct super_bloc - } - - if (compressed) { -- int zlib_err = 0, zlib_init = 0; -+ int res = 0, decomp_init = 0; -+ struct comp_request req; - - /* - * Uncompress block. -@@ -161,12 +163,13 @@ int squashfs_read_data(struct super_bloc - - mutex_lock(&msblk->read_data_mutex); - -- msblk->stream.avail_out = 0; -- msblk->stream.avail_in = 0; -+ req.avail_out = 0; -+ req.avail_in = 0; - - bytes = length; -+ length = 0; - do { -- if (msblk->stream.avail_in == 0 && k < b) { -+ if (req.avail_in == 0 && k < b) { - avail = min(bytes, msblk->devblksize - offset); - bytes -= avail; - wait_on_buffer(bh[k]); -@@ -179,45 +182,47 @@ int squashfs_read_data(struct super_bloc - continue; - } - -- msblk->stream.next_in = bh[k]->b_data + offset; -- msblk->stream.avail_in = avail; -+ req.next_in = bh[k]->b_data + offset; -+ req.avail_in = avail; - offset = 0; - } - -- if (msblk->stream.avail_out == 0 && page < pages) { -- msblk->stream.next_out = buffer[page++]; -- msblk->stream.avail_out = PAGE_CACHE_SIZE; -+ if (req.avail_out == 0 && page < pages) { -+ req.next_out = buffer[page++]; -+ req.avail_out = PAGE_CACHE_SIZE; - } - -- if (!zlib_init) { -- zlib_err = zlib_inflateInit(&msblk->stream); -- if (zlib_err != Z_OK) { -- ERROR("zlib_inflateInit returned" -- " unexpected result 0x%x," -- " srclength %d\n", zlib_err, -- srclength); -+ if (!decomp_init) { -+ res = crypto_decompress_init(msblk->tfm); -+ if (res) { -+ ERROR("crypto_decompress_init " -+ "returned %d, srclength %d\n", -+ res, srclength); - goto release_mutex; - } -- zlib_init = 1; -+ decomp_init = 1; - } - -- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); -+ res = crypto_decompress_update(msblk->tfm, &req); -+ if (res < 0) { -+ ERROR("crypto_decompress_update returned %d, " -+ "data probably corrupt\n", res); -+ goto release_mutex; -+ } -+ length += res; - -- if (msblk->stream.avail_in == 0 && k < b) -+ if (req.avail_in == 0 && k < b) - put_bh(bh[k++]); -- } while (zlib_err == Z_OK); -+ } while (bytes || res); - -- if (zlib_err != Z_STREAM_END) { -- ERROR("zlib_inflate error, data probably corrupt\n"); -+ res = crypto_decompress_final(msblk->tfm, &req); -+ if (res < 0) { -+ ERROR("crypto_decompress_final returned %d, data " -+ "probably corrupt\n", res); - goto release_mutex; - } -+ length += res; - -- zlib_err = zlib_inflateEnd(&msblk->stream); -- if (zlib_err != Z_OK) { -- ERROR("zlib_inflate error, data probably corrupt\n"); -- goto release_mutex; -- } -- length = msblk->stream.total_out; - mutex_unlock(&msblk->read_data_mutex); - } else { - /* ---- 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; ---- a/fs/squashfs/super.c -+++ b/fs/squashfs/super.c -@@ -37,11 +37,19 @@ - #include <linux/zlib.h> - #include <linux/magic.h> - -+#include <crypto/compress.h> -+ -+#include <net/netlink.h> -+ - #include "squashfs_fs.h" - #include "squashfs_fs_sb.h" - #include "squashfs_fs_i.h" - #include "squashfs.h" - -+ -+#define SQUASHFS_CRYPTO_ALG "zlib" -+ -+ - static struct file_system_type squashfs_fs_type; - static struct super_operations squashfs_super_ops; - -@@ -75,6 +83,16 @@ static int squashfs_fill_super(struct su - unsigned short flags; - unsigned int fragments; - u64 lookup_table_start; -+ struct { -+ struct nlattr nla; -+ int val; -+ } params = { -+ .nla = { -+ .nla_len = nla_attr_size(sizeof(int)), -+ .nla_type = ZLIB_DECOMP_WINDOWBITS, -+ }, -+ .val = DEF_WBITS, -+ }; - int err; - - TRACE("Entered squashfs_fill_superblock\n"); -@@ -86,16 +104,25 @@ static int squashfs_fill_super(struct su - } - msblk = sb->s_fs_info; - -- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(), -- GFP_KERNEL); -- if (msblk->stream.workspace == NULL) { -- ERROR("Failed to allocate zlib workspace\n"); -+ msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0, -+ CRYPTO_ALG_ASYNC); -+ if (IS_ERR(msblk->tfm)) { -+ ERROR("Failed to load %s crypto module\n", -+ SQUASHFS_CRYPTO_ALG); -+ err = PTR_ERR(msblk->tfm); -+ goto failed_pcomp; -+ } -+ -+ err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -+ if (err) { -+ ERROR("Failed to set up decompression parameters\n"); - goto failure; - } - - sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); - if (sblk == NULL) { - ERROR("Failed to allocate squashfs_super_block\n"); -+ err = -ENOMEM; - goto failure; - } - -@@ -294,17 +321,18 @@ failed_mount: - kfree(msblk->inode_lookup_table); - kfree(msblk->fragment_index); - kfree(msblk->id_table); -- kfree(msblk->stream.workspace); -+ crypto_free_pcomp(msblk->tfm); - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - kfree(sblk); - return err; - - failure: -- kfree(msblk->stream.workspace); -+ crypto_free_pcomp(msblk->tfm); -+failed_pcomp: - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; -- return -ENOMEM; -+ return err; - } - - -@@ -346,7 +374,7 @@ static void squashfs_put_super(struct su - 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; - } diff --git a/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch b/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch deleted file mode 100644 index d20285c5c..000000000 --- a/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch +++ /dev/null @@ -1,901 +0,0 @@ ---- /dev/null -+++ b/crypto/unlzma.c -@@ -0,0 +1,775 @@ -+/* -+ * LZMA uncompresion module for pcomp -+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> -+ * -+ * Based on: -+ * Initial Linux kernel adaptation -+ * Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ * Based on small lzma deflate implementation/Small range coder -+ * implementation for lzma. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * FIXME: the current implementation assumes that the caller will -+ * not free any output buffers until the whole decompression has been -+ * completed. This is necessary, because LZMA looks back at old output -+ * instead of doing a separate dictionary allocation, which saves RAM. -+ */ -+ -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/vmalloc.h> -+#include <linux/interrupt.h> -+#include <linux/mm.h> -+#include <linux/net.h> -+#include <linux/slab.h> -+#include <linux/kthread.h> -+ -+#include <crypto/internal/compress.h> -+#include <net/netlink.h> -+#include "unlzma.h" -+ -+static int instance = 0; -+ -+struct unlzma_buffer { -+ int offset; -+ int size; -+ u8 *ptr; -+}; -+ -+struct unlzma_ctx { -+ struct task_struct *thread; -+ wait_queue_head_t next_req; -+ wait_queue_head_t req_done; -+ struct mutex mutex; -+ bool waiting; -+ bool active; -+ bool cancel; -+ -+ const u8 *next_in; -+ int avail_in; -+ -+ u8 *next_out; -+ int avail_out; -+ -+ /* reader state */ -+ u32 code; -+ u32 range; -+ u32 bound; -+ -+ /* writer state */ -+ u8 previous_byte; -+ ssize_t pos; -+ int buf_full; -+ int n_buffers; -+ int buffers_max; -+ struct unlzma_buffer *buffers; -+ -+ /* cstate */ -+ int state; -+ u32 rep0, rep1, rep2, rep3; -+ -+ u32 dict_size; -+ -+ void *workspace; -+ int workspace_size; -+}; -+ -+static inline bool -+unlzma_should_stop(struct unlzma_ctx *ctx) -+{ -+ return unlikely(kthread_should_stop() || ctx->cancel); -+} -+ -+static void -+get_buffer(struct unlzma_ctx *ctx) -+{ -+ struct unlzma_buffer *bh; -+ -+ BUG_ON(ctx->n_buffers >= ctx->buffers_max); -+ bh = &ctx->buffers[ctx->n_buffers++]; -+ bh->ptr = ctx->next_out; -+ bh->offset = ctx->pos; -+ bh->size = ctx->avail_out; -+ ctx->buf_full = 0; -+} -+ -+static void -+unlzma_request_buffer(struct unlzma_ctx *ctx, int *avail) -+{ -+ do { -+ ctx->waiting = true; -+ mutex_unlock(&ctx->mutex); -+ wake_up(&ctx->req_done); -+ if (wait_event_interruptible(ctx->next_req, -+ unlzma_should_stop(ctx) || (*avail > 0))) -+ schedule(); -+ mutex_lock(&ctx->mutex); -+ } while (*avail <= 0 && !unlzma_should_stop(ctx)); -+ -+ if (!unlzma_should_stop(ctx) && ctx->buf_full) -+ get_buffer(ctx); -+} -+ -+static u8 -+rc_read(struct unlzma_ctx *ctx) -+{ -+ if (unlikely(ctx->avail_in <= 0)) -+ unlzma_request_buffer(ctx, &ctx->avail_in); -+ -+ if (unlzma_should_stop(ctx)) -+ return 0; -+ -+ ctx->avail_in--; -+ return *(ctx->next_in++); -+} -+ -+ -+static inline void -+rc_get_code(struct unlzma_ctx *ctx) -+{ -+ ctx->code = (ctx->code << 8) | rc_read(ctx); -+} -+ -+static void -+rc_normalize(struct unlzma_ctx *ctx) -+{ -+ if (ctx->range < (1 << RC_TOP_BITS)) { -+ ctx->range <<= 8; -+ rc_get_code(ctx); -+ } -+} -+ -+static int -+rc_is_bit_0(struct unlzma_ctx *ctx, u16 *p) -+{ -+ rc_normalize(ctx); -+ ctx->bound = *p * (ctx->range >> RC_MODEL_TOTAL_BITS); -+ return ctx->code < ctx->bound; -+} -+ -+static void -+rc_update_bit_0(struct unlzma_ctx *ctx, u16 *p) -+{ -+ ctx->range = ctx->bound; -+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; -+} -+ -+static void -+rc_update_bit_1(struct unlzma_ctx *ctx, u16 *p) -+{ -+ ctx->range -= ctx->bound; -+ ctx->code -= ctx->bound; -+ *p -= *p >> RC_MOVE_BITS; -+} -+ -+static bool -+rc_get_bit(struct unlzma_ctx *ctx, u16 *p, int *symbol) -+{ -+ if (rc_is_bit_0(ctx, p)) { -+ rc_update_bit_0(ctx, p); -+ *symbol *= 2; -+ return 0; -+ } else { -+ rc_update_bit_1(ctx, p); -+ *symbol = *symbol * 2 + 1; -+ return 1; -+ } -+} -+ -+static int -+rc_direct_bit(struct unlzma_ctx *ctx) -+{ -+ rc_normalize(ctx); -+ ctx->range >>= 1; -+ if (ctx->code >= ctx->range) { -+ ctx->code -= ctx->range; -+ return 1; -+ } -+ return 0; -+} -+ -+static void -+rc_bit_tree_decode(struct unlzma_ctx *ctx, u16 *p, int num_levels, int *symbol) -+{ -+ int i = num_levels; -+ -+ *symbol = 1; -+ while (i--) -+ rc_get_bit(ctx, p + *symbol, symbol); -+ *symbol -= 1 << num_levels; -+} -+ -+static u8 -+peek_old_byte(struct unlzma_ctx *ctx, u32 offs) -+{ -+ struct unlzma_buffer *bh = &ctx->buffers[ctx->n_buffers - 1]; -+ int i = ctx->n_buffers; -+ u32 pos; -+ -+ if (!ctx->n_buffers) { -+ printk(KERN_ERR "unlzma/%s: no buffer\n", __func__); -+ goto error; -+ } -+ -+ pos = ctx->pos - offs; -+ if (unlikely(pos >= ctx->dict_size)) -+ pos = ~pos & (ctx->dict_size - 1); -+ -+ while (bh->offset > pos) { -+ bh--; -+ i--; -+ if (!i) { -+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); -+ goto error; -+ } -+ } -+ -+ pos -= bh->offset; -+ if (pos >= bh->size) { -+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); -+ goto error; -+ } -+ -+ return bh->ptr[pos]; -+ -+error: -+ ctx->cancel = true; -+ return 0; -+} -+ -+static void -+write_byte(struct unlzma_ctx *ctx, u8 byte) -+{ -+ if (unlikely(ctx->avail_out <= 0)) { -+ unlzma_request_buffer(ctx, &ctx->avail_out); -+ } -+ -+ if (!ctx->avail_out) -+ return; -+ -+ ctx->previous_byte = byte; -+ *(ctx->next_out++) = byte; -+ ctx->avail_out--; -+ if (ctx->avail_out == 0) -+ ctx->buf_full = 1; -+ ctx->pos++; -+} -+ -+ -+static inline void -+copy_byte(struct unlzma_ctx *ctx, u32 offs) -+{ -+ write_byte(ctx, peek_old_byte(ctx, offs)); -+} -+ -+static void -+copy_bytes(struct unlzma_ctx *ctx, u32 rep0, int len) -+{ -+ do { -+ copy_byte(ctx, rep0); -+ len--; -+ if (unlzma_should_stop(ctx)) -+ break; -+ } while (len != 0); -+} -+ -+static void -+process_bit0(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob, -+ int lc, u32 literal_pos_mask) -+{ -+ int mi = 1; -+ rc_update_bit_0(ctx, prob); -+ prob = (p + LZMA_LITERAL + -+ (LZMA_LIT_SIZE -+ * (((ctx->pos & literal_pos_mask) << lc) -+ + (ctx->previous_byte >> (8 - lc)))) -+ ); -+ -+ if (ctx->state >= LZMA_NUM_LIT_STATES) { -+ int match_byte = peek_old_byte(ctx, ctx->rep0); -+ do { -+ u16 bit; -+ u16 *prob_lit; -+ -+ match_byte <<= 1; -+ bit = match_byte & 0x100; -+ prob_lit = prob + 0x100 + bit + mi; -+ if (rc_get_bit(ctx, prob_lit, &mi) != !!bit) -+ break; -+ } while (mi < 0x100); -+ } -+ while (mi < 0x100) { -+ u16 *prob_lit = prob + mi; -+ rc_get_bit(ctx, prob_lit, &mi); -+ } -+ write_byte(ctx, mi); -+ if (ctx->state < 4) -+ ctx->state = 0; -+ else if (ctx->state < 10) -+ ctx->state -= 3; -+ else -+ ctx->state -= 6; -+} -+ -+static void -+process_bit1(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob) -+{ -+ int offset; -+ u16 *prob_len; -+ int num_bits; -+ int len; -+ -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ ctx->rep3 = ctx->rep2; -+ ctx->rep2 = ctx->rep1; -+ ctx->rep1 = ctx->rep0; -+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 0 : 3; -+ prob = p + LZMA_LEN_CODER; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP_G0 + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ prob = (p + LZMA_IS_REP_0_LONG -+ + (ctx->state << -+ LZMA_NUM_POS_BITS_MAX) + -+ pos_state); -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ -+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? -+ 9 : 11; -+ copy_byte(ctx, ctx->rep0); -+ return; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ } -+ } else { -+ u32 distance; -+ -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP_G1 + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ distance = ctx->rep1; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP_G2 + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ distance = ctx->rep2; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ distance = ctx->rep3; -+ ctx->rep3 = ctx->rep2; -+ } -+ ctx->rep2 = ctx->rep1; -+ } -+ ctx->rep1 = ctx->rep0; -+ ctx->rep0 = distance; -+ } -+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 8 : 11; -+ prob = p + LZMA_REP_LEN_CODER; -+ } -+ -+ prob_len = prob + LZMA_LEN_CHOICE; -+ if (rc_is_bit_0(ctx, prob_len)) { -+ rc_update_bit_0(ctx, prob_len); -+ prob_len = (prob + LZMA_LEN_LOW -+ + (pos_state << -+ LZMA_LEN_NUM_LOW_BITS)); -+ offset = 0; -+ num_bits = LZMA_LEN_NUM_LOW_BITS; -+ } else { -+ rc_update_bit_1(ctx, prob_len); -+ prob_len = prob + LZMA_LEN_CHOICE_2; -+ if (rc_is_bit_0(ctx, prob_len)) { -+ rc_update_bit_0(ctx, prob_len); -+ prob_len = (prob + LZMA_LEN_MID -+ + (pos_state << -+ LZMA_LEN_NUM_MID_BITS)); -+ offset = 1 << LZMA_LEN_NUM_LOW_BITS; -+ num_bits = LZMA_LEN_NUM_MID_BITS; -+ } else { -+ rc_update_bit_1(ctx, prob_len); -+ prob_len = prob + LZMA_LEN_HIGH; -+ offset = ((1 << LZMA_LEN_NUM_LOW_BITS) -+ + (1 << LZMA_LEN_NUM_MID_BITS)); -+ num_bits = LZMA_LEN_NUM_HIGH_BITS; -+ } -+ } -+ -+ rc_bit_tree_decode(ctx, prob_len, num_bits, &len); -+ len += offset; -+ -+ if (ctx->state < 4) { -+ int pos_slot; -+ -+ ctx->state += LZMA_NUM_LIT_STATES; -+ prob = -+ p + LZMA_POS_SLOT + -+ ((len < -+ LZMA_NUM_LEN_TO_POS_STATES ? len : -+ LZMA_NUM_LEN_TO_POS_STATES - 1) -+ << LZMA_NUM_POS_SLOT_BITS); -+ rc_bit_tree_decode(ctx, prob, -+ LZMA_NUM_POS_SLOT_BITS, -+ &pos_slot); -+ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { -+ int i, mi; -+ num_bits = (pos_slot >> 1) - 1; -+ ctx->rep0 = 2 | (pos_slot & 1); -+ if (pos_slot < LZMA_END_POS_MODEL_INDEX) { -+ ctx->rep0 <<= num_bits; -+ prob = p + LZMA_SPEC_POS + -+ ctx->rep0 - pos_slot - 1; -+ } else { -+ num_bits -= LZMA_NUM_ALIGN_BITS; -+ while (num_bits--) -+ ctx->rep0 = (ctx->rep0 << 1) | -+ rc_direct_bit(ctx); -+ prob = p + LZMA_ALIGN; -+ ctx->rep0 <<= LZMA_NUM_ALIGN_BITS; -+ num_bits = LZMA_NUM_ALIGN_BITS; -+ } -+ i = 1; -+ mi = 1; -+ while (num_bits--) { -+ if (rc_get_bit(ctx, prob + mi, &mi)) -+ ctx->rep0 |= i; -+ i <<= 1; -+ } -+ } else -+ ctx->rep0 = pos_slot; -+ if (++(ctx->rep0) == 0) -+ return; -+ } -+ -+ len += LZMA_MATCH_MIN_LEN; -+ -+ copy_bytes(ctx, ctx->rep0, len); -+} -+ -+ -+static int -+do_unlzma(struct unlzma_ctx *ctx) -+{ -+ u8 hdr_buf[sizeof(struct lzma_header)]; -+ struct lzma_header *header = (struct lzma_header *)hdr_buf; -+ u32 pos_state_mask; -+ u32 literal_pos_mask; -+ int lc, pb, lp; -+ int num_probs; -+ int i, mi; -+ u16 *p; -+ -+ for (i = 0; i < sizeof(struct lzma_header); i++) { -+ hdr_buf[i] = rc_read(ctx); -+ } -+ -+ ctx->n_buffers = 0; -+ ctx->pos = 0; -+ get_buffer(ctx); -+ ctx->active = true; -+ ctx->state = 0; -+ ctx->rep0 = ctx->rep1 = ctx->rep2 = ctx->rep3 = 1; -+ -+ ctx->previous_byte = 0; -+ ctx->code = 0; -+ ctx->range = 0xFFFFFFFF; -+ -+ ctx->dict_size = le32_to_cpu(header->dict_size); -+ -+ if (header->pos >= (9 * 5 * 5)) -+ return -1; -+ -+ mi = 0; -+ lc = header->pos; -+ while (lc >= 9) { -+ mi++; -+ lc -= 9; -+ } -+ pb = 0; -+ lp = mi; -+ while (lp >= 5) { -+ pb++; -+ lp -= 5; -+ } -+ pos_state_mask = (1 << pb) - 1; -+ literal_pos_mask = (1 << lp) - 1; -+ -+ if (ctx->dict_size == 0) -+ ctx->dict_size = 1; -+ -+ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)); -+ if (ctx->workspace_size < num_probs * sizeof(*p)) { -+ if (ctx->workspace) -+ vfree(ctx->workspace); -+ ctx->workspace_size = num_probs * sizeof(*p); -+ ctx->workspace = vmalloc(ctx->workspace_size); -+ } -+ p = (u16 *) ctx->workspace; -+ if (!p) -+ return -1; -+ -+ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); -+ for (i = 0; i < num_probs; i++) -+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; -+ -+ for (i = 0; i < 5; i++) -+ rc_get_code(ctx); -+ -+ while (1) { -+ int pos_state = ctx->pos & pos_state_mask; -+ u16 *prob = p + LZMA_IS_MATCH + -+ (ctx->state << LZMA_NUM_POS_BITS_MAX) + pos_state; -+ if (rc_is_bit_0(ctx, prob)) -+ process_bit0(ctx, p, pos_state, prob, -+ lc, literal_pos_mask); -+ else { -+ process_bit1(ctx, p, pos_state, prob); -+ if (ctx->rep0 == 0) -+ break; -+ } -+ if (unlzma_should_stop(ctx)) -+ break; -+ } -+ if (likely(!unlzma_should_stop(ctx))) -+ rc_normalize(ctx); -+ -+ return ctx->pos; -+} -+ -+ -+static void -+unlzma_reset_buf(struct unlzma_ctx *ctx) -+{ -+ ctx->avail_in = 0; -+ ctx->next_in = NULL; -+ ctx->avail_out = 0; -+ ctx->next_out = NULL; -+} -+ -+static int -+unlzma_thread(void *data) -+{ -+ struct unlzma_ctx *ctx = data; -+ -+ mutex_lock(&ctx->mutex); -+ do { -+ if (do_unlzma(ctx) < 0) -+ ctx->pos = 0; -+ unlzma_reset_buf(ctx); -+ ctx->cancel = false; -+ ctx->active = false; -+ } while (!kthread_should_stop()); -+ mutex_unlock(&ctx->mutex); -+ return 0; -+} -+ -+ -+static int -+unlzma_init(struct crypto_tfm *tfm) -+{ -+ return 0; -+} -+ -+static void -+unlzma_cancel(struct unlzma_ctx *ctx) -+{ -+ unlzma_reset_buf(ctx); -+ -+ if (!ctx->active) -+ return; -+ -+ ctx->cancel = true; -+ do { -+ mutex_unlock(&ctx->mutex); -+ wake_up(&ctx->next_req); -+ schedule(); -+ mutex_lock(&ctx->mutex); -+ } while (ctx->cancel); -+} -+ -+ -+static void -+unlzma_exit(struct crypto_tfm *tfm) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ if (ctx->thread) { -+ unlzma_cancel(ctx); -+ kthread_stop(ctx->thread); -+ ctx->thread = NULL; -+ if (ctx->buffers) -+ kfree(ctx->buffers); -+ ctx->buffers_max = 0; -+ ctx->buffers = NULL; -+ } -+} -+ -+static int -+unlzma_decompress_setup(struct crypto_pcomp *tfm, void *p, unsigned int len) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); -+ struct nlattr *tb[UNLZMA_DECOMP_MAX + 1]; -+ int ret = 0; -+ -+ if (ctx->thread) -+ return -EINVAL; -+ -+ if (!p) -+ return -EINVAL; -+ -+ ret = nla_parse(tb, UNLZMA_DECOMP_MAX, p, len, NULL); -+ if (ret) -+ return ret; -+ -+ if (!tb[UNLZMA_DECOMP_OUT_BUFFERS]) -+ return -EINVAL; -+ -+ if (ctx->buffers_max && (ctx->buffers_max < -+ nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]))) { -+ kfree(ctx->buffers); -+ ctx->buffers_max = 0; -+ ctx->buffers = NULL; -+ } -+ if (!ctx->buffers) { -+ ctx->buffers_max = nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]); -+ ctx->buffers = kzalloc(sizeof(struct unlzma_buffer) * ctx->buffers_max, GFP_KERNEL); -+ } -+ if (!ctx->buffers) -+ return -ENOMEM; -+ -+ ctx->waiting = false; -+ mutex_init(&ctx->mutex); -+ init_waitqueue_head(&ctx->next_req); -+ init_waitqueue_head(&ctx->req_done); -+ ctx->thread = kthread_run(unlzma_thread, ctx, "unlzma/%d", instance++); -+ if (IS_ERR(ctx->thread)) { -+ ret = PTR_ERR(ctx->thread); -+ ctx->thread = NULL; -+ } -+ -+ return ret; -+} -+ -+static int -+unlzma_decompress_init(struct crypto_pcomp *tfm) -+{ -+ return 0; -+} -+ -+static void -+unlzma_wait_complete(struct unlzma_ctx *ctx, bool finish) -+{ -+ DEFINE_WAIT(__wait); -+ -+ do { -+ wake_up(&ctx->next_req); -+ prepare_to_wait(&ctx->req_done, &__wait, TASK_INTERRUPTIBLE); -+ mutex_unlock(&ctx->mutex); -+ schedule(); -+ mutex_lock(&ctx->mutex); -+ } while (!ctx->waiting && ctx->active); -+ finish_wait(&ctx->req_done, &__wait); -+} -+ -+static int -+unlzma_decompress_update(struct crypto_pcomp *tfm, struct comp_request *req) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); -+ size_t pos = 0; -+ -+ mutex_lock(&ctx->mutex); -+ if (!ctx->active && !req->avail_in) -+ goto out; -+ -+ pos = ctx->pos; -+ ctx->waiting = false; -+ ctx->next_in = req->next_in; -+ ctx->avail_in = req->avail_in; -+ ctx->next_out = req->next_out; -+ ctx->avail_out = req->avail_out; -+ -+ unlzma_wait_complete(ctx, false); -+ -+ req->next_in = ctx->next_in; -+ req->avail_in = ctx->avail_in; -+ req->next_out = ctx->next_out; -+ req->avail_out = ctx->avail_out; -+ ctx->next_in = 0; -+ ctx->avail_in = 0; -+ pos = ctx->pos - pos; -+ -+out: -+ mutex_unlock(&ctx->mutex); -+ if (ctx->cancel) -+ return -EINVAL; -+ -+ return pos; -+} -+ -+static int -+unlzma_decompress_final(struct crypto_pcomp *tfm, struct comp_request *req) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); -+ int ret = 0; -+ -+ /* cancel pending operation */ -+ mutex_lock(&ctx->mutex); -+ if (ctx->active) { -+ // ret = -EINVAL; -+ unlzma_cancel(ctx); -+ } -+ ctx->pos = 0; -+ mutex_unlock(&ctx->mutex); -+ return ret; -+} -+ -+ -+static struct pcomp_alg unlzma_alg = { -+ .decompress_setup = unlzma_decompress_setup, -+ .decompress_init = unlzma_decompress_init, -+ .decompress_update = unlzma_decompress_update, -+ .decompress_final = unlzma_decompress_final, -+ -+ .base = { -+ .cra_name = "lzma", -+ .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS, -+ .cra_ctxsize = sizeof(struct unlzma_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_init = unlzma_init, -+ .cra_exit = unlzma_exit, -+ } -+}; -+ -+static int __init -+unlzma_mod_init(void) -+{ -+ return crypto_register_pcomp(&unlzma_alg); -+} -+ -+static void __exit -+unlzma_mod_exit(void) -+{ -+ crypto_unregister_pcomp(&unlzma_alg); -+} -+ -+module_init(unlzma_mod_init); -+module_exit(unlzma_mod_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("LZMA Decompression Algorithm"); -+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -758,6 +758,12 @@ config CRYPTO_ZLIB - help - This is the zlib algorithm. - -+config CRYPTO_UNLZMA -+ tristate "LZMA decompression" -+ select CRYPTO_PCOMP -+ help -+ This is the lzma decompression module. -+ - config CRYPTO_LZO - tristate "LZO compression algorithm" - select CRYPTO_ALGAPI ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -75,6 +75,7 @@ obj-$(CONFIG_CRYPTO_SEED) += seed.o - obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o - obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o - obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o -+obj-$(CONFIG_CRYPTO_UNLZMA) += unlzma.o - obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o - obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o - obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o ---- /dev/null -+++ b/crypto/unlzma.h -@@ -0,0 +1,80 @@ -+/* LZMA uncompresion module for pcomp -+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> -+ * -+ * Based on: -+ * Initial Linux kernel adaptation -+ * Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ * Based on small lzma deflate implementation/Small range coder -+ * implementation for lzma. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+#ifndef __UNLZMA_H -+#define __UNLZMA_H -+ -+struct lzma_header { -+ __u8 pos; -+ __le32 dict_size; -+} __attribute__ ((packed)) ; -+ -+ -+#define RC_TOP_BITS 24 -+#define RC_MOVE_BITS 5 -+#define RC_MODEL_TOTAL_BITS 11 -+ -+#define LZMA_BASE_SIZE 1846 -+#define LZMA_LIT_SIZE 768 -+ -+#define LZMA_NUM_POS_BITS_MAX 4 -+ -+#define LZMA_LEN_NUM_LOW_BITS 3 -+#define LZMA_LEN_NUM_MID_BITS 3 -+#define LZMA_LEN_NUM_HIGH_BITS 8 -+ -+#define LZMA_LEN_CHOICE 0 -+#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) -+#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) -+#define LZMA_LEN_MID (LZMA_LEN_LOW \ -+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) -+#define LZMA_LEN_HIGH (LZMA_LEN_MID \ -+ +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) -+#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) -+ -+#define LZMA_NUM_STATES 12 -+#define LZMA_NUM_LIT_STATES 7 -+ -+#define LZMA_START_POS_MODEL_INDEX 4 -+#define LZMA_END_POS_MODEL_INDEX 14 -+#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) -+ -+#define LZMA_NUM_POS_SLOT_BITS 6 -+#define LZMA_NUM_LEN_TO_POS_STATES 4 -+ -+#define LZMA_NUM_ALIGN_BITS 4 -+ -+#define LZMA_MATCH_MIN_LEN 2 -+ -+#define LZMA_IS_MATCH 0 -+#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) -+#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ -+ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_SPEC_POS (LZMA_POS_SLOT \ -+ +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) -+#define LZMA_ALIGN (LZMA_SPEC_POS \ -+ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) -+#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) -+#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) -+#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) -+ -+#endif ---- a/include/crypto/compress.h -+++ b/include/crypto/compress.h -@@ -49,6 +49,12 @@ enum zlib_decomp_params { - - #define ZLIB_DECOMP_MAX (__ZLIB_DECOMP_MAX - 1) - -+enum unlzma_decomp_params { -+ UNLZMA_DECOMP_OUT_BUFFERS = 1, /* naximum number of output buffers */ -+ __UNLZMA_DECOMP_MAX, -+}; -+#define UNLZMA_DECOMP_MAX (__UNLZMA_DECOMP_MAX - 1) -+ - - struct crypto_pcomp { - struct crypto_tfm base; diff --git a/target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch b/target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch deleted file mode 100644 index 19deb7335..000000000 --- a/target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch +++ /dev/null @@ -1,244 +0,0 @@ ---- a/fs/squashfs/Kconfig -+++ b/fs/squashfs/Kconfig -@@ -2,7 +2,6 @@ config SQUASHFS - tristate "SquashFS 4.0 - Squashed file system support" - depends on BLOCK - 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 -@@ -37,6 +36,26 @@ config SQUASHFS_EMBEDDED - - If unsure, say N. - -+config SQUASHFS_SUPPORT_ZLIB -+ bool -+ prompt "Support ZLIB compression" if SQUASHFS_SUPPORT_LZMA -+ depends on SQUASHFS -+ select CRYPTO_ZLIB -+ default y -+ help -+ ZLIB is the default compression used in squashfs. If you are -+ using LZMA compression instead, you can remove support for ZLIB -+ entirely. -+ -+config SQUASHFS_SUPPORT_LZMA -+ bool "Support LZMA compression" -+ depends on SQUASHFS -+ select CRYPTO_UNLZMA -+ help -+ By default SquashFS uses ZLIB compression, however (if your tools -+ support it, you can use LZMA instead, which saves space. -+ -+ - config SQUASHFS_FRAGMENT_CACHE_SIZE - int "Number of fragments cached" if SQUASHFS_EMBEDDED - depends on SQUASHFS ---- a/fs/squashfs/squashfs_fs.h -+++ b/fs/squashfs/squashfs_fs.h -@@ -212,6 +212,7 @@ struct meta_index { - * definitions for structures on disk - */ - #define ZLIB_COMPRESSION 1 -+#define LZMA_COMPRESSION 2 - - struct squashfs_super_block { - __le32 s_magic; ---- a/fs/squashfs/super.c -+++ b/fs/squashfs/super.c -@@ -47,13 +47,76 @@ - #include "squashfs.h" - - --#define SQUASHFS_CRYPTO_ALG "zlib" -+static int squashfs_setup_zlib(struct squashfs_sb_info *msblk) -+{ -+ int err = -EOPNOTSUPP; -+ -+#ifdef CONFIG_SQUASHFS_SUPPORT_ZLIB -+ struct { -+ struct nlattr nla; -+ int val; -+ } params = { -+ .nla = { -+ .nla_len = nla_attr_size(sizeof(int)), -+ .nla_type = ZLIB_DECOMP_WINDOWBITS, -+ }, -+ .val = DEF_WBITS, -+ }; -+ -+ msblk->tfm = crypto_alloc_pcomp("zlib", 0, -+ CRYPTO_ALG_ASYNC); -+ if (IS_ERR(msblk->tfm)) { -+ ERROR("Failed to load zlib crypto module\n"); -+ return PTR_ERR(msblk->tfm); -+ } -+ -+ err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -+ if (err) { -+ ERROR("Failed to set up decompression parameters\n"); -+ crypto_free_pcomp(msblk->tfm); -+ } -+#endif -+ -+ return err; -+} -+ -+static int squashfs_setup_lzma(struct squashfs_sb_info *msblk) -+{ -+ int err = -EOPNOTSUPP; -+ -+#ifdef CONFIG_SQUASHFS_SUPPORT_LZMA -+ struct { -+ struct nlattr nla; -+ int val; -+ } params = { -+ .nla = { -+ .nla_len = nla_attr_size(sizeof(int)), -+ .nla_type = UNLZMA_DECOMP_OUT_BUFFERS, -+ }, -+ .val = (msblk->block_size / PAGE_CACHE_SIZE) + 1 -+ }; - -+ msblk->tfm = crypto_alloc_pcomp("lzma", 0, -+ CRYPTO_ALG_ASYNC); -+ if (IS_ERR(msblk->tfm)) { -+ ERROR("Failed to load lzma crypto module\n"); -+ return PTR_ERR(msblk->tfm); -+ } -+ -+ err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -+ if (err) { -+ ERROR("Failed to set up decompression parameters\n"); -+ crypto_free_pcomp(msblk->tfm); -+ } -+#endif -+ -+ return err; -+} - - static struct file_system_type squashfs_fs_type; - static struct super_operations squashfs_super_ops; - --static int supported_squashfs_filesystem(short major, short minor, short comp) -+static int supported_squashfs_filesystem(short major, short minor) - { - if (major < SQUASHFS_MAJOR) { - ERROR("Major/Minor mismatch, older Squashfs %d.%d " -@@ -66,9 +129,6 @@ static int supported_squashfs_filesystem - return -EINVAL; - } - -- if (comp != ZLIB_COMPRESSION) -- return -EINVAL; -- - return 0; - } - -@@ -83,16 +143,6 @@ static int squashfs_fill_super(struct su - unsigned short flags; - unsigned int fragments; - u64 lookup_table_start; -- struct { -- struct nlattr nla; -- int val; -- } params = { -- .nla = { -- .nla_len = nla_attr_size(sizeof(int)), -- .nla_type = ZLIB_DECOMP_WINDOWBITS, -- }, -- .val = DEF_WBITS, -- }; - int err; - - TRACE("Entered squashfs_fill_superblock\n"); -@@ -104,21 +154,6 @@ static int squashfs_fill_super(struct su - } - msblk = sb->s_fs_info; - -- msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0, -- CRYPTO_ALG_ASYNC); -- if (IS_ERR(msblk->tfm)) { -- ERROR("Failed to load %s crypto module\n", -- SQUASHFS_CRYPTO_ALG); -- err = PTR_ERR(msblk->tfm); -- goto failed_pcomp; -- } -- -- err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -- if (err) { -- ERROR("Failed to set up decompression parameters\n"); -- goto failure; -- } -- - sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); - if (sblk == NULL) { - ERROR("Failed to allocate squashfs_super_block\n"); -@@ -156,10 +191,28 @@ static int squashfs_fill_super(struct su - goto failed_mount; - } - -+ /* Check block size for sanity */ -+ msblk->block_size = le32_to_cpu(sblk->block_size); -+ if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE) -+ goto failed_mount; -+ - /* Check the MAJOR & MINOR versions and compression type */ - err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major), -- le16_to_cpu(sblk->s_minor), -- le16_to_cpu(sblk->compression)); -+ le16_to_cpu(sblk->s_minor)); -+ if (err < 0) -+ goto failed_mount; -+ -+ switch(le16_to_cpu(sblk->compression)) { -+ case ZLIB_COMPRESSION: -+ err = squashfs_setup_zlib(msblk); -+ break; -+ case LZMA_COMPRESSION: -+ err = squashfs_setup_lzma(msblk); -+ break; -+ default: -+ err = -EINVAL; -+ break; -+ } - if (err < 0) - goto failed_mount; - -@@ -179,11 +232,6 @@ static int squashfs_fill_super(struct su - i_size_read(sb->s_bdev->bd_inode)) - goto failed_mount; - -- /* Check block size for sanity */ -- msblk->block_size = le32_to_cpu(sblk->block_size); -- if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE) -- goto failed_mount; -- - /* - * Check the system page size is not larger than the filesystem - * block size (by default 128K). This is currently not supported. -@@ -315,21 +363,16 @@ allocate_root: - return 0; - - failed_mount: -+ if (msblk->tfm) -+ crypto_free_pcomp(msblk->tfm); - squashfs_cache_delete(msblk->block_cache); - squashfs_cache_delete(msblk->fragment_cache); - squashfs_cache_delete(msblk->read_page); - kfree(msblk->inode_lookup_table); - kfree(msblk->fragment_index); - kfree(msblk->id_table); -- crypto_free_pcomp(msblk->tfm); -- kfree(sb->s_fs_info); -- sb->s_fs_info = NULL; - kfree(sblk); -- return err; -- - failure: -- crypto_free_pcomp(msblk->tfm); --failed_pcomp: - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - return err; diff --git a/target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch b/target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch new file mode 100644 index 000000000..94096791f --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch @@ -0,0 +1,244 @@ +From 6c4419d997d4431bb62e73475cd6b084e83efbd1 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Tue, 22 Sep 2009 19:25:24 +0100 +Subject: [PATCH] Squashfs: move zlib decompression wrapper code into a separate file + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Makefile | 2 +- + fs/squashfs/block.c | 74 ++---------------------------- + fs/squashfs/squashfs.h | 4 ++ + fs/squashfs/zlib_wrapper.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 118 insertions(+), 71 deletions(-) + create mode 100644 fs/squashfs/zlib_wrapper.c + +--- a/fs/squashfs/Makefile ++++ b/fs/squashfs/Makefile +@@ -4,4 +4,4 @@ + + obj-$(CONFIG_SQUASHFS) += squashfs.o + squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o +-squashfs-y += namei.o super.o symlink.o ++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o +--- a/fs/squashfs/block.c ++++ b/fs/squashfs/block.c +@@ -29,7 +29,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/mutex.h> + #include <linux/string.h> + #include <linux/buffer_head.h> + #include <linux/zlib.h> +@@ -153,72 +152,10 @@ int squashfs_read_data(struct super_bloc + } + + if (compressed) { +- int zlib_err = 0, zlib_init = 0; +- +- /* +- * Uncompress block. +- */ +- +- mutex_lock(&msblk->read_data_mutex); +- +- msblk->stream.avail_out = 0; +- msblk->stream.avail_in = 0; +- +- bytes = length; +- do { +- if (msblk->stream.avail_in == 0 && k < b) { +- avail = min(bytes, msblk->devblksize - offset); +- bytes -= avail; +- wait_on_buffer(bh[k]); +- if (!buffer_uptodate(bh[k])) +- goto release_mutex; +- +- if (avail == 0) { +- offset = 0; +- put_bh(bh[k++]); +- continue; +- } +- +- msblk->stream.next_in = bh[k]->b_data + offset; +- msblk->stream.avail_in = avail; +- offset = 0; +- } +- +- if (msblk->stream.avail_out == 0 && page < pages) { +- msblk->stream.next_out = buffer[page++]; +- msblk->stream.avail_out = PAGE_CACHE_SIZE; +- } +- +- if (!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); +- goto release_mutex; +- } +- zlib_init = 1; +- } +- +- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); +- +- if (msblk->stream.avail_in == 0 && k < b) +- put_bh(bh[k++]); +- } while (zlib_err == Z_OK); +- +- if (zlib_err != Z_STREAM_END) { +- ERROR("zlib_inflate error, data probably corrupt\n"); +- goto release_mutex; +- } +- +- zlib_err = zlib_inflateEnd(&msblk->stream); +- if (zlib_err != Z_OK) { +- ERROR("zlib_inflate error, data probably corrupt\n"); +- goto release_mutex; +- } +- length = msblk->stream.total_out; +- mutex_unlock(&msblk->read_data_mutex); ++ length = zlib_uncompress(msblk, buffer, bh, b, offset, length, ++ srclength, pages); ++ if (length < 0) ++ goto read_failure; + } else { + /* + * Block is uncompressed. +@@ -255,9 +192,6 @@ int squashfs_read_data(struct super_bloc + kfree(bh); + return length; + +-release_mutex: +- mutex_unlock(&msblk->read_data_mutex); +- + block_release: + for (; k < b; k++) + put_bh(bh[k]); +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -70,6 +70,10 @@ extern struct inode *squashfs_iget(struc + unsigned int); + extern int squashfs_read_inode(struct inode *, long long); + ++/* zlib_wrapper.c */ ++extern int zlib_uncompress(struct squashfs_sb_info *, void **, ++ struct buffer_head **, int, int, int, int, int); ++ + /* + * Inodes and files operations + */ +--- /dev/null ++++ b/fs/squashfs/zlib_wrapper.c +@@ -0,0 +1,109 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * zlib_wrapper.c ++ */ ++ ++ ++#include <linux/mutex.h> ++#include <linux/buffer_head.h> ++#include <linux/zlib.h> ++ ++#include "squashfs_fs.h" ++#include "squashfs_fs_sb.h" ++#include "squashfs_fs_i.h" ++#include "squashfs.h" ++ ++int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, ++ struct buffer_head **bh, int b, int offset, int length, int srclength, ++ int pages) ++{ ++ int zlib_err = 0, zlib_init = 0; ++ int avail, bytes, k = 0, page = 0; ++ ++ mutex_lock(&msblk->read_data_mutex); ++ ++ msblk->stream.avail_out = 0; ++ msblk->stream.avail_in = 0; ++ ++ bytes = length; ++ do { ++ if (msblk->stream.avail_in == 0 && k < b) { ++ avail = min(bytes, msblk->devblksize - offset); ++ bytes -= avail; ++ wait_on_buffer(bh[k]); ++ if (!buffer_uptodate(bh[k])) ++ goto release_mutex; ++ ++ if (avail == 0) { ++ offset = 0; ++ put_bh(bh[k++]); ++ continue; ++ } ++ ++ msblk->stream.next_in = bh[k]->b_data + offset; ++ msblk->stream.avail_in = avail; ++ offset = 0; ++ } ++ ++ if (msblk->stream.avail_out == 0 && page < pages) { ++ msblk->stream.next_out = buffer[page++]; ++ msblk->stream.avail_out = PAGE_CACHE_SIZE; ++ } ++ ++ if (!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); ++ goto release_mutex; ++ } ++ zlib_init = 1; ++ } ++ ++ zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); ++ ++ if (msblk->stream.avail_in == 0 && k < b) ++ put_bh(bh[k++]); ++ } while (zlib_err == Z_OK); ++ ++ if (zlib_err != Z_STREAM_END) { ++ ERROR("zlib_inflate error, data probably corrupt\n"); ++ goto release_mutex; ++ } ++ ++ zlib_err = zlib_inflateEnd(&msblk->stream); ++ if (zlib_err != Z_OK) { ++ ERROR("zlib_inflate error, data probably corrupt\n"); ++ goto release_mutex; ++ } ++ ++ mutex_unlock(&msblk->read_data_mutex); ++ return msblk->stream.total_out; ++ ++release_mutex: ++ mutex_unlock(&msblk->read_data_mutex); ++ ++ for (; k < b; k++) ++ put_bh(bh[k]); ++ ++ return -EIO; ++} diff --git a/target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch b/target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch new file mode 100644 index 000000000..eacbb97ae --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch @@ -0,0 +1,317 @@ +From 37c44e85fd49676ec15ccaeea065662c1fbcda7d Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Wed, 23 Sep 2009 19:04:49 +0100 +Subject: [PATCH] Squashfs: Factor out remaining zlib dependencies into separate wrapper file + +Move zlib buffer init/destroy code into separate wrapper file. Also +make zlib z_stream field a void * removing the need to include zlib.h +for most files. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/block.c | 1 - + fs/squashfs/cache.c | 1 - + fs/squashfs/dir.c | 1 - + fs/squashfs/export.c | 1 - + fs/squashfs/file.c | 1 - + fs/squashfs/fragment.c | 1 - + fs/squashfs/id.c | 1 - + fs/squashfs/inode.c | 1 - + fs/squashfs/namei.c | 1 - + fs/squashfs/squashfs.h | 2 + + fs/squashfs/squashfs_fs_sb.h | 2 +- + fs/squashfs/super.c | 14 +++------ + fs/squashfs/symlink.c | 1 - + fs/squashfs/zlib_wrapper.c | 56 ++++++++++++++++++++++++++++++++--------- + 14 files changed, 51 insertions(+), 33 deletions(-) + +--- a/fs/squashfs/block.c ++++ b/fs/squashfs/block.c +@@ -31,7 +31,6 @@ + #include <linux/slab.h> + #include <linux/string.h> + #include <linux/buffer_head.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/cache.c ++++ b/fs/squashfs/cache.c +@@ -51,7 +51,6 @@ + #include <linux/sched.h> + #include <linux/spinlock.h> + #include <linux/wait.h> +-#include <linux/zlib.h> + #include <linux/pagemap.h> + + #include "squashfs_fs.h" +--- a/fs/squashfs/dir.c ++++ b/fs/squashfs/dir.c +@@ -30,7 +30,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/export.c ++++ b/fs/squashfs/export.c +@@ -39,7 +39,6 @@ + #include <linux/vfs.h> + #include <linux/dcache.h> + #include <linux/exportfs.h> +-#include <linux/zlib.h> + #include <linux/slab.h> + + #include "squashfs_fs.h" +--- a/fs/squashfs/file.c ++++ b/fs/squashfs/file.c +@@ -47,7 +47,6 @@ + #include <linux/string.h> + #include <linux/pagemap.h> + #include <linux/mutex.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/fragment.c ++++ b/fs/squashfs/fragment.c +@@ -36,7 +36,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/id.c ++++ b/fs/squashfs/id.c +@@ -34,7 +34,6 @@ + #include <linux/fs.h> + #include <linux/vfs.h> + #include <linux/slab.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/inode.c ++++ b/fs/squashfs/inode.c +@@ -40,7 +40,6 @@ + + #include <linux/fs.h> + #include <linux/vfs.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/namei.c ++++ b/fs/squashfs/namei.c +@@ -57,7 +57,6 @@ + #include <linux/slab.h> + #include <linux/string.h> + #include <linux/dcache.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -71,6 +71,8 @@ extern struct inode *squashfs_iget(struc + extern int squashfs_read_inode(struct inode *, long long); + + /* zlib_wrapper.c */ ++extern void *zlib_init(void); ++extern void zlib_free(void *); + extern int zlib_uncompress(struct squashfs_sb_info *, void **, + struct buffer_head **, int, int, int, int, int); + +--- 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; ++ void *stream; + __le64 *inode_lookup_table; + u64 inode_table; + u64 directory_table; +--- a/fs/squashfs/super.c ++++ b/fs/squashfs/super.c +@@ -35,7 +35,6 @@ + #include <linux/pagemap.h> + #include <linux/init.h> + #include <linux/module.h> +-#include <linux/zlib.h> + #include <linux/magic.h> + + #include "squashfs_fs.h" +@@ -87,12 +86,9 @@ static int squashfs_fill_super(struct su + } + 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->stream = zlib_init(); ++ if (msblk->stream == NULL) + goto failure; +- } + + sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); + if (sblk == NULL) { +@@ -292,17 +288,17 @@ failed_mount: + squashfs_cache_delete(msblk->block_cache); + squashfs_cache_delete(msblk->fragment_cache); + squashfs_cache_delete(msblk->read_page); ++ zlib_free(msblk->stream); + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->id_table); +- kfree(msblk->stream.workspace); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + kfree(sblk); + return err; + + failure: +- kfree(msblk->stream.workspace); ++ zlib_free(msblk->stream); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + return -ENOMEM; +@@ -346,10 +342,10 @@ static void squashfs_put_super(struct su + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + squashfs_cache_delete(sbi->read_page); ++ zlib_free(sbi->stream); + kfree(sbi->id_table); + kfree(sbi->fragment_index); + kfree(sbi->meta_index); +- kfree(sbi->stream.workspace); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + } +--- a/fs/squashfs/symlink.c ++++ b/fs/squashfs/symlink.c +@@ -36,7 +36,6 @@ + #include <linux/slab.h> + #include <linux/string.h> + #include <linux/pagemap.h> +-#include <linux/zlib.h> + + #include "squashfs_fs.h" + #include "squashfs_fs_sb.h" +--- a/fs/squashfs/zlib_wrapper.c ++++ b/fs/squashfs/zlib_wrapper.c +@@ -31,21 +31,51 @@ + #include "squashfs_fs_i.h" + #include "squashfs.h" + ++void *zlib_init() ++{ ++ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); ++ if (stream == NULL) ++ goto failed; ++ stream->workspace = kmalloc(zlib_inflate_workspacesize(), ++ GFP_KERNEL); ++ if (stream->workspace == NULL) ++ goto failed; ++ ++ return stream; ++ ++failed: ++ ERROR("Failed to allocate zlib workspace\n"); ++ kfree(stream); ++ return NULL; ++} ++ ++ ++void zlib_free(void *strm) ++{ ++ z_stream *stream = strm; ++ ++ if (stream) ++ kfree(stream->workspace); ++ kfree(stream); ++} ++ ++ + int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, + struct buffer_head **bh, int b, int offset, int length, int srclength, + int pages) + { + int zlib_err = 0, zlib_init = 0; + int avail, bytes, k = 0, page = 0; ++ z_stream *stream = msblk->stream; + + mutex_lock(&msblk->read_data_mutex); + +- msblk->stream.avail_out = 0; +- msblk->stream.avail_in = 0; ++ stream->avail_out = 0; ++ stream->avail_in = 0; + + bytes = length; + do { +- if (msblk->stream.avail_in == 0 && k < b) { ++ if (stream->avail_in == 0 && k < b) { + avail = min(bytes, msblk->devblksize - offset); + bytes -= avail; + wait_on_buffer(bh[k]); +@@ -58,18 +88,18 @@ int zlib_uncompress(struct squashfs_sb_i + continue; + } + +- msblk->stream.next_in = bh[k]->b_data + offset; +- msblk->stream.avail_in = avail; ++ stream->next_in = bh[k]->b_data + offset; ++ stream->avail_in = avail; + offset = 0; + } + +- if (msblk->stream.avail_out == 0 && page < pages) { +- msblk->stream.next_out = buffer[page++]; +- msblk->stream.avail_out = PAGE_CACHE_SIZE; ++ if (stream->avail_out == 0 && page < pages) { ++ stream->next_out = buffer[page++]; ++ stream->avail_out = PAGE_CACHE_SIZE; + } + + if (!zlib_init) { +- zlib_err = zlib_inflateInit(&msblk->stream); ++ zlib_err = zlib_inflateInit(stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflateInit returned unexpected " + "result 0x%x, srclength %d\n", +@@ -79,9 +109,9 @@ int zlib_uncompress(struct squashfs_sb_i + zlib_init = 1; + } + +- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); ++ zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH); + +- if (msblk->stream.avail_in == 0 && k < b) ++ if (stream->avail_in == 0 && k < b) + put_bh(bh[k++]); + } while (zlib_err == Z_OK); + +@@ -90,14 +120,14 @@ int zlib_uncompress(struct squashfs_sb_i + goto release_mutex; + } + +- zlib_err = zlib_inflateEnd(&msblk->stream); ++ zlib_err = zlib_inflateEnd(stream); + if (zlib_err != Z_OK) { + ERROR("zlib_inflate error, data probably corrupt\n"); + goto release_mutex; + } + + mutex_unlock(&msblk->read_data_mutex); +- return msblk->stream.total_out; ++ return stream->total_out; + + release_mutex: + mutex_unlock(&msblk->read_data_mutex); diff --git a/target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch b/target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch new file mode 100644 index 000000000..cbfbf5369 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch @@ -0,0 +1,426 @@ +From 327fbf47a419befc6bff74f3ca42d2b6f0841903 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Tue, 6 Oct 2009 04:04:15 +0100 +Subject: [PATCH] Squashfs: add a decompressor framework + +This adds a decompressor framework which allows multiple compression +algorithms to be cleanly supported. + +Also update zlib wrapper and other code to use the new framework. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Makefile | 2 +- + fs/squashfs/block.c | 6 ++-- + fs/squashfs/decompressor.c | 58 ++++++++++++++++++++++++++++++++++++++++++ + fs/squashfs/decompressor.h | 55 +++++++++++++++++++++++++++++++++++++++ + fs/squashfs/squashfs.h | 14 +++++----- + fs/squashfs/squashfs_fs_sb.h | 41 +++++++++++++++-------------- + fs/squashfs/super.c | 45 ++++++++++++++++++------------- + fs/squashfs/zlib_wrapper.c | 17 ++++++++++-- + 8 files changed, 185 insertions(+), 53 deletions(-) + create mode 100644 fs/squashfs/decompressor.c + create mode 100644 fs/squashfs/decompressor.h + +--- a/fs/squashfs/Makefile ++++ b/fs/squashfs/Makefile +@@ -4,4 +4,4 @@ + + obj-$(CONFIG_SQUASHFS) += squashfs.o + squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o +-squashfs-y += namei.o super.o symlink.o zlib_wrapper.o ++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o +--- a/fs/squashfs/block.c ++++ b/fs/squashfs/block.c +@@ -36,7 +36,7 @@ + #include "squashfs_fs_sb.h" + #include "squashfs_fs_i.h" + #include "squashfs.h" +- ++#include "decompressor.h" + /* + * Read the metadata block length, this is stored in the first two + * bytes of the metadata block. +@@ -151,8 +151,8 @@ int squashfs_read_data(struct super_bloc + } + + if (compressed) { +- length = zlib_uncompress(msblk, buffer, bh, b, offset, length, +- srclength, pages); ++ length = squashfs_decompress(msblk, buffer, bh, b, offset, ++ length, srclength, pages); + if (length < 0) + goto read_failure; + } else { +--- /dev/null ++++ b/fs/squashfs/decompressor.c +@@ -0,0 +1,58 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * decompressor.c ++ */ ++ ++#include <linux/types.h> ++#include <linux/mutex.h> ++#include <linux/buffer_head.h> ++ ++#include "squashfs_fs.h" ++#include "squashfs_fs_sb.h" ++#include "squashfs_fs_i.h" ++#include "decompressor.h" ++#include "squashfs.h" ++ ++/* ++ * This file (and decompressor.h) implements a decompressor framework for ++ * Squashfs, allowing multiple decompressors to be easily supported ++ */ ++ ++static const struct squashfs_decompressor squashfs_unknown_comp_ops = { ++ NULL, NULL, NULL, 0, "unknown", 0 ++}; ++ ++static const struct squashfs_decompressor *decompressor[] = { ++ &squashfs_zlib_comp_ops, ++ &squashfs_unknown_comp_ops ++}; ++ ++ ++const struct squashfs_decompressor *squashfs_lookup_decompressor(int id) ++{ ++ int i; ++ ++ for (i = 0; decompressor[i]->id; i++) ++ if (id == decompressor[i]->id) ++ break; ++ ++ return decompressor[i]; ++} +--- /dev/null ++++ b/fs/squashfs/decompressor.h +@@ -0,0 +1,55 @@ ++#ifndef DECOMPRESSOR_H ++#define DECOMPRESSOR_H ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * decompressor.h ++ */ ++ ++struct squashfs_decompressor { ++ void *(*init)(void); ++ void (*free)(void *); ++ int (*decompress)(struct squashfs_sb_info *, void **, ++ struct buffer_head **, int, int, int, int, int); ++ int id; ++ char *name; ++ int supported; ++}; ++ ++static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk) ++{ ++ return msblk->decompressor->init(); ++} ++ ++static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, ++ void *s) ++{ ++ if (msblk->decompressor) ++ msblk->decompressor->free(s); ++} ++ ++static inline int squashfs_decompress(struct squashfs_sb_info *msblk, ++ void **buffer, struct buffer_head **bh, int b, int offset, int length, ++ int srclength, int pages) ++{ ++ return msblk->decompressor->decompress(msblk, buffer, bh, b, offset, ++ length, srclength, pages); ++} ++#endif +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squa + u64, int); + extern int squashfs_read_table(struct super_block *, void *, u64, int); + ++/* decompressor.c */ ++extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); ++ + /* export.c */ + extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, + unsigned int); +@@ -70,14 +73,8 @@ extern struct inode *squashfs_iget(struc + unsigned int); + extern int squashfs_read_inode(struct inode *, long long); + +-/* zlib_wrapper.c */ +-extern void *zlib_init(void); +-extern void zlib_free(void *); +-extern int zlib_uncompress(struct squashfs_sb_info *, void **, +- struct buffer_head **, int, int, int, int, int); +- + /* +- * Inodes and files operations ++ * Inodes, files and decompressor operations + */ + + /* dir.c */ +@@ -94,3 +91,6 @@ extern const struct inode_operations squ + + /* symlink.c */ + extern const struct address_space_operations squashfs_symlink_aops; ++ ++/* zlib_wrapper.c */ ++extern const struct squashfs_decompressor squashfs_zlib_comp_ops; +--- a/fs/squashfs/squashfs_fs_sb.h ++++ b/fs/squashfs/squashfs_fs_sb.h +@@ -52,25 +52,26 @@ struct squashfs_cache_entry { + }; + + struct squashfs_sb_info { +- int devblksize; +- int devblksize_log2; +- struct squashfs_cache *block_cache; +- struct squashfs_cache *fragment_cache; +- struct squashfs_cache *read_page; +- int next_meta_index; +- __le64 *id_table; +- __le64 *fragment_index; +- unsigned int *fragment_index_2; +- struct mutex read_data_mutex; +- struct mutex meta_index_mutex; +- struct meta_index *meta_index; +- void *stream; +- __le64 *inode_lookup_table; +- u64 inode_table; +- u64 directory_table; +- unsigned int block_size; +- unsigned short block_log; +- long long bytes_used; +- unsigned int inodes; ++ const struct squashfs_decompressor *decompressor; ++ int devblksize; ++ int devblksize_log2; ++ struct squashfs_cache *block_cache; ++ struct squashfs_cache *fragment_cache; ++ struct squashfs_cache *read_page; ++ int next_meta_index; ++ __le64 *id_table; ++ __le64 *fragment_index; ++ unsigned int *fragment_index_2; ++ struct mutex read_data_mutex; ++ struct mutex meta_index_mutex; ++ struct meta_index *meta_index; ++ void *stream; ++ __le64 *inode_lookup_table; ++ u64 inode_table; ++ u64 directory_table; ++ unsigned int block_size; ++ unsigned short block_log; ++ long long bytes_used; ++ unsigned int inodes; + }; + #endif +--- a/fs/squashfs/super.c ++++ b/fs/squashfs/super.c +@@ -41,27 +41,35 @@ + #include "squashfs_fs_sb.h" + #include "squashfs_fs_i.h" + #include "squashfs.h" ++#include "decompressor.h" + + static struct file_system_type squashfs_fs_type; + static struct super_operations squashfs_super_ops; + +-static int supported_squashfs_filesystem(short major, short minor, short comp) ++static const struct squashfs_decompressor *supported_squashfs_filesystem(short ++ major, short minor, short id) + { ++ const struct squashfs_decompressor *decompressor; ++ + if (major < SQUASHFS_MAJOR) { + ERROR("Major/Minor mismatch, older Squashfs %d.%d " + "filesystems are unsupported\n", major, minor); +- return -EINVAL; ++ return NULL; + } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { + ERROR("Major/Minor mismatch, trying to mount newer " + "%d.%d filesystem\n", major, minor); + ERROR("Please update your kernel\n"); +- return -EINVAL; ++ return NULL; + } + +- if (comp != ZLIB_COMPRESSION) +- return -EINVAL; ++ decompressor = squashfs_lookup_decompressor(id); ++ if (!decompressor->supported) { ++ ERROR("Filesystem uses \"%s\" compression. This is not " ++ "supported\n", decompressor->name); ++ return NULL; ++ } + +- return 0; ++ return decompressor; + } + + +@@ -86,10 +94,6 @@ static int squashfs_fill_super(struct su + } + msblk = sb->s_fs_info; + +- msblk->stream = zlib_init(); +- if (msblk->stream == NULL) +- goto failure; +- + sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); + if (sblk == NULL) { + ERROR("Failed to allocate squashfs_super_block\n"); +@@ -116,25 +120,25 @@ static int squashfs_fill_super(struct su + goto failed_mount; + } + ++ err = -EINVAL; ++ + /* Check it is a SQUASHFS superblock */ + sb->s_magic = le32_to_cpu(sblk->s_magic); + if (sb->s_magic != SQUASHFS_MAGIC) { + if (!silent) + ERROR("Can't find a SQUASHFS superblock on %s\n", + bdevname(sb->s_bdev, b)); +- err = -EINVAL; + goto failed_mount; + } + +- /* Check the MAJOR & MINOR versions and compression type */ +- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major), ++ /* Check the MAJOR & MINOR versions and lookup compression type */ ++ msblk->decompressor = supported_squashfs_filesystem( ++ le16_to_cpu(sblk->s_major), + le16_to_cpu(sblk->s_minor), + le16_to_cpu(sblk->compression)); +- if (err < 0) ++ if (msblk->decompressor == NULL) + goto failed_mount; + +- err = -EINVAL; +- + /* + * Check if there's xattrs in the filesystem. These are not + * supported in this version, so warn that they will be ignored. +@@ -201,6 +205,10 @@ static int squashfs_fill_super(struct su + + err = -ENOMEM; + ++ msblk->stream = squashfs_decompressor_init(msblk); ++ if (msblk->stream == NULL) ++ goto failed_mount; ++ + msblk->block_cache = squashfs_cache_init("metadata", + SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); + if (msblk->block_cache == NULL) +@@ -288,7 +296,7 @@ failed_mount: + squashfs_cache_delete(msblk->block_cache); + squashfs_cache_delete(msblk->fragment_cache); + squashfs_cache_delete(msblk->read_page); +- zlib_free(msblk->stream); ++ squashfs_decompressor_free(msblk, msblk->stream); + kfree(msblk->inode_lookup_table); + kfree(msblk->fragment_index); + kfree(msblk->id_table); +@@ -298,7 +306,6 @@ failed_mount: + return err; + + failure: +- zlib_free(msblk->stream); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + return -ENOMEM; +@@ -342,7 +349,7 @@ static void squashfs_put_super(struct su + squashfs_cache_delete(sbi->block_cache); + squashfs_cache_delete(sbi->fragment_cache); + squashfs_cache_delete(sbi->read_page); +- zlib_free(sbi->stream); ++ squashfs_decompressor_free(sbi, sbi->stream); + kfree(sbi->id_table); + kfree(sbi->fragment_index); + kfree(sbi->meta_index); +--- a/fs/squashfs/zlib_wrapper.c ++++ b/fs/squashfs/zlib_wrapper.c +@@ -30,8 +30,9 @@ + #include "squashfs_fs_sb.h" + #include "squashfs_fs_i.h" + #include "squashfs.h" ++#include "decompressor.h" + +-void *zlib_init() ++static void *zlib_init(void) + { + z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); + if (stream == NULL) +@@ -50,7 +51,7 @@ failed: + } + + +-void zlib_free(void *strm) ++static void zlib_free(void *strm) + { + z_stream *stream = strm; + +@@ -60,7 +61,7 @@ void zlib_free(void *strm) + } + + +-int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, ++static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer, + struct buffer_head **bh, int b, int offset, int length, int srclength, + int pages) + { +@@ -137,3 +138,13 @@ release_mutex: + + return -EIO; + } ++ ++const struct squashfs_decompressor squashfs_zlib_comp_ops = { ++ .init = zlib_init, ++ .free = zlib_free, ++ .decompress = zlib_uncompress, ++ .id = ZLIB_COMPRESSION, ++ .name = "zlib", ++ .supported = 1 ++}; ++ diff --git a/target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch b/target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch new file mode 100644 index 000000000..a378c0005 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch @@ -0,0 +1,54 @@ +From 1885ca0a1973944684f252094a703b7c80dfc974 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Wed, 14 Oct 2009 03:58:11 +0100 +Subject: [PATCH] Squashfs: add decompressor entries for lzma and lzo + +Add knowledge of lzma/lzo compression formats to the decompressor +framework. For now these are added as unsupported. Without +these entries lzma/lzo compressed filesystems will be flagged as +having unknown compression which is undesirable. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/decompressor.c | 10 ++++++++++ + fs/squashfs/squashfs_fs.h | 4 +++- + 2 files changed, 13 insertions(+), 1 deletions(-) + +--- a/fs/squashfs/decompressor.c ++++ b/fs/squashfs/decompressor.c +@@ -36,12 +36,22 @@ + * Squashfs, allowing multiple decompressors to be easily supported + */ + ++static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = { ++ NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 ++}; ++ ++static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = { ++ NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 ++}; ++ + static const struct squashfs_decompressor squashfs_unknown_comp_ops = { + NULL, NULL, NULL, 0, "unknown", 0 + }; + + static const struct squashfs_decompressor *decompressor[] = { + &squashfs_zlib_comp_ops, ++ &squashfs_lzma_unsupported_comp_ops, ++ &squashfs_lzo_unsupported_comp_ops, + &squashfs_unknown_comp_ops + }; + +--- a/fs/squashfs/squashfs_fs.h ++++ b/fs/squashfs/squashfs_fs.h +@@ -211,7 +211,9 @@ struct meta_index { + /* + * definitions for structures on disk + */ +-#define ZLIB_COMPRESSION 1 ++#define ZLIB_COMPRESSION 1 ++#define LZMA_COMPRESSION 2 ++#define LZO_COMPRESSION 3 + + struct squashfs_super_block { + __le32 s_magic; diff --git a/target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch b/target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch new file mode 100644 index 000000000..099168134 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch @@ -0,0 +1,42 @@ +From 5f393ede3ddb5dd4cc2a9f243182fac45f1ce10b Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Wed, 14 Oct 2009 04:07:54 +0100 +Subject: [PATCH] Squashfs: add an extra parameter to the decompressor init function + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/decompressor.h | 4 ++-- + fs/squashfs/zlib_wrapper.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/squashfs/decompressor.h ++++ b/fs/squashfs/decompressor.h +@@ -24,7 +24,7 @@ + */ + + struct squashfs_decompressor { +- void *(*init)(void); ++ void *(*init)(struct squashfs_sb_info *); + void (*free)(void *); + int (*decompress)(struct squashfs_sb_info *, void **, + struct buffer_head **, int, int, int, int, int); +@@ -35,7 +35,7 @@ struct squashfs_decompressor { + + static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk) + { +- return msblk->decompressor->init(); ++ return msblk->decompressor->init(msblk); + } + + static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, +--- a/fs/squashfs/zlib_wrapper.c ++++ b/fs/squashfs/zlib_wrapper.c +@@ -32,7 +32,7 @@ + #include "squashfs.h" + #include "decompressor.h" + +-static void *zlib_init(void) ++static void *zlib_init(struct squashfs_sb_info *dummy) + { + z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); + if (stream == NULL) diff --git a/target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch b/target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch new file mode 100644 index 000000000..9fd57970f --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch @@ -0,0 +1,216 @@ +From f49e1efdd179d54e814ff2a8e8f469496583062c Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Tue, 20 Oct 2009 10:54:36 +0100 +Subject: [PATCH] Squashfs: add LZMA compression + +Add support for LZMA compressed filesystems. This is an initial +implementation. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Kconfig | 5 ++ + fs/squashfs/Makefile | 1 + + fs/squashfs/decompressor.c | 4 + + fs/squashfs/lzma_wrapper.c | 151 ++++++++++++++++++++++++++++++++++++++++++++ + fs/squashfs/squashfs.h | 3 + + 5 files changed, 164 insertions(+), 0 deletions(-) + create mode 100644 fs/squashfs/lzma_wrapper.c + +--- a/fs/squashfs/Kconfig ++++ b/fs/squashfs/Kconfig +@@ -26,6 +26,11 @@ config SQUASHFS + + If unsure, say N. + ++config SQUASHFS_LZMA ++ bool "Include support for LZMA compressed file systems" ++ depends on SQUASHFS ++ select DECOMPRESS_LZMA ++ + config SQUASHFS_EMBEDDED + + bool "Additional option for memory-constrained systems" +--- a/fs/squashfs/Makefile ++++ b/fs/squashfs/Makefile +@@ -5,3 +5,4 @@ + obj-$(CONFIG_SQUASHFS) += squashfs.o + squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o + squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o ++squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o +--- a/fs/squashfs/decompressor.c ++++ b/fs/squashfs/decompressor.c +@@ -50,7 +50,11 @@ static const struct squashfs_decompresso + + static const struct squashfs_decompressor *decompressor[] = { + &squashfs_zlib_comp_ops, ++#ifdef CONFIG_SQUASHFS_LZMA ++ &squashfs_lzma_comp_ops, ++#else + &squashfs_lzma_unsupported_comp_ops, ++#endif + &squashfs_lzo_unsupported_comp_ops, + &squashfs_unknown_comp_ops + }; +--- /dev/null ++++ b/fs/squashfs/lzma_wrapper.c +@@ -0,0 +1,151 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * 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, ++ * or (at your option) any later version. ++ * ++ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * lzma_wrapper.c ++ */ ++ ++#include <asm/unaligned.h> ++#include <linux/buffer_head.h> ++#include <linux/mutex.h> ++#include <linux/vmalloc.h> ++#include <linux/decompress/unlzma.h> ++ ++#include "squashfs_fs.h" ++#include "squashfs_fs_sb.h" ++#include "squashfs_fs_i.h" ++#include "squashfs.h" ++#include "decompressor.h" ++ ++struct squashfs_lzma { ++ void *input; ++ void *output; ++}; ++ ++/* decompress_unlzma.c is currently non re-entrant... */ ++DEFINE_MUTEX(lzma_mutex); ++ ++/* decompress_unlzma.c doesn't provide any context in its callbacks... */ ++static int lzma_error; ++ ++static void error(char *m) ++{ ++ ERROR("unlzma error: %s\n", m); ++ lzma_error = 1; ++} ++ ++ ++static void *lzma_init(struct squashfs_sb_info *msblk) ++{ ++ struct squashfs_lzma *stream = kzalloc(sizeof(*stream), GFP_KERNEL); ++ if (stream == NULL) ++ goto failed; ++ stream->input = vmalloc(msblk->block_size); ++ if (stream->input == NULL) ++ goto failed; ++ stream->output = vmalloc(msblk->block_size); ++ if (stream->output == NULL) ++ goto failed2; ++ ++ return stream; ++ ++failed2: ++ vfree(stream->input); ++failed: ++ ERROR("failed to allocate lzma workspace\n"); ++ kfree(stream); ++ return NULL; ++} ++ ++ ++static void lzma_free(void *strm) ++{ ++ struct squashfs_lzma *stream = strm; ++ ++ if (stream) { ++ vfree(stream->input); ++ vfree(stream->output); ++ } ++ kfree(stream); ++} ++ ++ ++static int lzma_uncompress(struct squashfs_sb_info *msblk, void **buffer, ++ struct buffer_head **bh, int b, int offset, int length, int srclength, ++ int pages) ++{ ++ struct squashfs_lzma *stream = msblk->stream; ++ void *buff = stream->input; ++ int avail, i, bytes = length, res; ++ ++ mutex_lock(&lzma_mutex); ++ ++ for (i = 0; i < b; i++) { ++ wait_on_buffer(bh[i]); ++ if (!buffer_uptodate(bh[i])) ++ goto block_release; ++ ++ avail = min(bytes, msblk->devblksize - offset); ++ memcpy(buff, bh[i]->b_data + offset, avail); ++ buff += avail; ++ bytes -= avail; ++ offset = 0; ++ put_bh(bh[i]); ++ } ++ ++ lzma_error = 0; ++ res = unlzma(stream->input, length, NULL, NULL, stream->output, NULL, ++ error); ++ if (res || lzma_error) ++ goto failed; ++ ++ /* uncompressed size is stored in the LZMA header (5 byte offset) */ ++ res = bytes = get_unaligned_le32(stream->input + 5); ++ for (i = 0, buff = stream->output; bytes && i < pages; i++) { ++ avail = min_t(int, bytes, PAGE_CACHE_SIZE); ++ memcpy(buffer[i], buff, avail); ++ buff += avail; ++ bytes -= avail; ++ } ++ if (bytes) ++ goto failed; ++ ++ mutex_unlock(&lzma_mutex); ++ return res; ++ ++block_release: ++ for (; i < b; i++) ++ put_bh(bh[i]); ++ ++failed: ++ mutex_unlock(&lzma_mutex); ++ ++ ERROR("lzma decompression failed, data probably corrupt\n"); ++ return -EIO; ++} ++ ++const struct squashfs_decompressor squashfs_lzma_comp_ops = { ++ .init = lzma_init, ++ .free = lzma_free, ++ .decompress = lzma_uncompress, ++ .id = LZMA_COMPRESSION, ++ .name = "lzma", ++ .supported = 1 ++}; ++ +--- a/fs/squashfs/squashfs.h ++++ b/fs/squashfs/squashfs.h +@@ -94,3 +94,6 @@ extern const struct address_space_operat + + /* zlib_wrapper.c */ + extern const struct squashfs_decompressor squashfs_zlib_comp_ops; ++ ++/* lzma wrapper.c */ ++extern const struct squashfs_decompressor squashfs_lzma_comp_ops; diff --git a/target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch b/target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch new file mode 100644 index 000000000..aa6c11012 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch @@ -0,0 +1,165 @@ +From fdf23ed283bc6ef5c25076ce2065f892120ff556 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <phillip@lougher.demon.co.uk> +Date: Thu, 22 Oct 2009 04:57:38 +0100 +Subject: [PATCH] Squashfs: Make unlzma available to non initramfs/initrd code + +Add a config option DECOMPRESS_LZMA_NEEDED which allows subsystems to +specify they need the unlzma code. Normally decompress_unlzma.c is +compiled with __init and unlzma is not exported to modules. + +Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk> +--- + fs/squashfs/Kconfig | 1 + + include/linux/decompress/bunzip2_mm.h | 12 ++++++++++++ + include/linux/decompress/inflate_mm.h | 12 ++++++++++++ + include/linux/decompress/mm.h | 3 --- + include/linux/decompress/unlzma_mm.h | 20 ++++++++++++++++++++ + lib/Kconfig | 3 +++ + lib/decompress_bunzip2.c | 1 + + lib/decompress_inflate.c | 1 + + lib/decompress_unlzma.c | 5 ++++- + 9 files changed, 54 insertions(+), 4 deletions(-) + create mode 100644 include/linux/decompress/bunzip2_mm.h + create mode 100644 include/linux/decompress/inflate_mm.h + create mode 100644 include/linux/decompress/unlzma_mm.h + +--- a/fs/squashfs/Kconfig ++++ b/fs/squashfs/Kconfig +@@ -30,6 +30,7 @@ config SQUASHFS_LZMA + bool "Include support for LZMA compressed file systems" + depends on SQUASHFS + select DECOMPRESS_LZMA ++ select DECOMPRESS_LZMA_NEEDED + + config SQUASHFS_EMBEDDED + +--- /dev/null ++++ b/include/linux/decompress/bunzip2_mm.h +@@ -0,0 +1,12 @@ ++#ifndef BUNZIP2_MM_H ++#define BUNZIP2_MM_H ++ ++#ifdef STATIC ++/* Code active when included from pre-boot environment: */ ++#define INIT ++#else ++/* Compile for initramfs/initrd code only */ ++#define INIT __init ++#endif ++ ++#endif +--- /dev/null ++++ b/include/linux/decompress/inflate_mm.h +@@ -0,0 +1,12 @@ ++#ifndef INFLATE_MM_H ++#define INFLATE_MM_H ++ ++#ifdef STATIC ++/* Code active when included from pre-boot environment: */ ++#define INIT ++#else ++/* Compile for initramfs/initrd code only */ ++#define INIT __init ++#endif ++ ++#endif +--- a/include/linux/decompress/mm.h ++++ b/include/linux/decompress/mm.h +@@ -53,8 +53,6 @@ static void free(void *where) + + #define set_error_fn(x) + +-#define INIT +- + #else /* STATIC */ + + /* Code active when compiled standalone for use when loading ramdisk: */ +@@ -77,7 +75,6 @@ static void free(void *where) + static void(*error)(char *m); + #define set_error_fn(x) error = x; + +-#define INIT __init + #define STATIC + + #include <linux/init.h> +--- /dev/null ++++ b/include/linux/decompress/unlzma_mm.h +@@ -0,0 +1,20 @@ ++#ifndef UNLZMA_MM_H ++#define UNLZMA_MM_H ++ ++#ifdef STATIC ++ ++/* Code active when included from pre-boot environment: */ ++#define INIT ++ ++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED) ++ ++/* Make it available to non initramfs/initrd code */ ++#define INIT ++#include <linux/module.h> ++#else ++ ++/* Compile for initramfs/initrd code only */ ++#define INIT __init ++#endif ++ ++#endif +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -117,6 +117,9 @@ config DECOMPRESS_BZIP2 + config DECOMPRESS_LZMA + tristate + ++config DECOMPRESS_LZMA_NEEDED ++ boolean ++ + # + # Generic allocator support is selected if needed + # +--- a/lib/decompress_bunzip2.c ++++ b/lib/decompress_bunzip2.c +@@ -52,6 +52,7 @@ + #include <linux/slab.h> + #endif /* STATIC */ + ++#include <linux/decompress/bunzip2_mm.h> + #include <linux/decompress/mm.h> + + #ifndef INT_MAX +--- a/lib/decompress_inflate.c ++++ b/lib/decompress_inflate.c +@@ -23,6 +23,7 @@ + + #endif /* STATIC */ + ++#include <linux/decompress/inflate_mm.h> + #include <linux/decompress/mm.h> + + #define GZIP_IOBUF_SIZE (16*1024) +--- a/lib/decompress_unlzma.c ++++ b/lib/decompress_unlzma.c +@@ -36,6 +36,7 @@ + #include <linux/slab.h> + #endif /* STATIC */ + ++#include <linux/decompress/unlzma_mm.h> + #include <linux/decompress/mm.h> + + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +@@ -523,7 +524,7 @@ static inline void INIT process_bit1(str + + + +-STATIC inline int INIT unlzma(unsigned char *buf, int in_len, ++STATIC int INIT unlzma(unsigned char *buf, int in_len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, +@@ -656,4 +657,6 @@ STATIC int INIT decompress(unsigned char + { + return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn); + } ++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED) ++EXPORT_SYMBOL(unlzma); + #endif diff --git a/target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch b/target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch deleted file mode 100644 index 086adf651..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch +++ /dev/null @@ -1,234 +0,0 @@ ---- a/fs/squashfs/Kconfig -+++ b/fs/squashfs/Kconfig -@@ -1,7 +1,8 @@ - config SQUASHFS - tristate "SquashFS 4.0 - Squashed file system support" - depends on BLOCK -- select ZLIB_INFLATE -+ select CRYPTO -+ select CRYPTO_ZLIB - help - Saying Y here includes support for SquashFS 4.0 (a Compressed - Read-Only File System). Squashfs is a highly compressed read-only ---- 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,8 @@ int squashfs_read_data(struct super_bloc - } - - if (compressed) { -- int zlib_err = 0, zlib_init = 0; -+ int res = 0, decomp_init = 0; -+ struct comp_request req; - - /* - * Uncompress block. -@@ -161,12 +163,13 @@ int squashfs_read_data(struct super_bloc - - mutex_lock(&msblk->read_data_mutex); - -- msblk->stream.avail_out = 0; -- msblk->stream.avail_in = 0; -+ req.avail_out = 0; -+ req.avail_in = 0; - - bytes = length; -+ length = 0; - do { -- if (msblk->stream.avail_in == 0 && k < b) { -+ if (req.avail_in == 0 && k < b) { - avail = min(bytes, msblk->devblksize - offset); - bytes -= avail; - wait_on_buffer(bh[k]); -@@ -179,45 +182,47 @@ int squashfs_read_data(struct super_bloc - continue; - } - -- msblk->stream.next_in = bh[k]->b_data + offset; -- msblk->stream.avail_in = avail; -+ req.next_in = bh[k]->b_data + offset; -+ req.avail_in = avail; - offset = 0; - } - -- if (msblk->stream.avail_out == 0 && page < pages) { -- msblk->stream.next_out = buffer[page++]; -- msblk->stream.avail_out = PAGE_CACHE_SIZE; -+ if (req.avail_out == 0 && page < pages) { -+ req.next_out = buffer[page++]; -+ req.avail_out = PAGE_CACHE_SIZE; - } - -- if (!zlib_init) { -- zlib_err = zlib_inflateInit(&msblk->stream); -- if (zlib_err != Z_OK) { -- ERROR("zlib_inflateInit returned" -- " unexpected result 0x%x," -- " srclength %d\n", zlib_err, -- srclength); -+ if (!decomp_init) { -+ res = crypto_decompress_init(msblk->tfm); -+ if (res) { -+ ERROR("crypto_decompress_init " -+ "returned %d, srclength %d\n", -+ res, srclength); - goto release_mutex; - } -- zlib_init = 1; -+ decomp_init = 1; - } - -- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH); -+ res = crypto_decompress_update(msblk->tfm, &req); -+ if (res < 0) { -+ ERROR("crypto_decompress_update returned %d, " -+ "data probably corrupt\n", res); -+ goto release_mutex; -+ } -+ length += res; - -- if (msblk->stream.avail_in == 0 && k < b) -+ if (req.avail_in == 0 && k < b) - put_bh(bh[k++]); -- } while (zlib_err == Z_OK); -+ } while (bytes || res); - -- if (zlib_err != Z_STREAM_END) { -- ERROR("zlib_inflate error, data probably corrupt\n"); -+ res = crypto_decompress_final(msblk->tfm, &req); -+ if (res < 0) { -+ ERROR("crypto_decompress_final returned %d, data " -+ "probably corrupt\n", res); - goto release_mutex; - } -+ length += res; - -- zlib_err = zlib_inflateEnd(&msblk->stream); -- if (zlib_err != Z_OK) { -- ERROR("zlib_inflate error, data probably corrupt\n"); -- goto release_mutex; -- } -- length = msblk->stream.total_out; - mutex_unlock(&msblk->read_data_mutex); - } else { - /* ---- 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; ---- a/fs/squashfs/super.c -+++ b/fs/squashfs/super.c -@@ -38,11 +38,19 @@ - #include <linux/zlib.h> - #include <linux/magic.h> - -+#include <crypto/compress.h> -+ -+#include <net/netlink.h> -+ - #include "squashfs_fs.h" - #include "squashfs_fs_sb.h" - #include "squashfs_fs_i.h" - #include "squashfs.h" - -+ -+#define SQUASHFS_CRYPTO_ALG "zlib" -+ -+ - static struct file_system_type squashfs_fs_type; - static struct super_operations squashfs_super_ops; - -@@ -76,6 +84,16 @@ static int squashfs_fill_super(struct su - unsigned short flags; - unsigned int fragments; - u64 lookup_table_start; -+ struct { -+ struct nlattr nla; -+ int val; -+ } params = { -+ .nla = { -+ .nla_len = nla_attr_size(sizeof(int)), -+ .nla_type = ZLIB_DECOMP_WINDOWBITS, -+ }, -+ .val = DEF_WBITS, -+ }; - int err; - - TRACE("Entered squashfs_fill_superblock\n"); -@@ -87,16 +105,25 @@ static int squashfs_fill_super(struct su - } - msblk = sb->s_fs_info; - -- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(), -- GFP_KERNEL); -- if (msblk->stream.workspace == NULL) { -- ERROR("Failed to allocate zlib workspace\n"); -+ msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0, -+ CRYPTO_ALG_ASYNC); -+ if (IS_ERR(msblk->tfm)) { -+ ERROR("Failed to load %s crypto module\n", -+ SQUASHFS_CRYPTO_ALG); -+ err = PTR_ERR(msblk->tfm); -+ goto failed_pcomp; -+ } -+ -+ err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -+ if (err) { -+ ERROR("Failed to set up decompression parameters\n"); - goto failure; - } - - sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); - if (sblk == NULL) { - ERROR("Failed to allocate squashfs_super_block\n"); -+ err = -ENOMEM; - goto failure; - } - -@@ -295,17 +322,18 @@ failed_mount: - kfree(msblk->inode_lookup_table); - kfree(msblk->fragment_index); - kfree(msblk->id_table); -- kfree(msblk->stream.workspace); -+ crypto_free_pcomp(msblk->tfm); - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - kfree(sblk); - return err; - - failure: -- kfree(msblk->stream.workspace); -+ crypto_free_pcomp(msblk->tfm); -+failed_pcomp: - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; -- return -ENOMEM; -+ return err; - } - - -@@ -349,7 +377,7 @@ static void squashfs_put_super(struct su - 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; - } diff --git a/target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch b/target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch deleted file mode 100644 index 48eb07de7..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch +++ /dev/null @@ -1,901 +0,0 @@ ---- /dev/null -+++ b/crypto/unlzma.c -@@ -0,0 +1,775 @@ -+/* -+ * LZMA uncompresion module for pcomp -+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> -+ * -+ * Based on: -+ * Initial Linux kernel adaptation -+ * Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ * Based on small lzma deflate implementation/Small range coder -+ * implementation for lzma. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * FIXME: the current implementation assumes that the caller will -+ * not free any output buffers until the whole decompression has been -+ * completed. This is necessary, because LZMA looks back at old output -+ * instead of doing a separate dictionary allocation, which saves RAM. -+ */ -+ -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/vmalloc.h> -+#include <linux/interrupt.h> -+#include <linux/mm.h> -+#include <linux/net.h> -+#include <linux/slab.h> -+#include <linux/kthread.h> -+ -+#include <crypto/internal/compress.h> -+#include <net/netlink.h> -+#include "unlzma.h" -+ -+static int instance = 0; -+ -+struct unlzma_buffer { -+ int offset; -+ int size; -+ u8 *ptr; -+}; -+ -+struct unlzma_ctx { -+ struct task_struct *thread; -+ wait_queue_head_t next_req; -+ wait_queue_head_t req_done; -+ struct mutex mutex; -+ bool waiting; -+ bool active; -+ bool cancel; -+ -+ const u8 *next_in; -+ int avail_in; -+ -+ u8 *next_out; -+ int avail_out; -+ -+ /* reader state */ -+ u32 code; -+ u32 range; -+ u32 bound; -+ -+ /* writer state */ -+ u8 previous_byte; -+ ssize_t pos; -+ int buf_full; -+ int n_buffers; -+ int buffers_max; -+ struct unlzma_buffer *buffers; -+ -+ /* cstate */ -+ int state; -+ u32 rep0, rep1, rep2, rep3; -+ -+ u32 dict_size; -+ -+ void *workspace; -+ int workspace_size; -+}; -+ -+static inline bool -+unlzma_should_stop(struct unlzma_ctx *ctx) -+{ -+ return unlikely(kthread_should_stop() || ctx->cancel); -+} -+ -+static void -+get_buffer(struct unlzma_ctx *ctx) -+{ -+ struct unlzma_buffer *bh; -+ -+ BUG_ON(ctx->n_buffers >= ctx->buffers_max); -+ bh = &ctx->buffers[ctx->n_buffers++]; -+ bh->ptr = ctx->next_out; -+ bh->offset = ctx->pos; -+ bh->size = ctx->avail_out; -+ ctx->buf_full = 0; -+} -+ -+static void -+unlzma_request_buffer(struct unlzma_ctx *ctx, int *avail) -+{ -+ do { -+ ctx->waiting = true; -+ mutex_unlock(&ctx->mutex); -+ wake_up(&ctx->req_done); -+ if (wait_event_interruptible(ctx->next_req, -+ unlzma_should_stop(ctx) || (*avail > 0))) -+ schedule(); -+ mutex_lock(&ctx->mutex); -+ } while (*avail <= 0 && !unlzma_should_stop(ctx)); -+ -+ if (!unlzma_should_stop(ctx) && ctx->buf_full) -+ get_buffer(ctx); -+} -+ -+static u8 -+rc_read(struct unlzma_ctx *ctx) -+{ -+ if (unlikely(ctx->avail_in <= 0)) -+ unlzma_request_buffer(ctx, &ctx->avail_in); -+ -+ if (unlzma_should_stop(ctx)) -+ return 0; -+ -+ ctx->avail_in--; -+ return *(ctx->next_in++); -+} -+ -+ -+static inline void -+rc_get_code(struct unlzma_ctx *ctx) -+{ -+ ctx->code = (ctx->code << 8) | rc_read(ctx); -+} -+ -+static void -+rc_normalize(struct unlzma_ctx *ctx) -+{ -+ if (ctx->range < (1 << RC_TOP_BITS)) { -+ ctx->range <<= 8; -+ rc_get_code(ctx); -+ } -+} -+ -+static int -+rc_is_bit_0(struct unlzma_ctx *ctx, u16 *p) -+{ -+ rc_normalize(ctx); -+ ctx->bound = *p * (ctx->range >> RC_MODEL_TOTAL_BITS); -+ return ctx->code < ctx->bound; -+} -+ -+static void -+rc_update_bit_0(struct unlzma_ctx *ctx, u16 *p) -+{ -+ ctx->range = ctx->bound; -+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; -+} -+ -+static void -+rc_update_bit_1(struct unlzma_ctx *ctx, u16 *p) -+{ -+ ctx->range -= ctx->bound; -+ ctx->code -= ctx->bound; -+ *p -= *p >> RC_MOVE_BITS; -+} -+ -+static bool -+rc_get_bit(struct unlzma_ctx *ctx, u16 *p, int *symbol) -+{ -+ if (rc_is_bit_0(ctx, p)) { -+ rc_update_bit_0(ctx, p); -+ *symbol *= 2; -+ return 0; -+ } else { -+ rc_update_bit_1(ctx, p); -+ *symbol = *symbol * 2 + 1; -+ return 1; -+ } -+} -+ -+static int -+rc_direct_bit(struct unlzma_ctx *ctx) -+{ -+ rc_normalize(ctx); -+ ctx->range >>= 1; -+ if (ctx->code >= ctx->range) { -+ ctx->code -= ctx->range; -+ return 1; -+ } -+ return 0; -+} -+ -+static void -+rc_bit_tree_decode(struct unlzma_ctx *ctx, u16 *p, int num_levels, int *symbol) -+{ -+ int i = num_levels; -+ -+ *symbol = 1; -+ while (i--) -+ rc_get_bit(ctx, p + *symbol, symbol); -+ *symbol -= 1 << num_levels; -+} -+ -+static u8 -+peek_old_byte(struct unlzma_ctx *ctx, u32 offs) -+{ -+ struct unlzma_buffer *bh = &ctx->buffers[ctx->n_buffers - 1]; -+ int i = ctx->n_buffers; -+ u32 pos; -+ -+ if (!ctx->n_buffers) { -+ printk(KERN_ERR "unlzma/%s: no buffer\n", __func__); -+ goto error; -+ } -+ -+ pos = ctx->pos - offs; -+ if (unlikely(pos >= ctx->dict_size)) -+ pos = ~pos & (ctx->dict_size - 1); -+ -+ while (bh->offset > pos) { -+ bh--; -+ i--; -+ if (!i) { -+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); -+ goto error; -+ } -+ } -+ -+ pos -= bh->offset; -+ if (pos >= bh->size) { -+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos); -+ goto error; -+ } -+ -+ return bh->ptr[pos]; -+ -+error: -+ ctx->cancel = true; -+ return 0; -+} -+ -+static void -+write_byte(struct unlzma_ctx *ctx, u8 byte) -+{ -+ if (unlikely(ctx->avail_out <= 0)) { -+ unlzma_request_buffer(ctx, &ctx->avail_out); -+ } -+ -+ if (!ctx->avail_out) -+ return; -+ -+ ctx->previous_byte = byte; -+ *(ctx->next_out++) = byte; -+ ctx->avail_out--; -+ if (ctx->avail_out == 0) -+ ctx->buf_full = 1; -+ ctx->pos++; -+} -+ -+ -+static inline void -+copy_byte(struct unlzma_ctx *ctx, u32 offs) -+{ -+ write_byte(ctx, peek_old_byte(ctx, offs)); -+} -+ -+static void -+copy_bytes(struct unlzma_ctx *ctx, u32 rep0, int len) -+{ -+ do { -+ copy_byte(ctx, rep0); -+ len--; -+ if (unlzma_should_stop(ctx)) -+ break; -+ } while (len != 0); -+} -+ -+static void -+process_bit0(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob, -+ int lc, u32 literal_pos_mask) -+{ -+ int mi = 1; -+ rc_update_bit_0(ctx, prob); -+ prob = (p + LZMA_LITERAL + -+ (LZMA_LIT_SIZE -+ * (((ctx->pos & literal_pos_mask) << lc) -+ + (ctx->previous_byte >> (8 - lc)))) -+ ); -+ -+ if (ctx->state >= LZMA_NUM_LIT_STATES) { -+ int match_byte = peek_old_byte(ctx, ctx->rep0); -+ do { -+ u16 bit; -+ u16 *prob_lit; -+ -+ match_byte <<= 1; -+ bit = match_byte & 0x100; -+ prob_lit = prob + 0x100 + bit + mi; -+ if (rc_get_bit(ctx, prob_lit, &mi) != !!bit) -+ break; -+ } while (mi < 0x100); -+ } -+ while (mi < 0x100) { -+ u16 *prob_lit = prob + mi; -+ rc_get_bit(ctx, prob_lit, &mi); -+ } -+ write_byte(ctx, mi); -+ if (ctx->state < 4) -+ ctx->state = 0; -+ else if (ctx->state < 10) -+ ctx->state -= 3; -+ else -+ ctx->state -= 6; -+} -+ -+static void -+process_bit1(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob) -+{ -+ int offset; -+ u16 *prob_len; -+ int num_bits; -+ int len; -+ -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ ctx->rep3 = ctx->rep2; -+ ctx->rep2 = ctx->rep1; -+ ctx->rep1 = ctx->rep0; -+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 0 : 3; -+ prob = p + LZMA_LEN_CODER; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP_G0 + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ prob = (p + LZMA_IS_REP_0_LONG -+ + (ctx->state << -+ LZMA_NUM_POS_BITS_MAX) + -+ pos_state); -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ -+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? -+ 9 : 11; -+ copy_byte(ctx, ctx->rep0); -+ return; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ } -+ } else { -+ u32 distance; -+ -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP_G1 + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ distance = ctx->rep1; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ prob = p + LZMA_IS_REP_G2 + ctx->state; -+ if (rc_is_bit_0(ctx, prob)) { -+ rc_update_bit_0(ctx, prob); -+ distance = ctx->rep2; -+ } else { -+ rc_update_bit_1(ctx, prob); -+ distance = ctx->rep3; -+ ctx->rep3 = ctx->rep2; -+ } -+ ctx->rep2 = ctx->rep1; -+ } -+ ctx->rep1 = ctx->rep0; -+ ctx->rep0 = distance; -+ } -+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 8 : 11; -+ prob = p + LZMA_REP_LEN_CODER; -+ } -+ -+ prob_len = prob + LZMA_LEN_CHOICE; -+ if (rc_is_bit_0(ctx, prob_len)) { -+ rc_update_bit_0(ctx, prob_len); -+ prob_len = (prob + LZMA_LEN_LOW -+ + (pos_state << -+ LZMA_LEN_NUM_LOW_BITS)); -+ offset = 0; -+ num_bits = LZMA_LEN_NUM_LOW_BITS; -+ } else { -+ rc_update_bit_1(ctx, prob_len); -+ prob_len = prob + LZMA_LEN_CHOICE_2; -+ if (rc_is_bit_0(ctx, prob_len)) { -+ rc_update_bit_0(ctx, prob_len); -+ prob_len = (prob + LZMA_LEN_MID -+ + (pos_state << -+ LZMA_LEN_NUM_MID_BITS)); -+ offset = 1 << LZMA_LEN_NUM_LOW_BITS; -+ num_bits = LZMA_LEN_NUM_MID_BITS; -+ } else { -+ rc_update_bit_1(ctx, prob_len); -+ prob_len = prob + LZMA_LEN_HIGH; -+ offset = ((1 << LZMA_LEN_NUM_LOW_BITS) -+ + (1 << LZMA_LEN_NUM_MID_BITS)); -+ num_bits = LZMA_LEN_NUM_HIGH_BITS; -+ } -+ } -+ -+ rc_bit_tree_decode(ctx, prob_len, num_bits, &len); -+ len += offset; -+ -+ if (ctx->state < 4) { -+ int pos_slot; -+ -+ ctx->state += LZMA_NUM_LIT_STATES; -+ prob = -+ p + LZMA_POS_SLOT + -+ ((len < -+ LZMA_NUM_LEN_TO_POS_STATES ? len : -+ LZMA_NUM_LEN_TO_POS_STATES - 1) -+ << LZMA_NUM_POS_SLOT_BITS); -+ rc_bit_tree_decode(ctx, prob, -+ LZMA_NUM_POS_SLOT_BITS, -+ &pos_slot); -+ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { -+ int i, mi; -+ num_bits = (pos_slot >> 1) - 1; -+ ctx->rep0 = 2 | (pos_slot & 1); -+ if (pos_slot < LZMA_END_POS_MODEL_INDEX) { -+ ctx->rep0 <<= num_bits; -+ prob = p + LZMA_SPEC_POS + -+ ctx->rep0 - pos_slot - 1; -+ } else { -+ num_bits -= LZMA_NUM_ALIGN_BITS; -+ while (num_bits--) -+ ctx->rep0 = (ctx->rep0 << 1) | -+ rc_direct_bit(ctx); -+ prob = p + LZMA_ALIGN; -+ ctx->rep0 <<= LZMA_NUM_ALIGN_BITS; -+ num_bits = LZMA_NUM_ALIGN_BITS; -+ } -+ i = 1; -+ mi = 1; -+ while (num_bits--) { -+ if (rc_get_bit(ctx, prob + mi, &mi)) -+ ctx->rep0 |= i; -+ i <<= 1; -+ } -+ } else -+ ctx->rep0 = pos_slot; -+ if (++(ctx->rep0) == 0) -+ return; -+ } -+ -+ len += LZMA_MATCH_MIN_LEN; -+ -+ copy_bytes(ctx, ctx->rep0, len); -+} -+ -+ -+static int -+do_unlzma(struct unlzma_ctx *ctx) -+{ -+ u8 hdr_buf[sizeof(struct lzma_header)]; -+ struct lzma_header *header = (struct lzma_header *)hdr_buf; -+ u32 pos_state_mask; -+ u32 literal_pos_mask; -+ int lc, pb, lp; -+ int num_probs; -+ int i, mi; -+ u16 *p; -+ -+ for (i = 0; i < sizeof(struct lzma_header); i++) { -+ hdr_buf[i] = rc_read(ctx); -+ } -+ -+ ctx->n_buffers = 0; -+ ctx->pos = 0; -+ get_buffer(ctx); -+ ctx->active = true; -+ ctx->state = 0; -+ ctx->rep0 = ctx->rep1 = ctx->rep2 = ctx->rep3 = 1; -+ -+ ctx->previous_byte = 0; -+ ctx->code = 0; -+ ctx->range = 0xFFFFFFFF; -+ -+ ctx->dict_size = le32_to_cpu(header->dict_size); -+ -+ if (header->pos >= (9 * 5 * 5)) -+ return -1; -+ -+ mi = 0; -+ lc = header->pos; -+ while (lc >= 9) { -+ mi++; -+ lc -= 9; -+ } -+ pb = 0; -+ lp = mi; -+ while (lp >= 5) { -+ pb++; -+ lp -= 5; -+ } -+ pos_state_mask = (1 << pb) - 1; -+ literal_pos_mask = (1 << lp) - 1; -+ -+ if (ctx->dict_size == 0) -+ ctx->dict_size = 1; -+ -+ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)); -+ if (ctx->workspace_size < num_probs * sizeof(*p)) { -+ if (ctx->workspace) -+ vfree(ctx->workspace); -+ ctx->workspace_size = num_probs * sizeof(*p); -+ ctx->workspace = vmalloc(ctx->workspace_size); -+ } -+ p = (u16 *) ctx->workspace; -+ if (!p) -+ return -1; -+ -+ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); -+ for (i = 0; i < num_probs; i++) -+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; -+ -+ for (i = 0; i < 5; i++) -+ rc_get_code(ctx); -+ -+ while (1) { -+ int pos_state = ctx->pos & pos_state_mask; -+ u16 *prob = p + LZMA_IS_MATCH + -+ (ctx->state << LZMA_NUM_POS_BITS_MAX) + pos_state; -+ if (rc_is_bit_0(ctx, prob)) -+ process_bit0(ctx, p, pos_state, prob, -+ lc, literal_pos_mask); -+ else { -+ process_bit1(ctx, p, pos_state, prob); -+ if (ctx->rep0 == 0) -+ break; -+ } -+ if (unlzma_should_stop(ctx)) -+ break; -+ } -+ if (likely(!unlzma_should_stop(ctx))) -+ rc_normalize(ctx); -+ -+ return ctx->pos; -+} -+ -+ -+static void -+unlzma_reset_buf(struct unlzma_ctx *ctx) -+{ -+ ctx->avail_in = 0; -+ ctx->next_in = NULL; -+ ctx->avail_out = 0; -+ ctx->next_out = NULL; -+} -+ -+static int -+unlzma_thread(void *data) -+{ -+ struct unlzma_ctx *ctx = data; -+ -+ mutex_lock(&ctx->mutex); -+ do { -+ if (do_unlzma(ctx) < 0) -+ ctx->pos = 0; -+ unlzma_reset_buf(ctx); -+ ctx->cancel = false; -+ ctx->active = false; -+ } while (!kthread_should_stop()); -+ mutex_unlock(&ctx->mutex); -+ return 0; -+} -+ -+ -+static int -+unlzma_init(struct crypto_tfm *tfm) -+{ -+ return 0; -+} -+ -+static void -+unlzma_cancel(struct unlzma_ctx *ctx) -+{ -+ unlzma_reset_buf(ctx); -+ -+ if (!ctx->active) -+ return; -+ -+ ctx->cancel = true; -+ do { -+ mutex_unlock(&ctx->mutex); -+ wake_up(&ctx->next_req); -+ schedule(); -+ mutex_lock(&ctx->mutex); -+ } while (ctx->cancel); -+} -+ -+ -+static void -+unlzma_exit(struct crypto_tfm *tfm) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ if (ctx->thread) { -+ unlzma_cancel(ctx); -+ kthread_stop(ctx->thread); -+ ctx->thread = NULL; -+ if (ctx->buffers) -+ kfree(ctx->buffers); -+ ctx->buffers_max = 0; -+ ctx->buffers = NULL; -+ } -+} -+ -+static int -+unlzma_decompress_setup(struct crypto_pcomp *tfm, void *p, unsigned int len) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); -+ struct nlattr *tb[UNLZMA_DECOMP_MAX + 1]; -+ int ret = 0; -+ -+ if (ctx->thread) -+ return -EINVAL; -+ -+ if (!p) -+ return -EINVAL; -+ -+ ret = nla_parse(tb, UNLZMA_DECOMP_MAX, p, len, NULL); -+ if (ret) -+ return ret; -+ -+ if (!tb[UNLZMA_DECOMP_OUT_BUFFERS]) -+ return -EINVAL; -+ -+ if (ctx->buffers_max && (ctx->buffers_max < -+ nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]))) { -+ kfree(ctx->buffers); -+ ctx->buffers_max = 0; -+ ctx->buffers = NULL; -+ } -+ if (!ctx->buffers) { -+ ctx->buffers_max = nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]); -+ ctx->buffers = kzalloc(sizeof(struct unlzma_buffer) * ctx->buffers_max, GFP_KERNEL); -+ } -+ if (!ctx->buffers) -+ return -ENOMEM; -+ -+ ctx->waiting = false; -+ mutex_init(&ctx->mutex); -+ init_waitqueue_head(&ctx->next_req); -+ init_waitqueue_head(&ctx->req_done); -+ ctx->thread = kthread_run(unlzma_thread, ctx, "unlzma/%d", instance++); -+ if (IS_ERR(ctx->thread)) { -+ ret = PTR_ERR(ctx->thread); -+ ctx->thread = NULL; -+ } -+ -+ return ret; -+} -+ -+static int -+unlzma_decompress_init(struct crypto_pcomp *tfm) -+{ -+ return 0; -+} -+ -+static void -+unlzma_wait_complete(struct unlzma_ctx *ctx, bool finish) -+{ -+ DEFINE_WAIT(__wait); -+ -+ do { -+ wake_up(&ctx->next_req); -+ prepare_to_wait(&ctx->req_done, &__wait, TASK_INTERRUPTIBLE); -+ mutex_unlock(&ctx->mutex); -+ schedule(); -+ mutex_lock(&ctx->mutex); -+ } while (!ctx->waiting && ctx->active); -+ finish_wait(&ctx->req_done, &__wait); -+} -+ -+static int -+unlzma_decompress_update(struct crypto_pcomp *tfm, struct comp_request *req) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); -+ size_t pos = 0; -+ -+ mutex_lock(&ctx->mutex); -+ if (!ctx->active && !req->avail_in) -+ goto out; -+ -+ pos = ctx->pos; -+ ctx->waiting = false; -+ ctx->next_in = req->next_in; -+ ctx->avail_in = req->avail_in; -+ ctx->next_out = req->next_out; -+ ctx->avail_out = req->avail_out; -+ -+ unlzma_wait_complete(ctx, false); -+ -+ req->next_in = ctx->next_in; -+ req->avail_in = ctx->avail_in; -+ req->next_out = ctx->next_out; -+ req->avail_out = ctx->avail_out; -+ ctx->next_in = 0; -+ ctx->avail_in = 0; -+ pos = ctx->pos - pos; -+ -+out: -+ mutex_unlock(&ctx->mutex); -+ if (ctx->cancel) -+ return -EINVAL; -+ -+ return pos; -+} -+ -+static int -+unlzma_decompress_final(struct crypto_pcomp *tfm, struct comp_request *req) -+{ -+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); -+ int ret = 0; -+ -+ /* cancel pending operation */ -+ mutex_lock(&ctx->mutex); -+ if (ctx->active) { -+ // ret = -EINVAL; -+ unlzma_cancel(ctx); -+ } -+ ctx->pos = 0; -+ mutex_unlock(&ctx->mutex); -+ return ret; -+} -+ -+ -+static struct pcomp_alg unlzma_alg = { -+ .decompress_setup = unlzma_decompress_setup, -+ .decompress_init = unlzma_decompress_init, -+ .decompress_update = unlzma_decompress_update, -+ .decompress_final = unlzma_decompress_final, -+ -+ .base = { -+ .cra_name = "lzma", -+ .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS, -+ .cra_ctxsize = sizeof(struct unlzma_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_init = unlzma_init, -+ .cra_exit = unlzma_exit, -+ } -+}; -+ -+static int __init -+unlzma_mod_init(void) -+{ -+ return crypto_register_pcomp(&unlzma_alg); -+} -+ -+static void __exit -+unlzma_mod_exit(void) -+{ -+ crypto_unregister_pcomp(&unlzma_alg); -+} -+ -+module_init(unlzma_mod_init); -+module_exit(unlzma_mod_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("LZMA Decompression Algorithm"); -+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -768,6 +768,12 @@ config CRYPTO_ZLIB - help - This is the zlib algorithm. - -+config CRYPTO_UNLZMA -+ tristate "LZMA decompression" -+ select CRYPTO_PCOMP -+ help -+ This is the lzma decompression module. -+ - config CRYPTO_LZO - tristate "LZO compression algorithm" - select CRYPTO_ALGAPI ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -75,6 +75,7 @@ obj-$(CONFIG_CRYPTO_SEED) += seed.o - obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o - obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o - obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o -+obj-$(CONFIG_CRYPTO_UNLZMA) += unlzma.o - obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o - obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o - obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o ---- /dev/null -+++ b/crypto/unlzma.h -@@ -0,0 +1,80 @@ -+/* LZMA uncompresion module for pcomp -+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> -+ * -+ * Based on: -+ * Initial Linux kernel adaptation -+ * Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ * Based on small lzma deflate implementation/Small range coder -+ * implementation for lzma. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+#ifndef __UNLZMA_H -+#define __UNLZMA_H -+ -+struct lzma_header { -+ __u8 pos; -+ __le32 dict_size; -+} __attribute__ ((packed)) ; -+ -+ -+#define RC_TOP_BITS 24 -+#define RC_MOVE_BITS 5 -+#define RC_MODEL_TOTAL_BITS 11 -+ -+#define LZMA_BASE_SIZE 1846 -+#define LZMA_LIT_SIZE 768 -+ -+#define LZMA_NUM_POS_BITS_MAX 4 -+ -+#define LZMA_LEN_NUM_LOW_BITS 3 -+#define LZMA_LEN_NUM_MID_BITS 3 -+#define LZMA_LEN_NUM_HIGH_BITS 8 -+ -+#define LZMA_LEN_CHOICE 0 -+#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) -+#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) -+#define LZMA_LEN_MID (LZMA_LEN_LOW \ -+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) -+#define LZMA_LEN_HIGH (LZMA_LEN_MID \ -+ +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) -+#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) -+ -+#define LZMA_NUM_STATES 12 -+#define LZMA_NUM_LIT_STATES 7 -+ -+#define LZMA_START_POS_MODEL_INDEX 4 -+#define LZMA_END_POS_MODEL_INDEX 14 -+#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) -+ -+#define LZMA_NUM_POS_SLOT_BITS 6 -+#define LZMA_NUM_LEN_TO_POS_STATES 4 -+ -+#define LZMA_NUM_ALIGN_BITS 4 -+ -+#define LZMA_MATCH_MIN_LEN 2 -+ -+#define LZMA_IS_MATCH 0 -+#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) -+#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ -+ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_SPEC_POS (LZMA_POS_SLOT \ -+ +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) -+#define LZMA_ALIGN (LZMA_SPEC_POS \ -+ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) -+#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) -+#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) -+#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) -+ -+#endif ---- a/include/crypto/compress.h -+++ b/include/crypto/compress.h -@@ -49,6 +49,12 @@ enum zlib_decomp_params { - - #define ZLIB_DECOMP_MAX (__ZLIB_DECOMP_MAX - 1) - -+enum unlzma_decomp_params { -+ UNLZMA_DECOMP_OUT_BUFFERS = 1, /* naximum number of output buffers */ -+ __UNLZMA_DECOMP_MAX, -+}; -+#define UNLZMA_DECOMP_MAX (__UNLZMA_DECOMP_MAX - 1) -+ - - struct crypto_pcomp { - struct crypto_tfm base; diff --git a/target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch b/target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch deleted file mode 100644 index 2725f0669..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch +++ /dev/null @@ -1,244 +0,0 @@ ---- a/fs/squashfs/Kconfig -+++ b/fs/squashfs/Kconfig -@@ -2,7 +2,6 @@ config SQUASHFS - tristate "SquashFS 4.0 - Squashed file system support" - depends on BLOCK - 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 -@@ -37,6 +36,26 @@ config SQUASHFS_EMBEDDED - - If unsure, say N. - -+config SQUASHFS_SUPPORT_ZLIB -+ bool -+ prompt "Support ZLIB compression" if SQUASHFS_SUPPORT_LZMA -+ depends on SQUASHFS -+ select CRYPTO_ZLIB -+ default y -+ help -+ ZLIB is the default compression used in squashfs. If you are -+ using LZMA compression instead, you can remove support for ZLIB -+ entirely. -+ -+config SQUASHFS_SUPPORT_LZMA -+ bool "Support LZMA compression" -+ depends on SQUASHFS -+ select CRYPTO_UNLZMA -+ help -+ By default SquashFS uses ZLIB compression, however (if your tools -+ support it, you can use LZMA instead, which saves space. -+ -+ - config SQUASHFS_FRAGMENT_CACHE_SIZE - int "Number of fragments cached" if SQUASHFS_EMBEDDED - depends on SQUASHFS ---- a/fs/squashfs/squashfs_fs.h -+++ b/fs/squashfs/squashfs_fs.h -@@ -212,6 +212,7 @@ struct meta_index { - * definitions for structures on disk - */ - #define ZLIB_COMPRESSION 1 -+#define LZMA_COMPRESSION 2 - - struct squashfs_super_block { - __le32 s_magic; ---- a/fs/squashfs/super.c -+++ b/fs/squashfs/super.c -@@ -48,13 +48,76 @@ - #include "squashfs.h" - - --#define SQUASHFS_CRYPTO_ALG "zlib" -+static int squashfs_setup_zlib(struct squashfs_sb_info *msblk) -+{ -+ int err = -EOPNOTSUPP; -+ -+#ifdef CONFIG_SQUASHFS_SUPPORT_ZLIB -+ struct { -+ struct nlattr nla; -+ int val; -+ } params = { -+ .nla = { -+ .nla_len = nla_attr_size(sizeof(int)), -+ .nla_type = ZLIB_DECOMP_WINDOWBITS, -+ }, -+ .val = DEF_WBITS, -+ }; -+ -+ msblk->tfm = crypto_alloc_pcomp("zlib", 0, -+ CRYPTO_ALG_ASYNC); -+ if (IS_ERR(msblk->tfm)) { -+ ERROR("Failed to load zlib crypto module\n"); -+ return PTR_ERR(msblk->tfm); -+ } -+ -+ err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -+ if (err) { -+ ERROR("Failed to set up decompression parameters\n"); -+ crypto_free_pcomp(msblk->tfm); -+ } -+#endif -+ -+ return err; -+} -+ -+static int squashfs_setup_lzma(struct squashfs_sb_info *msblk) -+{ -+ int err = -EOPNOTSUPP; -+ -+#ifdef CONFIG_SQUASHFS_SUPPORT_LZMA -+ struct { -+ struct nlattr nla; -+ int val; -+ } params = { -+ .nla = { -+ .nla_len = nla_attr_size(sizeof(int)), -+ .nla_type = UNLZMA_DECOMP_OUT_BUFFERS, -+ }, -+ .val = (msblk->block_size / PAGE_CACHE_SIZE) + 1 -+ }; - -+ msblk->tfm = crypto_alloc_pcomp("lzma", 0, -+ CRYPTO_ALG_ASYNC); -+ if (IS_ERR(msblk->tfm)) { -+ ERROR("Failed to load lzma crypto module\n"); -+ return PTR_ERR(msblk->tfm); -+ } -+ -+ err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -+ if (err) { -+ ERROR("Failed to set up decompression parameters\n"); -+ crypto_free_pcomp(msblk->tfm); -+ } -+#endif -+ -+ return err; -+} - - static struct file_system_type squashfs_fs_type; - static struct super_operations squashfs_super_ops; - --static int supported_squashfs_filesystem(short major, short minor, short comp) -+static int supported_squashfs_filesystem(short major, short minor) - { - if (major < SQUASHFS_MAJOR) { - ERROR("Major/Minor mismatch, older Squashfs %d.%d " -@@ -67,9 +130,6 @@ static int supported_squashfs_filesystem - return -EINVAL; - } - -- if (comp != ZLIB_COMPRESSION) -- return -EINVAL; -- - return 0; - } - -@@ -84,16 +144,6 @@ static int squashfs_fill_super(struct su - unsigned short flags; - unsigned int fragments; - u64 lookup_table_start; -- struct { -- struct nlattr nla; -- int val; -- } params = { -- .nla = { -- .nla_len = nla_attr_size(sizeof(int)), -- .nla_type = ZLIB_DECOMP_WINDOWBITS, -- }, -- .val = DEF_WBITS, -- }; - int err; - - TRACE("Entered squashfs_fill_superblock\n"); -@@ -105,21 +155,6 @@ static int squashfs_fill_super(struct su - } - msblk = sb->s_fs_info; - -- msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0, -- CRYPTO_ALG_ASYNC); -- if (IS_ERR(msblk->tfm)) { -- ERROR("Failed to load %s crypto module\n", -- SQUASHFS_CRYPTO_ALG); -- err = PTR_ERR(msblk->tfm); -- goto failed_pcomp; -- } -- -- err = crypto_decompress_setup(msblk->tfm, ¶ms, sizeof(params)); -- if (err) { -- ERROR("Failed to set up decompression parameters\n"); -- goto failure; -- } -- - sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); - if (sblk == NULL) { - ERROR("Failed to allocate squashfs_super_block\n"); -@@ -157,10 +192,28 @@ static int squashfs_fill_super(struct su - goto failed_mount; - } - -+ /* Check block size for sanity */ -+ msblk->block_size = le32_to_cpu(sblk->block_size); -+ if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE) -+ goto failed_mount; -+ - /* Check the MAJOR & MINOR versions and compression type */ - err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major), -- le16_to_cpu(sblk->s_minor), -- le16_to_cpu(sblk->compression)); -+ le16_to_cpu(sblk->s_minor)); -+ if (err < 0) -+ goto failed_mount; -+ -+ switch(le16_to_cpu(sblk->compression)) { -+ case ZLIB_COMPRESSION: -+ err = squashfs_setup_zlib(msblk); -+ break; -+ case LZMA_COMPRESSION: -+ err = squashfs_setup_lzma(msblk); -+ break; -+ default: -+ err = -EINVAL; -+ break; -+ } - if (err < 0) - goto failed_mount; - -@@ -180,11 +233,6 @@ static int squashfs_fill_super(struct su - i_size_read(sb->s_bdev->bd_inode)) - goto failed_mount; - -- /* Check block size for sanity */ -- msblk->block_size = le32_to_cpu(sblk->block_size); -- if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE) -- goto failed_mount; -- - /* - * Check the system page size is not larger than the filesystem - * block size (by default 128K). This is currently not supported. -@@ -316,21 +364,16 @@ allocate_root: - return 0; - - failed_mount: -+ if (msblk->tfm) -+ crypto_free_pcomp(msblk->tfm); - squashfs_cache_delete(msblk->block_cache); - squashfs_cache_delete(msblk->fragment_cache); - squashfs_cache_delete(msblk->read_page); - kfree(msblk->inode_lookup_table); - kfree(msblk->fragment_index); - kfree(msblk->id_table); -- crypto_free_pcomp(msblk->tfm); -- kfree(sb->s_fs_info); -- sb->s_fs_info = NULL; - kfree(sblk); -- return err; -- - failure: -- crypto_free_pcomp(msblk->tfm); --failed_pcomp: - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - return err; |