Index: head/sys/geom/multipath/g_multipath.c =================================================================== --- head/sys/geom/multipath/g_multipath.c +++ head/sys/geom/multipath/g_multipath.c @@ -107,8 +107,9 @@ #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_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 @@ 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);