summaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hfsplus/super.c')
-rw-r--r--fs/hfsplus/super.c56
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);
20static void hfsplus_destroy_inode(struct inode *inode); 20static 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
24static int hfsplus_system_read_inode(struct inode *inode) 25static 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;
563out_put_alloc_file: 597out_put_alloc_file:
564 iput(sbi->alloc_file); 598 iput(sbi->alloc_file);
599out_close_attr_tree:
600 hfs_btree_close(sbi->attr_tree);
565out_close_cat_tree: 601out_close_cat_tree:
566 hfs_btree_close(sbi->cat_tree); 602 hfs_btree_close(sbi->cat_tree);
567out_close_ext_tree: 603out_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
682destroy_attr_tree_cache:
683 hfsplus_destroy_attr_tree_cache();
684
685destroy_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