Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-6]: src/sys/dev Pull up following revision(s) (requested by bouye...
details: https://anonhg.NetBSD.org/src/rev/5afe4910159f
branches: netbsd-6
changeset: 776888:5afe4910159f
user: snj <snj%NetBSD.org@localhost>
date: Wed Feb 04 04:18:23 2015 +0000
description:
Pull up following revision(s) (requested by bouyer in ticket #1242):
sys/dev/vnd.c: revision 1.240, 1.241
As discussed in
http://mail-index.netbsd.org/tech-kern/2015/01/24/msg018339.html
don't bump v_numoutput if we need to vn_lock() the vnode before queuing
the corresponding I/O, because this may deadlock with genfs_do_putpages()
when called with the vnode locked (as can happen with fsync(2)).
Instead bump is just before the last VOP_STRATEGY(), or before calling
nestiobuf_done().
Thanks to Taylor R Campbell for review.
--
Fix typo in comment
diffstat:
sys/dev/vnd.c | 40 +++++++++++++++++++++++++++++-----------
1 files changed, 29 insertions(+), 11 deletions(-)
diffs (82 lines):
diff -r a6b6bbaa240b -r 5afe4910159f sys/dev/vnd.c
--- a/sys/dev/vnd.c Mon Jan 26 14:04:22 2015 +0000
+++ b/sys/dev/vnd.c Wed Feb 04 04:18:23 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vnd.c,v 1.219.8.2 2012/07/05 18:12:46 riz Exp $ */
+/* $NetBSD: vnd.c,v 1.219.8.3 2015/02/04 04:18:23 snj Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.219.8.2 2012/07/05 18:12:46 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.219.8.3 2015/02/04 04:18:23 snj Exp $");
#if defined(_KERNEL_OPT)
#include "opt_vnd.h"
@@ -782,15 +782,10 @@
size_t resid, sz;
off_t bn, offset;
struct vnode *vp;
+ struct buf *nbp = NULL;
flags = obp->b_flags;
- if (!(flags & B_READ)) {
- vp = bp->b_vp;
- mutex_enter(vp->v_interlock);
- vp->v_numoutput++;
- mutex_exit(vp->v_interlock);
- }
/* convert to a byte offset within the file. */
bn = obp->b_rawblkno * vnd->sc_dkdev.dk_label->d_secsize;
@@ -807,9 +802,8 @@
*/
error = 0;
bp->b_resid = bp->b_bcount;
- for (offset = 0, resid = bp->b_resid; resid;
+ for (offset = 0, resid = bp->b_resid; /* true */;
resid -= sz, offset += sz) {
- struct buf *nbp;
daddr_t nbn;
int off, nra;
@@ -862,10 +856,34 @@
nbp->vb_buf.b_flags, nbp->vb_buf.b_data,
nbp->vb_buf.b_bcount);
#endif
+ if (resid == sz) {
+ break;
+ }
VOP_STRATEGY(vp, nbp);
bn += sz;
}
- nestiobuf_done(bp, skipped, error);
+ if (!(flags & B_READ)) {
+ struct vnode *w_vp;
+ /*
+ * this is the last nested buf, account for
+ * the parent buf write too.
+ * This has to be done last, so that
+ * fsync won't wait for this write which
+ * has no chance to complete before all nested bufs
+ * have been queued. But it has to be done
+ * before the last VOP_STRATEGY()
+ * or the call to nestiobuf_done().
+ */
+ w_vp = bp->b_vp;
+ mutex_enter(w_vp->v_interlock);
+ w_vp->v_numoutput++;
+ mutex_exit(w_vp->v_interlock);
+ }
+ KASSERT(skipped != 0 || nbp != NULL);
+ if (skipped)
+ nestiobuf_done(bp, skipped, error);
+ else
+ VOP_STRATEGY(vp, nbp);
}
static void
Home |
Main Index |
Thread Index |
Old Index