
Create XDR and surrounding functions on the client for the LAYOUTRETURN
command.

---

 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c        |   17 ++
 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c         |   78 +++++++++++-
 linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h     |    1 
 linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_xdr.h  |    1 
 linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h |   14 ++
 5 files changed, 101 insertions(+), 10 deletions(-)

diff -puN fs/nfs/nfs4proc.c~client-layoutreturn fs/nfs/nfs4proc.c
--- linux-2.6.14-pnfs-current/fs/nfs/nfs4proc.c~client-layoutreturn	2006-01-13 17:36:59.264620000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c	2006-01-13 17:36:59.314570000 -0500
@@ -1496,6 +1496,16 @@ static int nfs4_proc_pnfs_layoutget(stru
 	return nfs4_map_errors(rpc_call_sync(NFS_CLIENT(ino), &msg, 0));
 }
 
+static int nfs4_proc_pnfs_layoutreturn(struct nfs4_pnfs_layoutreturn* layout)
+{
+	struct inode* ino = layout->args->inode;
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PNFS_LAYOUTRETURN],
+		.rpc_argp = layout->args,
+	};
+	return nfs4_map_errors(rpc_call_sync(NFS_CLIENT(ino), &msg, 0));
+}
+
 static int nfs4_proc_read(struct nfs_read_data *rdata)
 {
 	struct nfs4_exception exception = { };
@@ -1565,7 +1575,7 @@ static int _pnfs_proc_layoutcommit(struc
 	return status;
 }
 
-/* DH: Performs sync layoutcommit.  As a note, O_DIRECT will
+/* Performs sync layoutcommit.  As a note, O_DIRECT will
  * require this, but I currently haven't modified O_DIRECT for pNFS,
  * and I'm not sure if I ever will as bypassing the pagecache might
  * be the fastest way to do this. (well, I'm sure we will
@@ -2284,9 +2294,7 @@ nfs4_commit_done(struct rpc_task *task)
 	nfs_commit_done(task);
 }
 
-/* DH: Commit the data layout to the server.
- *     A caller must actually have a layout to call this function.
- */
+/*  Commit the data layout to the server.  */
 static void
 nfs4_proc_pnfs_layoutcommit_setup(struct nfs_write_data* data, int how)
 {
@@ -3356,6 +3364,7 @@ struct nfs_rpc_ops	nfs_v4_clientops = {
 	.pnfs_layoutget      = nfs4_proc_pnfs_layoutget,
 	.pnfs_layoutcommit_setup = nfs4_proc_pnfs_layoutcommit_setup,
 	.pnfs_layoutcommit       = pnfs_proc_layoutcommit,
+	.pnfs_layoutreturn       = nfs4_proc_pnfs_layoutreturn,
 };
 
 /*
diff -puN fs/nfs/nfs4xdr.c~client-layoutreturn fs/nfs/nfs4xdr.c
--- linux-2.6.14-pnfs-current/fs/nfs/nfs4xdr.c~client-layoutreturn	2006-01-13 17:36:59.280604000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c	2006-01-13 17:39:00.803632000 -0500
@@ -430,6 +430,13 @@ static int nfs_stat_to_errno(int);
 					 decode_putfh_maxsz + \
 					 decode_pnfs_layoutcommit_maxsz + \
 					 decode_getattr_maxsz)
+#define encode_pnfs_layoutreturn_sz	(8 + op_encode_hdr_maxsz)
+#define decode_pnfs_layoutreturn_maxsz  (op_decode_hdr_maxsz)
+#define NFS4_enc_pnfs_layoutreturn_sz	(compound_encode_hdr_maxsz +	\
+					 encode_putfh_maxsz +		\
+					 encode_pnfs_layoutreturn_sz)
+#define NFS4_dec_pnfs_layoutreturn_sz	(compound_decode_hdr_maxsz +	\
+					 decode_pnfs_layoutreturn_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -2698,7 +2705,7 @@ static int decode_attr_time_modify(struc
 	return status;
 }
 
-/* DH: The type of file system exported
+/* The type of file system exported
 */
 static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *layoutclass)
 {
@@ -2904,7 +2911,6 @@ static int decode_getfattr(struct xdr_st
 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
 		goto xdr_error;
 
-
 	if ((status = decode_attr_type(xdr, bitmap, &type)) != 0)
 		goto xdr_error;
 	fattr->type = nfs_type2fmt[type].nfs2type;
@@ -4340,7 +4346,7 @@ out:
 
 }
 
-/* DH:  Encode request for commiting the layout information for pNFS.
+/* Encode request for commiting the layout information for pNFS.
 */
 static int encode_pnfs_layoutcommit(struct xdr_stream *xdr, const struct pnfs_layoutcommit_arg *args)
 {
@@ -4364,7 +4370,7 @@ static int encode_pnfs_layoutcommit(stru
 	return 0;
 }
 
-/* DH: Receive a new stateid after commiting the layout
+/*  Receive a new stateid after commiting the layout
 */
 static int decode_pnfs_layoutcommit(struct xdr_stream *xdr, struct rpc_rqst *req, struct pnfs_layoutcommit_res *res)
 {
@@ -4381,7 +4387,7 @@ static int decode_pnfs_layoutcommit(stru
 }
 
 /*
- * DH: Encode LAYOUTCOMMIT request
+ * Encode LAYOUTCOMMIT request
  */
 static int nfs4_xdr_enc_pnfs_layoutcommit(struct rpc_rqst *req, uint32_t *p, struct pnfs_layoutcommit_arg *args)
 {
@@ -4405,7 +4411,7 @@ out:
 }
 
 /*
- * DH: Decode LAYOUTCOMMIT response
+ *  Decode LAYOUTCOMMIT response
  */
 static int nfs4_xdr_dec_pnfs_layoutcommit(struct rpc_rqst *rqstp, uint32_t *p, struct pnfs_layoutcommit_res *res)
 {
@@ -4428,6 +4434,65 @@ out:
 	return status;
 }
 
+/* :  Encode request to return the layout information for pNFS.
+*/
+static int encode_pnfs_layoutreturn(struct xdr_stream *xdr, const struct nfs4_pnfs_layoutreturn_arg *args)
+{
+	uint32_t *p;
+	RESERVE_SPACE(4);
+	WRITE32(OP_LAYOUTRETURN);
+	WRITE64(args->clientid);
+	WRITE64(args->offset);
+	WRITE64(args->length);
+	WRITE32(args->iomode);
+	WRITE32(args->type);
+	return 0;
+}
+
+static int decode_pnfs_layoutreturn(struct xdr_stream *xdr)
+{
+        return decode_op_hdr(xdr, OP_PUTFH);
+}
+
+/*
+ * Encode LAYOUTRETURN request
+ */
+static int nfs4_xdr_enc_pnfs_layoutreturn(struct rpc_rqst *req, uint32_t *p, struct nfs4_pnfs_layoutreturn_arg *args)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr = {
+		.nops = 2,
+	};
+	int status;
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, &hdr);
+	if ((status = encode_putfh(&xdr, NFS_FH(args->inode))) == 0)
+		status = encode_pnfs_layoutreturn(&xdr, args);
+	return status;
+}
+
+/*
+ * Decode LAYOUTRETURN response
+ */
+static int nfs4_xdr_dec_pnfs_layoutreturn(struct rpc_rqst *rqstp, uint32_t *p)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status)
+		goto out;
+	if ((status = decode_putfh(&xdr)) != 0)
+		goto out;
+	status = decode_pnfs_layoutreturn(&xdr);
+out:
+	return status;
+
+}
+
 uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 {
 	uint32_t bitmap[2] = {0};
@@ -4599,6 +4664,7 @@ struct rpc_procinfo	nfs4_procedures[] = 
   PROC(SETACL,		enc_setacl,	dec_setacl),
   PROC(PNFS_LAYOUTGET,	enc_pnfs_layoutget,	dec_pnfs_layoutget),
   PROC(PNFS_LAYOUTCOMMIT,	enc_pnfs_layoutcommit,	dec_pnfs_layoutcommit),
+  PROC(PNFS_LAYOUTRETURN,	enc_pnfs_layoutreturn,	dec_pnfs_layoutreturn),
 };
 
 struct rpc_version		nfs_version4 = {
diff -puN include/linux/nfs4.h~client-layoutreturn include/linux/nfs4.h
--- linux-2.6.14-pnfs-current/include/linux/nfs4.h~client-layoutreturn	2006-01-13 17:36:59.285599000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h	2006-01-13 17:36:59.347537000 -0500
@@ -392,6 +392,7 @@ enum {
 	NFSPROC4_CLNT_SETACL,
 	NFSPROC4_CLNT_PNFS_LAYOUTGET,
 	NFSPROC4_CLNT_PNFS_LAYOUTCOMMIT,
+	NFSPROC4_CLNT_PNFS_LAYOUTRETURN,
 };
 
 #endif
diff -puN include/linux/nfs_xdr.h~client-layoutreturn include/linux/nfs_xdr.h
--- linux-2.6.14-pnfs-current/include/linux/nfs_xdr.h~client-layoutreturn	2006-01-13 17:36:59.292592000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_xdr.h	2006-01-13 17:36:59.354530000 -0500
@@ -778,6 +778,7 @@ struct nfs_rpc_ops {
 	int	(*pnfs_layoutget)(struct nfs4_pnfs_layoutget* layout);
 	void	(*pnfs_layoutcommit_setup)(struct nfs_write_data *, int how);
 	int	(*pnfs_layoutcommit)  (struct nfs_write_data *);
+	int     (*pnfs_layoutreturn)(struct nfs4_pnfs_layoutreturn* layout);
 };
 
 /*
diff -puN include/linux/pnfs_xdr.h~client-layoutreturn include/linux/pnfs_xdr.h
--- linux-2.6.14-pnfs-current/include/linux/pnfs_xdr.h~client-layoutreturn	2006-01-13 17:36:59.297587000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h	2006-01-13 17:36:59.359525000 -0500
@@ -67,4 +67,18 @@ struct pnfs_layoutcommit_res {
 	const struct nfs_server *server;
 };
 
+struct nfs4_pnfs_layoutreturn_arg {
+	__u64	clientid;
+	__u64	offset;
+	__u64	length;
+	__u32	iomode;
+	__u32	type;
+	struct inode* inode;
+};
+
+struct nfs4_pnfs_layoutreturn {
+	struct nfs4_pnfs_layoutreturn_arg* args;
+	struct rpc_cred         *cred;
+};
+
 #endif /* LINUX_PNFS_XDR_H */
_
