Skip to content

Commit

Permalink
Btrfs: Pass transaction handle to security and ACL initialization fun…
Browse files Browse the repository at this point in the history
…ctions

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

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Yan, Zheng authored and Chris Mason committed Dec 17, 2009
1 parent 8082510 commit f34f57a
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 63 deletions.
23 changes: 13 additions & 10 deletions fs/btrfs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand All @@ -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) {
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);

Expand All @@ -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;
}
Expand Down
13 changes: 9 additions & 4 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))


/*
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down
19 changes: 7 additions & 12 deletions fs/btrfs/dir-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,24 @@ 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;
struct btrfs_disk_key disk_key;
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,
Expand Down Expand Up @@ -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;
}

Expand Down
15 changes: 8 additions & 7 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
80 changes: 54 additions & 26 deletions fs/btrfs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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);
Expand All @@ -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);

Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand All @@ -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);
}

Expand Down
9 changes: 5 additions & 4 deletions fs/btrfs/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ extern struct xattr_handler *btrfs_xattr_handlers[];

extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
void *buffer, size_t size);
extern int __btrfs_setxattr(struct inode *inode, const char *name,
const void *value, size_t size, int flags);

extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
struct inode *inode, const char *name,
const void *value, size_t size, int flags);
extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
void *buffer, size_t size);
extern int btrfs_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
extern int btrfs_removexattr(struct dentry *dentry, const char *name);

extern int btrfs_xattr_security_init(struct inode *inode, struct inode *dir);
extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir);

#endif /* __XATTR__ */

0 comments on commit f34f57a

Please sign in to comment.