Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Make dksubr use a spin-mutex again, since some drivers s...
details: https://anonhg.NetBSD.org/src/rev/08f3a7d7f4c7
branches: trunk
changeset: 340201:08f3a7d7f4c7
user: mlelstv <mlelstv%NetBSD.org@localhost>
date: Thu Aug 27 05:51:50 2015 +0000
description:
Make dksubr use a spin-mutex again, since some drivers still call dk_done
from hardware interrupt. Instead, release mutex while calling start routine.
The buffer peek/use/get sequence which can no longer be atomic. So consume
the buffer directly and on error privately save and retry the buffer later.
The dk_drain function is used to flush such a deferred buffer together with
the buffer queue.
Adjust drivers to use dk_drain.
Fix an error path where dk_done was called while the lock was already held.
diffstat:
sys/arch/xen/xen/xbd_xenbus.c | 15 +++-----
sys/dev/cgd.c | 11 ++----
sys/dev/dksubr.c | 73 ++++++++++++++++++++++++++++++++----------
sys/dev/dkvar.h | 5 ++-
sys/dev/ld.c | 13 +++----
5 files changed, 76 insertions(+), 41 deletions(-)
diffs (truncated from 322 to 300 lines):
diff -r 49f1cf2fdc6e -r 08f3a7d7f4c7 sys/arch/xen/xen/xbd_xenbus.c
--- a/sys/arch/xen/xen/xbd_xenbus.c Thu Aug 27 03:20:13 2015 +0000
+++ b/sys/arch/xen/xen/xbd_xenbus.c Thu Aug 27 05:51:50 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xbd_xenbus.c,v 1.72 2015/08/16 18:00:03 mlelstv Exp $ */
+/* $NetBSD: xbd_xenbus.c,v 1.73 2015/08/27 05:51:50 mlelstv Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -50,7 +50,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.72 2015/08/16 18:00:03 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.73 2015/08/27 05:51:50 mlelstv Exp $");
#include "opt_xen.h"
@@ -363,11 +363,9 @@
/* Delete all of our wedges. */
dkwedge_delall(&sc->sc_dksc.sc_dkdev);
- s = splbio();
/* Kill off any queued buffers. */
- bufq_drain(sc->sc_dksc.sc_bufq);
+ dk_drain(&sc->sc_dksc);
bufq_free(sc->sc_dksc.sc_bufq);
- splx(s);
/* detach disk */
disk_detach(&sc->sc_dksc.sc_dkdev);
@@ -701,12 +699,11 @@
next:
if (bp->b_data != xbdreq->req_data)
xbd_unmap_align(xbdreq);
- disk_unbusy(&sc->sc_dksc.sc_dkdev,
- (bp->b_bcount - bp->b_resid),
- (bp->b_flags & B_READ));
+
rnd_add_uint32(&sc->sc_rnd_source,
bp->b_blkno);
- biodone(bp);
+ dk_done(&sc->sc_dksc, bp);
+
SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, req_next);
}
done:
diff -r 49f1cf2fdc6e -r 08f3a7d7f4c7 sys/dev/cgd.c
--- a/sys/dev/cgd.c Thu Aug 27 03:20:13 2015 +0000
+++ b/sys/dev/cgd.c Thu Aug 27 05:51:50 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cgd.c,v 1.103 2015/08/21 09:33:53 christos Exp $ */
+/* $NetBSD: cgd.c,v 1.104 2015/08/27 05:51:50 mlelstv Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.103 2015/08/21 09:33:53 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.104 2015/08/27 05:51:50 mlelstv Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -565,7 +565,7 @@
return VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred);
case DIOCGSTRATEGY:
case DIOCSSTRATEGY:
- if ((dksc->sc_flags & DKF_INITED) == 0)
+ if (!DK_ATTACHED(dksc))
return ENOENT;
/*FALLTHROUGH*/
default:
@@ -722,7 +722,6 @@
static int
cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
{
- int s;
struct dk_softc *dksc = &cs->sc_dksc;
if (!DK_ATTACHED(dksc))
@@ -732,9 +731,7 @@
dkwedge_delall(&dksc->sc_dkdev);
/* Kill off any queued buffers. */
- s = splbio();
- bufq_drain(dksc->sc_bufq);
- splx(s);
+ dk_drain(dksc);
bufq_free(dksc->sc_bufq);
(void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
diff -r 49f1cf2fdc6e -r 08f3a7d7f4c7 sys/dev/dksubr.c
--- a/sys/dev/dksubr.c Thu Aug 27 03:20:13 2015 +0000
+++ b/sys/dev/dksubr.c Thu Aug 27 05:51:50 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dksubr.c,v 1.73 2015/08/23 07:47:52 mlelstv Exp $ */
+/* $NetBSD: dksubr.c,v 1.74 2015/08/27 05:51:50 mlelstv Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 1999, 2002, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.73 2015/08/23 07:47:52 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dksubr.c,v 1.74 2015/08/27 05:51:50 mlelstv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -74,6 +74,7 @@
static void dk_makedisklabel(struct dk_softc *);
static int dk_translate(struct dk_softc *, struct buf *);
+static void dk_done1(struct dk_softc *, struct buf *, bool);
void
dk_init(struct dk_softc *dksc, device_t dev, int dtype)
@@ -90,7 +91,7 @@
void
dk_attach(struct dk_softc *dksc)
{
- mutex_init(&dksc->sc_iolock, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&dksc->sc_iolock, MUTEX_DEFAULT, IPL_VM);
dksc->sc_flags |= DKF_INITED;
#ifdef DIAGNOSTIC
dksc->sc_flags |= DKF_WARNLABEL | DKF_LABELSANITY;
@@ -294,41 +295,55 @@
{
const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
int error;
- struct buf *qbp __diagused;
mutex_enter(&dksc->sc_iolock);
if (bp != NULL)
bufq_put(dksc->sc_bufq, bp);
- while ((bp = bufq_peek(dksc->sc_bufq)) != NULL) {
+ /*
+ * Peeking at the buffer queue and committing the operation
+ * only after success isn't atomic.
+ *
+ * So when a diskstart fails, the buffer is saved
+ * and tried again before the next buffer is fetched.
+ * dk_drain() handles flushing of a saved buffer.
+ *
+ * This keeps order of I/O operations, unlike bufq_put.
+ */
+
+ bp = dksc->sc_deferred;
+ dksc->sc_deferred = NULL;
+
+ if (bp == NULL)
+ bp = bufq_get(dksc->sc_bufq);
+
+ while (bp != NULL) {
disk_busy(&dksc->sc_dkdev);
+ mutex_exit(&dksc->sc_iolock);
error = dkd->d_diskstart(dksc->sc_dev, bp);
+ mutex_enter(&dksc->sc_iolock);
if (error == EAGAIN) {
+ dksc->sc_deferred = bp;
disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
break;
}
-#ifdef DIAGNOSTIC
- qbp = bufq_get(dksc->sc_bufq);
- KASSERT(bp == qbp);
-#else
- (void) bufq_get(dksc->sc_bufq);
-#endif
-
if (error != 0) {
bp->b_error = error;
bp->b_resid = bp->b_bcount;
- dk_done(dksc, bp);
+ dk_done1(dksc, bp, false);
}
+
+ bp = bufq_get(dksc->sc_bufq);
}
mutex_exit(&dksc->sc_iolock);
}
-void
-dk_done(struct dk_softc *dksc, struct buf *bp)
+static void
+dk_done1(struct dk_softc *dksc, struct buf *bp, bool lock)
{
struct disk *dk = &dksc->sc_dkdev;
@@ -340,9 +355,11 @@
printf("\n");
}
- mutex_enter(&dksc->sc_iolock);
+ if (lock)
+ mutex_enter(&dksc->sc_iolock);
disk_unbusy(dk, bp->b_bcount - bp->b_resid, (bp->b_flags & B_READ));
- mutex_exit(&dksc->sc_iolock);
+ if (lock)
+ mutex_exit(&dksc->sc_iolock);
#ifdef notyet
rnd_add_uint(&dksc->sc_rnd_source, bp->b_rawblkno);
@@ -351,6 +368,28 @@
biodone(bp);
}
+void
+dk_done(struct dk_softc *dksc, struct buf *bp)
+{
+ dk_done1(dksc, bp, true);
+}
+
+void
+dk_drain(struct dk_softc *dksc)
+{
+ struct buf *bp;
+
+ mutex_enter(&dksc->sc_iolock);
+ bp = dksc->sc_deferred;
+ if (bp != NULL) {
+ bp->b_error = EIO;
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+ }
+ bufq_drain(dksc->sc_bufq);
+ mutex_exit(&dksc->sc_iolock);
+}
+
int
dk_discard(struct dk_softc *dksc, dev_t dev, off_t pos, off_t len)
{
diff -r 49f1cf2fdc6e -r 08f3a7d7f4c7 sys/dev/dkvar.h
--- a/sys/dev/dkvar.h Thu Aug 27 03:20:13 2015 +0000
+++ b/sys/dev/dkvar.h Thu Aug 27 05:51:50 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dkvar.h,v 1.21 2015/08/16 18:00:03 mlelstv Exp $ */
+/* $NetBSD: dkvar.h,v 1.22 2015/08/27 05:51:50 mlelstv Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -47,6 +47,7 @@
kmutex_t sc_iolock; /* protects buffer queue */
struct bufq_state *sc_bufq; /* buffer queue */
int sc_dtype; /* disk type */
+ struct buf *sc_deferred; /* retry after start failed */
};
/* sc_flags:
@@ -62,6 +63,7 @@
#define DKF_TAKEDUMP 0x00200000 /* allow dumping */
#define DKF_KLABEL 0x00400000 /* keep label on close */
#define DKF_VLABEL 0x00800000 /* label is valid */
+#define DKF_SLEEP 0x80000000 /* dk_start/dk_done may sleep */
/* Mask of flags that dksubr.c understands, other flags are fair game */
#define DK_FLAGMASK 0xffff0000
@@ -89,6 +91,7 @@
int dk_discard(struct dk_softc *, dev_t, off_t, off_t);
void dk_start(struct dk_softc *, struct buf *);
void dk_done(struct dk_softc *, struct buf *);
+void dk_drain(struct dk_softc *);
int dk_size(struct dk_softc *, dev_t);
int dk_ioctl(struct dk_softc *, dev_t,
u_long, void *, int, struct lwp *);
diff -r 49f1cf2fdc6e -r 08f3a7d7f4c7 sys/dev/ld.c
--- a/sys/dev/ld.c Thu Aug 27 03:20:13 2015 +0000
+++ b/sys/dev/ld.c Thu Aug 27 05:51:50 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ld.c,v 1.91 2015/08/18 04:20:25 mlelstv Exp $ */
+/* $NetBSD: ld.c,v 1.92 2015/08/27 05:51:50 mlelstv Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.91 2015/08/18 04:20:25 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.92 2015/08/27 05:51:50 mlelstv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -197,8 +197,6 @@
mutex_enter(&sc->sc_mutex);
sc->sc_maxqueuecnt = 0;
- dk_detach(dksc);
-
while (sc->sc_queuecnt > 0) {
sc->sc_flags |= LDF_DRAIN;
cv_wait(&sc->sc_drain, &sc->sc_mutex);
@@ -224,11 +222,10 @@
Home |
Main Index |
Thread Index |
Old Index