Date: Tue, 30 Jul 1996 13:28:11 +0100 (BST) From: Doug Rabson <dfr@render.com> To: freebsd-current@freebsd.org Subject: NFS fixes for review Message-ID: <Pine.BSI.3.95.960730131214.11210E-100000@minnow.render.com>
next in thread | raw e-mail | index | archive | help
I have some fixes for NFSv3 in -current but I thought it would be a good idea run them through a reviewer or two: 1. Use the B_CLUSTEROK flag in nfs_doio() to allow multiple buffers to be committed with a single rpc. 2. Fix readdirplus in the NFSv3 server so that it is not totally broken. 3. Some extremely primitive support for NFSv3 async mode which would ignore the stability status from the server and always assume that the data was stably written. This can improve performance for a client because it reduces pressure on the buffer cache since it doesn't have to keep B_DELWRI|B_NEEDCOMMIT buffers around. This should probably also attempt a commit rpc in nfs_flush (implementation of VOP_FSYNC) but the patch does not include this. To use this support, a trivial change to mount_nfs is also needed to allow the async option to be used for NFS mounts. 4. Use a dynamically sized array to coalesce commit requests in nfs_flush() instead of a fixed size stack buffer. This can improve performance for copying large files over NFSv3 since it reduces the number of commit rpcs sent over the wire. 5. Fix a precedence error in nfs_writebp() which prevented proper handling of B_DELWRI|B_NEEDCOMMIT buffers. Also add relavent VMIO calls to make this code actually work. This part has already been reviewed by Rick Macklem. 6. Add some debug printfs to make my life easier. 7. Import a minor fix from NetBSD to supply a definition of the NFSv3 mount protocol version. This is required for some NetBSD fixes to mount_nfs which I will commit seperately. Index: nfs_bio.c =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfs_bio.c,v retrieving revision 1.24 diff -u -r1.24 nfs_bio.c --- nfs_bio.c 1996/07/16 10:19:43 1.24 +++ nfs_bio.c 1996/07/23 12:37:44 @@ -905,9 +905,11 @@ iomode = NFSV3WRITE_FILESYNC; bp->b_flags |= B_WRITEINPROG; error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit); - if (!error && iomode == NFSV3WRITE_UNSTABLE) + if (!error && iomode == NFSV3WRITE_UNSTABLE) { bp->b_flags |= B_NEEDCOMMIT; - else + if (bp->b_dirtyoff == 0 && bp->b_dirtyend == bp->b_bufsize) + bp->b_flags |= B_CLUSTEROK; + } else bp->b_flags &= ~B_NEEDCOMMIT; bp->b_flags &= ~B_WRITEINPROG; Index: nfs_serv.c =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfs_serv.c,v retrieving revision 1.30 diff -u -r1.30 nfs_serv.c --- nfs_serv.c 1996/06/08 12:16:26 1.30 +++ nfs_serv.c 1996/07/25 14:34:18 @@ -2919,6 +2919,7 @@ nfsm_srvpostop_attr(getret, &at); return (0); } + vput(nvp); dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; nfsm_reply(cnt); Index: nfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfs_vnops.c,v retrieving revision 1.34 diff -u -r1.34 nfs_vnops.c --- nfs_vnops.c 1996/07/16 10:19:45 1.34 +++ nfs_vnops.c 1996/07/23 12:39:28 @@ -1210,7 +1210,10 @@ tsiz -= len; } nfsmout: - *iomode = committed; + if (vp->v_mount->mnt_flag & MNT_ASYNC) + *iomode = NFSV3WRITE_FILESYNC; + else + *iomode = committed; if (error) uiop->uio_resid = tsiz; return (error); @@ -2607,6 +2610,9 @@ int error = 0, wccflag = NFSV3_WCCRATTR; struct mbuf *mreq, *mrep, *md, *mb, *mb2; +#ifdef NFS_DEBUG + printf("nfs_commit(%x, %d, %d, %x, %x)\n", vp, (int) offset, cnt, cred, procp); +#endif if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) return (0); nfsstats.rpccnt[NFSPROC_COMMIT]++; @@ -2757,13 +2763,14 @@ struct nfsmount *nmp = VFSTONFS(vp->v_mount); int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; int passone = 1; - u_quad_t off = (u_quad_t)-1, endoff = 0, toff; + u_quad_t off, endoff, toff; struct ucred* wcred = NULL; -#ifndef NFS_COMMITBVECSIZ -#define NFS_COMMITBVECSIZ 20 -#endif - struct buf *bvec[NFS_COMMITBVECSIZ]; + struct buf **bvec = NULL; + int bvecsize = 0, bveccount; +#ifdef NFS_DEBUG + printf("nfs_flush(%x, %x, %d, %x, %d)\n", vp, cred, waitfor, p, commit); +#endif if (nmp->nm_flag & NFSMNT_INT) slpflag = PCATCH; if (!commit) @@ -2776,12 +2783,41 @@ * job. */ again: + off = (u_quad_t)-1; + endoff = 0; bvecpos = 0; if (NFS_ISV3(vp) && commit) { s = splbio(); + /* + * Count up how many buffers waiting for a commit. + */ + bveccount = 0; + for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { + nbp = bp->b_vnbufs.le_next; + if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) + == (B_DELWRI | B_NEEDCOMMIT)) + bveccount++; + } + /* + * Allocate space to remember the list of bufs to commit. It is + * important to use M_NOWAIT here to avoid a race with nfs_write. + * If we can't get memory (for whatever reason), we will end up + * committing the buffers one-by-one in the loop below. + */ + if (bveccount > bvecsize) { + if (bvec != NULL) + free(bvec, M_TEMP); + bvec = (struct buf **) + malloc(bveccount * sizeof(struct buf *), + M_TEMP, M_NOWAIT); + if (bvec == NULL) + bvecsize = 0; + else + bvecsize = bveccount; + } for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { nbp = bp->b_vnbufs.le_next; - if (bvecpos >= NFS_COMMITBVECSIZ) + if (bvecpos >= bvecsize) break; if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) != (B_DELWRI | B_NEEDCOMMIT)) @@ -2822,10 +2858,14 @@ * one call for all of them, otherwise commit each one * separately. */ - if (wcred != NOCRED) + if (wcred != NOCRED) { +#ifdef NFS_DEBUG +printf("nfs_flush: calling nfs_commit(%x, %d, %d, %x, %x)\n", + vp, (int) off, (int) (endoff - off), wcred, p); +#endif retv = nfs_commit(vp, off, (int)(endoff - off), wcred, p); - else { + } else { retv = 0; for (i = 0; i < bvecpos; i++) { off_t off, size; @@ -2879,8 +2919,10 @@ "nfsfsync", slptimeo); splx(s); if (error) { - if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) - return (EINTR); + if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { + error = EINTR; + goto done; + } if (slpflag == PCATCH) { slpflag = 0; slptimeo = 2 * hz; @@ -2892,6 +2934,9 @@ panic("nfs_fsync: not dirty"); if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) continue; +#ifdef NFS_DEBUG +printf("nfs_flush: writing bp=%x, bp->b_flags=%x\n", bp, bp->b_flags); +#endif bremfree(bp); if (passone || !commit) bp->b_flags |= (B_BUSY|B_ASYNC); @@ -2912,8 +2957,10 @@ error = tsleep((caddr_t)&vp->v_numoutput, slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); if (error) { - if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) - return (EINTR); + if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { + error = EINTR; + goto done; + } if (slpflag == PCATCH) { slpflag = 0; slptimeo = 2 * hz; @@ -2928,6 +2975,9 @@ error = np->n_error; np->n_flag &= ~NWRITEERR; } +done: + if (bvec) + free(bvec, M_TEMP); return (error); } @@ -3129,8 +3179,9 @@ * an actual write will have to be scheduled via. VOP_STRATEGY(). * If B_WRITEINPROG is already set, then push it with a write anyhow. */ - if (oldflags & (B_NEEDCOMMIT | B_WRITEINPROG) == B_NEEDCOMMIT) { + if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; + vfs_busy_pages(bp, 1); bp->b_flags |= B_WRITEINPROG; retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, bp->b_wcred, bp->b_proc); @@ -3139,8 +3190,10 @@ bp->b_dirtyoff = bp->b_dirtyend = 0; bp->b_flags &= ~B_NEEDCOMMIT; biodone(bp); - } else if (retv == NFSERR_STALEWRITEVERF) + } else if (retv == NFSERR_STALEWRITEVERF) { nfs_clearcommit(bp->b_vp->v_mount); + vfs_unbusy_pages(bp); + } } if (retv) { if (force) Index: nfsnode.h =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfsnode.h,v retrieving revision 1.15 diff -u -r1.15 nfsnode.h --- nfsnode.h 1995/12/17 21:12:37 1.15 +++ nfsnode.h 1996/07/30 11:55:07 @@ -137,7 +137,7 @@ #define NUPD 0x0200 /* Special file updated */ #define NCHG 0x0400 /* Special file times changed */ #define NLOCKED 0x0800 /* node is locked */ -#define NWANTED 0x0100 /* someone wants to lock */ +#define NWANTED 0x1000 /* someone wants to lock */ /* * Convert between nfsnode pointers and vnode pointers Index: rpcv2.h =================================================================== RCS file: /home/ncvs/src/sys/nfs/rpcv2.h,v retrieving revision 1.4 diff -u -r1.4 rpcv2.h --- rpcv2.h 1995/06/27 11:07:02 1.4 +++ rpcv2.h 1996/07/17 14:16:14 @@ -90,6 +90,7 @@ /* RPC Prog definitions */ #define RPCPROG_MNT 100005 #define RPCMNT_VER1 1 +#define RPCMNT_VER3 3 #define RPCMNT_MOUNT 1 #define RPCMNT_DUMP 2 #define RPCMNT_UMOUNT 3 -- Doug Rabson, Microsoft RenderMorphics Ltd. Mail: dfr@render.com Phone: +44 171 251 4411 FAX: +44 171 251 0939
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSI.3.95.960730131214.11210E-100000>