Switch to the squashfs-lzma code from the squashfs-devel git tree.
authorImre Kaloz <kaloz@openwrt.org>
Mon, 2 Nov 2009 09:51:35 +0000 (09:51 +0000)
committerImre Kaloz <kaloz@openwrt.org>
Mon, 2 Nov 2009 09:51:35 +0000 (09:51 +0000)
SVN-Revision: 18267

24 files changed:
target/linux/generic-2.6/config-2.6.30
target/linux/generic-2.6/config-2.6.31
target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch [deleted file]
target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch [deleted file]
target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch [deleted file]
target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch [deleted file]
target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch [deleted file]
target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch [deleted file]
target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch [deleted file]

index 403cc54d72430df971f52211b57009c3fb5b8ee3..8e590b76604e885755b0468edeb96c2d81955321 100644 (file)
@@ -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
index e60f993a15e9391f9c8dbd3786a88da8a72f6fa2..3b4bed5e48a9e0d68e151890bff2d7face232a18 100644 (file)
@@ -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 (file)
index 0000000..33572b8
--- /dev/null
@@ -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 (file)
index 0000000..9409679
--- /dev/null
@@ -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 (file)
index 0000000..857834f
--- /dev/null
@@ -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 (file)
index 0000000..db2fe53
--- /dev/null
@@ -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 (file)
index 0000000..a378c00
--- /dev/null
@@ -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 (file)
index 0000000..0991681
--- /dev/null
@@ -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 (file)
index 0000000..9fd5797
--- /dev/null
@@ -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 (file)
index 0000000..64705d2
--- /dev/null
@@ -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 (file)
index abad724..0000000
+++ /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 (file)
index fc2a731..0000000
+++ /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, &params, sizeof(params));
-+      if (err) {
-+              ERROR("Failed to set up decompression parameters\n");
-               goto failure;
-       }
-       sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
-       if (sblk == NULL) {
-               ERROR("Failed to allocate squashfs_super_block\n");
-+              err = -ENOMEM;
-               goto failure;
-       }
-@@ -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 (file)
index d20285c..0000000
+++ /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 (file)
index 19deb73..0000000
+++ /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, &params, 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, &params, 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, &params, sizeof(params));
--      if (err) {
--              ERROR("Failed to set up decompression parameters\n");
--              goto failure;
--      }
--
-       sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
-       if (sblk == NULL) {
-               ERROR("Failed to allocate squashfs_super_block\n");
-@@ -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 (file)
index 0000000..9409679
--- /dev/null
@@ -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 (file)
index 0000000..eacbb97
--- /dev/null
@@ -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 (file)
index 0000000..cbfbf53
--- /dev/null
@@ -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 (file)
index 0000000..a378c00
--- /dev/null
@@ -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 (file)
index 0000000..0991681
--- /dev/null
@@ -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 (file)
index 0000000..9fd5797
--- /dev/null
@@ -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 (file)
index 0000000..aa6c110
--- /dev/null
@@ -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 (file)
index 086adf6..0000000
+++ /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, &params, sizeof(params));
-+      if (err) {
-+              ERROR("Failed to set up decompression parameters\n");
-               goto failure;
-       }
-       sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
-       if (sblk == NULL) {
-               ERROR("Failed to allocate squashfs_super_block\n");
-+              err = -ENOMEM;
-               goto failure;
-       }
-@@ -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 (file)
index 48eb07d..0000000
+++ /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 (file)
index 2725f06..0000000
+++ /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, &params, 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, &params, 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, &params, sizeof(params));
--      if (err) {
--              ERROR("Failed to set up decompression parameters\n");
--              goto failure;
--      }
--
-       sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
-       if (sblk == NULL) {
-               ERROR("Failed to allocate squashfs_super_block\n");
-@@ -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;