diff options
| -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 52a0bcaa7b6d..b1991a2a08e0 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 d66ad113b1cc..40ad88c12c64 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 9a3b4795f43c..b49b55584c84 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 196231794f64..3031d81f5f0f 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 | ||
