]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Monitor: don't open md array that doesn't exist.
authorNeilBrown <neilb@suse.de>
Tue, 28 Oct 2014 21:48:02 +0000 (08:48 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 25 Nov 2014 00:44:29 +0000 (11:44 +1100)
Opening a block-special-device for an array that doesn't
exist causes that array to be instantiated (as an empty array).
Races at array shutdown can cause the array to spontaneously
re-appear if some deamon notices a 'change' event and goes
to investigate.

Teach "mdadm --monitor" to avoid this race by checking the
"array_state" before opening the device.

Reported-by: Francis Moreau <francis.moro@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Monitor.c

index 5cb24fab8f2a4b83baa31ab2be05f9cb0b737a62..971d2ecbea723a8d6afbf77339b6e3ed9f92c803 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -460,7 +460,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
        mdu_array_info_t array;
        struct mdstat_ent *mse = NULL, *mse2;
        char *dev = st->devname;
-       int fd;
+       int fd = -1;
        int i;
        int remaining_disks;
        int last_disk;
@@ -468,6 +468,27 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
 
        if (test)
                alert("TestMessage", dev, NULL, ainfo);
+       if (st->devnm[0])
+               fd = open("/sys/block", O_RDONLY|O_DIRECTORY);
+       if (fd >= 0) {
+               /* Don't open the device unless it is present and
+                * active in sysfs.
+                */
+               char buf[10];
+               close(fd);
+               fd = sysfs_open(st->devnm, NULL, "array_state");
+               if (fd < 0 ||
+                   read(fd, buf, 10) < 5 ||
+                   strncmp(buf,"clear",5) == 0 ||
+                   strncmp(buf,"inact",5) == 0) {
+                       if (fd >= 0)
+                               close(fd);
+                       if (!st->err)
+                               alert("DeviceDisappeared", dev, NULL, ainfo);
+                       st->err++;
+                       return 0;
+               }
+       }
        fd = open(dev, O_RDONLY);
        if (fd < 0) {
                if (!st->err)