Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Oct 2016 08:48:59 +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-11@freebsd.org
Subject:   svn commit: r307665 - stable/11/sys/geom/mirror
Message-ID:  <201610200848.u9K8mxbx008081@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Thu Oct 20 08:48:58 2016
New Revision: 307665
URL: https://svnweb.freebsd.org/changeset/base/307665

Log:
  MFC r306762: Fix possible geom destruction before final provider close.
  
  Introduce internal counter to track opens.  Using provider's counters is
  not very successfull after calling g_wither_provider().

Modified:
  stable/11/sys/geom/mirror/g_mirror.c
  stable/11/sys/geom/mirror/g_mirror.h
  stable/11/sys/geom/mirror/g_mirror_ctl.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/geom/mirror/g_mirror.c
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror.c	Thu Oct 20 02:03:19 2016	(r307664)
+++ stable/11/sys/geom/mirror/g_mirror.c	Thu Oct 20 08:48:58 2016	(r307665)
@@ -2137,10 +2137,9 @@ g_mirror_destroy_provider(struct g_mirro
 		}
 	}
 	mtx_unlock(&sc->sc_queue_mtx);
-	G_MIRROR_DEBUG(0, "Device %s: provider %s destroyed.", sc->sc_name,
-	    sc->sc_provider->name);
 	g_wither_provider(sc->sc_provider, ENXIO);
 	sc->sc_provider = NULL;
+	G_MIRROR_DEBUG(0, "Device %s: provider destroyed.", sc->sc_name);
 	g_topology_unlock();
 	LIST_FOREACH(disk, &sc->sc_disks, d_next) {
 		if (disk->d_state == G_MIRROR_DISK_STATE_SYNCHRONIZING)
@@ -2866,7 +2865,7 @@ static int
 g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
 {
 	struct g_mirror_softc *sc;
-	int dcr, dcw, dce, error = 0;
+	int error = 0;
 
 	g_topology_assert();
 	G_MIRROR_DEBUG(2, "Access request for %s: r%dw%de%d.", pp->name, acr,
@@ -2877,30 +2876,21 @@ g_mirror_access(struct g_provider *pp, i
 		return (0);
 	KASSERT(sc != NULL, ("NULL softc (provider=%s).", pp->name));
 
-	dcr = pp->acr + acr;
-	dcw = pp->acw + acw;
-	dce = pp->ace + ace;
-
 	g_topology_unlock();
 	sx_xlock(&sc->sc_lock);
 	if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROY) != 0 ||
+	    (sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 ||
 	    LIST_EMPTY(&sc->sc_disks)) {
 		if (acr > 0 || acw > 0 || ace > 0)
 			error = ENXIO;
 		goto end;
 	}
-	if (dcw == 0)
-		g_mirror_idle(sc, dcw);
-	if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0) {
-		if (acr > 0 || acw > 0 || ace > 0) {
-			error = ENXIO;
-			goto end;
-		}
-		if (dcr == 0 && dcw == 0 && dce == 0) {
-			g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK,
-			    sc, NULL);
-		}
-	}
+	sc->sc_provider_open += acr + acw + ace;
+	if (pp->acw + acw == 0)
+		g_mirror_idle(sc, 0);
+	if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0 &&
+	    sc->sc_provider_open == 0)
+		g_post_event(g_mirror_destroy_delayed, sc, M_WAITOK, sc, NULL);
 end:
 	sx_xunlock(&sc->sc_lock);
 	g_topology_lock();
@@ -2957,6 +2947,7 @@ g_mirror_create(struct g_class *mp, cons
 	gp->softc = sc;
 	sc->sc_geom = gp;
 	sc->sc_provider = NULL;
+	sc->sc_provider_open = 0;
 	/*
 	 * Synchronization geom.
 	 */
@@ -2997,26 +2988,23 @@ int
 g_mirror_destroy(struct g_mirror_softc *sc, int how)
 {
 	struct g_mirror_disk *disk;
-	struct g_provider *pp;
 
 	g_topology_assert_not();
 	if (sc == NULL)
 		return (ENXIO);
 	sx_assert(&sc->sc_lock, SX_XLOCKED);
 
-	pp = sc->sc_provider;
-	if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0 ||
-	    SCHEDULER_STOPPED())) {
+	if (sc->sc_provider_open != 0 || SCHEDULER_STOPPED()) {
 		switch (how) {
 		case G_MIRROR_DESTROY_SOFT:
 			G_MIRROR_DEBUG(1,
-			    "Device %s is still open (r%dw%de%d).", pp->name,
-			    pp->acr, pp->acw, pp->ace);
+			    "Device %s is still open (%d).", sc->sc_name,
+			    sc->sc_provider_open);
 			return (EBUSY);
 		case G_MIRROR_DESTROY_DELAYED:
 			G_MIRROR_DEBUG(1,
 			    "Device %s will be destroyed on last close.",
-			    pp->name);
+			    sc->sc_name);
 			LIST_FOREACH(disk, &sc->sc_disks, d_next) {
 				if (disk->d_state ==
 				    G_MIRROR_DISK_STATE_SYNCHRONIZING) {
@@ -3027,7 +3015,7 @@ g_mirror_destroy(struct g_mirror_softc *
 			return (EBUSY);
 		case G_MIRROR_DESTROY_HARD:
 			G_MIRROR_DEBUG(1, "Device %s is still open, so it "
-			    "can't be definitely removed.", pp->name);
+			    "can't be definitely removed.", sc->sc_name);
 		}
 	}
 

Modified: stable/11/sys/geom/mirror/g_mirror.h
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror.h	Thu Oct 20 02:03:19 2016	(r307664)
+++ stable/11/sys/geom/mirror/g_mirror.h	Thu Oct 20 08:48:58 2016	(r307665)
@@ -179,6 +179,7 @@ struct g_mirror_softc {
 
 	struct g_geom	*sc_geom;
 	struct g_provider *sc_provider;
+	int		sc_provider_open;
 
 	uint32_t	sc_id;		/* Mirror unique ID. */
 

Modified: stable/11/sys/geom/mirror/g_mirror_ctl.c
==============================================================================
--- stable/11/sys/geom/mirror/g_mirror_ctl.c	Thu Oct 20 02:03:19 2016	(r307664)
+++ stable/11/sys/geom/mirror/g_mirror_ctl.c	Thu Oct 20 08:48:58 2016	(r307665)
@@ -658,8 +658,7 @@ g_mirror_ctl_resize(struct gctl_req *req
 		return;
 	}
 	/* Deny shrinking of an opened provider */
-	if ((g_debugflags & 16) == 0 && (sc->sc_provider->acr > 0 ||
-	    sc->sc_provider->acw > 0 || sc->sc_provider->ace > 0)) {
+	if ((g_debugflags & 16) == 0 && sc->sc_provider_open > 0) {
 		if (sc->sc_mediasize > mediasize) {
 			gctl_error(req, "Device %s is busy.",
 			    sc->sc_provider->name);



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