--- --- 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 #include #include +#include #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 #include #include +#include #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); _