]> git.pld-linux.org Git - packages/kernel.git/commitdiff
- lzma support for squashfs
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Sun, 13 Dec 2009 19:27:52 +0000 (19:27 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    kernel-patches.config -> 1.5
    kernel-squashfs-lzma.patch -> 1.1
    kernel.spec -> 1.737

kernel-patches.config
kernel-squashfs-lzma.patch [new file with mode: 0644]
kernel.spec

index 5059506790cd66c53284442085886921921ab2e8..57d86813f4acbd06a07cf3d374d7ec7335564439 100644 (file)
@@ -24,6 +24,7 @@ UNION_FS_DEBUG all=n
 SQUASHFS all=m
 SQUASHFS_EMBEDDED all=n
 SQUASHFS_FRAGMENT_CACHE_SIZE all=3
+SQUASHFS_LZMA all=y
 
 AUFS all=m
 AUFS_BRANCH_MAX_127 all=n
diff --git a/kernel-squashfs-lzma.patch b/kernel-squashfs-lzma.patch
new file mode 100644 (file)
index 0000000..a60734b
--- /dev/null
@@ -0,0 +1,1446 @@
+diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
+index 25a00d1..7ec5d7e 100644
+--- a/fs/squashfs/Kconfig
++++ b/fs/squashfs/Kconfig
+@@ -26,6 +26,12 @@ config SQUASHFS
+         If unsure, say N.
++config SQUASHFS_LZMA
++      bool "Include support for LZMA compressed file systems"
++      depends on SQUASHFS
++      select DECOMPRESS_LZMA
++      select DECOMPRESS_LZMA_NEEDED
++
+ config SQUASHFS_EMBEDDED
+       bool "Additional option for memory-constrained systems" 
+diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
+index 70e3244..45aaefd 100644
+--- a/fs/squashfs/Makefile
++++ b/fs/squashfs/Makefile
+@@ -4,4 +4,5 @@
+ 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 decompressor.o
++squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o
+diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
+index 2a79603..6f9914d 100644
+--- a/fs/squashfs/block.c
++++ b/fs/squashfs/block.c
+@@ -29,16 +29,14 @@
+ #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>
+ #include "squashfs_fs.h"
+ #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.
+@@ -153,72 +151,10 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
+       }
+       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 = squashfs_decompress(msblk, buffer, bh, b, offset,
++                      length, srclength, pages);
++              if (length < 0)
++                      goto read_failure;
+       } else {
+               /*
+                * Block is uncompressed.
+@@ -255,9 +191,6 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
+       kfree(bh);
+       return length;
+-release_mutex:
+-      mutex_unlock(&msblk->read_data_mutex);
+-
+ block_release:
+       for (; k < b; k++)
+               put_bh(bh[k]);
+diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
+index 40c98fa..57314be 100644
+--- 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"
+diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
+new file mode 100644
+index 0000000..0b6ad9b
+--- /dev/null
++++ b/fs/squashfs/decompressor.c
+@@ -0,0 +1,72 @@
++/*
++ * 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_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,
++#ifdef CONFIG_SQUASHFS_LZMA
++      &squashfs_lzma_comp_ops,
++#else
++      &squashfs_lzma_unsupported_comp_ops,
++#endif
++      &squashfs_lzo_unsupported_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];
++}
+diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
+new file mode 100644
+index 0000000..7425f80
+--- /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)(struct squashfs_sb_info *);
++      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(msblk);
++}
++
++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
+diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
+index 566b0ea..12b933a 100644
+--- 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"
+diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c
+index 2b1b8fe..7f93d5a 100644
+--- 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"
+diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
+index 717767d..a25c506 100644
+--- 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"
+diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
+index b5a2c15..7c90bbd 100644
+--- 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"
+diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c
+index 3795b83..b7f64bc 100644
+--- 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"
+diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
+index 9101dbd..49daaf6 100644
+--- 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"
+diff --git a/fs/squashfs/lzma_wrapper.c b/fs/squashfs/lzma_wrapper.c
+new file mode 100644
+index 0000000..9fa617d
+--- /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
++};
++
+diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
+index 9e39865..5266bd8 100644
+--- 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"
+diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
+index 0e9feb6..d094886 100644
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *,
+                               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);
+@@ -71,7 +74,7 @@ extern struct inode *squashfs_iget(struct super_block *, long long,
+ extern int squashfs_read_inode(struct inode *, long long);
+ /*
+- * Inodes and files operations
++ * Inodes, files and decompressor operations
+  */
+ /* dir.c */
+@@ -88,3 +91,9 @@ extern const struct inode_operations squashfs_dir_inode_ops;
+ /* symlink.c */
+ extern const struct address_space_operations squashfs_symlink_aops;
++
++/* 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/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
+index 283daaf..36e1604 100644
+--- 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/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
+index c8c6561..7533350 100644
+--- 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;
+-      z_stream                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
+diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
+index 6c197ef..3550aec 100644
+--- a/fs/squashfs/super.c
++++ b/fs/squashfs/super.c
+@@ -35,34 +35,41 @@
+ #include <linux/pagemap.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/zlib.h>
+ #include <linux/magic.h>
+ #include "squashfs_fs.h"
+ #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 const 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;
+ }
+@@ -87,13 +94,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
+       }
+       msblk = sb->s_fs_info;
+-      msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
+-              GFP_KERNEL);
+-      if (msblk->stream.workspace == NULL) {
+-              ERROR("Failed to allocate zlib workspace\n");
+-              goto failure;
+-      }
+-
+       sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
+       if (sblk == NULL) {
+               ERROR("Failed to allocate squashfs_super_block\n");
+@@ -120,25 +120,25 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
+               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.
+@@ -205,6 +205,10 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
+       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)
+@@ -292,17 +296,16 @@ failed_mount:
+       squashfs_cache_delete(msblk->block_cache);
+       squashfs_cache_delete(msblk->fragment_cache);
+       squashfs_cache_delete(msblk->read_page);
++      squashfs_decompressor_free(msblk, 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);
+       kfree(sb->s_fs_info);
+       sb->s_fs_info = NULL;
+       return -ENOMEM;
+@@ -346,10 +349,10 @@ static void squashfs_put_super(struct super_block *sb)
+               squashfs_cache_delete(sbi->block_cache);
+               squashfs_cache_delete(sbi->fragment_cache);
+               squashfs_cache_delete(sbi->read_page);
++              squashfs_decompressor_free(sbi, 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;
+       }
+diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
+index 83d8788..e80be20 100644
+--- 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"
+diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
+new file mode 100644
+index 0000000..4dd70e0
+--- /dev/null
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -0,0 +1,150 @@
++/*
++ * 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"
++#include "decompressor.h"
++
++static void *zlib_init(struct squashfs_sb_info *dummy)
++{
++      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;
++}
++
++
++static void zlib_free(void *strm)
++{
++      z_stream *stream = strm;
++
++      if (stream)
++              kfree(stream->workspace);
++      kfree(stream);
++}
++
++
++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)
++{
++      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);
++
++      stream->avail_out = 0;
++      stream->avail_in = 0;
++
++      bytes = length;
++      do {
++              if (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;
++                      }
++
++                      stream->next_in = bh[k]->b_data + offset;
++                      stream->avail_in = avail;
++                      offset = 0;
++              }
++
++              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(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(stream, Z_SYNC_FLUSH);
++
++              if (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(stream);
++      if (zlib_err != Z_OK) {
++              ERROR("zlib_inflate error, data probably corrupt\n");
++              goto release_mutex;
++      }
++
++      mutex_unlock(&msblk->read_data_mutex);
++      return stream->total_out;
++
++release_mutex:
++      mutex_unlock(&msblk->read_data_mutex);
++
++      for (; k < b; k++)
++              put_bh(bh[k]);
++
++      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/include/linux/decompress/bunzip2_mm.h b/include/linux/decompress/bunzip2_mm.h
+new file mode 100644
+index 0000000..863efd0
+--- /dev/null
++++ b/include/linux/decompress/bunzip2_mm.h
+@@ -0,0 +1,13 @@
++#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
++static void(*error)(char *m);
++#endif
++
++#endif
+diff --git a/include/linux/decompress/inflate_mm.h b/include/linux/decompress/inflate_mm.h
+new file mode 100644
+index 0000000..87a742b
+--- /dev/null
++++ b/include/linux/decompress/inflate_mm.h
+@@ -0,0 +1,13 @@
++#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
++static void(*error)(char *m);
++#endif
++
++#endif
+diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h
+index 12ff8c3..44f6e14 100644
+--- a/include/linux/decompress/mm.h
++++ b/include/linux/decompress/mm.h
+@@ -25,7 +25,7 @@ static void *malloc(int size)
+       void *p;
+       if (size < 0)
+-              error("Malloc error");
++              return NULL;
+       if (!malloc_ptr)
+               malloc_ptr = free_mem_ptr;
+@@ -35,7 +35,7 @@ static void *malloc(int size)
+       malloc_ptr += size;
+       if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
+-              error("Out of memory");
++              return NULL;
+       malloc_count++;
+       return p;
+@@ -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: */
+@@ -74,10 +72,8 @@ static void free(void *where)
+ #define large_malloc(a) vmalloc(a)
+ #define large_free(a) vfree(a)
+-static void(*error)(char *m);
+ #define set_error_fn(x) error = x;
+-#define INIT __init
+ #define STATIC
+ #include <linux/init.h>
+diff --git a/include/linux/decompress/unlzma_mm.h b/include/linux/decompress/unlzma_mm.h
+new file mode 100644
+index 0000000..859287e
+--- /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
+diff --git a/lib/Kconfig b/lib/Kconfig
+index bb1326d..25e7f28 100644
+--- 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
+ #
+diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c
+index 600f473..7db58b9 100644
+--- 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
+@@ -637,6 +638,8 @@ static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
+       /* Allocate bunzip_data.  Most fields initialize to zero. */
+       bd = *bdp = malloc(i);
++      if (!bd)
++              return RETVAL_OUT_OF_MEMORY;
+       memset(bd, 0, sizeof(struct bunzip_data));
+       /* Setup input buffer */
+       bd->inbuf = inbuf;
+@@ -664,6 +667,8 @@ static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
+       bd->dbufSize = 100000*(i-BZh0);
+       bd->dbuf = large_malloc(bd->dbufSize * sizeof(int));
++      if (!bd->dbuf)
++              return RETVAL_OUT_OF_MEMORY;
+       return RETVAL_OK;
+ }
+@@ -686,7 +691,7 @@ STATIC int INIT bunzip2(unsigned char *buf, int len,
+       if (!outbuf) {
+               error("Could not allocate output bufer");
+-              return -1;
++              return RETVAL_OUT_OF_MEMORY;
+       }
+       if (buf)
+               inbuf = buf;
+@@ -694,6 +699,7 @@ STATIC int INIT bunzip2(unsigned char *buf, int len,
+               inbuf = malloc(BZIP2_IOBUF_SIZE);
+       if (!inbuf) {
+               error("Could not allocate input bufer");
++              i = RETVAL_OUT_OF_MEMORY;
+               goto exit_0;
+       }
+       i = start_bunzip(&bd, inbuf, len, fill);
+@@ -720,11 +726,14 @@ STATIC int INIT bunzip2(unsigned char *buf, int len,
+       } else if (i == RETVAL_UNEXPECTED_OUTPUT_EOF) {
+               error("Compressed file ends unexpectedly");
+       }
++      if (!bd)
++              goto exit_1;
+       if (bd->dbuf)
+               large_free(bd->dbuf);
+       if (pos)
+               *pos = bd->inbufPos;
+       free(bd);
++exit_1:
+       if (!buf)
+               free(inbuf);
+ exit_0:
+diff --git a/lib/decompress_inflate.c b/lib/decompress_inflate.c
+index fc686c7..cb6bcab 100644
+--- 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)
+diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c
+index ca82fde..30d7f8e 100644
+--- 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))
+@@ -88,7 +89,7 @@ static int nofill(void *buffer, unsigned int len)
+ }
+ /* Called twice: once at startup and once in rc_normalize() */
+-static void INIT rc_read(struct rc *rc)
++static void INIT rc_read(struct rc *rc, void(*error)(char *x))
+ {
+       rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE);
+       if (rc->buffer_size <= 0)
+@@ -115,13 +116,13 @@ static inline void INIT rc_init(struct rc *rc,
+       rc->range = 0xFFFFFFFF;
+ }
+-static inline void INIT rc_init_code(struct rc *rc)
++static inline void INIT rc_init_code(struct rc *rc, void(*error)(char *x))
+ {
+       int i;
+       for (i = 0; i < 5; i++) {
+               if (rc->ptr >= rc->buffer_end)
+-                      rc_read(rc);
++                      rc_read(rc, error);
+               rc->code = (rc->code << 8) | *rc->ptr++;
+       }
+ }
+@@ -134,32 +135,33 @@ static inline void INIT rc_free(struct rc *rc)
+ }
+ /* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */
+-static void INIT rc_do_normalize(struct rc *rc)
++static void INIT rc_do_normalize(struct rc *rc, void(*error)(char *x))
+ {
+       if (rc->ptr >= rc->buffer_end)
+-              rc_read(rc);
++              rc_read(rc, error);
+       rc->range <<= 8;
+       rc->code = (rc->code << 8) | *rc->ptr++;
+ }
+-static inline void INIT rc_normalize(struct rc *rc)
++static inline void INIT rc_normalize(struct rc *rc, void(*error)(char *x))
+ {
+       if (rc->range < (1 << RC_TOP_BITS))
+-              rc_do_normalize(rc);
++              rc_do_normalize(rc, error);
+ }
+ /* Called 9 times */
+ /* Why rc_is_bit_0_helper exists?
+  *Because we want to always expose (rc->code < rc->bound) to optimizer
+  */
+-static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p)
++static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p,
++                                              void (*error)(char *x))
+ {
+-      rc_normalize(rc);
++      rc_normalize(rc, error);
+       rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
+       return rc->bound;
+ }
+-static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p)
++static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p, void(*error)(char *x))
+ {
+-      uint32_t t = rc_is_bit_0_helper(rc, p);
++      uint32_t t = rc_is_bit_0_helper(rc, p, error);
+       return rc->code < t;
+ }
+@@ -177,9 +179,9 @@ static inline void rc_update_bit_1(struct rc *rc, uint16_t *p)
+ }
+ /* Called 4 times in unlzma loop */
+-static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol)
++static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol, void(*error)(char *x))
+ {
+-      if (rc_is_bit_0(rc, p)) {
++      if (rc_is_bit_0(rc, p, error)) {
+               rc_update_bit_0(rc, p);
+               *symbol *= 2;
+               return 0;
+@@ -191,9 +193,9 @@ static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol)
+ }
+ /* Called once */
+-static inline int INIT rc_direct_bit(struct rc *rc)
++static inline int INIT rc_direct_bit(struct rc *rc , void(*error)(char *x))
+ {
+-      rc_normalize(rc);
++      rc_normalize(rc, error);
+       rc->range >>= 1;
+       if (rc->code >= rc->range) {
+               rc->code -= rc->range;
+@@ -204,13 +206,14 @@ static inline int INIT rc_direct_bit(struct rc *rc)
+ /* Called twice */
+ static inline void INIT
+-rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol)
++rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol,
++                                                      void(*error)(char *x))
+ {
+       int i = num_levels;
+       *symbol = 1;
+       while (i--)
+-              rc_get_bit(rc, p + *symbol, symbol);
++              rc_get_bit(rc, p + *symbol, symbol, error);
+       *symbol -= 1 << num_levels;
+ }
+@@ -347,7 +350,8 @@ static inline void INIT copy_bytes(struct writer *wr,
+ static inline void INIT process_bit0(struct writer *wr, struct rc *rc,
+                                    struct cstate *cst, uint16_t *p,
+                                    int pos_state, uint16_t *prob,
+-                                   int lc, uint32_t literal_pos_mask) {
++                                   int lc, uint32_t literal_pos_mask,
++                                   void(*error)(char *x)) {
+       int mi = 1;
+       rc_update_bit_0(rc, prob);
+       prob = (p + LZMA_LITERAL +
+@@ -365,7 +369,7 @@ static inline void INIT process_bit0(struct writer *wr, struct rc *rc,
+                       match_byte <<= 1;
+                       bit = match_byte & 0x100;
+                       prob_lit = prob + 0x100 + bit + mi;
+-                      if (rc_get_bit(rc, prob_lit, &mi)) {
++                      if (rc_get_bit(rc, prob_lit, &mi, error)) {
+                               if (!bit)
+                                       break;
+                       } else {
+@@ -376,7 +380,7 @@ static inline void INIT process_bit0(struct writer *wr, struct rc *rc,
+       }
+       while (mi < 0x100) {
+               uint16_t *prob_lit = prob + mi;
+-              rc_get_bit(rc, prob_lit, &mi);
++              rc_get_bit(rc, prob_lit, &mi, error);
+       }
+       write_byte(wr, mi);
+       if (cst->state < 4)
+@@ -389,7 +393,8 @@ static inline void INIT process_bit0(struct writer *wr, struct rc *rc,
+ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+                                           struct cstate *cst, uint16_t *p,
+-                                          int pos_state, uint16_t *prob) {
++                                          int pos_state, uint16_t *prob,
++                                          void(*error)(char *x)) {
+   int offset;
+       uint16_t *prob_len;
+       int num_bits;
+@@ -397,7 +402,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+       rc_update_bit_1(rc, prob);
+       prob = p + LZMA_IS_REP + cst->state;
+-      if (rc_is_bit_0(rc, prob)) {
++      if (rc_is_bit_0(rc, prob, error)) {
+               rc_update_bit_0(rc, prob);
+               cst->rep3 = cst->rep2;
+               cst->rep2 = cst->rep1;
+@@ -407,13 +412,13 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+       } else {
+               rc_update_bit_1(rc, prob);
+               prob = p + LZMA_IS_REP_G0 + cst->state;
+-              if (rc_is_bit_0(rc, prob)) {
++              if (rc_is_bit_0(rc, prob, error)) {
+                       rc_update_bit_0(rc, prob);
+                       prob = (p + LZMA_IS_REP_0_LONG
+                               + (cst->state <<
+                                  LZMA_NUM_POS_BITS_MAX) +
+                               pos_state);
+-                      if (rc_is_bit_0(rc, prob)) {
++                      if (rc_is_bit_0(rc, prob, error)) {
+                               rc_update_bit_0(rc, prob);
+                               cst->state = cst->state < LZMA_NUM_LIT_STATES ?
+@@ -428,13 +433,13 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+                       rc_update_bit_1(rc, prob);
+                       prob = p + LZMA_IS_REP_G1 + cst->state;
+-                      if (rc_is_bit_0(rc, prob)) {
++                      if (rc_is_bit_0(rc, prob, error)) {
+                               rc_update_bit_0(rc, prob);
+                               distance = cst->rep1;
+                       } else {
+                               rc_update_bit_1(rc, prob);
+                               prob = p + LZMA_IS_REP_G2 + cst->state;
+-                              if (rc_is_bit_0(rc, prob)) {
++                              if (rc_is_bit_0(rc, prob, error)) {
+                                       rc_update_bit_0(rc, prob);
+                                       distance = cst->rep2;
+                               } else {
+@@ -452,7 +457,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+       }
+       prob_len = prob + LZMA_LEN_CHOICE;
+-      if (rc_is_bit_0(rc, prob_len)) {
++      if (rc_is_bit_0(rc, prob_len, error)) {
+               rc_update_bit_0(rc, prob_len);
+               prob_len = (prob + LZMA_LEN_LOW
+                           + (pos_state <<
+@@ -462,7 +467,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+       } else {
+               rc_update_bit_1(rc, prob_len);
+               prob_len = prob + LZMA_LEN_CHOICE_2;
+-              if (rc_is_bit_0(rc, prob_len)) {
++              if (rc_is_bit_0(rc, prob_len, error)) {
+                       rc_update_bit_0(rc, prob_len);
+                       prob_len = (prob + LZMA_LEN_MID
+                                   + (pos_state <<
+@@ -478,7 +483,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+               }
+       }
+-      rc_bit_tree_decode(rc, prob_len, num_bits, &len);
++      rc_bit_tree_decode(rc, prob_len, num_bits, &len, error);
+       len += offset;
+       if (cst->state < 4) {
+@@ -493,7 +498,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+                        << LZMA_NUM_POS_SLOT_BITS);
+               rc_bit_tree_decode(rc, prob,
+                                  LZMA_NUM_POS_SLOT_BITS,
+-                                 &pos_slot);
++                                 &pos_slot, error);
+               if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
+                       int i, mi;
+                       num_bits = (pos_slot >> 1) - 1;
+@@ -506,7 +511,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+                               num_bits -= LZMA_NUM_ALIGN_BITS;
+                               while (num_bits--)
+                                       cst->rep0 = (cst->rep0 << 1) |
+-                                              rc_direct_bit(rc);
++                                              rc_direct_bit(rc, error);
+                               prob = p + LZMA_ALIGN;
+                               cst->rep0 <<= LZMA_NUM_ALIGN_BITS;
+                               num_bits = LZMA_NUM_ALIGN_BITS;
+@@ -514,7 +519,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+                       i = 1;
+                       mi = 1;
+                       while (num_bits--) {
+-                              if (rc_get_bit(rc, prob + mi, &mi))
++                              if (rc_get_bit(rc, prob + mi, &mi, error))
+                                       cst->rep0 |= i;
+                               i <<= 1;
+                       }
+@@ -531,12 +536,12 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc,
+-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,
+                             int *posp,
+-                            void(*error_fn)(char *x)
++                            void(*error)(char *x)
+       )
+ {
+       struct lzma_header header;
+@@ -552,8 +557,6 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
+       unsigned char *inbuf;
+       int ret = -1;
+-      set_error_fn(error_fn);
+-
+       if (buf)
+               inbuf = buf;
+       else
+@@ -576,7 +579,7 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
+       for (i = 0; i < sizeof(header); i++) {
+               if (rc.ptr >= rc.buffer_end)
+-                      rc_read(&rc);
++                      rc_read(&rc, error);
+               ((unsigned char *)&header)[i] = *rc.ptr++;
+       }
+@@ -621,17 +624,17 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
+       for (i = 0; i < num_probs; i++)
+               p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
+-      rc_init_code(&rc);
++      rc_init_code(&rc, error);
+       while (get_pos(&wr) < header.dst_size) {
+               int pos_state = get_pos(&wr) & pos_state_mask;
+               uint16_t *prob = p + LZMA_IS_MATCH +
+                       (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state;
+-              if (rc_is_bit_0(&rc, prob))
++              if (rc_is_bit_0(&rc, prob, error))
+                       process_bit0(&wr, &rc, &cst, p, pos_state, prob,
+-                                   lc, literal_pos_mask);
++                                   lc, literal_pos_mask, error);
+               else {
+-                      process_bit1(&wr, &rc, &cst, p, pos_state, prob);
++                      process_bit1(&wr, &rc, &cst, p, pos_state, prob, error);
+                       if (cst.rep0 == 0)
+                               break;
+               }
+@@ -664,4 +667,6 @@ STATIC int INIT decompress(unsigned char *buf, int in_len,
+ {
+       return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn);
+ }
++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
++EXPORT_SYMBOL(unlzma);
+ #endif
index d7c6ce78c74a7f5ceae97b900197f4f1404e2a60..f9d294777dc5f278749b1a3e0ed500848ff46996 100644 (file)
 
 %define                _enable_debug_packages                  0
 
-%define                squashfs_version        3.4
 %define                tuxonice_version        3.0.1
 %define                netfilter_snap          20070806
 
@@ -289,6 +288,9 @@ Patch148:   kernel-aufs2.patch
 
 Patch150:      kernel-ppc-crtsavres.patch
 
+# git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-devel.git
+Patch160:      kernel-squashfs-lzma.patch
+
 Patch200:      kernel-ppc-ICE-hacks.patch
 
 # The following patch extend the routing functionality in Linux
@@ -845,6 +847,8 @@ sed -i 's/-Werror//' arch/alpha/kernel/Makefile
 # FIXME
 #%patch150 -p1
 
+%patch160 -p1
+
 %ifarch ppc ppc64
 #patch200 -p1
 %endif
This page took 0.130266 seconds and 4 git commands to generate.