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

Reply via email to