diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-20 13:47:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-20 13:47:38 -0400 |
commit | 90290c4ebe5c64ee34fea0d2cc3025cb934917b8 (patch) | |
tree | f57eff4c719ca6a39f1e5ca70598cb80e82ccf96 | |
parent | d471ce53b1fab60110e4e9f647a345cea31752de (diff) | |
parent | 115930cb2d444a684975cf2325759cb48ebf80cc (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next
Pull btrfs fixes from Josef Bacik:
"I'm playing the role of Chris Mason this week while he's on vacation.
There are a few critical fixes for btrfs here, all regressions and
have been tested well"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next:
Btrfs: fix wrong write offset when replacing a device
Btrfs: re-add root to dead root list if we stop dropping it
Btrfs: fix lock leak when resuming snapshot deletion
Btrfs: update drop progress before stopping snapshot dropping
-rw-r--r-- | fs/btrfs/extent-tree.c | 27 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 2 |
2 files changed, 22 insertions, 7 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0236de711989..1204c8ef6f32 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -7466,6 +7466,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
7466 | int err = 0; | 7466 | int err = 0; |
7467 | int ret; | 7467 | int ret; |
7468 | int level; | 7468 | int level; |
7469 | bool root_dropped = false; | ||
7469 | 7470 | ||
7470 | path = btrfs_alloc_path(); | 7471 | path = btrfs_alloc_path(); |
7471 | if (!path) { | 7472 | if (!path) { |
@@ -7523,6 +7524,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
7523 | while (1) { | 7524 | while (1) { |
7524 | btrfs_tree_lock(path->nodes[level]); | 7525 | btrfs_tree_lock(path->nodes[level]); |
7525 | btrfs_set_lock_blocking(path->nodes[level]); | 7526 | btrfs_set_lock_blocking(path->nodes[level]); |
7527 | path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; | ||
7526 | 7528 | ||
7527 | ret = btrfs_lookup_extent_info(trans, root, | 7529 | ret = btrfs_lookup_extent_info(trans, root, |
7528 | path->nodes[level]->start, | 7530 | path->nodes[level]->start, |
@@ -7538,6 +7540,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
7538 | break; | 7540 | break; |
7539 | 7541 | ||
7540 | btrfs_tree_unlock(path->nodes[level]); | 7542 | btrfs_tree_unlock(path->nodes[level]); |
7543 | path->locks[level] = 0; | ||
7541 | WARN_ON(wc->refs[level] != 1); | 7544 | WARN_ON(wc->refs[level] != 1); |
7542 | level--; | 7545 | level--; |
7543 | } | 7546 | } |
@@ -7552,11 +7555,6 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
7552 | wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); | 7555 | wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); |
7553 | 7556 | ||
7554 | while (1) { | 7557 | while (1) { |
7555 | if (!for_reloc && btrfs_need_cleaner_sleep(root)) { | ||
7556 | pr_debug("btrfs: drop snapshot early exit\n"); | ||
7557 | err = -EAGAIN; | ||
7558 | goto out_end_trans; | ||
7559 | } | ||
7560 | 7558 | ||
7561 | ret = walk_down_tree(trans, root, path, wc); | 7559 | ret = walk_down_tree(trans, root, path, wc); |
7562 | if (ret < 0) { | 7560 | if (ret < 0) { |
@@ -7584,7 +7582,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
7584 | } | 7582 | } |
7585 | 7583 | ||
7586 | BUG_ON(wc->level == 0); | 7584 | BUG_ON(wc->level == 0); |
7587 | if (btrfs_should_end_transaction(trans, tree_root)) { | 7585 | if (btrfs_should_end_transaction(trans, tree_root) || |
7586 | (!for_reloc && btrfs_need_cleaner_sleep(root))) { | ||
7588 | ret = btrfs_update_root(trans, tree_root, | 7587 | ret = btrfs_update_root(trans, tree_root, |
7589 | &root->root_key, | 7588 | &root->root_key, |
7590 | root_item); | 7589 | root_item); |
@@ -7595,6 +7594,12 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
7595 | } | 7594 | } |
7596 | 7595 | ||
7597 | btrfs_end_transaction_throttle(trans, tree_root); | 7596 | btrfs_end_transaction_throttle(trans, tree_root); |
7597 | if (!for_reloc && btrfs_need_cleaner_sleep(root)) { | ||
7598 | pr_debug("btrfs: drop snapshot early exit\n"); | ||
7599 | err = -EAGAIN; | ||
7600 | goto out_free; | ||
7601 | } | ||
7602 | |||
7598 | trans = btrfs_start_transaction(tree_root, 0); | 7603 | trans = btrfs_start_transaction(tree_root, 0); |
7599 | if (IS_ERR(trans)) { | 7604 | if (IS_ERR(trans)) { |
7600 | err = PTR_ERR(trans); | 7605 | err = PTR_ERR(trans); |
@@ -7639,12 +7644,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root, | |||
7639 | free_extent_buffer(root->commit_root); | 7644 | free_extent_buffer(root->commit_root); |
7640 | btrfs_put_fs_root(root); | 7645 | btrfs_put_fs_root(root); |
7641 | } | 7646 | } |
7647 | root_dropped = true; | ||
7642 | out_end_trans: | 7648 | out_end_trans: |
7643 | btrfs_end_transaction_throttle(trans, tree_root); | 7649 | btrfs_end_transaction_throttle(trans, tree_root); |
7644 | out_free: | 7650 | out_free: |
7645 | kfree(wc); | 7651 | kfree(wc); |
7646 | btrfs_free_path(path); | 7652 | btrfs_free_path(path); |
7647 | out: | 7653 | out: |
7654 | /* | ||
7655 | * So if we need to stop dropping the snapshot for whatever reason we | ||
7656 | * need to make sure to add it back to the dead root list so that we | ||
7657 | * keep trying to do the work later. This also cleans up roots if we | ||
7658 | * don't have it in the radix (like when we recover after a power fail | ||
7659 | * or unmount) so we don't leak memory. | ||
7660 | */ | ||
7661 | if (root_dropped == false) | ||
7662 | btrfs_add_dead_root(root); | ||
7648 | if (err) | 7663 | if (err) |
7649 | btrfs_std_error(root->fs_info, err); | 7664 | btrfs_std_error(root->fs_info, err); |
7650 | return err; | 7665 | return err; |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 4ba2a69a60ad..64a157becbe5 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -2495,7 +2495,7 @@ again: | |||
2495 | ret = scrub_extent(sctx, extent_logical, extent_len, | 2495 | ret = scrub_extent(sctx, extent_logical, extent_len, |
2496 | extent_physical, extent_dev, flags, | 2496 | extent_physical, extent_dev, flags, |
2497 | generation, extent_mirror_num, | 2497 | generation, extent_mirror_num, |
2498 | extent_physical); | 2498 | extent_logical - logical + physical); |
2499 | if (ret) | 2499 | if (ret) |
2500 | goto out; | 2500 | goto out; |
2501 | 2501 | ||