Commit 90290c4e authored by Linus Torvalds's avatar Linus Torvalds

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
parents d471ce53 115930cb
...@@ -7466,6 +7466,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7466,6 +7466,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
int err = 0; int err = 0;
int ret; int ret;
int level; int level;
bool root_dropped = false;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) { if (!path) {
...@@ -7523,6 +7524,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7523,6 +7524,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
while (1) { while (1) {
btrfs_tree_lock(path->nodes[level]); btrfs_tree_lock(path->nodes[level]);
btrfs_set_lock_blocking(path->nodes[level]); btrfs_set_lock_blocking(path->nodes[level]);
path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
ret = btrfs_lookup_extent_info(trans, root, ret = btrfs_lookup_extent_info(trans, root,
path->nodes[level]->start, path->nodes[level]->start,
...@@ -7538,6 +7540,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7538,6 +7540,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
break; break;
btrfs_tree_unlock(path->nodes[level]); btrfs_tree_unlock(path->nodes[level]);
path->locks[level] = 0;
WARN_ON(wc->refs[level] != 1); WARN_ON(wc->refs[level] != 1);
level--; level--;
} }
...@@ -7552,11 +7555,6 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7552,11 +7555,6 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root);
while (1) { while (1) {
if (!for_reloc && btrfs_need_cleaner_sleep(root)) {
pr_debug("btrfs: drop snapshot early exit\n");
err = -EAGAIN;
goto out_end_trans;
}
ret = walk_down_tree(trans, root, path, wc); ret = walk_down_tree(trans, root, path, wc);
if (ret < 0) { if (ret < 0) {
...@@ -7584,7 +7582,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7584,7 +7582,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
} }
BUG_ON(wc->level == 0); BUG_ON(wc->level == 0);
if (btrfs_should_end_transaction(trans, tree_root)) { if (btrfs_should_end_transaction(trans, tree_root) ||
(!for_reloc && btrfs_need_cleaner_sleep(root))) {
ret = btrfs_update_root(trans, tree_root, ret = btrfs_update_root(trans, tree_root,
&root->root_key, &root->root_key,
root_item); root_item);
...@@ -7595,6 +7594,12 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7595,6 +7594,12 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
} }
btrfs_end_transaction_throttle(trans, tree_root); btrfs_end_transaction_throttle(trans, tree_root);
if (!for_reloc && btrfs_need_cleaner_sleep(root)) {
pr_debug("btrfs: drop snapshot early exit\n");
err = -EAGAIN;
goto out_free;
}
trans = btrfs_start_transaction(tree_root, 0); trans = btrfs_start_transaction(tree_root, 0);
if (IS_ERR(trans)) { if (IS_ERR(trans)) {
err = PTR_ERR(trans); err = PTR_ERR(trans);
...@@ -7639,12 +7644,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root, ...@@ -7639,12 +7644,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
free_extent_buffer(root->commit_root); free_extent_buffer(root->commit_root);
btrfs_put_fs_root(root); btrfs_put_fs_root(root);
} }
root_dropped = true;
out_end_trans: out_end_trans:
btrfs_end_transaction_throttle(trans, tree_root); btrfs_end_transaction_throttle(trans, tree_root);
out_free: out_free:
kfree(wc); kfree(wc);
btrfs_free_path(path); btrfs_free_path(path);
out: out:
/*
* So if we need to stop dropping the snapshot for whatever reason we
* need to make sure to add it back to the dead root list so that we
* keep trying to do the work later. This also cleans up roots if we
* don't have it in the radix (like when we recover after a power fail
* or unmount) so we don't leak memory.
*/
if (root_dropped == false)
btrfs_add_dead_root(root);
if (err) if (err)
btrfs_std_error(root->fs_info, err); btrfs_std_error(root->fs_info, err);
return err; return err;
......
...@@ -2495,7 +2495,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, ...@@ -2495,7 +2495,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
ret = scrub_extent(sctx, extent_logical, extent_len, ret = scrub_extent(sctx, extent_logical, extent_len,
extent_physical, extent_dev, flags, extent_physical, extent_dev, flags,
generation, extent_mirror_num, generation, extent_mirror_num,
extent_physical); extent_logical - logical + physical);
if (ret) if (ret)
goto out; goto out;
......
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