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;
}
/*