summaryrefslogtreecommitdiff
path: root/Grow.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-12-16 09:07:52 +1100
committerNeilBrown <neilb@suse.de>2010-12-16 09:07:52 +1100
commitb5420ef325eb2d80da9002a5805d6161f551dc0c (patch)
tree1418f8dcb715fa0f887b1a3a1f454a20d86d6afb /Grow.c
parent4347544720e154698dac981292be4d9fea4148ee (diff)
Grow: add disks chosen by metadata handler to array for growth.
With externally managed container based metadata, the ->reshape_super method must choose any spares that are to be added to the array. They should be prepared so that ->container_content will find them as spares (disk.state == 0) which are assigned to a slot (raid_disk >= 0). We need to take those and add them to the array(s). Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'Grow.c')
-rw-r--r--Grow.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/Grow.c b/Grow.c
index d77b7f0f..21e14373 100644
--- a/Grow.c
+++ b/Grow.c
@@ -666,7 +666,8 @@ void abort_reshape(struct mdinfo *sra)
sysfs_set_str(sra, NULL, "sync_max", "max");
}
-static int reshape_container_raid_disks(char *container, int raid_disks)
+static int reshape_container_raid_disks(struct supertype *st,
+ char *container, int raid_disks)
{
/* for each subarray switch to a raid level that can
* support the reshape, and set raid disks
@@ -682,15 +683,17 @@ static int reshape_container_raid_disks(char *container, int raid_disks)
changed = 0;
for (e = ent; e; e = e->next) {
- struct mdinfo *sub;
+ struct mdinfo *sub, *info;
unsigned int cache;
int level, takeover_delta = 0;
int parity_disks = 1;
unsigned int odata;
unsigned long blocks;
+ char *subarray;
if (!is_container_member(e, container))
continue;
+ subarray = strchr(e->metadata_version+10, '/')+1;
rv = -1;
level = map_name(pers, e->level);
@@ -756,6 +759,23 @@ static int reshape_container_raid_disks(char *container, int raid_disks)
changed++;
break;
}
+
+ /* add the devices that were chosen */
+ info = st->ss->container_content(st, subarray);
+ if (info) {
+ struct mdinfo *d;
+ for (d = info->devs; d; d = d->next) {
+ if (d->disk.state == 0 &&
+ d->disk.raid_disk >= 0) {
+ /* This is a spare that wants to
+ * be part of the array.
+ */
+ add_disk(-1, st, info, d);
+ }
+ }
+ }
+ sysfs_free(info);
+
if (!rv && level > 1)
start_reshape(sub);
sysfs_free(sub);
@@ -1542,7 +1562,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
goto release;
}
- count = reshape_container_raid_disks(container, raid_disks);
+ count = reshape_container_raid_disks(st, container, raid_disks);
if (count < 0) {
revert_container_raid_disks(st, fd, container);
rv = 1;
@@ -1825,6 +1845,29 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
break;
}
+ /* ->reshape_super might have chosen some spares from the
+ * container that it wants to be part of the new array.
+ * We can collect them with ->container_content and give
+ * them to the kernel.
+ */
+ if (st->ss->reshape_super && st->ss->container_content) {
+ struct mdinfo *info =
+ st->ss->container_content(st, subarray);
+ struct mdinfo *d;
+
+ if (info)
+ for (d = info->devs; d; d = d->next) {
+ if (d->disk.state == 0 &&
+ d->disk.raid_disk >= 0) {
+ /* This is a spare that wants to
+ * be part of the array.
+ */
+ add_disk(fd, st, info, d);
+ }
+ }
+ sysfs_free(info);
+ }
+
/* lastly, check that the internal stripe cache is
* large enough, or it won't work.
*/