summaryrefslogtreecommitdiff
path: root/drivers/md/md.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c6e44a836a53..07f207e53ba9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -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);