diff options
Diffstat (limited to 'fs/squashfs/super.c')
| -rw-r--r-- | fs/squashfs/super.c | 49 |
1 files changed, 26 insertions, 23 deletions
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 6c197ef53add..3550aec2f655 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
| @@ -35,34 +35,41 @@ | |||
| 35 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
| 36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| 37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| 38 | #include <linux/zlib.h> | ||
| 39 | #include <linux/magic.h> | 38 | #include <linux/magic.h> |
| 40 | 39 | ||
| 41 | #include "squashfs_fs.h" | 40 | #include "squashfs_fs.h" |
| 42 | #include "squashfs_fs_sb.h" | 41 | #include "squashfs_fs_sb.h" |
| 43 | #include "squashfs_fs_i.h" | 42 | #include "squashfs_fs_i.h" |
| 44 | #include "squashfs.h" | 43 | #include "squashfs.h" |
| 44 | #include "decompressor.h" | ||
| 45 | 45 | ||
| 46 | static struct file_system_type squashfs_fs_type; | 46 | static struct file_system_type squashfs_fs_type; |
| 47 | static const struct super_operations squashfs_super_ops; | 47 | static const struct super_operations squashfs_super_ops; |
| 48 | 48 | ||
| 49 | static int supported_squashfs_filesystem(short major, short minor, short comp) | 49 | static const struct squashfs_decompressor *supported_squashfs_filesystem(short |
| 50 | major, short minor, short id) | ||
| 50 | { | 51 | { |
| 52 | const struct squashfs_decompressor *decompressor; | ||
| 53 | |||
| 51 | if (major < SQUASHFS_MAJOR) { | 54 | if (major < SQUASHFS_MAJOR) { |
| 52 | ERROR("Major/Minor mismatch, older Squashfs %d.%d " | 55 | ERROR("Major/Minor mismatch, older Squashfs %d.%d " |
| 53 | "filesystems are unsupported\n", major, minor); | 56 | "filesystems are unsupported\n", major, minor); |
| 54 | return -EINVAL; | 57 | return NULL; |
| 55 | } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { | 58 | } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { |
| 56 | ERROR("Major/Minor mismatch, trying to mount newer " | 59 | ERROR("Major/Minor mismatch, trying to mount newer " |
| 57 | "%d.%d filesystem\n", major, minor); | 60 | "%d.%d filesystem\n", major, minor); |
| 58 | ERROR("Please update your kernel\n"); | 61 | ERROR("Please update your kernel\n"); |
| 59 | return -EINVAL; | 62 | return NULL; |
| 60 | } | 63 | } |
| 61 | 64 | ||
| 62 | if (comp != ZLIB_COMPRESSION) | 65 | decompressor = squashfs_lookup_decompressor(id); |
| 63 | return -EINVAL; | 66 | if (!decompressor->supported) { |
| 67 | ERROR("Filesystem uses \"%s\" compression. This is not " | ||
| 68 | "supported\n", decompressor->name); | ||
| 69 | return NULL; | ||
| 70 | } | ||
| 64 | 71 | ||
| 65 | return 0; | 72 | return decompressor; |
| 66 | } | 73 | } |
| 67 | 74 | ||
| 68 | 75 | ||
| @@ -87,13 +94,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 87 | } | 94 | } |
| 88 | msblk = sb->s_fs_info; | 95 | msblk = sb->s_fs_info; |
| 89 | 96 | ||
| 90 | msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(), | ||
| 91 | GFP_KERNEL); | ||
| 92 | if (msblk->stream.workspace == NULL) { | ||
| 93 | ERROR("Failed to allocate zlib workspace\n"); | ||
| 94 | goto failure; | ||
| 95 | } | ||
| 96 | |||
| 97 | sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); | 97 | sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); |
| 98 | if (sblk == NULL) { | 98 | if (sblk == NULL) { |
| 99 | ERROR("Failed to allocate squashfs_super_block\n"); | 99 | 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) | |||
| 120 | goto failed_mount; | 120 | goto failed_mount; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | err = -EINVAL; | ||
| 124 | |||
| 123 | /* Check it is a SQUASHFS superblock */ | 125 | /* Check it is a SQUASHFS superblock */ |
| 124 | sb->s_magic = le32_to_cpu(sblk->s_magic); | 126 | sb->s_magic = le32_to_cpu(sblk->s_magic); |
| 125 | if (sb->s_magic != SQUASHFS_MAGIC) { | 127 | if (sb->s_magic != SQUASHFS_MAGIC) { |
| 126 | if (!silent) | 128 | if (!silent) |
| 127 | ERROR("Can't find a SQUASHFS superblock on %s\n", | 129 | ERROR("Can't find a SQUASHFS superblock on %s\n", |
| 128 | bdevname(sb->s_bdev, b)); | 130 | bdevname(sb->s_bdev, b)); |
| 129 | err = -EINVAL; | ||
| 130 | goto failed_mount; | 131 | goto failed_mount; |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | /* Check the MAJOR & MINOR versions and compression type */ | 134 | /* Check the MAJOR & MINOR versions and lookup compression type */ |
| 134 | err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major), | 135 | msblk->decompressor = supported_squashfs_filesystem( |
| 136 | le16_to_cpu(sblk->s_major), | ||
| 135 | le16_to_cpu(sblk->s_minor), | 137 | le16_to_cpu(sblk->s_minor), |
| 136 | le16_to_cpu(sblk->compression)); | 138 | le16_to_cpu(sblk->compression)); |
| 137 | if (err < 0) | 139 | if (msblk->decompressor == NULL) |
| 138 | goto failed_mount; | 140 | goto failed_mount; |
| 139 | 141 | ||
| 140 | err = -EINVAL; | ||
| 141 | |||
| 142 | /* | 142 | /* |
| 143 | * Check if there's xattrs in the filesystem. These are not | 143 | * Check if there's xattrs in the filesystem. These are not |
| 144 | * supported in this version, so warn that they will be ignored. | 144 | * 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) | |||
| 205 | 205 | ||
| 206 | err = -ENOMEM; | 206 | err = -ENOMEM; |
| 207 | 207 | ||
| 208 | msblk->stream = squashfs_decompressor_init(msblk); | ||
| 209 | if (msblk->stream == NULL) | ||
| 210 | goto failed_mount; | ||
| 211 | |||
| 208 | msblk->block_cache = squashfs_cache_init("metadata", | 212 | msblk->block_cache = squashfs_cache_init("metadata", |
| 209 | SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); | 213 | SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); |
| 210 | if (msblk->block_cache == NULL) | 214 | if (msblk->block_cache == NULL) |
| @@ -292,17 +296,16 @@ failed_mount: | |||
| 292 | squashfs_cache_delete(msblk->block_cache); | 296 | squashfs_cache_delete(msblk->block_cache); |
| 293 | squashfs_cache_delete(msblk->fragment_cache); | 297 | squashfs_cache_delete(msblk->fragment_cache); |
| 294 | squashfs_cache_delete(msblk->read_page); | 298 | squashfs_cache_delete(msblk->read_page); |
| 299 | squashfs_decompressor_free(msblk, msblk->stream); | ||
| 295 | kfree(msblk->inode_lookup_table); | 300 | kfree(msblk->inode_lookup_table); |
| 296 | kfree(msblk->fragment_index); | 301 | kfree(msblk->fragment_index); |
| 297 | kfree(msblk->id_table); | 302 | kfree(msblk->id_table); |
| 298 | kfree(msblk->stream.workspace); | ||
| 299 | kfree(sb->s_fs_info); | 303 | kfree(sb->s_fs_info); |
| 300 | sb->s_fs_info = NULL; | 304 | sb->s_fs_info = NULL; |
| 301 | kfree(sblk); | 305 | kfree(sblk); |
| 302 | return err; | 306 | return err; |
| 303 | 307 | ||
| 304 | failure: | 308 | failure: |
| 305 | kfree(msblk->stream.workspace); | ||
| 306 | kfree(sb->s_fs_info); | 309 | kfree(sb->s_fs_info); |
| 307 | sb->s_fs_info = NULL; | 310 | sb->s_fs_info = NULL; |
| 308 | return -ENOMEM; | 311 | return -ENOMEM; |
| @@ -346,10 +349,10 @@ static void squashfs_put_super(struct super_block *sb) | |||
| 346 | squashfs_cache_delete(sbi->block_cache); | 349 | squashfs_cache_delete(sbi->block_cache); |
| 347 | squashfs_cache_delete(sbi->fragment_cache); | 350 | squashfs_cache_delete(sbi->fragment_cache); |
| 348 | squashfs_cache_delete(sbi->read_page); | 351 | squashfs_cache_delete(sbi->read_page); |
| 352 | squashfs_decompressor_free(sbi, sbi->stream); | ||
| 349 | kfree(sbi->id_table); | 353 | kfree(sbi->id_table); |
| 350 | kfree(sbi->fragment_index); | 354 | kfree(sbi->fragment_index); |
| 351 | kfree(sbi->meta_index); | 355 | kfree(sbi->meta_index); |
| 352 | kfree(sbi->stream.workspace); | ||
| 353 | kfree(sb->s_fs_info); | 356 | kfree(sb->s_fs_info); |
| 354 | sb->s_fs_info = NULL; | 357 | sb->s_fs_info = NULL; |
| 355 | } | 358 | } |
