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.c80
1 files changed, 44 insertions, 36 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 5fe1ca8abc70..7c655f9a7a50 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -388,7 +388,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
388 if (ret) 388 if (ret)
389 btrfs_err(fs_info, "kobj add dev failed %d", ret); 389 btrfs_err(fs_info, "kobj add dev failed %d", ret);
390 390
391 btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1); 391 btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
392 392
393 /* force writing the updated state information to disk */ 393 /* force writing the updated state information to disk */
394 trans = btrfs_start_transaction(root, 0); 394 trans = btrfs_start_transaction(root, 0);
@@ -507,7 +507,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
507 mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); 507 mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
508 return ret; 508 return ret;
509 } 509 }
510 btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1); 510 btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
511 511
512 trans = btrfs_start_transaction(root, 0); 512 trans = btrfs_start_transaction(root, 0);
513 if (IS_ERR(trans)) { 513 if (IS_ERR(trans)) {
@@ -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
@@ -690,7 +704,7 @@ static u64 __btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
690 u64 result; 704 u64 result;
691 int ret; 705 int ret;
692 706
693 if (fs_info->sb->s_flags & MS_RDONLY) 707 if (sb_rdonly(fs_info->sb))
694 return -EROFS; 708 return -EROFS;
695 709
696 mutex_lock(&dev_replace->lock_finishing_cancel_unmount); 710 mutex_lock(&dev_replace->lock_finishing_cancel_unmount);
@@ -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