Create XDR and surrounding functions in the client for the LAYOUTGET command. --- linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c | 13 + linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c | 101 ++++++++++++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c | 52 ++++++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h | 1 linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_xdr.h | 2 linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h | 49 +++++ 6 files changed, 218 insertions(+) diff -puN fs/nfs/nfs4proc.c~client-layoutget fs/nfs/nfs4proc.c --- linux-2.6.14-pnfs-current/fs/nfs/nfs4proc.c~client-layoutget 2006-01-13 17:27:59.861743000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c 2006-01-13 17:27:59.911743000 -0500 @@ -48,6 +48,7 @@ #include #include #include +#include #include "nfs4_fs.h" #include "delegation.h" @@ -1477,6 +1478,17 @@ static int _nfs4_proc_read(struct nfs_re return status; } +static int nfs4_proc_pnfs_layoutget(struct nfs4_pnfs_layoutget* layout) +{ + struct inode* ino = layout->args->inode; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PNFS_LAYOUTGET], + .rpc_argp = layout->args, + .rpc_resp = layout->res, + }; + 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 = { }; @@ -3261,6 +3273,7 @@ struct nfs_rpc_ops nfs_v4_clientops = { .file_release = nfs_release, .lock = nfs4_proc_lock, .clear_acl_cache = nfs4_zap_acl_attr, + .pnfs_layoutget = nfs4_proc_pnfs_layoutget, }; /* diff -puN fs/nfs/nfs4xdr.c~client-layoutget fs/nfs/nfs4xdr.c --- linux-2.6.14-pnfs-current/fs/nfs/nfs4xdr.c~client-layoutget 2006-01-13 17:27:59.876743000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4xdr.c 2006-01-13 17:29:45.616938000 -0500 @@ -51,6 +51,7 @@ #include #include #include +#include #include "nfs4_fs.h" #include "pnfs.h" @@ -410,6 +411,14 @@ static int nfs_stat_to_errno(int); #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ decode_putfh_maxsz + \ op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) +#define encode_pnfs_layoutget_sz (11 + op_encode_hdr_maxsz) +#define decode_pnfs_layoutget_maxsz (6 + PNFS_LAYOUT_MAXSIZE + \ + op_decode_hdr_maxsz) +#define NFS4_enc_pnfs_layoutget_sz (compound_encode_hdr_maxsz + \ + encode_putfh_maxsz + \ + encode_pnfs_layoutget_sz) +#define NFS4_dec_pnfs_layoutget_sz (compound_decode_hdr_maxsz + \ + decode_pnfs_layoutget_maxsz) static struct { unsigned int mode; @@ -4229,6 +4238,97 @@ static int nfs4_xdr_dec_delegreturn(stru return status; } +static int encode_pnfs_layoutget(struct xdr_stream *xdr, const struct nfs4_pnfs_layoutget_arg *args) +{ + uint32_t *p; + + RESERVE_SPACE(44); + WRITE32(OP_LAYOUTGET); + WRITE64(args->clientid); + WRITE32(args->type); + WRITE32(args->iomode); + WRITE64(args->offset); + WRITE64(args->length); + WRITE64(args->minlength); + WRITE32(args->maxcount); + + dprintk("%s: 1st type:%d iomode:%d off:%lu len:%lu mc:%d\n", + __FUNCTION__, + args->type, + args->iomode, + (unsigned long)args->offset, + (unsigned long)args->length, + args->maxcount); + return 0; +} + +static int decode_pnfs_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_pnfs_layoutget_res *res) +{ + uint32_t *p; + int status; + + status = decode_op_hdr(xdr, OP_LAYOUTGET); + if (status) + return status; + READ_BUF(28); + READ64(res->offset); + READ64(res->length); + READ32(res->iomode); + READ32(res->type); + READ_BUF(res->layout.len); + if (res->layout.len > PNFS_LAYOUT_MAXSIZE) + return -EINVAL; + COPYMEM(res->layout.buf, res->layout.len); + + dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:%d, lo.len:%d\n", + __FUNCTION__, + (unsigned long)res->offset, + (unsigned long)res->length, + res->iomode, + res->type, + res->layout.len); + return 0; +} + +/* + * Encode LAYOUTGET request + */ +static int nfs4_xdr_enc_pnfs_layoutget(struct rpc_rqst *req, uint32_t *p, struct nfs4_pnfs_layoutget_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_layoutget(&xdr, args); + return status; +} + +/* + * Decode LAYOUTGET response + */ +static int nfs4_xdr_dec_pnfs_layoutget(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_pnfs_layoutget_res *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) + goto out; + if ((status = decode_putfh(&xdr)) != 0) + goto out; + status = decode_pnfs_layoutget(&xdr,rqstp,res); +out: + return status; + +} + uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) { uint32_t bitmap[2] = {0}; @@ -4398,6 +4498,7 @@ struct rpc_procinfo nfs4_procedures[] = PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), PROC(GETACL, enc_getacl, dec_getacl), PROC(SETACL, enc_setacl, dec_setacl), + PROC(PNFS_LAYOUTGET, enc_pnfs_layoutget, dec_pnfs_layoutget), }; struct rpc_version nfs_version4 = { diff -puN fs/nfs/pnfs.c~client-layoutget fs/nfs/pnfs.c --- linux-2.6.14-pnfs-current/fs/nfs/pnfs.c~client-layoutget 2006-01-13 17:27:59.882743000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c 2006-01-13 17:27:59.933743000 -0500 @@ -189,5 +189,57 @@ pnfs_unregister_layoutdriver(struct pnfs } } +/* +* Get layout from server. +* for now, assume that whole file layouts are requested. +* arg->offset: 0 +* arg->length: all ones +* +* for now, assume the LAYOUTGET operation is triggered by an I/O request. +* the count field is the count in the I/O request, and will be used +* as the minlength. for the file operation that piggy-backs +* the LAYOUTGET operation with an OPEN, s +* arg->minlength = count. +*/ +static int +get_layout(struct inode* ino, struct nfs_open_context* ctx, size_t count, loff_t pos, int access_type, struct nfs4_pnfs_layoutget_arg* arg, struct nfs4_pnfs_layoutget_res* res) +{ + int status; + struct nfs_server *server = NFS_SERVER(ino); + struct nfs4_pnfs_layoutget gdata = { + .args = arg, + .res = res, + }; +/* + struct timeval begin = { 0, 0 }, end = { 0, 0 }; + do_gettimeofday(&begin); +*/ + dprintk("%s:Begin\n",__FUNCTION__); + + arg->clientid = ctx->state->owner->so_client->cl_clientid; + arg->type = server->pnfs_curr_ld->id; + /* FMODE_WRITE =2= LAYOUTMODE_RW, FMODE_READ =1= LAYOUTMODE_READ */ + arg->iomode = access_type; + arg->offset = 0; + arg->length = 0xFFFFFFFF; + arg->minlength = count; + arg->maxcount = PNFS_LAYOUT_MAXSIZE; + arg->inode = ino; + arg->ctx = ctx; + + /* Retrieve layout information from server */ + status = NFS_PROTO(ino)->pnfs_layoutget(&gdata); +/* + do_gettimeofday(&end); + if (end.tv_usec < begin.tv_usec) { + end.tv_usec = 1000000; end.tv_sec--; + } + end.tv_sec -= begin.tv_sec; + end.tv_usec -= begin.tv_usec; + printk("Sec:%ld usec: %ld\n",end.tv_sec,end.tv_usec); +*/ + return status; +} + EXPORT_SYMBOL(pnfs_unregister_layoutdriver); EXPORT_SYMBOL(pnfs_register_layoutdriver); diff -puN include/linux/nfs4.h~client-layoutget include/linux/nfs4.h --- linux-2.6.14-pnfs-current/include/linux/nfs4.h~client-layoutget 2006-01-13 17:27:59.886743000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4.h 2006-01-13 17:27:59.939738000 -0500 @@ -390,6 +390,7 @@ enum { NFSPROC4_CLNT_DELEGRETURN, NFSPROC4_CLNT_GETACL, NFSPROC4_CLNT_SETACL, + NFSPROC4_CLNT_PNFS_LAYOUTGET, }; #endif diff -puN include/linux/nfs_xdr.h~client-layoutget include/linux/nfs_xdr.h --- linux-2.6.14-pnfs-current/include/linux/nfs_xdr.h~client-layoutget 2006-01-13 17:27:59.893743000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_xdr.h 2006-01-13 17:27:59.945732000 -0500 @@ -2,6 +2,7 @@ #define _LINUX_NFS_XDR_H #include +#include #include struct nfs4_fsid { @@ -771,6 +772,7 @@ struct nfs_rpc_ops { int (*file_release) (struct inode *, struct file *); int (*lock)(struct file *, int, struct file_lock *); void (*clear_acl_cache)(struct inode *); + int (*pnfs_layoutget)(struct nfs4_pnfs_layoutget* layout); }; /* diff -puN /dev/null include/linux/pnfs_xdr.h --- /dev/null 2006-01-09 05:56:56.224752500 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/pnfs_xdr.h 2006-01-13 17:27:59.952725000 -0500 @@ -0,0 +1,49 @@ +/* + * include/linux/pnfs_xdr.h + * + * Common xdr data structures needed by pnfs client and server. + * + * Copyright (c) 2002 The Regents of the University of Michigan. + * All rights reserved. + * + * Dean Hildebrand + */ + +#ifndef LINUX_PNFS_XDR_H +#define LINUX_PNFS_XDR_H + +#include + +#define PNFS_LAYOUT_MAXSIZE 1024 +#define PNFS_MAX_NUM_LAYOUT_TYPES 2 + +struct nfs4_pnfs_layout { + __u32 len; + char *buf; +}; + +struct nfs4_pnfs_layoutget_arg { + __u64 clientid; + __u32 type; + __u32 iomode; + __u64 offset; + __u64 length; + __u64 minlength; + __u32 maxcount; + struct nfs_open_context* ctx; + struct inode* inode; +}; + +struct nfs4_pnfs_layoutget_res { + __u64 offset; + __u64 length; + __u32 iomode; + __u32 type; + struct nfs4_pnfs_layout layout; +}; + +struct nfs4_pnfs_layoutget { + struct nfs4_pnfs_layoutget_arg* args; + struct nfs4_pnfs_layoutget_res* res; +}; +#endif /* LINUX_PNFS_XDR_H */ _