
---


---
Create XDR and surrounding functions on the client for the GETDEVICELIST
command.


 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c        |   37 +++
 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c         |  121 ++++++++++++
 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c            |    8 
 linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h     |    1 
 linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h |    5 
 5 files changed, 172 insertions(+)

diff -puN fs/nfs/nfs4proc.c~client-devicelist fs/nfs/nfs4proc.c
--- linux-2.6.14-pnfs-current/fs/nfs/nfs4proc.c~client-devicelist	2006-01-13 17:39:38.901494000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c	2006-01-13 17:39:38.951494000 -0500
@@ -49,6 +49,7 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/pnfs_xdr.h>
+#include <linux/nfs4_pnfs.h>
 
 #include "nfs4_fs.h"
 #include "delegation.h"
@@ -1506,6 +1507,42 @@ static int nfs4_proc_pnfs_layoutreturn(s
 	return nfs4_map_errors(rpc_call_sync(NFS_CLIENT(ino), &msg, 0));
 }
 
+/* DH: Retrieve a list of devices from the server.
+ *
+ */
+static int _nfs4_pnfs_getdevicelist(struct nfs_server *server,
+				    struct pnfs_devicelist *res)
+{
+	struct nfs4_pnfs_getdevicelist_arg args = {
+		.fh = &server->fh,
+		.layoutclass = server->pnfs_curr_ld->id,
+	};
+
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PNFS_GETDEVICELIST],
+		.rpc_argp = &args,
+		.rpc_resp = res,
+	};
+
+	return rpc_call_sync(server->client, &msg, 0);
+}
+
+int nfs4_pnfs_getdevicelist(struct nfs_server *server,
+			    struct pnfs_devicelist* devlist)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server, _nfs4_pnfs_getdevicelist(server, devlist),
+				 &exception);
+	} while (exception.retry);
+
+	dprintk("nfs4_pnfs_getdevlist: err=%d, num_devs=%u\n",
+		err, devlist->num_devs);
+
+	return err;
+}
+
 static int nfs4_proc_read(struct nfs_read_data *rdata)
 {
 	struct nfs4_exception exception = { };
diff -puN fs/nfs/nfs4xdr.c~client-devicelist fs/nfs/nfs4xdr.c
--- linux-2.6.14-pnfs-current/fs/nfs/nfs4xdr.c~client-devicelist	2006-01-13 17:39:38.917494000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c	2006-01-13 17:39:38.979494000 -0500
@@ -52,6 +52,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/pnfs_xdr.h>
+#include <linux/nfs4_pnfs.h>
 #include "nfs4_fs.h"
 #include "pnfs.h"
 
@@ -437,6 +438,16 @@ static int nfs_stat_to_errno(int);
 					 encode_pnfs_layoutreturn_sz)
 #define NFS4_dec_pnfs_layoutreturn_sz	(compound_decode_hdr_maxsz +	\
 					 decode_pnfs_layoutreturn_maxsz)
+#define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 +	\
+				    (NFS4_VERIFIER_SIZE >> 2))
+#define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + 5 +		\
+				    NFS4_PNFS_DEV_MAXCOUNT*NFS4_PNFS_DEV_MAXSIZE)
+#define NFS4_enc_pnfs_getdevicelist_sz (compound_encode_hdr_maxsz + \
+					encode_putfh_maxsz +	    \
+					encode_getdevicelist_maxsz)
+#define NFS4_dec_pnfs_getdevicelist_sz (compound_decode_hdr_maxsz +	\
+					decode_putfh_maxsz +		\
+					decode_getdevicelist_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -1287,6 +1298,26 @@ static int encode_delegreturn(struct xdr
 	return 0;
 
 }
+
+/* DH:  Encode request to get information for a list of devices.
+*/
+static int encode_getdevicelist(struct xdr_stream *xdr, const struct nfs4_pnfs_getdevicelist_arg *args)
+{
+	uint32_t *p;
+	nfs4_verifier dummy = {
+		.data = "dummmmmy",
+	};
+
+	RESERVE_SPACE(20);
+	WRITE32(OP_GETDEVICELIST);
+	WRITE32(args->layoutclass);		/* layout type */
+	WRITE32(NFS4_PNFS_DEV_MAXCOUNT); 	/* maxcount */
+	WRITE64(0ULL);				/* cookie */
+	encode_nfs4_verifier(xdr, &dummy);
+
+	return 0;
+}
+
 /*
  * END OF "GENERIC" ENCODE ROUTINES.
  */
@@ -3496,6 +3527,58 @@ static int decode_delegreturn(struct xdr
 	return decode_op_hdr(xdr, OP_DELEGRETURN);
 }
 
