summaryrefslogtreecommitdiffstats
path: root/sys/geom/multipath/g_multipath.c
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2016-01-25 08:56:15 -0200
committerRenato Botelho <renato@netgate.com>2016-01-25 08:56:15 -0200
commiteb84e0723f3b4bc5e40024f66fe21c14b09e9ec4 (patch)
treefec6b99d018e13f1fccbe31478aaf29a28a55642 /sys/geom/multipath/g_multipath.c
parentc50df8e1b90c4f9b8bbffa592477c129854776ce (diff)
parent94b1bbbd44bd88b6db1c00d795cdf7675b3ae254 (diff)
downloadFreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.zip
FreeBSD-src-eb84e0723f3b4bc5e40024f66fe21c14b09e9ec4.tar.gz
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/geom/multipath/g_multipath.c')
-rw-r--r--sys/geom/multipath/g_multipath.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
index 0953d18..6644532 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);
OpenPOWER on IntegriCloud