Merge branch 'bkl/ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[safe/jmp/linux-2.6] / fs / squashfs / block.c
index c837dfc..653c030 100644 (file)
 #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
@@ -80,7 +79,7 @@ static struct buffer_head *get_block_length(struct super_block *sb,
  * generated a larger block - this does occasionally happen with zlib).
  */
 int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
-                       int length, u64 *next_index, int srclength)
+                       int length, u64 *next_index, int srclength, int pages)
 {
        struct squashfs_sb_info *msblk = sb->s_fs_info;
        struct buffer_head **bh;
@@ -88,9 +87,8 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
        u64 cur_index = index >> msblk->devblksize_log2;
        int bytes, compressed, b = 0, k = 0, page = 0, avail;
 
-
-       bh = kcalloc((msblk->block_size >> msblk->devblksize_log2) + 1,
-                               sizeof(*bh), GFP_KERNEL);
+       bh = kcalloc(((srclength + msblk->devblksize - 1)
+               >> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL);
        if (bh == NULL)
                return -ENOMEM;
 
@@ -153,77 +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) {
-                               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_NO_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 returned unexpected result"
-                               " 0x%x, srclength %d, avail_in %d,"
-                               " avail_out %d\n", zlib_err, srclength,
-                               msblk->stream.avail_in,
-                               msblk->stream.avail_out);
-                       goto release_mutex;
-               }
-
-               zlib_err = zlib_inflateEnd(&msblk->stream);
-               if (zlib_err != Z_OK) {
-                       ERROR("zlib_inflateEnd returned unexpected result 0x%x,"
-                               " srclength %d\n", zlib_err, srclength);
-                       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.
@@ -260,15 +191,13 @@ 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]);
 
 read_failure:
-       ERROR("sb_bread failed reading block 0x%llx\n", cur_index);
+       ERROR("squashfs_read_data failed to read block 0x%llx\n",
+                                       (unsigned long long) index);
        kfree(bh);
        return -EIO;
 }