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>
This commit is contained in:
parent
480f356641
commit
c2ecf5f61a
11
Detail.c
11
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,
|
||||
|
|
18
Monitor.c
18
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 &&
|
||||
|
|
1
ReadMe.c
1
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},
|
||||
|
|
9
lib.c
9
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.
|
||||
|
|
22
mdadm.8.in
22
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
|
||||
|
|
15
mdadm.c
15
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:
|
||||
|
|
12
mdadm.h
12
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);
|
||||
|
|
Loading…
Reference in New Issue