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 revisions 1.120, 1.123 (requested by fvdl):



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

description:
Pull up revisions 1.120,1.123 (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_vnops.c |  292 +++++++++++----------------------------------------
 1 files changed, 67 insertions(+), 225 deletions(-)

diffs (truncated from 375 to 300 lines):

diff -r 6dafb810da3f -r 5319543235e6 sys/nfs/nfs_vnops.c
--- a/sys/nfs/nfs_vnops.c       Thu Dec 14 23:37:15 2000 +0000
+++ b/sys/nfs/nfs_vnops.c       Thu Dec 14 23:37:18 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_vnops.c,v 1.113.4.2 2000/09/19 18:43:15 fvdl Exp $ */
+/*     $NetBSD: nfs_vnops.c,v 1.113.4.3 2000/12/14 23:37:18 he Exp $   */
 
 /*
  * Copyright (c) 1989, 1993
@@ -1693,7 +1693,7 @@
         * doesn't get "out of sync" with the server.
         * XXX There should be a better way!
         */
-       VOP_FSYNC(vp, cnp->cn_cred, FSYNC_WAIT, cnp->cn_proc);
+       VOP_FSYNC(vp, cnp->cn_cred, FSYNC_WAIT, 0, 0, cnp->cn_proc);
 
        v3 = NFS_ISV3(vp);
        nfsstats.rpccnt[NFSPROC_LINK]++;
@@ -2590,7 +2590,7 @@
 nfs_commit(vp, offset, cnt, cred, procp)
        struct vnode *vp;
        u_quad_t offset;
-       int cnt;
+       unsigned cnt;
        struct ucred *cred;
        struct proc *procp;
 {
@@ -2601,6 +2601,11 @@
        caddr_t bpos, dpos, cp2;
        int error = 0, wccflag = NFSV3_WCCRATTR;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+
+#ifdef fvdl_debug
+       printf("commit %lu - %lu\n", (unsigned long)offset,
+           (unsigned long)(offset + cnt));
+#endif
        
        if ((nmp->nm_iflag & NFSMNT_HASWRITEVERF) == 0)
                return (0);
@@ -2727,6 +2732,8 @@
                struct vnode * a_vp;
                struct ucred * a_cred;
                int  a_flags;
+               off_t offlo;
+               off_t offhi;
                struct proc * a_p;
        } */ *ap = v;
 
@@ -2738,6 +2745,13 @@
  * Flush all the blocks associated with a vnode.
  *     Walk through the buffer pool and push any dirty pages
  *     associated with the vnode.
+ *
+ *     Don't bother to cluster commits; the commitrange code will
+ *     do that. In the first pass, push all dirty buffers to the
+ *     server, using stable writes if commit is set to 1.
+ *     In the 2nd pass, push anything that might be left,
+ *     i.e. the buffer was busy in the first pass, or it wasn't
+ *     committed in the first pass.
  */
 int
 nfs_flush(vp, cred, waitfor, p, commit)
@@ -2748,172 +2762,74 @@
        int commit;
 {
        struct nfsnode *np = VTONFS(vp);
+       struct nfsmount *nmp = VFSTONFS(vp->v_mount);
        struct buf *bp;
-       int i;
        struct buf *nbp;
-       struct nfsmount *nmp = VFSTONFS(vp->v_mount);
-       int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
-       int passone = 1;
-       u_quad_t off, endoff, toff;
-       struct ucred* wcred;
-#ifndef NFS_COMMITBVECSIZ
-#define NFS_COMMITBVECSIZ      20
-#endif
-       struct buf *bvec[NFS_COMMITBVECSIZ];
+       int pass, s, error, slpflag, slptimeo;
 
-       if (nmp->nm_flag & NFSMNT_INT)
-               slpflag = PCATCH;
-       if (!commit)
-               passone = 0;
-       /*
-        * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
-        * server, but nas not been committed to stable storage on the server
-        * yet. On the first pass, the byte range is worked out and the commit
-        * rpc is done. On the second pass, nfs_writebp() is called to do the
-        * job.
-        */
-again:
-       bvecpos = 0;
-       off = (u_quad_t)-1;
-       endoff = 0;
-       wcred = NULL;
-       if (NFS_ISV3(vp) && commit) {
-               s = splbio();
-               for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
-                       nbp = bp->b_vnbufs.le_next;
-                       if (bvecpos >= NFS_COMMITBVECSIZ)
-                               break;
-                       if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
-                               != (B_DELWRI | B_NEEDCOMMIT))
-                               continue;
-                       bremfree(bp);
-                       /*
-                        * Work out if all buffers are using the same cred
-                        * so we can deal with them all with one commit.
-                        */
-                       if (wcred == NULL)
-                               wcred = bp->b_wcred;
-                       else if (wcred != bp->b_wcred)
-                               wcred = NOCRED;
-                       bp->b_flags |= (B_BUSY | B_WRITEINPROG);
-                       /*
-                        * A list of these buffers is kept so that the
-                        * second loop knows which buffers have actually
-                        * been committed. This is necessary, since there
-                        * may be a race between the commit rpc and new
-                        * uncommitted writes on the file.
-                        */
-                       bvec[bvecpos++] = bp;
-                       toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
-                               bp->b_dirtyoff;
-                       if (toff < off)
-                               off = toff;
-                       toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
-                       if (toff > endoff)
-                               endoff = toff;
-               }
-               splx(s);
-       }
-       if (bvecpos > 0) {
-               /*
-                * Commit data on the server, as required.
-                * If all bufs are using the same wcred, then use that with
-                * one call for all of them, otherwise commit each one
-                * separately.
-                */
-               if (wcred != NOCRED)
-                       retv = nfs_commit(vp, off, (int)(endoff - off),
-                                         wcred, p);
-               else {
-                       retv = 0;
-                       for (i = 0; i < bvecpos; i++) {
-                               off_t off, size;
-                               bp = bvec[i];
-                               off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
-                                       bp->b_dirtyoff;
-                               size = (u_quad_t)(bp->b_dirtyend
-                                                 - bp->b_dirtyoff);
-                               retv = nfs_commit(vp, off, (int)size,
-                                                 bp->b_wcred, p);
-                               if (retv) break;
-                       }
-               }
-
-               if (retv == NFSERR_STALEWRITEVERF)
-                       nfs_clearcommit(vp->v_mount);
-               /*
-                * Now, either mark the blocks I/O done or mark the
-                * blocks dirty, depending on whether the commit
-                * succeeded.
-                */
-               for (i = 0; i < bvecpos; i++) {
-                       bp = bvec[i];
-                       bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG);
-                       if (retv)
-                           brelse(bp);
-                       else {
-                           s = splbio();
-                           vp->v_numoutput++;
-                           bp->b_flags |= B_ASYNC;
-                           bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
-                           bp->b_dirtyoff = bp->b_dirtyend = 0;
-                           reassignbuf(bp, vp);
-                           splx(s);
-                           biodone(bp);
-                       }
-               }
-
-               /*
-                * If there may be more uncommitted buffer, try to
-                * commit them unless write verf isn't changed.
-                */
-               if (retv != NFSERR_STALEWRITEVERF &&
-                   bvecpos == NFS_COMMITBVECSIZ)
-                       goto again;
-       }
-
-       /*
-        * Start/do any write(s) that are required.
-        */
+       pass = 1;
+       error = 0;
+       slptimeo = 0;
+       slpflag = nmp->nm_flag & NFSMNT_INT ? PCATCH : 0;
 loop:
        s = splbio();
        for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
                nbp = bp->b_vnbufs.le_next;
                if (bp->b_flags & B_BUSY) {
-                       if (waitfor != MNT_WAIT || passone)
+                       if (pass == 2 && waitfor == MNT_WAIT) {
+                               bp->b_flags |= B_WANTED;
+                               error = tsleep((caddr_t)bp,
+                                   slpflag | (PRIBIO + 1),
+                                   "nfsfsync", slptimeo);
+                               splx(s);
+                               if (error) {
+                                   if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
+                                       return (EINTR);
+                                   if (slpflag == PCATCH) {
+                                       slpflag = 0;
+                                       slptimeo = 2 * hz;
+                                   }
+                               }
+                               goto loop;
+                       } else
                                continue;
-                       bp->b_flags |= B_WANTED;
-                       error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
-                               "nfsfsync", slptimeo);
-                       splx(s);
-                       if (error) {
-                           if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
-                               return (EINTR);
-                           if (slpflag == PCATCH) {
-                               slpflag = 0;
-                               slptimeo = 2 * hz;
-                           }
-                       }
-                       goto loop;
                }
