|
@@ -7466,6 +7466,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
|
|
|
int err = 0;
|
|
|
int ret;
|
|
|
int level;
|
|
|
+ bool root_dropped = false;
|
|
|
|
|
|
path = btrfs_alloc_path();
|
|
|
if (!path) {
|
|
@@ -7643,12 +7644,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
|
|
|
free_extent_buffer(root->commit_root);
|
|
|
btrfs_put_fs_root(root);
|
|
|
}
|
|
|
+ root_dropped = true;
|
|
|
out_end_trans:
|
|
|
btrfs_end_transaction_throttle(trans, tree_root);
|
|
|
out_free:
|
|
|
kfree(wc);
|
|
|
btrfs_free_path(path);
|
|
|
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)
|
|
|
btrfs_std_error(root->fs_info, err);
|
|
|
return err;
|