|
@@ -2375,6 +2375,36 @@ repeat:
|
|
|
}
|
|
|
EXPORT_SYMBOL(md_update_sb);
|
|
|
|
|
|
+static int add_bound_rdev(struct md_rdev *rdev)
|
|
|
+{
|
|
|
+ struct mddev *mddev = rdev->mddev;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ if (!mddev->pers->hot_remove_disk) {
|
|
|
+ /* If there is hot_add_disk but no hot_remove_disk
|
|
|
+ * then added disks for geometry changes,
|
|
|
+ * and should be added immediately.
|
|
|
+ */
|
|
|
+ super_types[mddev->major_version].
|
|
|
+ validate_super(mddev, rdev);
|
|
|
+ err = mddev->pers->hot_add_disk(mddev, rdev);
|
|
|
+ if (err) {
|
|
|
+ unbind_rdev_from_array(rdev);
|
|
|
+ export_rdev(rdev);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sysfs_notify_dirent_safe(rdev->sysfs_state);
|
|
|
+
|
|
|
+ set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
|
|
+ if (mddev->degraded)
|
|
|
+ set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
|
|
|
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
|
|
+ md_new_event(mddev);
|
|
|
+ md_wakeup_thread(mddev->thread);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/* words written to sysfs files may, or may not, be \n terminated.
|
|
|
* We want to accept with case. For this we use cmd_match.
|
|
|
*/
|
|
@@ -2564,6 +2594,12 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|
|
clear_bit(Replacement, &rdev->flags);
|
|
|
err = 0;
|
|
|
}
|
|
|
+ } else if (cmd_match(buf, "re-add")) {
|
|
|
+ if (test_bit(Faulty, &rdev->flags) && (rdev->raid_disk == -1)) {
|
|
|
+ clear_bit(Faulty, &rdev->flags);
|
|
|
+ err = add_bound_rdev(rdev);
|
|
|
+ } else
|
|
|
+ err = -EBUSY;
|
|
|
}
|
|
|
if (!err)
|
|
|
sysfs_notify_dirent_safe(rdev->sysfs_state);
|
|
@@ -5875,29 +5911,10 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
|
|
|
|
|
|
rdev->raid_disk = -1;
|
|
|
err = bind_rdev_to_array(rdev, mddev);
|
|
|
- if (!err && !mddev->pers->hot_remove_disk) {
|
|
|
- /* If there is hot_add_disk but no hot_remove_disk
|
|
|
- * then added disks for geometry changes,
|
|
|
- * and should be added immediately.
|
|
|
- */
|
|
|
- super_types[mddev->major_version].
|
|
|
- validate_super(mddev, rdev);
|
|
|
- err = mddev->pers->hot_add_disk(mddev, rdev);
|
|
|
- if (err)
|
|
|
- unbind_rdev_from_array(rdev);
|
|
|
- }
|
|
|
if (err)
|
|
|
export_rdev(rdev);
|
|
|
else
|
|
|
- sysfs_notify_dirent_safe(rdev->sysfs_state);
|
|
|
-
|
|
|
- set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
|
|
- if (mddev->degraded)
|
|
|
- set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
|
|
|
- set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
|
|
- if (!err)
|
|
|
- md_new_event(mddev);
|
|
|
- md_wakeup_thread(mddev->thread);
|
|
|
+ err = add_bound_rdev(rdev);
|
|
|
if (mddev_is_clustered(mddev) &&
|
|
|
(info->state & (1 << MD_DISK_CLUSTER_ADD)))
|
|
|
md_cluster_ops->add_new_disk_finish(mddev);
|