diff options
Diffstat (limited to 'fs/btrfs/xattr.c')
| -rw-r--r-- | fs/btrfs/xattr.c | 33 | 
1 files changed, 29 insertions, 4 deletions
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index af6246f36a9e..8a4514283a4b 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -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)  | 
