Copy of a message I also sent to 766@???
------------------------
1| mdadm: DeviceDisappeared event detected on md device /dev/md/md3
1| mdadm: DeviceDisappeared event detected on md device /dev/md/md2
1| mdadm: DeviceDisappeared event detected on md device /dev/md/md1
1| mdadm: DeviceDisappeared event detected on md device /dev/md/md0
2| mdadm: NewArray event detected on md device /dev/md0
2| mdadm: NewArray event detected on md device /dev/md1
2| mdadm: NewArray event detected on md device /dev/md3
2| mdadm: NewArray event detected on md device /dev/md2
Short version: Won't happen anymore with 4.5, bug can be closed.
Long Explanation:
-----------------
The 4.2 Monitor routine (in Monitor.c) uses the following loop to
preprocess mdadm.conf entries:
,----
| for (; mdlist; mdlist = mdlist->next) {
| struct state *st;
|
| if (mdlist->devname == NULL)
| continue;
| if (strcasecmp(mdlist->devname, "<ignore>") == 0)
| continue;
| st = xcalloc(1, sizeof *st);
| if (mdlist->devname[0] == '/')
| st->devname = xstrdup(mdlist->devname);
| else {
| st->devname = xmalloc(8+strlen(mdlist->devname)+1);
| strcat(strcpy(st->devname, "/dev/md/"),
| mdlist->devname);
| }
|
| [...]
|
| }
`----
This means it'll prefix array names which don't start with / with
/dev/md. The so-qualified names will then be passed to the check_array
routine:
,----
| static int check_array(struct state *st, struct mdstat_ent *mdstat,
| int test, struct alert_info *ainfo,
| int increments, char *prefer)
| {
| /* Update the state 'st' to reflect any changes shown in mdstat,
| * or found by directly examining the array, and return
| * '1' if the array is degraded, or '0' if it is optimal (or dead).
| */
|
| [...]
|
| char *dev = st->devname;
|
| [...]
|
| fd = open(dev, O_RDONLY);
| if (fd < 0)
| goto disappeared;
|
| [...]
|
| disappeared:
| if (!st->err && !is_container)
| alert("DeviceDisappeared", dev, NULL, ainfo);
`----
this will cause a single DeviceDisappeared alert if a name qualified in
this way doesn't actually exist. This is responsible for the quoted
output labelled with '1|' above.
The lines labelled with '2|' were logged because the listed md devices
weren't found in the /etc configuration but by scanning /proc/mdstat.
In 4.5, the Monitor loop was changed to
,----
| for (; mdlist; mdlist = mdlist->next) {
| struct state *st;
|
| if (mdlist->devname == NULL)
| continue;
| if (is_devname_ignore(mdlist->devname) == true)
| continue;
|
| st = xcalloc(1, sizeof *st);
| snprintf(st->devname, sizeof(st->devname), "%s%s",
| '/' == *mdlist->devname ? "" : DEV_MD_DIR, mdlist->devname);
| if (!is_mddev(st->devname)) {
| free(st);
| continue;
| }
`----
Among other things, is_mddev tries to open the qualified name and drops
it from the list if this doesn't succeed. The names thus won't be passed
to check_array anymore and won't cause alerts about disappearing devices
anymore.
The underlying issue must have been that a mdadm configuration file
either contained the /dev/md/mdN¹ names or just the mdN names without a
path.
¹ By default, /dev/md contains symlinks of the form /dev/md/N ->
/dev/mdN which are created by a udev rule on aray detection.