Prevent g_access calls to bad multipath members
When a multipath member is orphaned its access members are zeroed before its removed if marked for wither, so prevent any future calls to g_access on such members. This prevents a panic on debug kernels which validates the resultant values aren't negative. Reviewed by: mav MFC after: 2 weeks Sponsored by: Multiplay Differential Revision: https://reviews.freebsd.org/D4416
This commit is contained in:
parent
c7006ec555
commit
25080ac4d4
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user