Commit 5f465bf1 authored by Omar Sandoval's avatar Omar Sandoval Committed by David Sterba

btrfs: factor out common part of btrfs_{mknod,create,mkdir}()

btrfs_{mknod,create,mkdir}() are now identical other than the inode
initialization and some inconsequential function call order differences.
Factor out the common code to reduce code duplication.
Reviewed-by: default avatarSweet Tea Dorminy <sweettea-kernel@dorminy.me>
Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent a1fd0c35
...@@ -6326,23 +6326,15 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, ...@@ -6326,23 +6326,15 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
static int btrfs_mknod(struct user_namespace *mnt_userns, struct inode *dir, static int btrfs_create_common(struct inode *dir, struct dentry *dentry,
struct dentry *dentry, umode_t mode, dev_t rdev) struct inode *inode)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_root *root = BTRFS_I(dir)->root;
struct inode *inode; struct btrfs_trans_handle *trans;
int err; int err;
u64 index = 0; u64 index = 0;
inode = new_inode(dir->i_sb);
if (!inode)
return -ENOMEM;
inode_init_owner(mnt_userns, inode, dir, mode);
inode->i_op = &btrfs_special_inode_operations;
init_special_inode(inode, inode->i_mode, rdev);
/* /*
* 2 for inode item and ref * 2 for inode item and ref
* 2 for dir items * 2 for dir items
...@@ -6366,33 +6358,45 @@ static int btrfs_mknod(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -6366,33 +6358,45 @@ static int btrfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
if (err) if (err)
goto out_unlock; goto out_unlock;
err = btrfs_update_inode(trans, root, BTRFS_I(inode));
if (err)
goto out_unlock;
err = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode), err = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode),
dentry->d_name.name, dentry->d_name.len, 0, index); dentry->d_name.name, dentry->d_name.len, 0, index);
if (err) if (err)
goto out_unlock; goto out_unlock;
btrfs_update_inode(trans, root, BTRFS_I(inode));
d_instantiate_new(dentry, inode); d_instantiate_new(dentry, inode);
out_unlock: out_unlock:
btrfs_end_transaction(trans); btrfs_end_transaction(trans);
btrfs_btree_balance_dirty(fs_info);
if (err && inode) { if (err && inode) {
inode_dec_link_count(inode); inode_dec_link_count(inode);
discard_new_inode(inode); discard_new_inode(inode);
} }
btrfs_btree_balance_dirty(fs_info);
return err; return err;
} }
static int btrfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode, dev_t rdev)
{
struct inode *inode;
inode = new_inode(dir->i_sb);
if (!inode)
return -ENOMEM;
inode_init_owner(mnt_userns, inode, dir, mode);
inode->i_op = &btrfs_special_inode_operations;
init_special_inode(inode, inode->i_mode, rdev);
return btrfs_create_common(dir, dentry, inode);
}
static int btrfs_create(struct user_namespace *mnt_userns, struct inode *dir, static int btrfs_create(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode, bool excl) struct dentry *dentry, umode_t mode, bool excl)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(dir)->root;
struct inode *inode; struct inode *inode;
int err;
u64 index = 0;
inode = new_inode(dir->i_sb); inode = new_inode(dir->i_sb);
if (!inode) if (!inode)
...@@ -6401,49 +6405,7 @@ static int btrfs_create(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -6401,49 +6405,7 @@ static int btrfs_create(struct user_namespace *mnt_userns, struct inode *dir,
inode->i_fop = &btrfs_file_operations; inode->i_fop = &btrfs_file_operations;
inode->i_op = &btrfs_file_inode_operations; inode->i_op = &btrfs_file_inode_operations;
inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->a_ops = &btrfs_aops;
return btrfs_create_common(dir, dentry, inode);
/*
* 2 for inode item and ref
* 2 for dir items
* 1 for xattr if selinux is on
*/
trans = btrfs_start_transaction(root, 5);
if (IS_ERR(trans)) {
iput(inode);
return PTR_ERR(trans);
}
err = btrfs_new_inode(trans, root, inode, dir, dentry->d_name.name,
dentry->d_name.len, &index);
if (err) {
iput(inode);
inode = NULL;
goto out_unlock;
}
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_unlock;
err = btrfs_update_inode(trans, root, BTRFS_I(inode));
if (err)
goto out_unlock;
err = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode),
dentry->d_name.name, dentry->d_name.len, 0, index);
if (err)
goto out_unlock;
d_instantiate_new(dentry, inode);
out_unlock:
btrfs_end_transaction(trans);
if (err && inode) {
inode_dec_link_count(inode);
discard_new_inode(inode);
}
btrfs_btree_balance_dirty(fs_info);
return err;
} }
static int btrfs_link(struct dentry *old_dentry, struct inode *dir, static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
...@@ -6527,12 +6489,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -6527,12 +6489,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
static int btrfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, static int btrfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode) struct dentry *dentry, umode_t mode)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
struct inode *inode; struct inode *inode;
struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(dir)->root;
int err;
u64 index = 0;
inode = new_inode(dir->i_sb); inode = new_inode(dir->i_sb);
if (!inode) if (!inode)
...@@ -6540,50 +6497,7 @@ static int btrfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -6540,50 +6497,7 @@ static int btrfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
inode_init_owner(mnt_userns, inode, dir, S_IFDIR | mode); inode_init_owner(mnt_userns, inode, dir, S_IFDIR | mode);
inode->i_op = &btrfs_dir_inode_operations; inode->i_op = &btrfs_dir_inode_operations;
inode->i_fop = &btrfs_dir_file_operations; inode->i_fop = &btrfs_dir_file_operations;
return btrfs_create_common(dir, dentry, inode);
/*
* 2 items for inode and ref
* 2 items for dir items
* 1 for xattr if selinux is on
*/
trans = btrfs_start_transaction(root, 5);
if (IS_ERR(trans)) {
iput(inode);
return PTR_ERR(trans);
}
err = btrfs_new_inode(trans, root, inode, dir, dentry->d_name.name,
dentry->d_name.len, &index);
if (err) {
iput(inode);
inode = NULL;
goto out_fail;
}
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_fail;
err = btrfs_update_inode(trans, root, BTRFS_I(inode));
if (err)
goto out_fail;
err = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode),
dentry->d_name.name,
dentry->d_name.len, 0, index);
if (err)
goto out_fail;
d_instantiate_new(dentry, inode);
out_fail:
btrfs_end_transaction(trans);
if (err && inode) {
inode_dec_link_count(inode);
discard_new_inode(inode);
}
btrfs_btree_balance_dirty(fs_info);
return err;
} }
static noinline int uncompress_inline(struct btrfs_path *path, static noinline int uncompress_inline(struct btrfs_path *path,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment