Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Jan 2020 00:45:28 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r356582 - stable/12/sys/geom/shsec
Message-ID:  <202001100045.00A0jS3g017025@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Fri Jan 10 00:45:27 2020
New Revision: 356582
URL: https://svnweb.freebsd.org/changeset/base/356582

Log:
  MFC r356162, r356182: Fix GEOM_SHSEC orphanization.
  
  Previous code closed and destroyed consumer even with I/O in progress.
  This patch postpones the destruction till the last close, identical to
  GEOM_STRIPE, since they seem to have common origin.

Modified:
  stable/12/sys/geom/shsec/g_shsec.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/geom/shsec/g_shsec.c
==============================================================================
--- stable/12/sys/geom/shsec/g_shsec.c	Fri Jan 10 00:44:07 2020	(r356581)
+++ stable/12/sys/geom/shsec/g_shsec.c	Fri Jan 10 00:45:27 2020	(r356582)
@@ -164,7 +164,7 @@ g_shsec_remove_disk(struct g_consumer *cp)
 	}
 
 	if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
-		g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+		return;
 	g_detach(cp);
 	g_destroy_consumer(cp);
 }
@@ -183,14 +183,14 @@ g_shsec_orphan(struct g_consumer *cp)
 
 	g_shsec_remove_disk(cp);
 	/* If there are no valid disks anymore, remove device. */
-	if (g_shsec_nvalid(sc) == 0)
+	if (LIST_EMPTY(&gp->consumer))
 		g_shsec_destroy(sc, 1);
 }
 
 static int
 g_shsec_access(struct g_provider *pp, int dr, int dw, int de)
 {
-	struct g_consumer *cp1, *cp2;
+	struct g_consumer *cp1, *cp2, *tmp;
 	struct g_shsec_softc *sc;
 	struct g_geom *gp;
 	int error;
@@ -198,21 +198,6 @@ g_shsec_access(struct g_provider *pp, int dr, int dw, 
 	gp = pp->geom;
 	sc = gp->softc;
 
-	if (sc == NULL) {
-		/*
-		 * It looks like geom is being withered.
-		 * In that case we allow only negative requests.
-		 */
-		KASSERT(dr <= 0 && dw <= 0 && de <= 0,
-		    ("Positive access request (device=%s).", pp->name));
-		if ((pp->acr + dr) == 0 && (pp->acw + dw) == 0 &&
-		    (pp->ace + de) == 0) {
-			G_SHSEC_DEBUG(0, "Device %s definitely destroyed.",
-			    gp->name);
-		}
-		return (0);
-	}
-
 	/* On first open, grab an extra "exclusive" bit */
 	if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0)
 		de++;
@@ -221,21 +206,30 @@ g_shsec_access(struct g_provider *pp, int dr, int dw, 
 		de--;
 
 	error = ENXIO;
-	LIST_FOREACH(cp1, &gp->consumer, consumer) {
+	LIST_FOREACH_SAFE(cp1, &gp->consumer, consumer, tmp) {
 		error = g_access(cp1, dr, dw, de);
-		if (error == 0)
-			continue;
-		/*
-		 * If we fail here, backout all previous changes.
-		 */
-		LIST_FOREACH(cp2, &gp->consumer, consumer) {
-			if (cp1 == cp2)
-				return (error);
-			g_access(cp2, -dr, -dw, -de);
+		if (error != 0)
+			goto fail;
+		if (cp1->acr == 0 && cp1->acw == 0 && cp1->ace == 0 &&
+		    cp1->flags & G_CF_ORPHAN) {
+			g_detach(cp1);
+			g_destroy_consumer(cp1);
 		}
-		/* NOTREACHED */
 	}
 
+	/* If there are no valid disks anymore, remove device. */
+	if (LIST_EMPTY(&gp->consumer))
+		g_shsec_destroy(sc, 1);
+
+	return (error);
+
+fail:
+	/* If we fail here, backout all previous changes. */
+	LIST_FOREACH(cp2, &gp->consumer, consumer) {
+		if (cp1 == cp2)
+			break;
+		g_access(cp2, -dr, -dw, -de);
+	}
 	return (error);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001100045.00A0jS3g017025>