diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 43 |
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 | |||
1891 | slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | 1891 | slot_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) { |