Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f34f57a3 authored by Yan, Zheng's avatar Yan, Zheng Committed by Chris Mason
Browse files

Btrfs: Pass transaction handle to security and ACL initialization functions



Pass transaction handle down to security and ACL initialization
functions, so we can avoid starting nested transactions

Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 8082510e
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -94,7 +94,8 @@ static int btrfs_xattr_get_acl(struct inode *inode, int type,
/*
 * Needs to be called with fs_mutex held
 */
static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
static int btrfs_set_acl(struct btrfs_trans_handle *trans,
			 struct inode *inode, struct posix_acl *acl, int type)
{
	int ret, size = 0;
	const char *name;
@@ -140,8 +141,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
			goto out;
	}

	ret = __btrfs_setxattr(inode, name, value, size, 0);

	ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
out:
	kfree(value);

@@ -154,7 +154,7 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
static int btrfs_xattr_set_acl(struct inode *inode, int type,
			       const void *value, size_t size)
{
	int ret = 0;
	int ret;
	struct posix_acl *acl = NULL;

	if (value) {
@@ -167,7 +167,7 @@ static int btrfs_xattr_set_acl(struct inode *inode, int type,
		}
	}

	ret = btrfs_set_acl(inode, acl, type);
	ret = btrfs_set_acl(NULL, inode, acl, type);

	posix_acl_release(acl);

@@ -221,7 +221,8 @@ int btrfs_check_acl(struct inode *inode, int mask)
 * stuff has been fixed to work with that.  If the locking stuff changes, we
 * need to re-evaluate the acl locking stuff.
 */
int btrfs_init_acl(struct inode *inode, struct inode *dir)
int btrfs_init_acl(struct btrfs_trans_handle *trans,
		   struct inode *inode, struct inode *dir)
{
	struct posix_acl *acl = NULL;
	int ret = 0;
@@ -246,7 +247,8 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
		mode_t mode;

		if (S_ISDIR(inode->i_mode)) {
			ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT);
			ret = btrfs_set_acl(trans, inode, acl,
					    ACL_TYPE_DEFAULT);
			if (ret)
				goto failed;
		}
@@ -261,7 +263,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir)
			inode->i_mode = mode;
			if (ret > 0) {
				/* we need an acl */
				ret = btrfs_set_acl(inode, clone,
				ret = btrfs_set_acl(trans, inode, clone,
						    ACL_TYPE_ACCESS);
			}
		}
@@ -294,7 +296,7 @@ int btrfs_acl_chmod(struct inode *inode)

	ret = posix_acl_chmod_masq(clone, inode->i_mode);
	if (!ret)
		ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS);
		ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);

	posix_acl_release(clone);

@@ -320,7 +322,8 @@ int btrfs_acl_chmod(struct inode *inode)
	return 0;
}

int btrfs_init_acl(struct inode *inode, struct inode *dir)
int btrfs_init_acl(struct btrfs_trans_handle *trans,
		   struct inode *inode, struct inode *dir)
{
	return 0;
}
+9 −4
Original line number Diff line number Diff line
@@ -310,6 +310,9 @@ struct btrfs_header {
#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
					sizeof(struct btrfs_item) - \
					sizeof(struct btrfs_file_extent_item))
#define BTRFS_MAX_XATTR_SIZE(r)	(BTRFS_LEAF_DATA_SIZE(r) - \
				 sizeof(struct btrfs_item) -\
				 sizeof(struct btrfs_dir_item))


/*
@@ -2201,9 +2204,10 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
			      struct btrfs_path *path,
			      struct btrfs_dir_item *di);
int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
			    struct btrfs_root *root, const char *name,
			    u16 name_len, const void *data, u16 data_len,
			    u64 dir);
			    struct btrfs_root *root,
			    struct btrfs_path *path, u64 objectid,
			    const char *name, u16 name_len,
			    const void *data, u16 data_len);
struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
					  struct btrfs_root *root,
					  struct btrfs_path *path, u64 dir,
@@ -2382,7 +2386,8 @@ int btrfs_check_acl(struct inode *inode, int mask);
#else
#define btrfs_check_acl NULL
#endif
int btrfs_init_acl(struct inode *inode, struct inode *dir);
int btrfs_init_acl(struct btrfs_trans_handle *trans,
		   struct inode *inode, struct inode *dir);
int btrfs_acl_chmod(struct inode *inode);

/* relocation.c */
+7 −12
Original line number Diff line number Diff line
@@ -68,12 +68,12 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
 * into the tree
 */
