btrfs: switch to discard_new_inode()
Make sure that no partially set up inodes can be returned by open-by-handle. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
c2b6d621c4
commit
32955c5422
fs/btrfs
102
fs/btrfs/inode.c
102
fs/btrfs/inode.c
|
@ -6335,8 +6335,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
||||||
location->type = BTRFS_INODE_ITEM_KEY;
|
location->type = BTRFS_INODE_ITEM_KEY;
|
||||||
|
|
||||||
ret = btrfs_insert_inode_locked(inode);
|
ret = btrfs_insert_inode_locked(inode);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
iput(inode);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
path->leave_spinning = 1;
|
path->leave_spinning = 1;
|
||||||
ret = btrfs_insert_empty_items(trans, root, path, key, sizes, nitems);
|
ret = btrfs_insert_empty_items(trans, root, path, key, sizes, nitems);
|
||||||
|
@ -6395,12 +6397,11 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
||||||
return inode;
|
return inode;
|
||||||
|
|
||||||
fail_unlock:
|
fail_unlock:
|
||||||
unlock_new_inode(inode);
|
discard_new_inode(inode);
|
||||||
fail:
|
fail:
|
||||||
if (dir && name)
|
if (dir && name)
|
||||||
BTRFS_I(dir)->index_cnt--;
|
BTRFS_I(dir)->index_cnt--;
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
iput(inode);
|
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6505,7 +6506,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
|
||||||
struct btrfs_root *root = BTRFS_I(dir)->root;
|
struct btrfs_root *root = BTRFS_I(dir)->root;
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
int err;
|
int err;
|
||||||
int drop_inode = 0;
|
|
||||||
u64 objectid;
|
u64 objectid;
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
|
|
||||||
|
@ -6527,6 +6527,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
|
||||||
mode, &index);
|
mode, &index);
|
||||||
if (IS_ERR(inode)) {
|
if (IS_ERR(inode)) {
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
|
inode = NULL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6541,31 +6542,24 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
|
||||||
|
|
||||||
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
|
|
||||||
err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode),
|
err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode),
|
||||||
0, index);
|
0, index);
|
||||||
if (err) {
|
if (err)
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
} else {
|
|
||||||
btrfs_update_inode(trans, root, inode);
|
btrfs_update_inode(trans, root, 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);
|
btrfs_btree_balance_dirty(fs_info);
|
||||||
if (drop_inode) {
|
if (err && inode) {
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
iput(inode);
|
discard_new_inode(inode);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_unlock_inode:
|
|
||||||
drop_inode = 1;
|
|
||||||
unlock_new_inode(inode);
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
||||||
|
@ -6575,7 +6569,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans;
|
||||||
struct btrfs_root *root = BTRFS_I(dir)->root;
|
struct btrfs_root *root = BTRFS_I(dir)->root;
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
int drop_inode_on_err = 0;
|
|
||||||
int err;
|
int err;
|
||||||
u64 objectid;
|
u64 objectid;
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
|
@ -6598,9 +6591,9 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
||||||
mode, &index);
|
mode, &index);
|
||||||
if (IS_ERR(inode)) {
|
if (IS_ERR(inode)) {
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
|
inode = NULL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
drop_inode_on_err = 1;
|
|
||||||
/*
|
/*
|
||||||
* If the active LSM wants to access the inode during
|
* If the active LSM wants to access the inode during
|
||||||
* d_instantiate it needs these. Smack checks to see
|
* d_instantiate it needs these. Smack checks to see
|
||||||
|
@ -6613,33 +6606,28 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
||||||
|
|
||||||
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
|
|
||||||
err = btrfs_update_inode(trans, root, inode);
|
err = btrfs_update_inode(trans, root, inode);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
|
|
||||||
err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode),
|
err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry, BTRFS_I(inode),
|
||||||
0, index);
|
0, index);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
|
|
||||||
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
|
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
|
||||||
d_instantiate_new(dentry, inode);
|
d_instantiate_new(dentry, inode);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
btrfs_end_transaction(trans);
|
btrfs_end_transaction(trans);
|
||||||
if (err && drop_inode_on_err) {
|
if (err && inode) {
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
iput(inode);
|
discard_new_inode(inode);
|
||||||
}
|
}
|
||||||
btrfs_btree_balance_dirty(fs_info);
|
btrfs_btree_balance_dirty(fs_info);
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_unlock_inode:
|
|
||||||
unlock_new_inode(inode);
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
|
static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||||
|
@ -6748,6 +6736,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
S_IFDIR | mode, &index);
|
S_IFDIR | mode, &index);
|
||||||
if (IS_ERR(inode)) {
|
if (IS_ERR(inode)) {
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
|
inode = NULL;
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6758,34 +6747,30 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
|
|
||||||
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_fail_inode;
|
goto out_fail;
|
||||||
|
|
||||||
btrfs_i_size_write(BTRFS_I(inode), 0);
|
btrfs_i_size_write(BTRFS_I(inode), 0);
|
||||||
err = btrfs_update_inode(trans, root, inode);
|
err = btrfs_update_inode(trans, root, inode);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_fail_inode;
|
goto out_fail;
|
||||||
|
|
||||||
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.name,
|
||||||
dentry->d_name.len, 0, index);
|
dentry->d_name.len, 0, index);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_fail_inode;
|
goto out_fail;
|
||||||
|
|
||||||
d_instantiate_new(dentry, inode);
|
d_instantiate_new(dentry, inode);
|
||||||
drop_on_err = 0;
|
drop_on_err = 0;
|
||||||
|
|
||||||
out_fail:
|
out_fail:
|
||||||
btrfs_end_transaction(trans);
|
btrfs_end_transaction(trans);
|
||||||
if (drop_on_err) {
|
if (err && inode) {
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
iput(inode);
|
discard_new_inode(inode);
|
||||||
}
|
}
|
||||||
btrfs_btree_balance_dirty(fs_info);
|
btrfs_btree_balance_dirty(fs_info);
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_fail_inode:
|
|
||||||
unlock_new_inode(inode);
|
|
||||||
goto out_fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline int uncompress_inline(struct btrfs_path *path,
|
static noinline int uncompress_inline(struct btrfs_path *path,
|
||||||
|
@ -10112,7 +10097,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
int err;
|
int err;
|
||||||
int drop_inode = 0;
|
|
||||||
u64 objectid;
|
u64 objectid;
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
int name_len;
|
int name_len;
|
||||||
|
@ -10145,6 +10129,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
objectid, S_IFLNK|S_IRWXUGO, &index);
|
objectid, S_IFLNK|S_IRWXUGO, &index);
|
||||||
if (IS_ERR(inode)) {
|
if (IS_ERR(inode)) {
|
||||||
err = PTR_ERR(inode);
|
err = PTR_ERR(inode);
|
||||||
|
inode = NULL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10161,12 +10146,12 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
|
|
||||||
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
|
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
if (!path) {
|
if (!path) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
key.objectid = btrfs_ino(BTRFS_I(inode));
|
key.objectid = btrfs_ino(BTRFS_I(inode));
|
||||||
key.offset = 0;
|
key.offset = 0;
|
||||||
|
@ -10176,7 +10161,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
datasize);
|
datasize);
|
||||||
if (err) {
|
if (err) {
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
goto out_unlock_inode;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
leaf = path->nodes[0];
|
leaf = path->nodes[0];
|
||||||
ei = btrfs_item_ptr(leaf, path->slots[0],
|
ei = btrfs_item_ptr(leaf, path->slots[0],
|
||||||
|
@ -10208,26 +10193,19 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
if (!err)
|
if (!err)
|
||||||
err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry,
|
err = btrfs_add_nondir(trans, BTRFS_I(dir), dentry,
|
||||||
BTRFS_I(inode), 0, index);
|
BTRFS_I(inode), 0, index);
|
||||||
if (err) {
|
if (err)
|
||||||
drop_inode = 1;
|
goto out_unlock;
|
||||||
goto out_unlock_inode;
|
|
||||||
}
|
|
||||||
|
|
||||||
d_instantiate_new(dentry, inode);
|
d_instantiate_new(dentry, inode);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
btrfs_end_transaction(trans);
|
btrfs_end_transaction(trans);
|
||||||
if (drop_inode) {
|
if (err && inode) {
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
iput(inode);
|
discard_new_inode(inode);
|
||||||
}
|
}
|
||||||
btrfs_btree_balance_dirty(fs_info);
|
btrfs_btree_balance_dirty(fs_info);
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_unlock_inode:
|
|
||||||
drop_inode = 1;
|
|
||||||
unlock_new_inode(inode);
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
|
static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
|
||||||
|
@ -10436,14 +10414,14 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
|
|
||||||
ret = btrfs_init_inode_security(trans, inode, dir, NULL);
|
ret = btrfs_init_inode_security(trans, inode, dir, NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_inode;
|
goto out;
|
||||||
|
|
||||||
ret = btrfs_update_inode(trans, root, inode);
|
ret = btrfs_update_inode(trans, root, inode);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_inode;
|
goto out;
|
||||||
ret = btrfs_orphan_add(trans, BTRFS_I(inode));
|
ret = btrfs_orphan_add(trans, BTRFS_I(inode));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_inode;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We set number of links to 0 in btrfs_new_inode(), and here we set
|
* We set number of links to 0 in btrfs_new_inode(), and here we set
|
||||||
|
@ -10453,21 +10431,15 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
* d_tmpfile() -> inode_dec_link_count() -> drop_nlink()
|
* d_tmpfile() -> inode_dec_link_count() -> drop_nlink()
|
||||||
*/
|
*/
|
||||||
set_nlink(inode, 1);
|
set_nlink(inode, 1);
|
||||||
unlock_new_inode(inode);
|
|
||||||
d_tmpfile(dentry, inode);
|
d_tmpfile(dentry, inode);
|
||||||
|
unlock_new_inode(inode);
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
btrfs_end_transaction(trans);
|
btrfs_end_transaction(trans);
|
||||||
if (ret)
|
if (ret && inode)
|
||||||
iput(inode);
|
discard_new_inode(inode);
|
||||||
btrfs_btree_balance_dirty(fs_info);
|
btrfs_btree_balance_dirty(fs_info);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
out_inode:
|
|
||||||
unlock_new_inode(inode);
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((const))
|
__attribute__((const))
|
||||||
|
|
Loading…
Reference in New Issue