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;

Reply via email to