Module Name: src Committed By: mlelstv Date: Fri Nov 3 13:01:26 UTC 2017
Modified Files: src/sys/dev/ata: wd.c wdvar.h Log Message: Add WDF_OPEN flag to really disallow opening of a disk that has been invalidated. Restore wdbiorestart function to actually retry the failed I/O request instead of just restarting the queue. Fix compilation without ATADEBUG. To generate a diff of this commit: cvs rdiff -u -r1.434 -r1.435 src/sys/dev/ata/wd.c cvs rdiff -u -r1.45 -r1.46 src/sys/dev/ata/wdvar.h 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/ata/wd.c diff -u src/sys/dev/ata/wd.c:1.434 src/sys/dev/ata/wd.c:1.435 --- src/sys/dev/ata/wd.c:1.434 Wed Nov 1 19:34:46 2017 +++ src/sys/dev/ata/wd.c Fri Nov 3 13:01:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: wd.c,v 1.434 2017/11/01 19:34:46 mlelstv Exp $ */ +/* $NetBSD: wd.c,v 1.435 2017/11/03 13:01:26 mlelstv Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.434 2017/11/01 19:34:46 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.435 2017/11/03 13:01:26 mlelstv Exp $"); #include "opt_ata.h" #include "opt_wd.h" @@ -194,6 +194,7 @@ static struct wd_ioctl *wi_get(struct wd static void wdioctlstrategy(struct buf *); static void wdstart(device_t); +static void wdstart1(struct wd_softc *, struct buf *, struct ata_xfer *); static int wd_diskstart(device_t, struct buf *); static int wd_dumpblocks(device_t, void *, daddr_t, int); static void wd_iosize(device_t, int *); @@ -607,23 +608,10 @@ err: biodone(bp); } -static int -wd_diskstart(device_t dev, struct buf *bp) +static void +wdstart1(struct wd_softc *wd, struct buf *bp, struct ata_xfer *xfer) { - struct wd_softc *wd = device_private(dev); struct dk_softc *dksc = &wd->sc_dksc; - struct ata_xfer *xfer; - - mutex_enter(&wd->sc_lock); - - xfer = ata_get_xfer_ext(wd->drvp->chnl_softc, 0, - WD_USE_NCQ(wd) ? WD_MAX_OPENINGS(wd) : 0); - if (xfer == NULL) { - ATADEBUG_PRINT(("wdstart %s no xfer\n", - dksc->sc_xname), DEBUG_XFERS); - mutex_exit(&wd->sc_lock); - return EAGAIN; - } KASSERT(bp == xfer->c_bio.bp || xfer->c_bio.bp == NULL); KASSERT((xfer->c_flags & (C_WAITACT|C_FREE)) == 0); @@ -722,6 +710,29 @@ wd_diskstart(device_t dev, struct buf *b default: panic("wdstart1: bad return code from ata_bio()"); } +} + +static int +wd_diskstart(device_t dev, struct buf *bp) +{ + struct wd_softc *wd = device_private(dev); +#ifdef ATADEBUG + struct dk_softc *dksc = &wd->sc_dksc; +#endif + struct ata_xfer *xfer; + + mutex_enter(&wd->sc_lock); + + xfer = ata_get_xfer_ext(wd->drvp->chnl_softc, 0, + WD_USE_NCQ(wd) ? WD_MAX_OPENINGS(wd) : 0); + if (xfer == NULL) { + ATADEBUG_PRINT(("wd_diskstart %s no xfer\n", + dksc->sc_xname), DEBUG_XFERS); + mutex_exit(&wd->sc_lock); + return EAGAIN; + } + + wdstart1(wd, bp, xfer); mutex_exit(&wd->sc_lock); @@ -825,7 +836,7 @@ retry2: /* Rerun ASAP if just requeued */ callout_reset(&xfer->c_retry_callout, (xfer->c_bio.error == REQUEUE) ? 1 : RECOVERYTIME, - wdbiorestart, wd); + wdbiorestart, xfer); mutex_exit(&wd->sc_lock); return; @@ -896,13 +907,19 @@ noerror: if ((xfer->c_bio.flags & ATA_CO static void wdbiorestart(void *v) { - struct wd_softc *wd = v; + struct ata_xfer *xfer = v; + struct buf *bp = xfer->c_bio.bp; + struct wd_softc *wd = device_lookup_private(&wd_cd, WDUNIT(bp->b_dev)); +#ifdef ATADEBUG struct dk_softc *dksc = &wd->sc_dksc; +#endif - ATADEBUG_PRINT(("wdrestart %s\n", dksc->sc_xname), + ATADEBUG_PRINT(("wdbiorestart %s\n", dksc->sc_xname), DEBUG_XFERS); - dk_start(dksc, NULL); + mutex_enter(&wd->sc_lock); + wdstart1(wd, bp, xfer); + mutex_exit(&wd->sc_lock); } static void @@ -985,7 +1002,7 @@ wdopen(dev_t dev, int flag, int fmt, str * If any partition is open, but the disk has been invalidated, * disallow further opens. */ - if ((wd->sc_flags & WDF_LOADED) == 0) { + if ((wd->sc_flags & (WDF_OPEN | WDF_LOADED)) == WDF_OPEN) { if (part != RAW_PART || fmt != S_IFCHR) return EIO; } @@ -1023,6 +1040,7 @@ wd_firstopen(device_t self, dev_t dev, i wd->sc_flags |= WDF_LOADED; } + wd->sc_flags |= WDF_OPEN; return 0; bad: @@ -1041,6 +1059,7 @@ wd_lastclose(device_t self) wd_flushcache(wd, AT_WAIT, false); wd->atabus->ata_delref(wd->drvp); + wd->sc_flags &= ~WDF_OPEN; return 0; } Index: src/sys/dev/ata/wdvar.h diff -u src/sys/dev/ata/wdvar.h:1.45 src/sys/dev/ata/wdvar.h:1.46 --- src/sys/dev/ata/wdvar.h:1.45 Wed Nov 1 19:34:46 2017 +++ src/sys/dev/ata/wdvar.h Fri Nov 3 13:01:26 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: wdvar.h,v 1.45 2017/11/01 19:34:46 mlelstv Exp $ */ +/* $NetBSD: wdvar.h,v 1.46 2017/11/03 13:01:26 mlelstv Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -54,6 +54,7 @@ struct wd_softc { #define WDF_LBA 0x040 /* using LBA mode */ #define WDF_LBA48 0x100 /* using 48-bit LBA mode */ #define WDF_FLUSH_PEND 0x200 /* cache flush waits for free xfer */ +#define WDF_OPEN 0x400 /* device is open */ uint64_t sc_capacity; /* full capacity of the device */ uint64_t sc_capacity512; /* ... in DEV_BSIZE blocks */ uint32_t sc_capacity28; /* capacity accessible with LBA28 commands */