Module Name:    src
Committed By:   dyoung
Date:           Sat May 16 20:10:52 UTC 2009

Modified Files:
        src/sys/dev/scsipi: sd.c

Log Message:
Do not detach a sd(4) instance if it is open, but return EBUSY,
instead.  If the detach is forced, do what sdclose() does on the
last close: flush the cache, delete our reference to the SCSI bus
device, et cetera.


To generate a diff of this commit:
cvs rdiff -u -r1.281 -r1.282 src/sys/dev/scsipi/sd.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/scsipi/sd.c
diff -u src/sys/dev/scsipi/sd.c:1.281 src/sys/dev/scsipi/sd.c:1.282
--- src/sys/dev/scsipi/sd.c:1.281	Tue May 12 14:44:31 2009
+++ src/sys/dev/scsipi/sd.c	Sat May 16 20:10:52 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sd.c,v 1.281 2009/05/12 14:44:31 cegger Exp $	*/
+/*	$NetBSD: sd.c,v 1.282 2009/05/16 20:10:52 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@@ -47,7 +47,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.281 2009/05/12 14:44:31 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.282 2009/05/16 20:10:52 dyoung Exp $");
 
 #include "opt_scsi.h"
 #include "rnd.h"
@@ -103,6 +103,7 @@
 static bool	sd_suspend(device_t PMF_FN_PROTO);
 static bool	sd_shutdown(device_t, int);
 static int	sd_interpret_sense(struct scsipi_xfer *);
+static void	sdlastclose(struct sd_softc *);
 
 static int	sd_mode_sense(struct sd_softc *, u_int8_t, void *, size_t, int,
 		    int, int *);
@@ -349,7 +350,20 @@
 sddetach(device_t self, int flags)
 {
 	struct sd_softc *sd = device_private(self);
-	int s, bmaj, cmaj, i, mn;
+	int s, bmaj, cmaj, i, mn, rc;
+
+	rc = 0;
+	mutex_enter(&sd->sc_dk.dk_openlock);
+	if (sd->sc_dk.dk_openmask == 0)
+		;	/* nothing to do */
+	else if ((flags & DETACH_FORCE) != 0)
+		rc = EBUSY;
+	else
+		sdlastclose(sd);
+	mutex_exit(&sd->sc_dk.dk_openlock);
+
+	if (rc != 0)
+		return rc;
 
 	/* locate the major number */
 	bmaj = bdevsw_lookup_major(&sd_bdevsw);
@@ -582,6 +596,42 @@
 }
 
 /*
+ * Caller must hold sd->sc_dk.dk_openlock.
+ */
+static void
+sdlastclose(struct sd_softc *sd)
+{
+	struct scsipi_periph *periph = sd->sc_periph;
+	struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
+
+	/*
+	 * If the disk cache needs flushing, and the disk supports
+	 * it, do it now.
+	 */
+	if ((sd->flags & SDF_DIRTY) != 0) {
+		if (sd_flush(sd, 0)) {
+			aprint_error_dev(sd->sc_dev,
+				"cache synchronization failed\n");
+			sd->flags &= ~SDF_FLUSHING;
+		} else
+			sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY);
+	}
+
+	scsipi_wait_drain(periph);
+
+	if (periph->periph_flags & PERIPH_REMOVABLE)
+		scsipi_prevent(periph, SPAMR_ALLOW,
+		    XS_CTL_IGNORE_ILLEGAL_REQUEST |
+		    XS_CTL_IGNORE_NOT_READY |
+		    XS_CTL_SILENT);
+	periph->periph_flags &= ~PERIPH_OPEN;
+
+	scsipi_wait_drain(periph);
+
+	scsipi_adapter_delref(adapt);
+}
+
+/*
  * close the device.. only called if we are the LAST occurence of an open
  * device.  Convenient now but usually a pain.
  */
@@ -589,8 +639,6 @@
 sdclose(dev_t dev, int flag, int fmt, struct lwp *l)
 {
 	struct sd_softc *sd = device_lookup_private(&sd_cd, SDUNIT(dev));
-	struct scsipi_periph *periph = sd->sc_periph;
-	struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
 	int part = SDPART(dev);
 
 	mutex_enter(&sd->sc_dk.dk_openlock);
@@ -605,33 +653,8 @@
 	sd->sc_dk.dk_openmask =
 	    sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask;
 
-	if (sd->sc_dk.dk_openmask == 0) {
-		/*
-		 * If the disk cache needs flushing, and the disk supports
-		 * it, do it now.
-		 */
-		if ((sd->flags & SDF_DIRTY) != 0) {
-			if (sd_flush(sd, 0)) {
-				aprint_error_dev(sd->sc_dev,
-					"cache synchronization failed\n");
-				sd->flags &= ~SDF_FLUSHING;
-			} else
-				sd->flags &= ~(SDF_FLUSHING|SDF_DIRTY);
-		}
-
-		scsipi_wait_drain(periph);
-
-		if (periph->periph_flags & PERIPH_REMOVABLE)
-			scsipi_prevent(periph, SPAMR_ALLOW,
-			    XS_CTL_IGNORE_ILLEGAL_REQUEST |
-			    XS_CTL_IGNORE_NOT_READY |
-			    XS_CTL_SILENT);
-		periph->periph_flags &= ~PERIPH_OPEN;
-
-		scsipi_wait_drain(periph);
-
-		scsipi_adapter_delref(adapt);
-	}
+	if (sd->sc_dk.dk_openmask == 0)
+		sdlastclose(sd);
 
 	mutex_exit(&sd->sc_dk.dk_openlock);
 	return (0);

Reply via email to