diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2009-10-22 11:56:33 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2009-10-22 11:56:33 +0000 |
commit | 880758c4c85cc97935b1627004254f778e022efe (patch) | |
tree | 365548e11c1f092fbef63daa7d752e97d87a5e65 | |
parent | 9df3fa0d779e13d76b1adf6c7679b6783bd5fbfc (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.c | 15 | ||||
-rw-r--r-- | sys/scsi/scsiconf.c | 90 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 5 |
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 */ |