diff options
author | Neil Brown <neilb@notabene.brown> | 2008-06-27 18:31:31 -0400 |
---|---|---|
committer | Neil Brown <neilb@notabene.brown> | 2008-06-27 18:31:31 -0400 |
commit | 6c2fce2ef6b4821c21b5c42c7207cb9cf8c87eda (patch) | |
tree | 726b16f46c039df387f7cdfe0d195821d8955532 /drivers | |
parent | 8ed0a5216a0238f53b482ec88ce4aeed4b9f0da1 (diff) |
Support adding a spare to a live md array with external metadata.
i.e. extend the 'md/dev-XXX/slot' attribute so that you can
tell a device to fill an vacant slot in an and md array.
Signed-off-by: Neil Brown <neilb@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/md.c | 42 | ||||
-rw-r--r-- | drivers/md/multipath.c | 7 | ||||
-rw-r--r-- | drivers/md/raid1.c | 7 | ||||
-rw-r--r-- | drivers/md/raid10.c | 10 | ||||
-rw-r--r-- | drivers/md/raid5.c | 10 |
5 files changed, 67 insertions, 9 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 3b5cd4ef54f1..5d6fac1fd39e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1932,7 +1932,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
1932 | slot = -1; | 1932 | slot = -1; |
1933 | else if (e==buf || (*e && *e!= '\n')) | 1933 | else if (e==buf || (*e && *e!= '\n')) |
1934 | return -EINVAL; | 1934 | return -EINVAL; |
1935 | if (rdev->mddev->pers) { | 1935 | if (rdev->mddev->pers && slot == -1) { |
1936 | /* Setting 'slot' on an active array requires also | 1936 | /* Setting 'slot' on an active array requires also |
1937 | * updating the 'rd%d' link, and communicating | 1937 | * updating the 'rd%d' link, and communicating |
1938 | * with the personality with ->hot_*_disk. | 1938 | * with the personality with ->hot_*_disk. |
@@ -1940,8 +1940,6 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
1940 | * failed/spare devices. This normally happens automatically, | 1940 | * failed/spare devices. This normally happens automatically, |
1941 | * but not when the metadata is externally managed. | 1941 | * but not when the metadata is externally managed. |
1942 | */ | 1942 | */ |
1943 | if (slot != -1) | ||
1944 | return -EBUSY; | ||
1945 | if (rdev->raid_disk == -1) | 1943 | if (rdev->raid_disk == -1) |
1946 | return -EEXIST; | 1944 | return -EEXIST; |
1947 | /* personality does all needed checks */ | 1945 | /* personality does all needed checks */ |
@@ -1955,6 +1953,44 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
1955 | sysfs_remove_link(&rdev->mddev->kobj, nm); | 1953 | sysfs_remove_link(&rdev->mddev->kobj, nm); |
1956 | set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); | 1954 | set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); |
1957 | md_wakeup_thread(rdev->mddev->thread); | 1955 | md_wakeup_thread(rdev->mddev->thread); |
1956 | } else if (rdev->mddev->pers) { | ||
1957 | mdk_rdev_t *rdev2; | ||
1958 | struct list_head *tmp; | ||
1959 | /* Activating a spare .. or possibly reactivating | ||
1960 | * if we every get bitmaps working here. | ||
1961 | */ | ||
1962 | |||
1963 | if (rdev->raid_disk != -1) | ||
1964 | return -EBUSY; | ||
1965 | |||
1966 | if (rdev->mddev->pers->hot_add_disk == NULL) | ||
1967 | return -EINVAL; | ||
1968 | |||
1969 | rdev_for_each(rdev2, tmp, rdev->mddev) | ||
1970 | if (rdev2->raid_disk == slot) | ||
1971 | return -EEXIST; | ||
1972 | |||
1973 | rdev->raid_disk = slot; | ||
1974 | if (test_bit(In_sync, &rdev->flags)) | ||
1975 | rdev->saved_raid_disk = slot; | ||
1976 | else | ||
1977 | rdev->saved_raid_disk = -1; | ||
1978 | err = rdev->mddev->pers-> | ||
1979 | hot_add_disk(rdev->mddev, rdev); | ||
1980 | if (err != 1) { | ||
1981 | rdev->raid_disk = -1; | ||
1982 | if (err == 0) | ||
1983 | return -EEXIST; | ||
1984 | return err; | ||
1985 | } | ||
1986 | sprintf(nm, "rd%d", rdev->raid_disk); | ||
1987 | if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm)) | ||
1988 | printk(KERN_WARNING | ||
1989 | "md: cannot register " | ||
1990 | "%s for %s\n", | ||
1991 | nm, mdname(rdev->mddev)); | ||
1992 | |||
1993 | /* don't wakeup anyone, leave that to userspace. */ | ||
1958 | } else { | 1994 | } else { |
1959 | if (slot >= rdev->mddev->raid_disks) | 1995 | if (slot >= rdev->mddev->raid_disks) |
1960 | return -ENOSPC; | 1996 | return -ENOSPC; |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index e968116e0de9..4a1d714c048e 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -284,10 +284,15 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
284 | int found = 0; | 284 | int found = 0; |
285 | int path; | 285 | int path; |
286 | struct multipath_info *p; | 286 | struct multipath_info *p; |
287 | int first = 0; | ||
288 | int last = mddev->raid_disks - 1; | ||
289 | |||
290 | if (rdev->raid_disk >= 0) | ||
291 | first = last = rdev->raid_disk; | ||
287 | 292 | ||
288 | print_multipath_conf(conf); | 293 | print_multipath_conf(conf); |
289 | 294 | ||
290 | for (path=0; path<mddev->raid_disks; path++) | 295 | for (path = first; path <= last; path++) |
291 | if ((p=conf->multipaths+path)->rdev == NULL) { | 296 | if ((p=conf->multipaths+path)->rdev == NULL) { |
292 | q = rdev->bdev->bd_disk->queue; | 297 | q = rdev->bdev->bd_disk->queue; |
293 | blk_queue_stack_limits(mddev->queue, q); | 298 | blk_queue_stack_limits(mddev->queue, q); |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index c610b947218a..d32fc559ff05 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1103,8 +1103,13 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1103 | int found = 0; | 1103 | int found = 0; |
1104 | int mirror = 0; | 1104 | int mirror = 0; |
1105 | mirror_info_t *p; | 1105 | mirror_info_t *p; |
1106 | int first = 0; | ||
1107 | int last = mddev->raid_disks - 1; | ||
1106 | 1108 | ||
1107 | for (mirror=0; mirror < mddev->raid_disks; mirror++) | 1109 | if (rdev->raid_disk >= 0) |
1110 | first = last = rdev->raid_disk; | ||
1111 | |||
1112 | for (mirror = first; mirror <= last; mirror++) | ||
1108 | if ( !(p=conf->mirrors+mirror)->rdev) { | 1113 | if ( !(p=conf->mirrors+mirror)->rdev) { |
1109 | 1114 | ||
1110 | blk_queue_stack_limits(mddev->queue, | 1115 | blk_queue_stack_limits(mddev->queue, |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a71277b640ab..50ad8d2ae0e8 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1116,6 +1116,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1116 | int found = 0; | 1116 | int found = 0; |
1117 | int mirror; | 1117 | int mirror; |
1118 | mirror_info_t *p; | 1118 | mirror_info_t *p; |
1119 | int first = 0; | ||
1120 | int last = mddev->raid_disks - 1; | ||
1119 | 1121 | ||
1120 | if (mddev->recovery_cp < MaxSector) | 1122 | if (mddev->recovery_cp < MaxSector) |
1121 | /* only hot-add to in-sync arrays, as recovery is | 1123 | /* only hot-add to in-sync arrays, as recovery is |
@@ -1125,12 +1127,16 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1125 | if (!enough(conf)) | 1127 | if (!enough(conf)) |
1126 | return 0; | 1128 | return 0; |
1127 | 1129 | ||
1130 | if (rdev->raid_disk) | ||
1131 | first = last = rdev->raid_disk; | ||
1132 | |||
1128 | if (rdev->saved_raid_disk >= 0 && | 1133 | if (rdev->saved_raid_disk >= 0 && |
1134 | rdev->saved_raid_disk >= first && | ||
1129 | conf->mirrors[rdev->saved_raid_disk].rdev == NULL) | 1135 | conf->mirrors[rdev->saved_raid_disk].rdev == NULL) |
1130 | mirror = rdev->saved_raid_disk; | 1136 | mirror = rdev->saved_raid_disk; |
1131 | else | 1137 | else |
1132 | mirror = 0; | 1138 | mirror = first; |
1133 | for ( ; mirror < mddev->raid_disks; mirror++) | 1139 | for ( ; mirror <= last ; mirror++) |
1134 | if ( !(p=conf->mirrors+mirror)->rdev) { | 1140 | if ( !(p=conf->mirrors+mirror)->rdev) { |
1135 | 1141 | ||
1136 | blk_queue_stack_limits(mddev->queue, | 1142 | blk_queue_stack_limits(mddev->queue, |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 214b44122822..002f33b1ae00 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -4607,21 +4607,27 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
4607 | int found = 0; | 4607 | int found = 0; |
4608 | int disk; | 4608 | int disk; |
4609 | struct disk_info *p; | 4609 | struct disk_info *p; |
4610 | int first = 0; | ||
4611 | int last = conf->raid_disks - 1; | ||
4610 | 4612 | ||
4611 | if (mddev->degraded > conf->max_degraded) | 4613 | if (mddev->degraded > conf->max_degraded) |
4612 | /* no point adding a device */ | 4614 | /* no point adding a device */ |
4613 | return 0; | 4615 | return 0; |
4614 | 4616 | ||
4617 | if (rdev->raid_disk >= 0) | ||
4618 | first = last = rdev->raid_disk; | ||
4619 | |||
4615 | /* | 4620 | /* |
4616 | * find the disk ... but prefer rdev->saved_raid_disk | 4621 | * find the disk ... but prefer rdev->saved_raid_disk |
4617 | * if possible. | 4622 | * if possible. |
4618 | */ | 4623 | */ |
4619 | if (rdev->saved_raid_disk >= 0 && | 4624 | if (rdev->saved_raid_disk >= 0 && |
4625 | rdev->saved_raid_disk >= first && | ||
4620 | conf->disks[rdev->saved_raid_disk].rdev == NULL) | 4626 | conf->disks[rdev->saved_raid_disk].rdev == NULL) |
4621 | disk = rdev->saved_raid_disk; | 4627 | disk = rdev->saved_raid_disk; |
4622 | else | 4628 | else |
4623 | disk = 0; | 4629 | disk = first; |
4624 | for ( ; disk < conf->raid_disks; disk++) | 4630 | for ( ; disk <= last ; disk++) |
4625 | if ((p=conf->disks + disk)->rdev == NULL) { | 4631 | if ((p=conf->disks + disk)->rdev == NULL) { |
4626 | clear_bit(In_sync, &rdev->flags); | 4632 | clear_bit(In_sync, &rdev->flags); |
4627 | rdev->raid_disk = disk; | 4633 | rdev->raid_disk = disk; |