int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
			    struct btrfs_root *root, const char *name,
			    u16 name_len, const void *data, u16 data_len,
			    u64 dir)
			    struct btrfs_root *root,
			    struct btrfs_path *path, u64 objectid,
			    const char *name, u16 name_len,
			    const void *data, u16 data_len)
{
	int ret = 0;
	struct btrfs_path *path;
	struct btrfs_dir_item *dir_item;
	unsigned long name_ptr, data_ptr;
	struct btrfs_key key, location;
@@ -81,15 +81,11 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
	struct extent_buffer *leaf;
	u32 data_size;

	key.objectid = dir;
	BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root));

	key.objectid = objectid;
	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
	key.offset = btrfs_name_hash(name, name_len);
	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;
	if (name_len + data_len + sizeof(struct btrfs_dir_item) >
	    BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item))
		return -ENOSPC;

	data_size = sizeof(*dir_item) + name_len + data_len;
	dir_item = insert_with_overflow(trans, root, path, &key, data_size,
@@ -117,7 +113,6 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
	write_extent_buffer(leaf, data, data_ptr, data_len);
	btrfs_mark_buffer_dirty(path->nodes[0]);

	btrfs_free_path(path);
	return ret;
}

+8 −7
Original line number Diff line number Diff line
@@ -88,13 +88,14 @@ static noinline int cow_file_range(struct inode *inode,
				   u64 start, u64 end, int *page_started,
				   unsigned long *nr_written, int unlock);

static int btrfs_init_inode_security(struct inode *inode,  struct inode *dir)
static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
				     struct inode *inode,  struct inode *dir)
{
	int err;

	err = btrfs_init_acl(inode, dir);
	err = btrfs_init_acl(trans, inode, dir);
	if (!err)
		err = btrfs_xattr_security_init(inode, dir);
		err = btrfs_xattr_security_init(trans, inode, dir);
	return err;
}

@@ -4296,7 +4297,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
	if (IS_ERR(inode))
		goto out_unlock;

	err = btrfs_init_inode_security(inode, dir);
	err = btrfs_init_inode_security(trans, inode, dir);
	if (err) {
		drop_inode = 1;
		goto out_unlock;
@@ -4367,7 +4368,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
	if (IS_ERR(inode))
		goto out_unlock;

	err = btrfs_init_inode_security(inode, dir);
	err = btrfs_init_inode_security(trans, inode, dir);
	if (err) {
		drop_inode = 1;
		goto out_unlock;
@@ -4500,7 +4501,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)

	drop_on_err = 1;

	err = btrfs_init_inode_security(inode, dir);
	err = btrfs_init_inode_security(trans, inode, dir);
	if (err)
		goto out_fail;

@@ -5660,7 +5661,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
	if (IS_ERR(inode))
		goto out_unlock;

	err = btrfs_init_inode_security(inode, dir);
	err = btrfs_init_inode_security(trans, inode, dir);
	if (err) {
		drop_inode = 1;
		goto out_unlock;
+54 −26
Original line number Diff line number Diff line
@@ -85,22 +85,23 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
	return ret;
}

int __btrfs_setxattr(struct inode *inode, const char *name,
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)
		return ret;

	trans = btrfs_start_transaction(root, 1);
	if (!trans) {
		ret = -ENOMEM;
		goto out;
	}
	btrfs_set_trans_block_group(trans, inode);

	ret = do_setxattr(trans, inode, name, value, size, flags);
	if (ret)
		goto out;
	mod = 1;

out:
	if (mod) {
	inode->i_ctime = CURRENT_TIME;
	ret = btrfs_update_inode(trans, root, inode);
	}

	btrfs_end_transaction(trans, root);
	btrfs_free_path(path);
	BUG_ON(ret);
out:
	btrfs_end_transaction_throttle(trans, root);
	btrfs_unreserve_metadata_space(root, 2);
	return ret;
}

@@ -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);
	}

Loading