diff options
author | jh <jh@FreeBSD.org> | 2010-05-10 19:12:23 +0000 |
---|---|---|
committer | jh <jh@FreeBSD.org> | 2010-05-10 19:12:23 +0000 |
commit | e34ccbdd5795e4eeb93ec23a598ccb9342d9612a (patch) | |
tree | d0399c83b28e2e031a8d8a40aece04c54e605b56 /sys/geom | |
parent | a27d539c9ac7b17319630c5b530429562f22145c (diff) | |
download | FreeBSD-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.c | 9 | ||||
-rw-r--r-- | sys/geom/vinum/geom_vinum.h | 1 | ||||
-rw-r--r-- | sys/geom/vinum/geom_vinum_events.c | 14 | ||||
-rw-r--r-- | sys/geom/vinum/geom_vinum_var.h | 1 |
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 |