diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index ca011d1d1de7..429e95e9a942 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -2375,6 +2375,36 @@ repeat: | |||
2375 | } | 2375 | } |
2376 | EXPORT_SYMBOL(md_update_sb); | 2376 | EXPORT_SYMBOL(md_update_sb); |
2377 | 2377 | ||
2378 | static int add_bound_rdev(struct md_rdev *rdev) | ||
2379 | { | ||
2380 | struct mddev *mddev = rdev->mddev; | ||
2381 | int err = 0; | ||
2382 | |||
2383 | if (!mddev->pers->hot_remove_disk) { | ||
2384 | /* If there is hot_add_disk but no hot_remove_disk | ||
2385 | * then added disks for geometry changes, | ||
2386 | * and should be added immediately. | ||
2387 | */ | ||
2388 | super_types[mddev->major_version]. | ||
2389 | validate_super(mddev, rdev); | ||
2390 | err = mddev->pers->hot_add_disk(mddev, rdev); | ||
2391 | if (err) { | ||
2392 | unbind_rdev_from_array(rdev); | ||
2393 | export_rdev(rdev); | ||
2394 | return err; | ||
2395 | } | ||
2396 | } | ||
2397 | sysfs_notify_dirent_safe(rdev->sysfs_state); | ||
2398 | |||
2399 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | ||
2400 | if (mddev->degraded) | ||
2401 | set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); | ||
2402 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
2403 | md_new_event(mddev); | ||
2404 | md_wakeup_thread(mddev->thread); | ||
2405 | return 0; | ||
2406 | } | ||
2407 | |||
2378 | /* words written to sysfs files may, or may not, be \n terminated. | 2408 | /* words written to sysfs files may, or may not, be \n terminated. |
2379 | * We want to accept with case. For this we use cmd_match. | 2409 | * We want to accept with case. For this we use cmd_match. |
2380 | */ | 2410 | */ |
@@ -2564,6 +2594,12 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2564 | clear_bit(Replacement, &rdev->flags); | 2594 | clear_bit(Replacement, &rdev->flags); |
2565 | err = 0; | 2595 | err = 0; |
2566 | } | 2596 | } |
2597 | } else if (cmd_match(buf, "re-add")) { | ||
2598 | if (test_bit(Faulty, &rdev->flags) && (rdev->raid_disk == -1)) { | ||
2599 | clear_bit(Faulty, &rdev->flags); | ||
2600 | err = add_bound_rdev(rdev); | ||
2601 | } else | ||
2602 | err = -EBUSY; | ||
2567 | } | 2603 | } |
2568 | if (!err) | 2604 | if (!err) |
2569 | sysfs_notify_dirent_safe(rdev->sysfs_state); | 2605 | sysfs_notify_dirent_safe(rdev->sysfs_state); |
@@ -5875,29 +5911,10 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info) | |||
5875 | 5911 | ||
5876 | rdev->raid_disk = -1; | 5912 | rdev->raid_disk = -1; |
5877 | err = bind_rdev_to_array(rdev, mddev); | 5913 | err = bind_rdev_to_array(rdev, mddev); |
5878 | if (!err && !mddev->pers->hot_remove_disk) { | ||
5879 | /* If there is hot_add_disk but no hot_remove_disk | ||
5880 | * then added disks for geometry changes, | ||
5881 | * and should be added immediately. | ||
5882 | */ | ||
5883 | super_types[mddev->major_version]. | ||
5884 | validate_super(mddev, rdev); | ||
5885 | err = mddev->pers->hot_add_disk(mddev, rdev); | ||
5886 | if (err) | ||
5887 | unbind_rdev_from_array(rdev); | ||
5888 | } | ||
5889 | if (err) | 5914 | if (err) |
5890 | export_rdev(rdev); | 5915 | export_rdev(rdev); |
5891 | else | 5916 | else |
5892 | sysfs_notify_dirent_safe(rdev->sysfs_state); | 5917 | err = add_bound_rdev(rdev); |
5893 | |||
5894 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | ||
5895 | if (mddev->degraded) | ||
5896 | set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); | ||
5897 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
5898 | if (!err) | ||
5899 | md_new_event(mddev); | ||
5900 | md_wakeup_thread(mddev->thread); | ||
5901 | if (mddev_is_clustered(mddev) && | 5918 | if (mddev_is_clustered(mddev) && |
5902 | (info->state & (1 << MD_DISK_CLUSTER_ADD))) | 5919 | (info->state & (1 << MD_DISK_CLUSTER_ADD))) |
5903 | md_cluster_ops->add_new_disk_finish(mddev); | 5920 | md_cluster_ops->add_new_disk_finish(mddev); |