diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-03 19:31:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-03 19:31:43 -0500 |
commit | 89840966c57967fa5b36151c83b7c13fc9c5b3fd (patch) | |
tree | 732a098caea18475c0d08483a5b0ae4369c96a92 /fs | |
parent | 008aef526eb3c67239f1340aa74891355d8b609e (diff) | |
parent | 1065348d472f97b4b8eb53b60ec67e99148cbbca (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus:
hfsplus: fix up a comparism in hfsplus_file_extend
hfsplus: fix two memory leaks in wrapper.c
hfsplus: do not leak buffer on error
hfsplus: fix failed mount handling
Diffstat (limited to 'fs')
-rw-r--r-- | fs/hfsplus/extents.c | 4 | ||||
-rw-r--r-- | fs/hfsplus/part_tbl.c | 4 | ||||
-rw-r--r-- | fs/hfsplus/super.c | 106 | ||||
-rw-r--r-- | fs/hfsplus/wrapper.c | 4 |
4 files changed, 67 insertions, 51 deletions
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 52a0bcaa7b6..b1991a2a08e 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c | |||
@@ -397,8 +397,8 @@ int hfsplus_file_extend(struct inode *inode) | |||
397 | u32 start, len, goal; | 397 | u32 start, len, goal; |
398 | int res; | 398 | int res; |
399 | 399 | ||
400 | if (sbi->total_blocks - sbi->free_blocks + 8 > | 400 | if (sbi->alloc_file->i_size * 8 < |
401 | sbi->alloc_file->i_size * 8) { | 401 | sbi->total_blocks - sbi->free_blocks + 8) { |
402 | /* extend alloc file */ | 402 | /* extend alloc file */ |
403 | printk(KERN_ERR "hfs: extend alloc file! " | 403 | printk(KERN_ERR "hfs: extend alloc file! " |
404 | "(%llu,%u,%u)\n", | 404 | "(%llu,%u,%u)\n", |
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c index d66ad113b1c..40ad88c12c6 100644 --- a/fs/hfsplus/part_tbl.c +++ b/fs/hfsplus/part_tbl.c | |||
@@ -134,7 +134,7 @@ int hfs_part_find(struct super_block *sb, | |||
134 | res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, | 134 | res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, |
135 | data, READ); | 135 | data, READ); |
136 | if (res) | 136 | if (res) |
137 | return res; | 137 | goto out; |
138 | 138 | ||
139 | switch (be16_to_cpu(*((__be16 *)data))) { | 139 | switch (be16_to_cpu(*((__be16 *)data))) { |
140 | case HFS_OLD_PMAP_MAGIC: | 140 | case HFS_OLD_PMAP_MAGIC: |
@@ -147,7 +147,7 @@ int hfs_part_find(struct super_block *sb, | |||
147 | res = -ENOENT; | 147 | res = -ENOENT; |
148 | break; | 148 | break; |
149 | } | 149 | } |
150 | 150 | out: | |
151 | kfree(data); | 151 | kfree(data); |
152 | return res; | 152 | return res; |
153 | } | 153 | } |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 9a3b4795f43..b49b55584c8 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -338,20 +338,22 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
338 | struct inode *root, *inode; | 338 | struct inode *root, *inode; |
339 | struct qstr str; | 339 | struct qstr str; |
340 | struct nls_table *nls = NULL; | 340 | struct nls_table *nls = NULL; |
341 | int err = -EINVAL; | 341 | int err; |
342 | 342 | ||
343 | err = -EINVAL; | ||
343 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 344 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
344 | if (!sbi) | 345 | if (!sbi) |
345 | return -ENOMEM; | 346 | goto out; |
346 | 347 | ||
347 | sb->s_fs_info = sbi; | 348 | sb->s_fs_info = sbi; |
348 | mutex_init(&sbi->alloc_mutex); | 349 | mutex_init(&sbi->alloc_mutex); |
349 | mutex_init(&sbi->vh_mutex); | 350 | mutex_init(&sbi->vh_mutex); |
350 | hfsplus_fill_defaults(sbi); | 351 | hfsplus_fill_defaults(sbi); |
352 | |||
353 | err = -EINVAL; | ||
351 | if (!hfsplus_parse_options(data, sbi)) { | 354 | if (!hfsplus_parse_options(data, sbi)) { |
352 | printk(KERN_ERR "hfs: unable to parse mount options\n"); | 355 | printk(KERN_ERR "hfs: unable to parse mount options\n"); |
353 | err = -EINVAL; | 356 | goto out_unload_nls; |
354 | goto cleanup; | ||
355 | } | 357 | } |
356 | 358 | ||
357 | /* temporarily use utf8 to correctly find the hidden dir below */ | 359 | /* temporarily use utf8 to correctly find the hidden dir below */ |
@@ -359,16 +361,14 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
359 | sbi->nls = load_nls("utf8"); | 361 | sbi->nls = load_nls("utf8"); |
360 | if (!sbi->nls) { | 362 | if (!sbi->nls) { |
361 | printk(KERN_ERR "hfs: unable to load nls for utf8\n"); | 363 | printk(KERN_ERR "hfs: unable to load nls for utf8\n"); |
362 | err = -EINVAL; | 364 | goto out_unload_nls; |
363 | goto cleanup; | ||
364 | } | 365 | } |
365 | 366 | ||
366 | /* Grab the volume header */ | 367 | /* Grab the volume header */ |
367 | if (hfsplus_read_wrapper(sb)) { | 368 | if (hfsplus_read_wrapper(sb)) { |
368 | if (!silent) | 369 | if (!silent) |
369 | printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n"); | 370 | printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n"); |
370 | err = -EINVAL; | 371 | goto out_unload_nls; |
371 | goto cleanup; | ||
372 | } | 372 | } |
373 | vhdr = sbi->s_vhdr; | 373 | vhdr = sbi->s_vhdr; |
374 | 374 | ||
@@ -377,7 +377,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
377 | if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION || | 377 | if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION || |
378 | be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) { | 378 | be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) { |
379 | printk(KERN_ERR "hfs: wrong filesystem version\n"); | 379 | printk(KERN_ERR "hfs: wrong filesystem version\n"); |
380 | goto cleanup; | 380 | goto out_free_vhdr; |
381 | } | 381 | } |
382 | sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); | 382 | sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); |
383 | sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); | 383 | sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); |
@@ -421,19 +421,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
421 | sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); | 421 | sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); |
422 | if (!sbi->ext_tree) { | 422 | if (!sbi->ext_tree) { |
423 | printk(KERN_ERR "hfs: failed to load extents file\n"); | 423 | printk(KERN_ERR "hfs: failed to load extents file\n"); |
424 | goto cleanup; | 424 | goto out_free_vhdr; |
425 | } | 425 | } |
426 | sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); | 426 | sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); |
427 | if (!sbi->cat_tree) { | 427 | if (!sbi->cat_tree) { |
428 | printk(KERN_ERR "hfs: failed to load catalog file\n"); | 428 | printk(KERN_ERR "hfs: failed to load catalog file\n"); |
429 | goto cleanup; | 429 | goto out_close_ext_tree; |
430 | } | 430 | } |
431 | 431 | ||
432 | inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID); | 432 | inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID); |
433 | if (IS_ERR(inode)) { | 433 | if (IS_ERR(inode)) { |
434 | printk(KERN_ERR "hfs: failed to load allocation file\n"); | 434 | printk(KERN_ERR "hfs: failed to load allocation file\n"); |
435 | err = PTR_ERR(inode); | 435 | err = PTR_ERR(inode); |
436 | goto cleanup; | 436 | goto out_close_cat_tree; |
437 | } | 437 | } |
438 | sbi->alloc_file = inode; | 438 | sbi->alloc_file = inode; |
439 | 439 | ||
@@ -442,14 +442,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
442 | if (IS_ERR(root)) { | 442 | if (IS_ERR(root)) { |
443 | printk(KERN_ERR "hfs: failed to load root directory\n"); | 443 | printk(KERN_ERR "hfs: failed to load root directory\n"); |
444 | err = PTR_ERR(root); | 444 | err = PTR_ERR(root); |
445 | goto cleanup; | 445 | goto out_put_alloc_file; |
446 | } | ||
447 | sb->s_d_op = &hfsplus_dentry_operations; | ||
448 | sb->s_root = d_alloc_root(root); | ||
449 | if (!sb->s_root) { | ||
450 | iput(root); | ||
451 | err = -ENOMEM; | ||
452 | goto cleanup; | ||
453 | } | 446 | } |
454 | 447 | ||
455 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; | 448 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; |
@@ -459,46 +452,69 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
459 | if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { | 452 | if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { |
460 | hfs_find_exit(&fd); | 453 | hfs_find_exit(&fd); |
461 | if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) | 454 | if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) |
462 | goto cleanup; | 455 | goto out_put_root; |
463 | inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id)); | 456 | inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id)); |
464 | if (IS_ERR(inode)) { | 457 | if (IS_ERR(inode)) { |
465 | err = PTR_ERR(inode); | 458 | err = PTR_ERR(inode); |
466 | goto cleanup; | 459 | goto out_put_root; |
467 | } | 460 | } |
468 | sbi->hidden_dir = inode; | 461 | sbi->hidden_dir = inode; |
469 | } else | 462 | } else |
470 | hfs_find_exit(&fd); | 463 | hfs_find_exit(&fd); |
471 | 464 | ||
472 | if (sb->s_flags & MS_RDONLY) | 465 | if (!(sb->s_flags & MS_RDONLY)) { |
473 | goto out; | 466 | /* |
467 | * H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused | ||
468 | * all three are registered with Apple for our use | ||
469 | */ | ||
470 | vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); | ||
471 | vhdr->modify_date = hfsp_now2mt(); | ||
472 | be32_add_cpu(&vhdr->write_count, 1); | ||
473 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); | ||
474 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); | ||
475 | hfsplus_sync_fs(sb, 1); | ||
474 | 476 | ||
475 | /* H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused | 477 | if (!sbi->hidden_dir) { |
476 | * all three are registered with Apple for our use | 478 | mutex_lock(&sbi->vh_mutex); |
477 | */ | 479 | sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); |
478 | vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); | 480 | hfsplus_create_cat(sbi->hidden_dir->i_ino, root, &str, |
479 | vhdr->modify_date = hfsp_now2mt(); | 481 | sbi->hidden_dir); |
480 | be32_add_cpu(&vhdr->write_count, 1); | 482 | mutex_unlock(&sbi->vh_mutex); |
481 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); | 483 | |
482 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); | 484 | hfsplus_mark_inode_dirty(sbi->hidden_dir, |
483 | hfsplus_sync_fs(sb, 1); | 485 | HFSPLUS_I_CAT_DIRTY); |
484 | 486 | } | |
485 | if (!sbi->hidden_dir) { | ||
486 | mutex_lock(&sbi->vh_mutex); | ||
487 | sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); | ||
488 | hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode, | ||
489 | &str, sbi->hidden_dir); | ||
490 | mutex_unlock(&sbi->vh_mutex); | ||
491 | |||
492 | hfsplus_mark_inode_dirty(sbi->hidden_dir, HFSPLUS_I_CAT_DIRTY); | ||
493 | } | 487 | } |
494 | out: | 488 | |
489 | sb->s_d_op = &hfsplus_dentry_operations; | ||
490 | sb->s_root = d_alloc_root(root); | ||
491 | if (!sb->s_root) { | ||
492 | err = -ENOMEM; | ||
493 | goto out_put_hidden_dir; | ||
494 | } | ||
495 | |||
495 | unload_nls(sbi->nls); | 496 | unload_nls(sbi->nls); |
496 | sbi->nls = nls; | 497 | sbi->nls = nls; |
497 | return 0; | 498 | return 0; |
498 | 499 | ||
499 | cleanup: | 500 | out_put_hidden_dir: |
500 | hfsplus_put_super(sb); | 501 | iput(sbi->hidden_dir); |
502 | out_put_root: | ||
503 | iput(sbi->alloc_file); | ||
504 | out_put_alloc_file: | ||
505 | iput(sbi->alloc_file); | ||
506 | out_close_cat_tree: | ||
507 | hfs_btree_close(sbi->cat_tree); | ||
508 | out_close_ext_tree: | ||
509 | hfs_btree_close(sbi->ext_tree); | ||
510 | out_free_vhdr: | ||
511 | kfree(sbi->s_vhdr); | ||
512 | kfree(sbi->s_backup_vhdr); | ||
513 | out_unload_nls: | ||
514 | unload_nls(sbi->nls); | ||
501 | unload_nls(nls); | 515 | unload_nls(nls); |
516 | kfree(sbi); | ||
517 | out: | ||
502 | return err; | 518 | return err; |
503 | } | 519 | } |
504 | 520 | ||
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 196231794f6..3031d81f5f0 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c | |||
@@ -167,7 +167,7 @@ reread: | |||
167 | break; | 167 | break; |
168 | case cpu_to_be16(HFSP_WRAP_MAGIC): | 168 | case cpu_to_be16(HFSP_WRAP_MAGIC): |
169 | if (!hfsplus_read_mdb(sbi->s_vhdr, &wd)) | 169 | if (!hfsplus_read_mdb(sbi->s_vhdr, &wd)) |
170 | goto out; | 170 | goto out_free_backup_vhdr; |
171 | wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT; | 171 | wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT; |
172 | part_start += wd.ablk_start + wd.embed_start * wd.ablk_size; | 172 | part_start += wd.ablk_start + wd.embed_start * wd.ablk_size; |
173 | part_size = wd.embed_count * wd.ablk_size; | 173 | part_size = wd.embed_count * wd.ablk_size; |
@@ -179,7 +179,7 @@ reread: | |||
179 | * (should do this only for cdrom/loop though) | 179 | * (should do this only for cdrom/loop though) |
180 | */ | 180 | */ |
181 | if (hfs_part_find(sb, &part_start, &part_size)) | 181 | if (hfs_part_find(sb, &part_start, &part_size)) |
182 | goto out; | 182 | goto out_free_backup_vhdr; |
183 | goto reread; | 183 | goto reread; |
184 | } | 184 | } |
185 | 185 | ||