From 9008ed1c9623b7c11775ea8a7be17eb1bde5fd09 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 4 Nov 2008 20:51:12 +1100 Subject: [PATCH] Assemble: allow members of containers to be assembled and auto-assembled. Try to treat members of containers much like other arrays for assembly. We still look through the list of devices for a match (it will be the container), then find the relevant 'info' and try to assemble the array. Signed-off-by: NeilBrown --- Assemble.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++- config.c | 3 ++ mdadm.c | 3 ++ mdadm.h | 3 ++ util.c | 14 +++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) diff --git a/Assemble.c b/Assemble.c index b152ebef..e421f22d 100644 --- a/Assemble.c +++ b/Assemble.c @@ -50,7 +50,7 @@ static int name_matches(char *found, char *required, char *homehost) return 0; } -/*static */ int is_member_busy(char *metadata_version) +static int is_member_busy(char *metadata_version) { /* check if the given member array is active */ struct mdstat_ent *mdstat = mdstat_read(1, 0); @@ -273,6 +273,62 @@ int Assemble(struct supertype *st, char *mddev, } if (dfd >= 0) close(dfd); + if (tst && tst->sb && tst->ss->container_content + && tst->loaded_container) { + /* tmpdev is a container. We need to be either + * looking for a member, or auto-assembling + */ + if (st) { + /* already found some components, this cannot + * be another one. + */ + if (report_missmatch) + fprintf(stderr, Name ": %s is a container, but we are looking for components\n", + devname); + goto loop; + } + + if (ident->container) { + if (ident->container[0] == '/' && + !same_dev(ident->container, devname)) { + if (report_missmatch) + fprintf(stderr, Name ": %s is not the container required (%s)\n", + devname, ident->container); + goto loop; + } + if (ident->container[0] != '/') { + /* we have a uuid */ + int uuid[4]; + if (!parse_uuid(ident->container, uuid) || + !same_uuid(content->uuid, uuid, tst->ss->swapuuid)) { + if (report_missmatch) + fprintf(stderr, Name ": %s has wrong UUID to be required container\n", + devname); + goto loop; + } + } + } + /* It is worth looking inside this container. + */ + next_member: + if (tmpdev->content) + content = tmpdev->content; + else + content = tst->ss->container_content(tst); + + tmpdev->content = content->next; + if (tmpdev->content == NULL) + tmpdev->used = 1; + + } else if (ident->container || ident->member) { + /* No chance of this matching if we don't have + * a container */ + if (report_missmatch) + fprintf(stderr, Name "%s is not a container, and one is required.\n", + devname); + goto loop; + } + if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) && (!tst || !tst->sb || same_uuid(content->uuid, ident->uuid, tst->ss->swapuuid)==0)) { @@ -332,6 +388,30 @@ int Assemble(struct supertype *st, char *mddev, return 1; } + if (tst && tst->sb && tst->ss->container_content + && tst->loaded_container) { + /* we have the one container we need, don't keep + * looking. If the chosen member is active, skip. + */ + if (is_member_busy(content->text_version)) { + if (auto_assem) + goto loop; + fprintf(stderr, Name ": member %s in %s is already assembled\n", + content->text_version, + devname); + tst->ss->free_super(tst); + return 1; + } + st = tst; tst = NULL; + if (!auto_assem && tmpdev->next != NULL) { + fprintf(stderr, Name ": %s is a container, but is not " + "only device given: confused and aborting\n", + devname); + st->ss->free_super(st); + return 1; + } + break; + } if (st == NULL) st = dup_super(tst); if (st->minor_version == -1) @@ -380,6 +460,8 @@ int Assemble(struct supertype *st, char *mddev, tmpdev->used = 1; loop: + if (tmpdev->content) + goto next_member; if (tst) tst->ss->free_super(tst); } @@ -458,6 +540,13 @@ int Assemble(struct supertype *st, char *mddev, } ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */ +#ifndef MDASSEMBLE + if (content != &info) { + /* This is a member of a container. Try starting the array. */ + return assemble_container_content(st, mdfd, content, runstop, + chosen_name, verbose); + } +#endif /* Ok, no bad inconsistancy, we can try updating etc */ bitmap_done = 0; for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) { diff --git a/config.c b/config.c index 8b233559..6ab5a346 100644 --- a/config.c +++ b/config.c @@ -261,6 +261,7 @@ mddev_dev_t load_partitions(void) d->devname = strdup(name); d->next = rv; d->used = 0; + d->content = NULL; rv = d; } fclose(f); @@ -290,6 +291,7 @@ mddev_dev_t load_containers(void) } d->next = rv; d->used = 0; + d->content = NULL; rv = d; } free_mdstat(mdstat); @@ -803,6 +805,7 @@ mddev_dev_t conf_get_devs() t->devname = strdup(globbuf.gl_pathv[i]); t->next = dlist; t->used = 0; + t->content = NULL; dlist = t; /* printf("one dev is %s\n", t->devname);*/ } diff --git a/mdadm.c b/mdadm.c index f830a8dd..2bd963a5 100644 --- a/mdadm.c +++ b/mdadm.c @@ -256,6 +256,7 @@ int main(int argc, char *argv[]) dv->writemostly = writemostly; dv->re_add = re_add; dv->used = 0; + dv->content = NULL; dv->next = NULL; *devlistend = dv; devlistend = &dv->next; @@ -308,6 +309,8 @@ int main(int argc, char *argv[]) dv->disposition = devmode; dv->writemostly = writemostly; dv->re_add = re_add; + dv->used = 0; + dv->content = NULL; dv->next = NULL; *devlistend = dv; devlistend = &dv->next; diff --git a/mdadm.h b/mdadm.h index e76bc4d3..8131b60a 100644 --- a/mdadm.h +++ b/mdadm.h @@ -278,6 +278,8 @@ typedef struct mddev_dev_s { char writemostly; /* 1 for 'set writemostly', 2 for 'clear writemostly' */ char re_add; char used; /* set when used */ + struct mdinfo *content; /* If devname is a container, this might list + * the remaining member arrays. */ struct mddev_dev_s *next; } *mddev_dev_t; @@ -758,6 +760,7 @@ extern int get_mdp_major(void); extern int dev_open(char *dev, int flags); extern int open_dev_excl(int devnum); extern int is_standard(char *dev, int *nump); +extern int same_dev(char *one, char *two); extern int parse_auto(char *str, char *msg, int config); extern mddev_ident_t conf_get_ident(char *dev); diff --git a/util.c b/util.c index f15ba43d..1736d707 100644 --- a/util.c +++ b/util.c @@ -828,6 +828,20 @@ int open_dev_excl(int devnum) return -1; } +int same_dev(char *one, char *two) +{ + struct stat st1, st2; + if (stat(one, &st1) != 0) + return 0; + if (stat(two, &st2) != 0) + return 0; + if ((st1.st_mode & S_IFMT) != S_IFBLK) + return 0; + if ((st2.st_mode & S_IFMT) != S_IFBLK) + return 0; + return st1.st_rdev == st2.st_rdev; +} + struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, NULL }; #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) -- 2.39.2