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);