commit 33a9016139228c492f5e95278c8ee77418c53efa Author: Hannes Reinecke 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 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;