+/* Decode getdevicelist results for pNFS.
+ * TODO: Need to match this xdr with the server.
+ */
+static int decode_getdevicelist(struct xdr_stream *xdr, struct pnfs_devicelist *res)
+{
+	uint32_t *p;
+	int status, i, cnt;
+	uint32_t len = 0, total_len = 0;
+	struct nfs_writeverf verftemp;
+
+	status = decode_op_hdr(xdr, OP_GETDEVICELIST);
+	if (status)
+		return status;
+
+	/* TODO: Skip cookie for now */
+	READ_BUF(8);
+	p += 2;
+
+	/* Read verifier */
+	READ_BUF(8);
+	COPYMEM(verftemp.verifier, 8);
+
+	READ_BUF(4);
+	READ32(res->num_devs);
+
+	for (i = 0,cnt=0; i < res->num_devs && cnt < NFS4_PNFS_DEV_MAXCOUNT; i++)
+	{
+		READ_BUF(4);
+		READ32(res->devs[cnt].dev_id);  /* device id */
+
+		READ_BUF(4);
+		READ32(res->devs[cnt].layoutclass);
+
+		READ_BUF(4);
+		READ32(len);
+		READ_BUF(len);
+
+		/* DH-TODO: Can I decode this inline?  Is the xdr_stream
+		 * memory valid after the completion of this function?
+		 */
+/*		decode_opaque_inline(xdr, &len, &r_addr); */
+		COPYMEM(&res->devs[cnt].dev_addr_buf, len);
+		res->devs[cnt].dev_addr_len = len;
+
+		total_len += len;
+		cnt++;
+	}
+
+	res->devs_len = total_len;
+	return 0;
+}
+
 /*
  * Decode OPEN_DOWNGRADE response
  */
@@ -4493,6 +4576,43 @@ out:
 
 }
 
+/*
+ * DH: Encode GETDEVICELIST request
+ */
+static int nfs4_xdr_enc_pnfs_getdevicelist(struct rpc_rqst *req, uint32_t *p, struct nfs4_pnfs_getdevicelist_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, args->fh)) == 0)
+		status = encode_getdevicelist(&xdr, args);
+	return status;
+}
+
+/*
+ * DH: Decode GETDEVICELIST response
+ */
+static int nfs4_xdr_dec_pnfs_getdevicelist(struct rpc_rqst *rqstp, uint32_t *p, struct pnfs_devicelist *res)
+{
+	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 == 0) {
+		status = decode_putfh(&xdr);
+		if (status == 0)
+			status = decode_getdevicelist(&xdr, res);
+	}
+	return status;
+}
+
 uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 {
 	uint32_t bitmap[2] = {0};
@@ -4665,6 +4785,7 @@ struct rpc_procinfo	nfs4_procedures[] = 
   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),
+  PROC(PNFS_GETDEVICELIST,	enc_pnfs_getdevicelist,	dec_pnfs_getdevicelist),
 };
 
 struct rpc_version		nfs_version4 = {
diff -puN include/linux/nfs4.h~client-devicelist include/linux/nfs4.h
--- linux-2.6.14-pnfs-current/include/linux/nfs4.h~client-devicelist	2006-01-13 17:39:38.922494000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h	2006-01-13 17:39:38.985494000 -0500
@@ -393,6 +393,7 @@ enum {
 	NFSPROC4_CLNT_PNFS_LAYOUTGET,
 	NFSPROC4_CLNT_PNFS_LAYOUTCOMMIT,
 	NFSPROC4_CLNT_PNFS_LAYOUTRETURN,
+	NFSPROC4_CLNT_PNFS_GETDEVICELIST,
 };
 
 #endif
diff -puN include/linux/pnfs_xdr.h~client-devicelist include/linux/pnfs_xdr.h
--- linux-2.6.14-pnfs-current/include/linux/pnfs_xdr.h~client-devicelist	2006-01-13 17:39:38.927494000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h	2006-01-13 17:39:38.990494000 -0500
@@ -81,4 +81,9 @@ struct nfs4_pnfs_layoutreturn {
 	struct rpc_cred         *cred;
 };
 
+struct nfs4_pnfs_getdevicelist_arg {
+	const struct nfs_fh *           fh;
+	u32                             layoutclass;
+};
+
 #endif /* LINUX_PNFS_XDR_H */
diff -puN fs/nfs/pnfs.c~client-devicelist fs/nfs/pnfs.c
--- linux-2.6.14-pnfs-current/fs/nfs/pnfs.c~client-devicelist	2006-01-13 17:39:38.934494000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c	2006-01-13 17:39:38.996494000 -0500
@@ -57,6 +57,7 @@ extern void nfs_inode_remove_request(str
 extern void nfs_mark_request_commit(struct nfs_page *req);
 extern void nfs_writeback_done_full(struct nfs_write_data *data, int status);
 extern int nfs_fsync(struct file *file, struct dentry *dentry, int datasync);
+extern int nfs4_pnfs_getdevicelist(struct nfs_server *server, struct pnfs_devicelist* devlist);
 
 /* Locking:
  *
@@ -865,5 +866,12 @@ pnfs_fsync(struct file *file, struct den
 	return result;
 }
 
+int
+pnfs_getdevicelist(struct super_block *sb, struct pnfs_devicelist* devlist)
+{
+	struct nfs_server *server = NFS_SB(sb);
+	return nfs4_pnfs_getdevicelist(server, devlist);
+}
+
 EXPORT_SYMBOL(pnfs_unregister_layoutdriver);
 EXPORT_SYMBOL(pnfs_register_layoutdriver);
_
