From 3e280f14c271d1275ab6123b38cd1ff828d47fcf Mon Sep 17 00:00:00 2001 From: smh Date: Mon, 25 Jan 2016 09:29:29 +0000 Subject: [PATCH] MFC r292289: Prevent g_access calls to bad multipath members Sponsored by: Multiplay git-svn-id: svn://svn.freebsd.org/base/stable/10@294709 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/geom/multipath/g_multipath.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c index 0953d1881..6644532d0 100644 --- a/sys/geom/multipath/g_multipath.c +++ b/sys/geom/multipath/g_multipath.c @@ -107,8 +107,9 @@ struct g_class g_multipath_class = { #define MP_NEW 0x00000004 #define MP_POSTED 0x00000008 #define MP_BAD (MP_FAIL | MP_LOST | MP_NEW) -#define MP_IDLE 0x00000010 -#define MP_IDLE_MASK 0xfffffff0 +#define MP_WITHER 0x00000010 +#define MP_IDLE 0x00000020 +#define MP_IDLE_MASK 0xffffffe0 static int g_multipath_good(struct g_geom *gp) @@ -204,6 +205,7 @@ g_mpd(void *arg, int flags __unused) g_access(cp, -cp->acr, -cp->acw, -cp->ace); if (w > 0 && cp->provider != NULL && (cp->provider->geom->flags & G_GEOM_WITHER) == 0) { + cp->index |= MP_WITHER; g_post_event(g_mpd, cp, M_WAITOK, NULL); return; } @@ -467,23 +469,37 @@ g_multipath_access(struct g_provider *pp, int dr, int dw, int de) gp = pp->geom; + /* Error used if we have no valid consumers. */ + error = ENXIO; + LIST_FOREACH(cp, &gp->consumer, consumer) { + if (cp->index & MP_WITHER) + continue; + error = g_access(cp, dr, dw, de); if (error) { badcp = cp; goto fail; } } + + if (error != 0) + return (error); + sc = gp->softc; sc->sc_opened += dr + dw + de; if (sc->sc_stopping && sc->sc_opened == 0) g_multipath_destroy(gp); + return (0); fail: LIST_FOREACH(cp, &gp->consumer, consumer) { if (cp == badcp) break; + if (cp->index & MP_WITHER) + continue; + (void) g_access(cp, -dr, -dw, -de); } return (error); -- 2.45.0