|
@@ -72,6 +72,9 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
|
|
|
static struct workqueue_struct *md_wq;
|
|
|
static struct workqueue_struct *md_misc_wq;
|
|
|
|
|
|
+static int remove_and_add_spares(struct mddev *mddev,
|
|
|
+ struct md_rdev *this);
|
|
|
+
|
|
|
#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
|
|
|
|
|
|
/*
|
|
@@ -2805,12 +2808,10 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|
|
/* personality does all needed checks */
|
|
|
if (rdev->mddev->pers->hot_remove_disk == NULL)
|
|
|
return -EINVAL;
|
|
|
- err = rdev->mddev->pers->
|
|
|
- hot_remove_disk(rdev->mddev, rdev);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
- sysfs_unlink_rdev(rdev->mddev, rdev);
|
|
|
- rdev->raid_disk = -1;
|
|
|
+ clear_bit(Blocked, &rdev->flags);
|
|
|
+ remove_and_add_spares(rdev->mddev, rdev);
|
|
|
+ if (rdev->raid_disk >= 0)
|
|
|
+ return -EBUSY;
|
|
|
set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
|
|
|
md_wakeup_thread(rdev->mddev->thread);
|
|
|
} else if (rdev->mddev->pers) {
|
|
@@ -7649,14 +7650,16 @@ void md_do_sync(struct md_thread *thread)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(md_do_sync);
|
|
|
|
|
|
-static int remove_and_add_spares(struct mddev *mddev)
|
|
|
+static int remove_and_add_spares(struct mddev *mddev,
|
|
|
+ struct md_rdev *this)
|
|
|
{
|
|
|
struct md_rdev *rdev;
|
|
|
int spares = 0;
|
|
|
int removed = 0;
|
|
|
|
|
|
rdev_for_each(rdev, mddev)
|
|
|
- if (rdev->raid_disk >= 0 &&
|
|
|
+ if ((this == NULL || rdev == this) &&
|
|
|
+ rdev->raid_disk >= 0 &&
|
|
|
!test_bit(Blocked, &rdev->flags) &&
|
|
|
(test_bit(Faulty, &rdev->flags) ||
|
|
|
! test_bit(In_sync, &rdev->flags)) &&
|
|
@@ -7671,6 +7674,9 @@ static int remove_and_add_spares(struct mddev *mddev)
|
|
|
if (removed && mddev->kobj.sd)
|
|
|
sysfs_notify(&mddev->kobj, NULL, "degraded");
|
|
|
|
|
|
+ if (this)
|
|
|
+ goto no_add;
|
|
|
+
|
|
|
rdev_for_each(rdev, mddev) {
|
|
|
if (rdev->raid_disk >= 0 &&
|
|
|
!test_bit(In_sync, &rdev->flags) &&
|
|
@@ -7689,6 +7695,7 @@ static int remove_and_add_spares(struct mddev *mddev)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+no_add:
|
|
|
if (removed)
|
|
|
set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
|
|
return spares;
|
|
@@ -7872,7 +7879,7 @@ void md_check_recovery(struct mddev *mddev)
|
|
|
goto unlock;
|
|
|
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
|
|
|
clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
|
|
|
- } else if ((spares = remove_and_add_spares(mddev))) {
|
|
|
+ } else if ((spares = remove_and_add_spares(mddev, NULL))) {
|
|
|
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
|
|
|
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
|
|
|
clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
|