]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add --prefer option for --detail and --monitor
authorNeilBrown <neilb@suse.de>
Wed, 18 Apr 2012 01:00:07 +0000 (11:00 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 18 Apr 2012 01:00:07 +0000 (11:00 +1000)
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 <neilb@suse.de>
Detail.c
Monitor.c
ReadMe.c
lib.c
mdadm.8.in
mdadm.c
mdadm.h

index 1d7e3a1648288472ef396f55f2e55ed1e2b14042..ae15846d8d5bd6edb2d68fb00fc314387d3f86ae 100644 (file)
--- a/Detail.c
+++ b/Detail.c
@@ -27,7 +27,7 @@
 #include       "md_u.h"
 #include       <dirent.h>
 
-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 export, int test, char *homehost)
                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);
@@ -558,7 +559,7 @@ This is pretty boring
                if (test && d < array.raid_disks
                    && !(disk.state & (1<<MD_DISK_SYNC)))
                        rv |= 1;
-               if ((dv=map_dev(disk.major, disk.minor, 0))) {
+               if ((dv=map_dev_preferred(disk.major, disk.minor, 0, prefer))) {
                        if (brief) {
                                if (devices) {
                                        devices = realloc(devices,
index 7ed5282b2c33a85da756f9330cff88d5de2488ee..b0a242b44fa9ce03c939a2742a3c9b34934ab880 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -69,7 +69,7 @@ static int check_one_sharer(int scan);
 static void alert(char *event, char *dev, char *disc, struct alert_info *info);
 static int check_array(struct state *st, struct mdstat_ent *mdstat,
                       int test, struct alert_info *info,
-                      int increments);
+                      int increments, char *prefer);
 static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
                          int test, struct alert_info *info);
 static void try_spare_migration(struct state *statelist, struct alert_info *info);
@@ -79,7 +79,7 @@ int Monitor(struct mddev_dev *devlist,
            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)
 {
        /*
         * Every few seconds, scan every md device looking for changes
@@ -221,7 +221,8 @@ int Monitor(struct mddev_dev *devlist,
                mdstat = mdstat_read(oneshot?0:1, 0);
 
                for (st=statelist; st; st=st->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 */
@@ -445,7 +446,7 @@ static void alert(char *event, char *dev, char *disc, struct alert_info *info)
 
 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
@@ -617,7 +618,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
                        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;
@@ -629,8 +632,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
                        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 &&
index a60e11bb7507f90533f2bc3e8dcf081fb4d46e97..24c03e05e431e7c17af02552e0b6e8616fad70f7 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -174,6 +174,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},
diff --git a/lib.c b/lib.c
index 2739b3d388b2833d6a7f271242d8ab065f2fe11d..c04f6a0762d3ca14c4b782b88014169756d70c5d 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -188,8 +188,11 @@ int nftw(const char *path, int (*han)(const char *name, const struct stat *stb,
  * 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 create)
        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 create)
 }
 
 
+
 /* 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.
index bddecd903a6e16730e923f905025c39abf9db494..fa4d2f3108bf2f9670ef991b3af4443518715c2b 100644 (file)
@@ -389,6 +389,28 @@ will be allowed to use 'local' names (i.e. not ending in '_' followed
 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
diff --git a/mdadm.c b/mdadm.c
index 4d4820d39394c8e5dfcbfa556a7875391cb989cf..846bc9641af062d7436721e72794cb66c3903521 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -73,6 +73,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.
@@ -184,6 +185,13 @@ int main(int argc, char *argv[])
                        __offroot = 1;
                        continue;
 
+               case Prefer:
+                       if (prefer)
+                               free(prefer);
+                       if (asprintf(&prefer, "/%s/", optarg) <= 0)
+                               prefer = NULL;
+                       continue;
+
                case ':':
                case '?':
                        fputs(Usage, stderr);
@@ -1498,7 +1506,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);
@@ -1552,7 +1560,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)
@@ -1626,7 +1634,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:
diff --git a/mdadm.h b/mdadm.h
index 71cef38f61448996ef91c1da203a0f2bf2dbc142..e60a7066cc481f2c6a04881b6367ab0dcc761212 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -322,6 +322,7 @@ enum special_options {
        FreezeReshape,
        Continue,
        OffRootOpt,
+       Prefer,
 };
 
 /* structures read from config file */
@@ -532,7 +533,12 @@ extern char *map_num(mapping_t *map, int num);
 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;
@@ -1080,7 +1086,7 @@ extern int Create(struct supertype *st, char *mddev,
                  int runstop, int verbose, int force, int assume_clean,
                  char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof);
 
-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,
@@ -1089,7 +1095,7 @@ extern int Monitor(struct mddev_dev *devlist,
                   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);