aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-20 13:47:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-20 13:47:38 -0400
commit90290c4ebe5c64ee34fea0d2cc3025cb934917b8 (patch)
treef57eff4c719ca6a39f1e5ca70598cb80e82ccf96
parentd471ce53b1fab60110e4e9f647a345cea31752de (diff)
parent115930cb2d444a684975cf2325759cb48ebf80cc (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.c27
-rw-r--r--fs/btrfs/scrub.c2
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;
7642out_end_trans: 7648out_end_trans:
7643 btrfs_end_transaction_throttle(trans, tree_root); 7649 btrfs_end_transaction_throttle(trans, tree_root);
7644out_free: 7650out_free:
7645 kfree(wc); 7651 kfree(wc);
7646 btrfs_free_path(path); 7652 btrfs_free_path(path);
7647out: 7653out:
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