svn commit: r325272 - head/sys/geom

Andriy Gapon avg at FreeBSD.org
Wed Nov 1 10:53:12 UTC 2017


Author: avg
Date: Wed Nov  1 10:53:10 2017
New Revision: 325272
URL: https://svnweb.freebsd.org/changeset/base/325272

Log:
  geom_slice: fix r325227, protect against multiple calls to g_slice_free
  
  This geom does not immediately detach its consumer relying on the
  wither-washer to do that.  Since that happens asynchronously we may get
  additional spoiling events.  So, we need to account for that.
  
  There are multiple options for fixing this issue like detaching
  immediately or checking for G_CF_ORPHAN in g_slice_spoiled().
  The most reliable and least intrusive fix seems to be setting
  geom->softc to NULL on the first call and checking for NULL on
  subsequent calls.  This is something that the code did before r325227.
  
  Reported by:	David Wolfskill <david at catwhisker.org>,
  		O. Hartmann <o.hartmann at walstatt.org>
  Tested by:	David Wolfskill <david at catwhisker.org> (earlier version)
  Discussed with:	mav
  MFC after:	1 week
  X-MFC with:	r325227

Modified:
  head/sys/geom/geom_slice.c

Modified: head/sys/geom/geom_slice.c
==============================================================================
--- head/sys/geom/geom_slice.c	Wed Nov  1 10:49:41 2017	(r325271)
+++ head/sys/geom/geom_slice.c	Wed Nov  1 10:53:10 2017	(r325272)
@@ -71,10 +71,19 @@ g_slice_alloc(unsigned nslice, unsigned scsize)
 }
 
 static void
-g_slice_free(struct g_slicer *gsp)
+g_slice_free(struct g_geom *gp)
 {
+	struct g_slicer *gsp;
 
-	if (gsp == NULL)	/* XXX: phk thinks about this */
+	gsp = gp->softc;
+	gp->softc = NULL;
+
+	/*
+	 * We can get multiple spoiled events before wither-washer
+	 * detaches our consumer, so this can get called multiple
+	 * times.
+	 */
+	if (gsp == NULL)
 		return;
 	g_free(gsp->slices);
 	if (gsp->hotspot != NULL)
@@ -133,7 +142,7 @@ g_slice_access(struct g_provider *pp, int dr, int dw, 
 	 */
 	if (error == 0 && (gp->flags & G_GEOM_WITHER) != 0 &&
 	    (cp->acr + cp->acw + cp->ace) == 0)
-		g_slice_free(gsp);
+		g_slice_free(gp);
 
 	return (error);
 }
@@ -492,7 +501,7 @@ g_slice_orphan(struct g_consumer *cp)
 	 * otherwise g_slice_access() will do that after the last close.
 	 */
 	if ((cp->acr + cp->acw + cp->ace) == 0)
-		g_slice_free(gp->softc);
+		g_slice_free(gp);
 }
 
 void


More information about the svn-src-head mailing list