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.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index bee3edeea7a3..7a93a3e1a847 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -639,11 +639,39 @@ static void btrfs_dev_replace_update_device_in_mapping_tree(
639 write_unlock(&em_tree->lock); 639 write_unlock(&em_tree->lock);
640} 640}
641 641
642/*
643 * Read progress of device replace status according to the state and last
644 * stored position. The value format is the same as for
645 * btrfs_dev_replace::progress_1000
646 */
647static u64 btrfs_dev_replace_progress(struct btrfs_fs_info *fs_info)
648{
649 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
650 u64 ret = 0;
651
652 switch (dev_replace->replace_state) {
653 case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
654 case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
655 ret = 0;
656 break;
657 case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
658 ret = 1000;
659 break;
660 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
661 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
662 ret = div64_u64(dev_replace->cursor_left,
663 div_u64(btrfs_device_get_total_bytes(
664 dev_replace->srcdev), 1000));
665 break;
666 }
667
668 return ret;
669}
670
642void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info, 671void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
643 struct btrfs_ioctl_dev_replace_args *args) 672 struct btrfs_ioctl_dev_replace_args *args)
644{ 673{
645 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; 674 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
646 struct btrfs_device *srcdev;
647 675
648 btrfs_dev_replace_lock(dev_replace, 0); 676 btrfs_dev_replace_lock(dev_replace, 0);
649 /* even if !dev_replace_is_valid, the values are good enough for 677 /* even if !dev_replace_is_valid, the values are good enough for
@@ -656,21 +684,7 @@ void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
656 atomic64_read(&dev_replace->num_write_errors); 684 atomic64_read(&dev_replace->num_write_errors);
657 args->status.num_uncorrectable_read_errors = 685 args->status.num_uncorrectable_read_errors =
658 atomic64_read(&dev_replace->num_uncorrectable_read_errors); 686 atomic64_read(&dev_replace->num_uncorrectable_read_errors);
659 switch (dev_replace->replace_state) { 687 args->status.progress_1000 = btrfs_dev_replace_progress(fs_info);
660 case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
661 case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
662 args->status.progress_1000 = 0;
663 break;
664 case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
665 args->status.progress_1000 = 1000;
666 break;
667 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
668 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
669 srcdev = dev_replace->srcdev;
670 args->status.progress_1000 = div64_u64(dev_replace->cursor_left,
671 div_u64(btrfs_device_get_total_bytes(srcdev), 1000));
672 break;
673 }
674 btrfs_dev_replace_unlock(dev_replace, 0); 688 btrfs_dev_replace_unlock(dev_replace, 0);
675} 689}
676 690
@@ -795,25 +809,19 @@ static int btrfs_dev_replace_kthread(void *data)
795{ 809{
796 struct btrfs_fs_info *fs_info = data; 810 struct btrfs_fs_info *fs_info = data;
797 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; 811 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
798 struct btrfs_ioctl_dev_replace_args *status_args;
799 u64 progress; 812 u64 progress;
800 813
801 status_args = kzalloc(sizeof(*status_args), GFP_KERNEL); 814 progress = btrfs_dev_replace_progress(fs_info);
802 if (status_args) { 815 progress = div_u64(progress, 10);
803 btrfs_dev_replace_status(fs_info, status_args); 816 btrfs_info_in_rcu(fs_info,
804 progress = status_args->status.progress_1000; 817 "continuing dev_replace from %s (devid %llu) to %s @%u%%",
805 kfree(status_args); 818 dev_replace->srcdev->missing ? "<missing disk>"
806 progress = div_u64(progress, 10); 819 : rcu_str_deref(dev_replace->srcdev->name),
807 btrfs_info_in_rcu(fs_info, 820 dev_replace->srcdev->devid,
808 "continuing dev_replace from %s (devid %llu) to %s @%u%%", 821 dev_replace->tgtdev ? rcu_str_deref(dev_replace->tgtdev->name)
809 dev_replace->srcdev->missing ? "<missing disk>" : 822 : "<missing target disk>",
810 rcu_str_deref(dev_replace->srcdev->name), 823 (unsigned int)progress);
811 dev_replace->srcdev->devid, 824
812 dev_replace->tgtdev ?
813 rcu_str_deref(dev_replace->tgtdev->name) :
814 "<missing target disk>",
815 (unsigned int)progress);
816 }
817 btrfs_dev_replace_continue_on_mount(fs_info); 825 btrfs_dev_replace_continue_on_mount(fs_info);
818 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags); 826 clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
819 827