Source-Changes-HG archive

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

[src/netbsd-1-5]: src/sys/nfs Pull up revision 1.52 (requested by fvdl):



details:   https://anonhg.NetBSD.org/src/rev/ab3c94cdf079
branches:  netbsd-1-5
changeset: 490338:ab3c94cdf079
user:      he <he%NetBSD.org@localhost>
date:      Thu Dec 14 23:37:02 2000 +0000

description:
Pull up revision 1.52 (requested by fvdl):
  Improve NFS performance, possibly with as much as 100% in
  throughput.  Please note: this implies a kernel interface change,
  VOP_FSYNC gains two arguments.

diffstat:

 sys/nfs/nfs_bio.c |  106 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 87 insertions(+), 19 deletions(-)

diffs (164 lines):

diff -r 4007def55656 -r ab3c94cdf079 sys/nfs/nfs_bio.c
--- a/sys/nfs/nfs_bio.c Thu Dec 14 23:36:59 2000 +0000
+++ b/sys/nfs/nfs_bio.c Thu Dec 14 23:37:02 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_bio.c,v 1.49 2000/05/18 08:34:26 pk Exp $  */
+/*     $NetBSD: nfs_bio.c,v 1.49.4.1 2000/12/14 23:37:02 he Exp $      */
 
 /*
  * Copyright (c) 1989, 1993
@@ -727,7 +727,15 @@
                 * Since this block is being modified, it must be written
                 * again and not just committed.
                 */
-               bp->b_flags &= ~B_NEEDCOMMIT;
+               if (NFS_ISV3(vp)) {
+                       lockmgr(&np->n_commitlock, LK_EXCLUSIVE, NULL);
+                       if (bp->b_flags & B_NEEDCOMMIT) {
+                               bp->b_flags &= ~B_NEEDCOMMIT;
+                               nfs_del_tobecommitted_range(vp, bp);
+                       }
+                       nfs_del_committed_range(vp, bp);
+                       lockmgr(&np->n_commitlock, LK_RELEASE, NULL);
+               }
 
                /*
                 * If the lease is non-cachable or IO_SYNC do bwrite().
@@ -745,8 +753,7 @@
                } else if ((n + on) == biosize &&
                        (nmp->nm_flag & NFSMNT_NQNFS) == 0) {
                        bp->b_proc = (struct proc *)0;
-                       bp->b_flags |= B_ASYNC;
-                       (void)nfs_writebp(bp, 0);
+                       bawrite(bp);
                } else {
                        bdwrite(bp);
                }
@@ -958,9 +965,12 @@
        struct vnode *vp;
        struct nfsnode *np;
        struct nfsmount *nmp;
-       int error = 0, diff, len, iomode, must_commit = 0, s;
+       int error = 0, diff, len, iomode, must_commit = 0, s, retv = 0;
+       int pushedrange;
+       unsigned cnt;
        struct uio uio;
        struct iovec io;
+       off_t off;
 
        vp = bp->b_vp;
        np = VTONFS(vp);
@@ -1067,6 +1077,61 @@
                bp->b_error = error;
            }
        } else {
+           /*
+            * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
+            * an actual write will have to be scheduled.
+            */
+           if (bp->b_flags & B_NEEDCOMMIT) {
+               /*
+                * If the buffer is in the range that we already committed,
+                * there's nothing to do.
+                *
+                * If it's in the range that we need to commit, push the
+                * whole range at once. Else only push the buffer. In
+                * both these cases, acquire the commit lock to avoid
+                * other processes modifying the range. Normally the
+                * vnode lock should have handled this, but there are
+                * no proper vnode locks for NFS yet (XXX).
+                */
+               lockmgr(&np->n_commitlock, LK_EXCLUSIVE, NULL);
+               if (!(bp->b_flags & B_NEEDCOMMIT)) {
+                       lockmgr(&np->n_commitlock, LK_RELEASE, NULL);
+                       goto dowrite;
+               }
+               if (!nfs_in_committed_range(vp, bp)) {
+                       if (nfs_in_tobecommitted_range(vp, bp)) {
+                               pushedrange = 1;
+                               off = np->n_pushlo;
+                               /* XXX will be too big if > 2G buffer cache */
+                               cnt = np->n_pushhi - np->n_pushlo;
+                       } else {
+                               pushedrange = 0;
+                               off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE;
+                               cnt = bp->b_dirtyend;
+                       }
+                       bp->b_flags |= B_WRITEINPROG;
+                       retv = nfs_commit(bp->b_vp, off, cnt,
+                           bp->b_wcred, bp->b_proc);
+
+                       bp->b_flags &= ~B_WRITEINPROG;
+                       if (retv == 0) {
+                               if (pushedrange) {
+                                       nfs_merge_commit_ranges(vp);
+                               }
+                               else
+                                       nfs_add_committed_range(vp, bp);
+                       }
+               }
+               lockmgr(&np->n_commitlock, LK_RELEASE, NULL);
+               if (!retv) {
+                       bp->b_resid = bp->b_dirtyoff = bp->b_dirtyend = 0;
+                       bp->b_flags &= ~B_NEEDCOMMIT;
+                       biodone(bp);
+                       return (0);
+               } else if (retv == NFSERR_STALEWRITEVERF)
+                       nfs_clearcommit(bp->b_vp->v_mount);
+           }
+dowrite:
            io.iov_len = uiop->uio_resid = bp->b_dirtyend
                - bp->b_dirtyoff;
            uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE
