--- md.c.orig Mon Jan 12 11:52:00 2004 +++ md.c Sat Jan 24 23:56:25 2004 @@ -108,6 +108,8 @@ static u_char end_mfs_root[] __unused = #endif static g_init_t md_drvinit; +static g_fini_t md_drvfini; +static g_ctl_destroy_geom_t md_destroy_geom; static int mdrootready; static int mdunits; @@ -120,6 +122,12 @@ static struct cdevsw mdctl_cdevsw = { .d_name = MD_NAME, }; +struct g_class g_md_class = { + .name = "MD", + .init = md_drvinit, + .fini = md_drvfini, + .destroy_geom = md_destroy_geom, +}; static LIST_HEAD(, md_s) md_softc_list = LIST_HEAD_INITIALIZER(&md_softc_list); @@ -168,7 +176,12 @@ struct md_s { vm_object_t object; }; -static int mddestroy(struct md_s *sc, struct thread *td); +struct md_tmp { + int unit; + int error; +}; + +static void mddestroy(struct md_s *sc); static struct indir * new_indir(u_int shift) @@ -335,12 +348,6 @@ s_write(struct indir *ip, off_t offset, return (0); } - -struct g_class g_md_class = { - .name = "MD", - .init = md_drvinit, -}; - static int g_md_access(struct g_provider *pp, int r, int w, int e) { @@ -376,9 +383,6 @@ g_md_start(struct bio *bp) wakeup(sc); } -DECLARE_GEOM_CLASS(g_md_class, g_md); - - static int mdstart_malloc(struct md_s *sc, struct bio *bp) { @@ -812,7 +816,7 @@ mdcreate_malloc(struct md_ioctl *mdio) } } if (error) { - mddestroy(sc, NULL); + mddestroy(sc); return (error); } mdinit(sc); @@ -922,12 +926,12 @@ mdcreate_vnode(struct md_ioctl *mdio, st else sc->nsect = vattr.va_size / sc->secsize; /* XXX: round up ? */ if (sc->nsect == 0) { - mddestroy(sc, td); + mddestroy(sc); return (EINVAL); } error = mdsetcred(sc, td->td_ucred); if (error) { - mddestroy(sc, td); + mddestroy(sc); return (error); } mdinit(sc); @@ -935,15 +939,7 @@ mdcreate_vnode(struct md_ioctl *mdio, st } static void -md_zapit(void *p, int cancel) -{ - if (cancel) - return; - g_wither_geom(p, ENXIO); -} - -static int -mddestroy(struct md_s *sc, struct thread *td) +mddestroy(struct md_s *sc) { GIANT_REQUIRED; @@ -951,7 +947,7 @@ mddestroy(struct md_s *sc, struct thread mtx_destroy(&sc->queue_mtx); if (sc->gp) { sc->gp->softc = NULL; - g_waitfor_event(md_zapit, sc->gp, M_WAITOK, sc->gp, NULL); + g_wither_geom(sc->gp, ENXIO); sc->gp = NULL; sc->pp = NULL; } @@ -961,7 +957,7 @@ mddestroy(struct md_s *sc, struct thread tsleep(&sc->procp, PRIBIO, "mddestroy", hz / 10); if (sc->vnode != NULL) (void)vn_close(sc->vnode, sc->flags & MD_READONLY ? - FREAD : (FREAD|FWRITE), sc->cred, td); + FREAD : (FREAD|FWRITE), sc->cred, curthread); if (sc->cred != NULL) crfree(sc->cred); if (sc->object != NULL) { @@ -976,7 +972,6 @@ mddestroy(struct md_s *sc, struct thread LIST_REMOVE(sc, list); /* XXX: UNLOCK(unique unit numbers) */ free(sc, M_MD); - return (0); } static int @@ -1004,7 +999,7 @@ mdcreate_swap(struct md_ioctl *mdio, str */ if (mdio->md_size == 0) { - mddestroy(sc, td); + mddestroy(sc); return (EDOM); } @@ -1025,13 +1020,13 @@ mdcreate_swap(struct md_ioctl *mdio, str if (swap_pager_reserve(sc->object, 0, sc->nsect) < 0) { vm_object_deallocate(sc->object); sc->object = NULL; - mddestroy(sc, td); + mddestroy(sc); return (EDOM); } } error = mdsetcred(sc, td->td_ucred); if (error) { - mddestroy(sc, td); + mddestroy(sc); return (error); } mdinit(sc); @@ -1040,24 +1035,37 @@ mdcreate_swap(struct md_ioctl *mdio, str return (0); } -static int -mddetach(int unit, struct thread *td) +static void +mddetach(void *p, int cancel) { struct md_s *sc; + struct md_tmp *tmp; - sc = mdfind(unit); - if (sc == NULL) - return (ENOENT); - if (sc->opencount != 0 && !(sc->flags & MD_FORCE)) - return (EBUSY); + if (cancel != 0) + return; + tmp = p; + + sc = mdfind(tmp->unit); + if (sc == NULL) { + tmp->error = ENOENT; + return; + } + if (sc->opencount != 0 && !(sc->flags & MD_FORCE)) { + tmp->error = EBUSY; + return; + } switch(sc->type) { case MD_VNODE: case MD_SWAP: case MD_MALLOC: case MD_PRELOAD: - return (mddestroy(sc, td)); + tmp->error = 0; + mtx_lock(&Giant); + mddestroy(sc); + mtx_unlock(&Giant); + break; default: - return (EOPNOTSUPP); + tmp->error = EOPNOTSUPP; } } @@ -1096,13 +1104,24 @@ mdctlioctl(dev_t dev, u_long cmd, caddr_ default: return (EINVAL); } - case MDIOCDETACH: + case MDIOCDETACH: { + struct md_tmp *tmp; + int error; + if (mdio->md_version != MDIOVERSION) return (EINVAL); if (mdio->md_file != NULL || mdio->md_size != 0 || mdio->md_options != 0) return (EINVAL); - return (mddetach(mdio->md_unit, td)); + + tmp = malloc(sizeof(*tmp), M_TEMP, M_WAITOK | M_ZERO); + tmp->unit = mdio->md_unit; + g_waitfor_event(mddetach, tmp, M_WAITOK, tmp, NULL); + error = tmp->error; + free(tmp, M_TEMP); + + return (error); + } case MDIOCQUERY: if (mdio->md_version != MDIOVERSION) return (EINVAL); @@ -1199,37 +1218,35 @@ md_drvinit(struct g_class *mp __unused) g_topology_lock(); } +static void +md_drvfini(struct g_class *mp __unused) +{ + + KASSERT(LIST_EMPTY(&md_softc_list), ("device list isn't empty")); + + if (status_dev) + destroy_dev(status_dev); + status_dev = 0; +} + static int -md_modevent(module_t mod, int type, void *data) +md_destroy_geom(struct gctl_req *req __unused, struct g_class *mp __unused, + struct g_geom *gp) { - int error; struct md_s *sc; + struct md_tmp tmp; - switch (type) { - case MOD_LOAD: - break; - case MOD_UNLOAD: - LIST_FOREACH(sc, &md_softc_list, list) { - error = mddetach(sc->unit, curthread); - if (error != 0) - return (error); - } - if (status_dev) - destroy_dev(status_dev); - status_dev = 0; - break; - default: - break; - } - return (0); + g_topology_assert(); + sc = gp->softc; + + tmp.unit = sc->unit; + tmp.error = 0; + mddetach(&tmp, 0); + + return (tmp.error); } -static moduledata_t md_mod = { - MD_NAME, - md_modevent, - NULL -}; -DECLARE_MODULE(md, md_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); +DECLARE_GEOM_CLASS(g_md_class, md); MODULE_VERSION(md, MD_MODVER);