From: Chuck Lever <cel@citi.umich.edu>

hi trond, andrew-

this patch adds a new NFS procedure to issue a synchronous commit RPC.  it 
uses a single argument of type nfs_write_data, just like the asynchronous 
commit logic does.  this is a requirement for supporting direct I/O.

diff -Naurp 23-write_offset/fs/nfs/nfs3proc.c 24-commit_proc/fs/nfs/nfs3proc.c


 fs/nfs/nfs3proc.c       |   24 ++++++++++++++++++++++++
 fs/nfs/nfs4proc.c       |   39 ++++++++++++++++++++++++++++++++++++++-
 include/linux/nfs_xdr.h |    3 +--
 3 files changed, 63 insertions(+), 3 deletions(-)

diff -puN fs/nfs/nfs3proc.c~nfs-O_DIRET-sync-commit-rpcs fs/nfs/nfs3proc.c
--- 25/fs/nfs/nfs3proc.c~nfs-O_DIRET-sync-commit-rpcs	2003-06-17 16:00:24.000000000 -0700
+++ 25-akpm/fs/nfs/nfs3proc.c	2003-06-17 16:00:24.000000000 -0700
@@ -272,6 +272,29 @@ nfs3_proc_write(struct nfs_write_data *w
 	return status < 0? status : wdata->res.count;
 }
 
+static int
+nfs3_proc_commit(struct nfs_write_data *cdata)
+{
+	struct inode *		inode = cdata->inode;
+	struct nfs_fattr *	fattr = cdata->res.fattr;
+	struct rpc_message	msg = {
+		.rpc_proc	= &nfs3_procedures[NFS3PROC_COMMIT],
+		.rpc_argp	= &cdata->args,
+		.rpc_resp	= &cdata->res,
+		.rpc_cred	= cdata->cred,
+	};
+	int			status;
+
+	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
+			(long long) cdata->args.offset);
+	fattr->valid = 0;
+	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	if (status >= 0)
+		nfs3_write_refresh_inode(inode, fattr);
+	dprintk("NFS reply commit: %d\n", status);
+	return status;
+}
+
 /*
  * Create a regular file.
  * For now, we don't implement O_EXCL.
@@ -832,6 +855,7 @@ struct nfs_rpc_ops	nfs_v3_clientops = {
 	.readlink	= nfs3_proc_readlink,
 	.read		= nfs3_proc_read,
 	.write		= nfs3_proc_write,
+	.commit		= nfs3_proc_commit,
 	.create		= nfs3_proc_create,
 	.remove		= nfs3_proc_remove,
 	.unlink_setup	= nfs3_proc_unlink_setup,
diff -puN fs/nfs/nfs4proc.c~nfs-O_DIRET-sync-commit-rpcs fs/nfs/nfs4proc.c
--- 25/fs/nfs/nfs4proc.c~nfs-O_DIRET-sync-commit-rpcs	2003-06-17 16:00:24.000000000 -0700
+++ 25-akpm/fs/nfs/nfs4proc.c	2003-06-17 16:00:24.000000000 -0700
@@ -1093,6 +1093,43 @@ nfs4_proc_write(struct nfs_write_data *w
 	return status;
 }
 
+static int
+nfs4_proc_commit(struct nfs_write_data *cdata)
+{
+	struct inode *inode = cdata->inode;
+	struct nfs_fattr *fattr = cdata->res.fattr;
+	nfs4_stateid *stateid = &cdata->args.stateid;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_shareowner *sp;
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
+		.rpc_argp	= &cdata->args,
+		.rpc_resp	= &cdata->res,
+		.rpc_cred	= cdata->cred,
+	};
+	int status;
+
+	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
+			(long long) cdata->args.offset);
+
+	/*
+	 * Try first to use O_WRONLY, then O_RDWR stateid.
+	 */
+	sp = nfs4_get_inode_share(inode, O_WRONLY);
+	if (!sp)
+		sp = nfs4_get_inode_share(inode, O_RDWR);
+
+	if (sp)
+		memcpy(stateid, sp->so_stateid, sizeof(nfs4_stateid));
+	else
+		memcpy(stateid, zero_stateid, sizeof(nfs4_stateid));
+
+	fattr->valid = 0;
+	status = rpc_call_sync(server->client, &msg, 0);
+	dprintk("NFS reply commit: %d\n", status);
+	return status;
+}
+
 /*
  * Got race?
  * We will need to arrange for the VFS layer to provide an atomic open.
@@ -1732,7 +1769,7 @@ struct nfs_rpc_ops	nfs_v4_clientops = {
 	.readlink	= nfs4_proc_readlink,
 	.read		= nfs4_proc_read,
 	.write		= nfs4_proc_write,
-	.commit		= NULL,
+	.commit		= nfs4_proc_commit,
 	.create		= nfs4_proc_create,
 	.remove		= nfs4_proc_remove,
 	.unlink_setup	= nfs4_proc_unlink_setup,
diff -puN include/linux/nfs_xdr.h~nfs-O_DIRET-sync-commit-rpcs include/linux/nfs_xdr.h
--- 25/include/linux/nfs_xdr.h~nfs-O_DIRET-sync-commit-rpcs	2003-06-17 16:00:24.000000000 -0700
+++ 25-akpm/include/linux/nfs_xdr.h	2003-06-17 16:00:24.000000000 -0700
@@ -638,8 +638,7 @@ struct nfs_rpc_ops {
 	int	(*readlink)(struct inode *, struct page *);
 	int	(*read)    (struct nfs_read_data *);
 	int	(*write)   (struct nfs_write_data *);
-	int	(*commit)  (struct inode *, struct nfs_fattr *,
-			    unsigned long, unsigned int);
+	int	(*commit)  (struct nfs_write_data *);
 	int	(*create)  (struct inode *, struct qstr *, struct iattr *,
 			    int, struct nfs_fh *, struct nfs_fattr *);
 	int	(*remove)  (struct inode *, struct qstr *);

_