Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[pandora-kernel.git] / fs / squashfs / super.c
index 6c197ef..48b6f4a 100644 (file)
 #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)
@@ -271,7 +275,8 @@ allocate_root:
 
        err = squashfs_read_inode(root, root_inode);
        if (err) {
-               iget_failed(root);
+               make_bad_inode(root);
+               iput(root);
                goto failed_mount;
        }
        insert_inode_hash(root);
@@ -292,17 +297,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 +350,11 @@ 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(sbi->inode_lookup_table);
                kfree(sb->s_fs_info);
                sb->s_fs_info = NULL;
        }