]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
sysfs: detect disks that are in the process of being removed
authorDan Williams <dan.j.williams@intel.com>
Tue, 16 Sep 2008 03:58:43 +0000 (20:58 -0700)
committerDan Williams <dan.j.williams@intel.com>
Tue, 16 Sep 2008 03:58:43 +0000 (20:58 -0700)
When removing a disk there is a window where the 'slot' attribute of
md/dev-$name will return -EBUSY to read attempts.  When this happens
look at the the 'block' link, if it is removed then we can be sure the
device has been removed, versus some other error.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
sysfs.c

diff --git a/sysfs.c b/sysfs.c
index 182028cea6efef992bce97e8c12f67857daa2e76..9ef5b394b85fa75851ce3eb776a5c5d5830af29f 100644 (file)
--- a/sysfs.c
+++ b/sysfs.c
@@ -238,14 +238,33 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options)
                dev = malloc(sizeof(*dev));
                if (!dev)
                        goto abort;
-               dev->next = sra->devs;
-               sra->devs = dev;
-               strcpy(dev->sys_name, de->d_name);
 
                /* Always get slot, major, minor */
                strcpy(dbase, "slot");
-               if (load_sys(fname, buf))
-                       goto abort;
+               if (load_sys(fname, buf)) {
+                       /* hmm... unable to read 'slot' maybe the device
+                        * is going away?
+                        */
+                       strcpy(dbase, "block");
+                       if (readlink(fname, buf, sizeof(buf)) < 0 &&
+                           errno != ENAMETOOLONG) {
+                               /* ...yup device is gone */
+                               free(dev);
+                               continue;
+                       } else {
+                               /* slot is unreadable but 'block' link
+                                * still intact... something bad is happening
+                                * so abort
+                                */
+                               free(dev);
+                               goto abort;
+                       }
+                       
+               }
+               dev->next = sra->devs;
+               sra->devs = dev;
+
+               strcpy(dev->sys_name, de->d_name);
                dev->disk.raid_disk = strtoul(buf, &ep, 10);
                if (*ep) dev->disk.raid_disk = -1;