summaryrefslogtreecommitdiffstats
path: root/sys/nfs/nfs_serv.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1999-09-17 05:57:57 +0000
committerdillon <dillon@FreeBSD.org>1999-09-17 05:57:57 +0000
commit581716d4dfa79a615e2d311e2da0b1eca85bb5b6 (patch)
treeca5c480c585acbc3d10eb3b4ab470a7596253dbb /sys/nfs/nfs_serv.c
parent4c1e280de7db1d524317194a371a5d246f0f5cfa (diff)
downloadFreeBSD-src-581716d4dfa79a615e2d311e2da0b1eca85bb5b6.zip
FreeBSD-src-581716d4dfa79a615e2d311e2da0b1eca85bb5b6.tar.gz
Asynchronized client-side nfs_commit. NFS commit operations were
previously issued synchronously even if async daemons (nfsiod's) were available. The commit has been moved from the strategy code to the doio code in order to asynchronize it. Removed use of lastr in preparation for removal of vnode->v_lastr. It has been replaced with seqcount, which is already supported by the system and, in fact, gives us a better heuristic for sequential detection then lastr ever did. Made major performance improvements to the server side commit. The server previously fsync'd the entire file for each commit rpc. The server now bawrite()s only those buffers related to the offset/size specified in the commit rpc. Note that we do not commit the meta-data yet. This works still needs to be done. Note that a further optimization can be done (and has not yet been done) on the client: we can merge multiple potential commit rpc's into a single rpc with a greater file offset/size range and greatly reduce rpc traffic. Reviewed by: Alan Cox <alc@cs.rice.edu>, David Greenman <dg@root.com>
Diffstat (limited to 'sys/nfs/nfs_serv.c')
-rw-r--r--sys/nfs/nfs_serv.c75
1 files changed, 72 insertions, 3 deletions
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c
index a8ce893d..2c6a05f 100644
--- a/sys/nfs/nfs_serv.c
+++ b/sys/nfs/nfs_serv.c
@@ -96,6 +96,7 @@
#include <sys/stat.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
+#include <sys/buf.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -115,6 +116,8 @@
#define nfsdbprintf(info)
#endif
+#define MAX_COMMIT_COUNT (1024 * 1024)
+
nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
NFFIFO, NFNON };
#ifndef NFS_NOSERVER
@@ -133,6 +136,10 @@ SYSCTL_DECL(_vfs_nfs);
static 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;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, "");
+SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
static int nfsrv_access __P((struct vnode *,int,struct ucred *,int,
struct proc *, int));
@@ -3624,11 +3631,73 @@ nfsrv_commit(nfsd, slp, procp, mrq)
goto nfsmout;
}
for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
- if (vp->v_object &&
- (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
+
+ if (cnt > MAX_COMMIT_COUNT) {
+ /*
+ * Give up and do the whole thing
+ */
+ if (vp->v_object &&
+ (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
+ }
+ error = VOP_FSYNC(vp, cred, MNT_WAIT, procp);
+ } else {
+ /*
+ * Locate and synchronously write any buffers that fall
+ * into the requested range. Note: we are assuming that
+ * f_iosize is a power of 2.
+ */
+ int iosize = vp->v_mount->mnt_stat.f_iosize;
+ int iomask = iosize - 1;
+ int s;
+ daddr_t lblkno;
+
+ /*
+ * Align to iosize boundry, super-align to page boundry.
+ */
+ if (off & iomask) {
+ cnt += off & iomask;
+ off &= ~(u_quad_t)iomask;
+ }
+ if (off & PAGE_MASK) {
+ cnt += off & PAGE_MASK;
+ off &= ~(u_quad_t)PAGE_MASK;
+ }
+ lblkno = off / iosize;
+
+ if (vp->v_object &&
+ (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
+ vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
+ }
+
+ s = splbio();
+ while (cnt > 0) {
+ struct buf *bp;
+
+ /*
+ * If we have a buffer and it is marked B_DELWRI we
+ * have to lock and write it. Otherwise the prior
+ * write is assumed to have already been committed.
+ */
+ if ((bp = gbincore(vp, lblkno)) != NULL && (bp->b_flags & B_DELWRI)) {
+ if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
+ BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL);
+ continue; /* retry */
+ }
+ bremfree(bp);
+ bp->b_flags &= ~B_ASYNC;
+ VOP_BWRITE(bp->b_vp, bp);
+ ++nfs_commit_miss;
+ }
+ ++nfs_commit_blks;
+ if (cnt < iosize)
+ break;
+ cnt -= iosize;
+ ++lblkno;
+ }
+ splx(s);
}
- error = VOP_FSYNC(vp, cred, MNT_WAIT, procp);
+
aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
vput(vp);
vp = NULL;
OpenPOWER on IntegriCloud