diff options
Diffstat (limited to 'fs/squashfs/super.c')
-rw-r--r-- | fs/squashfs/super.c | 112 |
1 files changed, 65 insertions, 47 deletions
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 5c8184c061a4..6f26abee3597 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Squashfs - a compressed read only filesystem for Linux | 2 | * Squashfs - a compressed read only filesystem for Linux |
3 | * | 3 | * |
4 | * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 | 4 | * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 |
5 | * Phillip Lougher <phillip@lougher.demon.co.uk> | 5 | * Phillip Lougher <phillip@squashfs.org.uk> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
@@ -83,7 +83,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
83 | long long root_inode; | 83 | long long root_inode; |
84 | unsigned short flags; | 84 | unsigned short flags; |
85 | unsigned int fragments; | 85 | unsigned int fragments; |
86 | u64 lookup_table_start, xattr_id_table_start; | 86 | u64 lookup_table_start, xattr_id_table_start, next_table; |
87 | int err; | 87 | int err; |
88 | 88 | ||
89 | TRACE("Entered squashfs_fill_superblock\n"); | 89 | TRACE("Entered squashfs_fill_superblock\n"); |
@@ -95,12 +95,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
95 | } | 95 | } |
96 | msblk = sb->s_fs_info; | 96 | msblk = sb->s_fs_info; |
97 | 97 | ||
98 | sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); | ||
99 | if (sblk == NULL) { | ||
100 | ERROR("Failed to allocate squashfs_super_block\n"); | ||
101 | goto failure; | ||
102 | } | ||
103 | |||
104 | msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE); | 98 | msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE); |
105 | msblk->devblksize_log2 = ffz(~msblk->devblksize); | 99 | msblk->devblksize_log2 = ffz(~msblk->devblksize); |
106 | 100 | ||
@@ -114,10 +108,12 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
114 | * of bytes_used) we need to set it to an initial sensible dummy value | 108 | * of bytes_used) we need to set it to an initial sensible dummy value |
115 | */ | 109 | */ |
116 | msblk->bytes_used = sizeof(*sblk); | 110 | msblk->bytes_used = sizeof(*sblk); |
117 | err = squashfs_read_table(sb, sblk, SQUASHFS_START, sizeof(*sblk)); | 111 | sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk)); |
118 | 112 | ||
119 | if (err < 0) { | 113 | if (IS_ERR(sblk)) { |
120 | ERROR("unable to read squashfs_super_block\n"); | 114 | ERROR("unable to read squashfs_super_block\n"); |
115 | err = PTR_ERR(sblk); | ||
116 | sblk = NULL; | ||
121 | goto failed_mount; | 117 | goto failed_mount; |
122 | } | 118 | } |
123 | 119 | ||
@@ -218,18 +214,61 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
218 | goto failed_mount; | 214 | goto failed_mount; |
219 | } | 215 | } |
220 | 216 | ||
217 | /* Handle xattrs */ | ||
218 | sb->s_xattr = squashfs_xattr_handlers; | ||
219 | xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start); | ||
220 | if (xattr_id_table_start == SQUASHFS_INVALID_BLK) { | ||
221 | next_table = msblk->bytes_used; | ||
222 | goto allocate_id_index_table; | ||
223 | } | ||
224 | |||
225 | /* Allocate and read xattr id lookup table */ | ||
226 | msblk->xattr_id_table = squashfs_read_xattr_id_table(sb, | ||
227 | xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids); | ||
228 | if (IS_ERR(msblk->xattr_id_table)) { | ||
229 | ERROR("unable to read xattr id index table\n"); | ||
230 | err = PTR_ERR(msblk->xattr_id_table); | ||
231 | msblk->xattr_id_table = NULL; | ||
232 | if (err != -ENOTSUPP) | ||
233 | goto failed_mount; | ||
234 | } | ||
235 | next_table = msblk->xattr_table; | ||
236 | |||
237 | allocate_id_index_table: | ||
221 | /* Allocate and read id index table */ | 238 | /* Allocate and read id index table */ |
222 | msblk->id_table = squashfs_read_id_index_table(sb, | 239 | msblk->id_table = squashfs_read_id_index_table(sb, |
223 | le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids)); | 240 | le64_to_cpu(sblk->id_table_start), next_table, |
241 | le16_to_cpu(sblk->no_ids)); | ||
224 | if (IS_ERR(msblk->id_table)) { | 242 | if (IS_ERR(msblk->id_table)) { |
243 | ERROR("unable to read id index table\n"); | ||
225 | err = PTR_ERR(msblk->id_table); | 244 | err = PTR_ERR(msblk->id_table); |
226 | msblk->id_table = NULL; | 245 | msblk->id_table = NULL; |
227 | goto failed_mount; | 246 | goto failed_mount; |
228 | } | 247 | } |
248 | next_table = msblk->id_table[0]; | ||
249 | |||
250 | /* Handle inode lookup table */ | ||
251 | lookup_table_start = le64_to_cpu(sblk->lookup_table_start); | ||
252 | if (lookup_table_start == SQUASHFS_INVALID_BLK) | ||
253 | goto handle_fragments; | ||
254 | |||
255 | /* Allocate and read inode lookup table */ | ||
256 | msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb, | ||
257 | lookup_table_start, next_table, msblk->inodes); | ||
258 | if (IS_ERR(msblk->inode_lookup_table)) { | ||
259 | ERROR("unable to read inode lookup table\n"); | ||
260 | err = PTR_ERR(msblk->inode_lookup_table); | ||
261 | msblk->inode_lookup_table = NULL; | ||
262 | goto failed_mount; | ||
263 | } | ||
264 | next_table = msblk->inode_lookup_table[0]; | ||
229 | 265 | ||
266 | sb->s_export_op = &squashfs_export_ops; | ||
267 | |||
268 | handle_fragments: | ||
230 | fragments = le32_to_cpu(sblk->fragments); | 269 | fragments = le32_to_cpu(sblk->fragments); |
231 | if (fragments == 0) | 270 | if (fragments == 0) |
232 | goto allocate_lookup_table; | 271 | goto check_directory_table; |
233 | 272 | ||
234 | msblk->fragment_cache = squashfs_cache_init("fragment", | 273 | msblk->fragment_cache = squashfs_cache_init("fragment", |
235 | SQUASHFS_CACHED_FRAGMENTS, msblk->block_size); | 274 | SQUASHFS_CACHED_FRAGMENTS, msblk->block_size); |
@@ -240,45 +279,29 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) | |||
240 | 279 | ||
241 | /* Allocate and read fragment index table */ | 280 | /* Allocate and read fragment index table */ |
242 | msblk->fragment_index = squashfs_read_fragment_index_table(sb, | 281 | msblk->fragment_index = squashfs_read_fragment_index_table(sb, |
243 | le64_to_cpu(sblk->fragment_table_start), fragments); | 282 | le64_to_cpu(sblk->fragment_table_start), next_table, fragments); |
244 | if (IS_ERR(msblk->fragment_index)) { | 283 | if (IS_ERR(msblk->fragment_index)) { |
284 | ERROR("unable to read fragment index table\n"); | ||
245 | err = PTR_ERR(msblk->fragment_index); | 285 | err = PTR_ERR(msblk->fragment_index); |
246 | msblk->fragment_index = NULL; | 286 | msblk->fragment_index = NULL; |
247 | goto failed_mount; | 287 | goto failed_mount; |
248 | } | 288 | } |
289 | next_table = msblk->fragment_index[0]; | ||
249 | 290 | ||
250 | allocate_lookup_table: | 291 | check_directory_table: |
251 | lookup_table_start = le64_to_cpu(sblk->lookup_table_start); | 292 | /* Sanity check directory_table */ |
252 | if (lookup_table_start == SQUASHFS_INVALID_BLK) | 293 | if (msblk->directory_table >= next_table) { |
253 | goto allocate_xattr_table; | 294 | err = -EINVAL; |
254 | |||
255 | /* Allocate and read inode lookup table */ | ||
256 | msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb, | ||
257 | lookup_table_start, msblk->inodes); | ||
258 | if (IS_ERR(msblk->inode_lookup_table)) { | ||
259 | err = PTR_ERR(msblk->inode_lookup_table); | ||
260 | msblk->inode_lookup_table = NULL; | ||
261 | goto failed_mount; | 295 | goto failed_mount; |
262 | } | 296 | } |
263 | 297 | ||
264 | sb->s_export_op = &squashfs_export_ops; | 298 | /* Sanity check inode_table */ |
265 | 299 | if (msblk->inode_table >= msblk->directory_table) { | |
266 | allocate_xattr_table: | 300 | err = -EINVAL; |
267 | sb->s_xattr = squashfs_xattr_handlers; | 301 | goto failed_mount; |
268 | xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start); | ||
269 | if (xattr_id_table_start == SQUASHFS_INVALID_BLK) | ||
270 | goto allocate_root; | ||
271 | |||
272 | /* Allocate and read xattr id lookup table */ | ||
273 | msblk->xattr_id_table = squashfs_read_xattr_id_table(sb, | ||
274 | xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids); | ||
275 | if (IS_ERR(msblk->xattr_id_table)) { | ||
276 | err = PTR_ERR(msblk->xattr_id_table); | ||
277 | msblk->xattr_id_table = NULL; | ||
278 | if (err != -ENOTSUPP) | ||
279 | goto failed_mount; | ||
280 | } | 302 | } |
281 | allocate_root: | 303 | |
304 | /* allocate root */ | ||
282 | root = new_inode(sb); | 305 | root = new_inode(sb); |
283 | if (!root) { | 306 | if (!root) { |
284 | err = -ENOMEM; | 307 | err = -ENOMEM; |
@@ -318,11 +341,6 @@ failed_mount: | |||
318 | sb->s_fs_info = NULL; | 341 | sb->s_fs_info = NULL; |
319 | kfree(sblk); | 342 | kfree(sblk); |
320 | return err; | 343 | return err; |
321 | |||
322 | failure: | ||
323 | kfree(sb->s_fs_info); | ||
324 | sb->s_fs_info = NULL; | ||
325 | return -ENOMEM; | ||
326 | } | 344 | } |
327 | 345 | ||
328 | 346 | ||
@@ -475,5 +493,5 @@ static const struct super_operations squashfs_super_ops = { | |||
475 | module_init(init_squashfs_fs); | 493 | module_init(init_squashfs_fs); |
476 | module_exit(exit_squashfs_fs); | 494 | module_exit(exit_squashfs_fs); |
477 | MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem"); | 495 | MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem"); |
478 | MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); | 496 | MODULE_AUTHOR("Phillip Lougher <phillip@squashfs.org.uk>"); |
479 | MODULE_LICENSE("GPL"); | 497 | MODULE_LICENSE("GPL"); |