summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-09-16 05:58:43 +0200
committerDan Williams <dan.j.williams@intel.com>2008-09-16 05:58:43 +0200
commit4795982e68f72ef44bd29c9883e5f6291088a3e1 (patch)
tree6a17d7ec939a5d2c922a28c6a26c55f4fa44b9f2
parentmonitor: clean up some debug messages (diff)
downloadmdadm-4795982e68f72ef44bd29c9883e5f6291088a3e1.tar.xz
mdadm-4795982e68f72ef44bd29c9883e5f6291088a3e1.zip
sysfs: detect disks that are in the process of being removed
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>
-rw-r--r--sysfs.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/sysfs.c b/sysfs.c
index 182028ce..9ef5b394 100644
--- 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;