Update path_offline() to return device status
authorHannes Reinecke <hare@suse.de>
Wed, 3 Feb 2010 13:22:22 +0000 (14:22 +0100)
committerChristophe Varoqui <christophe.varoqui@free.fr>
Wed, 3 Feb 2010 14:29:57 +0000 (15:29 +0100)
A SCSI device can have for more states than just 'offline' and
'running'. In fact, any device _not_ in state 'running' is
unaccessible to I/O, so running a path checker on these devices
will cause the checker to be delayed and hence stall the entire
daemon.

This patch updates the path_offline() function to return the
actual device state. Path checkers will only be run if the
state is PATH_UP. A 'blocked' device state will be translated
into PATH_PENDING, causing the checkerloop to skip this device
and recheck as soon as possible.

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

index 98d1618..6b99d07 100644 (file)
@@ -587,7 +587,7 @@ path_offline (struct path * pp)
        pp->sysdev = sysfs_device_from_path(pp);
        if (!pp->sysdev) {
                condlog(1, "%s: failed to get sysfs information", pp->dev);
-               return 1;
+               return PATH_WILD;
        }
 
        parent = sysfs_device_get_parent(pp->sysdev);
@@ -597,20 +597,25 @@ path_offline (struct path * pp)
                parent = sysfs_device_get_parent(parent);
        if (!parent) {
                condlog(1, "%s: failed to get parent", pp->dev);
-               return 1;
+               return PATH_WILD;
        }
 
        if (sysfs_get_state(parent, buff, SCSI_STATE_SIZE))
-               return 1;
+               return PATH_WILD;
 
        condlog(3, "%s: state = %s", pp->dev, buff);
 
        if (!strncmp(buff, "offline", 7)) {
                pp->offline = 1;
-               return 1;
+               return PATH_DOWN;
        }
        pp->offline = 0;
-       return 0;
+       if (!strncmp(buff, "blocked", 7))
+               return PATH_PENDING;
+       else if (!strncmp(buff, "running", 7))
+               return PATH_UP;
+
+       return PATH_DOWN;
 }
 
 extern int
@@ -703,6 +708,7 @@ static int
 get_state (struct path * pp)
 {
        struct checker * c = &pp->checker;
+       int sysfs_state;
 
        condlog(3, "%s: get_state", pp->dev);
 
@@ -718,9 +724,10 @@ get_state (struct path * pp)
                        return 1;
                }
        }
-       if (path_offline(pp)) {
-               condlog(3, "%s: path offline", pp->dev);
-               pp->state = PATH_DOWN;
+       sysfs_state = path_offline(pp);
+       if (sysfs_state != PATH_UP) {
+               condlog(3, "%s: path inaccessible", pp->dev);
+               pp->state = sysfs_state;
                return 0;
        }
        pp->state = checker_check(c);
index e875d14..e7955bd 100644 (file)
@@ -948,9 +948,8 @@ check_path (struct vectors * vecs, struct path * pp)
         */
        checker_set_async(&pp->checker);
 
-       if (path_offline(pp))
-               newstate = PATH_DOWN;
-       else
+       newstate = path_offline(pp);
+       if (newstate == PATH_UP)
                newstate = checker_check(&pp->checker);
 
        if (newstate < 0) {