summaryrefslogtreecommitdiff
path: root/Assemble.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-06-05 15:58:31 +1000
committerNeilBrown <neilb@suse.de>2014-06-05 15:58:31 +1000
commit02b70e83e6367c3337de288320cf4b0edf51ad0e (patch)
tree0926b10c42306245ef781c0ad31ba4d05a587380 /Assemble.c
parent8a3544f8959375ee167a46ff9e7fc4050127b349 (diff)
Incremental: remove old devices when assembling in container.
When assembling a native array we just give all devices to the kernel and leave it to discard the 'old' ones (based on sequence/event number). For external/container arrays, mdadm needs to do that. So in assemble_container_content, get list of current devices in array and discard any that aren't in the 'content' given. They must have been rejected by metadata manager. If we cannot discard old devices the array must already be active, so just leave it alone, but with a message. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'Assemble.c')
-rw-r--r--Assemble.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/Assemble.c b/Assemble.c
index a57d384d..63e09ac3 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1793,7 +1793,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
struct mdinfo *content, struct context *c,
char *chosen_name, int *result)
{
- struct mdinfo *dev, *sra;
+ struct mdinfo *dev, *sra, *dev2;
int working = 0, preexist = 0;
int expansion = 0;
struct map_ent *map = NULL;
@@ -1804,7 +1804,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
sysfs_init(content, mdfd, NULL);
- sra = sysfs_read(mdfd, NULL, GET_VERSION);
+ sra = sysfs_read(mdfd, NULL, GET_VERSION|GET_DEVS);
if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) {
if (content->array.major_version == -1 &&
content->array.minor_version == -2 &&
@@ -1831,8 +1831,22 @@ int assemble_container_content(struct supertype *st, int mdfd,
if (st->ss->external && content->recovery_blocked && start_reshape)
block_subarray(content);
- if (sra)
- sysfs_free(sra);
+ for (dev2 = sra->devs; dev2; dev2 = dev2->next) {
+ for (dev = content->devs; dev; dev = dev->next)
+ if (dev2->disk.major == dev->disk.major &&
+ dev2->disk.minor == dev->disk.minor)
+ break;
+ if (dev)
+ continue;
+ /* Don't want this one any more */
+ if (sysfs_set_str(sra, dev2, "slot", "none") < 0 &&
+ errno == EBUSY) {
+ pr_err("Cannot remove old device %s: not updating %s\n", dev2->sys_name, sra->sys_name);
+ sysfs_free(sra);
+ return 1;
+ }
+ sysfs_set_str(sra, dev2, "state", "remove");
+ }
old_raid_disks = content->array.raid_disks - content->delta_disks;
avail = xcalloc(content->array.raid_disks, 1);
for (dev = content->devs; dev; dev = dev->next) {
@@ -1847,6 +1861,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
} else if (errno == EEXIST)
preexist++;
}
+ sysfs_free(sra);
if (working + expansion == 0 && c->runstop <= 0) {
free(avail);
return 1;/* Nothing new, don't try to start */