From cc79c7aeb0c29c2a14e7b73de67a1adcbdad3a1c Mon Sep 17 00:00:00 2001 From: thorpej Date: Sat, 25 Sep 2004 03:34:02 +0000 Subject: [PATCH] Add support for wedges to the ATA disk driver. --- sys/dev/ata/wd.c | 93 ++++++++++++++++++++++++++++++++------------- sys/dev/ata/wdvar.h | 3 +- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c index 32b80b301906..61ddacd0cc43 100644 --- a/sys/dev/ata/wd.c +++ b/sys/dev/ata/wd.c @@ -1,4 +1,4 @@ -/* $NetBSD: wd.c,v 1.293 2004/09/16 20:52:43 bouyer Exp $ */ +/* $NetBSD: wd.c,v 1.294 2004/09/25 03:34:02 thorpej Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -66,7 +66,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.293 2004/09/16 20:52:43 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.294 2004/09/25 03:34:02 thorpej Exp $"); #ifndef ATADEBUG #define ATADEBUG @@ -195,7 +195,7 @@ void wd_shutdown(void *); int wd_getcache(struct wd_softc *, int *); int wd_setcache(struct wd_softc *, int); -struct dkdriver wddkdriver = { wdstrategy }; +struct dkdriver wddkdriver = { wdstrategy, minphys }; #ifdef HAS_BAD144_HANDLING static void bad144intern(struct wd_softc *); @@ -275,8 +275,6 @@ wdattach(struct device *parent, struct device *self, void *aux) const struct wd_quirk *wdq; ATADEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); - lockinit(&wd->sc_lock, PRIBIO | PCATCH, "wdlock", 0, 0); - callout_init(&wd->sc_restart_ch); bufq_alloc(&wd->sc_q, BUFQ_DISK_DEFAULT_STRAT()|BUFQ_SORT_RAWBLOCK); #ifdef WD_SOFTBADSECT @@ -389,6 +387,9 @@ wdattach(struct device *parent, struct device *self, void *aux) rnd_attach_source(&wd->rnd_source, wd->sc_dev.dv_xname, RND_TYPE_DISK, 0); #endif + + /* Discover wedges on this disk. */ + dkwedge_discover(&wd->sc_dk); } int @@ -428,6 +429,9 @@ wddetach(struct device *self, int flags) vdevgone(cmaj, mn, mn, VCHR); } + /* Delete all of our wedges. */ + dkwedge_delall(&sc->sc_dk); + s = splbio(); /* Kill off any queued buffers. */ @@ -465,7 +469,6 @@ wddetach(struct device *self, int flags) rnd_detach_source(&sc->rnd_source); #endif - lockmgr(&sc->sc_lock, LK_DRAIN, NULL); sc->drvp->drive_flags = 0; /* no drive any more here */ return (0); @@ -870,16 +873,27 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p) if ((wd->sc_dev.dv_flags & DVF_ACTIVE) == 0) return (ENODEV); + part = WDPART(dev); + + if ((error = lockmgr(&wd->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL)) != 0) + return (error); + + /* + * If there are wedges, and this is not RAW_PART, then we + * need to fail. + */ + if (wd->sc_dk.dk_nwedges != 0 && part != RAW_PART) { + error = EBUSY; + goto bad1; + } + /* * If this is the first open of this device, add a reference * to the adapter. */ if (wd->sc_dk.dk_openmask == 0 && (error = wd->atabus->ata_addref(wd->drvp)) != 0) - return (error); - - if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0) - goto bad4; + goto bad1; if (wd->sc_dk.dk_openmask != 0) { /* @@ -888,7 +902,7 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p) */ if ((wd->sc_flags & WDF_LOADED) == 0) { error = EIO; - goto bad3; + goto bad2; } } else { if ((wd->sc_flags & WDF_LOADED) == 0) { @@ -902,14 +916,12 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p) } } - part = WDPART(dev); - /* Check that the partition exists. */ if (part != RAW_PART && (part >= wd->sc_dk.dk_label->d_npartitions || wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { error = ENXIO; - goto bad; + goto bad2; } /* Insure only one open at a time. */ @@ -924,18 +936,14 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p) wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; - lockmgr(&wd->sc_lock, LK_RELEASE, NULL); + (void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL); return 0; -bad: - if (wd->sc_dk.dk_openmask == 0) { - } - -bad3: - lockmgr(&wd->sc_lock, LK_RELEASE, NULL); -bad4: + bad2: if (wd->sc_dk.dk_openmask == 0) wd->atabus->ata_delref(wd->drvp); + bad1: + (void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL); return error; } @@ -947,7 +955,8 @@ wdclose(dev_t dev, int flag, int fmt, struct proc *p) int error; ATADEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS); - if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0) + + if ((error = lockmgr(&wd->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL)) != 0) return error; switch (fmt) { @@ -970,7 +979,7 @@ wdclose(dev_t dev, int flag, int fmt, struct proc *p) wd->atabus->ata_delref(wd->drvp); } - lockmgr(&wd->sc_lock, LK_RELEASE, NULL); + (void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL); return 0; } @@ -1236,7 +1245,8 @@ wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) #endif lp = (struct disklabel *)addr; - if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0) + if ((error = lockmgr(&wd->sc_dk.dk_openlock, LK_EXCLUSIVE, + NULL)) != 0) goto bad; wd->sc_flags |= WDF_LABELLING; @@ -1260,7 +1270,7 @@ wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) } wd->sc_flags &= ~WDF_LABELLING; - lockmgr(&wd->sc_lock, LK_RELEASE, NULL); + (void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL); bad: #ifdef __HAVE_OLD_DISKLABEL if (newlabel != NULL) @@ -1385,6 +1395,37 @@ bad: return(error); } + case DIOCAWEDGE: + { + struct dkwedge_info *dkw = (void *) addr; + + if ((flag & FWRITE) == 0) + return (EBADF); + + /* If the ioctl happens here, the parent is us. */ + strcpy(dkw->dkw_parent, wd->sc_dev.dv_xname); + return (dkwedge_add(dkw)); + } + + case DIOCDWEDGE: + { + struct dkwedge_info *dkw = (void *) addr; + + if ((flag & FWRITE) == 0) + return (EBADF); + + /* If the ioctl happens here, the parent is us. */ + strcpy(dkw->dkw_parent, wd->sc_dev.dv_xname); + return (dkwedge_del(dkw)); + } + + case DIOCLWEDGES: + { + struct dkwedge_list *dkwl = (void *) addr; + + return (dkwedge_list(&wd->sc_dk, dkwl, p)); + } + default: return ENOTTY; } diff --git a/sys/dev/ata/wdvar.h b/sys/dev/ata/wdvar.h index 5b1ce3e2bd4a..5269fd37f9e4 100644 --- a/sys/dev/ata/wdvar.h +++ b/sys/dev/ata/wdvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: wdvar.h,v 1.27 2004/08/30 09:34:42 drochner Exp $ */ +/* $NetBSD: wdvar.h,v 1.28 2004/09/25 03:34:02 thorpej Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -40,7 +40,6 @@ struct wd_softc { /* General disk infos */ struct device sc_dev; struct disk sc_dk; - struct lock sc_lock; struct bufq_state sc_q; struct callout sc_restart_ch; int sc_quirks; /* any quirks drive might have */