|
|
@@ -800,39 +800,58 @@ int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
|
|
|
case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
|
|
|
result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED;
|
|
|
btrfs_dev_replace_write_unlock(dev_replace);
|
|
|
- goto leave;
|
|
|
+ break;
|
|
|
case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
|
|
|
+ result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
|
|
|
+ tgt_device = dev_replace->tgtdev;
|
|
|
+ src_device = dev_replace->srcdev;
|
|
|
+ btrfs_dev_replace_write_unlock(dev_replace);
|
|
|
+ btrfs_scrub_cancel(fs_info);
|
|
|
+ /* btrfs_dev_replace_finishing() will handle the cleanup part */
|
|
|
+ btrfs_info_in_rcu(fs_info,
|
|
|
+ "dev_replace from %s (devid %llu) to %s canceled",
|
|
|
+ btrfs_dev_name(src_device), src_device->devid,
|
|
|
+ btrfs_dev_name(tgt_device));
|
|
|
+ break;
|
|
|
case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
|
|
|
+ /*
|
|
|
+ * Scrub doing the replace isn't running so we need to do the
|
|
|
+ * cleanup step of btrfs_dev_replace_finishing() here
|
|
|
+ */
|
|
|
result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
|
|
|
tgt_device = dev_replace->tgtdev;
|
|
|
src_device = dev_replace->srcdev;
|
|
|
dev_replace->tgtdev = NULL;
|
|
|
dev_replace->srcdev = NULL;
|
|
|
- break;
|
|
|
- }
|
|
|
- dev_replace->replace_state = BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED;
|
|
|
- dev_replace->time_stopped = ktime_get_real_seconds();
|
|
|
- dev_replace->item_needs_writeback = 1;
|
|
|
- btrfs_dev_replace_write_unlock(dev_replace);
|
|
|
- btrfs_scrub_cancel(fs_info);
|
|
|
+ dev_replace->replace_state =
|
|
|
+ BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED;
|
|
|
+ dev_replace->time_stopped = ktime_get_real_seconds();
|
|
|
+ dev_replace->item_needs_writeback = 1;
|
|
|
|
|
|
- trans = btrfs_start_transaction(root, 0);
|
|
|
- if (IS_ERR(trans)) {
|
|
|
- mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
|
|
|
- return PTR_ERR(trans);
|
|
|
- }
|
|
|
- ret = btrfs_commit_transaction(trans);
|
|
|
- WARN_ON(ret);
|
|
|
+ btrfs_dev_replace_write_unlock(dev_replace);
|
|
|
|
|
|
- btrfs_info_in_rcu(fs_info,
|
|
|
- "dev_replace from %s (devid %llu) to %s canceled",
|
|
|
- btrfs_dev_name(src_device), src_device->devid,
|
|
|
- btrfs_dev_name(tgt_device));
|
|
|
+ btrfs_scrub_cancel(fs_info);
|
|
|
+
|
|
|
+ trans = btrfs_start_transaction(root, 0);
|
|
|
+ if (IS_ERR(trans)) {
|
|
|
+ mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
|
|
|
+ return PTR_ERR(trans);
|
|
|
+ }
|
|
|
+ ret = btrfs_commit_transaction(trans);
|
|
|
+ WARN_ON(ret);
|
|
|
|
|
|
- if (tgt_device)
|
|
|
- btrfs_destroy_dev_replace_tgtdev(tgt_device);
|
|
|
+ btrfs_info_in_rcu(fs_info,
|
|
|
+ "suspended dev_replace from %s (devid %llu) to %s canceled",
|
|
|
+ btrfs_dev_name(src_device), src_device->devid,
|
|
|
+ btrfs_dev_name(tgt_device));
|
|
|
+
|
|
|
+ if (tgt_device)
|
|
|
+ btrfs_destroy_dev_replace_tgtdev(tgt_device);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ result = -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
-leave:
|
|
|
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
|
|
|
return result;
|
|
|
}
|