#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
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 */
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);
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,
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);
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
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 */
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
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;
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 &&
{"export", 0, 0, 'Y'},
{"sparc2.2", 0, 0, Sparc22},
{"test", 0, 0, 't'},
+ {"prefer", 1, 0, Prefer},
/* For Follow/monitor */
{"mail", 1, 0, EMail},
* 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;
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;
}
+
/* 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.
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
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.
__offroot = 1;
continue;
+ case Prefer:
+ if (prefer)
+ free(prefer);
+ if (asprintf(&prefer, "/%s/", optarg) <= 0)
+ prefer = NULL;
+ continue;
+
case ':':
case '?':
fputs(Usage, stderr);
if (devmode == 'D')
rv |= Detail(name, v,
export, test,
- homehost);
+ homehost, prefer);
else
rv |= WaitClean(name, -1, v);
put_md_name(name);
case 'D':
rv |= Detail(dv->devname,
brief?1+verbose:0,
- export, test, homehost);
+ export, test, homehost, prefer);
continue;
case 'K': /* Zero superblock */
if (ss)
}
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:
FreezeReshape,
Continue,
OffRootOpt,
+ Prefer,
};
/* structures read from config file */
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;
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,
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);