Module Name: src
Committed By: dyoung
Date: Fri May 15 23:49:28 UTC 2009
Modified Files:
src/sys/dev/ata: wd.c
Log Message:
Do not detach a wd(4) instance if it is open, but return EBUSY,
instead. If the detach is forced, do what wdclose() does on the
last close: flush the cache, clear the flag WDF_LOADED, and delete
our reference to the ATA bus device.
To generate a diff of this commit:
cvs rdiff -u -r1.373 -r1.374 src/sys/dev/ata/wd.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/ata/wd.c
diff -u src/sys/dev/ata/wd.c:1.373 src/sys/dev/ata/wd.c:1.374
--- src/sys/dev/ata/wd.c:1.373 Tue May 12 14:16:53 2009
+++ src/sys/dev/ata/wd.c Fri May 15 23:49:28 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: wd.c,v 1.373 2009/05/12 14:16:53 cegger Exp $ */
+/* $NetBSD: wd.c,v 1.374 2009/05/15 23:49:28 dyoung Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@@ -59,7 +59,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.373 2009/05/12 14:16:53 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.374 2009/05/15 23:49:28 dyoung Exp $");
#include "opt_ata.h"
@@ -133,6 +133,7 @@
int wdprint(void *, char *);
void wdperror(const struct wd_softc *);
+static void wdlastclose(struct wd_softc *);
static bool wd_suspend(device_t PMF_FN_PROTO);
static int wd_standby(struct wd_softc *, int);
@@ -456,7 +457,20 @@
wddetach(device_t self, int flags)
{
struct wd_softc *sc = device_private(self);
- int s, bmaj, cmaj, i, mn;
+ int bmaj, cmaj, i, mn, rc, s;
+
+ rc = 0;
+ mutex_enter(&sc->sc_dk.dk_openlock);
+ if (sc->sc_dk.dk_openmask == 0)
+ ; /* nothing to do */
+ else if ((flags & DETACH_FORCE) == 0)
+ rc = EBUSY;
+ else
+ wdlastclose(sc);
+ mutex_exit(&sc->sc_dk.dk_openlock);
+
+ if (rc != 0)
+ return rc;
/* locate the major number */
bmaj = bdevsw_lookup_major(&wd_bdevsw);
@@ -1001,6 +1015,20 @@
return error;
}
+/*
+ * Caller must hold wd->sc_dk.dk_openlock.
+ */
+static void
+wdlastclose(struct wd_softc *wd)
+{
+ wd_flushcache(wd, AT_WAIT);
+
+ if (! (wd->sc_flags & WDF_KLABEL))
+ wd->sc_flags &= ~WDF_LOADED;
+
+ wd->atabus->ata_delref(wd->drvp);
+}
+
int
wdclose(dev_t dev, int flag, int fmt, struct lwp *l)
{
@@ -1023,14 +1051,8 @@
wd->sc_dk.dk_openmask =
wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
- if (wd->sc_dk.dk_openmask == 0) {
- wd_flushcache(wd, AT_WAIT);
-
- if (! (wd->sc_flags & WDF_KLABEL))
- wd->sc_flags &= ~WDF_LOADED;
-
- wd->atabus->ata_delref(wd->drvp);
- }
+ if (wd->sc_dk.dk_openmask == 0)
+ wdlastclose(wd);
mutex_exit(&wd->sc_dk.dk_openlock);
return 0;