Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-7]: src/sys/dev Pull up following revision(s) (requested by bouye...



details:   https://anonhg.NetBSD.org/src/rev/7b4ecacae8cf
branches:  netbsd-7
changeset: 798919:7b4ecacae8cf
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Jan 28 19:16:21 2015 +0000

description:
Pull up following revision(s) (requested by bouyer in ticket #468):
        sys/dev/vnd.c: revision 1.240
        sys/dev/vnd.c: revision 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 ee635f182407 -r 7b4ecacae8cf sys/dev/vnd.c
--- a/sys/dev/vnd.c     Wed Jan 28 19:00:28 2015 +0000
+++ b/sys/dev/vnd.c     Wed Jan 28 19:16:21 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vnd.c,v 1.232.2.2 2014/11/11 10:42:22 martin Exp $     */
+/*     $NetBSD: vnd.c,v 1.232.2.3 2015/01/28 19:16:21 martin 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.232.2.2 2014/11/11 10:42:22 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.232.2.3 2015/01/28 19:16:21 martin Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_vnd.h"
@@ -795,15 +795,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;
@@ -820,9 +815,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;
 
@@ -875,10 +869,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