summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorjh <jh@FreeBSD.org>2010-05-10 19:12:23 +0000
committerjh <jh@FreeBSD.org>2010-05-10 19:12:23 +0000
commite34ccbdd5795e4eeb93ec23a598ccb9342d9612a (patch)
treed0399c83b28e2e031a8d8a40aece04c54e605b56 /sys/geom
parenta27d539c9ac7b17319630c5b530429562f22145c (diff)
downloadFreeBSD-src-e34ccbdd5795e4eeb93ec23a598ccb9342d9612a.zip
FreeBSD-src-e34ccbdd5795e4eeb93ec23a598ccb9342d9612a.tar.gz
- Don't return EAGAIN from gv_unload(). It was used to work around the
deadlock fixed in r207671. - Wait for worker process to exit at class unload. The worker process was not guaranteed to exit before the linker unloaded the module. - Use 0 as the worker process exit status instead of ENXIO and style the NOTREACHED comment. Reviewed by: lulf X-MFC after: r207671
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/vinum/geom_vinum.c9
-rw-r--r--sys/geom/vinum/geom_vinum.h1
-rw-r--r--sys/geom/vinum/geom_vinum_events.c14
-rw-r--r--sys/geom/vinum/geom_vinum_var.h1
4 files changed, 20 insertions, 5 deletions
diff --git a/sys/geom/vinum/geom_vinum.c b/sys/geom/vinum/geom_vinum.c
index 479fc8a..107b80d 100644
--- a/sys/geom/vinum/geom_vinum.c
+++ b/sys/geom/vinum/geom_vinum.c
@@ -186,7 +186,7 @@ gv_init(struct g_class *mp)
mtx_init(&sc->config_mtx, "gv_config", NULL, MTX_DEF);
mtx_init(&sc->equeue_mtx, "gv_equeue", NULL, MTX_DEF);
mtx_init(&sc->bqueue_mtx, "gv_bqueue", NULL, MTX_DEF);
- kproc_create(gv_worker, sc, NULL, 0, 0, "gv_worker");
+ kproc_create(gv_worker, sc, &sc->worker, 0, 0, "gv_worker");
}
static int
@@ -200,10 +200,9 @@ gv_unload(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
sc = gp->softc;
if (sc != NULL) {
- gv_post_event(sc, GV_EVENT_THREAD_EXIT, NULL, NULL, 0, 0);
+ gv_worker_exit(sc);
gp->softc = NULL;
g_wither_geom(gp, ENXIO);
- return (EAGAIN);
}
return (0);
@@ -984,8 +983,8 @@ gv_worker(void *arg)
g_free(sc->bqueue_down);
g_free(sc->bqueue_up);
g_free(sc);
- kproc_exit(ENXIO);
- break; /* not reached */
+ kproc_exit(0);
+ /* NOTREACHED */
default:
G_VINUM_DEBUG(1, "unknown event %d", ev->type);
diff --git a/sys/geom/vinum/geom_vinum.h b/sys/geom/vinum/geom_vinum.h
index 6381b5f..f40d726 100644
--- a/sys/geom/vinum/geom_vinum.h
+++ b/sys/geom/vinum/geom_vinum.h
@@ -122,6 +122,7 @@ int gv_detach_sd(struct gv_sd *, int);
void gv_worker(void *);
void gv_post_event(struct gv_softc *, int, void *, void *, intmax_t,
intmax_t);
+void gv_worker_exit(struct gv_softc *);
struct gv_event *gv_get_event(struct gv_softc *);
void gv_remove_event(struct gv_softc *, struct gv_event *);
void gv_drive_tasted(struct gv_softc *, struct g_provider *);
diff --git a/sys/geom/vinum/geom_vinum_events.c b/sys/geom/vinum/geom_vinum_events.c
index 02c14ce..fcd45f1 100644
--- a/sys/geom/vinum/geom_vinum_events.c
+++ b/sys/geom/vinum/geom_vinum_events.c
@@ -58,6 +58,20 @@ gv_post_event(struct gv_softc *sc, int event, void *arg1, void *arg2,
mtx_unlock(&sc->equeue_mtx);
}
+void
+gv_worker_exit(struct gv_softc *sc)
+{
+ struct gv_event *ev;
+
+ ev = g_malloc(sizeof(*ev), M_WAITOK | M_ZERO);
+ ev->type = GV_EVENT_THREAD_EXIT;
+
+ mtx_lock(&sc->equeue_mtx);
+ TAILQ_INSERT_TAIL(&sc->equeue, ev, events);
+ wakeup(sc);
+ msleep(sc->worker, &sc->equeue_mtx, PDROP, "gv_wor", 0);
+}
+
struct gv_event *
gv_get_event(struct gv_softc *sc)
{
diff --git a/sys/geom/vinum/geom_vinum_var.h b/sys/geom/vinum/geom_vinum_var.h
index eac3c2c..350661c 100644
--- a/sys/geom/vinum/geom_vinum_var.h
+++ b/sys/geom/vinum/geom_vinum_var.h
@@ -238,6 +238,7 @@ struct gv_softc {
struct bio_queue_head *bqueue_up; /* BIO queue for completed
requests. */
struct g_geom *geom; /* Pointer to our VINUM geom. */
+ struct proc *worker; /* Worker process. */
};
#endif
OpenPOWER on IntegriCloud