From 9ca39acb3e8bc31811e463d19fae81c5501aea65 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 28 Nov 2013 15:15:30 +1100 Subject: [PATCH] Incremental: add --export handling. If --export is given with --incremental, then MD_DEVNAME is output which gives the name of the device (in /dev/md) that is the array (or container) that the device would be added to. Also MD_STARTED is set to one of no unsafe yes nothing to indicate if the array was started. IF MD_STARTED=unsafe then it may be appropriate to run mdadm -R /dev/md/$MD_DEVNAME after a timeout to ensure newly degraded array are started. If MD_FOREIGN=yes it might be appropriate to suppress this as the array is probably not critical. Signed-off-by: NeilBrown --- Assemble.c | 19 +++++++++++---- Incremental.c | 64 ++++++++++++++++++++++++++++++++++++++++++++------- mdadm.8.in | 21 +++++++++++++++-- mdadm.h | 6 ++++- 4 files changed, 94 insertions(+), 16 deletions(-) diff --git a/Assemble.c b/Assemble.c index 11b77c28..44e905bb 100644 --- a/Assemble.c +++ b/Assemble.c @@ -1419,7 +1419,7 @@ try_again: /* This is a member of a container. Try starting the array. */ int err; err = assemble_container_content(st, mdfd, content, c, - chosen_name); + chosen_name, NULL); close(mdfd); return err; } @@ -1771,7 +1771,7 @@ try_again: #ifndef MDASSEMBLE int assemble_container_content(struct supertype *st, int mdfd, struct mdinfo *content, struct context *c, - char *chosen_name) + char *chosen_name, int *result) { struct mdinfo *dev, *sra; int working = 0, preexist = 0; @@ -1838,7 +1838,9 @@ int assemble_container_content(struct supertype *st, int mdfd, if (enough(content->array.level, content->array.raid_disks, content->array.layout, content->array.state & 1, avail) == 0) { - if (c->verbose >= 0) { + if (c->export && result) + *result |= INCR_NO; + else if (c->verbose >= 0) { pr_err("%s assembled with %d device%s", chosen_name, preexist + working, preexist + working == 1 ? "":"s"); @@ -1854,7 +1856,9 @@ int assemble_container_content(struct supertype *st, int mdfd, if (c->runstop <= 0 && (working + preexist + expansion) < content->array.working_disks) { - if (c->verbose >= 0) { + if (c->export && result) + *result |= INCR_UNSAFE; + else if (c->verbose >= 0) { pr_err("%s assembled with %d device%s", chosen_name, preexist + working, preexist + working == 1 ? "":"s"); @@ -1918,7 +1922,12 @@ int assemble_container_content(struct supertype *st, int mdfd, !start_reshape) block_subarray(content); - if (c->verbose >= 0) { + if (c->export && result) { + if (err) + *result |= INCR_NO; + else + *result |= INCR_YES; + } else if (c->verbose >= 0) { if (err) pr_err("array %s now has %d device%s", chosen_name, working + preexist, diff --git a/Incremental.c b/Incremental.c index d082e61d..0703deae 100644 --- a/Incremental.c +++ b/Incremental.c @@ -91,6 +91,7 @@ int Incremental(char *devname, struct context *c, struct mdinfo *sra = NULL, *d; struct mddev_ident *match; char chosen_name[1024]; + char *md_devname; int rv = 1; struct map_ent *mp, *map = NULL; int dfd = -1, mdfd = -1; @@ -138,6 +139,8 @@ int Incremental(char *devname, struct context *c, if (map_lock(&map)) pr_err("failed to get " "exclusive lock on mapfile\n"); + if (c->export) + printf("MD_DEVNAME=%s\n", devname); rv = Incremental_container(st, devname, c, NULL); map_unlock(&map); return rv; @@ -459,6 +462,15 @@ int Incremental(char *devname, struct context *c, info.array.working_disks ++; } + if (strncmp(chosen_name, "/dev/md/", 8) == 0) + md_devname = chosen_name+8; + else + md_devname = chosen_name; + if (c->export) { + printf("MD_DEVICE=%s\n", fd2devnm(mdfd)); + printf("MD_DEVNAME=%s\n", md_devname); + printf("MD_FOREIGN=%s\n", trustworthy == FOREIGN ? "yes" : "no"); + } /* 7/ Is there enough devices to possibly start the array? */ /* 7a/ if not, finish with success. */ @@ -466,7 +478,7 @@ int Incremental(char *devname, struct context *c, char devnm[32]; /* Try to assemble within the container */ sysfs_uevent(sra, "change"); - if (c->verbose >= 0) + if (!c->export && c->verbose >= 0) pr_err("container %s now has %d device%s\n", chosen_name, info.array.working_disks, info.array.working_disks == 1?"":"s"); @@ -498,7 +510,9 @@ int Incremental(char *devname, struct context *c, if (enough(info.array.level, info.array.raid_disks, info.array.layout, info.array.state & 1, avail) == 0) { - if (c->verbose >= 0) + if (c->export) { + printf("MD_STARTED=no\n"); + } else if (c->verbose >= 0) pr_err("%s attached to %s, not enough to start (%d).\n", devname, chosen_name, active_disks); rv = 0; @@ -512,7 +526,9 @@ int Incremental(char *devname, struct context *c, /* + start the array (auto-readonly). */ if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) { - if (c->verbose >= 0) + if (c->export) { + printf("MD_STARTED=already\n"); + } else if (c->verbose >= 0) pr_err("%s attached to %s which is already active.\n", devname, chosen_name); rv = 0; @@ -559,7 +575,9 @@ int Incremental(char *devname, struct context *c, rv = sysfs_set_str(sra, NULL, "array_state", "read-auto"); if (rv == 0) { - if (c->verbose >= 0) + if (c->export) { + printf("MD_STARTED=yes\n"); + } else if (c->verbose >= 0) pr_err("%s attached to %s, which has been started.\n", devname, chosen_name); rv = 0; @@ -582,7 +600,9 @@ int Incremental(char *devname, struct context *c, rv = 1; } } else { - if (c->verbose >= 0) + if (c->export) { + printf("MD_STARTED=unsafe\n"); + } else if (c->verbose >= 0) pr_err("%s attached to %s, not enough to start safely.\n", devname, chosen_name); rv = 0; @@ -1436,6 +1456,7 @@ static int Incremental_container(struct supertype *st, char *devname, int sfd; int ra_blocked = 0; int ra_all = 0; + int result = 0; st->ss->getinfo_super(st, &info, NULL); @@ -1443,7 +1464,9 @@ static int Incremental_container(struct supertype *st, char *devname, info.container_enough > 0) /* pass */; else { - if (c->verbose) + if (c->export) { + printf("MD_STARTED=no\n"); + } else if (c->verbose) pr_err("not enough devices to start the container\n"); return 0; } @@ -1464,8 +1487,12 @@ static int Incremental_container(struct supertype *st, char *devname, list = st->ss->container_content(st, NULL); /* when nothing to activate - quit */ - if (list == NULL) + if (list == NULL) { + if (c->export) { + printf("MD_STARTED=nothing\n"); + } return 0; + } for (ra = list ; ra ; ra = ra->next) { int mdfd; char chosen_name[1024]; @@ -1555,9 +1582,30 @@ static int Incremental_container(struct supertype *st, char *devname, } assemble_container_content(st, mdfd, ra, c, - chosen_name); + chosen_name, &result); close(mdfd); } + if (c->export && result) { + char sep = '='; + printf("MD_STARTED"); + if (result & INCR_NO) { + printf("%cno", sep); + sep = ','; + } + if (result & INCR_UNSAFE) { + printf("%cunsafe", sep); + sep = ','; + } + if (result & INCR_ALREADY) { + printf("%calready", sep); + sep = ','; + } + if (result & INCR_YES) { + printf("%cyes", sep); + sep = ','; + } + printf("\n"); + } /* don't move spares to container with volume being activated when all volumes are blocked */ diff --git a/mdadm.8.in b/mdadm.8.in index 61cb4f71..f49822ec 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -1440,13 +1440,30 @@ absolute filepath or a link, e.g. .TP .BR \-Y ", " \-\-export When used with -.B \-\-detail , \-\-detail-platform -or +.BR \-\-detail , +.BR \-\-detail-platform , .BR \-\-examine , +or +.B \-\-incremental output will be formatted as .B key=value pairs for easy import into the environment. +With +.B \-\-incremental +The value +.B MD_STARTED +indicates whether an array was started +.RB ( yes ) +or not, which may include a reason +.RB ( unsafe ", " nothing ", " no ). +Also the value +.B MD_FOREIGN +indicates if the array is expected on this host +.RB ( no ), +or seems to be from elsewhere +.RB ( yes ). + .TP .BR \-E ", " \-\-examine Print contents of the metadata stored on the named device(s). diff --git a/mdadm.h b/mdadm.h index 7cfdd8fd..c38fdfb9 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1331,7 +1331,11 @@ extern void append_metadata_update(struct supertype *st, void *buf, int len); extern int assemble_container_content(struct supertype *st, int mdfd, struct mdinfo *content, struct context *c, - char *chosen_name); + char *chosen_name, int *result); +#define INCR_NO 1 +#define INCR_UNSAFE 2 +#define INCR_ALREADY 4 +#define INCR_YES 8 extern struct mdinfo *container_choose_spares(struct supertype *st, unsigned long long min_size, struct domainlist *domlist, -- 2.39.2