mnt_flags fixes in do_remount()
[safe/jmp/linux-2.6] / fs / btrfs / xattr.c
index b0fc93f..193b58f 100644 (file)
@@ -85,22 +85,23 @@ out:
        return ret;
 }
 
-int __btrfs_setxattr(struct inode *inode, const char *name,
-                           const void *value, size_t size, int flags)
+static int do_setxattr(struct btrfs_trans_handle *trans,
+                      struct inode *inode, const char *name,
+                      const void *value, size_t size, int flags)
 {
        struct btrfs_dir_item *di;
        struct btrfs_root *root = BTRFS_I(inode)->root;
-       struct btrfs_trans_handle *trans;
        struct btrfs_path *path;
-       int ret = 0, mod = 0;
+       size_t name_len = strlen(name);
+       int ret = 0;
+
+       if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
+               return -ENOSPC;
 
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
 
-       trans = btrfs_join_transaction(root, 1);
-       btrfs_set_trans_block_group(trans, inode);
-
        /* first lets see if we already have this xattr */
        di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
                                strlen(name), -1);
@@ -118,15 +119,12 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
                }
 
                ret = btrfs_delete_one_dir_name(trans, root, path, di);
-               if (ret)
-                       goto out;
+               BUG_ON(ret);
                btrfs_release_path(root, path);
 
                /* if we don't have a value then we are removing the xattr */
-               if (!value) {
-                       mod = 1;
+               if (!value)
                        goto out;
-               }
        } else {
                btrfs_release_path(root, path);
 
@@ -138,20 +136,45 @@ int __btrfs_setxattr(struct inode *inode, const char *name,
        }
 
        /* ok we have to create a completely new xattr */
-       ret = btrfs_insert_xattr_item(trans, root, name, strlen(name),
-                                     value, size, inode->i_ino);
+       ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino,
+                                     name, name_len, value, size);
+       BUG_ON(ret);
+out:
+       btrfs_free_path(path);
+       return ret;
+}
+
+int __btrfs_setxattr(struct btrfs_trans_handle *trans,
+                    struct inode *inode, const char *name,
+                    const void *value, size_t size, int flags)
+{
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       int ret;
+
+       if (trans)
+               return do_setxattr(trans, inode, name, value, size, flags);
+
+       ret = btrfs_reserve_metadata_space(root, 2);
        if (ret)
-               goto out;
-       mod = 1;
+               return ret;
 
-out:
-       if (mod) {
-               inode->i_ctime = CURRENT_TIME;
-               ret = btrfs_update_inode(trans, root, inode);
+       trans = btrfs_start_transaction(root, 1);
+       if (!trans) {
+               ret = -ENOMEM;
+               goto out;
        }
+       btrfs_set_trans_block_group(trans, inode);
 
-       btrfs_end_transaction(trans, root);
-       btrfs_free_path(path);
+       ret = do_setxattr(trans, inode, name, value, size, flags);
+       if (ret)
+               goto out;
+
+       inode->i_ctime = CURRENT_TIME;
+       ret = btrfs_update_inode(trans, root, inode);
+       BUG_ON(ret);
+out:
+       btrfs_end_transaction_throttle(trans, root);
+       btrfs_unreserve_metadata_space(root, 2);
        return ret;
 }
 
@@ -260,7 +283,7 @@ err:
  * attributes are handled directly.
  */
 struct xattr_handler *btrfs_xattr_handlers[] = {
-#ifdef CONFIG_BTRFS_POSIX_ACL
+#ifdef CONFIG_BTRFS_FS_POSIX_ACL
        &btrfs_xattr_acl_access_handler,
        &btrfs_xattr_acl_default_handler,
 #endif
@@ -314,7 +337,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 
        if (size == 0)
                value = "";  /* empty EA, do not remove */
-       return __btrfs_setxattr(dentry->d_inode, name, value, size, flags);
+
+       return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
+                               flags);
 }
 
 int btrfs_removexattr(struct dentry *dentry, const char *name)
@@ -329,10 +354,13 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
 
        if (!btrfs_is_valid_xattr(name))
                return -EOPNOTSUPP;
-       return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+
+       return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
+                               XATTR_REPLACE);
 }
 
-int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
+int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+                             struct inode *inode, struct inode *dir)
 {
        int err;
        size_t len;
@@ -354,7 +382,7 @@ int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
        } else {
                strcpy(name, XATTR_SECURITY_PREFIX);
                strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-               err = __btrfs_setxattr(inode, name, value, len, 0);
+               err = __btrfs_setxattr(trans, inode, name, value, len, 0);
                kfree(name);
        }