From 1e7162a8ff1b3da47109d13915bdaf9504f12d52 Mon Sep 17 00:00:00 2001 From: csapuntz Date: Tue, 18 Apr 2000 05:53:17 +0000 Subject: [PATCH] sd and scsibus detach cdlock/cdunlock now through disk_lock/disk_unlock --- sys/scsi/cd.c | 43 +------- sys/scsi/scsiconf.c | 45 +++++++- sys/scsi/sd.c | 249 ++++++++++++++++++++++++++++++-------------- 3 files changed, 217 insertions(+), 120 deletions(-) diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c index 1ce727ebcf1..04c1a52698f 100644 --- a/sys/scsi/cd.c +++ b/sys/scsi/cd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cd.c,v 1.52 2000/04/09 07:09:03 csapuntz Exp $ */ +/* $OpenBSD: cd.c,v 1.53 2000/04/18 05:53:17 csapuntz Exp $ */ /* $NetBSD: cd.c,v 1.100 1997/04/02 02:29:30 mycroft Exp $ */ /* @@ -110,8 +110,6 @@ struct cd_toc { int cdmatch __P((struct device *, void *, void *)); void cdattach __P((struct device *, struct device *, void *)); -int cdlock __P((struct cd_softc *)); -void cdunlock __P((struct cd_softc *)); void cdstart __P((void *)); void cdminphys __P((struct buf *)); void cdgetdisklabel __P((dev_t, struct cd_softc *, struct disklabel *, @@ -173,6 +171,9 @@ struct scsi_inquiry_pattern cd_patterns[] = { extern struct cd_ops cd_atapibus_ops; extern struct cd_ops cd_scsibus_ops; +#define cdlock(softc) disk_lock(&(softc)->sc_dk) +#define cdunlock(softc) disk_unlock(&(softc)->sc_dk) + int cdmatch(parent, match, aux) struct device *parent; @@ -236,42 +237,6 @@ cdattach(parent, self, aux) printf("\n"); } -/* - * Wait interruptibly for an exclusive lock. - * - * XXX - * Several drivers do this; it should be abstracted and made MP-safe. - */ -int -cdlock(cd) - struct cd_softc *cd; -{ - int error; - - while ((cd->flags & CDF_LOCKED) != 0) { - cd->flags |= CDF_WANTED; - if ((error = tsleep(cd, PRIBIO | PCATCH, "cdlck", 0)) != 0) - return error; - } - cd->flags |= CDF_LOCKED; - return 0; -} - -/* - * Unlock and wake up any waiters. - */ -void -cdunlock(cd) - struct cd_softc *cd; -{ - - cd->flags &= ~CDF_LOCKED; - if ((cd->flags & CDF_WANTED) != 0) { - cd->flags &= ~CDF_WANTED; - wakeup(cd); - } -} - /* * open the device. Make sure the partition info is a up-to-date as can be. */ diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index e3e47f40554..3f002877821 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.c,v 1.51 2000/04/08 19:19:33 csapuntz Exp $ */ +/* $OpenBSD: scsiconf.c,v 1.52 2000/04/18 05:53:17 csapuntz Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* @@ -86,10 +86,17 @@ struct scsi_device probe_switch = { int scsibusmatch __P((struct device *, void *, void *)); void scsibusattach __P((struct device *, struct device *, void *)); +int scsibusactivate __P((struct device *, enum devact)); +int scsibusdetach __P((struct device *, int)); +void scsibuszeroref __P((struct device *)); + int scsibussubmatch __P((struct device *, void *, void *)); + + struct cfattach scsibus_ca = { - sizeof(struct scsibus_softc), scsibusmatch, scsibusattach + sizeof(struct scsibus_softc), scsibusmatch, scsibusattach, + scsibusdetach, scsibusactivate, scsibuszeroref }; struct cfdriver scsibus_cd = { @@ -184,6 +191,40 @@ scsibusattach(parent, self, aux) scsi_probe_bus(sb->sc_dev.dv_unit, -1, -1); } + +int +scsibusactivate(dev, act) + struct device *dev; + enum devact act; +{ + return (config_activate_children(dev, act)); +} + +int +scsibusdetach (dev, type) + struct device *dev; + int type; +{ + return (config_detach_children(dev, type)); +} + +void +scsibuszeroref(dev) + struct device *dev; +{ + struct scsibus_softc *sb = (struct scsibus_softc *)dev; + int i; + + for (i = 0; i < sb->sc_buswidth; i++) { + if (sb->sc_link[i] != NULL) + free(sb->sc_link[i], M_DEVBUF); + } + + free(sb->sc_link, M_DEVBUF); +} + + + int scsibussubmatch(parent, match, aux) struct device *parent; diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index 7cc7995c85d..e0018164a62 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sd.c,v 1.42 2000/04/08 19:19:33 csapuntz Exp $ */ +/* $OpenBSD: sd.c,v 1.43 2000/04/18 05:53:17 csapuntz Exp $ */ /* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ /*- @@ -80,9 +80,12 @@ #include /* for BBSIZE and SBSIZE */ +#include + #define SDOUTSTANDING 4 #define SDUNIT(dev) DISKUNIT(dev) +#define SDMINOR(unit, part) DISKMINOR(unit, part) #define SDPART(dev) DISKPART(dev) #define MAKESDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) @@ -90,8 +93,10 @@ int sdmatch __P((struct device *, void *, void *)); void sdattach __P((struct device *, struct device *, void *)); -int sdlock __P((struct sd_softc *)); -void sdunlock __P((struct sd_softc *)); +int sdactivate __P((struct device *, enum devact)); +int sddetach __P((struct device *, int)); +void sdzeroref __P((struct device *)); + void sdminphys __P((struct buf *)); void sdgetdisklabel __P((dev_t, struct sd_softc *, struct disklabel *, struct cpu_disklabel *, int)); @@ -104,7 +109,8 @@ int sd_interpret_sense __P((struct scsi_xfer *)); void viscpy __P((u_char *, u_char *, int)); struct cfattach sd_ca = { - sizeof(struct sd_softc), sdmatch, sdattach + sizeof(struct sd_softc), sdmatch, sdattach, + sddetach, sdactivate, sdzeroref }; struct cfdriver sd_cd = { @@ -134,6 +140,10 @@ struct scsi_inquiry_pattern sd_patterns[] = { extern struct sd_ops sd_scsibus_ops; extern struct sd_ops sd_atapibus_ops; +#define sdlock(softc) disk_lock(&(softc)->sc_dk) +#define sdunlock(softc) disk_unlock(&(softc)->sc_dk) +#define sdlookup(unit) (struct sd_softc *)device_lookup(&sd_cd, (unit)) + int sdmatch(parent, match, aux) struct device *parent; @@ -247,7 +257,6 @@ sdattach(parent, self, aux) } printf("\n"); -#ifdef notyet /* * Establish a shutdown hook so that we can ensure that * our data has actually made it onto the platter at @@ -260,43 +269,79 @@ sdattach(parent, self, aux) shutdownhook_establish(sd_shutdown, sd)) == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", sd->sc_dev.dv_xname); -#endif } -/* - * Wait interruptibly for an exclusive lock. - * - * XXX - * Several drivers do this; it should be abstracted and made MP-safe. - */ int -sdlock(sd) - struct sd_softc *sd; +sdactivate(self, act) + struct device *self; + enum devact act; { - int error; + int rv = 0; + + switch (act) { + case DVACT_ACTIVATE: + break; + + case DVACT_DEACTIVATE: + /* + * Nothing to do; we key off the device's DVF_ACTIVATE. + */ + break; + } + return (rv); +} + + +int +sddetach(self, flags) + struct device *self; + int flags; +{ + struct sd_softc *sc = (struct sd_softc *)self; + struct buf *dp, *bp; + int s, bmaj, cmaj, mn; - while ((sd->flags & SDF_LOCKED) != 0) { - sd->flags |= SDF_WANTED; - if ((error = tsleep(sd, PRIBIO | PCATCH, "sdlck", 0)) != 0) - return error; + /* Remove unprocessed buffers from queue */ + s = splbio(); + for (dp = &sc->buf_queue; (bp = dp->b_actf) != NULL; ) { + dp->b_actf = bp->b_actf; + + bp->b_error = ENXIO; + bp->b_flags |= B_ERROR; + biodone(bp); } - sd->flags |= SDF_LOCKED; - return 0; + splx(s); + + /* locate the major number */ + mn = SDMINOR(self->dv_unit, 0); + + for (bmaj = 0; bmaj < nblkdev; bmaj++) + if (bdevsw[bmaj].d_open == sdopen) + vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK); + for (cmaj = 0; cmaj < nchrdev; cmaj++) + if (cdevsw[cmaj].d_open == sdopen) + vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR); + + /* Get rid of the shutdown hook. */ + if (sc->sc_sdhook != NULL) + shutdownhook_disestablish(sc->sc_sdhook); + +#if NRND > 0 + /* Unhook the entropy source. */ + rnd_detach_source(&sc->rnd_source); +#endif + + return (0); } -/* - * Unlock and wake up any waiters. - */ void -sdunlock(sd) - struct sd_softc *sd; +sdzeroref(self) + struct device *self; { + struct sd_softc *sd = (struct sd_softc *)self; - sd->flags &= ~SDF_LOCKED; - if ((sd->flags & SDF_WANTED) != 0) { - sd->flags &= ~SDF_WANTED; - wakeup(sd); - } + /* Detach disk. */ + disk_detach(&sd->sc_dk); } /* @@ -314,10 +359,8 @@ sdopen(dev, flag, fmt, p) int error; unit = SDUNIT(dev); - if (unit >= sd_cd.cd_ndevs) - return ENXIO; - sd = sd_cd.cd_devs[unit]; - if (!sd) + sd = sdlookup(unit); + if (sd == NULL) return ENXIO; sc_link = sd->sc_link; @@ -326,8 +369,10 @@ sdopen(dev, flag, fmt, p) ("sdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, sd_cd.cd_ndevs, part)); - if ((error = sdlock(sd)) != 0) + if ((error = sdlock(sd)) != 0) { + device_unref(&sd->sc_dev); return error; + } if (sd->sc_dk.dk_openmask != 0) { /* @@ -407,6 +452,7 @@ sdopen(dev, flag, fmt, p) SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n")); sdunlock(sd); + device_unref(&sd->sc_dev); return 0; bad2: @@ -421,6 +467,7 @@ bad: bad3: sdunlock(sd); + device_unref(&sd->sc_dev); return error; } @@ -434,10 +481,14 @@ sdclose(dev, flag, fmt, p) int flag, fmt; struct proc *p; { - struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(dev)]; + struct sd_softc *sd; int part = SDPART(dev); int error; + sd = sdlookup(SDUNIT(dev)); + if (sd == NULL) + return ENXIO; + if ((error = sdlock(sd)) != 0) return error; @@ -468,6 +519,7 @@ sdclose(dev, flag, fmt, p) } sdunlock(sd); + device_unref(&sd->sc_dev); return 0; } @@ -480,9 +532,15 @@ void sdstrategy(bp) struct buf *bp; { - struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(bp->b_dev)]; + struct sd_softc *sd; int s; + sd = sdlookup(SDUNIT(bp->b_dev)); + if (sd == NULL) { + bp->b_error = ENXIO; + goto bad; + } + SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy ")); SC_DEBUG(sd->sc_link, SDEV_DB1, ("%ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno)); @@ -533,6 +591,8 @@ sdstrategy(bp) sdstart(sd); splx(s); + + device_unref(&sd->sc_dev); return; bad: @@ -543,6 +603,9 @@ done: */ bp->b_resid = bp->b_bcount; biodone(bp); + + if (sd != NULL) + device_unref(&sd->sc_dev); } /* @@ -702,9 +765,13 @@ void sdminphys(bp) struct buf *bp; { - struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(bp->b_dev)]; + struct sd_softc *sd; long max; + sd = sdlookup(SDUNIT(bp->b_dev)); + if (sd == NULL) + return; /* XXX - right way to fail this? */ + /* * If the device is ancient, we want to make sure that * the transfer fits into a 6-byte cdb. @@ -724,6 +791,8 @@ sdminphys(bp) } (*sd->sc_link->adapter->scsi_minphys)(bp); + + device_unref(&sd->sc_dev); } int @@ -758,10 +827,14 @@ sdioctl(dev, cmd, addr, flag, p) int flag; struct proc *p; { - struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(dev)]; - int error; + struct sd_softc *sd; + int error = 0; int part = SDPART(dev); + sd = sdlookup(SDUNIT(dev)); + if (sd == NULL) + return ENXIO; + SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdioctl 0x%lx ", cmd)); /* @@ -780,10 +853,13 @@ sdioctl(dev, cmd, addr, flag, p) break; /* FALLTHROUGH */ default: - if ((sd->sc_link->flags & SDEV_OPEN) == 0) - return (ENODEV); - else - return (EIO); + if ((sd->sc_link->flags & SDEV_OPEN) == 0) { + error = ENODEV; + goto exit; + } else { + error = EIO; + goto exit; + } } } @@ -791,32 +867,34 @@ sdioctl(dev, cmd, addr, flag, p) case DIOCRLDINFO: sdgetdisklabel(dev, sd, sd->sc_dk.dk_label, sd->sc_dk.dk_cpulabel, 0); - return 0; + goto exit; case DIOCGPDINFO: { struct cpu_disklabel osdep; sdgetdisklabel(dev, sd, (struct disklabel *)addr, &osdep, 1); - return 0; + goto exit; } case DIOCGDINFO: *(struct disklabel *)addr = *(sd->sc_dk.dk_label); - return 0; + goto exit; case DIOCGPART: ((struct partinfo *)addr)->disklab = sd->sc_dk.dk_label; ((struct partinfo *)addr)->part = &sd->sc_dk.dk_label->d_partitions[SDPART(dev)]; - return 0; + goto exit; case DIOCWDINFO: case DIOCSDINFO: - if ((flag & FWRITE) == 0) - return EBADF; + if ((flag & FWRITE) == 0) { + error = EBADF; + goto exit; + } if ((error = sdlock(sd)) != 0) - return error; + goto exit; sd->flags |= SDF_LABELLING; error = setdisklabel(sd->sc_dk.dk_label, @@ -831,46 +909,57 @@ sdioctl(dev, cmd, addr, flag, p) sd->flags &= ~SDF_LABELLING; sdunlock(sd); - return error; + goto exit; case DIOCWLABEL: - if ((flag & FWRITE) == 0) - return EBADF; + if ((flag & FWRITE) == 0) { + error = EBADF; + goto exit; + } if (*(int *)addr) sd->flags |= SDF_WLABEL; else sd->flags &= ~SDF_WLABEL; - return 0; + goto exit; case DIOCLOCK: - return scsi_prevent(sd->sc_link, + error = scsi_prevent(sd->sc_link, (*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0); + goto exit; case MTIOCTOP: - if (((struct mtop *)addr)->mt_op != MTOFFL) - return EIO; + if (((struct mtop *)addr)->mt_op != MTOFFL) { + error = EIO; + goto exit; + } /* FALLTHROUGH */ case DIOCEJECT: - if ((sd->sc_link->flags & SDEV_REMOVABLE) == 0) - return ENOTTY; + if ((sd->sc_link->flags & SDEV_REMOVABLE) == 0) { + error = ENOTTY; + goto exit; + } sd->sc_link->flags |= SDEV_EJECTING; - return 0; + goto exit; case SCIOCREASSIGN: - if ((flag & FWRITE) == 0) - return EBADF; + if ((flag & FWRITE) == 0) { + error = EBADF; + goto exit; + } error = sd_reassign_blocks(sd, (*(int *)addr)); - return error; + goto exit; default: - if (part != RAW_PART) - return ENOTTY; - return scsi_do_ioctl(sd->sc_link, dev, cmd, addr, flag, p); + if (part != RAW_PART) { + error = ENOTTY; + goto exit; + } + error = scsi_do_ioctl(sd->sc_link, dev, cmd, addr, flag, p); } -#ifdef DIAGNOSTIC - panic("sdioctl: impossible"); -#endif + exit: + device_unref(&sd->sc_dev); + return (error); } /* @@ -1053,21 +1142,20 @@ sdsize(dev) dev_t dev; { struct sd_softc *sd; - int part, unit, omask; + int part, omask; int size; - unit = SDUNIT(dev); - if (unit >= sd_cd.cd_ndevs) - return -1; - sd = sd_cd.cd_devs[unit]; + sd = sdlookup(SDUNIT(dev)); if (sd == NULL) return -1; part = SDPART(dev); omask = sd->sc_dk.dk_openmask & (1 << part); - if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0) - return -1; + if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0) { + size = -1; + goto exit; + } if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0) size = -1; else if (sd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) @@ -1076,7 +1164,10 @@ sdsize(dev) size = sd->sc_dk.dk_label->d_partitions[part].p_size * (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE); if (omask == 0 && sdclose(dev, 0, S_IFBLK, NULL) != 0) - return -1; + size = -1; + + exit: + device_unref(&sd->sc_dev); return size; } -- 2.20.1