@@ -1078,18 +1143,23 @@
                iomode = NFSV3WRITE_UNSTABLE;
            else
                iomode = NFSV3WRITE_FILESYNC;
+
            bp->b_flags |= B_WRITEINPROG;
-#ifdef fvdl_debug
-           printf("nfs_doio(%p): bp %p doff %d dend %d\n", 
-               vp, bp, bp->b_dirtyoff, bp->b_dirtyend);
-#endif
            error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit);
            s = splbio();
-           if (!error && iomode == NFSV3WRITE_UNSTABLE)
+           if (!error && iomode == NFSV3WRITE_UNSTABLE) {
                bp->b_flags |= B_NEEDCOMMIT;
-           else
+               lockmgr(&np->n_commitlock, LK_EXCLUSIVE, NULL);
+               nfs_add_tobecommitted_range(vp, bp);
+               lockmgr(&np->n_commitlock, LK_RELEASE, NULL);
+           } else if (!error && bp->b_flags & B_NEEDCOMMIT) {
                bp->b_flags &= ~B_NEEDCOMMIT;
-           bp->b_flags &= ~B_WRITEINPROG;
+               lockmgr(&np->n_commitlock, LK_EXCLUSIVE, NULL);
+               nfs_del_committed_range(vp, bp);
+               lockmgr(&np->n_commitlock, LK_RELEASE, NULL);
+           }
+           /* XXX the use of NOCACHE is a hack */
+           bp->b_flags &= ~(B_WRITEINPROG|B_NOCACHE);
 
            /*
             * For an interrupted write, the buffer is still valid and the
@@ -1105,15 +1175,13 @@
             */
            if (error == EINTR || (!error && (bp->b_flags & B_NEEDCOMMIT))) {
                bp->b_flags |= B_DELWRI;
-
                /*
-                * Since for the B_ASYNC case, nfs_bwrite() has reassigned the
-                * buffer to the clean list, we have to reassign it back to the
-                * dirty one. Ugh.
+                * A B_ASYNC block still needs to be committed, so put
+                * it back on the dirty list.
                 */
-               if (bp->b_flags & B_ASYNC) {
-                   reassignbuf(bp, vp);
-               } else if (error)
+               if (bp->b_flags & B_ASYNC)
+                       reassignbuf(bp, vp);
+               else if (error)
                    bp->b_flags |= B_EINTR;
            } else {
                if (error) {



Home | Main Index | Thread Index | Old Index