summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2011-11-01 23:12:22 +0000
committermav <mav@FreeBSD.org>2011-11-01 23:12:22 +0000
commit98d097d322e20dc1dbe956e9512aeedaa90f876d (patch)
tree3d49920bd6adc2fbfeb87c165770673abba39737 /sys/geom
parent788539ae310aec644e882cf14828996f85dbcc7e (diff)
downloadFreeBSD-src-98d097d322e20dc1dbe956e9512aeedaa90f876d.zip
FreeBSD-src-98d097d322e20dc1dbe956e9512aeedaa90f876d.tar.gz
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().
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/geom_dev.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 210f2ee..fa2a89a 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -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);
OpenPOWER on IntegriCloud