+#ifdef DIAGNOSTIC
                if ((bp->b_flags & B_DELWRI) == 0)
                        panic("nfs_fsync: not dirty");
-               if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT))
+#endif
+               if (!commit && (bp->b_flags & B_NEEDCOMMIT))
                        continue;
+               /*
+                * Note: can't use B_VFLUSH here, since there is no
+                * real vnode lock, so we can't leave the buffer on
+                * the freelist.
+                */
                bremfree(bp);
-               if (passone || !commit)
-                   bp->b_flags |= (B_BUSY|B_ASYNC);
-               else
-                   bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
+               if (commit)
+                       /*
+                        * Setting B_NOCACHE has the effect
+                        * effect of nfs_doio using a stable write
+                        * RPC. XXX this abuses the B_NOCACHE flag,
+                        * but it is needed to tell nfs_strategy
+                        * that this buffer is async, but needs to
+                        * be written with a stable RPC. nfs_doio
+                        * will remove B_NOCACHE again.
+                        */
+                       bp->b_flags |= B_NOCACHE;
+
+               bp->b_flags |= B_BUSY | B_ASYNC;
                splx(s);
                VOP_BWRITE(bp);
                goto loop;
        }
        splx(s);
-       if (passone) {
-               passone = 0;
-               goto again;
+
+       if (commit && pass == 1) {
+               pass = 2;
+               goto loop;
        }
+
        if (waitfor == MNT_WAIT) {
                s = splbio();
                while (vp->v_numoutput) {
@@ -3125,7 +3041,7 @@
 }
 
 /*
- * Just call nfs_writebp() with the force argument set to 1.
+ * Just call bwrite().
  */
 int
 nfs_bwrite(v)
@@ -3135,81 +3051,7 @@
                struct vnode *a_bp;
        } */ *ap = v;
 
-       return (nfs_writebp(ap->a_bp, 1));
-}
-
-/*



Home | Main Index | Thread Index | Old Index