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 */