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