Module Name: src Committed By: dyoung Date: Tue Jul 21 19:41:00 UTC 2009
Modified Files: src/sys/dev/dkwedge: dk.c Log Message: Extract a lot of code from dkwedge_del(), and move it to dkwedge_detach() to create a comprehensive detachment hook. Let that hook run at shutdown. Now, 'drvctl -d dk0' actually deletes a wedge if it is not in-use (otherwise fails w/ EBUSY), and wedges are gracefully detached from their "parent" at shutdown. To generate a diff of this commit: cvs rdiff -u -r1.46 -r1.47 src/sys/dev/dkwedge/dk.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/dkwedge/dk.c diff -u src/sys/dev/dkwedge/dk.c:1.46 src/sys/dev/dkwedge/dk.c:1.47 --- src/sys/dev/dkwedge/dk.c:1.46 Thu Jul 2 00:56:48 2009 +++ src/sys/dev/dkwedge/dk.c Tue Jul 21 19:41:00 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: dk.c,v 1.46 2009/07/02 00:56:48 dyoung Exp $ */ +/* $NetBSD: dk.c,v 1.47 2009/07/21 19:41:00 dyoung Exp $ */ /*- * Copyright (c) 2004, 2005, 2006, 2007 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.46 2009/07/02 00:56:48 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.47 2009/07/21 19:41:00 dyoung Exp $"); #include "opt_dkwedge.h" @@ -95,6 +95,7 @@ static void dkrestart(void *); static int dklastclose(struct dkwedge_softc *); +static int dkwedge_detach(device_t, int); static dev_type_open(dkopen); static dev_type_close(dkclose); @@ -149,23 +150,10 @@ aprint_error_dev(self, "couldn't establish power handler\n"); } -/* - * dkwedge_detach: - * - * Autoconfiguration detach function for pseudo-device glue. - */ -static int -dkwedge_detach(device_t self, int flags) -{ - - pmf_device_deregister(self); - /* Always succeeds. */ - return (0); -} - CFDRIVER_DECL(dk, DV_DISK, NULL); -CFATTACH_DECL_NEW(dk, 0, - dkwedge_match, dkwedge_attach, dkwedge_detach, NULL); +CFATTACH_DECL3_NEW(dk, 0, + dkwedge_match, dkwedge_attach, dkwedge_detach, NULL, NULL, NULL, + DVF_DETACH_SHUTDOWN); /* * dkwedge_wait_drain: @@ -423,36 +411,111 @@ } /* - * dkwedge_del: [exported function] + * dkwedge_find: * - * Delete a disk wedge based on the provided information. + * Lookup a disk wedge based on the provided information. * NOTE: We look up the wedge based on the wedge devname, * not wname. + * + * Return NULL if the wedge is not found, otherwise return + * the wedge's softc. Assign the wedge's unit number to unitp + * if unitp is not NULL. */ -int -dkwedge_del(struct dkwedge_info *dkw) +static struct dkwedge_softc * +dkwedge_find(struct dkwedge_info *dkw, u_int *unitp) { struct dkwedge_softc *sc = NULL; u_int unit; - int bmaj, cmaj, s; /* Find our softc. */ dkw->dkw_devname[sizeof(dkw->dkw_devname) - 1] = '\0'; - rw_enter(&dkwedges_lock, RW_WRITER); + rw_enter(&dkwedges_lock, RW_READER); for (unit = 0; unit < ndkwedges; unit++) { if ((sc = dkwedges[unit]) != NULL && strcmp(device_xname(sc->sc_dev), dkw->dkw_devname) == 0 && strcmp(sc->sc_parent->dk_name, dkw->dkw_parent) == 0) { - /* Mark the wedge as dying. */ - sc->sc_state = DKW_STATE_DYING; break; } } rw_exit(&dkwedges_lock); if (unit == ndkwedges) + return NULL; + + if (unitp != NULL) + *unitp = unit; + + return sc; +} + +/* + * dkwedge_del: [exported function] + * + * Delete a disk wedge based on the provided information. + * NOTE: We look up the wedge based on the wedge devname, + * not wname. + */ +int +dkwedge_del(struct dkwedge_info *dkw) +{ + struct dkwedge_softc *sc = NULL; + + /* Find our softc. */ + if ((sc = dkwedge_find(dkw, NULL)) == NULL) return (ESRCH); - KASSERT(sc != NULL); + return config_detach(sc->sc_dev, DETACH_FORCE | DETACH_QUIET); +} + +static int +dkwedge_begindetach(struct dkwedge_softc *sc, int flags) +{ + struct disk *dk = &sc->sc_dk; + int rc; + + rc = 0; + mutex_enter(&dk->dk_openlock); + mutex_enter(&sc->sc_parent->dk_rawlock); + if (dk->dk_openmask == 0) + ; /* nothing to do */ + else if ((flags & DETACH_FORCE) == 0) + rc = EBUSY; + else + rc = dklastclose(sc); + mutex_exit(&sc->sc_parent->dk_rawlock); + mutex_exit(&dk->dk_openlock); + + return rc; +} + +/* + * dkwedge_detach: + * + * Autoconfiguration detach function for pseudo-device glue. + */ +static int +dkwedge_detach(device_t self, int flags) +{ + struct dkwedge_softc *sc = NULL; + u_int unit; + int bmaj, cmaj, rc, s; + + rw_enter(&dkwedges_lock, RW_WRITER); + for (unit = 0; unit < ndkwedges; unit++) { + if ((sc = dkwedges[unit]) != NULL && sc->sc_dev == self) + break; + } + if (unit == ndkwedges) + rc = ENXIO; + else if ((rc = dkwedge_begindetach(sc, flags)) == 0) { + /* Mark the wedge as dying. */ + sc->sc_state = DKW_STATE_DYING; + } + rw_exit(&dkwedges_lock); + + if (rc != 0) + return rc; + + pmf_device_deregister(self); /* Locate the wedge major numbers. */ bmaj = bdevsw_lookup_major(&dk_bdevsw); @@ -495,9 +558,6 @@ sc->sc_parent->dk_name, sc->sc_wname); /* XXX Unicode */ - /* Delete our pseudo-device. */ - (void) config_detach(sc->sc_dev, DETACH_FORCE | DETACH_QUIET); - mutex_enter(&sc->sc_parent->dk_openlock); sc->sc_parent->dk_nwedges--; LIST_REMOVE(sc, sc_plink); @@ -518,7 +578,7 @@ free(sc, M_DKWEDGE); - return (0); + return 0; } /*