NFS performance fixes.
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 14 Jul 2008 17:45:49 +0000 (17:45 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 14 Jul 2008 17:45:49 +0000 (17:45 +0000)
* sync on an NFS mount was a big NOP due to a silly bug.

* utimes (setattr w/ mtime-changed) was unconditionally flushing the file,
  causing programs such as cpdup, rsync, rdist, and tar xp to sync on each
  file.

  change it so it does not unconditionally flush the file.

sys/vfs/nfs/nfs.h
sys/vfs/nfs/nfs_bio.c
sys/vfs/nfs/nfs_serv.c
sys/vfs/nfs/nfs_vfsops.c
sys/vfs/nfs/nfs_vnops.c

index c811564..9aeb797 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs.h       8.4 (Berkeley) 5/1/95
  * $FreeBSD: src/sys/nfs/nfs.h,v 1.53.2.5 2002/02/20 01:35:34 iedowse Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs.h,v 1.19 2006/12/23 00:41:29 swildner Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs.h,v 1.20 2008/07/14 17:45:49 dillon Exp $
  */
 
 #ifndef _NFS_NFS_H_
@@ -305,6 +305,7 @@ extern vm_zone_t nfsmount_zone;
 #endif
 
 extern struct callout nfs_timer_handle;
+extern int nfs_async;
 
 struct uio;
 struct buf;
index 818e796..9305345 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_bio.c   8.9 (Berkeley) 3/30/95
  * $FreeBSD: /repoman/r/ncvs/src/sys/nfsclient/nfs_bio.c,v 1.130 2004/04/14 23:23:55 peadar Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_bio.c,v 1.43 2008/04/22 18:46:53 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_bio.c,v 1.44 2008/07/14 17:45:49 dillon Exp $
  */
 
 
@@ -1045,6 +1045,11 @@ again:
                 *
                 * IO_INVAL appears to be unused.  The idea appears to be
                 * to turn off caching in this case.  Very odd.  XXX
+                *
+                * If nfs_async is set bawrite() will use an unstable write
+                * (build dirty bufs on the server), so we might as well
+                * push it out with bawrite().  If nfs_async is not set we
+                * use bdwrite() to cache dirty bufs on the client.
                 */
                if ((np->n_flag & NDONTCACHE) || (ioflag & IO_SYNC)) {
                        if (ioflag & IO_INVAL)
@@ -1057,9 +1062,8 @@ again:
                                if (error)
                                        break;
                        }
-               } else if ((n + on) == biosize) {
-                       bp->b_flags |= B_ASYNC;
-                       bwrite(bp);
+               } else if ((n + on) == biosize && nfs_async) {
+                       bawrite(bp);
                } else {
                        bdwrite(bp);
                }
index ebddb36..d8a3c88 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
  * $FreeBSD: src/sys/nfs/nfs_serv.c,v 1.93.2.6 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.46 2007/11/20 21:36:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.47 2008/07/14 17:45:49 dillon Exp $
  */
 
 /*
@@ -134,7 +134,7 @@ static struct timespec      nfsver;
 
 SYSCTL_DECL(_vfs_nfs);
 
-static int nfs_async;
+int nfs_async;
 SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
 static int nfs_commit_blks;
 static int nfs_commit_miss;
index f116515..9c35b4a 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_vfsops.c        8.12 (Berkeley) 5/20/95
  * $FreeBSD: src/sys/nfs/nfs_vfsops.c,v 1.91.2.7 2003/01/27 20:04:08 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.51 2007/09/04 00:48:18 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.52 2008/07/14 17:45:49 dillon Exp $
  */
 
 #include "opt_bootp.h"
@@ -1130,7 +1130,7 @@ nfs_sync(struct mount *mp, int waitfor)
        struct scaninfo scaninfo;
        int error;
 
-       scaninfo.rescan = 0;
+       scaninfo.rescan = 1;
        scaninfo.waitfor = waitfor;
        scaninfo.allerror = 0;
 
index 2b5658e..a05e57d 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
  * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.77 2008/06/08 08:38:06 sephe Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.78 2008/07/14 17:45:49 dillon Exp $
  */
 
 
@@ -226,6 +226,10 @@ int nfs_numasync = 0;
 
 SYSCTL_DECL(_vfs_nfs);
 
+static int nfs_flush_on_rename = 1;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, flush_on_rename, CTLFLAG_RW, 
+          &nfs_flush_on_rename, 0, "flush fvp prior to rename");
+
 static int     nfsaccess_cache_timeout = NFS_DEFATTRTIMO;
 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW, 
           &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
@@ -670,7 +674,11 @@ nfs_setattr(struct vop_setattr_args *ap)
            vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
            (vp->v_mount->mnt_flag & MNT_RDONLY))
                return (EROFS);
+
        if (vap->va_size != VNOVAL) {
+               /*
+                * truncation requested
+                */
                switch (vp->v_type) {
                case VDIR:
                        return (EISDIR);
@@ -729,12 +737,26 @@ again:
                        np->n_vattr.va_size = vap->va_size;
                        break;
                }
-       } else if ((vap->va_mtime.tv_sec != VNOVAL ||
-               vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NLMODIFIED) &&
-               vp->v_type == VREG &&
-               (error = nfs_vinvalbuf(vp, V_SAVE, 1)) == EINTR
-       ) {
-               return (error);
+       } else if ((np->n_flag & NLMODIFIED) && vp->v_type == VREG) {
+               /*
+                * What to do.  If we are modifying the mtime we lose
+                * mtime detection of changes made by the server or other
+                * clients.  But programs like rsync/rdist/cpdup are going
+                * to call utimes a lot.  We don't want to piecemeal sync.
+                *
+                * For now sync if any prior remote changes were detected,
+                * but allow us to lose track of remote changes made during
+                * the utimes operation.
+                */
+               if (np->n_flag & NRMODIFIED)
+                       error = nfs_vinvalbuf(vp, V_SAVE, 1);
+               if (error == EINTR)
+                       return (error);
+               if (error == 0) {
+                       if (vap->va_mtime.tv_sec != VNOVAL) {
+                               np->n_mtime = vap->va_mtime.tv_sec;
+                       }
+               }
        }
        error = nfs_setattrrpc(vp, vap, ap->a_cred, td);
 
@@ -1700,15 +1722,14 @@ nfs_rename(struct vop_old_rename_args *ap)
        }
 
        /*
-        * We have to flush B_DELWRI data prior to renaming
-        * the file.  If we don't, the delayed-write buffers
-        * can be flushed out later after the file has gone stale
-        * under NFSV3.  NFSV2 does not have this problem because
-        * ( as far as I can tell ) it flushes dirty buffers more
-        * often.
+        * We shouldn't have to flush fvp on rename as the file handle should
+        * not change, but the default is to do so.
+        *
+        * We must flush tvp on rename because it might become stale on the
+        * server after the rename.
         */
-
-       VOP_FSYNC(fvp, MNT_WAIT);
+       if (nfs_flush_on_rename)
+           VOP_FSYNC(fvp, MNT_WAIT);
        if (tvp)
            VOP_FSYNC(tvp, MNT_WAIT);
 
@@ -3053,9 +3074,8 @@ nfs_flush_bp(struct buf *bp, void *data)
                        }
                        bremfree(bp);
 
-                       bp->b_flags |= B_ASYNC;
                        crit_exit();
-                       bwrite(bp);
+                       bawrite(bp);
                } else {
                        crit_exit();
                        error = 0;