svn commit: r292289 - head/sys/geom/multipath

Steven Hartland smh at FreeBSD.org
Tue Dec 15 21:11:42 UTC 2015


Author: smh
Date: Tue Dec 15 21:11:41 2015
New Revision: 292289
URL: https://svnweb.freebsd.org/changeset/base/292289

Log:
  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

Modified:
  head/sys/geom/multipath/g_multipath.c

Modified: head/sys/geom/multipath/g_multipath.c
==============================================================================
--- head/sys/geom/multipath/g_multipath.c	Tue Dec 15 21:02:53 2015	(r292288)
+++ head/sys/geom/multipath/g_multipath.c	Tue Dec 15 21:11:41 2015	(r292289)
@@ -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
 
 	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);


More information about the svn-src-all mailing list