Commit 32955c54 authored by Al Viro's avatar Al Viro

btrfs: switch to discard_new_inode()

Make sure that no partially set up inodes can be returned by
open-by-handle.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c2b6d621
...@@ -6335,8 +6335,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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))
......
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