From d5a4041647d2b3328ce45ff727afe37477f07c75 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 13 Sep 2013 10:51:20 +1000 Subject: [PATCH] Make -IRs and --run work properly for containers. We really need to make sure assemble_container_content() gets called to finished the assembly of these. Reported-by: Francis Moreau Signed-off-by: NeilBrown --- Assemble.c | 2 +- Incremental.c | 53 +++++++++++++++++++++++++++++++++++++++++++-------- Manage.c | 4 ++-- mdadm.c | 7 ++++--- mdadm.h | 4 ++-- 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/Assemble.c b/Assemble.c index bc85603..86b4c89 100644 --- a/Assemble.c +++ b/Assemble.c @@ -1817,7 +1817,7 @@ int assemble_container_content(struct supertype *st, int mdfd, working++; } else if (errno == EEXIST) preexist++; - if (working + expansion == 0) + if (working + expansion == 0 && c->runstop <= 0) return 1;/* Nothing new, don't try to start */ map_update(&map, fd2devnm(mdfd), diff --git a/Incremental.c b/Incremental.c index f256b48..1bb3638 100644 --- a/Incremental.c +++ b/Incremental.c @@ -44,7 +44,7 @@ static int try_spare(char *devname, int *dfdp, struct dev_policy *pol, struct supertype *st, int verbose); static int Incremental_container(struct supertype *st, char *devname, - struct context *c); + struct context *c, char *only); int Incremental(char *devname, struct context *c, struct supertype *st) @@ -138,7 +138,7 @@ int Incremental(char *devname, struct context *c, if (map_lock(&map)) pr_err("failed to get " "exclusive lock on mapfile\n"); - rv = Incremental_container(st, devname, c); + rv = Incremental_container(st, devname, c, NULL); map_unlock(&map); return rv; } @@ -478,7 +478,7 @@ int Incremental(char *devname, struct context *c, close(mdfd); sysfs_free(sra); if (!rv) - rv = Incremental_container(st, chosen_name, c); + rv = Incremental_container(st, chosen_name, c, NULL); map_unlock(&map); if (rv == 1) /* Don't fail the whole -I if a subarray didn't @@ -1278,7 +1278,7 @@ static int try_spare(char *devname, int *dfdp, struct dev_policy *pol, return rv; } -int IncrementalScan(int verbose, char *devnm) +int IncrementalScan(struct context *c, char *devnm) { /* look at every device listed in the 'map' file. * If one is found that is not running then: @@ -1290,10 +1290,13 @@ int IncrementalScan(int verbose, char *devnm) struct map_ent *me; struct mddev_ident *devs, *mddev; int rv = 0; + char container[32]; + char *only = NULL; map_read(&mapl); devs = conf_get_ident(NULL); +restart: for (me = mapl ; me ; me = me->next) { mdu_array_info_t array; mdu_bitmap_file_t bmf; @@ -1302,10 +1305,42 @@ int IncrementalScan(int verbose, char *devnm) if (devnm && strcmp(devnm, me->devnm) != 0) continue; + if (devnm && me->metadata[0] == '/') { + char *sl; + /* member array, need to work on container */ + strncpy(container, me->metadata+1, 32); + container[31] = 0; + sl = strchr(container, '/'); + if (sl) + *sl = 0; + only = devnm; + devnm = container; + goto restart; + } mdfd = open_dev(me->devnm); if (mdfd < 0) continue; + if (!isdigit(me->metadata[0])) { + /* must be a container */ + struct supertype *st = super_by_fd(mdfd, NULL); + int ret = 0; + struct map_ent *map = NULL; + if (st) + st->ignore_hw_compat = 1; + if (st && st->ss->load_container) + ret = st->ss->load_container(st, mdfd, NULL); + close(mdfd); + if (!ret && st->ss->container_content) { + if (map_lock(&map)) + pr_err("failed to get exclusive lock on mapfile\n"); + ret = Incremental_container(st, me->path, c, only); + map_unlock(&map); + } + if (ret) + rv = 1; + continue; + } if (ioctl(mdfd, GET_ARRAY_INFO, &array) == 0 || errno != ENODEV) { close(mdfd); @@ -1330,7 +1365,7 @@ int IncrementalScan(int verbose, char *devnm) close(bmfd); } } - if (verbose >= 0) { + if (c->verbose >= 0) { if (added == 0) pr_err("Added bitmap %s to %s\n", mddev->bitmap_file, me->path); @@ -1346,7 +1381,7 @@ int IncrementalScan(int verbose, char *devnm) if (sra) { if (sysfs_set_str(sra, NULL, "array_state", "read-auto") == 0) { - if (verbose >= 0) + if (c->verbose >= 0) pr_err("started array %s\n", me->path ?: me->devnm); } else { @@ -1387,7 +1422,7 @@ static char *container2devname(char *devname) } static int Incremental_container(struct supertype *st, char *devname, - struct context *c) + struct context *c, char *only) { /* Collect the contents of this container and for each * array, choose a device name and assemble the array. @@ -1458,7 +1493,7 @@ static int Incremental_container(struct supertype *st, char *devname, strcpy(chosen_name, mp->path); else strcpy(chosen_name, mp->devnm); - } else { + } else if (!only) { /* Check in mdadm.conf for container == devname and * member == ra->text_version after second slash. @@ -1515,6 +1550,8 @@ static int Incremental_container(struct supertype *st, char *devname, trustworthy, chosen_name); } + if (only && (!mp || strcmp(mp->devnm, only) != 0)) + continue; if (mdfd < 0) { pr_err("failed to open %s: %s.\n", diff --git a/Manage.c b/Manage.c index 910caa6..c8276ca 100644 --- a/Manage.c +++ b/Manage.c @@ -170,7 +170,7 @@ static void remove_devices(char *devnm, char *path) free(path2); } -int Manage_run(char *devname, int fd, int verbose) +int Manage_run(char *devname, int fd, struct context *c) { /* Run the array. Array must already be configured * Requires >= 0.90.0 @@ -187,7 +187,7 @@ int Manage_run(char *devname, int fd, int verbose) return 1; } strcpy(nm, nmp); - return IncrementalScan(verbose, nm); + return IncrementalScan(c, nm); } int Manage_stop(char *devname, int fd, int verbose, int will_retry) diff --git a/mdadm.c b/mdadm.c index 1ada607..f55a035 100644 --- a/mdadm.c +++ b/mdadm.c @@ -1293,7 +1293,7 @@ int main(int argc, char *argv[]) if (!rv && c.readonly < 0) rv = Manage_ro(devlist->devname, mdfd, c.readonly); if (!rv && c.runstop > 0) - rv = Manage_run(devlist->devname, mdfd, c.verbose); + rv = Manage_run(devlist->devname, mdfd, &c); if (!rv && c.runstop < 0) rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0); break; @@ -1535,7 +1535,7 @@ int main(int argc, char *argv[]) pr_err("--incremental --scan --fail not supported.\n"); break; } - rv = IncrementalScan(c.verbose, NULL); + rv = IncrementalScan(&c, NULL); } if (!devlist) { if (!rebuild_map && !c.scan) { @@ -1804,7 +1804,8 @@ static int misc_list(struct mddev_dev *devlist, if (mdfd>=0) { switch(dv->disposition) { case 'R': - rv |= Manage_run(dv->devname, mdfd, c->verbose); break; + c->runstop = 1; + rv |= Manage_run(dv->devname, mdfd, c); break; case 'S': rv |= Manage_stop(dv->devname, mdfd, c->verbose, 0); break; case 'o': diff --git a/mdadm.h b/mdadm.h index 2eca603..c90fe10 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1171,7 +1171,7 @@ struct stat64; extern int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s); extern int Manage_ro(char *devname, int fd, int readonly); -extern int Manage_run(char *devname, int fd, int quiet); +extern int Manage_run(char *devname, int fd, struct context *c); extern int Manage_stop(char *devname, int fd, int quiet, int will_retry); extern int Manage_subdevs(char *devname, int fd, @@ -1237,7 +1237,7 @@ extern int WaitClean(char *dev, int sock, int verbose); extern int Incremental(char *devname, struct context *c, struct supertype *st); extern void RebuildMap(void); -extern int IncrementalScan(int verbose, char *devnm); +extern int IncrementalScan(struct context *c, char *devnm); extern int IncrementalRemove(char *devname, char *path, int verbose); extern int CreateBitmap(char *filename, int force, char uuid[16], unsigned long chunksize, unsigned long daemon_sleep,