Merge tag 'nfs-for-3.9-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[cascardo/linux.git] / fs / hfsplus / super.c
index 796198d..974c26f 100644 (file)
@@ -20,6 +20,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb);
 static void hfsplus_destroy_inode(struct inode *inode);
 
 #include "hfsplus_fs.h"
+#include "xattr.h"
 
 static int hfsplus_system_read_inode(struct inode *inode)
 {
@@ -118,6 +119,7 @@ static int hfsplus_system_write_inode(struct inode *inode)
        case HFSPLUS_ATTR_CNID:
                fork = &vhdr->attr_file;
                tree = sbi->attr_tree;
+               break;
        default:
                return -EIO;
        }
@@ -191,6 +193,12 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait)
        error2 = filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
        if (!error)
                error = error2;
+       if (sbi->attr_tree) {
+               error2 =
+                   filemap_write_and_wait(sbi->attr_tree->inode->i_mapping);
+               if (!error)
+                       error = error2;
+       }
        error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
        if (!error)
                error = error2;
@@ -281,6 +289,7 @@ static void hfsplus_put_super(struct super_block *sb)
                hfsplus_sync_fs(sb, 1);
        }
 
+       hfs_btree_close(sbi->attr_tree);
        hfs_btree_close(sbi->cat_tree);
        hfs_btree_close(sbi->ext_tree);
        iput(sbi->alloc_file);
@@ -477,12 +486,20 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                printk(KERN_ERR "hfs: failed to load catalog file\n");
                goto out_close_ext_tree;
        }
+       if (vhdr->attr_file.total_blocks != 0) {
+               sbi->attr_tree = hfs_btree_open(sb, HFSPLUS_ATTR_CNID);
+               if (!sbi->attr_tree) {
+                       printk(KERN_ERR "hfs: failed to load attributes file\n");
+                       goto out_close_cat_tree;
+               }
+       }
+       sb->s_xattr = hfsplus_xattr_handlers;
 
        inode = hfsplus_iget(sb, HFSPLUS_ALLOC_CNID);
        if (IS_ERR(inode)) {
                printk(KERN_ERR "hfs: failed to load allocation file\n");
                err = PTR_ERR(inode);
-               goto out_close_cat_tree;
+               goto out_close_attr_tree;
        }
        sbi->alloc_file = inode;
 
@@ -542,10 +559,27 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                        }
                        err = hfsplus_create_cat(sbi->hidden_dir->i_ino, root,
                                                 &str, sbi->hidden_dir);
-                       mutex_unlock(&sbi->vh_mutex);
-                       if (err)
+                       if (err) {
+                               mutex_unlock(&sbi->vh_mutex);
+                               goto out_put_hidden_dir;
+                       }
+
+                       err = hfsplus_init_inode_security(sbi->hidden_dir,
+                                                               root, &str);
+                       if (err == -EOPNOTSUPP)
+                               err = 0; /* Operation is not supported. */
+                       else if (err) {
+                               /*
+                                * Try to delete anyway without
+                                * error analysis.
+                                */
+                               hfsplus_delete_cat(sbi->hidden_dir->i_ino,
+                                                       root, &str);
+                               mutex_unlock(&sbi->vh_mutex);
                                goto out_put_hidden_dir;
+                       }
 
+                       mutex_unlock(&sbi->vh_mutex);
                        hfsplus_mark_inode_dirty(sbi->hidden_dir,
                                                 HFSPLUS_I_CAT_DIRTY);
                }
@@ -562,6 +596,8 @@ out_put_root:
        sb->s_root = NULL;
 out_put_alloc_file:
        iput(sbi->alloc_file);
+out_close_attr_tree:
+       hfs_btree_close(sbi->attr_tree);
 out_close_cat_tree:
        hfs_btree_close(sbi->cat_tree);
 out_close_ext_tree:
@@ -635,9 +671,20 @@ static int __init init_hfsplus_fs(void)
                hfsplus_init_once);
        if (!hfsplus_inode_cachep)
                return -ENOMEM;
+       err = hfsplus_create_attr_tree_cache();
+       if (err)
+               goto destroy_inode_cache;
        err = register_filesystem(&hfsplus_fs_type);
        if (err)
-               kmem_cache_destroy(hfsplus_inode_cachep);
+               goto destroy_attr_tree_cache;
+       return 0;
+
+destroy_attr_tree_cache:
+       hfsplus_destroy_attr_tree_cache();
+
+destroy_inode_cache:
+       kmem_cache_destroy(hfsplus_inode_cachep);
+
        return err;
 }
 
@@ -650,6 +697,7 @@ static void __exit exit_hfsplus_fs(void)
         * destroy cache.
         */
        rcu_barrier();
+       hfsplus_destroy_attr_tree_cache();
        kmem_cache_destroy(hfsplus_inode_cachep);
 }