From: Matthew Dillon Date: Mon, 14 Jul 2008 17:45:49 +0000 (+0000) Subject: NFS performance fixes. X-Git-Tag: v2.1.1~904 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/a482a28a416459195cf2d1169045ac7170a48d20 NFS performance fixes. * 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. --- diff --git a/sys/vfs/nfs/nfs.h b/sys/vfs/nfs/nfs.h index c81156478e..9aeb797dc5 100644 --- a/sys/vfs/nfs/nfs.h +++ b/sys/vfs/nfs/nfs.h @@ -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; diff --git a/sys/vfs/nfs/nfs_bio.c b/sys/vfs/nfs/nfs_bio.c index 818e796a80..9305345dfb 100644 --- a/sys/vfs/nfs/nfs_bio.c +++ b/sys/vfs/nfs/nfs_bio.c @@ -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); } diff --git a/sys/vfs/nfs/nfs_serv.c b/sys/vfs/nfs/nfs_serv.c index ebddb36a1a..d8a3c884d0 100644 --- a/sys/vfs/nfs/nfs_serv.c +++ b/sys/vfs/nfs/nfs_serv.c @@ -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; diff --git a/sys/vfs/nfs/nfs_vfsops.c b/sys/vfs/nfs/nfs_vfsops.c index f116515a9c..9c35b4a5df 100644 --- a/sys/vfs/nfs/nfs_vfsops.c +++ b/sys/vfs/nfs/nfs_vfsops.c @@ -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; diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c index 2b5658ed4f..a05e57d03a 100644 --- a/sys/vfs/nfs/nfs_vnops.c +++ b/sys/vfs/nfs/nfs_vnops.c @@ -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;