|
@@ -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;
|
|
|
}
|