From c2ecf5f61aca2d73b7d5a6cb3a26973916d5c0d1 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 18 Apr 2012 11:00:07 +1000 Subject: [PATCH] Add --prefer option for --detail and --monitor Both --detail and --monitor can report the names of member devices on an array, and do so by searching /dev and finding the shortest name that matches. If --prefer=foo is given, they will instead prefer a name that contain /foo/. So mdadm --detail /dev/md0 --prefer=by-path will list the component devices via their /dev/disk/by-path/xxx names. Signed-off-by: NeilBrown --- Detail.c | 11 ++++++----- Monitor.c | 18 +++++++++++------- ReadMe.c | 1 + lib.c | 9 +++++++-- mdadm.8.in | 22 ++++++++++++++++++++++ mdadm.c | 15 ++++++++++++--- mdadm.h | 12 +++++++++--- 7 files changed, 68 insertions(+), 20 deletions(-) --- mdadm-3.2.2.orig/Detail.c +++ mdadm-3.2.2/Detail.c @@ -27,7 +27,7 @@ #include "md_u.h" #include -int Detail(char *dev, int brief, int export, int test, char *homehost) +int Detail(char *dev, int brief, int export, int test, char *homehost, char *prefer) { /* * Print out details for an md array by using @@ -105,7 +105,7 @@ int Detail(char *dev, int brief, int exp int dn = st->container_dev; member = subarray; - container = map_dev(dev2major(dn), dev2minor(dn), 1); + container = map_dev_preferred(dev2major(dn), dev2minor(dn), 1, prefer); } /* try to load a superblock */ @@ -491,8 +491,9 @@ This is pretty boring vbuf[10+nlen] != '/') continue; dn = devname2devnum(de->d_name); - printf(" %s", map_dev(dev2major(dn), - dev2minor(dn), 1)); + printf(" %s", map_dev_preferred( + dev2major(dn), + dev2minor(dn), 1, prefer)); } if (dir) closedir(dir); @@ -559,7 +560,7 @@ This is pretty boring if (test && d < array.raid_disks && !(disk.state & (1<next) - if (check_array(st, mdstat, test, &info, increments)) + if (check_array(st, mdstat, test, &info, + increments, prefer)) anydegraded = 1; /* now check if there are any new devices found in mdstat */ @@ -437,7 +438,7 @@ static void alert(char *event, char *dev static int check_array(struct state *st, struct mdstat_ent *mdstat, int test, struct alert_info *ainfo, - int increments) + int increments, char *prefer) { /* Update the state 'st' to reflect any changes shown in mdstat, * or found by directly examining the array, and return @@ -608,7 +609,9 @@ static int check_array(struct state *st, disc.major = disc.minor = 0; } else if (info[i].major || info[i].minor) { newstate = info[i].state; - dv = map_dev(info[i].major, info[i].minor, 1); + dv = map_dev_preferred( + info[i].major, info[i].minor, 1, + prefer); disc.state = newstate; disc.major = info[i].major; disc.minor = info[i].minor; @@ -620,8 +623,9 @@ static int check_array(struct state *st, disc.major = disc.minor = 0; } if (dv == NULL && st->devid[i]) - dv = map_dev(major(st->devid[i]), - minor(st->devid[i]), 1); + dv = map_dev_preferred( + major(st->devid[i]), + minor(st->devid[i]), 1, prefer); change = newstate ^ st->devstate[i]; if (st->utime && change && !st->err) { if (i < array.raid_disks && --- mdadm-3.2.2.orig/ReadMe.c +++ mdadm-3.2.2/ReadMe.c @@ -176,6 +176,7 @@ struct option long_options[] = { {"export", 0, 0, 'Y'}, {"sparc2.2", 0, 0, Sparc22}, {"test", 0, 0, 't'}, + {"prefer", 1, 0, Prefer}, /* For Follow/monitor */ {"mail", 1, 0, EMail}, --- mdadm-3.2.2.orig/lib.c +++ mdadm-3.2.2/lib.c @@ -188,8 +188,11 @@ int nftw(const char *path, int (*han)(co * If we find multiple names, choose the shortest. * If we find a name in /dev/md/, we prefer that. * This applies only to names for MD devices. + * If 'prefer' is set (normally to e.g. /by-path/) + * then we prefer a name which contains that string. */ -char *map_dev(int major, int minor, int create) +char *map_dev_preferred(int major, int minor, int create, + char *prefer) { struct devmap *p; char *regular = NULL, *preferred=NULL; @@ -219,7 +222,8 @@ char *map_dev(int major, int minor, int for (p=devlist; p; p=p->next) if (p->major == major && p->minor == minor) { - if (strncmp(p->name, "/dev/md/",8) == 0) { + if (strncmp(p->name, "/dev/md/",8) == 0 + || (prefer && strstr(p->name, prefer))) { if (preferred == NULL || strlen(p->name) < strlen(preferred)) preferred = p->name; @@ -243,6 +247,7 @@ char *map_dev(int major, int minor, int } + /* conf_word gets one word from the conf file. * if "allow_key", then accept words at the start of a line, * otherwise stop when such a word is found. --- mdadm-3.2.2.orig/mdadm.8.in +++ mdadm-3.2.2/mdadm.8.in @@ -377,6 +377,28 @@ will be allowed to use 'local' names (i. by a digit string). See below under .BR "Auto Assembly" . +.TP +.B \-\-prefer= +When +.I mdadm +needs to print the name for a device it normally finds the name in +.B /dev +which refers to the device and is shortest. When a path component is +given with +.B \-\-prefer +.I mdadm +will prefer a longer name if it contains that component. For example +.B \-\-prefer=by-uuid +will prefer a name in a subdirectory of +.B /dev +called +.BR by-uuid . + +This functionality is currently only provided by +.B \-\-detail +and +.BR \-\-monitor . + .SH For create, build, or grow: .TP --- mdadm-3.2.2.orig/mdadm.c +++ mdadm-3.2.2/mdadm.c @@ -74,6 +74,7 @@ int main(int argc, char *argv[]) int test = 0; int export = 0; int assume_clean = 0; + char *prefer = NULL; char *symlinks = NULL; int grow_continue = 0; /* autof indicates whether and how to create device node. @@ -176,6 +177,13 @@ int main(int argc, char *argv[]) homehost = optarg; continue; + case Prefer: + if (prefer) + free(prefer); + if (asprintf(&prefer, "/%s/", optarg) <= 0) + prefer = NULL; + continue; + case ':': case '?': fputs(Usage, stderr); @@ -1504,7 +1512,7 @@ int main(int argc, char *argv[]) if (devmode == 'D') rv |= Detail(name, v, export, test, - homehost); + homehost, prefer); else rv |= WaitClean(name, -1, v); put_md_name(name); @@ -1558,7 +1566,7 @@ int main(int argc, char *argv[]) case 'D': rv |= Detail(dv->devname, brief?1+verbose:0, - export, test, homehost); + export, test, homehost, prefer); continue; case 'K': /* Zero superblock */ if (ss) @@ -1632,7 +1640,8 @@ int main(int argc, char *argv[]) } rv= Monitor(devlist, mailaddr, program, delay?delay:60, daemonise, scan, oneshot, - dosyslog, test, pidfile, increments, spare_sharing); + dosyslog, test, pidfile, increments, + spare_sharing, prefer); break; case GROW: --- mdadm-3.2.2.orig/mdadm.h +++ mdadm-3.2.2/mdadm.h @@ -331,6 +331,7 @@ enum special_options { FreezeReshape, Continue, DataOffset, + Prefer, }; /* structures read from config file */ @@ -542,7 +543,12 @@ extern char *map_num(mapping_t *map, int extern int map_name(mapping_t *map, char *name); extern mapping_t r5layout[], r6layout[], pers[], modes[], faultylayout[]; -extern char *map_dev(int major, int minor, int create); +extern char *map_dev_preferred(int major, int minor, int create, + char *prefer); +static inline char *map_dev(int major, int minor, int create) +{ + return map_dev_preferred(major, minor, create, NULL); +} struct active_array; struct metadata_update; @@ -1092,7 +1098,7 @@ extern int Create(struct supertype *st, char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof, unsigned long long data_offset); -extern int Detail(char *dev, int brief, int export, int test, char *homehost); +extern int Detail(char *dev, int brief, int export, int test, char *homehost, char *prefer); extern int Detail_Platform(struct superswitch *ss, int scan, int verbose); extern int Query(char *dev); extern int Examine(struct mddev_dev *devlist, int brief, int export, int scan, @@ -1101,7 +1107,7 @@ extern int Monitor(struct mddev_dev *dev char *mailaddr, char *alert_cmd, int period, int daemonise, int scan, int oneshot, int dosyslog, int test, char *pidfile, int increments, - int share); + int share, char *prefer); extern int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl); extern int Kill_subarray(char *dev, char *subarray, int quiet);