Commit 00e4e6b3 authored by Chris Mason's avatar Chris Mason

Get rid of BTRFS_I(inode)->index and use local vars instead

rename and link don't always have a lock on the source inode, and
our use of a per-inode index variable was racy.  This changes things to
store the index in a local variable instead.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 7d2b4daa
...@@ -57,15 +57,6 @@ struct btrfs_inode { ...@@ -57,15 +57,6 @@ struct btrfs_inode {
* number for new files that are created * number for new files that are created
*/ */
u64 index_cnt; u64 index_cnt;
/*
* index holds the directory index for this inode on creation, so
* add_link can do what its supposed to. This isn't populated when the
* inode is read because there isn't really a reason to know this unless
* we are creating the directory index or deleting it, and deletion
* reads the index off of the inode reference at unlink time.
*/
u64 index;
}; };
static inline struct btrfs_inode *BTRFS_I(struct inode *inode) static inline struct btrfs_inode *BTRFS_I(struct inode *inode)
......
...@@ -2153,7 +2153,8 @@ static int btrfs_set_inode_index_count(struct inode *inode) ...@@ -2153,7 +2153,8 @@ static int btrfs_set_inode_index_count(struct inode *inode)
return ret; return ret;
} }
static int btrfs_set_inode_index(struct inode *dir, struct inode *inode) static int btrfs_set_inode_index(struct inode *dir, struct inode *inode,
u64 *index)
{ {
int ret = 0; int ret = 0;
...@@ -2163,7 +2164,7 @@ static int btrfs_set_inode_index(struct inode *dir, struct inode *inode) ...@@ -2163,7 +2164,7 @@ static int btrfs_set_inode_index(struct inode *dir, struct inode *inode)
return ret; return ret;
} }
BTRFS_I(inode)->index = BTRFS_I(dir)->index_cnt; *index = BTRFS_I(dir)->index_cnt;
BTRFS_I(dir)->index_cnt++; BTRFS_I(dir)->index_cnt++;
return ret; return ret;
...@@ -2176,7 +2177,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -2176,7 +2177,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
u64 ref_objectid, u64 ref_objectid,
u64 objectid, u64 objectid,
struct btrfs_block_group_cache *group, struct btrfs_block_group_cache *group,
int mode) int mode, u64 *index)
{ {
struct inode *inode; struct inode *inode;
struct btrfs_inode_item *inode_item; struct btrfs_inode_item *inode_item;
...@@ -2198,11 +2199,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -2198,11 +2199,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (dir) { if (dir) {
ret = btrfs_set_inode_index(dir, inode); ret = btrfs_set_inode_index(dir, inode, index);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
} else {
BTRFS_I(inode)->index = 0;
} }
/* /*
* index_cnt is ignored for everything but a dir, * index_cnt is ignored for everything but a dir,
...@@ -2268,7 +2267,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -2268,7 +2267,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1, ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1,
struct btrfs_inode_ref); struct btrfs_inode_ref);
btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len); btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
btrfs_set_inode_ref_index(path->nodes[0], ref, BTRFS_I(inode)->index); btrfs_set_inode_ref_index(path->nodes[0], ref, *index);
ptr = (unsigned long)(ref + 1); ptr = (unsigned long)(ref + 1);
write_extent_buffer(path->nodes[0], name, ptr, name_len); write_extent_buffer(path->nodes[0], name, ptr, name_len);
...@@ -2296,7 +2295,7 @@ static inline u8 btrfs_inode_type(struct inode *inode) ...@@ -2296,7 +2295,7 @@ static inline u8 btrfs_inode_type(struct inode *inode)
static int btrfs_add_link(struct btrfs_trans_handle *trans, static int btrfs_add_link(struct btrfs_trans_handle *trans,
struct dentry *dentry, struct inode *inode, struct dentry *dentry, struct inode *inode,
int add_backref) int add_backref, u64 index)
{ {
int ret; int ret;
struct btrfs_key key; struct btrfs_key key;
...@@ -2311,7 +2310,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, ...@@ -2311,7 +2310,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
dentry->d_name.name, dentry->d_name.len, dentry->d_name.name, dentry->d_name.len,
dentry->d_parent->d_inode->i_ino, dentry->d_parent->d_inode->i_ino,
&key, btrfs_inode_type(inode), &key, btrfs_inode_type(inode),
BTRFS_I(inode)->index); index);
if (ret == 0) { if (ret == 0) {
if (add_backref) { if (add_backref) {
ret = btrfs_insert_inode_ref(trans, root, ret = btrfs_insert_inode_ref(trans, root,
...@@ -2319,7 +2318,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, ...@@ -2319,7 +2318,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
dentry->d_name.len, dentry->d_name.len,
inode->i_ino, inode->i_ino,
parent_inode->i_ino, parent_inode->i_ino,
BTRFS_I(inode)->index); index);
} }
btrfs_i_size_write(parent_inode, parent_inode->i_size + btrfs_i_size_write(parent_inode, parent_inode->i_size +
dentry->d_name.len * 2); dentry->d_name.len * 2);
...@@ -2332,9 +2331,9 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, ...@@ -2332,9 +2331,9 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
static int btrfs_add_nondir(struct btrfs_trans_handle *trans, static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
struct dentry *dentry, struct inode *inode, struct dentry *dentry, struct inode *inode,
int backref) int backref, u64 index)
{ {
int err = btrfs_add_link(trans, dentry, inode, backref); int err = btrfs_add_link(trans, dentry, inode, backref, index);
if (!err) { if (!err) {
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
return 0; return 0;
...@@ -2354,6 +2353,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, ...@@ -2354,6 +2353,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
int drop_inode = 0; int drop_inode = 0;
u64 objectid; u64 objectid;
unsigned long nr = 0; unsigned long nr = 0;
u64 index = 0;
if (!new_valid_dev(rdev)) if (!new_valid_dev(rdev))
return -EINVAL; return -EINVAL;
...@@ -2374,7 +2374,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, ...@@ -2374,7 +2374,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
dentry->d_name.len, dentry->d_name.len,
dentry->d_parent->d_inode->i_ino, objectid, dentry->d_parent->d_inode->i_ino, objectid,
BTRFS_I(dir)->block_group, mode); BTRFS_I(dir)->block_group, mode, &index);
err = PTR_ERR(inode); err = PTR_ERR(inode);
if (IS_ERR(inode)) if (IS_ERR(inode))
goto out_unlock; goto out_unlock;
...@@ -2386,7 +2386,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, ...@@ -2386,7 +2386,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
} }
btrfs_set_trans_block_group(trans, inode); btrfs_set_trans_block_group(trans, inode);
err = btrfs_add_nondir(trans, dentry, inode, 0); err = btrfs_add_nondir(trans, dentry, inode, 0, index);
if (err) if (err)
drop_inode = 1; drop_inode = 1;
else { else {
...@@ -2419,6 +2419,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, ...@@ -2419,6 +2419,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
int drop_inode = 0; int drop_inode = 0;
unsigned long nr = 0; unsigned long nr = 0;
u64 objectid; u64 objectid;
u64 index = 0;
err = btrfs_check_free_space(root, 1, 0); err = btrfs_check_free_space(root, 1, 0);
if (err) if (err)
...@@ -2435,7 +2436,8 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, ...@@ -2435,7 +2436,8 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
dentry->d_name.len, dentry->d_name.len,
dentry->d_parent->d_inode->i_ino, dentry->d_parent->d_inode->i_ino,
objectid, BTRFS_I(dir)->block_group, mode); objectid, BTRFS_I(dir)->block_group, mode,
&index);
err = PTR_ERR(inode); err = PTR_ERR(inode);
if (IS_ERR(inode)) if (IS_ERR(inode))
goto out_unlock; goto out_unlock;
...@@ -2447,7 +2449,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, ...@@ -2447,7 +2449,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
} }
btrfs_set_trans_block_group(trans, inode); btrfs_set_trans_block_group(trans, inode);
err = btrfs_add_nondir(trans, dentry, inode, 0); err = btrfs_add_nondir(trans, dentry, inode, 0, index);
if (err) if (err)
drop_inode = 1; drop_inode = 1;
else { else {
...@@ -2489,6 +2491,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -2489,6 +2491,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
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 = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
u64 index;
unsigned long nr = 0; unsigned long nr = 0;
int err; int err;
int drop_inode = 0; int drop_inode = 0;
...@@ -2504,7 +2507,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -2504,7 +2507,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
err = btrfs_check_free_space(root, 1, 0); err = btrfs_check_free_space(root, 1, 0);
if (err) if (err)
goto fail; goto fail;
err = btrfs_set_inode_index(dir, inode); err = btrfs_set_inode_index(dir, inode, &index);
if (err) if (err)
goto fail; goto fail;
...@@ -2513,7 +2516,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -2513,7 +2516,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
btrfs_set_trans_block_group(trans, dir); btrfs_set_trans_block_group(trans, dir);
atomic_inc(&inode->i_count); atomic_inc(&inode->i_count);
err = btrfs_add_nondir(trans, dentry, inode, 1); err = btrfs_add_nondir(trans, dentry, inode, 1, index);
if (err) if (err)
drop_inode = 1; drop_inode = 1;
...@@ -2544,6 +2547,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -2544,6 +2547,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
int err = 0; int err = 0;
int drop_on_err = 0; int drop_on_err = 0;
u64 objectid = 0; u64 objectid = 0;
u64 index = 0;
unsigned long nr = 1; unsigned long nr = 1;
err = btrfs_check_free_space(root, 1, 0); err = btrfs_check_free_space(root, 1, 0);
...@@ -2567,7 +2571,8 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -2567,7 +2571,8 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
dentry->d_name.len, dentry->d_name.len,
dentry->d_parent->d_inode->i_ino, objectid, dentry->d_parent->d_inode->i_ino, objectid,
BTRFS_I(dir)->block_group, S_IFDIR | mode); BTRFS_I(dir)->block_group, S_IFDIR | mode,
&index);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
goto out_fail; goto out_fail;
...@@ -2588,7 +2593,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -2588,7 +2593,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
if (err) if (err)
goto out_fail; goto out_fail;
err = btrfs_add_link(trans, dentry, inode, 0); err = btrfs_add_link(trans, dentry, inode, 0, index);
if (err) if (err)
goto out_fail; goto out_fail;
...@@ -3203,9 +3208,10 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, ...@@ -3203,9 +3208,10 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root,
struct btrfs_block_group_cache *block_group) struct btrfs_block_group_cache *block_group)
{ {
struct inode *inode; struct inode *inode;
u64 index = 0;
inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid,
new_dirid, block_group, S_IFDIR | 0700); new_dirid, block_group, S_IFDIR | 0700, &index);
if (IS_ERR(inode)) if (IS_ERR(inode))
return PTR_ERR(inode); return PTR_ERR(inode);
inode->i_op = &btrfs_dir_inode_operations; inode->i_op = &btrfs_dir_inode_operations;
...@@ -3384,6 +3390,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -3384,6 +3390,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
struct inode *new_inode = new_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode;
struct inode *old_inode = old_dentry->d_inode; struct inode *old_inode = old_dentry->d_inode;
struct timespec ctime = CURRENT_TIME; struct timespec ctime = CURRENT_TIME;
u64 index = 0;
int ret; int ret;
if (S_ISDIR(old_inode->i_mode) && new_inode && if (S_ISDIR(old_inode->i_mode) && new_inode &&
...@@ -3419,11 +3426,11 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -3419,11 +3426,11 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
goto out_fail; goto out_fail;
} }
} }
ret = btrfs_set_inode_index(new_dir, old_inode); ret = btrfs_set_inode_index(new_dir, old_inode, &index);
if (ret) if (ret)
goto out_fail; goto out_fail;
ret = btrfs_add_link(trans, new_dentry, old_inode, 1); ret = btrfs_add_link(trans, new_dentry, old_inode, 1, index);
if (ret) if (ret)
goto out_fail; goto out_fail;
...@@ -3464,6 +3471,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -3464,6 +3471,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
int err; int err;
int drop_inode = 0; int drop_inode = 0;
u64 objectid; u64 objectid;
u64 index = 0 ;
int name_len; int name_len;
int datasize; int datasize;
unsigned long ptr; unsigned long ptr;
...@@ -3491,7 +3499,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -3491,7 +3499,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
dentry->d_name.len, dentry->d_name.len,
dentry->d_parent->d_inode->i_ino, objectid, dentry->d_parent->d_inode->i_ino, objectid,
BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO); BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,
&index);
err = PTR_ERR(inode); err = PTR_ERR(inode);
if (IS_ERR(inode)) if (IS_ERR(inode))
goto out_unlock; goto out_unlock;
...@@ -3503,7 +3512,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -3503,7 +3512,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
} }
btrfs_set_trans_block_group(trans, inode); btrfs_set_trans_block_group(trans, inode);
err = btrfs_add_nondir(trans, dentry, inode, 0); err = btrfs_add_nondir(trans, dentry, inode, 0, index);
if (err) if (err)
drop_inode = 1; drop_inode = 1;
else { else {
......
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