diff options
Diffstat (limited to 'fs/btrfs/dev-replace.c')
| -rw-r--r-- | fs/btrfs/dev-replace.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 6f662b34ba0e..ca6a3a3b6b6c 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c | |||
| @@ -316,11 +316,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root, | |||
| 316 | struct btrfs_device *tgt_device = NULL; | 316 | struct btrfs_device *tgt_device = NULL; |
| 317 | struct btrfs_device *src_device = NULL; | 317 | struct btrfs_device *src_device = NULL; |
| 318 | 318 | ||
| 319 | if (btrfs_fs_incompat(fs_info, RAID56)) { | ||
| 320 | btrfs_warn(fs_info, "dev_replace cannot yet handle RAID5/RAID6"); | ||
| 321 | return -EOPNOTSUPP; | ||
| 322 | } | ||
| 323 | |||
| 324 | switch (args->start.cont_reading_from_srcdev_mode) { | 319 | switch (args->start.cont_reading_from_srcdev_mode) { |
| 325 | case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS: | 320 | case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS: |
| 326 | case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID: | 321 | case BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID: |
| @@ -422,9 +417,15 @@ int btrfs_dev_replace_start(struct btrfs_root *root, | |||
| 422 | &dev_replace->scrub_progress, 0, 1); | 417 | &dev_replace->scrub_progress, 0, 1); |
| 423 | 418 | ||
| 424 | ret = btrfs_dev_replace_finishing(root->fs_info, ret); | 419 | ret = btrfs_dev_replace_finishing(root->fs_info, ret); |
| 425 | WARN_ON(ret); | 420 | /* don't warn if EINPROGRESS, someone else might be running scrub */ |
| 421 | if (ret == -EINPROGRESS) { | ||
| 422 | args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS; | ||
| 423 | ret = 0; | ||
| 424 | } else { | ||
| 425 | WARN_ON(ret); | ||
| 426 | } | ||
| 426 | 427 | ||
| 427 | return 0; | 428 | return ret; |
| 428 | 429 | ||
| 429 | leave: | 430 | leave: |
| 430 | dev_replace->srcdev = NULL; | 431 | dev_replace->srcdev = NULL; |
| @@ -542,7 +543,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | |||
| 542 | btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device); | 543 | btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device); |
| 543 | mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); | 544 | mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); |
| 544 | 545 | ||
| 545 | return 0; | 546 | return scrub_ret; |
| 546 | } | 547 | } |
| 547 | 548 | ||
| 548 | printk_in_rcu(KERN_INFO | 549 | printk_in_rcu(KERN_INFO |
| @@ -571,15 +572,11 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | |||
| 571 | list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list); | 572 | list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list); |
| 572 | fs_info->fs_devices->rw_devices++; | 573 | fs_info->fs_devices->rw_devices++; |
| 573 | 574 | ||
| 574 | /* replace the sysfs entry */ | ||
| 575 | btrfs_kobj_rm_device(fs_info, src_device); | ||
| 576 | btrfs_kobj_add_device(fs_info, tgt_device); | ||
| 577 | |||
| 578 | btrfs_dev_replace_unlock(dev_replace); | 575 | btrfs_dev_replace_unlock(dev_replace); |
| 579 | 576 | ||
| 580 | btrfs_rm_dev_replace_blocked(fs_info); | 577 | btrfs_rm_dev_replace_blocked(fs_info); |
| 581 | 578 | ||
| 582 | btrfs_rm_dev_replace_srcdev(fs_info, src_device); | 579 | btrfs_rm_dev_replace_remove_srcdev(fs_info, src_device); |
| 583 | 580 | ||
| 584 | btrfs_rm_dev_replace_unblocked(fs_info); | 581 | btrfs_rm_dev_replace_unblocked(fs_info); |
| 585 | 582 | ||
| @@ -594,6 +591,11 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | |||
| 594 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | 591 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); |
| 595 | mutex_unlock(&uuid_mutex); | 592 | mutex_unlock(&uuid_mutex); |
| 596 | 593 | ||
| 594 | /* replace the sysfs entry */ | ||
| 595 | btrfs_kobj_rm_device(fs_info, src_device); | ||
| 596 | btrfs_kobj_add_device(fs_info, tgt_device); | ||
| 597 | btrfs_rm_dev_replace_free_srcdev(fs_info, src_device); | ||
| 598 | |||
| 597 | /* write back the superblocks */ | 599 | /* write back the superblocks */ |
| 598 | trans = btrfs_start_transaction(root, 0); | 600 | trans = btrfs_start_transaction(root, 0); |
| 599 | if (!IS_ERR(trans)) | 601 | if (!IS_ERR(trans)) |
| @@ -920,9 +922,9 @@ void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info) | |||
| 920 | percpu_counter_inc(&fs_info->bio_counter); | 922 | percpu_counter_inc(&fs_info->bio_counter); |
| 921 | } | 923 | } |
| 922 | 924 | ||
| 923 | void btrfs_bio_counter_dec(struct btrfs_fs_info *fs_info) | 925 | void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount) |
| 924 | { | 926 | { |
| 925 | percpu_counter_dec(&fs_info->bio_counter); | 927 | percpu_counter_sub(&fs_info->bio_counter, amount); |
| 926 | 928 | ||
| 927 | if (waitqueue_active(&fs_info->replace_wait)) | 929 | if (waitqueue_active(&fs_info->replace_wait)) |
| 928 | wake_up(&fs_info->replace_wait); | 930 | wake_up(&fs_info->replace_wait); |
