diff options
Diffstat (limited to 'fs/hfsplus/super.c')
-rw-r--r-- | fs/hfsplus/super.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 796198d26553..974c26f96fae 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -20,6 +20,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb); | |||
20 | static void hfsplus_destroy_inode(struct inode *inode); | 20 | static void hfsplus_destroy_inode(struct inode *inode); |
21 | 21 | ||
22 | #include "hfsplus_fs.h" | 22 | #include "hfsplus_fs.h" |
23 | #include "xattr.h" | ||
23 | 24 | ||
24 | static int hfsplus_system_read_inode(struct inode *inode) | 25 | static int hfsplus_system_read_inode(struct inode *inode) |
25 | { | 26 | { |
@@ -118,6 +119,7 @@ static int hfsplus_system_write_inode(struct inode *inode) | |||
118 | case HFSPLUS_ATTR_CNID: | 119 | case HFSPLUS_ATTR_CNID: |
119 | fork = &vhdr->attr_file; | 120 | fork = &vhdr->attr_file; |
120 | tree = sbi->attr_tree; | 121 | tree = sbi->attr_tree; |
122 | break; | ||
121 | default: | 123 | default: |
122 | return -EIO; | 124 | return -EIO; |
123 | } | 125 | } |
@@ -191,6 +193,12 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait) | |||
191 | error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping); | 193 | error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping); |
192 | if (!error) | 194 | if (!error) |
193 | error = error2; | 195 | error = error2; |
196 | if (sbi->attr_tree) { | ||
197 | error2 = | ||
198 | filemap_write_and_wait(sbi->attr_tree->inode->i_mapping); | ||
199 | if (!error) | ||
200 | error = error2; | ||
201 | } | ||
194 | error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping); | 202 | error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping); |
195 | if (!error) | 203 | if (!error) |
196 | error = error2; | 204 | error = error2; |
@@ -281,6 +289,7 @@ static void hfsplus_put_super(struct super_block *sb) | |||
281 | hfsplus_sync_fs(sb, 1); | 289 | hfsplus_sync_fs(sb, 1); |
282 | } | 290 | } |
283 | 291 | ||
292 | hfs_btree_close(sbi->attr_tree); | ||
284 | hfs_btree_close(sbi->cat_tree); | 293 | hfs_btree_close(sbi->cat_tree); |
285 | hfs_btree_close(sbi->ext_tree); | 294 | hfs_btree_close(sbi->ext_tree); |
286 | iput(sbi->alloc_file); | 295 | iput(sbi->alloc_file); |
@@ -477,12 +486,20 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
477 | printk(KERN_ERR "hfs: failed to load catalog file\n"); | 486 | printk(KERN_ERR "hfs: failed to load catalog file\n"); |
478 | goto out_close_ext_tree; | 487 | goto out_close_ext_tree; |
479 | } | 488 | } |
489 | if (vhdr->attr_file.total_blocks != 0) { | ||
490 | sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID); | ||
491 | if (!sbi->attr_tree) { | ||
492 | printk(KERN_ERR "hfs: failed to load attributes file\n"); | ||
493 | goto out_close_cat_tree; | ||
494 | } | ||
495 | } | ||
496 | sb->s_xattr = hfsplus_xattr_handlers; | ||
480 | 497 | ||
481 | inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID); | 498 | inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID); |
482 | if (IS_ERR(inode)) { | 499 | if (IS_ERR(inode)) { |
483 | printk(KERN_ERR "hfs: failed to load allocation file\n"); | 500 | printk(KERN_ERR "hfs: failed to load allocation file\n"); |
484 | err = PTR_ERR(inode); | 501 | err = PTR_ERR(inode); |
485 | goto out_close_cat_tree; | 502 | goto out_close_attr_tree; |
486 | } | 503 | } |
487 | sbi->alloc_file = inode; | 504 | sbi->alloc_file = inode; |
488 | 505 | ||
@@ -542,10 +559,27 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
542 | } | 559 | } |
543 | err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root, | 560 | err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root, |
544 | &str, sbi->hidden_dir); | 561 | &str, sbi->hidden_dir); |
545 | mutex_unlock(&sbi->vh_mutex); | 562 | if (err) { |
546 | if (err) | 563 | mutex_unlock(&sbi->vh_mutex); |
564 | goto out_put_hidden_dir; | ||
565 | } | ||
566 | |||
567 | err = hfsplus_init_inode_security(sbi->hidden_dir, | ||
568 | root, &str); | ||
569 | if (err == -EOPNOTSUPP) | ||
570 | err = 0; /* Operation is not supported. */ | ||
571 | else if (err) { | ||
572 | /* | ||
573 | * Try to delete anyway without | ||
574 | * error analysis. | ||
575 | */ | ||
576 | hfsplus_delete_cat(sbi->hidden_dir->i_ino, | ||
577 | root, &str); | ||
578 | mutex_unlock(&sbi->vh_mutex); | ||
547 | goto out_put_hidden_dir; | 579 | goto out_put_hidden_dir; |
580 | } | ||
548 | 581 | ||
582 | mutex_unlock(&sbi->vh_mutex); | ||
549 | hfsplus_mark_inode_dirty(sbi->hidden_dir, | 583 | hfsplus_mark_inode_dirty(sbi->hidden_dir, |
550 | HFSPLUS_I_CAT_DIRTY); | 584 | HFSPLUS_I_CAT_DIRTY); |
551 | } | 585 | } |
@@ -562,6 +596,8 @@ out_put_root: | |||
562 | sb->s_root = NULL; | 596 | sb->s_root = NULL; |
563 | out_put_alloc_file: | 597 | out_put_alloc_file: |
564 | iput(sbi->alloc_file); | 598 | iput(sbi->alloc_file); |
599 | out_close_attr_tree: | ||
600 | hfs_btree_close(sbi->attr_tree); | ||
565 | out_close_cat_tree: | 601 | out_close_cat_tree: |
566 | hfs_btree_close(sbi->cat_tree); | 602 | hfs_btree_close(sbi->cat_tree); |
567 | out_close_ext_tree: | 603 | out_close_ext_tree: |
@@ -635,9 +671,20 @@ static int __init init_hfsplus_fs(void) | |||
635 | hfsplus_init_once); | 671 | hfsplus_init_once); |
636 | if (!hfsplus_inode_cachep) | 672 | if (!hfsplus_inode_cachep) |
637 | return -ENOMEM; | 673 | return -ENOMEM; |
674 | err = hfsplus_create_attr_tree_cache(); | ||
675 | if (err) | ||
676 | goto destroy_inode_cache; | ||
638 | err = register_filesystem(&hfsplus_fs_type); | 677 | err = register_filesystem(&hfsplus_fs_type); |
639 | if (err) | 678 | if (err) |
640 | kmem_cache_destroy(hfsplus_inode_cachep); | 679 | goto destroy_attr_tree_cache; |
680 | return 0; | ||
681 | |||
682 | destroy_attr_tree_cache: | ||
683 | hfsplus_destroy_attr_tree_cache(); | ||
684 | |||
685 | destroy_inode_cache: | ||
686 | kmem_cache_destroy(hfsplus_inode_cachep); | ||
687 | |||
641 | return err; | 688 | return err; |
642 | } | 689 | } |
643 | 690 | ||
@@ -650,6 +697,7 @@ static void __exit exit_hfsplus_fs(void) | |||
650 | * destroy cache. | 697 | * destroy cache. |
651 | */ | 698 | */ |
652 | rcu_barrier(); | 699 | rcu_barrier(); |
700 | hfsplus_destroy_attr_tree_cache(); | ||
653 | kmem_cache_destroy(hfsplus_inode_cachep); | 701 | kmem_cache_destroy(hfsplus_inode_cachep); |
654 | } | 702 | } |
655 | 703 | ||