diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 53ca025655fc..a79299a89b7d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1335,8 +1335,11 @@ next_slot: | |||
1335 | leaf = path->nodes[0]; | 1335 | leaf = path->nodes[0]; |
1336 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | 1336 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { |
1337 | ret = btrfs_next_leaf(root, path); | 1337 | ret = btrfs_next_leaf(root, path); |
1338 | if (ret < 0) | 1338 | if (ret < 0) { |
1339 | if (cow_start != (u64)-1) | ||
1340 | cur_offset = cow_start; | ||
1339 | goto error; | 1341 | goto error; |
1342 | } | ||
1340 | if (ret > 0) | 1343 | if (ret > 0) |
1341 | break; | 1344 | break; |
1342 | leaf = path->nodes[0]; | 1345 | leaf = path->nodes[0]; |
@@ -3385,6 +3388,11 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, | |||
3385 | ret = btrfs_orphan_reserve_metadata(trans, inode); | 3388 | ret = btrfs_orphan_reserve_metadata(trans, inode); |
3386 | ASSERT(!ret); | 3389 | ASSERT(!ret); |
3387 | if (ret) { | 3390 | if (ret) { |
3391 | /* | ||
3392 | * dec doesn't need spin_lock as ->orphan_block_rsv | ||
3393 | * would be released only if ->orphan_inodes is | ||
3394 | * zero. | ||
3395 | */ | ||
3388 | atomic_dec(&root->orphan_inodes); | 3396 | atomic_dec(&root->orphan_inodes); |
3389 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, | 3397 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, |
3390 | &inode->runtime_flags); | 3398 | &inode->runtime_flags); |
@@ -3399,12 +3407,17 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, | |||
3399 | if (insert >= 1) { | 3407 | if (insert >= 1) { |
3400 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); | 3408 | ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); |
3401 | if (ret) { | 3409 | if (ret) { |
3402 | atomic_dec(&root->orphan_inodes); | ||
3403 | if (reserve) { | 3410 | if (reserve) { |
3404 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, | 3411 | clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, |
3405 | &inode->runtime_flags); | 3412 | &inode->runtime_flags); |
3406 | btrfs_orphan_release_metadata(inode); | 3413 | btrfs_orphan_release_metadata(inode); |
3407 | } | 3414 | } |
3415 | /* | ||
3416 | * btrfs_orphan_commit_root may race with us and set | ||
3417 | * ->orphan_block_rsv to zero, in order to avoid that, | ||
3418 | * decrease ->orphan_inodes after everything is done. | ||
3419 | */ | ||
3420 | atomic_dec(&root->orphan_inodes); | ||
3408 | if (ret != -EEXIST) { | 3421 | if (ret != -EEXIST) { |
3409 | clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | 3422 | clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, |
3410 | &inode->runtime_flags); | 3423 | &inode->runtime_flags); |
@@ -3436,28 +3449,26 @@ static int btrfs_orphan_del(struct btrfs_trans_handle *trans, | |||
3436 | { | 3449 | { |
3437 | struct btrfs_root *root = inode->root; | 3450 | struct btrfs_root *root = inode->root; |
3438 | int delete_item = 0; | 3451 | int delete_item = 0; |
3439 | int release_rsv = 0; | ||
3440 | int ret = 0; | 3452 | int ret = 0; |
3441 | 3453 | ||
3442 | spin_lock(&root->orphan_lock); | ||
3443 | if (test_and_clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, | 3454 | if (test_and_clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, |
3444 | &inode->runtime_flags)) | 3455 | &inode->runtime_flags)) |
3445 | delete_item = 1; | 3456 | delete_item = 1; |
3446 | 3457 | ||
3458 | if (delete_item && trans) | ||
3459 | ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode)); | ||
3460 | |||
3447 | if (test_and_clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, | 3461 | if (test_and_clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED, |
3448 | &inode->runtime_flags)) | 3462 | &inode->runtime_flags)) |
3449 | release_rsv = 1; | 3463 | btrfs_orphan_release_metadata(inode); |
3450 | spin_unlock(&root->orphan_lock); | ||
3451 | 3464 | ||
3452 | if (delete_item) { | 3465 | /* |
3466 | * btrfs_orphan_commit_root may race with us and set ->orphan_block_rsv | ||
3467 | * to zero, in order to avoid that, decrease ->orphan_inodes after | ||
3468 | * everything is done. | ||
3469 | */ | ||
3470 | if (delete_item) | ||
3453 | atomic_dec(&root->orphan_inodes); | 3471 | atomic_dec(&root->orphan_inodes); |
3454 | if (trans) | ||
3455 | ret = btrfs_del_orphan_item(trans, root, | ||
3456 | btrfs_ino(inode)); | ||
3457 | } | ||
3458 | |||
3459 | if (release_rsv) | ||
3460 | btrfs_orphan_release_metadata(inode); | ||
3461 | 3472 | ||
3462 | return ret; | 3473 | return ret; |
3463 | } | 3474 | } |
@@ -5281,7 +5292,7 @@ void btrfs_evict_inode(struct inode *inode) | |||
5281 | trace_btrfs_inode_evict(inode); | 5292 | trace_btrfs_inode_evict(inode); |
5282 | 5293 | ||
5283 | if (!root) { | 5294 | if (!root) { |
5284 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | 5295 | clear_inode(inode); |
5285 | return; | 5296 | return; |
5286 | } | 5297 | } |
5287 | 5298 | ||