File multipath-tools-dont-access-blocked-devices-in-checkerloop of Package multipath-tools

commit 33a9016139228c492f5e95278c8ee77418c53efa
Author: Hannes Reinecke <hare@suse.de>
Date:   Mon Jan 26 13:50:28 2009 +0100

    Check for blocked devices in checkerloop()
    
    The checkerloop should also check for blocked devices; reducing
    multipathd stall even further.
    
    Signed-off-by: Hannes Reinecke <hare@suse.de>

diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 2e63cdf..b56899a 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -688,7 +688,7 @@ static int sysfs_get_sdev_state(struct path *pp)
 	if (!sysfs_get_state(parent, dev_state, 32)) {
 		if (!strncmp(dev_state, "blocked", 7)) {
 			condlog(3, "%s: device blocked", pp->dev);
-			return PATH_UNCHECKED;
+			return PATH_PENDING;
 		} else if (!strncmp(dev_state, "running", 7)) {
 			return PATH_UP;
 		}
@@ -792,40 +792,40 @@ cciss_ioctl_pathinfo (struct path * pp, int mask)
 	return 0;
 }
 
-static int
+int
 get_state (struct path * pp)
 {
 	struct checker * c = &pp->checker;
+	int state = PATH_UNCHECKED;
 
 	condlog(3, "%s: get_state", pp->dev);
 
 	if (pp->bus == SYSFS_BUS_SCSI && pp->sysdev) {
 		/* Check the sdev state before accessing it */
-		pp->state = sysfs_get_sdev_state(pp);
-		if (pp->state == PATH_UNCHECKED || pp->state == PATH_DOWN) {
+		state = sysfs_get_sdev_state(pp);
+		if (state == PATH_PENDING || state == PATH_DOWN) {
 			/* Further checking pointless */
-			pp->priority = 0;
-			return 0;
+			return state;
 		}
 	}
 	if (!checker_selected(c)) {
 		select_checker(pp);
 		if (!checker_selected(c)) {
 			condlog(3, "%s: No checker selected", pp->dev);
-			return 1;
+			return PATH_UNCHECKED;
 		}
 		checker_set_fd(c, pp->fd);
 		if (checker_init(c, pp->mpp?&pp->mpp->mpcontext:NULL)) {
 			condlog(3, "%s: checker init failed", pp->dev);
-			return 1;
+			return PATH_UNCHECKED;
 		}
 	}
-	pp->state = checker_check(c);
-	condlog(3, "%s: state = %i", pp->dev, pp->state);
-	if (pp->state == PATH_DOWN && strlen(checker_message(c)))
+	state = checker_check(c);
+	condlog(3, "%s: state = %i", pp->dev, state);
+	if (state == PATH_DOWN && strlen(checker_message(c)))
 		condlog(3, "%s: checker msg is \"%s\"",
 			pp->dev, checker_message(c));
-	return 0;
+	return state;
 }
 
 static int
@@ -839,7 +839,7 @@ get_prio (struct path * pp)
 	if (pp->bus == SYSFS_BUS_SCSI) {
 		/* Check the sdev state before accessing it */
 		path_state = sysfs_get_sdev_state(pp);
-		if (path_state == PATH_DOWN || path_state == PATH_UNCHECKED) {
+		if (path_state == PATH_DOWN || path_state == PATH_PENDING) {
 			pp->priority = PRIO_UNDEF;
 			return 0;
 		}
@@ -914,8 +914,11 @@ pathinfo (struct path *pp, vector hwtable, int mask)
 	    cciss_ioctl_pathinfo(pp, mask))
 		goto blank;
 
-	if (mask & DI_CHECKER && get_state(pp))
-		goto blank;
+	if (mask & DI_CHECKER) {
+		pp->state = get_state(pp);
+		if (pp->state == PATH_UNCHECKED || pp->state == PATH_WILD)
+			goto blank;
+	}
 
 	 /*
 	  * Retrieve path priority, even for PATH_DOWN paths if it has never
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
index 3749674..a460491 100644
--- a/libmultipath/discovery.h
+++ b/libmultipath/discovery.h
@@ -33,6 +33,7 @@ int pathinfo (struct path *, vector hwtable, int mask);
 struct path * store_pathinfo (vector pathvec, vector hwtable,
 			      char * devname, int flag);
 int sysfs_set_fc_values (struct path *pp, int dev_loss_tmo, int fast_io_fail_tmo);
+int get_state(struct path *pp);
 
 /*
  * discovery bitmask
diff --git a/multipathd/main.c b/multipathd/main.c
index 7bc0211..5456a6c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -116,6 +116,9 @@ coalesce_maps(struct vectors *vecs, vector nmpv)
 	unsigned int i;
 	int j;
 
+	if (!vecs)
+		return 0;
+
 	vector_foreach_slot (ompv, ompp, i) {
 		if (!find_mp_by_wwid(nmpv, ompp->wwid)) {
 			/*
@@ -942,16 +945,16 @@ check_path (struct vectors * vecs, struct path * pp)
 	 */
 	checker_set_async(&pp->checker);
 
-	newstate = checker_check(&pp->checker);
+	newstate = get_state(pp);
 
-	if (newstate < 0) {
+	if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) {
 		condlog(2, "%s: unusable path", pp->dev);
 		pathinfo(pp, conf->hwtable, 0);
 		return;
 	}
 	/*
-	 * Async IO in flight. Keep the previous path state
-	 * and reschedule as soon as possible
+	 * Async IO in flight or path blocked. Keep the previous
+	 * path state and reschedule as soon as possible
 	 */
 	if (newstate == PATH_PENDING) {
 		pp->tick = 1;
openSUSE Build Service is sponsored by