libmultipath: proactively remove path
authorHannes Reinecke <hare@suse.de>
Fri, 13 Dec 2013 12:12:41 +0000 (13:12 +0100)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Fri, 13 Dec 2013 21:39:21 +0000 (22:39 +0100)
When path_offline() detects a removed path we really do not need
to wait for any uevent to arrive, but can remove the path
straightaway.

Signed-off-by: Hannes Reinecke <hare@suse.de>
libmultipath/checkers.c
libmultipath/checkers.h
libmultipath/discovery.c
libmultipath/sysfs.c
multipathd/main.c

index 47f5c68..4a4cd7c 100644 (file)
@@ -18,6 +18,7 @@ char *checker_state_names[] = {
       "ghost",
       "pending",
       "timeout",
+      "removed",
 };
 
 static LIST_HEAD(checkers);
index 1b6c22d..e62b52f 100644 (file)
  * PATH_TIMEOUT:
  * - Use: Only tur checker
  * - Description: Command timed out
+ *
+ * PATH REMOVED:
+ * - Use: All checkers
+ * - Description: Device has been removed from the system
  */
 enum path_check_state {
        PATH_WILD,
@@ -60,6 +64,7 @@ enum path_check_state {
        PATH_GHOST,
        PATH_PENDING,
        PATH_TIMEOUT,
+       PATH_REMOVED,
        PATH_MAX_STATE
 };
 
index d519c02..ccd3b62 100644 (file)
@@ -839,6 +839,7 @@ path_offline (struct path * pp)
 {
        struct udev_device * parent;
        char buff[SCSI_STATE_SIZE];
+       int err;
 
        if (pp->bus != SYSFS_BUS_SCSI)
                return PATH_UP;
@@ -853,12 +854,18 @@ path_offline (struct path * pp)
 
        if (!parent) {
                condlog(1, "%s: failed to get sysfs information", pp->dev);
-               return PATH_DOWN;
+               return PATH_REMOVED;
        }
 
        memset(buff, 0x0, SCSI_STATE_SIZE);
-       if (sysfs_attr_get_value(parent, "state", buff, SCSI_STATE_SIZE) <= 0)
-               return PATH_DOWN;
+       err = sysfs_attr_get_value(parent, "state", buff, SCSI_STATE_SIZE);
+       if (err <= 0) {
+               if (err == -ENXIO)
+                       return PATH_REMOVED;
+               else
+                       return PATH_DOWN;
+       }
+
 
        condlog(3, "%s: path state = %s", pp->dev, buff);
 
@@ -1084,6 +1091,8 @@ pathinfo (struct path *pp, vector hwtable, int mask)
        }
 
        path_state = path_offline(pp);
+       if (path_state == PATH_REMOVED)
+               goto blank;
 
        /*
         * fetch info not available through sysfs
index 8ba27d4..e5834f9 100644 (file)
@@ -59,7 +59,7 @@ ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name,
        condlog(4, "open '%s'", devpath);
        if (stat(devpath, &statbuf) != 0) {
                condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
-               return -errno;
+               return -ENXIO;
        }
 
        /* skip directories */
index 309b1aa..a3547c5 100644 (file)
@@ -1125,6 +1125,11 @@ check_path (struct vectors * vecs, struct path * pp)
        pp->tick = conf->checkint;
 
        newstate = path_offline(pp);
+       if (newstate == PATH_REMOVED) {
+               condlog(2, "%s: remove path (checker)", pp->dev);
+               ev_remove_path(pp, vecs);
+               return;
+       }
        if (newstate == PATH_UP)
                newstate = get_state(pp, 1);
        else