diff --git a/multipath-tools-check-vector-defines b/multipath-tools-check-vector-defines new file mode 100644 index 0000000..fc767f9 --- /dev/null +++ b/multipath-tools-check-vector-defines @@ -0,0 +1,30 @@ +commit 03b42661495abdb9fa594ff82105f705d2c4148f +Author: Hannes Reinecke +Date: Mon Jan 26 13:01:33 2009 +0100 + + Error checking for VECTOR_XXX defines + + Christophe doesn't believe in error checking. I, however, have + been tripping over them all the time. + + References: bnc#469269 + + Signed-off-by: Hannes Reinecke + +diff --git a/libmultipath/vector.h b/libmultipath/vector.h +index aa9e134..59cfd27 100644 +--- a/libmultipath/vector.h ++++ b/libmultipath/vector.h +@@ -31,9 +31,9 @@ struct _vector { + typedef struct _vector *vector; + + #define VECTOR_DEFAULT_SIZE 1 +-#define VECTOR_SLOT(V,E) ((V)->slot[(E)]) +-#define VECTOR_SIZE(V) ((V)->allocated) +-#define VECTOR_LAST_SLOT(V) ((V)->slot[((V)->allocated - 1)]) ++#define VECTOR_SLOT(V,E) (((V) && (E) < (V)->allocated) ? (V)->slot[(E)] : NULL) ++#define VECTOR_SIZE(V) ((V) ? (V)->allocated : 0) ++#define VECTOR_LAST_SLOT(V) (((V) && (V)->allocated) ? (V)->slot[((V)->allocated - 1)] : NULL) + + #define vector_foreach_slot(v,p,i) \ + for (i = 0; (v) && i < (v)->allocated && ((p) = (v)->slot[i]); i++) diff --git a/multipath-tools-dont-access-blocked-devices-in-checkerloop b/multipath-tools-dont-access-blocked-devices-in-checkerloop new file mode 100644 index 0000000..9fb795c --- /dev/null +++ b/multipath-tools-dont-access-blocked-devices-in-checkerloop @@ -0,0 +1,146 @@ +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; diff --git a/multipath-tools.changes b/multipath-tools.changes index 790df3b..9d0e0ff 100644 --- a/multipath-tools.changes +++ b/multipath-tools.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Jan 26 14:17:57 CET 2009 - hare@suse.de + +- Don't access blocked devices in checkerloop() +- Check for validity in VECTOR_XXX defines (bnc#469269,bnc#457465) + ------------------------------------------------------------------- Fri Jan 23 14:15:18 CET 2009 - hare@suse.de diff --git a/multipath-tools.spec b/multipath-tools.spec index 749fc36..8b0e88a 100644 --- a/multipath-tools.spec +++ b/multipath-tools.spec @@ -27,7 +27,7 @@ Requires: device-mapper kpartx PreReq: %insserv_prereq %fillup_prereq coreutils grep diffutils AutoReqProv: on Version: 0.4.8 -Release: 30 +Release: 33 Summary: Tools to Manage Multipathed Devices with the device-mapper Source: multipath-tools-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -93,6 +93,8 @@ Patch58: %{name}-quote-variable-in-mkinitrd-setup Patch59: %{name}-update-dev_loss_tmo-handling Patch60: %{name}-fix-directio-error-messages Patch61: %{name}-update-sdev_state-handling +Patch62: %{name}-check-vector-defines +Patch63: %{name}-dont-access-blocked-devices-in-checkerloop %description This package provides the tools to manage multipathed devices by @@ -195,6 +197,8 @@ Authors: %patch59 -p1 %patch60 -p1 %patch61 -p1 +%patch62 -p1 +%patch63 -p1 %build make OPTFLAGS="$RPM_OPT_FLAGS" @@ -256,6 +260,9 @@ exit 0 %{_mandir}/man8/kpartx.8* %changelog +* Mon Jan 26 2009 hare@suse.de +- Don't access blocked devices in checkerloop() +- Check for validity in VECTOR_XXX defines (bnc#469269,bnc#457465) * Fri Jan 23 2009 hare@suse.de - Update dev_loss_tmo handling (bnc#458393) - Fix directio error messages