From ef66c032876c9f24c0eb96a98a0cf232782b6cde Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 6 Feb 2008 01:39:51 -0800 Subject: [PATCH] --- yaml --- r: 83594 b: refs/heads/master c: c303da6d713b87b7b3f999f5acce8ecc76ff1adb h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/md/md.c | 43 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/[refs] b/[refs] index 57b3b54aa00c..ddb10a0463fc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: e691063a61f7f72a7d2882eb744b07a520cde23b +refs/heads/master: c303da6d713b87b7b3f999f5acce8ecc76ff1adb diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index e2782a04012d..00788c56276f 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -1891,20 +1891,44 @@ static ssize_t slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) { char *e; + int err; + char nm[20]; int slot = simple_strtoul(buf, &e, 10); if (strncmp(buf, "none", 4)==0) slot = -1; else if (e==buf || (*e && *e!= '\n')) return -EINVAL; - if (rdev->mddev->pers) - /* Cannot set slot in active array (yet) */ - return -EBUSY; - if (slot >= rdev->mddev->raid_disks) - return -ENOSPC; - rdev->raid_disk = slot; - /* assume it is working */ - rdev->flags = 0; - set_bit(In_sync, &rdev->flags); + if (rdev->mddev->pers) { + /* Setting 'slot' on an active array requires also + * updating the 'rd%d' link, and communicating + * with the personality with ->hot_*_disk. + * For now we only support removing + * failed/spare devices. This normally happens automatically, + * but not when the metadata is externally managed. + */ + if (slot != -1) + return -EBUSY; + if (rdev->raid_disk == -1) + return -EEXIST; + /* personality does all needed checks */ + if (rdev->mddev->pers->hot_add_disk == NULL) + return -EINVAL; + err = rdev->mddev->pers-> + hot_remove_disk(rdev->mddev, rdev->raid_disk); + if (err) + return err; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_remove_link(&rdev->mddev->kobj, nm); + set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); + md_wakeup_thread(rdev->mddev->thread); + } else { + if (slot >= rdev->mddev->raid_disks) + return -ENOSPC; + rdev->raid_disk = slot; + /* assume it is working */ + rdev->flags = 0; + set_bit(In_sync, &rdev->flags); + } return len; } @@ -5549,6 +5573,7 @@ static int remove_and_add_spares(mddev_t *mddev) ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk >= 0 && + !mddev->external && (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) && atomic_read(&rdev->nr_pending)==0) {