Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Nov 2011 23:12:23 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r227009 - head/sys/geom
Message-ID:  <201111012312.pA1NCNuY089112@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Nov  1 23:12:22 2011
New Revision: 227009
URL: http://svn.freebsd.org/changeset/base/227009

Log:
  Make orphan() method in geom_dev asynchronous using destroy_dev_sched_cb()
  instead of destroy_dev(). It moves device destruction waiting out of the
  topology lock and so fixes dead lock between orphanization and closing.
  Real provider and geom destruction called from swi context after device
  destroyed as callback of the destroy_dev_sched_cb().

Modified:
  head/sys/geom/geom_dev.c

Modified: head/sys/geom/geom_dev.c
==============================================================================
--- head/sys/geom/geom_dev.c	Tue Nov  1 22:22:46 2011	(r227008)
+++ head/sys/geom/geom_dev.c	Tue Nov  1 23:12:22 2011	(r227009)
@@ -506,6 +506,32 @@ g_dev_strategy(struct bio *bp)
  */
 
 static void
+g_dev_cleanup(void *arg)
+{
+	struct g_geom *gp;
+	struct g_consumer *cp;
+
+	mtx_unlock(&Giant);
+	cp = arg;
+	gp = cp->geom;
+	g_trace(G_T_TOPOLOGY, "g_dev_cleanup(%p(%s))", cp, cp->provider->name);
+
+	/* Wait for the cows to come home */
+	while (cp->nstart != cp->nend)
+		pause("gdevcleanup", hz / 10);
+
+	g_topology_lock();
+	if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
+		g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+
+	g_detach(cp);
+	g_destroy_consumer(cp);
+	g_destroy_geom(gp);
+	g_topology_unlock();
+	mtx_lock(&Giant);
+}
+
+static void
 g_dev_orphan(struct g_consumer *cp)
 {
 	struct g_geom *gp;
@@ -521,18 +547,7 @@ g_dev_orphan(struct g_consumer *cp)
 		set_dumper(NULL);
 
 	/* Destroy the struct cdev *so we get no more requests */
-	destroy_dev(dev);
-
-	/* Wait for the cows to come home */
-	while (cp->nstart != cp->nend)
-		pause("gdevorphan", hz / 10);
-
-	if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
-		g_access(cp, -cp->acr, -cp->acw, -cp->ace);
-
-	g_detach(cp);
-	g_destroy_consumer(cp);
-	g_destroy_geom(gp);
+	destroy_dev_sched_cb(dev, g_dev_cleanup, cp);
 }
 
 DECLARE_GEOM_CLASS(g_dev_class, g_dev);



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