diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-08-05 11:18:09 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:06 -0400 |
commit | 00e4e6b33a0f78aab4b788d6d31c884fd8bf88da (patch) | |
tree | 726c1b05385f15566aa5c14ff694870f6eb6def2 /fs/btrfs/inode.c | |
parent | 7d2b4daa67379960477568abda62b8ba9ee3a8aa (diff) |
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: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 99121a55ffbe..4d8ffc01931e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2153,7 +2153,8 @@ out: | |||
2153 | return ret; | 2153 | return ret; |
2154 | } | 2154 | } |
2155 | 2155 | ||
2156 | static int btrfs_set_inode_index(struct inode *dir, struct inode *inode) | 2156 | static int btrfs_set_inode_index(struct inode *dir, struct inode *inode, |
2157 | u64 *index) | ||
2157 | { | 2158 | { |
2158 | int ret = 0; | 2159 | int ret = 0; |
2159 | 2160 | ||
@@ -2163,7 +2164,7 @@ static int btrfs_set_inode_index(struct inode *dir, struct inode *inode) | |||
2163 | return ret; | 2164 | return ret; |
2164 | } | 2165 | } |
2165 | 2166 | ||
2166 | BTRFS_I(inode)->index = BTRFS_I(dir)->index_cnt; | 2167 | *index = BTRFS_I(dir)->index_cnt; |
2167 | BTRFS_I(dir)->index_cnt++; | 2168 | BTRFS_I(dir)->index_cnt++; |
2168 | 2169 | ||
2169 | return ret; | 2170 | return ret; |
@@ -2176,7 +2177,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
2176 | u64 ref_objectid, | 2177 | u64 ref_objectid, |
2177 | u64 objectid, | 2178 | u64 objectid, |
2178 | struct btrfs_block_group_cache *group, | 2179 | struct btrfs_block_group_cache *group, |
2179 | int mode) | 2180 | int mode, u64 *index) |
2180 | { | 2181 | { |
2181 | struct inode *inode; | 2182 | struct inode *inode; |
2182 | struct btrfs_inode_item *inode_item; | 2183 | struct btrfs_inode_item *inode_item; |
@@ -2198,11 +2199,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
2198 | return ERR_PTR(-ENOMEM); | 2199 | return ERR_PTR(-ENOMEM); |
2199 | 2200 | ||
2200 | if (dir) { | 2201 | if (dir) { |
2201 | ret = btrfs_set_inode_index(dir, inode); | 2202 | ret = btrfs_set_inode_index(dir, inode, index); |
2202 | if (ret) | 2203 | if (ret) |
2203 | return ERR_PTR(ret); | 2204 | return ERR_PTR(ret); |
2204 | } else { | ||
2205 | BTRFS_I(inode)->index = 0; | ||
2206 | } | 2205 | } |
2207 | /* | 2206 | /* |
2208 | * index_cnt is ignored for everything but a dir, | 2207 | * 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 | ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1, | 2267 | ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1, |
2269 | struct btrfs_inode_ref); | 2268 | struct btrfs_inode_ref); |
2270 | btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len); | 2269 | btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len); |
2271 | btrfs_set_inode_ref_index(path->nodes[0], ref, BTRFS_I(inode)->index); | 2270 | btrfs_set_inode_ref_index(path->nodes[0], ref, *index); |
2272 | ptr = (unsigned long)(ref + 1); | 2271 | ptr = (unsigned long)(ref + 1); |
2273 | write_extent_buffer(path->nodes[0], name, ptr, name_len); | 2272 | write_extent_buffer(path->nodes[0], name, ptr, name_len); |
2274 | 2273 | ||
@@ -2296,7 +2295,7 @@ static inline u8 btrfs_inode_type(struct inode *inode) | |||
2296 | 2295 | ||
2297 | static int btrfs_add_link(struct btrfs_trans_handle *trans, | 2296 | static int btrfs_add_link(struct btrfs_trans_handle *trans, |
2298 | struct dentry *dentry, struct inode *inode, | 2297 | struct dentry *dentry, struct inode *inode, |
2299 | int add_backref) | 2298 | int add_backref, u64 index) |
2300 | { | 2299 | { |
2301 | int ret; | 2300 | int ret; |
2302 | struct btrfs_key key; | 2301 | struct btrfs_key key; |
@@ -2311,7 +2310,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
2311 | dentry->d_name.name, dentry->d_name.len, | 2310 | dentry->d_name.name, dentry->d_name.len, |
2312 | dentry->d_parent->d_inode->i_ino, | 2311 | dentry->d_parent->d_inode->i_ino, |
2313 | &key, btrfs_inode_type(inode), | 2312 | &key, btrfs_inode_type(inode), |
2314 | BTRFS_I(inode)->index); | 2313 | index); |
2315 | if (ret == 0) { | 2314 | if (ret == 0) { |
2316 | if (add_backref) { | 2315 | if (add_backref) { |
2317 | ret = btrfs_insert_inode_ref(trans, root, | 2316 | ret = btrfs_insert_inode_ref(trans, root, |
@@ -2319,7 +2318,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
2319 | dentry->d_name.len, | 2318 | dentry->d_name.len, |
2320 | inode->i_ino, | 2319 | inode->i_ino, |
2321 | parent_inode->i_ino, | 2320 | parent_inode->i_ino, |
2322 | BTRFS_I(inode)->index); | 2321 | index); |
2323 | } | 2322 | } |
2324 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 2323 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
2325 | dentry->d_name.len * 2); | 2324 | dentry->d_name.len * 2); |
@@ -2332,9 +2331,9 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
2332 | 2331 | ||
2333 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | 2332 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, |
2334 | struct dentry *dentry, struct inode *inode, | 2333 | struct dentry *dentry, struct inode *inode, |
2335 | int backref) | 2334 | int backref, u64 index) |
2336 | { | 2335 | { |
2337 | int err = btrfs_add_link(trans, dentry, inode, backref); | 2336 | int err = btrfs_add_link(trans, dentry, inode, backref, index); |
2338 | if (!err) { | 2337 | if (!err) { |
2339 | d_instantiate(dentry, inode); | 2338 | d_instantiate(dentry, inode); |
2340 | return 0; | 2339 | return 0; |
@@ -2354,6 +2353,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
2354 | int drop_inode = 0; | 2353 | int drop_inode = 0; |
2355 | u64 objectid; | 2354 | u64 objectid; |
2356 | unsigned long nr = 0; | 2355 | unsigned long nr = 0; |
2356 | u64 index = 0; | ||
2357 | 2357 | ||
2358 | if (!new_valid_dev(rdev)) | 2358 | if (!new_valid_dev(rdev)) |
2359 | return -EINVAL; | 2359 | return -EINVAL; |
@@ -2374,7 +2374,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
2374 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 2374 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
2375 | dentry->d_name.len, | 2375 | dentry->d_name.len, |
2376 | dentry->d_parent->d_inode->i_ino, objectid, | 2376 | dentry->d_parent->d_inode->i_ino, objectid, |
2377 | BTRFS_I(dir)->block_group, mode); | 2377 | BTRFS_I(dir)->block_group, mode, &index); |
2378 | err = PTR_ERR(inode); | 2378 | err = PTR_ERR(inode); |
2379 | if (IS_ERR(inode)) | 2379 | if (IS_ERR(inode)) |
2380 | goto out_unlock; | 2380 | goto out_unlock; |
@@ -2386,7 +2386,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
2386 | } | 2386 | } |
2387 | 2387 | ||
2388 | btrfs_set_trans_block_group(trans, inode); | 2388 | btrfs_set_trans_block_group(trans, inode); |
2389 | err = btrfs_add_nondir(trans, dentry, inode, 0); | 2389 | err = btrfs_add_nondir(trans, dentry, inode, 0, index); |
2390 | if (err) | 2390 | if (err) |
2391 | drop_inode = 1; | 2391 | drop_inode = 1; |
2392 | else { | 2392 | else { |
@@ -2419,6 +2419,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
2419 | int drop_inode = 0; | 2419 | int drop_inode = 0; |
2420 | unsigned long nr = 0; | 2420 | unsigned long nr = 0; |
2421 | u64 objectid; | 2421 | u64 objectid; |
2422 | u64 index = 0; | ||
2422 | 2423 | ||
2423 | err = btrfs_check_free_space(root, 1, 0); | 2424 | err = btrfs_check_free_space(root, 1, 0); |
2424 | if (err) | 2425 | if (err) |
@@ -2435,7 +2436,8 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
2435 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 2436 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
2436 | dentry->d_name.len, | 2437 | dentry->d_name.len, |
2437 | dentry->d_parent->d_inode->i_ino, | 2438 | dentry->d_parent->d_inode->i_ino, |
2438 | objectid, BTRFS_I(dir)->block_group, mode); | 2439 | objectid, BTRFS_I(dir)->block_group, mode, |
2440 | &index); | ||
2439 | err = PTR_ERR(inode); | 2441 | err = PTR_ERR(inode); |
2440 | if (IS_ERR(inode)) | 2442 | if (IS_ERR(inode)) |
2441 | goto out_unlock; | 2443 | goto out_unlock; |
@@ -2447,7 +2449,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
2447 | } | 2449 | } |
2448 | 2450 | ||
2449 | btrfs_set_trans_block_group(trans, inode); | 2451 | btrfs_set_trans_block_group(trans, inode); |
2450 | err = btrfs_add_nondir(trans, dentry, inode, 0); | 2452 | err = btrfs_add_nondir(trans, dentry, inode, 0, index); |
2451 | if (err) | 2453 | if (err) |
2452 | drop_inode = 1; | 2454 | drop_inode = 1; |
2453 | else { | 2455 | else { |
@@ -2489,6 +2491,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
2489 | struct btrfs_trans_handle *trans; | 2491 | struct btrfs_trans_handle *trans; |
2490 | struct btrfs_root *root = BTRFS_I(dir)->root; | 2492 | struct btrfs_root *root = BTRFS_I(dir)->root; |
2491 | struct inode *inode = old_dentry->d_inode; | 2493 | struct inode *inode = old_dentry->d_inode; |
2494 | u64 index; | ||
2492 | unsigned long nr = 0; | 2495 | unsigned long nr = 0; |
2493 | int err; | 2496 | int err; |
2494 | int drop_inode = 0; | 2497 | int drop_inode = 0; |
@@ -2504,7 +2507,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
2504 | err = btrfs_check_free_space(root, 1, 0); | 2507 | err = btrfs_check_free_space(root, 1, 0); |
2505 | if (err) | 2508 | if (err) |
2506 | goto fail; | 2509 | goto fail; |
2507 | err = btrfs_set_inode_index(dir, inode); | 2510 | err = btrfs_set_inode_index(dir, inode, &index); |
2508 | if (err) | 2511 | if (err) |
2509 | goto fail; | 2512 | goto fail; |
2510 | 2513 | ||
@@ -2513,7 +2516,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
2513 | btrfs_set_trans_block_group(trans, dir); | 2516 | btrfs_set_trans_block_group(trans, dir); |
2514 | atomic_inc(&inode->i_count); | 2517 | atomic_inc(&inode->i_count); |
2515 | 2518 | ||
2516 | err = btrfs_add_nondir(trans, dentry, inode, 1); | 2519 | err = btrfs_add_nondir(trans, dentry, inode, 1, index); |
2517 | 2520 | ||
2518 | if (err) | 2521 | if (err) |
2519 | drop_inode = 1; | 2522 | drop_inode = 1; |
@@ -2544,6 +2547,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
2544 | int err = 0; | 2547 | int err = 0; |
2545 | int drop_on_err = 0; | 2548 | int drop_on_err = 0; |
2546 | u64 objectid = 0; | 2549 | u64 objectid = 0; |
2550 | u64 index = 0; | ||
2547 | unsigned long nr = 1; | 2551 | unsigned long nr = 1; |
2548 | 2552 | ||
2549 | err = btrfs_check_free_space(root, 1, 0); | 2553 | 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 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 2571 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
2568 | dentry->d_name.len, | 2572 | dentry->d_name.len, |
2569 | dentry->d_parent->d_inode->i_ino, objectid, | 2573 | dentry->d_parent->d_inode->i_ino, objectid, |
2570 | BTRFS_I(dir)->block_group, S_IFDIR | mode); | 2574 | BTRFS_I(dir)->block_group, S_IFDIR | mode, |
2575 | &index); | ||
2571 | if (IS_ERR(inode)) { | 2576 | if (IS_ERR(inode)) { |
2572 | err = PTR_ERR(inode); | 2577 | err = PTR_ERR(inode); |
2573 | goto out_fail; | 2578 | goto out_fail; |
@@ -2588,7 +2593,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
2588 | if (err) | 2593 | if (err) |
2589 | goto out_fail; | 2594 | goto out_fail; |
2590 | 2595 | ||
2591 | err = btrfs_add_link(trans, dentry, inode, 0); | 2596 | err = btrfs_add_link(trans, dentry, inode, 0, index); |
2592 | if (err) | 2597 | if (err) |
2593 | goto out_fail; | 2598 | goto out_fail; |
2594 | 2599 | ||
@@ -3203,9 +3208,10 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, | |||
3203 | struct btrfs_block_group_cache *block_group) | 3208 | struct btrfs_block_group_cache *block_group) |
3204 | { | 3209 | { |
3205 | struct inode *inode; | 3210 | struct inode *inode; |
3211 | u64 index = 0; | ||
3206 | 3212 | ||
3207 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, | 3213 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, |
3208 | new_dirid, block_group, S_IFDIR | 0700); | 3214 | new_dirid, block_group, S_IFDIR | 0700, &index); |
3209 | if (IS_ERR(inode)) | 3215 | if (IS_ERR(inode)) |
3210 | return PTR_ERR(inode); | 3216 | return PTR_ERR(inode); |
3211 | inode->i_op = &btrfs_dir_inode_operations; | 3217 | inode->i_op = &btrfs_dir_inode_operations; |
@@ -3384,6 +3390,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
3384 | struct inode *new_inode = new_dentry->d_inode; | 3390 | struct inode *new_inode = new_dentry->d_inode; |
3385 | struct inode *old_inode = old_dentry->d_inode; | 3391 | struct inode *old_inode = old_dentry->d_inode; |
3386 | struct timespec ctime = CURRENT_TIME; | 3392 | struct timespec ctime = CURRENT_TIME; |
3393 | u64 index = 0; | ||
3387 | int ret; | 3394 | int ret; |
3388 | 3395 | ||
3389 | if (S_ISDIR(old_inode->i_mode) && new_inode && | 3396 | 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 | goto out_fail; | 3426 | goto out_fail; |
3420 | } | 3427 | } |
3421 | } | 3428 | } |
3422 | ret = btrfs_set_inode_index(new_dir, old_inode); | 3429 | ret = btrfs_set_inode_index(new_dir, old_inode, &index); |
3423 | if (ret) | 3430 | if (ret) |
3424 | goto out_fail; | 3431 | goto out_fail; |
3425 | 3432 | ||
3426 | ret = btrfs_add_link(trans, new_dentry, old_inode, 1); | 3433 | ret = btrfs_add_link(trans, new_dentry, old_inode, 1, index); |
3427 | if (ret) | 3434 | if (ret) |
3428 | goto out_fail; | 3435 | goto out_fail; |
3429 | 3436 | ||
@@ -3464,6 +3471,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
3464 | int err; | 3471 | int err; |
3465 | int drop_inode = 0; | 3472 | int drop_inode = 0; |
3466 | u64 objectid; | 3473 | u64 objectid; |
3474 | u64 index = 0 ; | ||
3467 | int name_len; | 3475 | int name_len; |
3468 | int datasize; | 3476 | int datasize; |
3469 | unsigned long ptr; | 3477 | unsigned long ptr; |
@@ -3491,7 +3499,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
3491 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 3499 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
3492 | dentry->d_name.len, | 3500 | dentry->d_name.len, |
3493 | dentry->d_parent->d_inode->i_ino, objectid, | 3501 | dentry->d_parent->d_inode->i_ino, objectid, |
3494 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO); | 3502 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, |
3503 | &index); | ||
3495 | err = PTR_ERR(inode); | 3504 | err = PTR_ERR(inode); |
3496 | if (IS_ERR(inode)) | 3505 | if (IS_ERR(inode)) |
3497 | goto out_unlock; | 3506 | goto out_unlock; |
@@ -3503,7 +3512,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
3503 | } | 3512 | } |
3504 | 3513 | ||
3505 | btrfs_set_trans_block_group(trans, inode); | 3514 | btrfs_set_trans_block_group(trans, inode); |
3506 | err = btrfs_add_nondir(trans, dentry, inode, 0); | 3515 | err = btrfs_add_nondir(trans, dentry, inode, 0, index); |
3507 | if (err) | 3516 | if (err) |
3508 | drop_inode = 1; | 3517 | drop_inode = 1; |
3509 | else { | 3518 | else { |