Create XDR and surrounding functions on the client for the GETDEVICEINFO command. --- linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c | 37 ++++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c | 98 ++++++++++++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c | 14 + linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h | 1 linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h | 6 5 files changed, 156 insertions(+) diff -puN fs/nfs/nfs4proc.c~client-deviceinfo fs/nfs/nfs4proc.c --- linux-2.6.14-pnfs-current/fs/nfs/nfs4proc.c~client-deviceinfo 2006-01-13 17:39:44.061239000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c 2006-01-13 17:39:44.123239000 -0500 @@ -1543,6 +1543,43 @@ int nfs4_pnfs_getdevicelist(struct nfs_s return err; } +/* DH: Retrieve information for a particular storage device. + */ +static int _nfs4_pnfs_getdeviceinfo(struct nfs_server *server, + u32 dev_id, + struct pnfs_device *res) +{ + struct nfs4_pnfs_getdeviceinfo_arg args = { + .fh = &server->fh, + .dev_id = dev_id, + }; + + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PNFS_GETDEVICEINFO], + .rpc_argp = &args, + .rpc_resp = res, + }; + + return rpc_call_sync(server->client, &msg, 0); +} + +int nfs4_pnfs_getdeviceinfo(struct nfs_server *server, + u32 dev_id, + struct pnfs_device* res) +{ + struct nfs4_exception exception = { }; + int err; + do { + err = nfs4_handle_exception(server, + _nfs4_pnfs_getdeviceinfo(server, dev_id, res), + &exception); + } while (exception.retry); + + dprintk("nfs4_pnfs_getdevinfo: err=%d dev_id=%d\n", err, dev_id); + + return err; +} + static int nfs4_proc_read(struct nfs_read_data *rdata) { struct nfs4_exception exception = { }; diff -puN fs/nfs/nfs4xdr.c~client-deviceinfo fs/nfs/nfs4xdr.c --- linux-2.6.14-pnfs-current/fs/nfs/nfs4xdr.c~client-deviceinfo 2006-01-13 17:39:44.077239000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c 2006-01-13 17:39:44.152239000 -0500 @@ -448,6 +448,15 @@ static int nfs_stat_to_errno(int); #define NFS4_dec_pnfs_getdevicelist_sz (compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ decode_getdevicelist_maxsz) +#define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 2) +#define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + 3 + \ + NFS4_PNFS_DEV_MAXSIZE) +#define NFS4_enc_pnfs_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ + encode_putfh_maxsz + \ + encode_getdeviceinfo_maxsz) +#define NFS4_dec_pnfs_getdeviceinfo_sz (compound_decode_hdr_maxsz + \ + decode_putfh_maxsz + \ + decode_getdeviceinfo_maxsz) static struct { unsigned int mode; @@ -1318,6 +1327,18 @@ static int encode_getdevicelist(struct x return 0; } +/* DH: Encode request to get information for a specific device. +*/ +static int encode_getdeviceinfo(struct xdr_stream *xdr, const struct nfs4_pnfs_getdeviceinfo_arg *args) +{ + uint32_t *p; + RESERVE_SPACE(12); + WRITE32(OP_GETDEVICEINFO); + WRITE32(args->layoutclass); + WRITE32(args->dev_id); + return 0; +} + /* * END OF "GENERIC" ENCODE ROUTINES. */ @@ -3579,6 +3600,38 @@ static int decode_getdevicelist(struct x return 0; } +/* DH: decode device info arguments +*/ +static int decode_getdeviceinfo(struct xdr_stream *xdr, + struct pnfs_device *res) +{ + uint32_t *p; + uint32_t len; + int status; + + status = decode_op_hdr(xdr, OP_GETDEVICEINFO); + if (status) + return status; + + READ_BUF(4); + READ32(res->dev_id); /* device id */ + + READ_BUF(4); + READ32(res->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->dev_addr_buf, len); + res->dev_addr_len = len; + return 0; +} + /* * Decode OPEN_DOWNGRADE response */ @@ -4613,6 +4666,50 @@ static int nfs4_xdr_dec_pnfs_getdeviceli return status; } +/* + * DH: Encode GETDEVICEINFO request + */ +static int nfs4_xdr_enc_pnfs_getdeviceinfo(struct rpc_rqst *req, + uint32_t *p, + struct nfs4_pnfs_getdeviceinfo_arg *args) +{ + struct xdr_stream xdr; + struct compound_hdr hdr = { + .nops = 1, + }; + 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_getdeviceinfo(&xdr, args); + return status; +} + +/* + * DH: Decode GETDEVICEINFO response + */ +/* + * GETDEVINFO + */ +static int nfs4_xdr_dec_pnfs_getdeviceinfo(struct rpc_rqst *rqstp, + uint32_t *p, + struct pnfs_device *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_getdeviceinfo(&xdr, res); + } + return status; +} + uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) { uint32_t bitmap[2] = {0}; @@ -4786,6 +4883,7 @@ struct rpc_procinfo nfs4_procedures[] = 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), + PROC(PNFS_GETDEVICEINFO, enc_pnfs_getdeviceinfo, dec_pnfs_getdeviceinfo), }; struct rpc_version nfs_version4 = { diff -puN include/linux/nfs4.h~client-deviceinfo include/linux/nfs4.h --- linux-2.6.14-pnfs-current/include/linux/nfs4.h~client-deviceinfo 2006-01-13 17:39:44.094239000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h 2006-01-13 17:39:44.158239000 -0500 @@ -394,6 +394,7 @@ enum { NFSPROC4_CLNT_PNFS_LAYOUTCOMMIT, NFSPROC4_CLNT_PNFS_LAYOUTRETURN, NFSPROC4_CLNT_PNFS_GETDEVICELIST, + NFSPROC4_CLNT_PNFS_GETDEVICEINFO, }; #endif diff -puN fs/nfs/pnfs.c~client-deviceinfo fs/nfs/pnfs.c --- linux-2.6.14-pnfs-current/fs/nfs/pnfs.c~client-deviceinfo 2006-01-13 17:39:44.101239000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c 2006-01-13 17:39:44.165239000 -0500 @@ -58,6 +58,7 @@ extern void nfs_mark_request_commit(stru 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); +extern int nfs4_pnfs_getdeviceinfo(struct nfs_server *server, u32 dev_id, struct pnfs_device *res); /* Locking: * @@ -873,5 +874,18 @@ pnfs_getdevicelist(struct super_block *s return nfs4_pnfs_getdevicelist(server, devlist); } +/* Retrieve the device information for a device. + */ +int +pnfs_getdeviceinfo(struct super_block *sb, u32 dev_id, struct pnfs_device* dev) +{ + struct nfs_server *server = NFS_SB(sb); + int rc; + + rc = nfs4_pnfs_getdeviceinfo(server, dev_id, dev); + + return rc; +} + EXPORT_SYMBOL(pnfs_unregister_layoutdriver); EXPORT_SYMBOL(pnfs_register_layoutdriver); diff -puN include/linux/pnfs_xdr.h~client-deviceinfo include/linux/pnfs_xdr.h --- linux-2.6.14-pnfs-current/include/linux/pnfs_xdr.h~client-deviceinfo 2006-01-13 17:39:44.106240000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h 2006-01-13 17:39:44.169240000 -0500 @@ -86,4 +86,10 @@ struct nfs4_pnfs_getdevicelist_arg { u32 layoutclass; }; +struct nfs4_pnfs_getdeviceinfo_arg { + const struct nfs_fh * fh; + u32 layoutclass; + u32 dev_id; +}; + #endif /* LINUX_PNFS_XDR_H */ _