summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-04-18 11:00:07 +1000
committerNeilBrown <neilb@suse.de>2012-04-18 11:00:07 +1000
commitc2ecf5f61aca2d73b7d5a6cb3a26973916d5c0d1 (patch)
tree747e82e252a746c42c01879ec41587ae6c336935
parent480f3566411675ec41f18e5f6e15429f891e144c (diff)
downloadmdadm-c2ecf5f61aca2d73b7d5a6cb3a26973916d5c0d1.tar.gz
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 <neilb@suse.de>
-rw-r--r--Detail.c11
-rw-r--r--Monitor.c18
-rw-r--r--ReadMe.c1
-rw-r--r--lib.c9
-rw-r--r--mdadm.8.in22
-rw-r--r--mdadm.c15
-rw-r--r--mdadm.h12
7 files changed, 68 insertions, 20 deletions
diff --git a/Detail.c b/Detail.c
index 1d7e3a1..ae15846 100644
--- 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,
diff --git a/Monitor.c b/Monitor.c
index 7ed5282..b0a242b 100644
--- 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 &&
diff --git a/ReadMe.c b/ReadMe.c
index a60e11b..24c03e0 100644
--- 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 2739b3d..c04f6a0 100644
--- 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.
diff --git a/mdadm.8.in b/mdadm.8.in
index bddecd9..fa4d2f3 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -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 4d4820d..846bc96 100644
--- 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 71cef38..e60a706 100644
--- 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);