Merge tag 'for-5.12-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / fs / btrfs / xattr.c
index af6246f..8a45142 100644 (file)
@@ -229,11 +229,33 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name,
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
+       const bool start_trans = (current->journal_info == NULL);
        int ret;
 
-       trans = btrfs_start_transaction(root, 2);
-       if (IS_ERR(trans))
-               return PTR_ERR(trans);
+       if (start_trans) {
+               /*
+                * 1 unit for inserting/updating/deleting the xattr
+                * 1 unit for the inode item update
+                */
+               trans = btrfs_start_transaction(root, 2);
+               if (IS_ERR(trans))
+                       return PTR_ERR(trans);
+       } else {
+               /*
+                * This can happen when smack is enabled and a directory is being
+                * created. It happens through d_instantiate_new(), which calls
+                * smack_d_instantiate(), which in turn calls __vfs_setxattr() to
+                * set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the
+                * inode. We have already reserved space for the xattr and inode
+                * update at btrfs_mkdir(), so just use the transaction handle.
+                * We don't join or start a transaction, as that will reset the
+                * block_rsv of the handle and trigger a warning for the start
+                * case.
+                */
+               ASSERT(strncmp(name, XATTR_SECURITY_PREFIX,
+                              XATTR_SECURITY_PREFIX_LEN) == 0);
+               trans = current->journal_info;
+       }
 
        ret = btrfs_setxattr(trans, inode, name, value, size, flags);
        if (ret)
@@ -244,7 +266,8 @@ int btrfs_setxattr_trans(struct inode *inode, const char *name,
        ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
        BUG_ON(ret);
 out:
-       btrfs_end_transaction(trans);
+       if (start_trans)
+               btrfs_end_transaction(trans);
        return ret;
 }
 
@@ -362,6 +385,7 @@ static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
 }
 
 static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
+                                  struct user_namespace *mnt_userns,
                                   struct dentry *unused, struct inode *inode,
                                   const char *name, const void *buffer,
                                   size_t size, int flags)
@@ -371,6 +395,7 @@ static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
 }
 
 static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
+                                       struct user_namespace *mnt_userns,
                                        struct dentry *unused, struct inode *inode,
                                        const char *name, const void *value,
                                        size_t size, int flags)