summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2009-10-22 11:56:33 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2009-10-22 11:56:33 +0000
commit880758c4c85cc97935b1627004254f778e022efe (patch)
tree365548e11c1f092fbef63daa7d752e97d87a5e65
parent9df3fa0d779e13d76b1adf6c7679b6783bd5fbfc (diff)
devices below the scsibus should all be detached via scsi_detach_lun.
scsibusdetach wasnt doign it properly, so we would be leaking on detach in some cases. now, with the introduction of mpath, the scsi_link structures can represent a path to a mpath node as well as normal devices. this intercepts the device activate entrypoints and sends them to mpath if it it in use rather than assuming a device is always there. the scsibusdetach change ensures that detach always ends up handling the mpath node case too. hotplug bus functionality (eg, usb) tested by form@
-rw-r--r--sys/scsi/mpath.c15
-rw-r--r--sys/scsi/scsiconf.c90
-rw-r--r--sys/scsi/scsiconf.h5
3 files changed, 87 insertions, 23 deletions
diff --git a/sys/scsi/mpath.c b/sys/scsi/mpath.c
index a3ae183f478..cbd0a890ca1 100644
--- a/sys/scsi/mpath.c
+++ b/sys/scsi/mpath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpath.c,v 1.5 2009/10/14 01:33:22 dlg Exp $ */
+/* $OpenBSD: mpath.c,v 1.6 2009/10/22 11:56:32 dlg Exp $ */
/*
* Copyright (c) 2009 David Gwynne <dlg@openbsd.org>
@@ -307,3 +307,16 @@ mpath_path_detach(struct scsi_link *link, int flags)
panic("mpath: unable to locate path for detach");
}
+
+int
+mpath_path_activate(struct scsi_link *link)
+{
+ return (0);
+}
+
+int
+mpath_path_deactivate(struct scsi_link *link)
+{
+ return (0);
+}
+
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
index e730f6543bf..17fe99141ed 100644
--- a/sys/scsi/scsiconf.c
+++ b/sys/scsi/scsiconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.c,v 1.145 2009/10/14 01:33:22 dlg Exp $ */
+/* $OpenBSD: scsiconf.c,v 1.146 2009/10/22 11:56:32 dlg Exp $ */
/* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */
/*
@@ -199,35 +199,74 @@ scsibusattach(struct device *parent, struct device *self, void *aux)
int
scsibusactivate(struct device *dev, int act)
{
- return (config_activate_children(dev, act));
+ struct scsibus_softc *sc = (struct scsibus_softc *)dev;
+ struct scsi_link *link;
+ int i, j;
+ int rv, ret = 0;
+
+ for (i = 0; i < sc->sc_buswidth; i++) {
+ if (sc->sc_link[i] == NULL)
+ continue;
+
+ for (j = 0; j < sc->adapter_link->luns; j++) {
+ link = sc->sc_link[i][j];
+ if (link == NULL)
+ continue;
+ dev = link->device_softc;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+#if NMPATH > 0
+ if (dev == NULL)
+ rv = mpath_path_activate(link);
+ else
+#endif /* NMPATH */
+ rv = config_activate(dev);
+ break;
+
+ case DVACT_DEACTIVATE:
+#if NMPATH > 0
+ if (dev == NULL)
+ rv = mpath_path_deactivate(link);
+ else
+#endif /* NMPATH */
+ rv = config_deactivate(dev);
+ break;
+ default:
+#ifdef DIAGNOSTIC
+ printf("%s: unsupported act %d\n",
+ sc->sc_dev.dv_xname, act);
+#endif
+ rv = EOPNOTSUPP;
+ break;
+
+ }
+
+ if (rv != 0)
+ ret = rv;
+ }
+ }
+
+ return (ret);
}
int
scsibusdetach(struct device *dev, int type)
{
struct scsibus_softc *sb = (struct scsibus_softc *)dev;
- struct scsi_link *sc_link;
- int i, j, error;
+ int i, error;
#if NBIO > 0
bio_unregister(&sb->sc_dev);
#endif
- if ((error = config_detach_children(dev, type)) != 0)
+ error = scsi_detach_bus(sb, type);
+ if (error != 0)
return (error);
for (i = 0; i < sb->sc_buswidth; i++) {
- if (sb->sc_link[i] != NULL) {
- for (j = 0; j < sb->adapter_link->luns; j++) {
- sc_link = sb->sc_link[i][j];
- if (sc_link != NULL) {
- if (sc_link->id != NULL)
- devid_free(sc_link->id);
- free(sc_link, M_DEVBUF);
- }
- }
+ if (sb->sc_link[i] != NULL)
free(sb->sc_link[i], M_DEVBUF);
- }
}
free(sb->sc_link, M_DEVBUF);
@@ -279,6 +318,9 @@ scsibus_bioctl(struct device *dev, u_long cmd, caddr_t addr)
case SBIOCDETACH:
sdev = (struct sbioc_device *)addr;
+ if (sdev->sd_target == -1 && sdev->sd_lun == -1)
+ return (scsi_detach_bus(sc, 0));
+
if (sdev->sd_target == -1)
return (EINVAL);
@@ -384,12 +426,17 @@ int
scsi_detach_bus(struct scsibus_softc *sc, int flags)
{
struct scsi_link *alink = sc->adapter_link;
- int i;
+ int i, err, rv = 0, detached;
- for (i = 0; i < alink->adapter_buswidth; i++)
- scsi_detach_target(sc, i, flags);
+ for (i = 0; i < alink->adapter_buswidth; i++) {
+ err = scsi_detach_target(sc, i, flags);
+ if (err == 0)
+ detached = 1;
+ else
+ rv = err;
+ }
- return (0);
+ return (detached ? rv : ENXIO);
}
int
@@ -410,9 +457,10 @@ scsi_detach_target(struct scsibus_softc *sc, int target, int flags)
continue;
err = scsi_detach_lun(sc, target, i, flags);
- if (err != 0)
+ if (err == 0)
+ detached = 1;
+ else
rv = err;
- detached = 1;
}
return (detached ? rv : ENXIO);
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
index 82ca8533e04..63cdacecd1b 100644
--- a/sys/scsi/scsiconf.h
+++ b/sys/scsi/scsiconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsiconf.h,v 1.103 2009/10/20 00:19:24 dlg Exp $ */
+/* $OpenBSD: scsiconf.h,v 1.104 2009/10/22 11:56:32 dlg Exp $ */
/* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */
/*
@@ -584,5 +584,8 @@ void scsi_xs_put(struct scsi_xfer *);
int mpath_path_attach(struct scsi_link *);
int mpath_path_detach(struct scsi_link *, int);
+int mpath_path_activate(struct scsi_link *);
+int mpath_path_deactivate(struct scsi_link *);
+
#endif /* _KERNEL */
#endif /* SCSI_SCSICONF_H */