aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/dev-replace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/dev-replace.c')
-rw-r--r--fs/btrfs/dev-replace.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 33d07c426c59..08092d329f66 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -803,39 +803,58 @@ int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
803 case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED: 803 case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
804 result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED; 804 result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED;
805 btrfs_dev_replace_write_unlock(dev_replace); 805 btrfs_dev_replace_write_unlock(dev_replace);
806 goto leave; 806 break;
807 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED: 807 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
808 result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
809 tgt_device = dev_replace->tgtdev;
810 src_device = dev_replace->srcdev;
811 btrfs_dev_replace_write_unlock(dev_replace);
812 btrfs_scrub_cancel(fs_info);
813 /* btrfs_dev_replace_finishing() will handle the cleanup part */
814 btrfs_info_in_rcu(fs_info,
815 "dev_replace from %s (devid %llu) to %s canceled",
816 btrfs_dev_name(src_device), src_device->devid,
817 btrfs_dev_name(tgt_device));
818 break;
808 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED: 819 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
820 /*
821 * Scrub doing the replace isn't running so we need to do the
822 * cleanup step of btrfs_dev_replace_finishing() here
823 */
809 result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR; 824 result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
810 tgt_device = dev_replace->tgtdev; 825 tgt_device = dev_replace->tgtdev;
811 src_device = dev_replace->srcdev; 826 src_device = dev_replace->srcdev;
812 dev_replace->tgtdev = NULL; 827 dev_replace->tgtdev = NULL;
813 dev_replace->srcdev = NULL; 828 dev_replace->srcdev = NULL;
814 break; 829 dev_replace->replace_state =
815 } 830 BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED;
816 dev_replace->replace_state = BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED; 831 dev_replace->time_stopped = ktime_get_real_seconds();
817 dev_replace->time_stopped = ktime_get_real_seconds(); 832 dev_replace->item_needs_writeback = 1;
818 dev_replace->item_needs_writeback = 1;
819 btrfs_dev_replace_write_unlock(dev_replace);
820 btrfs_scrub_cancel(fs_info);
821 833
822 trans = btrfs_start_transaction(root, 0); 834 btrfs_dev_replace_write_unlock(dev_replace);
823 if (IS_ERR(trans)) {
824 mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
825 return PTR_ERR(trans);
826 }
827 ret = btrfs_commit_transaction(trans);
828 WARN_ON(ret);
829 835
830 btrfs_info_in_rcu(fs_info, 836 btrfs_scrub_cancel(fs_info);
831 "dev_replace from %s (devid %llu) to %s canceled", 837
832 btrfs_dev_name(src_device), src_device->devid, 838 trans = btrfs_start_transaction(root, 0);
833 btrfs_dev_name(tgt_device)); 839 if (IS_ERR(trans)) {
840 mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
841 return PTR_ERR(trans);
842 }
843 ret = btrfs_commit_transaction(trans);
844 WARN_ON(ret);
834 845
835 if (tgt_device) 846 btrfs_info_in_rcu(fs_info,
836 btrfs_destroy_dev_replace_tgtdev(tgt_device); 847 "suspended dev_replace from %s (devid %llu) to %s canceled",
848 btrfs_dev_name(src_device), src_device->devid,
849 btrfs_dev_name(tgt_device));
850
851 if (tgt_device)
852 btrfs_destroy_dev_replace_tgtdev(tgt_device);
853 break;
854 default:
855 result = -EINVAL;
856 }
837 857
838leave:
839 mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); 858 mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
840 return result; 859 return result;
841} 860}