aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e2782a04012d..00788c56276f 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1891,20 +1891,44 @@ static ssize_t
1891slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) 1891slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
1892{ 1892{
1893 char *e; 1893 char *e;
1894 int err;
1895 char nm[20];
1894 int slot = simple_strtoul(buf, &e, 10); 1896 int slot = simple_strtoul(buf, &e, 10);
1895 if (strncmp(buf, "none", 4)==0) 1897 if (strncmp(buf, "none", 4)==0)
1896 slot = -1; 1898 slot = -1;
1897 else if (e==buf || (*e && *e!= '\n')) 1899 else if (e==buf || (*e && *e!= '\n'))
1898 return -EINVAL; 1900 return -EINVAL;
1899 if (rdev->mddev->pers) 1901 if (rdev->mddev->pers) {
1900 /* Cannot set slot in active array (yet) */ 1902 /* Setting 'slot' on an active array requires also
1901 return -EBUSY; 1903 * updating the 'rd%d' link, and communicating
1902 if (slot >= rdev->mddev->raid_disks) 1904 * with the personality with ->hot_*_disk.
1903 return -ENOSPC; 1905 * For now we only support removing
1904 rdev->raid_disk = slot; 1906 * failed/spare devices. This normally happens automatically,
1905 /* assume it is working */ 1907 * but not when the metadata is externally managed.
1906 rdev->flags = 0; 1908 */
1907 set_bit(In_sync, &rdev->flags); 1909 if (slot != -1)
1910 return -EBUSY;
1911 if (rdev->raid_disk == -1)
1912 return -EEXIST;
1913 /* personality does all needed checks */
1914 if (rdev->mddev->pers->hot_add_disk == NULL)
1915 return -EINVAL;
1916 err = rdev->mddev->pers->
1917 hot_remove_disk(rdev->mddev, rdev->raid_disk);
1918 if (err)
1919 return err;
1920 sprintf(nm, "rd%d", rdev->raid_disk);
1921 sysfs_remove_link(&rdev->mddev->kobj, nm);
1922 set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
1923 md_wakeup_thread(rdev->mddev->thread);
1924 } else {
1925 if (slot >= rdev->mddev->raid_disks)
1926 return -ENOSPC;
1927 rdev->raid_disk = slot;
1928 /* assume it is working */
1929 rdev->flags = 0;
1930 set_bit(In_sync, &rdev->flags);
1931 }
1908 return len; 1932 return len;
1909} 1933}
1910 1934
@@ -5549,6 +5573,7 @@ static int remove_and_add_spares(mddev_t *mddev)
5549 5573
5550 ITERATE_RDEV(mddev,rdev,rtmp) 5574 ITERATE_RDEV(mddev,rdev,rtmp)
5551 if (rdev->raid_disk >= 0 && 5575 if (rdev->raid_disk >= 0 &&
5576 !mddev->external &&
5552 (test_bit(Faulty, &rdev->flags) || 5577 (test_bit(Faulty, &rdev->flags) ||
5553 ! test_bit(In_sync, &rdev->flags)) && 5578 ! test_bit(In_sync, &rdev->flags)) &&
5554 atomic_read(&rdev->nr_pending)==0) { 5579 atomic_read(&rdev->nr_pending)==0) {