nfs41 client patches for review
Subsystems (4)
cover nfs41 client patches for review
Trond,
Here's the patch series for nfs41 client side, rebased over 2.6.28 for review.
I've cleaned up the patch as much as I could in the given time frame but surely there's more work to be done.
I encourage others to comment on the patches as well.
Thanks,
Benny
pre-nfs41 patches:
[RFC 01/85] sunrpc: get rid of rpc_rqst.rq_bufsize
[RFC 02/85] nfs: return compound hdr.status when there are no op replies [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine
general defs:
[RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1
[RFC 06/85] nfs41: common protocol definitions
[RFC 07/85] nfs41: define NFS4_MAX_MINOR_VERSION based on CONFIG_NFS_V4_1 [RFC 08/85] nfs41: client xdr definitions
basic support for minorversion != 0:
[RFC 09/85] nfs41: add mount command option minorvers
[RFC 10/85] nfs41: struct nfs_server minorversion
[RFC 11/85] nfs41: nfs_client.cl_minorversion
[RFC 12/85] nfs41: set nfs_client rpc_ops based on minorversion
[RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client
[RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table. [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops
[RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails
sessions basic functionality:
[RFC 18/85] nfs41: sessions client infrastructure [RFC 19/85] nfs41: share client sessions across mounts [RFC 20/85] nfs41: slot table init and destroy [RFC 21/85] nfs41: find slot
[RFC 22/85] nfs41: free slot
support for sequence for legacy ops:
[RFC 23/85] nfs41: minorversion support for xdr [RFC 24/85] nfs41: stubs for nfs41 procedures [RFC 25/85] nfs41: make nfs4_wait_bit_killable public [RFC 26/85] nfs41: introduce nfs4_call_sync [RFC 27/85] nfs41: nfs4_setup_sequence
[RFC 28/85] nfs41: setup_sequence method
[RFC 29/85] nfs41: nfs41_sequence_done
[RFC 30/85] nfs41: nfs41_call_sync_done
[RFC 31/85] nfs41: separate free slot from sequence done [RFC 32/85] nfs41: sequence setup/done support [RFC 33/85] nfs41: Support sessions with O_DIRECT.
nfs41 ops:
[RFC 34/85] nfs41: exchange_id operation
[RFC 35/85] nfs41: get_lease_time
[RFC 36/85] nfs41: create_session operation
[RFC 37/85] nfs41: destroy_session operation
[RFC 38/85] nfs41: sequence operation
session setup and recovery:
[RFC 39/85] nfs41: session recovery infrastructure
[RFC 40/85] nfs41: schedule async session reset
[RFC 41/85] nfs41: lease renewal
[RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset [RFC 43/85] nfs41: use rpc prepare call state for session reset [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors [RFC 45/85] nfs41: start session recovery from nfs4_setup_sequence [RFC 46/85] nfs41: introduce get_state_renewal_cred
[RFC 47/85] nfs41: get cred in exchange_id when cred arg is NULL [RFC 48/85] nfs41: establish sessions-based clientid
[RFC 49/85] nfs41: recover lease in _nfs4_lookup_root
[RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session [RFC 51/85] nfs41: state reclaimer renew lease error handling [RFC 52/85] nfs41: increment_{open,lock}_seqid
backchannel:
[RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream. [RFC 54/85] nfs41: Skip past the RPC call direction
[RFC 55/85] nfs41: Refactor NFSv4 callback service
[RFC 56/85] nfs41: client callback structures
[RFC 57/85] nfs41: Initialize new rpc_xprt callback related fields [RFC 58/85] nfs41: New backchannel helper routines
[RFC 59/85] nfs41: New include/linux/sunrpc/bc_xprt.h
[RFC 60/85] nfs41: New xs_tcp_read_data()
[RFC 61/85] nfs41: Add backchannel processing support to RPC state machine [RFC 62/85] nfs41: Backchannel callback service helper routines [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL in call_status
callback service:
[RFC 64/85] nfs41: Refactor svc_process()
[RFC 65/85] nfs41: Backchannel bc_svc_process()
[RFC 66/85] nfs41: Implement NFSv4.1 callback service process.
[RFC 67/85] nfs41: sunrpc: provide functions to create and destroy a svc_xprt for backchannel use [RFC 68/85] nfs41: sunrpc: add a struct svc_xprt pointer to struct svc_serv for backchannel use [RFC 69/85] nfs41: create a svc_xprt for nfs41 callback thread and use for incoming callbacks [RFC 70/85] nfs41: save svc_serv in nfs_callback_info
[RFC 71/85] nfs41: Add a reference to svc_serv during callback service bring up [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
[RFC 73/85] nfs41: Setup the backchannel
[RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel.
[RFC 75/85] nfs41: Get the rpc_xprt * from the rpc_rqst instead of the rpc_clnt. [RFC 76/85] nfs41: Release backchannel resources associated with session
callback processing:
[RFC 77/85] nfs41: store minorversion in cb_compound_hdr_arg [RFC 78/85] nfs41: decode minorversion 1 cb_compound header [RFC 79/85] nfs41: callback numbers definitions
[RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op [RFC 81/85] nfs41: define CB_NOTIFY_DEVICEID as not supported [RFC 82/85] nfs41: cb_sequence protocol level data structures [RFC 83/85] nfs41: cb_sequence proc implementation
[RFC 84/85] nfs41: cb_sequence xdr implementation
[RFC 85/85] nfs41: verify CB_SEQUENCE position in callback compound
RFC 3/85 nfs: remove incorrect usage of nfs4 compound response hdr.status
3 call sites look at hdr.status before returning success. hdr.status must be zero in this case so there's no point in this.
Currently, hdr.status is correctly processed at decode_op_hdr time if the op status cannot be decoded.
--- fs/nfs/nfs4xdr.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)
fs/nfs/nfs4xdr.c +0 -6
@@ -4423,8 +4423,6 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf status =decode_putfh (&xdr);if (!status) status =decode_fsinfo (&xdr, fsinfo); -if (!status) - status =nfs4_stat_to_errno (hdr.status);return status; }
@@ -4513,8 +4511,6 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, status =decode_compound_hdr (&xdr, &hdr);if (!status) status =decode_setclientid (&xdr, clp); -if (!status) - status =nfs4_stat_to_errno (hdr.status);return status; }
@@ -4535,8 +4531,6 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str status =decode_putrootfh (&xdr);if (!status) status =decode_fsinfo (&xdr, fsinfo); -if (!status) - status =nfs4_stat_to_errno (hdr.status);return status; }
Signature · 1 line
1.6.0.2
RFC 4/85 FIXME: NFS: Increment operation number in each encode_* routine
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
FIXME: bhalevy: is this a good opportunity for a cleanup-only patch to fix whitespacing?
Pass in the compound_hdr and bump the number of operations in each encode_* subroutine so as to allow us to more easily construct new compound statements.
Fix tabs, do not fix 'do not use assignment in if condition' warnings.
--- fs/nfs/nfs4xdr.c | 630 ++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 401 insertions(+), 229 deletions(-)
fs/nfs/nfs4xdr.c +401 -229
@@ -578,9 +578,10 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *xdr_encode_opaque (p, str, len); } -static int encode_compound_hdr (struct xdr_stream *xdr,struct compound_hdr *hdr) +static __u32 * +encode_compound_hdr (struct xdr_stream *xdr,struct compound_hdr *hdr) { -__be32 *p; +__be32 *p, *nops;dprintk ("encode_compound: tag=%.*s\n" , (int )hdr->taglen, hdr->tag);BUG_ON (hdr->taglen >NFS4_MAXTAGLEN );
@@ -588,8 +589,14 @@ static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)WRITE32 (hdr->taglen);WRITEMEM (hdr->tag, hdr->taglen);WRITE32 (NFS4_MINOR_VERSION ); + nops = p;WRITE32 (hdr->nops); -return 0 ; +return nops; +} + +static inline void encode_nops (__be32 *nops,struct compound_hdr *hdr) +{ + *nops =htonl (hdr->nops); }static void encode_nfs4_verifier (struct xdr_stream *xdr,const nfs4_verifier *verf)
@@ -728,18 +735,22 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const sreturn status; } -static int encode_access (struct xdr_stream *xdr,u32 access) +static int +encode_access (struct xdr_stream *xdr,u32 access,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (8 );WRITE32 (OP_ACCESS );WRITE32 (access); - + hdr->nops++; +return 0 ; } -static int encode_close (struct xdr_stream *xdr,const struct nfs_closeargs *arg) +static int +encode_close (struct xdr_stream *xdr,const struct nfs_closeargs *arg, +struct compound_hdr *hdr) {__be32 *p;
@@ -747,23 +758,29 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)WRITE32 (OP_CLOSE );WRITE32 (arg->seqid->sequence->counter);WRITEMEM (arg->stateid->data,NFS4_STATEID_SIZE ); + hdr->nops++;return 0 ; } -static int encode_commit (struct xdr_stream *xdr,const struct nfs_writeargs *args) +static int +encode_commit (struct xdr_stream *xdr,const struct nfs_writeargs *args, +struct compound_hdr *hdr) {__be32 *p; -RESERVE_SPACE (16 ); -WRITE32 (OP_COMMIT ); -WRITE64 (args->offset); -WRITE32 (args->count); +RESERVE_SPACE (16 ); +WRITE32 (OP_COMMIT ); +WRITE64 (args->offset); +WRITE32 (args->count); + hdr->nops++; -return 0 ; +return 0 ; } -static int encode_create (struct xdr_stream *xdr,const struct nfs4_create_arg *create) +static int +encode_create (struct xdr_stream *xdr,const struct nfs4_create_arg *create, +struct compound_hdr *hdr) {__be32 *p;
@@ -791,11 +808,14 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *cRESERVE_SPACE (4 + create->name->len);WRITE32 (create->name->len);WRITEMEM (create->name->name, create->name->len); + hdr->nops++;return encode_attrs (xdr, create->attrs, create->server); } -static int encode_getattr_one (struct xdr_stream *xdr,uint32_t bitmap) +static int +encode_getattr_one (struct xdr_stream *xdr,uint32_t bitmap, +struct compound_hdr *hdr) {__be32 *p;
@@ -803,10 +823,13 @@ static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)WRITE32 (OP_GETATTR );WRITE32 (1 );WRITE32 (bitmap); + hdr->nops++;return 0 ; } -static int encode_getattr_two (struct xdr_stream *xdr,uint32_t bm0,uint32_t bm1) +static int +encode_getattr_two (struct xdr_stream *xdr,uint32_t bm0,uint32_t bm1, +struct compound_hdr *hdr) {__be32 *p;
@@ -815,40 +838,51 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1WRITE32 (2 );WRITE32 (bm0);WRITE32 (bm1); + hdr->nops++;return 0 ; } -static int encode_getfattr (struct xdr_stream *xdr,const u32 * bitmask) +static int +encode_getfattr (struct xdr_stream *xdr,const u32 *bitmask, +struct compound_hdr *hdr) {return encode_getattr_two (xdr, bitmask[0 ] & nfs4_fattr_bitmap[0 ], - bitmask[1 ] & nfs4_fattr_bitmap[1 ]); + bitmask[1 ] & nfs4_fattr_bitmap[1 ], hdr); } -static int encode_fsinfo (struct xdr_stream *xdr,const u32 * bitmask) +static int +encode_fsinfo (struct xdr_stream *xdr,const u32 *bitmask, +struct compound_hdr *hdr) {return encode_getattr_two (xdr, bitmask[0 ] & nfs4_fsinfo_bitmap[0 ], - bitmask[1 ] & nfs4_fsinfo_bitmap[1 ]); + bitmask[1 ] & nfs4_fsinfo_bitmap[1 ], hdr); } -static int encode_fs_locations (struct xdr_stream *xdr,const u32 * bitmask) +static int +encode_fs_locations (struct xdr_stream *xdr,const u32 *bitmask, +struct compound_hdr *hdr) {return encode_getattr_two (xdr, bitmask[0 ] & nfs4_fs_locations_bitmap[0 ], - bitmask[1 ] & nfs4_fs_locations_bitmap[1 ]); + bitmask[1 ] & nfs4_fs_locations_bitmap[1 ], + hdr); } -static int encode_getfh (struct xdr_stream *xdr) +static int encode_getfh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_GETFH ); + hdr->nops++;return 0 ; } -static int encode_link (struct xdr_stream *xdr,const struct qstr *name) +static int +encode_link (struct xdr_stream *xdr,const struct qstr *name, +struct compound_hdr *hdr) {__be32 *p;
@@ -856,6 +890,7 @@ static int encode_link(struct xdr_stream *xdr, const struct qstr *name)WRITE32 (OP_LINK );WRITE32 (name->len);WRITEMEM (name->name, name->len); + hdr->nops++;return 0 ; }
@@ -878,7 +913,9 @@ static inline uint64_t nfs4_lock_length(struct file_lock *fl)* opcode,type,reclaim,offset,length,new_lock_owner = 32 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 */ -static int encode_lock (struct xdr_stream *xdr,const struct nfs_lock_args *args) +static int +encode_lock (struct xdr_stream *xdr,const struct nfs_lock_args *args, +struct compound_hdr *hdr) {__be32 *p;
@@ -904,11 +941,14 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)WRITEMEM (args->lock_stateid->data,NFS4_STATEID_SIZE );WRITE32 (args->lock_seqid->sequence->counter); } + hdr->nops++;return 0 ; } -static int encode_lockt (struct xdr_stream *xdr,const struct nfs_lockt_args *args) +static int +encode_lockt (struct xdr_stream *xdr,const struct nfs_lockt_args *args, +struct compound_hdr *hdr) {__be32 *p;
@@ -921,11 +961,14 @@ static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *argWRITE32 (16 );WRITEMEM ("lock id:" ,8 );WRITE64 (args->lock_owner.id); + hdr->nops++;return 0 ; } -static int encode_locku (struct xdr_stream *xdr,const struct nfs_locku_args *args) +static int +encode_locku (struct xdr_stream *xdr,const struct nfs_locku_args *args, +struct compound_hdr *hdr) {__be32 *p;
@@ -936,11 +979,14 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *argWRITEMEM (args->stateid->data,NFS4_STATEID_SIZE );WRITE64 (args->fl->fl_start);WRITE64 (nfs4_lock_length (args->fl)); + hdr->nops++;return 0 ; } -static int encode_lookup (struct xdr_stream *xdr,const struct qstr *name) +static int +encode_lookup (struct xdr_stream *xdr,const struct qstr *name, +struct compound_hdr *hdr) {int len = name->len;__be32 *p;
@@ -949,6 +995,7 @@ static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)WRITE32 (OP_LOOKUP );WRITE32 (len);WRITEMEM (name->name, len); + hdr->nops++;return 0 ; }
@@ -1072,7 +1119,9 @@ static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const strucencode_string (xdr, name->len, name->name); } -static int encode_open (struct xdr_stream *xdr,const struct nfs_openargs *arg) +static int +encode_open (struct xdr_stream *xdr,const struct nfs_openargs *arg, +struct compound_hdr *hdr) {encode_openhdr (xdr, arg);encode_opentype (xdr, arg);
@@ -1089,10 +1138,14 @@ static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)default :BUG (); } + hdr->nops++;return 0 ; } -static int encode_open_confirm (struct xdr_stream *xdr,const struct nfs_open_confirmargs *arg) +static int +encode_open_confirm (struct xdr_stream *xdr, +const struct nfs_open_confirmargs *arg, +struct compound_hdr *hdr) {__be32 *p;
@@ -1100,11 +1153,14 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_conWRITE32 (OP_OPEN_CONFIRM );WRITEMEM (arg->stateid->data,NFS4_STATEID_SIZE );WRITE32 (arg->seqid->sequence->counter); + hdr->nops++;return 0 ; } -static int encode_open_downgrade (struct xdr_stream *xdr,const struct nfs_closeargs *arg) +static int +encode_open_downgrade (struct xdr_stream *xdr,const struct nfs_closeargs *arg, +struct compound_hdr *hdr) {__be32 *p;
@@ -1113,11 +1169,13 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeaWRITEMEM (arg->stateid->data,NFS4_STATEID_SIZE );WRITE32 (arg->seqid->sequence->counter);encode_share_access (xdr, arg->open_flags); + hdr->nops++;return 0 ; }static int -encode_putfh (struct xdr_stream *xdr,const struct nfs_fh *fh) +encode_putfh (struct xdr_stream *xdr,const struct nfs_fh *fh, +struct compound_hdr *hdr) {int len = fh->size;__be32 *p;
@@ -1126,21 +1184,24 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)WRITE32 (OP_PUTFH );WRITE32 (len);WRITEMEM (fh->data, len); + hdr->nops++;return 0 ; } -static int encode_putrootfh (struct xdr_stream *xdr) +static int encode_putrootfh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_PUTROOTFH ); + hdr->nops++;return 0 ; } -static void encode_stateid (struct xdr_stream *xdr,const struct nfs_open_context *ctx) +static void +encode_stateid (struct xdr_stream *xdr,const struct nfs_open_context *ctx) {nfs4_stateid stateid;__be32 *p;
@@ -1153,7 +1214,9 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_contextWRITEMEM (zero_stateid.data,NFS4_STATEID_SIZE ); } -static int encode_read (struct xdr_stream *xdr,const struct nfs_readargs *args) +static int +encode_read (struct xdr_stream *xdr,const struct nfs_readargs *args, +struct compound_hdr *hdr) {__be32 *p;
@@ -1165,11 +1228,14 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)RESERVE_SPACE (12 );WRITE64 (args->offset);WRITE32 (args->count); + hdr->nops++;return 0 ; } -static int encode_readdir (struct xdr_stream *xdr,const struct nfs4_readdir_arg *readdir,struct rpc_rqst *req) +static int +encode_readdir (struct xdr_stream *xdr,const struct nfs4_readdir_arg *readdir, +struct rpc_rqst *req,struct compound_hdr *hdr) {uint32_t attrs[2 ] = {FATTR4_WORD0_RDATTR_ERROR |FATTR4_WORD0_FILEID ,
@@ -1191,6 +1257,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg attrs[1 ] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID ;WRITE32 (attrs[0 ] & readdir->bitmask[0 ]);WRITE32 (attrs[1 ] & readdir->bitmask[1 ]); + hdr->nops++; dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", __func__, (unsigned long long)readdir->cookie,
@@ -1202,17 +1269,22 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_argreturn 0 ; } -static int encode_readlink (struct xdr_stream *xdr,const struct nfs4_readlink *readlink,struct rpc_rqst *req) +static int +encode_readlink (struct xdr_stream *xdr,const struct nfs4_readlink *readlink, +struct rpc_rqst *req,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_READLINK ); + hdr->nops++;return 0 ; } -static int encode_remove (struct xdr_stream *xdr,const struct qstr *name) +static int +encode_remove (struct xdr_stream *xdr,const struct qstr *name, +struct compound_hdr *hdr) {__be32 *p;
@@ -1220,11 +1292,14 @@ static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)WRITE32 (OP_REMOVE );WRITE32 (name->len);WRITEMEM (name->name, name->len); + hdr->nops++;return 0 ; } -static int encode_rename (struct xdr_stream *xdr,const struct qstr *oldname,const struct qstr *newname) +static int +encode_rename (struct xdr_stream *xdr,const struct qstr *oldname, +const struct qstr *newname,struct compound_hdr *hdr) {__be32 *p;
@@ -1236,34 +1311,40 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, conRESERVE_SPACE (4 + newname->len);WRITE32 (newname->len);WRITEMEM (newname->name, newname->len); + hdr->nops++;return 0 ; } -static int encode_renew (struct xdr_stream *xdr,const struct nfs_client *client_stateid) +static int +encode_renew (struct xdr_stream *xdr,const struct nfs_client *client_stateid, +struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (12 );WRITE32 (OP_RENEW );WRITE64 (client_stateid->cl_clientid); + hdr->nops++;return 0 ; }static int -encode_restorefh (struct xdr_stream *xdr) +encode_restorefh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_RESTOREFH ); + hdr->nops++;return 0 ; }static int -encode_setacl (struct xdr_stream *xdr,struct nfs_setaclargs *arg) +encode_setacl (struct xdr_stream *xdr,struct nfs_setaclargs *arg, +struct compound_hdr *hdr) {__be32 *p;
@@ -1278,21 +1359,25 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)RESERVE_SPACE (4 );WRITE32 (arg->acl_len);xdr_write_pages (xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); + hdr->nops++;return 0 ; }static int -encode_savefh (struct xdr_stream *xdr) +encode_savefh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_SAVEFH ); + hdr->nops++;return 0 ; } -static int encode_setattr (struct xdr_stream *xdr,const struct nfs_setattrargs *arg,const struct nfs_server *server) +static int +encode_setattr (struct xdr_stream *xdr,const struct nfs_setattrargs *arg, +const struct nfs_server *server,struct compound_hdr *hdr) {int status;__be32 *p;
@@ -1300,6 +1385,7 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *RESERVE_SPACE (4 +NFS4_STATEID_SIZE );WRITE32 (OP_SETATTR );WRITEMEM (arg->stateid.data,NFS4_STATEID_SIZE ); + hdr->nops++;if ((status =encode_attrs (xdr, arg->iap, server)))return status;
@@ -1307,7 +1393,10 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *return 0 ; } -static int encode_setclientid (struct xdr_stream *xdr,const struct nfs4_setclientid *setclientid) +static int +encode_setclientid (struct xdr_stream *xdr, +const struct nfs4_setclientid *setclientid, +struct compound_hdr *hdr) {__be32 *p;
@@ -1322,11 +1411,15 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclienencode_string (xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);RESERVE_SPACE (4 );WRITE32 (setclientid->sc_cb_ident); + hdr->nops++;return 0 ; } -static int encode_setclientid_confirm (struct xdr_stream *xdr,const struct nfs_client *client_state) +static int +encode_setclientid_confirm (struct xdr_stream *xdr, +const struct nfs_client *client_state, +struct compound_hdr *hdr) {__be32 *p;
@@ -1334,11 +1427,14 @@ static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_cWRITE32 (OP_SETCLIENTID_CONFIRM );WRITE64 (client_state->cl_clientid);WRITEMEM (client_state->cl_confirm.data,NFS4_VERIFIER_SIZE ); + hdr->nops++;return 0 ; } -static int encode_write (struct xdr_stream *xdr,const struct nfs_writeargs *args) +static int +encode_write (struct xdr_stream *xdr,const struct nfs_writeargs *args, +struct compound_hdr *hdr) {__be32 *p;
@@ -1353,11 +1449,14 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *argsWRITE32 (args->count);xdr_write_pages (xdr, args->pages, args->pgbase, args->count); + hdr->nops++;return 0 ; } -static int encode_delegreturn (struct xdr_stream *xdr,const nfs4_stateid *stateid) +static int +encode_delegreturn (struct xdr_stream *xdr,const nfs4_stateid *stateid, +struct compound_hdr *hdr) {__be32 *p;
@@ -1365,6 +1464,7 @@ static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateiWRITE32 (OP_DELEGRETURN );WRITEMEM (stateid->data,NFS4_STATEID_SIZE ); + hdr->nops++;return 0 ; }
@@ -1379,20 +1479,22 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status !=0 ) goto out; - status =encode_access (&xdr, args->access); + status =encode_access (&xdr, args->access, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1403,20 +1505,22 @@ static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =4 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_lookup (&xdr, args->name)) !=0 ) +if ((status =encode_lookup (&xdr, args->name, &hdr)) !=0 ) goto out; -if ((status =encode_getfh (&xdr)) !=0 ) +if ((status =encode_getfh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1427,17 +1531,19 @@ static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struc {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putrootfh (&xdr)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putrootfh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_getfh (&xdr)) ==0 ) - status =encode_getfattr (&xdr, args->bitmask); +if ((status =encode_getfh (&xdr, &hdr)) ==0 ) + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1448,18 +1554,20 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->fh, &hdr)) !=0 ) goto out; -if ((status =encode_remove (&xdr, &args->name)) !=0 ) +if ((status =encode_remove (&xdr, &args->name, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1470,26 +1578,29 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->old_dir)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->old_dir, &hdr)) !=0 ) goto out; -if ((status =encode_savefh (&xdr)) !=0 ) +if ((status =encode_savefh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_putfh (&xdr, args->new_dir)) !=0 ) +if ((status =encode_putfh (&xdr, args->new_dir, &hdr)) !=0 ) goto out; -if ((status =encode_rename (&xdr, args->old_name, args->new_name)) !=0 ) +if ((status =encode_rename (&xdr, args->old_name, args->new_name, + &hdr)) !=0 ) goto out; -if ((status =encode_getfattr (&xdr, args->bitmask)) !=0 ) +if ((status =encode_getfattr (&xdr, args->bitmask, &hdr)) !=0 ) goto out; -if ((status =encode_restorefh (&xdr)) !=0 ) +if ((status =encode_restorefh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1500,26 +1611,28 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->fh, &hdr)) !=0 ) goto out; -if ((status =encode_savefh (&xdr)) !=0 ) +if ((status =encode_savefh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_link (&xdr, args->name)) !=0 ) +if ((status =encode_link (&xdr, args->name, &hdr)) !=0 ) goto out; -if ((status =encode_getfattr (&xdr, args->bitmask)) !=0 ) +if ((status =encode_getfattr (&xdr, args->bitmask, &hdr)) !=0 ) goto out; -if ((status =encode_restorefh (&xdr)) !=0 ) +if ((status =encode_restorefh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1530,26 +1643,28 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_savefh (&xdr)) !=0 ) +if ((status =encode_savefh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_create (&xdr, args)) !=0 ) +if ((status =encode_create (&xdr, args, &hdr)) !=0 ) goto out; -if ((status =encode_getfh (&xdr)) !=0 ) +if ((status =encode_getfh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_getfattr (&xdr, args->bitmask)) !=0 ) +if ((status =encode_getfattr (&xdr, args->bitmask, &hdr)) !=0 ) goto out; -if ((status =encode_restorefh (&xdr)) !=0 ) +if ((status =encode_restorefh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1568,14 +1683,16 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->fh)) ==0 ) - status =encode_getfattr (&xdr, args->bitmask); + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->fh, &hdr)) ==0 ) + status =encode_getfattr (&xdr, args->bitmask, &hdr); +encode_nops (nops, &hdr);return status; }
@@ -1586,20 +1703,22 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closea {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_close (&xdr, args); + status =encode_close (&xdr, args, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1610,32 +1729,34 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openarg {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_savefh (&xdr); + status =encode_savefh (&xdr, &hdr);if (status) goto out; - status =encode_open (&xdr, args); + status =encode_open (&xdr, args, &hdr);if (status) goto out; - status =encode_getfh (&xdr); + status =encode_getfh (&xdr, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr);if (status) goto out; - status =encode_restorefh (&xdr); + status =encode_restorefh (&xdr, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1646,17 +1767,19 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_open_confirm (&xdr, args); + status =encode_open_confirm (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1667,20 +1790,22 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_open (&xdr, args); + status =encode_open (&xdr, args, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1691,20 +1816,22 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct n {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_open_downgrade (&xdr, args); + status =encode_open_downgrade (&xdr, args, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1715,17 +1842,19 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_ar {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_lock (&xdr, args); + status =encode_lock (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1736,17 +1865,19 @@ static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_lockt (&xdr, args); + status =encode_lockt (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1757,17 +1888,19 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_locku (&xdr, args); + status =encode_locku (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1778,18 +1911,19 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;unsigned int replen;int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_readlink (&xdr, args, req); + status =encode_readlink (&xdr, args, req, &hdr);/* set up reply kvec * toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -1800,6 +1934,7 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n args->pgbase, args->pglen); out: +encode_nops (nops, &hdr);return status; }
@@ -1810,18 +1945,19 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;int replen;int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_readdir (&xdr, args, req); + status =encode_readdir (&xdr, args, req, &hdr);/* set up reply kvec * toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -1835,6 +1971,7 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf args->pgbase, args->count); out: +encode_nops (nops, &hdr);return status; }
@@ -1846,16 +1983,17 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargstruct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int replen, status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_read (&xdr, args); + status =encode_read (&xdr, args, &hdr);if (status) goto out;
@@ -1868,6 +2006,7 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readarg args->pages, args->pgbase, args->count); req->rq_rcv_buf.flags |=XDRBUF_READ ; out: +encode_nops (nops, &hdr);return status; }
@@ -1877,23 +2016,25 @@ out:static int nfs4_xdr_enc_setattr (struct rpc_rqst *req,__be32 *p,struct nfs_setattrargs *args) { -struct xdr_stream xdr; -struct compound_hdr hdr = { - .nops =3 , - }; -int status; +struct xdr_stream xdr; +struct compound_hdr hdr = { + .nops =0 , + }; +int status; +__be32 *nops; -xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); -if (status) - goto out; - status =encode_setattr (&xdr, args, args->server); -if (status) - goto out; - status =encode_getfattr (&xdr, args->bitmask); +xdr_init_encode (&xdr, &req->rq_snd_buf, p); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr); +if (status) + goto out; + status =encode_setattr (&xdr, args, args->server, &hdr); +if (status) + goto out; + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: -return status; +encode_nops (nops, &hdr); +return status; }/*
@@ -1906,21 +2047,23 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,struct xdr_stream xdr;struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int replen, status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_getattr_two (&xdr,FATTR4_WORD0_ACL ,0 ); + status =encode_getattr_two (&xdr,FATTR4_WORD0_ACL ,0 , &hdr);/* set up reply buffer: */ replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) <<2 ;xdr_inline_pages (&req->rq_rcv_buf, replen, args->acl_pages, args->acl_pgbase, args->acl_len); out: +encode_nops (nops, &hdr);return status; }
@@ -1931,21 +2074,23 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writea {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_write (&xdr, args); + status =encode_write (&xdr, args, &hdr);if (status) goto out; req->rq_snd_buf.flags |=XDRBUF_WRITE ; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1956,20 +2101,22 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_write {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_commit (&xdr, args); + status =encode_commit (&xdr, args, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -1980,15 +2127,17 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (!status) - status =encode_fsinfo (&xdr, args->bitmask); + status =encode_fsinfo (&xdr, args->bitmask, &hdr); +encode_nops (nops, &hdr);return status; }
@@ -1999,16 +2148,19 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (!status) status =encode_getattr_one (&xdr, - args->bitmask[0 ] & nfs4_pathconf_bitmap[0 ]); + args->bitmask[0 ] & nfs4_pathconf_bitmap[0 ], + &hdr); +encode_nops (nops, &hdr);return status; }
@@ -2019,17 +2171,19 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status ==0 ) status =encode_getattr_two (&xdr, args->bitmask[0 ] & nfs4_statfs_bitmap[0 ], - args->bitmask[1 ] & nfs4_statfs_bitmap[1 ]); + args->bitmask[1 ] & nfs4_statfs_bitmap[1 ], &hdr); +encode_nops (nops, &hdr);return status; }
@@ -2040,18 +2194,20 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struc {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, fhandle); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, fhandle, &hdr);if (status ==0 ) status =encode_getattr_one (&xdr,FATTR4_WORD0_SUPPORTED_ATTRS |FATTR4_WORD0_LINK_SUPPORT |FATTR4_WORD0_SYMLINK_SUPPORT | -FATTR4_WORD0_ACLSUPPORT ); +FATTR4_WORD0_ACLSUPPORT , &hdr); +encode_nops (nops, &hdr);return status; }
@@ -2062,12 +2218,16 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =1 , + .nops =0 , }; +int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -return encode_renew (&xdr, clp); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_renew (&xdr, clp, &hdr); +encode_nops (nops, &hdr); +return status; }/*
@@ -2077,12 +2237,16 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4 {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =1 , + .nops =0 , }; +int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -return encode_setclientid (&xdr, sc); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_setclientid (&xdr, sc, &hdr); +encode_nops (nops, &hdr); +return status; }/*
@@ -2092,18 +2256,20 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };const u32 lease_bitmap[2 ] = {FATTR4_WORD0_LEASE_TIME ,0 };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_setclientid_confirm (&xdr, clp); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_setclientid_confirm (&xdr, clp, &hdr);if (!status) - status =encode_putrootfh (&xdr); + status =encode_putrootfh (&xdr, &hdr);if (!status) - status =encode_fsinfo (&xdr, lease_bitmap); + status =encode_fsinfo (&xdr, lease_bitmap, &hdr); +encode_nops (nops, &hdr);return status; }
@@ -2114,20 +2280,22 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struc {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fhandle); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fhandle, &hdr);if (status !=0 ) goto out; - status =encode_delegreturn (&xdr, args->stateid); + status =encode_delegreturn (&xdr, args->stateid, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }
@@ -2138,19 +2306,20 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;int replen;int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_lookup (&xdr, args->name)) !=0 ) +if ((status =encode_lookup (&xdr, args->name, &hdr)) !=0 ) goto out; -if ((status =encode_fs_locations (&xdr, args->bitmask)) !=0 ) +if ((status =encode_fs_locations (&xdr, args->bitmask, &hdr)) !=0 ) goto out;/* set up reply * toplevel_status + OP_PUTFH + status
@@ -2160,6 +2329,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfsxdr_inline_pages (&req->rq_rcv_buf, replen, &args->page,0 ,PAGE_SIZE ); out: +encode_nops (nops, &hdr);return status; }
@@ -4036,20 +4206,22 @@ out:static int nfs4_xdr_enc_setacl (struct rpc_rqst *req,__be32 *p,struct nfs_setaclargs *args) { -struct xdr_stream xdr; -struct compound_hdr hdr = { - .nops =2 , - }; -int status; +struct xdr_stream xdr; +struct compound_hdr hdr = { + .nops =0 , + }; +int status; +__be32 *nops; -xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); -if (status) - goto out; - status =encode_setacl (&xdr, args); +xdr_init_encode (&xdr, &req->rq_snd_buf, p); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr); +if (status) + goto out; + status =encode_setacl (&xdr, args, &hdr); out: -return status; +encode_nops (nops, &hdr); +return status; }/* * Decode SETACL response
Signature · 1 line
1.6.0.2
RFC 5/85 nfs41: Add Kconfig symbols for NFSv4.1
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Added CONFIG_NFS_V4_1 and made it depend upon CONFIG_NFS_V4 and EXPERIMENTAL.
--- fs/Kconfig | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
fs/Kconfig +9 -0
@@ -1216,6 +1216,15 @@ config NFS_V4 If unsure, say N. +config NFS_V4_1 + bool "NFS client support for NFSv4.1 (EXPERIMENTAL)" + depends on NFS_V4 && EXPERIMENTAL + help + This option enables support for minor version 1 of the NFSv4 protocol + (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client. + + If unsure, say N. + config ROOT_NFS bool "Root file system on NFS" depends on NFS_FS=y && IP_PNP
Signature · 1 line
1.6.0.2
RFC 6/85 nfs41: common protocol definitions
In reply to Benny Halevynfs41: define all NFSv4.1 operation and error code constants.
Note that some of the definitions are used by both the nfs41 client and the server code (hence enclosed in defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)).
--- include/linux/nfs.h | 19 ++++++++- include/linux/nfs4.h | 112 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 3 deletions(-)
include/linux/nfs.h +18 -1
@@ -109,7 +109,24 @@NFSERR_FILE_OPEN =10046 ,/* v4 */ NFSERR_ADMIN_REVOKED =10047 ,/* v4 */ NFSERR_CB_PATH_DOWN =10048 ,/* v4 */ - NFSERR_REPLAY_ME = 10049 /* v4 */ +NFSERR_BADIOMODE =10049 ,/* v4.1 */ +NFSERR_BADLAYOUT =10050 ,/* v4.1 */ +NFSERR_BAD_SESSION_DIGEST =10051 ,/* v4.1 */ +NFSERR_BADSESSION =10052 ,/* v4.1 */ +NFSERR_BADSLOT =10053 ,/* v4.1 */ +NFSERR_COMPLETE_ALREADY =10054 ,/* v4.1 */ +NFSERR_CONN_NOT_BOUND_TO_SESSION =10055 ,/* v4.1 */ +NFSERR_DELEG_ALREADY_WANTED =10056 ,/* v4.1 */ +NFSERR_DIRDELEG_UNAVAIL =10057 ,/* v4.1 */ +NFSERR_LAYOUTTRYLATER =10058 ,/* v4.1 */ +NFSERR_LAYOUTUNAVAILABLE =10059 ,/* v4.1 */ +NFSERR_NOMATCHING_LAYOUT =10060 ,/* v4.1 */ +NFSERR_RECALLCONFLICT =10061 ,/* v4.1 */ +NFSERR_UNKNOWN_LAYOUTTYPE =10062 ,/* v4.1 */ +NFSERR_SEQ_MISORDERED =10063 ,/* v4.1 */ +NFSERR_SEQUENCE_POS =10064 ,/* v4.1 */ + + NFSERR_REPLAY_ME = 11001, /* linux internal */ };/* NFSv2 file types - beware, these are not the same in NFSv3 */
include/linux/nfs4.h +110 -2
161 lines not on this page · raw message
Signature · 1 line
1.6.0.2
RFC 7/85 nfs41: define NFS4_MAX_MINOR_VERSION based on CONFIG_NFS_V4_1
In reply to Benny HalevyFrom: Mike Sager <[email protected]>
If 4.1 isn't supported, NFS4_MAX_MINOR_VERSION will be 0.
--- include/linux/nfs4.h | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
include/linux/nfs4.h +7 -0
@@ -435,6 +435,13 @@ enum lock_type4 {#define NFSPROC4_NULL 0#define NFSPROC4_COMPOUND 1#define NFS4_MINOR_VERSION 1 + +#if defined(CONFIG_NFS_V4_1 ) +#define NFS4_MAX_MINOR_VERSION 1 +#else +#define NFS4_MAX_MINOR_VERSION 0 +#endif /* CONFIG_NFS_V4_1 */ +#define NFS4_DEBUG 1/* Index of predefined Linux client operations */
Signature · 1 line
1.6.0.2
RFC 8/85 nfs41: client xdr definitions
In reply to Benny HalevyDefine stubs for sequence args and res data structures and embed them in all other nfs4 and nfs41 xdr types. They are needed for sending any op in a nfs41 compound rpc.
--- include/linux/nfs_xdr.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 118 insertions(+), 0 deletions(-)
include/linux/nfs_xdr.h +118 -0
@@ -113,6 +113,43 @@ struct nfs4_change_info { };struct nfs_seqid ; + +/* Opaque session ID */ +struct sessionid4 { +char data[NFS4_MAX_SESSIONID_LEN ]; +}; + +struct nfs41_sequence_args { +/* stub */ +}; + +#define SEQ4_STATUS_CB_PATH_DOWN 0x00000001 +#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING 0x00000002 +#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED 0x00000004 +#define SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED 0x00000008 +#define SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED 0x00000010 +#define SEQ4_STATUS_ADMIN_STATE_REVOKED 0x00000020 +#define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040 +#define SEQ4_STATUS_LEASE_MOVED 0x00000080 +#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100 + +struct nfs41_sequence_res { +/* stub */ +}; + +#if defined(CONFIG_NFS_V4_1 ) + +struct nfs4_get_lease_time_args { +struct nfs41_sequence_args la_seq_args; +}; + +struct nfs4_get_lease_time_res { +struct nfs_fsinfo *lr_fsinfo; +struct nfs41_sequence_res lr_seq_res; +}; + +#endif /* CONFIG_NFS_V4_1 */ +/* * Arguments to the open call. */
@@ -132,6 +169,7 @@ struct nfs_openargs {const struct nfs_server *server;/* Needed for ID mapping */ const u32 * bitmask;__u32 claim; +struct nfs41_sequence_args seq_args; };struct nfs_openres {
@@ -148,6 +186,7 @@ struct nfs_openres {__u32 do_recall;__u64 maxsize;__u32 attrset[NFS4_BITMAP_SIZE ]; +struct nfs41_sequence_res seq_res; };/*
@@ -173,6 +212,7 @@ struct nfs_closeargs {struct nfs_seqid * seqid;int open_flags;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs_closeres {
@@ -180,6 +220,7 @@ struct nfs_closeres {struct nfs_fattr * fattr;struct nfs_seqid * seqid;const struct nfs_server *server; +struct nfs41_sequence_res seq_res; };/* * * Arguments to the lock,lockt, and locku call.
@@ -200,12 +241,14 @@ struct nfs_lock_args { unsigned char block : 1; unsigned char reclaim : 1; unsigned char new_lock_owner : 1; +struct nfs41_sequence_args seq_args; };struct nfs_lock_res {nfs4_stateid stateid;struct nfs_seqid * lock_seqid;struct nfs_seqid * open_seqid; +struct nfs41_sequence_res seq_res; };struct nfs_locku_args {
@@ -213,32 +256,38 @@ struct nfs_locku_args {struct file_lock * fl;struct nfs_seqid * seqid;nfs4_stateid * stateid; +struct nfs41_sequence_args seq_args; };struct nfs_locku_res {nfs4_stateid stateid;struct nfs_seqid * seqid; +struct nfs41_sequence_res seq_res; };struct nfs_lockt_args {struct nfs_fh * fh;struct file_lock * fl;struct nfs_lowner lock_owner; +struct nfs41_sequence_args seq_args; };struct nfs_lockt_res {struct file_lock * denied;/* LOCK, LOCKT failed */ +struct nfs41_sequence_res seq_res; };struct nfs4_delegreturnargs {const struct nfs_fh *fhandle;const nfs4_stateid *stateid;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_delegreturnres {struct nfs_fattr * fattr;const struct nfs_server *server; +struct nfs41_sequence_res seq_res; };/*
@@ -251,12 +300,14 @@ struct nfs_readargs {__u32 count;unsigned int pgbase;struct page ** pages; +struct nfs41_sequence_args seq_args; };struct nfs_readres {struct nfs_fattr * fattr;__u32 count;int eof; +struct nfs41_sequence_res seq_res; };/*
@@ -271,6 +322,7 @@ struct nfs_writeargs {unsigned int pgbase;struct page ** pages;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs_writeverf {
@@ -283,6 +335,7 @@ struct nfs_writeres {struct nfs_writeverf * verf;__u32 count;const struct nfs_server *server; +struct nfs41_sequence_res seq_res; };/*
@@ -292,12 +345,14 @@ struct nfs_removeargs {const struct nfs_fh *fh;struct qstr name;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs_removeres {const struct nfs_server *server;struct nfs4_change_info cinfo;struct nfs_fattr dir_attr; +struct nfs41_sequence_res seq_res; };/*
@@ -350,6 +405,7 @@ struct nfs_setattrargs {struct iattr * iap;const struct nfs_server * server;/* Needed for name mapping */ const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs_setaclargs {
@@ -357,6 +413,11 @@ struct nfs_setaclargs {size_t acl_len;unsigned int acl_pgbase;struct page ** acl_pages; +struct nfs41_sequence_args seq_args; +}; + +struct nfs_setaclres { +struct nfs41_sequence_res seq_res; };struct nfs_getaclargs {
@@ -364,11 +425,18 @@ struct nfs_getaclargs {size_t acl_len;unsigned int acl_pgbase;struct page ** acl_pages; +struct nfs41_sequence_args seq_args; +}; + +struct nfs_getaclres { +size_t *acl_len; +struct nfs41_sequence_res seq_res; };struct nfs_setattrres {struct nfs_fattr * fattr;const struct nfs_server * server; +struct nfs41_sequence_res seq_res; };struct nfs_linkargs {
@@ -548,6 +616,7 @@ struct nfs4_accessargs {const struct nfs_fh * fh;const u32 * bitmask;u32 access; +struct nfs41_sequence_args seq_args; };struct nfs4_accessres {
@@ -555,6 +624,7 @@ struct nfs4_accessres {struct nfs_fattr * fattr;u32 supported;u32 access; +struct nfs41_sequence_res seq_res; };struct nfs4_create_arg {
@@ -574,6 +644,7 @@ struct nfs4_create_arg {const struct iattr * attrs;const struct nfs_fh * dir_fh;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_create_res {
@@ -582,21 +653,30 @@ struct nfs4_create_res {struct nfs_fattr * fattr;struct nfs4_change_info dir_cinfo;struct nfs_fattr * dir_fattr; +struct nfs41_sequence_res seq_res; };struct nfs4_fsinfo_arg {const struct nfs_fh * fh;const u32 * bitmask; +struct nfs41_sequence_args seq_args; +}; + +struct nfs4_fsinfo_res { +struct nfs_fsinfo *fsinfo; +struct nfs41_sequence_res seq_res; };struct nfs4_getattr_arg {const struct nfs_fh * fh;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_getattr_res {const struct nfs_server * server;struct nfs_fattr * fattr; +struct nfs41_sequence_res seq_res; };struct nfs4_link_arg {
@@ -604,6 +684,7 @@ struct nfs4_link_arg {const struct nfs_fh * dir_fh;const struct qstr * name;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_link_res {
@@ -611,6 +692,7 @@ struct nfs4_link_res {struct nfs_fattr * fattr;struct nfs4_change_info cinfo;struct nfs_fattr * dir_attr; +struct nfs41_sequence_res seq_res; };
@@ -618,21 +700,30 @@ struct nfs4_lookup_arg {const struct nfs_fh * dir_fh;const struct qstr * name;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_lookup_res {const struct nfs_server * server;struct nfs_fattr * fattr;struct nfs_fh * fh; +struct nfs41_sequence_res seq_res; };struct nfs4_lookup_root_arg {const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_pathconf_arg {const struct nfs_fh * fh;const u32 * bitmask; +struct nfs41_sequence_args seq_args; +}; + +struct nfs4_pathconf_res { +struct nfs_pathconf *pathconf; +struct nfs41_sequence_res seq_res; };struct nfs4_readdir_arg {
@@ -643,11 +734,13 @@ struct nfs4_readdir_arg {struct page ** pages;/* zero-copy data */ unsigned int pgbase;/* zero-copy data */ const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_readdir_res {nfs4_verifier verifier;unsigned int pgbase; +struct nfs41_sequence_res seq_res; };struct nfs4_readlink {
@@ -655,6 +748,11 @@ struct nfs4_readlink {unsigned int pgbase;unsigned int pglen;/* zero-copy data */ struct page ** pages;/* zero-copy data */ +struct nfs41_sequence_args seq_args; +}; + +struct nfs4_readlink_res { +struct nfs41_sequence_res seq_res; };struct nfs4_rename_arg {
@@ -663,6 +761,7 @@ struct nfs4_rename_arg {const struct qstr * old_name;const struct qstr * new_name;const u32 * bitmask; +struct nfs41_sequence_args seq_args; };struct nfs4_rename_res {
@@ -671,6 +770,7 @@ struct nfs4_rename_res {struct nfs_fattr * old_fattr;struct nfs4_change_info new_cinfo;struct nfs_fattr * new_fattr; +struct nfs41_sequence_res seq_res; };#define NFS4_SETCLIENTID_NAMELEN (127)
@@ -689,6 +789,17 @@ struct nfs4_setclientid {struct nfs4_statfs_arg {const struct nfs_fh * fh;const u32 * bitmask; +struct nfs41_sequence_args seq_args; +}; + +struct nfs4_statfs_res { +struct nfs_fsstat *fsstat; +struct nfs41_sequence_res seq_res; +}; + +struct nfs4_server_caps_arg { +struct nfs_fh *fhandle; +struct nfs41_sequence_args seq_args; };struct nfs4_server_caps_res {
@@ -696,6 +807,7 @@ struct nfs4_server_caps_res {u32 acl_bitmask;u32 has_links;u32 has_symlinks; +struct nfs41_sequence_res seq_res; };struct nfs4_string {
@@ -730,6 +842,12 @@ struct nfs4_fs_locations_arg {const struct qstr *name;struct page *page;const u32 *bitmask; + struct nfs41_sequence_args seq_args; +}; + +struct nfs4_fs_locations_res { +struct nfs4_fs_locations *fs_locations; +struct nfs41_sequence_res seq_res; };#endif /* CONFIG_NFS_V4 */
Signature · 1 line
1.6.0.2
RFC 9/85 nfs41: add mount command option minorvers
In reply to Benny HalevyFrom: Mike Sager <[email protected]>
mount -t nfs4 -o minorvers=[0|1] specifies whether to use 4.0 or 4.1. The default is 1.
--- fs/nfs/internal.h | 1 + fs/nfs/super.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 0 deletions(-)
fs/nfs/internal.h +1 -0
@@ -41,6 +41,7 @@ struct nfs_parsed_mount_data {unsigned int auth_flavor_len;rpc_authflavor_t auth_flavors[1 ];char *client_address; +unsigned int minorversion;struct {struct sockaddr_storage address;
fs/nfs/super.c +10 -0
@@ -87,6 +87,7 @@ enum { Opt_mountport, Opt_mountvers, Opt_nfsvers, + Opt_minorversion,/* Mount options that take string arguments */ Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
@@ -146,6 +147,7 @@ static const match_table_t nfs_mount_option_tokens = { { Opt_mountvers, "mountvers=%u" }, { Opt_nfsvers, "nfsvers=%u" }, { Opt_nfsvers, "vers=%u" }, + { Opt_minorversion, "minorversion=%u" }, { Opt_sec, "sec=%s" }, { Opt_proto, "proto=%s" },
@@ -1160,6 +1162,13 @@ static int nfs_parse_mount_options(char *raw,nfs_parse_invalid_value ("nfsvers" ); }break ; +case Opt_minorversion: +if (match_int (args, &option)) +return 0 ; +if (option <0 || option >NFS4_MAX_MINOR_VERSION ) +return 0 ; + mnt->minorversion = option; +break ;/* * options that take text values
@@ -2208,6 +2217,7 @@ static int nfs4_validate_mount_data(void *options, args->nfs_server.port =NFS_PORT ;/* 2049 unless user set port= */ args->auth_flavors[0 ] =RPC_AUTH_UNIX ; args->auth_flavor_len =0 ; + args->minorversion =NFS4_MAX_MINOR_VERSION ;switch (data->version) {case 1 :
Signature · 1 line
1.6.0.2
RFC 10/85 nfs41: struct nfs_server minorversion
In reply to Benny HalevyFrom: Mike Sager <[email protected]>
Set nfs_server minorversion from mount option (or default). During client initialization, use this minorversion.
--- fs/nfs/client.c | 2 ++ include/linux/nfs_fs_sb.h | 1 + 2 files changed, 3 insertions(+), 0 deletions(-)
fs/nfs/client.c +2 -0
@@ -1112,6 +1112,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,if (!server)return ERR_PTR (-ENOMEM ); + server->minorversion = data->minorversion; +/* set up the general RPC client */ error =nfs4_init_server (server, data);if (error <0 )
include/linux/nfs_fs_sb.h +1 -0
@@ -115,6 +115,7 @@ struct nfs_server {u32 acl_bitmask;/* V4 bitmask representing the ACEs that are supported on this filesystem */ +u32 minorversion;#endif void (*destroy)(struct nfs_server *);
Signature · 1 line
1.6.0.2
RFC 11/85 nfs41: nfs_client.cl_minorversion
In reply to Benny HalevyThis field is set to the nfsv4 minor version for this mount.
--- fs/nfs/client.c | 1 + include/linux/nfs_fs_sb.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletions(-)
fs/nfs/client.c +1 -0
@@ -1030,6 +1030,7 @@ static int nfs4_set_client(struct nfs_server *server, error =PTR_ERR (clp); goto error; } + clp->cl_minorversion = server->minorversion; error =nfs4_init_client (clp, timeparms, ip_addr, authflavour);if (error <0 ) goto error_put;
include/linux/nfs_fs_sb.h +2 -1
@@ -69,7 +69,8 @@ struct nfs_client {*/ char cl_ipaddr[48 ];unsigned char cl_id_uniquifier; -#endif +u32 cl_minorversion; +#endif /* CONFIG_NFS_V4 */ };/*
Signature · 1 line
1.6.0.2
RFC 12/85 nfs41: set nfs_client rpc_ops based on minorversion
In reply to Benny Halevy--- fs/nfs/client.c | 6 ++-- fs/nfs/nfs4proc.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/nfs_xdr.h | 3 ++ 3 files changed, 54 insertions(+), 4 deletions(-)
fs/nfs/client.c +3 -3
@@ -359,7 +359,8 @@ static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_inint error;dprintk ("--> nfs_get_client(%s,v%u)\n" , - cl_init->hostname ?:"" , cl_init->rpc_ops->version); + cl_init->hostname ?:"" , + cl_init->rpc_ops ? cl_init->rpc_ops->version :0 );/* see if the client already exists */ do {
@@ -976,7 +977,7 @@ static int nfs4_init_client(struct nfs_client *clp, }/* Check NFS protocol revision and initialize RPC op vector */ - clp->rpc_ops = &nfs_v4_clientops; + clp->rpc_ops = nfsv4_minorversion_clientops[clp->cl_minorversion]; error =nfs_create_rpc_client (clp, timeparms, authflavour,RPC_CLNT_CREATE_DISCRTRY );
@@ -1016,7 +1017,6 @@ static int nfs4_set_client(struct nfs_server *server, .hostname = hostname, .addr = addr, .addrlen = addrlen, - .rpc_ops = &nfs_v4_clientops, .proto = proto, };struct nfs_client *clp;
fs/nfs/nfs4proc.c +48 -1
61 lines not on this page · raw message
include/linux/nfs_xdr.h +3 -0
@@ -966,6 +966,9 @@ struct nfs_rpc_ops {extern const struct nfs_rpc_ops nfs_v2_clientops;extern const struct nfs_rpc_ops nfs_v3_clientops;extern const struct nfs_rpc_ops nfs_v4_clientops; +extern const struct nfs_rpc_ops nfs_v40_clientops; +extern const struct nfs_rpc_ops nfs_v41_clientops; +extern const struct nfs_rpc_ops *nfsv4_minorversion_clientops[];extern struct rpc_version nfs_version2;extern struct rpc_version nfs_version3;extern struct rpc_version nfs_version4;
Signature · 1 line
1.6.0.2
RFC 13/85 nfs41: use ptr to rpc procedures via struct nfs_client
In reply to Benny HalevyTo support heterogenuous mount minor version, use the ptr to the effective rpc procedures table via nfs_client->cl_rpcclient->cl_procinfo rather than a global one.
nfs4_proc() is a static inline helper to get the rpc procedure given a struct nfs_client * and the procedure index.
--- fs/nfs/internal.h | 5 --- fs/nfs/nfs4_fs.h | 1 - fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++------------------- fs/nfs/nfs4xdr.c | 22 +++++++++-- include/linux/nfs_fs_sb.h | 9 +++++ include/linux/nfs_xdr.h | 3 ++ 6 files changed, 81 insertions(+), 47 deletions(-)
fs/nfs/internal.h +0 -5
@@ -134,11 +134,6 @@ extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);extern __be32 *nfs4_decode_dirent (__be32 *p,struct nfs_entry *entry,int plus);#endif -/* nfs4proc.c */ -#ifdef CONFIG_NFS_V4 -extern struct rpc_procinfo nfs4_procedures[]; -#endif -/* dir.c */ extern int nfs_access_cache_shrinker (int nr_to_scan,gfp_t gfp_mask);
fs/nfs/nfs4_fs.h +0 -1
@@ -226,7 +226,6 @@ extern const nfs4_stateid zero_stateid;/* nfs4xdr.c */ extern __be32 *nfs4_decode_dirent (__be32 *p,struct nfs_entry *entry,int plus); -extern struct rpc_procinfo nfs4_procedures[];struct nfs4_mount_data ;
fs/nfs/nfs4proc.c +51 -37
320 lines not on this page · raw message
fs/nfs/nfs4xdr.c +18 -4
@@ -4922,11 +4922,25 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), }; -struct rpc_version nfs_version4 = { - .number =4 , - .nrprocs =ARRAY_SIZE (nfs4_procedures), - .procs = nfs4_procedures +#if defined(CONFIG_NFS_V4_1 ) +struct rpc_procinfo nfs41_procedures[] = { }; +#endif /* CONFIG_NFS_V4_1 */ + +struct rpc_version nfs_version4 = { + .number =4 , + .nrprocs =ARRAY_SIZE (nfs4_procedures), + .procs = nfs4_procedures +}; + +#ifdef CONFIG_NFS_V4_1 +struct rpc_version nfs_version41 = { + .number =4 , + .nrprocs =ARRAY_SIZE (nfs41_procedures), + .procs = nfs41_procedures +}; + +#endif /* CONFIG_NFS_V4_1 */ /* * Local variables:
include/linux/nfs_fs_sb.h +9 -0
@@ -73,6 +73,15 @@ struct nfs_client {#endif /* CONFIG_NFS_V4 */ }; +#ifdef CONFIG_NFS_V4 +static inline struct rpc_procinfo * +nfs4_proc (struct nfs_client *clp,int idx) +{ +struct rpc_procinfo *procs = clp->cl_rpcclient->cl_procinfo; +return &procs[idx]; +} +#endif /* CONFIG_NFS_V4 */ +/* * NFS client parameters stored in the superblock. */
include/linux/nfs_xdr.h +3 -0
@@ -969,6 +969,9 @@ extern const struct nfs_rpc_ops nfs_v4_clientops;extern const struct nfs_rpc_ops nfs_v40_clientops;extern const struct nfs_rpc_ops nfs_v41_clientops;extern const struct nfs_rpc_ops *nfsv4_minorversion_clientops[]; +extern struct rpc_version *nfs4_minorversions[]; +extern struct rpc_procinfo *nfs4_minorversion_procedures[]; +extern struct rpc_version nfs_version2;extern struct rpc_version nfs_version3;extern struct rpc_version nfs_version4;
Signature · 1 line
1.6.0.2
RFC 14/85 nfs41: sunrpc: support minorversion for rpc_clnt version table.
In reply to Benny HalevyValidate minorversion only if not zero as legacy code declares nrminorvers==0 and that should work just fine with minorversion==0 argument.
Pass minorversion down to rpc_create in nfs_create_rpc_client
--- fs/nfs/client.c | 17 ++++++++++++++--- include/linux/nfs_xdr.h | 3 +++ include/linux/sunrpc/clnt.h | 10 +++++++++- net/sunrpc/clnt.c | 13 ++++++++----- 4 files changed, 34 insertions(+), 9 deletions(-)
fs/nfs/client.c +14 -3
@@ -56,7 +56,10 @@ static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);/* * RPC cruft for NFS */ -static struct rpc_version *nfs_version[5 ] = { +#define NFS_MAXVERSION 4 + +static struct rpc_version *nfs_version[(NFS_MAXVERSION +1 ) * + (NFS4_MAX_MINOR_VERSION +1 )] = { [2 ] = &nfs_version2, #ifdef CONFIG_NFS_V3 [3] = &nfs_version3,
@@ -64,12 +67,16 @@ static struct rpc_version *nfs_version[5] = { #ifdef CONFIG_NFS_V4 [4] = &nfs_version4, #endif +#ifdef CONFIG_NFS_V4_1 + [(NFS_MAXVERSION + 1) + 4] = &nfs_version41, +#endif /* CONFIG_NFS_V4_1 */ }; struct rpc_program nfs_program = { .name = "nfs", .number = NFS_PROGRAM, - .nrvers =ARRAY_SIZE (nfs_version), + .nrvers = NFS_MAXVERSION + 1, + .nrminorvers = NFS4_MAX_MINOR_VERSION + 1, .version = nfs_version, .stats = &nfs_rpcstat, .pipe_dir_name = "/nfs",
@@ -482,6 +489,9 @@ static int nfs_create_rpc_client(struct nfs_client *clp, .servername = clp->cl_hostname, .program = &nfs_program, .version = clp->rpc_ops->version, +#ifdef CONFIG_NFS_V4 + .minorversion = clp->cl_minorversion, +#endif /* CONFIG_NFS_V4 */ .authflavor = flavor, .flags = flags, };
@@ -550,7 +560,7 @@ static void nfs_init_server_aclclient(struct nfs_server *server)if (server->flags &NFS_MOUNT_NOACL ) goto out_noacl; - server->client_acl =rpc_bind_new_program (server->client, &nfsacl_program,3 ); + server->client_acl =rpc_bind_new_program (server->client, &nfsacl_program,3 ,0 );if (IS_ERR (server->client_acl)) goto out_noacl;
@@ -970,6 +980,7 @@ static int nfs4_init_client(struct nfs_client *clp, {int error; +dprintk ("--> nfs4_init_client minorversion %u\n" , clp->cl_minorversion);if (clp->cl_cons_state ==NFS_CS_READY ) {/* the client is initialised already */ dprintk ("<-- nfs4_init_client() = 0 [already %p]\n" , clp);
include/linux/nfs_xdr.h +3 -0
@@ -975,6 +975,9 @@ extern struct rpc_procinfo *nfs4_minorversion_procedures[];extern struct rpc_version nfs_version2;extern struct rpc_version nfs_version3;extern struct rpc_version nfs_version4; +#if defined(CONFIG_NFS_V4_1 ) +extern struct rpc_version nfs_version41; +#endif /* CONFIG_NFS_V4_1 */ extern struct rpc_version nfsacl_version3;extern struct rpc_program nfsacl_program;
include/linux/sunrpc/clnt.h +9 -1
@@ -68,11 +68,18 @@ struct rpc_program {char * name;/* protocol name */ u32 number;/* program number */ unsigned int nrvers;/* number of versions */ +unsigned int nrminorvers;/* number of minor versions */ struct rpc_version ** version;/* version array */ struct rpc_stat * stats;/* statistics */ char * pipe_dir_name;/* path to rpc_pipefs dir */ }; +static inline struct rpc_version * +get_rpc_version (struct rpc_program *prog,u32 vers,int minorvers) +{ +return prog->version[minorvers * prog->nrvers + vers]; +} +struct rpc_version {u32 number;/* version number */ unsigned int nrprocs;/* number of procs */
@@ -106,6 +113,7 @@ struct rpc_create_args {struct rpc_program *program;u32 prognumber;/* overrides program->number */ u32 version; +unsigned char minorversion;rpc_authflavor_t authflavor;unsigned long flags; };
@@ -120,7 +128,7 @@ struct rpc_create_args {struct rpc_clnt *rpc_create (struct rpc_create_args *args);struct rpc_clnt *rpc_bind_new_program (struct rpc_clnt *, -struct rpc_program *,u32 ); +struct rpc_program *,u32 ,int minorversion);struct rpc_clnt *rpc_clone_client (struct rpc_clnt *);void rpc_shutdown_client (struct rpc_clnt *);void rpc_release_client (struct rpc_clnt *);
net/sunrpc/clnt.c +8 -5
@@ -148,9 +148,10 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struif (!xprt) goto out_no_xprt; -if (args->version >= program->nrvers) +if (args->version >= program->nrvers || + (args->minorversion && args->minorversion >= program->nrminorvers)) goto out_err; - version = program->version[args->version]; + version =get_rpc_version (program, args->version, args->minorversion);if (version ==NULL ) goto out_err;
@@ -472,14 +473,16 @@ rpc_release_client(struct rpc_clnt *clnt)*/ struct rpc_clnt *rpc_bind_new_program (struct rpc_clnt *old,struct rpc_program *program, -u32 vers) +u32 vers,int minorversion) {struct rpc_clnt *clnt;struct rpc_version *version;int err; -BUG_ON (vers >= program->nrvers || !program->version[vers]); - version = program->version[vers]; +BUG_ON (vers >= program->nrvers || + (minorversion && minorversion >= program->nrminorvers) || + !get_rpc_version (program, vers, minorversion)); + version =get_rpc_version (program, vers, minorversion); clnt =rpc_clone_client (old);if (IS_ERR (clnt)) goto out;
Signature · 1 line
1.6.0.2
RFC 15/85 nfs41: Proper initialization of nfs_client_initdata.rpc_ops
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
The rpc_ops needs to be initialized to the proper minor version clientops so that nfs_get_client() can find an existing nfs_client structure if a mount to the same server has already occurred.
This enables the traditional sharing of nfs_client structures, as well as fixes the problem where mounts of the same filesystem on the same mountpoint were not being detected correctly.
--- fs/nfs/client.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
fs/nfs/client.c +2 -0
@@ -1028,6 +1028,8 @@ static int nfs4_set_client(struct nfs_server *server, .hostname = hostname, .addr = addr, .addrlen = addrlen, + .rpc_ops = + nfsv4_minorversion_clientops[server->minorversion], .proto = proto, };struct nfs_client *clp;
Signature · 1 line
1.6.0.2
RFC 16/85 nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover
In reply to Benny Halevystatus is cleared on recovery start and may be left as non-zero if recovery failed so it can be picked up by an upper layer caller (e.g. nfs4_create_server)
--- fs/nfs/nfs4proc.c | 2 ++ fs/nfs/nfs4state.c | 5 ++++- include/linux/nfs_fs_sb.h | 1 + 3 files changed, 7 insertions(+), 1 deletions(-)
fs/nfs/nfs4proc.c +2 -0
@@ -2802,6 +2802,8 @@ static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp) res =wait_on_bit (&clp->cl_state,NFS4CLNT_STATE_RECOVER , nfs4_wait_bit_killable,TASK_KILLABLE ); +if (!res) + res = clp->cl_recovery_status;rwsem_release (&clp->cl_sem.dep_map,1 , _RET_IP_);return res;
fs/nfs/nfs4state.c +4 -1
@@ -814,8 +814,10 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp) {if (!clp)return ; -if (test_and_set_bit (NFS4CLNT_STATE_RECOVER , &clp->cl_state) ==0 ) +if (test_and_set_bit (NFS4CLNT_STATE_RECOVER , &clp->cl_state) ==0 ) { + clp->cl_recovery_status =0 ;nfs4_recover_state (clp); + } }static int nfs4_reclaim_locks (struct nfs4_state_recovery_ops *ops,struct nfs4_state *state)
@@ -1018,6 +1020,7 @@ out: out_error:printk (KERN_WARNING "Error: state recovery failed on NFSv4 server %s" " with error %d\n" , clp->cl_hostname, -status); + clp->cl_recovery_status = status;set_bit (NFS4CLNT_LEASE_EXPIRED , &clp->cl_state); goto out; }
include/linux/nfs_fs_sb.h +1 -0
@@ -38,6 +38,7 @@ struct nfs_client {u64 cl_clientid;/* constant */ nfs4_verifier cl_confirm;unsigned long cl_state; +int cl_recovery_status;struct rb_root cl_openowner_id;struct rb_root cl_lockowner_id;
Signature · 1 line
1.6.0.2
RFC 17/85 nfs41: fallback to lower minorversion if nfs4_create_server fails
In reply to Benny Halevyretry nfs4_create_server with lower minorversion on minorvers_mismatch error
--- fs/nfs/client.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
fs/nfs/client.c +11 -1
@@ -1118,15 +1118,17 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, {struct nfs_fattr fattr;struct nfs_server *server; +int minorvers = data->minorversion;int error;dprintk ("--> nfs4_create_server()\n" ); +retry: server =nfs_alloc_server ();if (!server)return ERR_PTR (-ENOMEM ); - server->minorversion = data->minorversion; + server->minorversion = minorvers;/* set up the general RPC client */ error =nfs4_init_server (server, data);
@@ -1168,7 +1170,15 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,return server; error: +if (server->nfs_client && server->nfs_client->cl_recovery_status) + error = server->nfs_client->cl_recovery_status;nfs_free_server (server); +if (minorvers >0 && error == -NFS4ERR_MINOR_VERS_MISMATCH ) { + minorvers--; +dprintk ("%s: error %d retrying with minorvers=%d\n" , + __func__, error, minorvers); + goto retry; + }dprintk ("<-- nfs4_create_server() = error %d\n" , error);return ERR_PTR (error); }
Signature · 1 line
1.6.0.2
RFC 18/85 nfs41: sessions client infrastructure
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
NFSv4.1 Sessions basic data types, initialization, and destruction.
The session is always associated with a struct nfs_client that holds the exchange_id results. Add an nfs_client struct backpointer to the session and refactor the session recovery routines to only require a struct nfs4_sessions parameter.
--- fs/nfs/client.c | 40 +++++++++++++++++++++++++++++++++++++ fs/nfs/internal.h | 1 + fs/nfs/nfs4_fs.h | 4 +++ fs/nfs/nfs4proc.c | 35 ++++++++++++++++++++++++++++++++ include/linux/nfs4_session.h | 45 ++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs_fs_sb.h | 5 ++++ 6 files changed, 130 insertions(+), 0 deletions(-) create mode 100644 include/linux/nfs4_session.h
fs/nfs/client.c +40 -0
@@ -37,6 +37,9 @@#include <linux/in6.h> #include <net/ipv6.h> #include <linux/nfs_xdr.h> +#if defined(CONFIG_NFS_V4_1 ) +#include <linux/nfs4_session.h> +#endif /* CONFIG_NFS_V4_1 */ #include <asm/system.h>
@@ -884,6 +887,11 @@ void nfs_free_server(struct nfs_server *server)list_del (&server->master_link);spin_unlock (&nfs_client_lock); +#ifdef CONFIG_NFS_V4_1 +if (server->nfs_client->cl_session !=NULL ) +nfs4_put_session (&server->nfs_client->cl_session); +#endif /* CONFIG_NFS_V4_1 */ +if (server->destroy !=NULL ) server->destroy (server);
@@ -1110,6 +1118,34 @@ error: }/* +* Allocate and initialize a session if required +*/ +int nfs4_init_session (struct nfs_client *clp,struct rpc_clnt *clnt) +{ +int error =0 ; + +#if defined(CONFIG_NFS_V4_1 ) +if (clp->cl_minorversion) { +struct nfs4_session *session =NULL ; +/* +* Create the session and mark it expired. +* When a SEQUENCE operation encounters the expired session +* it will do session recovery to initialize it. +*/ + session =nfs4_alloc_session (); +if (!session) + error = -ENOMEM ; +else { + session->clnt = clnt; + session->clp = clp; + } + clp->cl_session = session; + } +#endif /* CONFIG_NFS_V4_1 */ +return error; +} + +/* * Create a version 4 volume record * - keyed on server and FSID */
@@ -1139,6 +1175,10 @@ retry:BUG_ON (!server->nfs_client->rpc_ops);BUG_ON (!server->nfs_client->rpc_ops->file_inode_ops); + error =nfs4_init_session (server->nfs_client, server->client); +if (error) + goto error; +/* Probe the root fh to retrieve its FSID */ error =nfs4_path_walk (server, mntfh, data->nfs_server.export_path);if (error <0 )
fs/nfs/internal.h +1 -0
@@ -82,6 +82,7 @@ extern void nfs_free_server(struct nfs_server *server);extern struct nfs_server *nfs_clone_server (struct nfs_server *,struct nfs_fh *,struct nfs_fattr *); +extern int nfs4_init_session (struct nfs_client *clp,struct rpc_clnt *clnt);#ifdef CONFIG_PROC_FS extern int __init nfs_fs_proc_init (void );extern void nfs_fs_proc_exit (void );
fs/nfs/nfs4_fs.h +4 -0
@@ -188,6 +188,10 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; +#if defined(CONFIG_NFS_V4_1 ) +extern void nfs4_put_session (struct nfs4_session **session); +extern struct nfs4_session *nfs4_alloc_session (void ); +#endif /* CONFIG_NFS_V4_1 */ extern const u32 nfs4_fattr_bitmap[2 ];extern const u32 nfs4_statfs_bitmap[2 ];
fs/nfs/nfs4proc.c +35 -0
@@ -53,6 +53,9 @@#include "delegation.h" #include "internal.h" #include "iostat.h" +#if defined(CONFIG_NFS_V4_1 ) +#include <linux/nfs4_session.h> +#endif /* CONFIG_NFS_V4_1 */ #define NFSDBG_FACILITY NFSDBG_PROC
@@ -3679,6 +3682,38 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,return status; } +#ifdef CONFIG_NFS_V4_1 +struct nfs4_session *nfs4_alloc_session (void ) +{ +struct nfs4_session *session; + + session =kzalloc (sizeof (struct nfs4_session ),GFP_ATOMIC ); +if (!session) +return NULL ; + +atomic_set (&session->ref_count,1 ); + +return session; +} + +static void nfs4_free_session (struct nfs4_session *session) +{ +dprintk ("%s: freeing session %p\n" , __func__, session); +kfree (session); +} + +void nfs4_put_session (struct nfs4_session **session) +{ +dprintk ("--> nfs4_put_session()\n" ); +if (atomic_dec_and_test (&((*session)->ref_count))) { +nfs4_free_session (*session); + *session =NULL ; + } +dprintk ("<-- nfs4_put_session()\n" ); +} + +#endif /* CONFIG_NFS_V4_1 */ +struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { .recover_open = nfs4_open_reclaim, .recover_lock = nfs4_lock_reclaim,
include/linux/nfs4_session.h new file +45 -0
45 lines not on this page · raw message
include/linux/nfs_fs_sb.h +5 -0
@@ -7,6 +7,7 @@#include <asm/atomic.h> +struct nfs4_session ;struct nfs_iostats ;struct nlm_host ;
@@ -72,6 +73,10 @@ struct nfs_client {unsigned char cl_id_uniquifier;u32 cl_minorversion;#endif /* CONFIG_NFS_V4 */ + +#ifdef CONFIG_NFS_V4_1 +struct nfs4_session *cl_session;/* sharred session */ +#endif /* CONFIG_NFS_V4_1 */ };#ifdef CONFIG_NFS_V4
Signature · 1 line
1.6.0.2
RFC 19/85 nfs41: share client sessions across mounts
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
Do not create a new session for each new mount (FSID).
Call nfs4_get_session to bump the reference count for each cloned nfs4 server which now share the struct nfs_client session.
nfs41: check minorversion on nfs41_get_session
--- fs/nfs/client.c | 4 ++++ fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4proc.c | 5 +++++ 3 files changed, 10 insertions(+), 0 deletions(-)
fs/nfs/client.c +4 -0
@@ -1336,6 +1336,10 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,if (!IS_ERR (source->client_acl))nfs_init_server_aclclient (server); +#ifdef CONFIG_NFS_V4_1 +nfs4_get_session (server->nfs_client); +#endif /* CONFIG_NFS_V4_1 */ +/* probe the filesystem info for this server filesystem */ error =nfs_probe_fsinfo (server, fh, &fattr_fsinfo);if (error <0 )
fs/nfs/nfs4_fs.h +1 -0
@@ -190,6 +190,7 @@ extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;#if defined(CONFIG_NFS_V4_1 )extern void nfs4_put_session (struct nfs4_session **session); +extern void nfs4_get_session (struct nfs_client *clp);extern struct nfs4_session *nfs4_alloc_session (void );#endif /* CONFIG_NFS_V4_1 */
fs/nfs/nfs4proc.c +5 -0
@@ -3712,6 +3712,11 @@ void nfs4_put_session(struct nfs4_session **session)dprintk ("<-- nfs4_put_session()\n" ); } +void nfs4_get_session (struct nfs_client *clp) +{ +if (clp->cl_minorversion ==1 ) +atomic_inc (&clp->cl_session->ref_count); +}#endif /* CONFIG_NFS_V4_1 */ struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
Signature · 1 line
1.6.0.2
RFC 20/85 nfs41: slot table init and destroy
In reply to Benny HalevyCode to initialize and destroy the slot table.
Uses bitmap-based allocation.
--- fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs4_session.h | 17 ++++++++ 2 files changed, 105 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +88 -0
@@ -3683,6 +3683,92 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, }#ifdef CONFIG_NFS_V4_1 +/* +* Initialize slot table +* +* Note: the "used" bitmap points to _used_slots id max_slots <= BITS_PER_LONG. +* Otherwise, we dynamically allocate enough ulongs to hold max_slots bits. +*/ +static int nfs4_init_slot_table (struct nfs4_channel *channel) +{ +struct nfs4_slot_table *tbl = &channel->slot_table; +int i, max_slots = channel->chan_attrs.max_reqs; +struct nfs4_slot *slot; +unsigned long *used; +int ret = -ENOMEM ; + +dprintk ("--> %s: max_reqs=%u\n" , __func__, + channel->chan_attrs.max_reqs); + slot =kzalloc (max_slots *sizeof (struct nfs4_slot ),GFP_ATOMIC ); +if (!slot) + goto out; +for (i =0 ; i < max_slots; ++i) + slot[i].seq_nr =1 ; + +if (max_slots <=BITS_PER_LONG ) + used = &tbl->_used_slots;/* use word in tbl */ +else { +/* allocate enough unsigned longs for max_slots bits */ + used =kzalloc (sizeof (unsigned long ) * +DIV_ROUND_UP (max_slots,BITS_PER_LONG ), +GFP_ATOMIC ); +if (!used) + goto out_free; + } + ret =0 ; + +spin_lock (&tbl->slot_tbl_lock); +if (tbl->slots !=NULL ) { +spin_unlock (&tbl->slot_tbl_lock); +dprintk ("%s: slot table already initialized. tbl=%p slots=%p\n" , + __func__, tbl, tbl->slots); +WARN_ON (1 ); + goto out_free; + } + tbl->max_slots = max_slots; + tbl->slots = slot; + tbl->used_slots = used; + tbl->lowest_free_slotid =0 ;/* first slot is free */ + tbl->highest_used_slotid =-1 ;/* no slot is currently used */ +spin_unlock (&tbl->slot_tbl_lock); +dprintk ("%s: tbl=%p slots=%p max_slots=%d\n" , __func__, + tbl, tbl->slots, tbl->max_slots); +out: +dprintk ("<-- %s: return %d\n" , __func__, ret); +return ret; +out_free: +kfree (slot); +if (used != &tbl->_used_slots) +kfree (used); + goto out; +} + +/* Destroy the slot table */ +static void nfs4_destroy_slot_table (struct nfs4_channel *channel) +{ +if (channel->slot_table.slots ==NULL ) +return ; +kfree (channel->slot_table.slots); + channel->slot_table.slots =NULL ; +/* Was the "used" bitmap dynamically allocated? */ +if (channel->slot_table.used_slots != &channel->slot_table._used_slots) +kfree (channel->slot_table.used_slots); + +return ; +} + +static int nfs4_init_channel (struct nfs4_channel *channel) +{ +struct nfs4_slot_table *tbl; + + tbl = &channel->slot_table; + +spin_lock_init (&tbl->slot_tbl_lock); +rpc_init_wait_queue (&tbl->slot_tbl_waitq,"Slot table" ); + +return 0 ; +} +struct nfs4_session *nfs4_alloc_session (void ) {struct nfs4_session *session;
@@ -3693,6 +3779,7 @@ struct nfs4_session *nfs4_alloc_session(void)atomic_set (&session->ref_count,1 ); +nfs4_init_channel (&session->fore_channel);return session; }
@@ -3706,6 +3793,7 @@ void nfs4_put_session(struct nfs4_session **session) {dprintk ("--> nfs4_put_session()\n" );if (atomic_dec_and_test (&((*session)->ref_count))) { +nfs4_destroy_slot_table (&((*session)->fore_channel));nfs4_free_session (*session); *session =NULL ; }
include/linux/nfs4_session.h +17 -0
@@ -17,9 +17,26 @@ struct nfs4_channel_attrs {u32 rdma_attrs; }; +struct nfs4_slot { +u32 seq_nr; +}; + +struct nfs4_slot_table { +struct nfs4_slot *slots;/* seqid per slot */ +unsigned long *used_slots;/* used/unused bitmap */ +unsigned long _used_slots;/* used when max_slots fits */ +spinlock_t slot_tbl_lock; +struct rpc_wait_queue slot_tbl_waitq;/* allocators may wait here */ +int max_slots;/* # slots in table */ +int lowest_free_slotid;/* lower bound hint */ +int highest_used_slotid;/* sent to server on each SEQ. +* op for dynamic resizing */ +}; +struct nfs4_channel {struct nfs4_channel_attrs chan_attrs;struct rpc_clnt *rpc_client; +struct nfs4_slot_table slot_table; };/*
Signature · 1 line
1.6.0.2
RFC 21/85 nfs41: find slot
In reply to Benny HalevyFind a free slot using bitmap-based allocation. Use the optimized ffz function to find a zero bit in the bitmap that indicates a free slot, starting the search from the 'lowest_free_slotid' position.
If found, mark the slot as used in the bitmap, get the slot's slotid and seqid, and update max_slotid to be used by the SEQUENCE operation.
Also, update lowest_free_slotid for next search.
If no free slot was found the caller has to wait for a free slot (outside the scope of this function)
--- fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs4_session.h | 5 ++ 2 files changed, 93 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +88 -0
@@ -207,6 +207,94 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestampspin_unlock (&clp->cl_lock); } +#if defined(CONFIG_NFS_V4_1 ) + +/* +* idx2bmp - return pointer to bitmap word holding index "idx". +* +* inputs: +* @base points to bitmap. +* @idx slot index. +* +* output: +* @bit optional, *bit set to bit index of "idx" in the returned +* bitmap word. +*/ +static inline unsigned long *idx2bmp (unsigned long *base,int idx,int *bit) +{ + base += idx /BITS_PER_LONG ; +if (bit) + *bit = idx & (BITS_PER_LONG -1 ); +return base; +} + +/* +* bmp2idx - return absolute index of bmp:bit in bitmap. +* +* inputs: +* @base points to bitmap. +* @bmp points to bitmap word. +* @bit bit index in bitmap word. +*/ +static inline int bmp2idx (unsigned long *base,unsigned long *bmp, +int bit) +{ +return ((bmp - base) *BITS_PER_LONG ) + bit; +} + +/* +* nfs4_find_slot - efficiently look for a free slot +* +* nfs4_find_slot uses the ffz cpu-optimized function to look for an unset +* bit in each word in the bitmap. +* Scan starts at lowest_free_slotid, which is a hint for the free slot, +* as all lower-numbered slots are known to be used. +* If found, we mark the slot as used, update the highest_used_slotid, +* and respectively set up the sequence operation args. +* The lowest_free_slotid is always set to the successive slotid. +* A pointer to the slot's seqid is returned if found, or NULL otherwise. +*/ +static struct nfs4_slot * +nfs4_find_slot (struct nfs4_slot_table *tbl,struct rpc_task *task) +{ +int bit, slotid; +struct nfs4_slot *slot =NULL ; +unsigned long *used, u; + +spin_lock (&tbl->slot_tbl_lock); + slotid = tbl->lowest_free_slotid; +while (slotid < tbl->max_slots) { + used =idx2bmp (tbl->used_slots, slotid,NULL ); + u = *used; +if (u == ~0UL ) { +/* all slots marked used in this word */ + slotid +=BITS_PER_LONG ; +continue ; + } +/* find first slot marked free in word */ + bit =ffz (u); + slotid =bmp2idx (tbl->used_slots, used, bit); +/* mark slot used. note that we don't do that if +* slotid >= tbl->max_slots so not to confuse +* highest_used_slotid algorithm */ +if (slotid < tbl->max_slots) { + *used |= (1 << bit); +if (slotid > tbl->highest_used_slotid) + tbl->highest_used_slotid = slotid; + slot = tbl->slots + slotid; + slotid++;/* for updating lowest_free_slot */ + } +break ; + } + tbl->lowest_free_slotid = slotid; +spin_unlock (&tbl->slot_tbl_lock); +dprintk ("<-- %s slot %p slotid %d\n" , __func__, + slot, slot ?slot_idx (tbl, slot) :-1 ); +return slot; +} + +#endif /* CONFIG_NFS_V4_1 */ +static void update_changeattr (struct inode *dir,struct nfs4_change_info *cinfo) {struct nfs_inode *nfsi =NFS_I (dir);
include/linux/nfs4_session.h +5 -0
@@ -33,6 +33,11 @@ struct nfs4_slot_table {* op for dynamic resizing */ }; +static inline int slot_idx (struct nfs4_slot_table *tbl,struct nfs4_slot *sp) +{ +return sp - tbl->slots; +} +struct nfs4_channel {struct nfs4_channel_attrs chan_attrs;struct rpc_clnt *rpc_client;
Signature · 1 line
1.6.0.2
RFC 22/85 nfs41: free slot
In reply to Benny HalevyFree a slot in the slot table.
Mark the slot as free in the bitmap-based allocation table by clearing a bit corresponding to the slotid.
Update lowest_free_slotid if freed slotid is lower than that. Update highest_used_slotid. In the case the freed slotid equals the highest_used_slotid, scan downwards for the next highest used slotid using the optimized fls* functions.
Finally, wake up thread waiting on slot_tbl_waitq for a free slot to become available.
--- fs/nfs/nfs4proc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 54 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +54 -0
@@ -243,6 +243,60 @@ static inline int bmp2idx(unsigned long *base, unsigned long *bmp, }/* +* nfs4_find_slot - free a slot and efficiently update slot table. +* +* freeing a slot is trivially done by clearing its respective bit +* in the bitmap. +* The lowest_free_slotid is updated if the freed slotid is lower than that. +* If the freed slotid equals highest_used_slotid we want to update it +* so that the server would be able to size down the slot table if needed, +* otherwise we know that the highest_used_slotid is still in use. +* When updating highest_used_slotid there may be "holes" in the bitmap +* so we need to scan down from highest_used_slotid to 0 looking for the now +* highest slotid in use. +* We use the fls cpu-optimized function to look for the last set bit in each +* word in the bitmap. +* If none found, highest_used_slotid is set to -1. +*/ +static void +nfs41_free_slot (struct nfs4_slot_table *tbl,struct nfs4_slot *slot) +{ +int slotid =slot_idx (tbl, slot); +unsigned long *used, u; +int bit; + +spin_lock (&tbl->slot_tbl_lock); +/* clear used bit in bitmap */ + used =idx2bmp (tbl->used_slots, slotid, &bit); + *used &= ~(1 << bit); + +if (slotid < tbl->lowest_free_slotid) + tbl->lowest_free_slotid = slotid; + +/* update highest_used_slotid when it is freed */ +if (slotid == tbl->highest_used_slotid) { + tbl->highest_used_slotid =-1 ; + slotid--; +/* scan down for the highest used slotid */ +while (slotid >=0 ) { + used =idx2bmp (tbl->used_slots, slotid,NULL ); + u = *used; +if (!u) { +/* all slots marked free in this word */ + slotid -=BITS_PER_LONG ; +continue ; + } + bit =__fls (u); + tbl->highest_used_slotid =bmp2idx (tbl->used_slots, + used, bit); +break ; + } + } +spin_unlock (&tbl->slot_tbl_lock); +rpc_wake_up_next (&tbl->slot_tbl_waitq); +} + +/* * nfs4_find_slot - efficiently look for a free slot * * nfs4_find_slot uses the ffz cpu-optimized function to look for an unset
Signature · 1 line
1.6.0.2
RFC 23/85 nfs41: minorversion support for xdr
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
Add the minorversion to struct rpc_version and struct rpc_clnt, and struct compound_hdr. Switch on the minorversion to perfom NFSv4.0 vrs NFSv4.1 encoding,
Add the nfsv41 encode and decode sizes. Add encode_sequence to all nfs4_enc_* routines and decode_sequence to all nfs4_dec_* routines as required by v41.
--- fs/nfs/nfs4xdr.c | 641 +++++++++++++++++++++++++++++++------------ include/linux/sunrpc/clnt.h | 2 + net/sunrpc/clnt.c | 2 + 3 files changed, 471 insertions(+), 174 deletions(-)
fs/nfs/nfs4xdr.c +467 -174
@@ -240,43 +240,63 @@ static int nfs4_stat_to_errno(int); (encode_getattr_maxsz)#define decode_fs_locations_maxsz \ (0) + +#if defined(CONFIG_NFS_V4_1 ) +#define encode_sequence_maxsz 0/* stub */ +#define decode_sequence_maxsz 0/* stub */ +#else /* CONFIG_NFS_V4_1 */ +#define encode_sequence_maxsz 0 +#define decode_sequence_maxsz 0 +#endif /* CONFIG_NFS_V4_1 */ +#define NFS4_enc_compound_sz (1024)/* XXX: large enough? */ #define NFS4_dec_compound_sz (1024)/* XXX: large enough? */ #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_read_maxsz)#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_read_maxsz)#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_readlink_maxsz)#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_readlink_maxsz)#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_readdir_maxsz)#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_readdir_maxsz)#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_write_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_write_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_commit_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_commit_maxsz + \ decode_getattr_maxsz) -#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ +#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_savefh_maxsz + \ encode_open_maxsz + \
@@ -284,7 +304,8 @@ static int nfs4_stat_to_errno(int); encode_getattr_maxsz + \ encode_restorefh_maxsz + \ encode_getattr_maxsz) -#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ +#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_savefh_maxsz + \ decode_open_maxsz + \
@@ -301,43 +322,53 @@ static int nfs4_stat_to_errno(int); decode_putfh_maxsz + \ decode_open_confirm_maxsz)#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_open_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_open_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_open_downgrade_sz \ (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_open_downgrade_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_open_downgrade_sz \ (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_open_downgrade_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_close_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_close_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_setattr_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_setattr_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_fsinfo_maxsz)#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_fsinfo_maxsz)#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
@@ -359,64 +390,81 @@ static int nfs4_stat_to_errno(int); decode_putrootfh_maxsz + \ decode_fsinfo_maxsz)#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_lock_maxsz)#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_lock_maxsz)#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_lockt_maxsz)#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_lockt_maxsz)#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_locku_maxsz)#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_locku_maxsz)#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_access_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_access_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_lookup_maxsz + \ encode_getattr_maxsz + \ encode_getfh_maxsz)#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_lookup_maxsz + \ decode_getattr_maxsz + \ decode_getfh_maxsz)#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putrootfh_maxsz + \ encode_getattr_maxsz + \ encode_getfh_maxsz)#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putrootfh_maxsz + \ decode_getattr_maxsz + \ decode_getfh_maxsz)#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_remove_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ op_decode_hdr_maxsz + 5 + \ decode_getattr_maxsz)#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_savefh_maxsz + \ encode_putfh_maxsz + \
@@ -425,6 +473,7 @@ static int nfs4_stat_to_errno(int); encode_restorefh_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_savefh_maxsz + \ decode_putfh_maxsz + \
@@ -433,6 +482,7 @@ static int nfs4_stat_to_errno(int); decode_restorefh_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_savefh_maxsz + \ encode_putfh_maxsz + \
@@ -441,6 +491,7 @@ static int nfs4_stat_to_errno(int); encode_restorefh_maxsz + \ decode_getattr_maxsz)#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_savefh_maxsz + \ decode_putfh_maxsz + \
@@ -449,16 +500,19 @@ static int nfs4_stat_to_errno(int); decode_restorefh_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_symlink_maxsz + \ encode_getattr_maxsz + \ encode_getfh_maxsz)#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_symlink_maxsz + \ decode_getattr_maxsz + \ decode_getfh_maxsz)#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_savefh_maxsz + \ encode_create_maxsz + \
@@ -467,6 +521,7 @@ static int nfs4_stat_to_errno(int); encode_restorefh_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_savefh_maxsz + \ decode_create_maxsz + \
@@ -475,49 +530,63 @@ static int nfs4_stat_to_errno(int); decode_restorefh_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_statfs_maxsz)#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_statfs_maxsz)#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_delegreturn_maxsz + \ encode_getattr_maxsz)#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_delegreturn_maxsz + \ decode_getattr_maxsz)#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_getacl_maxsz)#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_getacl_maxsz)#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_setacl_maxsz)#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_setacl_maxsz)#define NFS4_enc_fs_locations_sz \ (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ encode_putfh_maxsz + \ encode_lookup_maxsz + \ encode_fs_locations_maxsz)#define NFS4_dec_fs_locations_sz \ (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_lookup_maxsz + \ decode_fs_locations_maxsz)
@@ -543,6 +612,7 @@ struct compound_hdr {uint32_t nops;uint32_t taglen;char * tag; +u32 minorversion; };/*
@@ -578,7 +648,7 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *xdr_encode_opaque (p, str, len); } -static __u32 * +static __be32 *encode_compound_hdr (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p, *nops;
@@ -588,7 +658,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)RESERVE_SPACE (12 +(XDR_QUADLEN (hdr->taglen)<<2 ));WRITE32 (hdr->taglen);WRITEMEM (hdr->tag, hdr->taglen); -WRITE32 (NFS4_MINOR_VERSION ); +WRITE32 (hdr->minorversion); nops = p;WRITE32 (hdr->nops);return nops;
@@ -1377,7 +1447,8 @@ encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)static int encode_setattr (struct xdr_stream *xdr,const struct nfs_setattrargs *arg, -const struct nfs_server *server,struct compound_hdr *hdr) +const struct nfs_server *server, +struct compound_hdr *hdr) {int status;__be32 *p;
@@ -1468,6 +1539,30 @@ encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,return 0 ; } + +#if defined(CONFIG_NFS_V4_1 ) +/* NFSv4.1 operations */ +static int encode_sequence (struct xdr_stream *xdr, +const struct nfs41_sequence_args *args, +struct compound_hdr *hdr) +{ +if (hdr->minorversion ==0 ) +return 0 ; + +/* stub */ + hdr->nops++; + +return 0 ; +} +#else /* CONFIG_NFS_V4_1 */ +static inline int encode_sequence (struct xdr_stream *xdr, +const struct nfs41_sequence_args *args, +struct compound_hdr *hdr) +{ +return 0 ; +} +#endif /* CONFIG_NFS_V4_1 */ +/* * END OF "GENERIC" ENCODE ROUTINES. */
@@ -1475,17 +1570,19 @@ encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,/* * Encode an ACCESS request */ -static int nfs4_xdr_enc_access (struct rpc_rqst *req,__be32 *p,const struct nfs4_accessargs *args) +static int nfs4_xdr_enc_access (struct rpc_rqst *req,__be32 *p, +const struct nfs4_accessargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status !=0 ) goto out;
@@ -1501,17 +1598,19 @@ out:/* * Encode LOOKUP request */ -static int nfs4_xdr_enc_lookup (struct rpc_rqst *req,__be32 *p,const struct nfs4_lookup_arg *args) +static int nfs4_xdr_enc_lookup (struct rpc_rqst *req,__be32 *p, +const struct nfs4_lookup_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out;if ((status =encode_lookup (&xdr, args->name, &hdr)) !=0 )
@@ -1527,17 +1626,19 @@ out:/* * Encode LOOKUP_ROOT request */ -static int nfs4_xdr_enc_lookup_root (struct rpc_rqst *req,__be32 *p,const struct nfs4_lookup_root_arg *args) +static int nfs4_xdr_enc_lookup_root (struct rpc_rqst *req,__be32 *p, +const struct nfs4_lookup_root_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putrootfh (&xdr, &hdr)) !=0 ) goto out;if ((status =encode_getfh (&xdr, &hdr)) ==0 )
@@ -1550,17 +1651,19 @@ out:/* * Encode REMOVE request */ -static int nfs4_xdr_enc_remove (struct rpc_rqst *req,__be32 *p,const struct nfs_removeargs *args) +static int nfs4_xdr_enc_remove (struct rpc_rqst *req,__be32 *p, +const struct nfs_removeargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putfh (&xdr, args->fh, &hdr)) !=0 ) goto out;if ((status =encode_remove (&xdr, &args->name, &hdr)) !=0 )
@@ -1574,17 +1677,19 @@ out:/* * Encode RENAME request */ -static int nfs4_xdr_enc_rename (struct rpc_rqst *req,__be32 *p,const struct nfs4_rename_arg *args) +static int nfs4_xdr_enc_rename (struct rpc_rqst *req,__be32 *p, +const struct nfs4_rename_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putfh (&xdr, args->old_dir, &hdr)) !=0 ) goto out;if ((status =encode_savefh (&xdr, &hdr)) !=0 )
@@ -1607,17 +1712,19 @@ out:/* * Encode LINK request */ -static int nfs4_xdr_enc_link (struct rpc_rqst *req,__be32 *p,const struct nfs4_link_arg *args) +static int nfs4_xdr_enc_link (struct rpc_rqst *req,__be32 *p, +const struct nfs4_link_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putfh (&xdr, args->fh, &hdr)) !=0 ) goto out;if ((status =encode_savefh (&xdr, &hdr)) !=0 )
@@ -1639,17 +1746,19 @@ out:/* * Encode CREATE request */ -static int nfs4_xdr_enc_create (struct rpc_rqst *req,__be32 *p,const struct nfs4_create_arg *args) +static int nfs4_xdr_enc_create (struct rpc_rqst *req,__be32 *p, +const struct nfs4_create_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out;if ((status =encode_savefh (&xdr, &hdr)) !=0 )
@@ -1679,17 +1788,19 @@ static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nf/* * Encode GETATTR request */ -static int nfs4_xdr_enc_getattr (struct rpc_rqst *req,__be32 *p,const struct nfs4_getattr_arg *args) +static int nfs4_xdr_enc_getattr (struct rpc_rqst *req,__be32 *p, +const struct nfs4_getattr_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putfh (&xdr, args->fh, &hdr)) ==0 ) status =encode_getfattr (&xdr, args->bitmask, &hdr);encode_nops (nops, &hdr);
@@ -1699,17 +1810,19 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf/* * Encode a CLOSE request */ -static int nfs4_xdr_enc_close (struct rpc_rqst *req,__be32 *p,struct nfs_closeargs *args) +static int nfs4_xdr_enc_close (struct rpc_rqst *req,__be32 *p, +struct nfs_closeargs *args) { -struct xdr_stream xdr; -struct compound_hdr hdr = { - .nops =0 , - }; +struct xdr_stream xdr; +struct compound_hdr hdr = { + .minorversion = req->rq_task->tk_client->cl_mvers, + };int status;__be32 *nops; -xdr_init_encode (&xdr, &req->rq_snd_buf, p); +xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1725,17 +1838,19 @@ out:/* * Encode an OPEN request */ -static int nfs4_xdr_enc_open (struct rpc_rqst *req,__be32 *p,struct nfs_openargs *args) +static int nfs4_xdr_enc_open (struct rpc_rqst *req,__be32 *p, +struct nfs_openargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1767,7 +1882,7 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;
@@ -1786,17 +1901,19 @@ out:/* * Encode an OPEN request with no attributes. */ -static int nfs4_xdr_enc_open_noattr (struct rpc_rqst *req,__be32 *p,struct nfs_openargs *args) +static int nfs4_xdr_enc_open_noattr (struct rpc_rqst *req,__be32 *p, +struct nfs_openargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1812,17 +1929,19 @@ out:/* * Encode an OPEN_DOWNGRADE request */ -static int nfs4_xdr_enc_open_downgrade (struct rpc_rqst *req,__be32 *p,struct nfs_closeargs *args) +static int nfs4_xdr_enc_open_downgrade (struct rpc_rqst *req,__be32 *p, +struct nfs_closeargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1838,17 +1957,19 @@ out:/* * Encode a LOCK request */ -static int nfs4_xdr_enc_lock (struct rpc_rqst *req,__be32 *p,struct nfs_lock_args *args) +static int nfs4_xdr_enc_lock (struct rpc_rqst *req,__be32 *p, +struct nfs_lock_args *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1861,17 +1982,19 @@ out:/* * Encode a LOCKT request */ -static int nfs4_xdr_enc_lockt (struct rpc_rqst *req,__be32 *p,struct nfs_lockt_args *args) +static int nfs4_xdr_enc_lockt (struct rpc_rqst *req,__be32 *p, +struct nfs_lockt_args *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1884,17 +2007,19 @@ out:/* * Encode a LOCKU request */ -static int nfs4_xdr_enc_locku (struct rpc_rqst *req,__be32 *p,struct nfs_locku_args *args) +static int nfs4_xdr_enc_locku (struct rpc_rqst *req,__be32 *p, +struct nfs_locku_args *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1907,11 +2032,12 @@ out:/* * Encode a READLINK request */ -static int nfs4_xdr_enc_readlink (struct rpc_rqst *req,__be32 *p,const struct nfs4_readlink *args) +static int nfs4_xdr_enc_readlink (struct rpc_rqst *req,__be32 *p, +const struct nfs4_readlink *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;unsigned int replen;
@@ -1920,6 +2046,7 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nxdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1941,11 +2068,12 @@ out:/* * Encode a READDIR request */ -static int nfs4_xdr_enc_readdir (struct rpc_rqst *req,__be32 *p,const struct nfs4_readdir_arg *args) +static int nfs4_xdr_enc_readdir (struct rpc_rqst *req,__be32 *p, +const struct nfs4_readdir_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;int replen;
@@ -1954,6 +2082,7 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfxdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -1978,18 +2107,20 @@ out:/* * Encode a READ request */ -static int nfs4_xdr_enc_read (struct rpc_rqst *req,__be32 *p,struct nfs_readargs *args) +static int nfs4_xdr_enc_read (struct rpc_rqst *req,__be32 *p, +struct nfs_readargs *args) {struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int replen, status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -2013,18 +2144,20 @@ out:/* * Encode an SETATTR request */ -static int nfs4_xdr_enc_setattr (struct rpc_rqst *req,__be32 *p,struct nfs_setattrargs *args) +static int nfs4_xdr_enc_setattr (struct rpc_rqst *req,__be32 *p, +struct nfs_setattrargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -2042,18 +2175,19 @@ out:*/ static int nfs4_xdr_enc_getacl (struct rpc_rqst *req,__be32 *p, -struct nfs_getaclargs *args) +struct nfs_getaclargs *args) {struct xdr_stream xdr;struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int replen, status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -2070,24 +2204,25 @@ out:/* * Encode a WRITE request */ -static int nfs4_xdr_enc_write (struct rpc_rqst *req,__be32 *p,struct nfs_writeargs *args) +static int nfs4_xdr_enc_write (struct rpc_rqst *req,__be32 *p, +struct nfs_writeargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; status =encode_write (&xdr, args, &hdr);if (status) goto out; - req->rq_snd_buf.flags |=XDRBUF_WRITE ; status =encode_getfattr (&xdr, args->bitmask, &hdr); out:encode_nops (nops, &hdr);
@@ -2097,17 +2232,19 @@ out:/* * a COMMIT request */ -static int nfs4_xdr_enc_commit (struct rpc_rqst *req,__be32 *p,struct nfs_writeargs *args) +static int nfs4_xdr_enc_commit (struct rpc_rqst *req,__be32 *p, +struct nfs_writeargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out;
@@ -2123,17 +2260,19 @@ out:/* * FSINFO request */ -static int nfs4_xdr_enc_fsinfo (struct rpc_rqst *req,__be32 *p,struct nfs4_fsinfo_arg *args) +static int nfs4_xdr_enc_fsinfo (struct rpc_rqst *req,__be32 *p, +struct nfs4_fsinfo_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (!status) status =encode_fsinfo (&xdr, args->bitmask, &hdr);
@@ -2144,17 +2283,19 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin/* * a PATHCONF request */ -static int nfs4_xdr_enc_pathconf (struct rpc_rqst *req,__be32 *p,const struct nfs4_pathconf_arg *args) +static int nfs4_xdr_enc_pathconf (struct rpc_rqst *req,__be32 *p, +const struct nfs4_pathconf_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (!status) status = encode_getattr_one(&xdr,
@@ -2167,22 +2308,25 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n/* * a STATFS request */ -static int nfs4_xdr_enc_statfs (struct rpc_rqst *req,__be32 *p,const struct nfs4_statfs_arg *args) +static int nfs4_xdr_enc_statfs (struct rpc_rqst *req,__be32 *p, +const struct nfs4_statfs_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status ==0 ) status =encode_getattr_two (&xdr, args->bitmask[0 ] & nfs4_statfs_bitmap[0 ], - args->bitmask[1 ] & nfs4_statfs_bitmap[1 ], &hdr); + args->bitmask[1 ] & nfs4_statfs_bitmap[1 ], + &hdr);encode_nops (nops, &hdr);return status; }
@@ -2190,18 +2334,20 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs/* * GETATTR_BITMAP request */ -static int nfs4_xdr_enc_server_caps (struct rpc_rqst *req,__be32 *p,const struct nfs_fh *fhandle) +static int nfs4_xdr_enc_server_caps (struct rpc_rqst *req,__be32 *p, +struct nfs4_server_caps_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, fhandle, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); + status =encode_putfh (&xdr, args->fhandle, &hdr);if (status ==0 ) status = encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS| FATTR4_WORD0_LINK_SUPPORT|
@@ -2218,7 +2364,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;
@@ -2226,6 +2372,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_clientxdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); status =encode_renew (&xdr, clp, &hdr); +encode_nops (nops, &hdr);return status; }
@@ -2237,7 +2384,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4 {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;
@@ -2245,6 +2392,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); status =encode_setclientid (&xdr, sc, &hdr); +encode_nops (nops, &hdr);return status; }
@@ -2256,7 +2404,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };const u32 lease_bitmap[2 ] = {FATTR4_WORD0_LEASE_TIME ,0 };int status;
@@ -2276,17 +2424,19 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str/* * DELEGRETURN request */ -static int nfs4_xdr_enc_delegreturn (struct rpc_rqst *req,__be32 *p,const struct nfs4_delegreturnargs *args) +static int nfs4_xdr_enc_delegreturn (struct rpc_rqst *req,__be32 *p, +const struct nfs4_delegreturnargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fhandle, &hdr);if (status !=0 ) goto out;
@@ -2302,11 +2452,12 @@ out:/* * Encode FS_LOCATIONS request */ -static int nfs4_xdr_enc_fs_locations (struct rpc_rqst *req,__be32 *p,struct nfs4_fs_locations_arg *args) +static int nfs4_xdr_enc_fs_locations (struct rpc_rqst *req,__be32 *p, +struct nfs4_fs_locations_arg *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;int replen;
@@ -2315,6 +2466,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfsxdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr);if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out;if ((status =encode_lookup (&xdr, args->name, &hdr)) !=0 )
@@ -2325,7 +2477,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs* toplevel_status + OP_PUTFH + status * + OP_LOOKUP + status + OP_GETATTR + status = 7 */ - replen = (RPC_REPHDRSIZE + auth->au_rslack +7 ) <<2 ; + replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_enc_fsinfo_sz) <<2 ;xdr_inline_pages (&req->rq_rcv_buf, replen, &args->page,0 ,PAGE_SIZE ); out:
@@ -3963,19 +4115,48 @@ static int decode_delegreturn(struct xdr_stream *xdr)return decode_op_hdr (xdr,OP_DELEGRETURN ); } +#if defined(CONFIG_NFS_V4_1 ) +static int decode_sequence (struct xdr_stream *xdr, +struct nfs41_sequence_res *res, +struct rpc_rqst *rqstp) +{ +if (rqstp->rq_task->tk_client->cl_mvers ==0 ) +return 0 ; + +/* stub */ + +return 0 ; +} +#else /* CONFIG_NFS_V4_1 */ +static inline int decode_sequence (struct xdr_stream *xdr, +struct nfs41_sequence_res *res, +struct rpc_rqst *rqstp) +{ +return 0 ; +} +#endif /* CONFIG_NFS_V4_1 */ + +/* +* END OF "GENERIC" DECODE ROUTINES. +*/ +/* * Decode OPEN_DOWNGRADE response */ -static int nfs4_xdr_dec_open_downgrade (struct rpc_rqst *rqstp,__be32 *p,struct nfs_closeres *res) +static int nfs4_xdr_dec_open_downgrade (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_closeres *res) { -struct xdr_stream xdr; -struct compound_hdr hdr; -int status; +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; +xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -3988,20 +4169,21 @@ out: }/* -* END OF "GENERIC" DECODE ROUTINES. -*/ - -/* * Decode ACCESS response */ -static int nfs4_xdr_dec_access (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_accessres *res) +static int nfs4_xdr_dec_access (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_accessres *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status;xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out; status =decode_putfh (&xdr);if (status !=0 )
@@ -4017,14 +4199,19 @@ out:/* * Decode LOOKUP response */ -static int nfs4_xdr_dec_lookup (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_lookup_res *res) +static int nfs4_xdr_dec_lookup (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_lookup_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status;xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out;if ((status =decode_putfh (&xdr)) !=0 ) goto out;
@@ -4040,14 +4227,19 @@ out:/* * Decode LOOKUP_ROOT response */ -static int nfs4_xdr_dec_lookup_root (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_lookup_res *res) +static int nfs4_xdr_dec_lookup_root (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_lookup_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status;xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out;if ((status =decode_putrootfh (&xdr)) !=0 ) goto out;
@@ -4060,14 +4252,19 @@ out:/* * Decode REMOVE response */ -static int nfs4_xdr_dec_remove (struct rpc_rqst *rqstp,__be32 *p,struct nfs_removeres *res) +static int nfs4_xdr_dec_remove (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_removeres *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status;xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out;if ((status =decode_putfh (&xdr)) !=0 ) goto out;
@@ -4081,14 +4278,19 @@ out:/* * Decode RENAME response */ -static int nfs4_xdr_dec_rename (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_rename_res *res) +static int nfs4_xdr_dec_rename (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_rename_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status; - +xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out;if ((status =decode_putfh (&xdr)) !=0 ) goto out;
@@ -4111,14 +4313,19 @@ out:/* * Decode LINK response */ -static int nfs4_xdr_dec_link (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_link_res *res) +static int nfs4_xdr_dec_link (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_link_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status;xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out;if ((status =decode_putfh (&xdr)) !=0 ) goto out;
@@ -4144,14 +4351,19 @@ out:/* * Decode CREATE response */ -static int nfs4_xdr_dec_create (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_create_res *res) +static int nfs4_xdr_dec_create (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_create_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status; - +xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out;if ((status =decode_putfh (&xdr)) !=0 ) goto out;
@@ -4181,7 +4393,8 @@ static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_c/* * Decode GETATTR response */ -static int nfs4_xdr_dec_getattr (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_getattr_res *res) +static int nfs4_xdr_dec_getattr (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_getattr_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4191,56 +4404,65 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_g status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out; status =decode_getfattr (&xdr, res->fattr, res->server); out:return status; - }/* * Encode an SETACL request */ static int -nfs4_xdr_enc_setacl (struct rpc_rqst *req,__be32 *p,struct nfs_setaclargs *args) +nfs4_xdr_enc_setacl (struct rpc_rqst *req,__be32 *p, +struct nfs_setaclargs *args) {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =0 , + .minorversion = req->rq_task->tk_client->cl_mvers, };int status;__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); nops =encode_compound_hdr (&xdr, &hdr); +encode_sequence (&xdr, &args->seq_args, &hdr); status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; status =encode_setacl (&xdr, args, &hdr); out: -encode_nops (nops, &hdr);return status; } +/* * Decode SETACL response */ static int -nfs4_xdr_dec_setacl (struct rpc_rqst *rqstp,__be32 *p,void *res) +nfs4_xdr_dec_setacl (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_setaclres *res) {struct xdr_stream xdr;struct compound_hdr hdr; +struct nfs_setattrres *sattrp =NULL ;int status;xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out; - status =decode_setattr (&xdr, res); + status =decode_setattr (&xdr, sattrp); out:return status; }
@@ -4249,7 +4471,8 @@ out:* Decode GETACL response */ static int -nfs4_xdr_dec_getacl (struct rpc_rqst *rqstp,__be32 *p,size_t *acl_len) +nfs4_xdr_dec_getacl (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_getaclres *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4259,10 +4482,13 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len) status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out; - status =decode_getacl (&xdr, rqstp, acl_len); + status =decode_getacl (&xdr, rqstp, res->acl_len); out:return status;
@@ -4271,16 +4497,20 @@ out:/* * Decode CLOSE response */ -static int nfs4_xdr_dec_close (struct rpc_rqst *rqstp,__be32 *p,struct nfs_closeres *res) +static int nfs4_xdr_dec_close (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_closeres *res) { -struct xdr_stream xdr; -struct compound_hdr hdr; -int status; +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; +xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4301,16 +4531,20 @@ out:/* * Decode OPEN response */ -static int nfs4_xdr_dec_open (struct rpc_rqst *rqstp,__be32 *p,struct nfs_openres *res) +static int nfs4_xdr_dec_open (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_openres *res) { -struct xdr_stream xdr; -struct compound_hdr hdr; -int status; +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; +xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4355,16 +4589,20 @@ out:/* * Decode OPEN response */ -static int nfs4_xdr_dec_open_noattr (struct rpc_rqst *rqstp,__be32 *p,struct nfs_openres *res) +static int nfs4_xdr_dec_open_noattr (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_openres *res) { -struct xdr_stream xdr; -struct compound_hdr hdr; -int status; +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; +xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4379,16 +4617,20 @@ out:/* * Decode SETATTR response */ -static int nfs4_xdr_dec_setattr (struct rpc_rqst *rqstp,__be32 *p,struct nfs_setattrres *res) +static int nfs4_xdr_dec_setattr (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_setattrres *res) { -struct xdr_stream xdr; -struct compound_hdr hdr; -int status; +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; +xdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4405,7 +4647,8 @@ out:/* * Decode LOCK response */ -static int nfs4_xdr_dec_lock (struct rpc_rqst *rqstp,__be32 *p,struct nfs_lock_res *res) +static int nfs4_xdr_dec_lock (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_lock_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4415,6 +4658,9 @@ static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_ status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4426,7 +4672,8 @@ out:/* * Decode LOCKT response */ -static int nfs4_xdr_dec_lockt (struct rpc_rqst *rqstp,__be32 *p,struct nfs_lockt_res *res) +static int nfs4_xdr_dec_lockt (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_lockt_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4436,6 +4683,9 @@ static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4447,7 +4697,8 @@ out:/* * Decode LOCKU response */ -static int nfs4_xdr_dec_locku (struct rpc_rqst *rqstp,__be32 *p,struct nfs_locku_res *res) +static int nfs4_xdr_dec_locku (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_locku_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4457,6 +4708,9 @@ static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4468,7 +4722,8 @@ out:/* * Decode READLINK response */ -static int nfs4_xdr_dec_readlink (struct rpc_rqst *rqstp,__be32 *p,void *res) +static int nfs4_xdr_dec_readlink (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_readlink_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4478,6 +4733,9 @@ static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res) status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4489,7 +4747,8 @@ out:/* * Decode READDIR response */ -static int nfs4_xdr_dec_readdir (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_readdir_res *res) +static int nfs4_xdr_dec_readdir (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_readdir_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4499,6 +4758,9 @@ static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_r status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4510,7 +4772,8 @@ out:/* * Decode Read response */ -static int nfs4_xdr_dec_read (struct rpc_rqst *rqstp,__be32 *p,struct nfs_readres *res) +static int nfs4_xdr_dec_read (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_readres *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4520,6 +4783,9 @@ static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readr status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4533,7 +4799,8 @@ out:/* * Decode WRITE response */ -static int nfs4_xdr_dec_write (struct rpc_rqst *rqstp,__be32 *p,struct nfs_writeres *res) +static int nfs4_xdr_dec_write (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_writeres *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4543,6 +4810,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writ status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4559,7 +4829,8 @@ out:/* * Decode COMMIT response */ -static int nfs4_xdr_dec_commit (struct rpc_rqst *rqstp,__be32 *p,struct nfs_writeres *res) +static int nfs4_xdr_dec_commit (struct rpc_rqst *rqstp,__be32 *p, +struct nfs_writeres *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4569,6 +4840,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri status =decode_compound_hdr (&xdr, &hdr);if (status) goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) + goto out; status =decode_putfh (&xdr);if (status) goto out;
@@ -4583,7 +4857,8 @@ out:/* * FSINFO request */ -static int nfs4_xdr_dec_fsinfo (struct rpc_rqst *req,__be32 *p,struct nfs_fsinfo *fsinfo) +static int nfs4_xdr_dec_fsinfo (struct rpc_rqst *req,__be32 *p, +struct nfs4_fsinfo_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4592,16 +4867,19 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfxdr_init_decode (&xdr, &req->rq_rcv_buf, p); status =decode_compound_hdr (&xdr, &hdr);if (!status) + status =decode_sequence (&xdr, &res->seq_res, req); +if (!status) status =decode_putfh (&xdr);if (!status) - status =decode_fsinfo (&xdr, fsinfo); + status =decode_fsinfo (&xdr, res->fsinfo);return status; }/* * PATHCONF request */ -static int nfs4_xdr_dec_pathconf (struct rpc_rqst *req,__be32 *p,struct nfs_pathconf *pathconf) +static int nfs4_xdr_dec_pathconf (struct rpc_rqst *req,__be32 *p, +struct nfs4_pathconf_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4610,16 +4888,19 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_patxdr_init_decode (&xdr, &req->rq_rcv_buf, p); status =decode_compound_hdr (&xdr, &hdr);if (!status) + status =decode_sequence (&xdr, &res->seq_res, req); +if (!status) status =decode_putfh (&xdr);if (!status) - status =decode_pathconf (&xdr, pathconf); + status =decode_pathconf (&xdr, res->pathconf);return status; }/* * STATFS request */ -static int nfs4_xdr_dec_statfs (struct rpc_rqst *req,__be32 *p,struct nfs_fsstat *fsstat) +static int nfs4_xdr_dec_statfs (struct rpc_rqst *req,__be32 *p, +struct nfs4_statfs_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4628,23 +4909,30 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fsstaxdr_init_decode (&xdr, &req->rq_rcv_buf, p); status =decode_compound_hdr (&xdr, &hdr);if (!status) + status =decode_sequence (&xdr, &res->seq_res, req); +if (!status) status =decode_putfh (&xdr);if (!status) - status =decode_statfs (&xdr, fsstat); + status =decode_statfs (&xdr, res->fsstat);return status; }/* * GETATTR_BITMAP request */ -static int nfs4_xdr_dec_server_caps (struct rpc_rqst *req,__be32 *p,struct nfs4_server_caps_res *res) +static int nfs4_xdr_dec_server_caps (struct rpc_rqst *req,__be32 *p, +struct nfs4_server_caps_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;int status;xdr_init_decode (&xdr, &req->rq_rcv_buf, p); -if ((status =decode_compound_hdr (&xdr, &hdr)) !=0 ) + status =decode_compound_hdr (&xdr, &hdr); +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, req); +if (status) goto out;if ((status =decode_putfh (&xdr)) !=0 ) goto out;
@@ -4709,7 +4997,8 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str/* * DELEGRETURN request */ -static int nfs4_xdr_dec_delegreturn (struct rpc_rqst *rqstp,__be32 *p,struct nfs4_delegreturnres *res) +static int nfs4_xdr_dec_delegreturn (struct rpc_rqst *rqstp,__be32 *p, +struct nfs4_delegreturnres *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4717,7 +5006,10 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfxdr_init_decode (&xdr, &rqstp->rq_rcv_buf, p); status =decode_compound_hdr (&xdr, &hdr); -if (status !=0 ) +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, rqstp); +if (status) goto out; status =decode_putfh (&xdr);if (status !=0 )
@@ -4731,7 +5023,8 @@ out:/* * FS_LOCATIONS request */ -static int nfs4_xdr_dec_fs_locations (struct rpc_rqst *req,__be32 *p,struct nfs4_fs_locations *res) +static int nfs4_xdr_dec_fs_locations (struct rpc_rqst *req,__be32 *p, +struct nfs4_fs_locations_res *res) {struct xdr_stream xdr;struct compound_hdr hdr;
@@ -4739,14 +5032,18 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfsxdr_init_decode (&xdr, &req->rq_rcv_buf, p); status =decode_compound_hdr (&xdr, &hdr); -if (status !=0 ) +if (status) + goto out; + status =decode_sequence (&xdr, &res->seq_res, req); +if (status) goto out;if ((status =decode_putfh (&xdr)) !=0 ) goto out;if ((status =decode_lookup (&xdr)) !=0 ) goto out;xdr_enter_page (&xdr,PAGE_SIZE ); - status =decode_getfattr (&xdr, &res->fattr, res->server); + status =decode_getfattr (&xdr, &res->fs_locations->fattr, + res->fs_locations->server); out:return status; }
@@ -4877,10 +5174,10 @@ nfs4_stat_to_errno(int stat)#define PROC (proc, argtype, restype) \ [NFSPROC4_CLNT_##proc] = { \ .p_proc = NFSPROC4_COMPOUND, \ - .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \ - .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \ - .p_arglen = NFS4_##argtype##_sz, \ - .p_replen = NFS4_##restype##_sz, \ + .p_encode = (kxdrproc_t) nfs4##_xdr_##argtype, \ + .p_decode = (kxdrproc_t) nfs4##_xdr_##restype, \ + .p_arglen = NFS4##_##argtype##_sz, \ + .p_replen = NFS4##_##restype##_sz, \ .p_statidx = NFSPROC4_CLNT_##proc, \ .p_name = #proc, \ }
@@ -4922,11 +5219,6 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), }; -#if defined(CONFIG_NFS_V4_1 ) -struct rpc_procinfo nfs41_procedures[] = { -}; -#endif /* CONFIG_NFS_V4_1 */ -struct rpc_version nfs_version4 = { .number =4 , .nrprocs =ARRAY_SIZE (nfs4_procedures),
@@ -4936,8 +5228,9 @@ struct rpc_version nfs_version4 = {#ifdef CONFIG_NFS_V4_1 struct rpc_version nfs_version41 = { .number =4 , - .nrprocs =ARRAY_SIZE (nfs41_procedures), - .procs = nfs41_procedures + .minorversion =1 , + .nrprocs =ARRAY_SIZE (nfs4_procedures), + .procs = nfs4_procedures };#endif /* CONFIG_NFS_V4_1 */
include/linux/sunrpc/clnt.h +2 -0
@@ -32,6 +32,7 @@ struct rpc_clnt {struct rpc_procinfo * cl_procinfo;/* procedure info */ u32 cl_prog,/* RPC program number */ cl_vers,/* RPC version number */ + cl_mvers,/* RPC minorversion number */ cl_maxproc;/* max procedure number */ char * cl_server;/* server machine name */
@@ -82,6 +83,7 @@ get_rpc_version(struct rpc_program *prog, u32 vers, int minorvers)struct rpc_version {u32 number;/* version number */ +u32 minorversion;/* minorversion number */ unsigned int nrprocs;/* number of procs */ struct rpc_procinfo * procs;/* procedure array */ };
net/sunrpc/clnt.c +2 -0
@@ -177,6 +177,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru clnt->cl_protname = program->name; clnt->cl_prog = args->prognumber ? : program->number; clnt->cl_vers = version->number; + clnt->cl_mvers = version->minorversion; clnt->cl_stats = program->stats; clnt->cl_metrics =rpc_alloc_iostats (clnt); err = -ENOMEM ;
@@ -491,6 +492,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, clnt->cl_protname = program->name; clnt->cl_prog = program->number; clnt->cl_vers = version->number; + clnt->cl_mvers = version->minorversion; clnt->cl_stats = program->stats; err =rpc_ping (clnt,RPC_TASK_SOFT );if (err !=0 ) {
Signature · 1 line
1.6.0.2
RFC 24/85 nfs41: stubs for nfs41 procedures
In reply to Benny Halevy--- fs/nfs/nfs4_fs.h | 2 ++ fs/nfs/nfs4proc.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 0 deletions(-)
fs/nfs/nfs4_fs.h +2 -0
@@ -192,6 +192,8 @@ extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;extern void nfs4_put_session (struct nfs4_session **session);extern void nfs4_get_session (struct nfs_client *clp);extern struct nfs4_session *nfs4_alloc_session (void ); +extern int nfs4_proc_create_session (struct nfs4_session *); +extern int nfs4_proc_destroy_session (struct nfs4_session *);#endif /* CONFIG_NFS_V4_1 */ extern const u32 nfs4_fattr_bitmap[2 ];
fs/nfs/nfs4proc.c +26 -0
@@ -3825,6 +3825,11 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, }#ifdef CONFIG_NFS_V4_1 +static int nfs4_proc_exchange_id (struct nfs_client *clp,struct rpc_cred *cred) +{ +return -1 ;/* stub */ +} +/* * Initialize slot table *
@@ -3947,6 +3952,27 @@ void nfs4_get_session(struct nfs_client *clp)if (clp->cl_minorversion ==1 )atomic_inc (&clp->cl_session->ref_count); } + +int nfs4_proc_create_session (struct nfs4_session *session) +{ +return -1 ;/* stub */ +} + +int nfs4_proc_destroy_session (struct nfs4_session *session) +{ +return -1 ;/* stub */ +} + +static int nfs4_proc_sequence (struct nfs_client *clp,struct rpc_cred *cred) +{ +return -1 ;/* stub */ +} + +static int nfs41_proc_async_sequence (struct nfs_client *clp, +struct rpc_cred *cred) +{ +return -1 ;/* stub */ +}#endif /* CONFIG_NFS_V4_1 */ struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
Signature · 1 line
1.6.0.2
RFC 25/85 nfs41: make nfs4_wait_bit_killable public
In reply to Benny HalevyFrom: Rahul Iyer <[email protected]>
nfs4_wait_bit_killable to be used by NFSv4.1 session recover logic.
--- fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4proc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletions(-)
fs/nfs/nfs4_fs.h +1 -0
@@ -179,6 +179,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, strucextern int nfs4_proc_setclientid_confirm (struct nfs_client *,struct rpc_cred *);extern int nfs4_proc_async_renew (struct nfs_client *,struct rpc_cred *);extern int nfs4_proc_renew (struct nfs_client *,struct rpc_cred *); +extern int nfs4_wait_bit_killable (void *);extern int nfs4_do_close (struct path *path,struct nfs4_state *state,int wait);extern struct dentry *nfs4_atomic_open (struct inode *,struct dentry *,struct nameidata *);extern int nfs4_open_revalidate (struct inode *,struct dentry *,int ,struct nameidata *);
fs/nfs/nfs4proc.c +1 -1
@@ -2929,7 +2929,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)return 0 ; } -static int nfs4_wait_bit_killable (void *word) +int nfs4_wait_bit_killable (void *word) {if (fatal_signal_pending (current))return -ERESTARTSYS ;
Signature · 1 line
1.6.0.2
RFC 26/85 nfs41: introduce nfs4_call_sync
In reply to Benny HalevyUse nfs4_call_sync rather than rpc_call_sync to provide for a nfs41 sessions-enabled interface for sessions manipulation.
The nfs41 rpc logic uses the rpc_call_validate_args method to recover and create the session, as well as selecting a free slot id and the rpc_call_done to free the slot and update slot table related metadata.
--- fs/nfs/nfs4proc.c | 127 ++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 96 insertions(+), 31 deletions(-)
fs/nfs/nfs4proc.c +96 -31
@@ -349,6 +349,19 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)#endif /* CONFIG_NFS_V4_1 */ +static int _nfs4_call_sync (struct nfs_server *server, +struct rpc_message *msg, +struct nfs41_sequence_args *args, +struct nfs41_sequence_res *res, +int cache_reply) +{ +return rpc_call_sync (server->client, msg,0 ); +} + +#define nfs4_call_sync (server, msg, args, res, cache_reply) \ + _nfs4_call_sync((server), (msg), &(args)->seq_args, \ + &(res)->seq_res, (cache_reply)) +static void update_changeattr (struct inode *dir,struct nfs4_change_info *cinfo) {struct nfs_inode *nfsi =NFS_I (dir);
@@ -1318,7 +1331,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, }else memcpy (&arg.stateid, &zero_stateid,sizeof (arg.stateid)); - status =rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &arg, &res,1 );if (status ==0 && state !=NULL )renew_lease (server, timestamp);return status;
@@ -1620,15 +1633,19 @@ out_drop:static int _nfs4_server_capabilities (struct nfs_server *server,struct nfs_fh *fhandle) { +struct nfs4_server_caps_arg args = { + .fhandle = fhandle, + };struct nfs4_server_caps_res res = {};struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_SERVER_CAPS ), - .rpc_argp = fhandle, + .rpc_argp = &args, .rpc_resp = &res, };int status; - status =rpc_call_sync (server->client, &msg,0 ); +dprintk ("--> %s\n" , __func__); + status =nfs4_call_sync (server, &msg, &args, &res,0 );if (status ==0 ) {memcpy (server->attr_bitmask, res.attr_bitmask,sizeof (server->attr_bitmask));if (res.attr_bitmask[0 ] &FATTR4_WORD0_ACL )
@@ -1639,6 +1656,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f server->caps |=NFS_CAP_SYMLINKS ; server->acl_bitmask = res.acl_bitmask; } + +dprintk ("<-- %s status= %d\n" , __func__, status);return status; }
@@ -1670,8 +1689,13 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, .rpc_argp = &args, .rpc_resp = &res, }; +int status; + +dprintk ("--> %s\n" , __func__);nfs_fattr_init (info->fattr); -return rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 ); +dprintk ("<-- %s status= %d\n" , __func__, status); +return status; } static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -1759,9 +1783,12 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, .rpc_argp = &args, .rpc_resp = &res, }; +int status;nfs_fattr_init (fattr); -return rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 ); + +return status; }static int nfs4_proc_getattr (struct nfs_server *server,struct nfs_fh *fhandle,struct nfs_fattr *fattr)
@@ -1843,10 +1870,10 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d };nfs_fattr_init (fattr); -dprintk ("NFS call lookupfh %s\n" , name->name); - status =rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 );dprintk ("NFS reply lookupfh: %d\n" , status); +return status; }
@@ -1931,7 +1958,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry args.access |=NFS4_ACCESS_EXECUTE ; }nfs_fattr_init (&fattr); - status =rpc_call_sync (NFS_CLIENT (inode), &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 );if (!status) { entry->mask =0 ;if (res.access &NFS4_ACCESS_READ )
@@ -1991,13 +2018,17 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, .pglen = pglen, .pages = &page, }; +struct nfs4_readlink_res res;struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_READLINK ), .rpc_argp = &args, - .rpc_resp =NULL , + .rpc_resp = &res, }; +int status; + + status =nfs4_call_sync (server, &msg, &args, &res,0 ); -return rpc_call_sync (NFS_CLIENT (inode), &msg,0 ); +return status; } static int nfs4_proc_readlink(struct inode *inode, struct page *page,
@@ -2090,11 +2121,12 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)int status;nfs_fattr_init (&res.dir_attr); - status =rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,1 );if (status ==0 ) {update_changeattr (dir, &res.cinfo);nfs_post_op_update_inode (dir, &res.dir_attr); } +return status; }
@@ -2158,14 +2190,14 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,nfs_fattr_init (res.old_fattr);nfs_fattr_init (res.new_fattr); - status =rpc_call_sync (server->client, &msg,0 ); - + status =nfs4_call_sync (server, &msg, &arg, &res,1 );if (!status) {update_changeattr (old_dir, &res.old_cinfo);nfs_post_op_update_inode (old_dir, res.old_fattr);update_changeattr (new_dir, &res.new_cinfo);nfs_post_op_update_inode (new_dir, res.new_fattr); } +return status; }
@@ -2207,7 +2239,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *nfs_fattr_init (res.fattr);nfs_fattr_init (res.dir_attr); - status =rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &arg, &res,1 );if (!status) {update_changeattr (dir, &res.cinfo);nfs_post_op_update_inode (dir, res.dir_attr);
@@ -2269,7 +2301,9 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,static int nfs4_do_create (struct inode *dir,struct dentry *dentry,struct nfs4_createdata *data) { -int status =rpc_call_sync (NFS_CLIENT (dir), &data->msg,0 ); +struct nfs_server *server =NFS_SERVER (dir); +int status =nfs4_call_sync (server, &data->msg, + &data->arg, &data->res,1 );if (status ==0 ) {update_changeattr (dir, &data->res.dir_cinfo);nfs_post_op_update_inode (dir, data->res.dir_fattr);
@@ -2378,12 +2412,14 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long long)cookie); +nfs4_setup_readdir (cookie,NFS_COOKIEVERF (dir), dentry, &args); res.pgbase = args.pgbase; - status =rpc_call_sync (NFS_CLIENT (dir), &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 );if (status ==0 )memcpy (NFS_COOKIEVERF (dir), res.verifier.data,NFS4_VERIFIER_SIZE ); +nfs_invalidate_atime (dir);dprintk ("%s: returns %d\n" , __func__, status);
@@ -2458,14 +2494,20 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, .fh = fhandle, .bitmask = server->attr_bitmask, }; +struct nfs4_statfs_res res = { + .fsstat = fsstat, + };struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_STATFS ), .rpc_argp = &args, - .rpc_resp = fsstat, + .rpc_resp = &res, }; +int status;nfs_fattr_init (fsstat->fattr); -return rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 ); + +return status; }static int nfs4_proc_statfs (struct nfs_server *server,struct nfs_fh *fhandle,struct nfs_fsstat *fsstat)
@@ -2487,13 +2529,21 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, .fh = fhandle, .bitmask = server->attr_bitmask, }; +struct nfs4_fsinfo_res res = { + .fsinfo = fsinfo, + };struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_FSINFO ), .rpc_argp = &args, - .rpc_resp = fsinfo, + .rpc_resp = &res, }; +int status; + +dprintk ("--> %s\n" , __func__); + status =nfs4_call_sync (server, &msg, &args, &res,0 ); -return rpc_call_sync (server->client, &msg,0 ); +dprintk ("<-- %s status= %d\n" , __func__, status); +return status; }static int nfs4_do_fsinfo (struct nfs_server *server,struct nfs_fh *fhandle,struct nfs_fsinfo *fsinfo)
@@ -2522,20 +2572,28 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle .fh = fhandle, .bitmask = server->attr_bitmask, }; +struct nfs4_pathconf_res res = { + .pathconf = pathconf, + };struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_PATHCONF ), .rpc_argp = &args, - .rpc_resp = pathconf, + .rpc_resp = &res, }; +int status =0 ; +dprintk ("--> %s\n" , __func__);/* None of the pathconf attributes are mandatory to implement */ if ((args.bitmask[0 ] & nfs4_pathconf_bitmap[0 ]) ==0 ) {memset (pathconf,0 ,sizeof (*pathconf)); -return 0 ; + goto out; }nfs_fattr_init (pathconf->fattr); -return rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 ); +out: +dprintk ("<-- %s status= %d\n" , __func__, status); +return status; } static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -2778,18 +2836,21 @@ out:static ssize_t __nfs4_get_acl_uncached (struct inode *inode,void *buf,size_t buflen) {struct page *pages[NFS4ACL_MAXPAGES ]; +size_t resp_len = buflen;struct nfs_getaclargs args = { .fh =NFS_FH (inode), .acl_pages = pages, .acl_len = buflen, }; -size_t resp_len = buflen; +struct nfs_getaclres res = { + .acl_len = &resp_len, + };void *resp_buf;struct nfs_server *server =NFS_SERVER (inode);struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_GETACL ), .rpc_argp = &args, - .rpc_resp = &resp_len, + .rpc_resp = &res, };struct page *localpage =NULL ;int ret;
@@ -2808,7 +2869,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu resp_buf = buf;buf_to_pages (buf, buflen, args.acl_pages, &args.acl_pgbase); } - ret =rpc_call_sync (NFS_CLIENT (inode), &msg,0 ); + ret =nfs4_call_sync (server, &msg, &args, &res,0 );if (ret) goto out_free;if (resp_len > args.acl_len)
@@ -2869,10 +2930,11 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl .acl_pages = pages, .acl_len = buflen, }; +struct nfs_setaclres res;struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_SETACL ), .rpc_argp = &arg, - .rpc_resp =NULL , + .rpc_resp = &res, };int ret;
@@ -2880,7 +2942,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflreturn -EOPNOTSUPP ;nfs_inode_return_delegation (inode);buf_to_pages (buf, buflen, arg.acl_pages, &arg.acl_pgbase); - ret =rpc_call_sync (NFS_CLIENT (inode), &msg,0 ); + ret =nfs4_call_sync (server, &msg, &arg, &res,1 );nfs_access_zap_cache (inode);nfs_zap_acl_cache (inode);return ret;
@@ -3240,7 +3302,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock goto out; lsp = request->fl_u.nfs4_fl.owner; arg.lock_owner.id = lsp->ls_id.id; - status =rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &arg, &res,1 );switch (status) {case 0 : request->fl_type =F_UNLCK ;
@@ -3808,10 +3870,13 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, .page = page, .bitmask = bitmask, }; +struct nfs4_fs_locations_res res = { + .fs_locations = fs_locations, + };struct rpc_message msg = { .rpc_proc =nfs4_proc (server->nfs_client,NFSPROC4_CLNT_FS_LOCATIONS ), .rpc_argp = &args, - .rpc_resp = fs_locations, + .rpc_resp = &res, };int status;
@@ -3819,7 +3884,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,nfs_fattr_init (&fs_locations->fattr); fs_locations->server = server; fs_locations->nlocations =0 ; - status =rpc_call_sync (server->client, &msg,0 ); + status =nfs4_call_sync (server, &msg, &args, &res,0 );dprintk ("%s: returned status = %d\n" , __func__, status);return status; }
Signature · 1 line
1.6.0.2
RFC 27/85 nfs41: nfs4_setup_sequence
In reply to Benny HalevyPerform the nfs4_setup_sequence in the rpc_call_prepare state.
If a session slot is not available, we will rpc_sleep_on the slot wait queue leaving the tk_action as rpc_call_prepare.
Once we have a session slot, hang on to it even through rpc_restart_calls. Ensure the nfs41_sequence_res sr_slot pointer is NULL before rpc_run_task is called as nfs41_setup_sequence will only find a new slot if it is NULL.
A future patch will call free slot after any rpc_restart_calls, and handle the rpc restart that result from a sequence operation error.
nfs41: simplify nfs4_call_sync
--- fs/nfs/nfs4proc.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs_xdr.h | 2 +- 2 files changed, 94 insertions(+), 1 deletions(-)
fs/nfs/nfs4proc.c +93 -0
@@ -347,6 +347,70 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)return slot; } +static int nfs41_setup_sequence (struct nfs4_session *session, +struct nfs41_sequence_args *args, +struct nfs41_sequence_res *res, +int cache_reply, +struct rpc_task *task) +{ +/* stub */ +return 0 ; +} + +int nfs4_setup_sequence (struct nfs_client *clp, +struct nfs41_sequence_args *args, +struct nfs41_sequence_res *res, +int cache_reply, +struct rpc_task *task) +{ +int ret =0 ; + +dprintk ("--> %s clp %p session %p cl_minorversion %d res->sr_slot %p\n" , + __func__, clp, clp->cl_session, clp->cl_minorversion, + res->sr_slot); + +if (clp->cl_minorversion ==0 || res->sr_slot) + goto out; +BUG_ON (clp->cl_minorversion !=1 ); + ret =nfs41_setup_sequence (clp->cl_session, args, res, + cache_reply, task); +if (ret) { +memset (res,0 ,sizeof (*res)); +if (ret != -EAGAIN ) { +/* terminate rpc task */ + task->tk_status = ret; + task->tk_action =NULL ; + } + } +out: +dprintk ("<-- %s status=%d\n" , __func__, ret); +return ret; +} + +struct nfs41_call_sync_data { +struct nfs_server *server; +struct rpc_message *msg; +struct nfs41_sequence_args *seq_args; +struct nfs41_sequence_res *seq_res; +int cache_reply; +}; + +static void nfs41_call_sync_prepare (struct rpc_task *task,void *calldata) +{ +struct nfs41_call_sync_data *data = calldata; + +dprintk ("--> %s data->server->session %p\n" , __func__, + data->server->nfs_client->cl_session); +if (nfs4_setup_sequence (data->server->nfs_client, data->seq_args, + data->seq_res, data->cache_reply, task)) +return ; +rpc_call_start (task); +} + +struct rpc_call_ops nfs41_call_sync_ops = { + .rpc_call_prepare = nfs41_call_sync_prepare, +}; +#endif /* CONFIG_NFS_V4_1 */ static int _nfs4_call_sync(struct nfs_server *server,
@@ -355,6 +419,35 @@ static int _nfs4_call_sync(struct nfs_server *server, struct nfs41_sequence_res *res, int cache_reply) { +#ifdef CONFIG_NFS_V4_1 +if (server->nfs_client->cl_minorversion) { +int ret; +struct rpc_task *task; +struct nfs41_call_sync_data data = { + .server = server, + .msg = msg, + .seq_args = args, + .seq_res = res, + .cache_reply = cache_reply, + }; +struct rpc_task_setup task_setup = { + .rpc_client = server->client, + .rpc_message = msg, + .callback_ops = &nfs41_call_sync_ops, + .callback_data = &data + }; + + res->sr_slot =NULL ; + task =rpc_run_task (&task_setup); +if (IS_ERR (task)) + ret =PTR_ERR (task); +else { + ret = task->tk_status; +rpc_put_task (task); + } +return ret; + } +#endif /* CONFIG_NFS_V4_1 */ return rpc_call_sync (server->client, msg,0 ); }
include/linux/nfs_xdr.h +1 -1
@@ -134,7 +134,7 @@ struct nfs41_sequence_args {#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100struct nfs41_sequence_res { -/* stub */ +struct nfs4_slot *sr_slot;/* slot used to send request */ };#if defined(CONFIG_NFS_V4_1 )
Signature · 1 line
1.6.0.2
RFC 28/85 nfs41: setup_sequence method
In reply to Benny HalevyAllocate a slot in the session slot table and set the sequence op arguments.
Called at the rpc prepare stage.
--- fs/nfs/nfs4proc.c | 23 ++++++++++++++++++++++- include/linux/nfs_xdr.h | 5 ++++- 2 files changed, 26 insertions(+), 2 deletions(-)
fs/nfs/nfs4proc.c +22 -1
@@ -353,7 +353,28 @@ static int nfs41_setup_sequence(struct nfs4_session *session,int cache_reply, struct rpc_task *task) { -/* stub */ + struct nfs4_slot *slot; +struct nfs4_slot_table *tbl; + +dprintk ("--> %s\n" , __func__); + tbl = &session->fore_channel.slot_table; + slot =nfs4_find_slot (tbl, task); + +if (!slot) { +rpc_sleep_on (&tbl->slot_tbl_waitq, task,NULL ); +dprintk ("<-- %s: no free slots\n" , __func__); +return -EAGAIN ; + } + + args->sa_session = session; + args->sa_slot = slot; + args->sa_cache_this = cache_reply; + +dprintk ("<-- %s slot=%p slotid=%d seqid=%d\n" , __func__, + slot,slot_idx (tbl, slot), slot->seq_nr); + + res->sr_slot = slot; + res->sr_renewal_time = jiffies;return 0 ; }
include/linux/nfs_xdr.h +4 -1
@@ -120,7 +120,9 @@ struct sessionid4 { };struct nfs41_sequence_args { -/* stub */ +struct nfs4_session *sa_session; +struct nfs4_slot *sa_slot; +u32 sa_cache_this; };#define SEQ4_STATUS_CB_PATH_DOWN 0x00000001
@@ -135,6 +137,7 @@ struct nfs41_sequence_args {struct nfs41_sequence_res {struct nfs4_slot *sr_slot;/* slot used to send request */ +unsigned long sr_renewal_time; };#if defined(CONFIG_NFS_V4_1 )
Signature · 1 line
1.6.0.2
RFC 2/85 nfs: return compound hdr.status when there are no op replies
In reply to Benny HalevyWhen there are no op replies encoded in the compound reply hdr.status still contains the overall status of the compound rpc. This can happen, e.g., when the server returns a NFS4ERR_MINOR_VERS_MISMATCH error.
--- fs/nfs/nfs4xdr.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
fs/nfs/nfs4xdr.c +2 -0
@@ -2222,6 +2222,8 @@ static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr) hdr->tag = (char *)p; p +=XDR_QUADLEN (hdr->taglen);READ32 (hdr->nops); +if (unlikely (hdr->nops <1 )) +return nfs4_stat_to_errno (hdr->status);return 0 ; }
Signature · 1 line
1.6.0.2
RFC 29/85 nfs41: nfs41_sequence_done
In reply to Benny HalevyHandle session level errors, update slot sequence id and sessions bookeeping, free slot.
--- fs/nfs/nfs4proc.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs_xdr.h | 3 ++ 2 files changed, 64 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +61 -0
@@ -296,6 +296,66 @@ nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)rpc_wake_up_next (&tbl->slot_tbl_waitq); } +/* For pNFS filelayout data servers: +* the nfs_client is NULL - to signal no lease update. +* session is the data server. +*/ +static void nfs41_sequence_done (struct nfs_client *clp, +struct nfs41_sequence_res *res, +int rpc_status) +{ +unsigned long timestamp; +struct nfs4_slot_table *tbl; +struct nfs4_slot *slot; +int status =NFS4_OK ; + +if (res->sr_flags &SEQ4_STATUS_USE_TK_STATUS ) + status = rpc_status; + + tbl = &res->sr_session->fore_channel.slot_table; + slot = res->sr_slot; + +switch (status) { +case NFS4_OK : +/* +* The sequence call was successful, +* Update the slot's sequence and client's lease renewal timers +*/ + ++slot->seq_nr; +if (!clp) +break ; + timestamp = res->sr_renewal_time; +spin_lock (&clp->cl_lock); +if (time_before (clp->cl_last_renewal, timestamp)) + clp->cl_last_renewal = timestamp; +spin_unlock (&clp->cl_lock); +break ; + +case -NFS4ERR_BADSESSION : +case -NFS4ERR_BADSLOT : +case -NFS4ERR_BADXDR : +case -NFS4ERR_BAD_HIGH_SLOT : +case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION : +case -NFS4ERR_DEADSESSION : +case -NFS4ERR_DELAY : +case -NFS4ERR_REP_TOO_BIG : +case -NFS4ERR_REP_TOO_BIG_TO_CACHE : +case -NFS4ERR_REQ_TOO_BIG : +case -NFS4ERR_RETRY_UNCACHED_REP : +case -NFS4ERR_SEQUENCE_POS : +case -NFS4ERR_SEQ_FALSE_RETRY : +case -NFS4ERR_SEQ_MISORDERED : +case -NFS4ERR_TOO_MANY_OPS : +dprintk ("%s: status %d\n" , __func__, status); +break ; + +default : +printk (KERN_WARNING "%s: Unexpected status %d\n" , __func__, + status); + } +nfs41_free_slot (tbl, slot); +} +/* * nfs4_find_slot - efficiently look for a free slot *
@@ -373,6 +433,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,dprintk ("<-- %s slot=%p slotid=%d seqid=%d\n" , __func__, slot,slot_idx (tbl, slot), slot->seq_nr); + res->sr_session = session; res->sr_slot = slot; res->sr_renewal_time = jiffies;return 0 ;
include/linux/nfs_xdr.h +3 -0
@@ -134,8 +134,11 @@ struct nfs41_sequence_args {#define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040#define SEQ4_STATUS_LEASE_MOVED 0x00000080#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100 +#define SEQ4_STATUS_USE_TK_STATUS 0x10000000/* internal error */ struct nfs41_sequence_res { +struct nfs4_session *sr_session; +u32 sr_flags;struct nfs4_slot *sr_slot;/* slot used to send request */ unsigned long sr_renewal_time; };
Signature · 1 line
1.6.0.2
RFC 30/85 nfs41: nfs41_call_sync_done
In reply to Benny HalevyImplement nfs4.1 synchronous rpc_call_done method that essentially just calls nfs4_sequence_done, that turns around and calls nfs41_sequence_done for minorversion1 rpcs.
--- fs/nfs/nfs4proc.c | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +18 -0
@@ -489,8 +489,17 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) rpc_call_start(task); } +static void nfs41_call_sync_done (struct rpc_task *task,void *calldata) +{ +struct nfs41_call_sync_data *data = calldata; +struct nfs_server *server = data->server; + +nfs41_sequence_done (server->nfs_client, data->seq_res, task->tk_status); +} +struct rpc_call_ops nfs41_call_sync_ops = { .rpc_call_prepare = nfs41_call_sync_prepare, + .rpc_call_done = nfs41_call_sync_done, };#endif /* CONFIG_NFS_V4_1 */
@@ -537,6 +546,15 @@ static int _nfs4_call_sync(struct nfs_server *server,_nfs4_call_sync ((server), (msg), &(args)->seq_args, \ &(res)->seq_res, (cache_reply)) +static void nfs4_sequence_done (const struct nfs_server *server, +struct nfs41_sequence_res *res,int rpc_status) +{ +#ifdef CONFIG_NFS_V4_1 +if (server->nfs_client->cl_minorversion) +nfs41_sequence_done (server->nfs_client, res, rpc_status); +#endif /* CONFIG_NFS_V4_1 */ +} +static void update_changeattr (struct inode *dir,struct nfs4_change_info *cinfo) {struct nfs_inode *nfsi =NFS_I (dir);
Signature · 1 line
1.6.0.2
RFC 31/85 nfs41: separate free slot from sequence done
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
Don't free the slot until after all rpc_restart_calls have completed. Session reset will require more work.
--- fs/nfs/internal.h | 14 ++++++++++++++ fs/nfs/nfs4proc.c | 36 +++++++++++++++++++++++++++++------- fs/nfs/read.c | 8 ++++++-- fs/nfs/write.c | 1 + 4 files changed, 50 insertions(+), 9 deletions(-)
fs/nfs/internal.h +14 -0
@@ -180,6 +180,20 @@ extern int nfs4_path_walk(struct nfs_server *server, const char *path);#endif +/* nfs4proc.c */ +#ifdef CONFIG_NFS_V4_1 +extern void nfs41_sequence_free_slot (struct nfs41_sequence_res *res); +#endif /* CONFIG_NFS_V4_1 */ + +static inline void nfs4_sequence_free_slot (const struct nfs_server *server, +struct nfs41_sequence_res *res) +{ +#ifdef CONFIG_NFS_V4_1 +if (server->nfs_client->cl_minorversion) +nfs41_sequence_free_slot (res); +#endif /* CONFIG_NFS_V4_1 */ +} +/* * Determine the device name as a string */
fs/nfs/nfs4proc.c +29 -7
@@ -258,7 +258,7 @@ static inline int bmp2idx(unsigned long *base, unsigned long *bmp,* word in the bitmap. * If none found, highest_used_slotid is set to -1. */ -static void +void nfs41_free_slot (struct nfs4_slot_table *tbl,struct nfs4_slot *slot) {int slotid =slot_idx (tbl, slot);
@@ -296,6 +296,17 @@ nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)rpc_wake_up_next (&tbl->slot_tbl_waitq); } +void nfs41_sequence_free_slot (struct nfs41_sequence_res *res) +{ +if (res->sr_session ==NULL || res->sr_slot ==NULL ) { +dprintk ("%s: %s\n" , __func__, + res->sr_session ==NULL ?"No session" :"No slot" ); +return ; + } +nfs41_free_slot (&res->sr_session->fore_channel.slot_table, + res->sr_slot); +} +/* For pNFS filelayout data servers: * the nfs_client is NULL - to signal no lease update. * session is the data server.
@@ -346,14 +357,18 @@ static void nfs41_sequence_done(struct nfs_client *clp,case -NFS4ERR_SEQ_FALSE_RETRY :case -NFS4ERR_SEQ_MISORDERED :case -NFS4ERR_TOO_MANY_OPS : -dprintk ("%s: status %d\n" , __func__, status); +dprintk ("%s: Free Slot: status %d\n" , __func__, status); +/* The session needs to be reset, so free the slot and set the +* sr_slot to NULL so that nfs4_setup_sequence calls +* nfs41_find_slot and kicks off session reset. */ +nfs41_sequence_free_slot (res); + res->sr_slot =NULL ;break ;default :printk (KERN_WARNING "%s: Unexpected status %d\n" , __func__, status); } -nfs41_free_slot (tbl, slot); }/*
@@ -495,6 +510,7 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)struct nfs_server *server = data->server;nfs41_sequence_done (server->nfs_client, data->seq_res, task->tk_status); +nfs41_sequence_free_slot (data->seq_res); }struct rpc_call_ops nfs41_call_sync_ops = {
@@ -1592,6 +1608,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)return ; } } +nfs4_sequence_free_slot (server, &calldata->res.seq_res);nfs_refresh_inode (calldata->inode, calldata->res.fattr); }
@@ -2352,6 +2369,7 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)if (nfs4_async_handle_error (task, res->server) == -EAGAIN )return 0 ; +nfs4_sequence_free_slot (res->server, &res->seq_res);update_changeattr (dir, &res->cinfo);nfs_post_op_update_inode (dir, &res->dir_attr);return 1 ;
@@ -2855,11 +2873,13 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messagstatic int nfs4_commit_done (struct rpc_task *task,struct nfs_write_data *data) {struct inode *inode = data->inode; - -if (nfs4_async_handle_error (task,NFS_SERVER (inode)) == -EAGAIN ) { +struct nfs_server *server =NFS_SERVER (inode); + +if (nfs4_async_handle_error (task, server) == -EAGAIN ) {rpc_restart_call (task);return -EAGAIN ; } +nfs4_sequence_free_slot (server, &data->res.seq_res);nfs_refresh_inode (inode, data->res.fattr);return 0 ; }
@@ -3585,6 +3605,7 @@ static void nfs4_locku_release_calldata(void *data)static void nfs4_locku_done (struct rpc_task *task,void *data) {struct nfs4_unlockdata *calldata = data; +const struct nfs_server *server = calldata->server;if (RPC_ASSASSINATED (task))return ;
@@ -3593,15 +3614,16 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)memcpy (calldata->lsp->ls_stateid.data, calldata->res.stateid.data,sizeof (calldata->lsp->ls_stateid.data)); -renew_lease (calldata->server, calldata->timestamp); +renew_lease (server, calldata->timestamp);break ;case -NFS4ERR_STALE_STATEID :case -NFS4ERR_EXPIRED :break ;default : -if (nfs4_async_handle_error (task, calldata->server) == -EAGAIN ) +if (nfs4_async_handle_error (task, server) == -EAGAIN )rpc_restart_call (task); } +nfs4_sequence_free_slot (server, &calldata->res.seq_res); }static void nfs4_locku_prepare (struct rpc_task *task,void *data)
fs/nfs/read.c +6 -2
@@ -351,19 +351,23 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *datastruct nfs_readres *resp = &data->res;if (resp->eof || resp->count == argp->count) -return ; + goto out;/* This is a short read! */ nfs_inc_stats (data->inode,NFSIOS_SHORTREAD );/* Has the server at least made some progress? */ if (resp->count ==0 ) -return ; + goto out;/* Yes, so retry the read at the end of the data */ argp->offset += resp->count; argp->pgbase += resp->count; argp->count -= resp->count;rpc_restart_call (task); +return ; +out: +nfs4_sequence_free_slot (NFS_SERVER (data->inode), &data->res.seq_res); +return ; }/*
fs/nfs/write.c +1 -0
@@ -1171,6 +1171,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)/* Can't do anything about it except throw an error. */ task->tk_status = -EIO ; } +nfs4_sequence_free_slot (NFS_SERVER (data->inode), &data->res.seq_res);return 0 ; }
Signature · 1 line
1.6.0.2
RFC 32/85 nfs41: sequence setup/done support
In reply to Benny HalevyImlpement the rpc_call_validate_args methods for asynchronuos nfs rpcs, call nfs41_setup_sequence from respective rpc_call_validate_args methods.
Call nfs4_sequence_done from respective rpc_call_done methods.
Note that we need to pass a pointer to the nfs_server in calls data for passing on to nfs4_sequence_done.
--- fs/nfs/direct.c | 1 + fs/nfs/nfs4_fs.h | 10 ++++++ fs/nfs/nfs4proc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++--- fs/nfs/read.c | 23 +++++++++++++ fs/nfs/unlink.c | 16 +++++++++ fs/nfs/write.c | 23 +++++++++++++ include/linux/nfs_xdr.h | 7 ++-- 7 files changed, 152 insertions(+), 8 deletions(-)
fs/nfs/direct.c +1 -0
@@ -306,6 +306,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,if (unlikely (!data))break ; + data->args.server =NFS_SERVER (inode);down_read (¤t->mm->mmap_sem); result =get_user_pages (current, current->mm, user_addr, data->npages,1 ,0 , data->pagevec,NULL );
fs/nfs/nfs4_fs.h +10 -0
@@ -190,11 +190,21 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;#if defined(CONFIG_NFS_V4_1 ) +extern int nfs4_setup_sequence (struct nfs_client *clp, +struct nfs41_sequence_args *args,struct nfs41_sequence_res *res, +int cache_reply,struct rpc_task *task);extern void nfs4_put_session (struct nfs4_session **session);extern void nfs4_get_session (struct nfs_client *clp);extern struct nfs4_session *nfs4_alloc_session (void );extern int nfs4_proc_create_session (struct nfs4_session *);extern int nfs4_proc_destroy_session (struct nfs4_session *); +#else /* CONFIG_NFS_v4_1 */ +static inline int nfs4_setup_sequence (struct nfs_client *clp, +struct nfs41_sequence_args *args,struct nfs41_sequence_res *res, +int cache_reply,struct rpc_task *task) +{ +return 0 ; +}#endif /* CONFIG_NFS_V4_1 */ extern const u32 nfs4_fattr_bitmap[2 ];
fs/nfs/nfs4proc.c +75 -5
212 lines not on this page · raw message
fs/nfs/read.c +23 -0
@@ -22,6 +22,7 @@#include <asm/system.h> +#include "nfs4_fs.h" #include "internal.h" #include "iostat.h"
@@ -175,6 +176,7 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, .flags = RPC_TASK_ASYNC | swap_flags, }; +BUG_ON (data->args.server ==NULL ); data->req = req; data->inode = inode; data->cred = msg.rpc_cred;
@@ -254,6 +256,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne data =nfs_readdata_alloc (1 );if (!data) goto out_bad; + data->args.server =NFS_SERVER (inode);list_add (&data->pages, &list); requests++; nbytes -= len;
@@ -305,6 +308,7 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsignedif (!data) goto out_bad; + data->args.server =NFS_SERVER (inode); pages = data->pagevec;while (!list_empty (head)) { req =nfs_list_entry (head->next);
@@ -404,7 +408,23 @@ static void nfs_readpage_release_partial(void *calldata)nfs_readdata_release (calldata); } +#if defined(CONFIG_NFS_V4_1 ) +void nfs_read_prepare (struct rpc_task *task,void *calldata) +{ +struct nfs_read_data *data = calldata; +struct nfs_server *server = data->args.server; + +if (nfs4_setup_sequence (server->nfs_client, &data->args.seq_args, + &data->res.seq_res,0 , task)) +return ; +rpc_call_start (task); +} +#endif /* CONFIG_NFS_V4_1 */ +static const struct rpc_call_ops nfs_read_partial_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_read_prepare, +#endif .rpc_call_done = nfs_readpage_result_partial, .rpc_release = nfs_readpage_release_partial, };
@@ -468,6 +488,9 @@ static void nfs_readpage_release_full(void *calldata) }static const struct rpc_call_ops nfs_read_full_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_read_prepare, +#endif .rpc_call_done = nfs_readpage_result_full, .rpc_release = nfs_readpage_release_full, };
fs/nfs/unlink.c +16 -0
@@ -15,6 +15,7 @@#include <linux/wait.h> #include "internal.h" +#include "nfs4_fs.h" struct nfs_unlinkdata {struct hlist_node list;
@@ -102,9 +103,24 @@ static void nfs_async_unlink_release(void *calldata)nfs_sb_deactive (sb); } +#if defined(CONFIG_NFS_V4_1 ) +void nfs_unlink_prepare (struct rpc_task *task,void *calldata) +{ +struct nfs_unlinkdata *data = calldata; +struct nfs_server *server =NFS_SERVER (data->dir); + +if (nfs4_setup_sequence (server->nfs_client, &data->args.seq_args, + &data->res.seq_res,1 , task)) +return ; +rpc_call_start (task); +} +#endif /* CONFIG_NFS_V4_1 */ static const struct rpc_call_ops nfs_unlink_ops = { .rpc_call_done = nfs_async_unlink_done, .rpc_release = nfs_async_unlink_release, +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_unlink_prepare, +#endif };static int nfs_do_call_unlink (struct dentry *parent,struct inode *dir,struct nfs_unlinkdata *data)
fs/nfs/write.c +23 -0
@@ -25,6 +25,7 @@#include "delegation.h" #include "internal.h" #include "iostat.h" +#include "nfs4_fs.h" #define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -1026,7 +1027,23 @@ out:nfs_writedata_release (calldata); } +#if defined(CONFIG_NFS_V4_1 ) +void nfs_write_prepare (struct rpc_task *task,void *calldata) +{ +struct nfs_write_data *data = calldata; +struct nfs_server *server =NFS_SERVER (data->inode); + +if (nfs4_setup_sequence (server->nfs_client, &data->args.seq_args, + &data->res.seq_res,1 , task)) +return ; +rpc_call_start (task); +} +#endif /* CONFIG_NFS_V4_1 */ +static const struct rpc_call_ops nfs_write_partial_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_write_prepare, +#endif .rpc_call_done = nfs_writeback_done_partial, .rpc_release = nfs_writeback_release_partial, };
@@ -1089,6 +1106,9 @@ remove_request: }static const struct rpc_call_ops nfs_write_full_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_write_prepare, +#endif .rpc_call_done = nfs_writeback_done_full, .rpc_release = nfs_writeback_release_full, };
@@ -1328,6 +1348,9 @@ static void nfs_commit_release(void *calldata) }static const struct rpc_call_ops nfs_commit_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_write_prepare, +#endif .rpc_call_done = nfs_commit_done, .rpc_release = nfs_commit_release, };
include/linux/nfs_xdr.h +4 -3
@@ -172,7 +172,7 @@ struct nfs_openargs {int delegation_type;/* CLAIM_PREVIOUS */ } u;const struct qstr * name; -const struct nfs_server *server;/* Needed for ID mapping */ +struct nfs_server * server;/* Needed for ID mapping */ const u32 * bitmask;__u32 claim;struct nfs41_sequence_args seq_args;
@@ -292,7 +292,7 @@ struct nfs4_delegreturnargs {struct nfs4_delegreturnres {struct nfs_fattr * fattr; -const struct nfs_server *server; +struct nfs_server *server;struct nfs41_sequence_res seq_res; };
@@ -306,6 +306,7 @@ struct nfs_readargs {__u32 count;unsigned int pgbase;struct page ** pages; +struct nfs_server *server;struct nfs41_sequence_args seq_args; };
@@ -355,7 +356,7 @@ struct nfs_removeargs { };struct nfs_removeres { -const struct nfs_server *server; +struct nfs_server *server;struct nfs4_change_info cinfo;struct nfs_fattr dir_attr;struct nfs41_sequence_res seq_res;
Signature · 1 line
1.6.0.2
RFC 33/85 nfs41: Support sessions with O_DIRECT.
In reply to Benny HalevyFrom: Dean Hildebrand <[email protected]>
--- fs/nfs/direct.c | 9 +++++++++ fs/nfs/internal.h | 6 ++++++ 2 files changed, 15 insertions(+), 0 deletions(-)
fs/nfs/direct.c +9 -0
@@ -259,6 +259,9 @@ static void nfs_direct_read_release(void *calldata) }static const struct rpc_call_ops nfs_read_direct_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_read_prepare, +#endif /* CONFIG_NFS_V4_1 */ .rpc_call_done = nfs_direct_read_result, .rpc_release = nfs_direct_read_release, };
@@ -536,6 +539,9 @@ static void nfs_direct_commit_release(void *calldata) }static const struct rpc_call_ops nfs_commit_direct_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_write_prepare, +#endif /* CONFIG_NFS_V4_1 */ .rpc_call_done = nfs_direct_commit_result, .rpc_release = nfs_direct_commit_release, };
@@ -674,6 +680,9 @@ out_unlock: }static const struct rpc_call_ops nfs_write_direct_ops = { +#if defined(CONFIG_NFS_V4_1) + .rpc_call_prepare = nfs_write_prepare, +#endif /* CONFIG_NFS_V4_1 */ .rpc_call_done = nfs_direct_write_result, .rpc_release = nfs_direct_write_release, };
fs/nfs/internal.h +6 -0
@@ -180,6 +180,12 @@ extern int nfs4_path_walk(struct nfs_server *server, const char *path);#endif +/* read.c */ +extern void nfs_read_prepare (struct rpc_task *task,void *calldata); + +/* write.c */ +extern void nfs_write_prepare (struct rpc_task *task,void *calldata); +/* nfs4proc.c */ #ifdef CONFIG_NFS_V4_1 extern void nfs41_sequence_free_slot (struct nfs41_sequence_res *res);
Signature · 1 line
1.6.0.2
RFC 34/85 nfs41: exchange_id operation
In reply to Benny HalevyImplement the exchange_id operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Unlike NFSv4.0, NFSv4.1 requires machine credentials. RPC_AUTH_GSS machine credentials will be passed into the kernel at mount time to be available for the exchange_id operation.
RPC_AUTH_UNIX root mounts can use the UNIX root credential. Store the root credential in the nfs_client struct.
Without a credential, NFSv4.1 state renewal fails.
nfs41: establish clientid via exchange id only if cred != NULL
Quoted 1 line
From 2.6.26
reclaimer()uses machine cred for setting up the client id
therefore it is never expected to be NULL.
Note: NFS4_OPAQUE_LIMIT moved from include/linux/nfsd/state.h to include/linux/nfs4.h since it's now used also for client side exchange_id xdr data type.
--- fs/nfs/nfs4proc.c | 63 +++++++++++++++++++- fs/nfs/nfs4xdr.c | 143 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs4.h | 1 + include/linux/nfs_fs_sb.h | 6 ++ include/linux/nfs_xdr.h | 42 +++++++++++++ include/linux/nfsd/state.h | 1 - 6 files changed, 254 insertions(+), 2 deletions(-)
fs/nfs/nfs4proc.c +62 -1
@@ -48,6 +48,7 @@#include <linux/smp_lock.h> #include <linux/namei.h> #include <linux/mount.h> +#include <linux/module.h> #include "nfs4_fs.h" #include "delegation.h"
@@ -4175,9 +4176,69 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, }#ifdef CONFIG_NFS_V4_1 +/* +* nfs4_proc_exchange_id() +* +* Since the clientid has expired, all compounds using sessions +* associated with the stale clientid will be returning +* NFS4ERR_BADSESSION in the sequence operation, and will therefore +* be in some phase of session reset. +*/ static int nfs4_proc_exchange_id (struct nfs_client *clp,struct rpc_cred *cred) { -return -1 ;/* stub */ +nfs4_verifier verifier; +struct nfs41_exchange_id_args args = { + .flags = clp->cl_exchange_flags, + }; +struct nfs41_exchange_id_res res = { + .client = clp, + }; +int status; +int loop =0 ; +struct rpc_message msg = { + .rpc_proc =nfs4_proc (clp,NFSPROC4_CLNT_EXCHANGE_ID ), + .rpc_argp = &args, + .rpc_resp = &res, + .rpc_cred = cred, + }; +__be32 *p; + +dprintk ("--> %s\n" , __func__); +BUG_ON (clp ==NULL ); + p = (u32 *)verifier.data; + *p++ =htonl ((u32 )clp->cl_boot_time.tv_sec); + *p =htonl ((u32 )clp->cl_boot_time.tv_nsec); + args.verifier = &verifier; + +while (1 ) { + args.id_len =scnprintf (args.id,sizeof (args.id), +"%s/%s %u" , + clp->cl_ipaddr, +rpc_peeraddr2str (clp->cl_rpcclient, +RPC_DISPLAY_ADDR ), + clp->cl_id_uniquifier); + + status =rpc_call_sync (clp->cl_rpcclient, &msg,0 ); + +if (status !=NFS4ERR_CLID_INUSE ) +break ; + +if (signalled ()) +break ; + +/* Andy Adamson <andros at netapp.com>: Waiting a lease period +* allows the server to throw away a clientid previously +* established by this client. Of course, it doesn't help when +* the conflicting clientid was established by another client. +*/ +if (loop++ &1 ) +ssleep (clp->cl_lease_time +1 ); +else if (++clp->cl_id_uniquifier ==0 ) +break ; + } + +dprintk ("<-- %s status= %d\n" , __func__, status); +return status; }/*
fs/nfs/nfs4xdr.c +143 -0
185 lines not on this page · raw message
include/linux/nfs4.h +1 -0
@@ -21,6 +21,7 @@#define NFS4_FHSIZE 128#define NFS4_MAXPATHLEN PATH_MAX#define NFS4_MAXNAMLEN NAME_MAX +#define NFS4_OPAQUE_LIMIT 1024#define NFS4_MAX_SESSIONID_LEN 16#define NFS4_ACCESS_READ 0x0001
include/linux/nfs_fs_sb.h +6 -0
@@ -75,6 +75,12 @@ struct nfs_client {#endif /* CONFIG_NFS_V4 */ #ifdef CONFIG_NFS_V4_1 +/* clientid returned from EXCHANGE_ID, used by session operations */ +u64 cl_ex_clid; +/* The sequence id to use for the next CREATE_SESSION */ +u32 cl_seqid; +/* The flags used for obtaining the clientid during EXCHANGE_ID */ +u32 cl_exchange_flags;struct nfs4_session *cl_session;/* sharred session */ #endif /* CONFIG_NFS_V4_1 */ };
include/linux/nfs_xdr.h +42 -0
48 lines not on this page · raw message
include/linux/nfsd/state.h +0 -1
@@ -41,7 +41,6 @@#include <linux/kref.h> #include <linux/sunrpc/clnt.h> -#define NFS4_OPAQUE_LIMIT 1024 typedef struct { u32 cl_boot; u32 cl_id;
Signature · 1 line
1.6.0.2
RFC 35/85 nfs41: get_lease_time
In reply to Benny Halevyget_lease_time uses the FSINFO rpc operation to
get the lease time attribute.
--- fs/nfs/nfs4proc.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/nfs/nfs4xdr.c | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +84 -0
@@ -4241,6 +4241,90 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)return status; } +struct nfs4_get_lease_time_data { +struct nfs4_get_lease_time_args *args; +struct nfs4_get_lease_time_res *res; +struct nfs_client *clp; +struct nfs4_session *session; +}; + +static void nfs4_get_lease_time_prepare (struct rpc_task *task, +void *calldata) +{ +int ret; +struct nfs4_get_lease_time_data *data = + (struct nfs4_get_lease_time_data *)calldata; + +dprintk ("--> %s\n" , __func__); +/* just setup sequence, do not trigger session recovery +since we're invoked within one */ + ret =nfs41_setup_sequence (data->session, + &data->args->la_seq_args, + &data->res->lr_seq_res,0 , task); + +BUG_ON (ret == -EAGAIN ); +rpc_call_start (task); +dprintk ("<-- %s\n" , __func__); +} + +static void nfs4_get_lease_time_done (struct rpc_task *task, +void *calldata) +{ +struct nfs4_get_lease_time_data *data = + (struct nfs4_get_lease_time_data *)calldata; + +dprintk ("--> %s\n" , __func__); +nfs41_sequence_done (data->clp, &data->res->lr_seq_res, task->tk_status); +nfs41_sequence_free_slot (&data->res->lr_seq_res); +dprintk ("<-- %s\n" , __func__); +} + +struct rpc_call_ops nfs4_get_lease_time_ops = { + .rpc_call_prepare = nfs4_get_lease_time_prepare, + .rpc_call_done = nfs4_get_lease_time_done, +}; + +int nfs4_proc_get_lease_time (struct nfs_client *clp, +struct nfs4_session *session,struct nfs_fsinfo *fsinfo) +{ +struct rpc_task *task; +struct nfs4_get_lease_time_args args; +struct nfs4_get_lease_time_res res = { + .lr_fsinfo = fsinfo, + }; +struct nfs4_get_lease_time_data data = { + .args = &args, + .res = &res, + .clp = clp, + .session = session, + }; +struct rpc_message msg = { + .rpc_proc =nfs4_proc (clp,NFSPROC4_CLNT_GET_LEASE_TIME ), + .rpc_argp = &args, + .rpc_resp = &res, + }; +struct rpc_task_setup task_setup = { + .rpc_client = session->clnt, + .rpc_message = &msg, + .callback_ops = &nfs4_get_lease_time_ops, + .callback_data = &data + }; +int status; + +dprintk ("--> %s\n" , __func__); + task =rpc_run_task (&task_setup); + +if (IS_ERR (task)) + status =PTR_ERR (task); +else { + status = task->tk_status; +rpc_put_task (task); + } +dprintk ("<-- %s return %d\n" , __func__, status); + +return status; +} +/* * Initialize slot table *
fs/nfs/nfs4xdr.c +56 -0
80 lines not on this page · raw message
Signature · 1 line
1.6.0.2
RFC 36/85 nfs41: create_session operation
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
Implement the create_session operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
--- fs/nfs/nfs4proc.c | 141 ++++++++++++++++++++++++++++++++++- fs/nfs/nfs4xdr.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs_xdr.h | 17 ++++ 3 files changed, 350 insertions(+), 1 deletions(-)
fs/nfs/nfs4proc.c +140 -1
@@ -55,6 +55,7 @@#include "internal.h" #include "iostat.h" #if defined(CONFIG_NFS_V4_1 ) +#include "callback.h" #include <linux/nfs4_session.h> #endif /* CONFIG_NFS_V4_1 */
@@ -4448,9 +4449,147 @@ void nfs4_get_session(struct nfs_client *clp)atomic_inc (&clp->cl_session->ref_count); } +/* Initialize the values to be used by the client in CREATE_SESSION */ +static void nfs4_init_channel_attrs (struct nfs_client *clp, +struct nfs4_channel_attrs *fc_attrs, +struct nfs4_channel_attrs *bc_attrs) +{ +/* XXX: We need to have good values here... 32K is a wild guess */ + fc_attrs->headerpadsz = bc_attrs->headerpadsz =0 ; + fc_attrs->max_rqst_sz = bc_attrs->max_rqst_sz =NFS_MAX_FILE_IO_SIZE ; + fc_attrs->max_resp_sz = bc_attrs->max_resp_sz =NFS_MAX_FILE_IO_SIZE ; + fc_attrs->max_resp_sz_cached = bc_attrs->max_resp_sz_cached = +NFS_MAX_FILE_IO_SIZE ; + fc_attrs->max_ops = bc_attrs->max_ops =0xFFFFFFFF ; + fc_attrs->max_reqs = bc_attrs->max_reqs = + clp->cl_rpcclient->cl_xprt->max_reqs; + fc_attrs->rdma_attrs = bc_attrs->rdma_attrs =0 ; +} + +/* Check the values returned by the server for CREATE_SESSION. Since we made +* our needs known, if the server gives us more than we need, we don't bother +* with it. +*/ +static void nfs4_adjust_channel_attrs (struct nfs4_channel_attrs *req_attrs, +struct nfs4_channel_attrs *resp_attrs) +{ +dprintk ("%s: before adjusting: max_rqst_sz=%u max_resp_sz=%u " +"max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n" , + __func__, + resp_attrs->max_rqst_sz, resp_attrs->max_resp_sz, + resp_attrs->max_resp_sz_cached, resp_attrs->max_ops, + resp_attrs->max_reqs); + +if (req_attrs->max_rqst_sz < resp_attrs->max_rqst_sz) + resp_attrs->max_rqst_sz = req_attrs->max_rqst_sz; + +if (req_attrs->max_resp_sz < resp_attrs->max_resp_sz) + resp_attrs->max_resp_sz = req_attrs->max_resp_sz; + +if (req_attrs->max_resp_sz_cached < resp_attrs->max_resp_sz) + resp_attrs->max_resp_sz = req_attrs->max_resp_sz_cached; + +if (req_attrs->max_ops < resp_attrs->max_ops) + resp_attrs->max_ops = req_attrs->max_ops; + +if (req_attrs->max_reqs < resp_attrs->max_reqs) + resp_attrs->max_reqs = req_attrs->max_reqs; + +dprintk ("%s: after adjusting: max_rqst_sz=%u max_resp_sz=%u " +"max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n" , + __func__, + resp_attrs->max_rqst_sz, resp_attrs->max_resp_sz, + resp_attrs->max_resp_sz_cached, resp_attrs->max_ops, + resp_attrs->max_reqs); + +/* We ignore the rdma channel attributes */ +} + +static int _nfs4_proc_create_session (struct nfs4_session *session) +{ +struct nfs_client *clp = session->clp; +struct nfs41_create_session_args args = { + .client = clp, + .session = session, + .cb_program =NFS4_CALLBACK , + }; + +struct nfs41_create_session_res res = { + .client = clp, + .session = session, + }; + +struct rpc_message msg = { + .rpc_proc =nfs4_proc (clp,NFSPROC4_CLNT_CREATE_SESSION ), + .rpc_argp = &args, + .rpc_resp = &res, + }; +int status; + +nfs4_init_channel_attrs (clp, &args.fc_attrs, &args.bc_attrs); + args.flags = (SESSION4_PERSIST ); + + status =rpc_call_sync (session->clnt, &msg,0 ); + +/* Set the negotiated values in the session's channel_attrs struct */ + +if (!status) { +nfs4_adjust_channel_attrs (&args.fc_attrs, + &session->fore_channel.chan_attrs); +nfs4_adjust_channel_attrs (&args.bc_attrs, + &session->back_channel.chan_attrs); +/* Increment the clientid slot sequence id */ + clp->cl_seqid++; + } + +return status; +} + +/* +* Issues a CREATE_SESSION operation to the server. +* It is the responsibility of the caller to verify the session is +* expired before calling this routine. +*/ int nfs4_proc_create_session (struct nfs4_session *session) { -return -1 ;/* stub */ +int status; +u32 *ptr; +struct nfs_fsinfo fsinfo; +struct nfs_client *clp = session->clp; + +dprintk ("--> %s clp=%p session=%p\n" , __func__, clp, session); + + status =_nfs4_proc_create_session (session); +if (status) + goto out; + + session->clnt = clp->cl_rpcclient; + +/* Init the fore channel */ + status =nfs4_init_slot_table (&session->fore_channel); +dprintk ("fore channel initialization returned %d\n" , status); +if (status) + goto out; + +dprintk ("%s client>seqid %d\n" , __func__, clp->cl_seqid); + ptr = (int *)session->sess_id; +dprintk ("sessionid is: %u:%u:%u:%u\n" , ptr[0 ], ptr[1 ], ptr[2 ], ptr[3 ]); + +/* Get the lease time */ + status =nfs4_proc_get_lease_time (clp, session, &fsinfo); +if (status ==0 ) { +/* Update lease time and schedule renewal */ +spin_lock (&clp->cl_lock); + clp->cl_lease_time = fsinfo.lease_time *HZ ; + clp->cl_last_renewal = jiffies; +clear_bit (NFS4CLNT_LEASE_EXPIRED , &clp->cl_state); +spin_unlock (&clp->cl_lock); + +nfs4_schedule_state_renewal (clp); + } +out: +dprintk ("<-- %s\n" , __func__); +return status; }int nfs4_proc_destroy_session (struct nfs4_session *session)
fs/nfs/nfs4xdr.c +193 -0
241 lines not on this page · raw message
include/linux/nfs_xdr.h +17 -0
@@ -2,6 +2,9 @@#define _LINUX_NFS_XDR_H#include <linux/nfsacl.h> +#ifdef CONFIG_NFS_V4_1 +#include <linux/nfs4_session.h> +#endif /* * To change the maximum rsize and wsize supported by the NFS client, adjust
@@ -899,6 +902,20 @@ struct nfs41_exchange_id_res {struct server_scope server_scope; struct nfs_impl_id4 impl_id; }; + +struct nfs41_create_session_args { +struct nfs_client *client; +struct nfs4_session *session; +uint32_t flags; +uint32_t cb_program; +struct nfs4_channel_attrs fc_attrs;/* Fore Channel */ +struct nfs4_channel_attrs bc_attrs;/* Back Channel */ +}; + +struct nfs41_create_session_res { +struct nfs_client *client; +struct nfs4_session *session; +};#endif /* CONFIG_NFS_V4_1 */ struct nfs_page ;
Signature · 1 line
1.6.0.2
RFC 37/85 nfs41: destroy_session operation
In reply to Benny HalevyImplement the destroy_session operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
--- fs/nfs/nfs4proc.c | 23 ++++++++++++++++++- fs/nfs/nfs4xdr.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/nfs/super.c | 2 + 3 files changed, 86 insertions(+), 1 deletions(-)
fs/nfs/nfs4proc.c +22 -1
@@ -4592,9 +4592,30 @@ out:return status; } +/* +* Issue the over-the-wire RPC DESTROY_SESSION. +* The caller must serialize access to this routine. +*/ int nfs4_proc_destroy_session (struct nfs4_session *session) { -return -1 ;/* stub */ +int status =0 ; +struct rpc_message msg; + +dprintk ("--> nfs4_proc_destroy_session\n" ); + + msg.rpc_proc =nfs4_proc (session->clp,NFSPROC4_CLNT_DESTROY_SESSION ); + msg.rpc_argp = session; + msg.rpc_resp =NULL ; + msg.rpc_cred =NULL ; + status =rpc_call_sync (session->clnt, &msg,0 ); + +if (status) +printk (KERN_WARNING +"Got error %d from the server on DESTROY_SESSION. " +"Session has been destroyed regardless...\n" , status); + +dprintk ("<-- nfs4_proc_destroy_session\n" ); +return status; }static int nfs4_proc_sequence (struct nfs_client *clp,struct rpc_cred *cred)
fs/nfs/nfs4xdr.c +62 -0
104 lines not on this page · raw message
fs/nfs/super.c +2 -0
@@ -2431,11 +2431,13 @@ static void nfs4_kill_super(struct super_block *sb) {struct nfs_server *server =NFS_SB (sb); +dprintk ("--> %s\n" , __func__);nfs_return_all_delegations (sb);kill_anon_super (sb);nfs4_renewd_prepare_shutdown (server);nfs_free_server (server); +dprintk ("<-- %s\n" , __func__); }/*
Signature · 1 line
1.6.0.2
RFC 38/85 nfs41: sequence operation
In reply to Benny HalevyImplement the sequence operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Check returned sessionid, slotid and slot sequenceid in decode_sequence.
Pass the sequence operation status to nfs41_sequence_done in order to determine when to increment the slot sequence ID.
Free slot is separated from sequence done.
--- fs/nfs/nfs4proc.c | 92 +++++++++++++++++++++++++++++++++++++++++- fs/nfs/nfs4xdr.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 201 insertions(+), 6 deletions(-)
fs/nfs/nfs4proc.c +90 -2
@@ -4620,13 +4620,101 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)static int nfs4_proc_sequence (struct nfs_client *clp,struct rpc_cred *cred) { -return -1 ;/* stub */ +struct nfs41_sequence_args args; +struct nfs41_sequence_res res; +struct nfs_server *server; + +struct rpc_message msg = { + .rpc_proc =nfs4_proc (clp,NFSPROC4_CLNT_SEQUENCE ), + .rpc_argp = &args, + .rpc_resp = &res, + .rpc_cred = cred, + }; +int status; + +/* +* We need to renew the lease on the server. For this, we use any +* session we have on the server to send the SEQUENCE op +*/ +BUG_ON (list_empty (&clp->cl_superblocks)); + + server = list_entry(clp->cl_superblocks.next, struct nfs_server, + client_link); + + args.sa_cache_this =0 ; + + status =_nfs4_call_sync (server, &msg, &args, &res,0 ); +return status; +} + +void nfs41_sequence_call_done (struct rpc_task *task,void *data) +{ +struct nfs_server *server = (struct nfs_server *)data; + +nfs4_sequence_done (server, task->tk_msg.rpc_resp, task->tk_status); +nfs4_sequence_free_slot (server, task->tk_msg.rpc_resp); +dprintk ("%s rpc_cred %p\n" , __func__, task->tk_msg.rpc_cred); + +put_rpccred (task->tk_msg.rpc_cred); +kfree (task->tk_msg.rpc_argp); +kfree (task->tk_msg.rpc_resp); + +dprintk ("<-- %s\n" , __func__); +} + +static void nfs41_sequence_prepare (struct rpc_task *task,void *data) +{ +struct nfs_server *server; +struct nfs41_sequence_args *args; +struct nfs41_sequence_res *res; + + server = (struct nfs_server *)data; + args = task->tk_msg.rpc_argp; + res = task->tk_msg.rpc_resp; + +if (nfs4_setup_sequence (server->nfs_client, args, res,0 , task)) +return ; +rpc_call_start (task); } +static const struct rpc_call_ops nfs41_sequence_ops = { + .rpc_call_done = nfs41_sequence_call_done, + .rpc_call_prepare = nfs41_sequence_prepare, +}; +static int nfs41_proc_async_sequence (struct nfs_client *clp,struct rpc_cred *cred) { -return -1 ;/* stub */ +struct nfs41_sequence_args *args; +struct nfs41_sequence_res *res; +struct nfs_server *server; +struct rpc_message msg = { + .rpc_proc =nfs4_proc (clp,NFSPROC4_CLNT_SEQUENCE ), + .rpc_cred = cred, + }; + + args =kzalloc (sizeof (*args),GFP_KERNEL ); +if (!args) +return -ENOMEM ; + res =kzalloc (sizeof (*res),GFP_KERNEL ); +if (!res) { +kfree (args); +return -ENOMEM ; + } + msg.rpc_argp = args; + msg.rpc_resp = res; + +/* +* We need to renew the lease on the server. For this, we use any +* session we have on the server to send the SEQUENCE op +*/ +BUG_ON (list_empty (&clp->cl_superblocks)); + + server = list_entry(clp->cl_superblocks.next, struct nfs_server, + client_link); + +return rpc_call_async (server->client, &msg,RPC_TASK_SOFT , + &nfs41_sequence_ops, (void *)server); }#endif /* CONFIG_NFS_V4_1 */
fs/nfs/nfs4xdr.c +111 -4
165 lines not on this page · raw message
Signature · 1 line
1.6.0.2
RFC 39/85 nfs41: session recovery infrastructure
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
FIXME: review comment message.
NFSv4.1 session recovery.
Sessions are created in the "alloc" state and session recovery is used to initiate session creation as well.
nfs41: Correctly use new session in exception handling
We will need to handle several layers of session recovery depending on the error. As a last resort, we will need to use the big hammer; destroy an existing session and create a new one.
The current code creates a new session without destroying the old one. Destroy the existing session and initialize a new session before calling nfs41_recover_session_sync.
nfs41: correctly expire and validate session
Do not expire session in session_reclaimer error case where the session could be ok (create session succeeded) but nfs4_proc_get_lease_time failed. Leave the session expiration (as well as new session initialization) to callers.
The session is valid as soon as the create session rpc completes successfully, and is not dependant upon a successful nfs4_proc_get_lease_time rpc. Move session validation from nfs4_proc_create_session to the success case of _nfs4_proc_create_session.
nfs41: add nfs_client pointer to struct nfs4_session
The session is always associated with a struct nfs_client that holds the exchange_id results. Add an nfs_client struct backpointer to the session and refactor the session recovery routines to only require a struct nfs4_sessions parameter.
--- fs/nfs/Makefile | 1 + fs/nfs/client.c | 2 +- fs/nfs/nfs41_session_recovery.c | 186 ++++++++++++++++++++++++++++++++ fs/nfs/nfs4proc.c | 17 +++- include/linux/nfs41_session_recovery.h | 40 +++++++ 5 files changed, 242 insertions(+), 4 deletions(-) create mode 100644 fs/nfs/nfs41_session_recovery.c create mode 100644 include/linux/nfs41_session_recovery.h
fs/nfs/Makefile +1 -0
@@ -14,4 +14,5 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ delegation.o idmap.o \ callback.o callback_xdr.o callback_proc.o \ nfs4namespace.o +nfs-$(CONFIG_NFS_V4_1) += nfs41_session_recovery.o nfs-$(CONFIG_SYSCTL) += sysctl.o
fs/nfs/client.c +1 -1
@@ -38,7 +38,7 @@#include <net/ipv6.h> #include <linux/nfs_xdr.h> #if defined(CONFIG_NFS_V4_1 ) -#include <linux/nfs4_session.h> +#include <linux/nfs41_session_recovery.h> #endif /* CONFIG_NFS_V4_1 */ #include <asm/system.h>
fs/nfs/nfs41_session_recovery.c new file +186 -0
186 lines not on this page · raw message
fs/nfs/nfs4proc.c +14 -3
@@ -56,7 +56,7 @@#include "iostat.h" #if defined(CONFIG_NFS_V4_1 )#include "callback.h" -#include <linux/nfs4_session.h> +#include <linux/nfs41_session_recovery.h> #endif /* CONFIG_NFS_V4_1 */ #define NFSDBG_FACILITY NFSDBG_PROC
@@ -68,7 +68,7 @@ struct nfs4_opendata;static int _nfs4_proc_open (struct nfs4_opendata *data);static int nfs4_do_fsinfo (struct nfs_server *,struct nfs_fh *,struct nfs_fsinfo *);static int nfs4_async_handle_error (struct rpc_task *,const struct nfs_server *); -static int nfs4_handle_exception (const struct nfs_server *server,int errorcode,struct nfs4_exception *exception); +static int nfs4_handle_exception (struct nfs_server *server,int errorcode,struct nfs4_exception *exception);static int nfs4_wait_clnt_recover (struct rpc_clnt *clnt,struct nfs_client *clp);static int _nfs4_proc_lookup (struct inode *dir,const struct qstr *name,struct nfs_fh *fhandle,struct nfs_fattr *fattr);static int _nfs4_proc_getattr (struct nfs_server *server,struct nfs_fh *fhandle,struct nfs_fattr *fattr);
@@ -3280,7 +3280,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)/* This is the error handling routine for processes that are allowed * to sleep. */ -static int nfs4_handle_exception (const struct nfs_server *server,int errorcode,struct nfs4_exception *exception) +static int nfs4_handle_exception (struct nfs_server *server,int errorcode,struct nfs4_exception *exception) {struct nfs_client *clp = server->nfs_client;int ret = errorcode;
@@ -4420,6 +4420,8 @@ struct nfs4_session *nfs4_alloc_session(void)if (!session)return NULL ; +nfs41_set_session_alloc (session); +atomic_set (&session->ref_count,1 );nfs4_init_channel (&session->fore_channel);
@@ -4538,6 +4540,8 @@ static int _nfs4_proc_create_session(struct nfs4_session *session) &session->fore_channel.chan_attrs);nfs4_adjust_channel_attrs (&args.bc_attrs, &session->back_channel.chan_attrs); +nfs41_set_session_valid (session);/* Activate session */ +/* Increment the clientid slot sequence id */ clp->cl_seqid++; }
@@ -4603,6 +4607,10 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)dprintk ("--> nfs4_proc_destroy_session\n" ); +/* session is still being created */ +if (nfs41_test_session_alloc (session)) +return status; + msg.rpc_proc =nfs4_proc (session->clp,NFSPROC4_CLNT_DESTROY_SESSION ); msg.rpc_argp = session; msg.rpc_resp =NULL ;
@@ -4641,6 +4649,9 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) server = list_entry(clp->cl_superblocks.next, struct nfs_server, client_link); +if (nfs41_test_session_alloc (clp->cl_session)) +return -NFS4ERR_STALE_CLIENTID ; + args.sa_cache_this =0 ; status =_nfs4_call_sync (server, &msg, &args, &res,0 );
include/linux/nfs41_session_recovery.h new file +40 -0
@@ -0,0 +1,40 @@ +/* +* Session Recovery header file +* +* Author: Rahul Iyer <[email protected]> +* +* This code is released under GPL. For details see Documentation/COPYING +*/ + +#ifndef __NFS41_SESSION_RECOVERY_H__ +#define __NFS41_SESSION_RECOVERY_H__ + +#if defined(CONFIG_NFS_V4_1 ) + +/* +* Session state bits +*/ +enum nfs41_session_state { +NFS41_SESSION_ALLOC =0 , +NFS41_SESSION_RECOVER , +}; + +/* +* Set the session state to alloc +*/ +static inline int nfs41_set_session_alloc (struct nfs4_session *session) +{ +return test_and_set_bit (NFS41_SESSION_ALLOC , &session->session_state); +} + +static inline int nfs41_test_session_alloc (struct nfs4_session *session) +{ +return test_bit (NFS41_SESSION_ALLOC , &session->session_state); +} + +int nfs41_set_session_valid (struct nfs4_session *); +int nfs41_recover_session (struct nfs4_session *); +int nfs41_recover_session_sync (struct nfs4_session *); + +#endif /* CONFIG_NFS_V4_1 */ +#endif /* __NFS41_SESSION_RECOVERY_H__ */
Signature · 1 line
1.6.0.2
RFC 40/85 nfs41: schedule async session reset
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
Define a new session reset state which is set upon a sequence operation error in both the sync and async error handlers.
Place all new requests and all but the last outstanding rpc on the slot_tbl_waitq. Spawn the recovery thread when the last slot is free. Call nfs4_proc_destroy_session, reinitialize the session, call nfs4_proc_create_session, clear the session reset state, and wake up the next task on the slot_tbl_waitq.
Return the nfs4_proc_destroy_session status to the session reclaimer and check for NFS4ERR_BADSESSION and NFS4ERR_DEADSESSION. Other destroy session errors should be handled in nfs4_proc_destroy_session where the call can be retried with adjusted arguments.
--- fs/nfs/nfs41_session_recovery.c | 51 +++++++++++++++++++++-- fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4proc.c | 69 +++++++++++++++++++++++++++++-- include/linux/nfs41_session_recovery.h | 30 ++++++++++++++ 4 files changed, 141 insertions(+), 11 deletions(-)
fs/nfs/nfs41_session_recovery.c +46 -5
@@ -48,6 +48,17 @@ static int nfs41_start_session_recovery(struct nfs4_session *session)return ret; } +/* +* Session reset +*/ + +int nfs41_wait_session_reset (struct nfs4_session *session) +{ +might_sleep (); +return wait_on_bit (&session->session_state,NFS41_SESSION_RESET , + nfs4_wait_bit_killable,TASK_KILLABLE ); +} +struct reclaimer_arg {struct nfs4_session *session; };
@@ -74,17 +85,49 @@ static int nfs41_wait_session_recover_sync(struct nfs4_session *session)static int session_reclaimer (void *arg) { -int ret; +int ret, reset;struct reclaimer_arg *rec = (struct reclaimer_arg *)arg; -dprintk ("--> %s\n" , __func__); +dprintk ("--> %s session %p\n" , __func__, rec->session);allow_signal (SIGKILL ); - ret =nfs4_proc_create_session (rec->session); + reset =nfs41_test_session_reset (rec->session); +if (reset) { +dprintk ("%s Session Reset\n" , __func__); +/* Reset is called only when all slots are clear. +* +* Bail on the reset if destroy session op fails or if +* the session ref_count is not 1 +* +* Of course since we are resetting the session, +* it's OK if the session is already destroyed +* on the server. +*/ + ret =nfs4_proc_destroy_session (rec->session); +switch (ret) { +case 0 : +case -NFS4ERR_BADSESSION : +case -NFS4ERR_DEADSESSION : +break ; +default : + goto out_error; + } +memset (rec->session->sess_id,0 ,sizeof (nfs41_sessionid)); + } + ret =nfs4_proc_create_session (rec->session, reset);if (ret) goto out_error; out: +if (reset) { +struct nfs4_slot_table *tbl; + + tbl = &rec->session->fore_channel.slot_table; +/* Need to clear reset bit and wake up the next rpc task +* even on error */ +nfs41_clear_session_reset (rec->session); +rpc_wake_up_next (&tbl->slot_tbl_waitq); + }nfs41_end_session_recovery (rec->session);kfree (rec);module_put_and_exit (0 );
@@ -96,8 +139,6 @@ out_error:switch (ret) {case -NFS4ERR_STALE_CLIENTID : -case -NFS4ERR_STALE_STATEID : -case -NFS4ERR_EXPIRED :set_bit (NFS4CLNT_LEASE_EXPIRED , &rec->session->clp->cl_state);break ; }
fs/nfs/nfs4_fs.h +1 -1
@@ -196,7 +196,7 @@ extern int nfs4_setup_sequence(struct nfs_client *clp,extern void nfs4_put_session (struct nfs4_session **session);extern void nfs4_get_session (struct nfs_client *clp);extern struct nfs4_session *nfs4_alloc_session (void ); -extern int nfs4_proc_create_session (struct nfs4_session *); +extern int nfs4_proc_create_session (struct nfs4_session *,int reset);extern int nfs4_proc_destroy_session (struct nfs4_session *);#else /* CONFIG_NFS_v4_1 */ static inline int nfs4_setup_sequence(struct nfs_client *clp,
fs/nfs/nfs4proc.c +64 -5
117 lines not on this page · raw message
include/linux/nfs41_session_recovery.h +30 -0
@@ -13,10 +13,17 @@/* * Session state bits +* +* State machine. +* NFS41_SESSION_ALLOC bit set: session is ready for create_session call. +* NFS41_SESSION_RECOVER bit set: session is being reset/recovered +* NFS41_SESSION_ALLOC bit unset: valid session in use. +* NFS41_SESSION_RESET bit set: session is being reset. */ enum nfs41_session_state {NFS41_SESSION_ALLOC =0 ,NFS41_SESSION_RECOVER , +NFS41_SESSION_RESET , };/*
@@ -32,6 +39,29 @@ static inline int nfs41_test_session_alloc(struct nfs4_session *session)return test_bit (NFS41_SESSION_ALLOC , &session->session_state); } +/* +* Set, test, and clear the session reset state +*/ +static inline int nfs41_set_session_reset (struct nfs4_session *session) +{ +return test_and_set_bit (NFS41_SESSION_RESET , &session->session_state); +} + +static inline int nfs41_test_session_reset (struct nfs4_session *session) +{ +return test_bit (NFS41_SESSION_RESET , &session->session_state); +} + +static inline void nfs41_clear_session_reset (struct nfs4_session *session) +{ +smp_mb__before_clear_bit (); +clear_bit (NFS41_SESSION_RESET , + &session->session_state); +smp_mb__after_clear_bit (); +wake_up_bit (&session->session_state,NFS41_SESSION_RESET ); +} + +int nfs41_wait_session_reset (struct nfs4_session *session);int nfs41_set_session_valid (struct nfs4_session *);int nfs41_recover_session (struct nfs4_session *);int nfs41_recover_session_sync (struct nfs4_session *);
Signature · 1 line
1.6.0.2
RFC 41/85 nfs41: lease renewal
In reply to Benny HalevySend a NFSv4.1 SEQUENCE op rather than RENEW that was deprecated in minorversion 1.
Use the nfs_client minorversion to select reboot_recover/ network_partition_recovery/state_renewal ops.
Note: we use reclaimer to create the nfs41 session before there are any cl_superblocks for the nfs_client.
--- fs/nfs/nfs4_fs.h | 11 +++++++- fs/nfs/nfs4proc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++- fs/nfs/nfs4renewd.c | 5 ++- fs/nfs/nfs4state.c | 21 +++++++++-------- 4 files changed, 81 insertions(+), 16 deletions(-)
fs/nfs/nfs4_fs.h +9 -2
@@ -162,6 +162,11 @@ struct nfs4_exception {struct nfs4_state_recovery_ops {int (*recover_open)(struct nfs4_state_owner *,struct nfs4_state *);int (*recover_lock)(struct nfs4_state *,struct file_lock *); +int (*renew_lease)(struct nfs_client *,struct rpc_cred *); +}; + +struct nfs4_state_maintenance_ops { +int (*sched_state_renewal)(struct nfs_client *,struct rpc_cred *); };extern struct dentry_operations nfs4_dentry_operations;
@@ -187,8 +192,8 @@ extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhextern int nfs4_proc_fs_locations (struct inode *dir,const struct qstr *name,struct nfs4_fs_locations *fs_locations,struct page *page); -extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; -extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; +extern struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[]; +extern struct nfs4_state_recovery_ops *nfs4_network_partition_recovery_ops[];#if defined(CONFIG_NFS_V4_1 ) extern int nfs4_setup_sequence(struct nfs_client *clp, struct nfs41_sequence_args *args, struct nfs41_sequence_res *res,
@@ -207,6 +212,8 @@ static inline int nfs4_setup_sequence(struct nfs_client *clp, }#endif /* CONFIG_NFS_V4_1 */ +extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[]; +extern const u32 nfs4_fattr_bitmap[2 ];extern const u32 nfs4_statfs_bitmap[2 ];extern const u32 nfs4_pathconf_bitmap[2 ];
fs/nfs/nfs4proc.c +58 -2
78 lines not on this page · raw message
fs/nfs/nfs4renewd.c +3 -2
@@ -59,12 +59,14 @@void nfs4_renew_state (struct work_struct *work) { +struct nfs4_state_maintenance_ops *ops;struct nfs_client *clp = container_of(work, struct nfs_client, cl_renewd.work);struct rpc_cred *cred;long lease, timeout;unsigned long last, now; + ops = nfs4_state_renewal_ops[clp->cl_minorversion];down_read (&clp->cl_sem);dprintk ("%s: start\n" , __func__);/* Are there any active superblocks? */
@@ -86,8 +88,7 @@ nfs4_renew_state(struct work_struct *work) }spin_unlock (&clp->cl_lock);/* Queue an asynchronous RENEW. */ -nfs4_proc_async_renew (clp, cred); -put_rpccred (cred); + ops->sched_state_renewal (clp, cred); timeout = (2 * lease) /3 ;spin_lock (&clp->cl_lock); }else
fs/nfs/nfs4state.c +11 -10
@@ -952,24 +952,24 @@ static int reclaimer(void *ptr)/* Ensure exclusive access to NFSv4 state */ down_write (&clp->cl_sem);/* Are there any NFS mounts out there? */ -if (list_empty (&clp->cl_superblocks)) +if (clp->cl_minorversion ==0 &&list_empty (&clp->cl_superblocks)) goto out; restart_loop:dprintk ("%s: starting loop\n" , __func__); - ops = &nfs4_network_partition_recovery_ops; + ops = nfs4_network_partition_recovery_ops[clp->cl_minorversion];/* Are there any open files on this volume? */ cred =nfs4_get_renew_cred (clp);if (cred !=NULL ) {/* Yes there are: try to renew the old lease */ - status =nfs4_proc_renew (clp, cred); + status = ops->renew_lease (clp, cred);put_rpccred (cred);switch (status) { -case 0 : -case -NFS4ERR_CB_PATH_DOWN : - goto out; -case -NFS4ERR_STALE_CLIENTID : -case -NFS4ERR_LEASE_MOVED : - ops = &nfs4_reboot_recovery_ops; +case 0 : +case -NFS4ERR_CB_PATH_DOWN : + goto out; +case -NFS4ERR_STALE_CLIENTID : +case -NFS4ERR_LEASE_MOVED : + ops = nfs4_reboot_recovery_ops[clp->cl_minorversion]; } }else {/* "reboot" to ensure we clear all state on the server */
@@ -998,7 +998,8 @@ restart_loop: status =nfs4_reclaim_open_state (ops, sp);if (status <0 ) {if (status == -NFS4ERR_NO_GRACE ) { - ops = &nfs4_network_partition_recovery_ops; + ops = nfs4_network_partition_recovery_ops[ + clp->cl_minorversion]; status =nfs4_reclaim_open_state (ops, sp); }if (status == -NFS4ERR_STALE_CLIENTID )
Signature · 1 line
1.6.0.2
RFC 42/85 nfs41: sunrpc: Export the call prepare state for session reset
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
--- include/linux/sunrpc/clnt.h | 1 + include/linux/sunrpc/sched.h | 1 + net/sunrpc/clnt.c | 13 +++++++++++++ net/sunrpc/sched.c | 2 +- 4 files changed, 16 insertions(+), 1 deletions(-)
include/linux/sunrpc/clnt.h +1 -0
@@ -151,6 +151,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags);struct rpc_task *rpc_call_null (struct rpc_clnt *clnt,struct rpc_cred *cred,int flags); +void rpc_restart_call_prepare (struct rpc_task *);void rpc_restart_call (struct rpc_task *);void rpc_setbufsize (struct rpc_clnt *,unsigned int ,unsigned int );size_t rpc_max_payload (struct rpc_clnt *);
include/linux/sunrpc/sched.h +1 -0
@@ -237,6 +237,7 @@ void rpc_show_tasks(void);int rpc_init_mempool (void );void rpc_destroy_mempool (void );extern struct workqueue_struct *rpciod_workqueue; +void rpc_prepare_task (struct rpc_task *task);static inline void rpc_exit (struct rpc_task *task,int status) {
net/sunrpc/clnt.c +13 -0
@@ -684,6 +684,19 @@ void rpc_force_rebind(struct rpc_clnt *clnt)EXPORT_SYMBOL_GPL (rpc_force_rebind);/* +* Restart an (async) RPC call from the call_prepare state. +* Usually called from within the exit handler. +*/ +void +rpc_restart_call_prepare (struct rpc_task *task) +{ +if (RPC_ASSASSINATED (task)) +return ; + task->tk_action = rpc_prepare_task; +} +EXPORT_SYMBOL_GPL (rpc_restart_call_prepare); + +/* * Restart an (async) RPC call. Usually called from within the * exit handler. */
net/sunrpc/sched.c +1 -1
@@ -574,7 +574,7 @@ EXPORT_SYMBOL_GPL(rpc_delay);/* * Helper to call task->tk_ops->rpc_call_prepare */ -static void rpc_prepare_task (struct rpc_task *task) +void rpc_prepare_task (struct rpc_task *task) { task->tk_ops->rpc_call_prepare (task, task->tk_calldata); }
Signature · 1 line
1.6.0.2
RFC 43/85 nfs41: use rpc prepare call state for session reset
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
--- fs/nfs/internal.h | 4 ++++ fs/nfs/nfs4proc.c | 22 +++++++++++++++++----- fs/nfs/read.c | 2 +- fs/nfs/unlink.c | 2 +- fs/nfs/write.c | 2 +- 5 files changed, 24 insertions(+), 8 deletions(-)
fs/nfs/internal.h +4 -0
@@ -130,6 +130,10 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);extern struct rpc_procinfo nfs3_procedures[];extern __be32 *nfs3_decode_dirent (__be32 *,struct nfs_entry *,int ); +/* nfs4proc.c */ +extern void nfs4_restart_rpc (struct rpc_task *task, +const struct nfs_server *server); +/* nfs4xdr.c */ #ifdef CONFIG_NFS_V4 extern __be32 *nfs4_decode_dirent (__be32 *p,struct nfs_entry *entry,int plus);
fs/nfs/nfs4proc.c +17 -5
@@ -593,6 +593,18 @@ static void nfs4_sequence_done(const struct nfs_server *server,#endif /* CONFIG_NFS_V4_1 */ } +void nfs4_restart_rpc (struct rpc_task *task,const struct nfs_server *server) +{ +#ifdef CONFIG_NFS_V4_1 +if (server->nfs_client->cl_minorversion && +nfs41_test_session_reset (server->nfs_client->cl_session)) { +rpc_restart_call_prepare (task); +return ; + } +#endif /* CONFIG_NFS_V4_1 */ +rpc_restart_call (task); +} +static void update_changeattr (struct inode *dir,struct nfs4_change_info *cinfo) {struct nfs_inode *nfsi =NFS_I (dir);
@@ -1638,7 +1650,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)break ;default :if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);return ; } }
@@ -2871,7 +2883,7 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)/* nfs4_sequence_free_slot called in the read rpc_call_done */ nfs4_sequence_done (server, &data->res.seq_res, task->tk_status);if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);dprintk ("<-- %s status= %d\n" , __func__, -EAGAIN );return -EAGAIN ; }
@@ -2899,7 +2911,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)/* slot is freed in nfs_writeback_done */ nfs4_sequence_done (server, &data->res.seq_res, task->tk_status);if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);return -EAGAIN ; }if (task->tk_status >=0 ) {
@@ -2927,7 +2939,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)nfs4_sequence_done (server, &data->res.seq_res, task->tk_status);if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);return -EAGAIN ; }nfs4_sequence_free_slot (server, &data->res.seq_res);
@@ -3701,7 +3713,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)break ;default :if (nfs4_async_handle_error (task, server) == -EAGAIN ) -rpc_restart_call (task); +nfs4_restart_rpc (task, server); }nfs4_sequence_free_slot (server, &calldata->res.seq_res); }
fs/nfs/read.c +1 -1
@@ -367,7 +367,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data argp->offset += resp->count; argp->pgbase += resp->count; argp->count -= resp->count; -rpc_restart_call (task); +nfs4_restart_rpc (task,NFS_SERVER (data->inode));return ; out:nfs4_sequence_free_slot (NFS_SERVER (data->inode), &data->res.seq_res);
fs/nfs/unlink.c +1 -1
@@ -83,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)struct inode *dir = data->dir;if (!NFS_PROTO (dir)->unlink_done (task, dir)) -rpc_restart_call (task); +nfs4_restart_rpc (task,NFS_SERVER (dir)); }/**
fs/nfs/write.c +1 -1
@@ -1179,7 +1179,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)*/ argp->stable =NFS_FILE_SYNC ; } -rpc_restart_call (task); +nfs4_restart_rpc (task,NFS_SERVER (data->inode));return -EAGAIN ; }if (time_before (complain, jiffies)) {
Signature · 1 line
1.6.0.2
RFC 44/85 nfs41: kick start nfs41 session recovery when handling errors
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
--- fs/nfs/nfs4proc.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 71 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +71 -0
@@ -3256,6 +3256,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)rpc_wake_up_queued_task (&clp->cl_rpcwaitq, task); task->tk_status =0 ;return -EAGAIN ; +#if defined(CONFIG_NFS_V4_1 ) +case -NFS4ERR_BADSESSION : +case -NFS4ERR_BADSLOT : +case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION : +case -NFS4ERR_BACK_CHAN_BUSY : +case -NFS4ERR_SEQ_MISORDERED : +case -NFS4ERR_SEQUENCE_POS : +case -NFS4ERR_REQ_TOO_BIG : +case -NFS4ERR_REP_TOO_BIG : +case -NFS4ERR_REP_TOO_BIG_TO_CACHE : +case -NFS4ERR_RETRY_UNCACHED_REP : +case -NFS4ERR_TOO_MANY_OPS : +case -NFS4ERR_OP_NOT_IN_SESSION : +dprintk ("%s ERROR %d, Reset session\n" , __func__, + task->tk_status); +nfs41_set_session_reset (clp->cl_session); + task->tk_status =0 ; +return -EAGAIN ; +#endif /* CONFIG_NFS_V4_1 */ case -NFS4ERR_DELAY :nfs_inc_server_stats (server,NFSIOS_DELAY );case -NFS4ERR_GRACE :
@@ -3331,7 +3350,30 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc ret =nfs4_wait_clnt_recover (server->client, clp);if (ret ==0 ) exception->retry =1 ; +#if !defined(CONFIG_NFS_V4_1 )break ; +#else /* !defined(CONFIG_NFS_V4_1) */ +if (!server->nfs_client->cl_minorversion) +break ; +/* FALLTHROUGH */ +case -NFS4ERR_BADSESSION : +case -NFS4ERR_BADSLOT : +case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION : +case -NFS4ERR_BACK_CHAN_BUSY : +case -NFS4ERR_SEQ_MISORDERED : +case -NFS4ERR_SEQUENCE_POS : +case -NFS4ERR_REQ_TOO_BIG : +case -NFS4ERR_REP_TOO_BIG : +case -NFS4ERR_REP_TOO_BIG_TO_CACHE : +case -NFS4ERR_RETRY_UNCACHED_REP : +case -NFS4ERR_TOO_MANY_OPS : +case -NFS4ERR_OP_NOT_IN_SESSION : +dprintk ("%s ERROR: %d Reset session\n" , __func__, + errorcode); +nfs41_set_session_reset (clp->cl_session); + exception->retry =1 ; +/* FALLTHROUGH */ +#endif /* !defined(CONFIG_NFS_V4_1) */ case -NFS4ERR_FILE_OPEN :case -NFS4ERR_GRACE :case -NFS4ERR_DELAY :
@@ -4735,8 +4777,37 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)void nfs41_sequence_call_done (struct rpc_task *task,void *data) {struct nfs_server *server = (struct nfs_server *)data; +struct nfs_client *clp = server->nfs_client;nfs4_sequence_done (server, task->tk_msg.rpc_resp, task->tk_status); + +if (task->tk_status <0 ) { +switch (task->tk_status) { +case -NFS4ERR_STALE_CLIENTID : +case -NFS4ERR_EXPIRED : +case -NFS4ERR_CB_PATH_DOWN : +nfs4_schedule_state_recovery (clp); +case -NFS4ERR_BADSLOT : +case -NFS4ERR_BADSESSION : +case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION : +case -NFS4ERR_BACK_CHAN_BUSY : +case -NFS4ERR_SEQ_MISORDERED : +case -NFS4ERR_SEQUENCE_POS : +case -NFS4ERR_REQ_TOO_BIG : +case -NFS4ERR_REP_TOO_BIG : +case -NFS4ERR_REP_TOO_BIG_TO_CACHE : +case -NFS4ERR_RETRY_UNCACHED_REP : +case -NFS4ERR_TOO_MANY_OPS : +case -NFS4ERR_OP_NOT_IN_SESSION : +dprintk ("%s ERROR %d Reset session\n" , __func__, + task->tk_status); + +if (nfs4_async_handle_error (task, server) == -EAGAIN ) { +nfs4_restart_rpc (task, server); +return ; + } + } + }nfs4_sequence_free_slot (server, task->tk_msg.rpc_resp);dprintk ("%s rpc_cred %p\n" , __func__, task->tk_msg.rpc_cred);
Signature · 1 line
1.6.0.2
RFC 45/85 nfs41: start session recovery from nfs4_setup_sequence
In reply to Benny Halevy--- fs/nfs/nfs4proc.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
fs/nfs/nfs4proc.c +5 -2
@@ -491,8 +491,11 @@ int nfs4_setup_sequence(struct nfs_client *clp,if (clp->cl_minorversion ==0 || res->sr_slot) goto out;BUG_ON (clp->cl_minorversion !=1 ); - ret =nfs41_setup_sequence (clp->cl_session, args, res, - cache_reply, task); +if (nfs41_test_session_alloc (clp->cl_session)) + ret =nfs41_recover_session_sync (clp->cl_session); +if (!ret) + ret =nfs41_setup_sequence (clp->cl_session, args, res, + cache_reply, task);if (ret) {memset (res,0 ,sizeof (*res));if (ret != -EAGAIN ) {
Signature · 1 line
1.6.0.2
RFC 46/85 nfs41: introduce get_state_renewal_cred
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
Reuse the cred used at exchange_id time for
sending SEQUENCE to renew the client's lease.
--- fs/nfs/client.c | 4 ++++ fs/nfs/nfs4_fs.h | 4 ++++ fs/nfs/nfs4proc.c | 13 +++++++++++++ fs/nfs/nfs4renewd.c | 2 +- fs/nfs/nfs4state.c | 14 +++++++++++++- include/linux/nfs_fs_sb.h | 1 + 6 files changed, 36 insertions(+), 2 deletions(-)
fs/nfs/client.c +4 -0
@@ -207,6 +207,10 @@ static void nfs_free_client(struct nfs_client *clp)if (clp->cl_machine_cred !=NULL )put_rpccred (clp->cl_machine_cred); +#ifdef CONFIG_NFS_V4_1 +if (clp->cl_ex_cred !=NULL ) +put_rpccred (clp->cl_ex_cred); +#endif /* CONFIG_NFS_V4_1 */ kfree (clp->cl_hostname);kfree (clp);
fs/nfs/nfs4_fs.h +4 -0
@@ -167,6 +167,7 @@ struct nfs4_state_recovery_ops {struct nfs4_state_maintenance_ops {int (*sched_state_renewal)(struct nfs_client *,struct rpc_cred *); +struct rpc_cred * (*get_state_renewal_cred)(struct nfs_client *); };extern struct dentry_operations nfs4_dentry_operations;
@@ -228,6 +229,9 @@ extern void nfs4_renew_state(struct work_struct *);/* nfs4state.c */ struct rpc_cred *nfs4_get_renew_cred (struct nfs_client *clp); +#ifdef CONFIG_NFS_V4_1 +struct rpc_cred *nfs41_get_state_renewal_cred (struct nfs_client *clp); +#endif /* CONFIG_NFS_V4_1 */ extern struct nfs4_state_owner *nfs4_get_state_owner (struct nfs_server *,struct rpc_cred *);extern void nfs4_put_state_owner (struct nfs4_state_owner *);
fs/nfs/nfs4proc.c +13 -0
@@ -4317,6 +4317,17 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)else if (++clp->cl_id_uniquifier ==0 )break ; } +if (status ==0 ) { +if (clp->cl_ex_cred) { +dprintk ("%s put cl_ex_cred %p\n" , __func__, + clp->cl_ex_cred); +put_rpccred (clp->cl_ex_cred); + } + +BUG_ON (cred ==NULL ); + clp->cl_ex_cred =get_rpccred (cred); +dprintk ("%s set cl_ex_cred %p\n" , __func__, clp->cl_ex_cred); + }dprintk ("<-- %s status= %d\n" , __func__, status);return status;
@@ -4907,11 +4918,13 @@ struct nfs4_state_recovery_ops nfs41_network_partition_recovery_ops = {struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = { .sched_state_renewal = nfs4_proc_async_renew, + .get_state_renewal_cred = nfs4_get_renew_cred, };#if defined(CONFIG_NFS_V4_1 )struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { .sched_state_renewal = nfs41_proc_async_sequence, + .get_state_renewal_cred = nfs41_get_state_renewal_cred, };#endif
fs/nfs/nfs4renewd.c +1 -1
@@ -79,7 +79,7 @@ nfs4_renew_state(struct work_struct *work) timeout = (2 * lease) /3 + (long )last - (long )now;/* Are we close to a lease timeout? */ if (time_after (now, last + lease/3 )) { - cred =nfs4_get_renew_cred (clp); + cred = ops->get_state_renewal_cred (clp);if (cred ==NULL ) {set_bit (NFS4CLNT_LEASE_EXPIRED , &clp->cl_state);spin_unlock (&clp->cl_lock);
fs/nfs/nfs4state.c +13 -1
@@ -73,6 +73,16 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)return status; } +#if defined(CONFIG_NFS_V4_1 ) +struct rpc_cred * +nfs41_get_state_renewal_cred (struct nfs_client *clp) +{ +if (clp->cl_ex_cred) +get_rpccred (clp->cl_ex_cred); +return (clp->cl_ex_cred); +} +#endif /* CONFIG_NFS_V4_1 */ +static struct rpc_cred *nfs4_get_machine_cred (struct nfs_client *clp) {struct rpc_cred *cred =NULL ;
@@ -943,6 +953,7 @@ static int reclaimer(void *ptr)struct nfs4_state_owner *sp;struct rb_node *pos;struct nfs4_state_recovery_ops *ops; +struct nfs4_state_maintenance_ops *m_ops;struct rpc_cred *cred;int status =0 ;
@@ -957,8 +968,9 @@ static int reclaimer(void *ptr) restart_loop:dprintk ("%s: starting loop\n" , __func__); ops = nfs4_network_partition_recovery_ops[clp->cl_minorversion]; + m_ops = nfs4_state_renewal_ops[clp->cl_minorversion];/* Are there any open files on this volume? */ - cred =nfs4_get_renew_cred (clp); + cred = m_ops->get_state_renewal_cred (clp);if (cred !=NULL ) {/* Yes there are: try to renew the old lease */ status = ops->renew_lease (clp, cred);
include/linux/nfs_fs_sb.h +1 -0
@@ -81,6 +81,7 @@ struct nfs_client {u32 cl_seqid;/* The flags used for obtaining the clientid during EXCHANGE_ID */ u32 cl_exchange_flags; +struct rpc_cred *cl_ex_cred;/* exchange_id credential */ struct nfs4_session *cl_session;/* sharred session */ #endif /* CONFIG_NFS_V4_1 */ };
Signature · 1 line
1.6.0.2
RFC 47/85 nfs41: get cred in exchange_id when cred arg is NULL
In reply to Benny HalevyWhen creating a session to a pnfs data server, the cred is passed down as NULL. Either use the saved cl_ex_cred or get a new one using nfs4_get_setclientid_cred.
--- fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4proc.c | 18 +++++++++++++++--- fs/nfs/nfs4state.c | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-)
fs/nfs/nfs4_fs.h +1 -0
@@ -229,6 +229,7 @@ extern void nfs4_renew_state(struct work_struct *);/* nfs4state.c */ struct rpc_cred *nfs4_get_renew_cred (struct nfs_client *clp); +struct rpc_cred *nfs4_get_setclientid_cred (struct nfs_client *clp);#ifdef CONFIG_NFS_V4_1 struct rpc_cred *nfs41_get_state_renewal_cred (struct nfs_client *clp);#endif /* CONFIG_NFS_V4_1 */
fs/nfs/nfs4proc.c +15 -3
@@ -4276,6 +4276,7 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) };int status;int loop =0 ; +int got_cred =0 ;struct rpc_message msg = { .rpc_proc =nfs4_proc (clp,NFSPROC4_CLNT_EXCHANGE_ID ), .rpc_argp = &args,
@@ -4286,6 +4287,16 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)dprintk ("--> %s\n" , __func__);BUG_ON (clp ==NULL ); + +if (!cred) { +/* FIXME: do we need to lock clp and take a ref count on cl_ex_cred? */ + cred = clp->cl_ex_cred; +if (!cred) { + cred =nfs4_get_setclientid_cred (clp); + got_cred = (cred !=NULL ); + } + } + p = (u32 *)verifier.data; *p++ =htonl ((u32 )clp->cl_boot_time.tv_sec); *p =htonl ((u32 )clp->cl_boot_time.tv_nsec);
@@ -4317,17 +4328,18 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)else if (++clp->cl_id_uniquifier ==0 )break ; } -if (status ==0 ) { +if ((status ==0 ) && (cred != clp->cl_ex_cred) && (cred !=NULL )) { +/* FIXME: do we need to lock clp here? */ if (clp->cl_ex_cred) {dprintk ("%s put cl_ex_cred %p\n" , __func__, clp->cl_ex_cred);put_rpccred (clp->cl_ex_cred); } - -BUG_ON (cred ==NULL ); clp->cl_ex_cred =get_rpccred (cred);dprintk ("%s set cl_ex_cred %p\n" , __func__, clp->cl_ex_cred); } +if (got_cred) +put_rpccred (cred);dprintk ("<-- %s status= %d\n" , __func__, status);return status;
fs/nfs/nfs4state.c +1 -1
@@ -122,7 +122,7 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)return cred; } -static struct rpc_cred *nfs4_get_setclientid_cred (struct nfs_client *clp) +struct rpc_cred *nfs4_get_setclientid_cred (struct nfs_client *clp) {struct nfs4_state_owner *sp;struct rb_node *pos;
Signature · 1 line
1.6.0.2
RFC 48/85 nfs41: establish sessions-based clientid
In reply to Benny Halevynfsv4.1 clientid is established via EXCHANGE_ID rather than SETCLIENTID{,_CONFIRM}
This is implemented using a new establish_clid method in nfs4_state_recovery_ops.
nfs41: establish clientid via exchange id only if cred != NULL
Quoted 1 line
From 2.6.26
reclaimer()uses machine cred for setting up the client id
therefore it is never expected to be NULL.
--- fs/nfs/nfs4_fs.h | 2 ++ fs/nfs/nfs4proc.c | 4 ++++ fs/nfs/nfs4state.c | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-)
fs/nfs/nfs4_fs.h +2 -0
@@ -163,6 +163,7 @@ struct nfs4_state_recovery_ops {int (*recover_open)(struct nfs4_state_owner *,struct nfs4_state *);int (*recover_lock)(struct nfs4_state *,struct file_lock *);int (*renew_lease)(struct nfs_client *,struct rpc_cred *); +int (*establish_clid)(struct nfs_client *,struct rpc_cred *); };struct nfs4_state_maintenance_ops {
@@ -186,6 +187,7 @@ extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *)extern int nfs4_proc_async_renew (struct nfs_client *,struct rpc_cred *);extern int nfs4_proc_renew (struct nfs_client *,struct rpc_cred *);extern int nfs4_wait_bit_killable (void *); +extern int nfs4_init_clientid (struct nfs_client *,struct rpc_cred *);extern int nfs4_do_close (struct path *path,struct nfs4_state *state,int wait);extern struct dentry *nfs4_atomic_open (struct inode *,struct dentry *,struct nameidata *);extern int nfs4_open_revalidate (struct inode *,struct dentry *,int ,struct nameidata *);
fs/nfs/nfs4proc.c +4 -0
@@ -4904,6 +4904,7 @@ struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { .recover_open = nfs4_open_reclaim, .recover_lock = nfs4_lock_reclaim, .renew_lease = nfs4_proc_renew, + .establish_clid = nfs4_init_clientid, };#if defined(CONFIG_NFS_V4_1 )
@@ -4911,6 +4912,7 @@ struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { .recover_open = nfs4_open_reclaim, .recover_lock = nfs4_lock_reclaim, .renew_lease = nfs4_proc_sequence, + .establish_clid = nfs4_proc_exchange_id, };#endif /* CONFIG_NFS_V4_1 */
@@ -4918,6 +4920,7 @@ struct nfs4_state_recovery_ops nfs40_network_partition_recovery_ops = { .recover_open = nfs4_open_expired, .recover_lock = nfs4_lock_expired, .renew_lease = nfs4_proc_renew, + .establish_clid = nfs4_init_clientid, };#if defined(CONFIG_NFS_V4_1 )
@@ -4925,6 +4928,7 @@ struct nfs4_state_recovery_ops nfs41_network_partition_recovery_ops = { .recover_open = nfs4_open_expired, .recover_lock = nfs4_lock_expired, .renew_lease = nfs4_proc_sequence, + .establish_clid = nfs4_proc_exchange_id, };#endif /* CONFIG_NFS_V4_1 */
fs/nfs/nfs4state.c +3 -2
@@ -62,7 +62,7 @@ const nfs4_stateid zero_stateid;static LIST_HEAD (nfs4_clientid_list); -static int nfs4_init_client (struct nfs_client *clp,struct rpc_cred *cred) +int nfs4_init_clientid (struct nfs_client *clp,struct rpc_cred *cred) {int status =nfs4_proc_setclientid (clp,NFS4_CALLBACK , nfs_callback_tcpport, cred);
@@ -991,8 +991,9 @@ restart_loop:nfs4_state_mark_reclaim (clp); status = -ENOENT ; cred =nfs4_get_setclientid_cred (clp); +dprintk ("%s: setclientid_cred %p\n" , __func__, cred);if (cred !=NULL ) { - status =nfs4_init_client (clp, cred); + status = ops->establish_clid (clp, cred);put_rpccred (cred);/* Handle case where the user hasn't set up machine creds */ if (status == -EACCES && cred == clp->cl_machine_cred) {
Signature · 1 line
1.6.0.2
RFC 49/85 nfs41: recover lease in _nfs4_lookup_root
In reply to Benny HalevyThis creates the nfsv4.1 session on mount.
--- fs/nfs/nfs4proc.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +4 -0
@@ -1956,7 +1956,11 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,dprintk ("--> %s\n" , __func__);nfs_fattr_init (info->fattr); + status =nfs4_recover_expired_lease (server); +if (status !=0 ) + goto out; status =nfs4_call_sync (server, &msg, &args, &res,0 ); +out:dprintk ("<-- %s status= %d\n" , __func__, status);return status; }
Signature · 1 line
1.6.0.2
RFC 50/85 nfs41: schedule state recovery on BAD or DEAD session
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
When a clientid is stale, the sequence operation will return NFS4ERR_BADSESSION or NFS4ERR_DEADSESSION. This will put the session into reset mode, and run the session_reclaimer thread which calls destroy_session and create_session. Destroy_session will also return NFS4ERR_BADSESSION or NFS4ERR_DEADSESSION which is ignored by the session reset. Create_session will return NFS4ERR_STALE_CLIENTID and the session reclaimer sets the nfs_client cl_state to NFS4CLNT_LEASE_EXPIRED.
Catch the NFS4CLNT_LEASE_EXPIRED cl_state in nfs4_find_slot, and attempt to recover the expired client id.
--- fs/nfs/nfs4proc.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
fs/nfs/nfs4proc.c +7 -0
@@ -403,6 +403,13 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task,dprintk ("%s Slot Table Empty\n" , __func__);spin_unlock (&tbl->slot_tbl_lock); ret =nfs41_recover_session_sync (session); +if (test_and_clear_bit (NFS4CLNT_LEASE_EXPIRED , + &session->clp->cl_state)) { + +printk (KERN_WARNING "%s Clientid Reset\n" , + __func__); +nfs4_schedule_state_recovery (session->clp); + }if (ret)return slot;nfs41_wait_session_reset (session);
Signature · 1 line
1.6.0.2
RFC 51/85 nfs41: state reclaimer renew lease error handling
In reply to Benny HalevyFrom: Andy Adamson <[email protected]>
The state reclaimer has been called due to a NFS4_STALE_CLIENTID or NFS4_EXPIRE error. First it tries to renew the old lease (network partion case) which for v4.1 means an nfs4_proc_sequence call. Any error from the sequence operation means that the lease cannot be renewed.
Switch on the minorversion to handle the error return from the renew lease call.
--- fs/nfs/nfs4state.c | 20 +++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-)
fs/nfs/nfs4state.c +13 -7
@@ -975,18 +975,24 @@ restart_loop:/* Yes there are: try to renew the old lease */ status = ops->renew_lease (clp, cred);put_rpccred (cred); -switch (status) { -case 0 : -case -NFS4ERR_CB_PATH_DOWN : +if (!status) goto out; -case -NFS4ERR_STALE_CLIENTID : -case -NFS4ERR_LEASE_MOVED : - ops = nfs4_reboot_recovery_ops[clp->cl_minorversion]; - } +if (clp->cl_minorversion ==0 ) +switch (status) { +case -NFS4ERR_CB_PATH_DOWN : + goto out; +case -NFS4ERR_STALE_CLIENTID : +case -NFS4ERR_LEASE_MOVED : +break ; +default : + goto establish_clid; + } + ops = nfs4_reboot_recovery_ops[clp->cl_minorversion]; }else {/* "reboot" to ensure we clear all state on the server */ clp->cl_boot_time =CURRENT_TIME ; } +establish_clid:/* We're going to have to re-establish a clientid */ nfs4_state_mark_reclaim (clp); status = -ENOENT ;
Signature · 1 line
1.6.0.2
RFC 52/85 nfs41: increment_{open,lock}_seqid
In reply to Benny HalevyUnlike minorversion0, in nfsv4.1 the open and lock seqids need not be incremented by the client and should always be set to zero.
This is implemented using a new nfs_rpc_ops methods - increment_open_seqid and increment_lock_seqid
--- fs/nfs/nfs4proc.c | 4 ++++ fs/nfs/nfs4state.c | 14 +++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-)
fs/nfs/nfs4proc.c +4 -0
@@ -1757,6 +1757,10 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait) calldata->state = state; calldata->arg.fh =NFS_FH (state->inode); calldata->arg.stateid = &state->open_stateid; +if (server->minorversion) { +BUG_ON (server->minorversion !=1 ); +memset (calldata->arg.stateid->data,0 ,4 );/* clear seqid */ + }/* Serialization for the sequence id */ calldata->arg.seqid =nfs_alloc_seqid (&state->owner->so_seqid);if (calldata->arg.seqid ==NULL )
fs/nfs/nfs4state.c +9 -5
@@ -747,12 +747,16 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)void nfs_increment_open_seqid (int status,struct nfs_seqid *seqid) { -if (status == -NFS4ERR_BAD_SEQID ) { -struct nfs4_state_owner *sp =container_of (seqid->sequence, - struct nfs4_state_owner, so_seqid); +struct nfs4_state_owner *sp =container_of (seqid->sequence, + struct nfs4_state_owner, so_seqid); +struct nfs_server *server = sp->so_server; + +if (status == -NFS4ERR_BAD_SEQID )nfs4_drop_state_owner (sp); - } -nfs_increment_seqid (status, seqid); +if (server->minorversion ==0 ) +nfs_increment_seqid (status, seqid); +else +BUG_ON (server->minorversion !=1 ); }/*
Signature · 1 line
1.6.0.2
RFC 53/85 nfs41: Add ability to read RPC call direction on TCP stream.
In reply to Benny HalevyNFSv4.1 callbacks can arrive over an existing connection. This patch adds the logic to read the RPC call direction (call or reply). It does this by updating the state machine to look for the call direction invoking xs_tcp_read_calldir(...) after reading the XID.
To avoid confusion, keep tcp_calldir in code in host order.
--- net/sunrpc/xprtsock.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 45 insertions(+), 4 deletions(-)
net/sunrpc/xprtsock.c +45 -4
@@ -222,7 +222,8 @@ struct sock_xprt {* State of TCP reply receive */ __be32 tcp_fraghdr, - tcp_xid; + tcp_xid, + tcp_calldir;/* Is this a call or a reply? */ u32 tcp_offset, tcp_reclen;
@@ -259,6 +260,7 @@ struct sock_xprt {#define TCP_RCV_COPY_FRAGHDR (1UL << 1)#define TCP_RCV_COPY_XID (1UL << 2)#define TCP_RCV_COPY_DATA (1UL << 3) +#define TCP_RCV_COPY_CALLDIR (1UL << 4)static inline struct sockaddr *xs_addr (struct rpc_xprt *xprt) {
@@ -919,7 +921,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea transport->tcp_offset =0 ;/* Sanity check of the record length */ -if (unlikely (transport->tcp_reclen <4 )) { +if (unlikely (transport->tcp_reclen <8 )) {dprintk ("RPC: invalid TCP record fragment length\n" );xprt_force_disconnect (xprt);return ;
@@ -954,13 +956,47 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_rif (used != len)return ; transport->tcp_flags &= ~TCP_RCV_COPY_XID ; - transport->tcp_flags |=TCP_RCV_COPY_DATA ; + transport->tcp_flags |=TCP_RCV_COPY_CALLDIR ; transport->tcp_copied =4 ; -dprintk ("RPC: reading reply for XID %08x\n" , +dprintk ("RPC: reading %s XID %08x\n" , + (transport->tcp_calldir ==RPC_REPLY ) ?"reply for" + :"request with" ,ntohl (transport->tcp_xid));xs_tcp_check_fraghdr (transport); } +static inline void xs_tcp_read_calldir (struct sock_xprt *transport, +struct xdr_skb_reader *desc) +{ +size_t len, used; +u32 offset; +char *p; + +/* +* We want transport->tcp_offset to be 8 at the end of this routine +* (4 bytes for the xid and 4 bytes for the call/reply flag). +* When this function is called for the first time, +* transport->tcp_offset is 4 (after having already read the xid). +*/ + offset = transport->tcp_offset -sizeof (transport->tcp_xid); + len =sizeof (transport->tcp_calldir) - offset; +dprintk ("RPC: reading CALL/REPLY flag (%Zu bytes)\n" , len); + p = ((char *) &transport->tcp_calldir) + offset; + used =xdr_skb_read_bits (desc, p, len); + transport->tcp_offset += used; +if (used != len) +return ; + transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR ; + transport->tcp_flags |=TCP_RCV_COPY_DATA ; + transport->tcp_copied +=4 ; + transport->tcp_calldir =ntohl (transport->tcp_calldir); +dprintk ("RPC: reading %s CALL/REPLY flag %08x\n" , + (transport->tcp_calldir ==RPC_REPLY ) ?"reply for" + :"request with" , + transport->tcp_calldir); +xs_tcp_check_fraghdr (transport); +} +static inline void xs_tcp_read_request (struct rpc_xprt *xprt,struct xdr_skb_reader *desc) { struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1077,6 +1113,11 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, unsxs_tcp_read_xid (transport, &desc);continue ; } +/* Read in the call/reply flag */ +if (transport->tcp_flags &TCP_RCV_COPY_CALLDIR ) { +xs_tcp_read_calldir (transport, &desc); +continue ; + }/* Read in the request data */ if (transport->tcp_flags &TCP_RCV_COPY_DATA ) {xs_tcp_read_request (xprt, &desc);
Signature · 1 line
1.6.0.2
RFC 54/85 nfs41: Skip past the RPC call direction
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
xs_tcp_read_calldir() is now responsible for reading the RPC call direction and determining whether it is a reply or a callback request. The call to xdr_skb_read_bits() inside xs_tcp_read_calldir() moves the xdr_skb_reader offset past the RPC call direction (offset should be equal to 8). Therefore xs_tcp_read_common() called from xs_tcp_ready_reply() should be copying the TCP buffer starting past the RPC call direction. It is now necessary to read the RPC call direction earlier to determine whether to call the reply handler or the callback handler.
call_verify() should therefore skip past the XID and call/reply flag.
--- net/sunrpc/clnt.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
net/sunrpc/clnt.c +7 -6
@@ -1371,13 +1371,14 @@ rpc_verify_header(struct rpc_task *task) }if ((len -=3 ) <0 ) goto out_overflow; - p +=1 ;/* skip XID */ -if ((n =ntohl (*p++)) !=RPC_REPLY ) { -dprintk ("RPC: %5u %s: not an RPC reply: %x\n" , - task->tk_pid, __func__, n); - goto out_garbage; - } +/* +* Skip the XID and call direction. +* The underlying transport has read the XID and RPC call direction +* to determine this is an RPC reply. +*/ + p +=2 ; +if ((n =ntohl (*p++)) !=RPC_MSG_ACCEPTED ) {if (--len <0 ) goto out_overflow;
Signature · 1 line
1.6.0.2
RFC 55/85 nfs41: Refactor NFSv4 callback service
In reply to Benny HalevyPrepare the NFSv4 callback service mechanism to understand v4.0 and v4.1 callbacks. Create a new function nfs4_callback_up() that contains the minor version 0 specific logic. It is invoked by nfs_callback_up().
Augment the list of arguments passed to nfs_callback_up() since it will need to deal with minor version 1 as well. Move the creation of the backchannel after the rpc_client has been initialized since the rpc_xprt structure will be needed to crated the NFSv4.1 callback.
Keep a pointer to the callback_svc that will be set as per the minor version used.
--- fs/nfs/callback.c | 62 +++++++++++++++++++++++++++++++++++++--------------- fs/nfs/callback.h | 2 +- fs/nfs/client.c | 23 ++++++++++--------- 3 files changed, 57 insertions(+), 30 deletions(-)
fs/nfs/callback.c +44 -18
@@ -67,7 +67,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,* This is the callback kernel thread. */ static int -nfs_callback_svc (void *vrqstp) +nfs4_callback_svc (void *vrqstp) {int err, preverr =0 ;struct svc_rqst *rqstp = vrqstp;
@@ -104,12 +104,37 @@ nfs_callback_svc(void *vrqstp)return 0 ; } + +/* +* Prepare to bring up the NFSv4 callback service +*/ +struct svc_rqst * +nfs4_callback_up (struct svc_serv *serv) +{ +int ret; + + ret =svc_create_xprt (serv,"tcp" , nfs_callback_set_tcpport, +SVC_SOCK_ANONYMOUS ); +if (unlikely (ret <=0 )) { +if (ret ==0 ) + ret = -EIO ; +return ERR_PTR (ret); + } + nfs_callback_tcpport = ret; +dprintk ("NFS: Callback listener port = %u (af %u)\n" , + nfs_callback_tcpport, nfs_callback_family); +return svc_prepare_thread (serv, &serv->sv_pools[0 ]); +} +/* * Bring up the callback thread if it is not already up. */ -int nfs_callback_up (void ) +int nfs_callback_up (u32 minorversion,void *args) {struct svc_serv *serv =NULL ; +struct svc_rqst *rqstp; +int (* callback_svc)(void *vrqstp); +char svc_name[12 ];int ret =0 ;mutex_lock (&nfs_callback_mutex);
@@ -117,30 +142,31 @@ int nfs_callback_up(void) goto out; serv =svc_create (&nfs4_callback_program,NFS4_CALLBACK_BUFSIZE , nfs_callback_family,NULL ); - ret = -ENOMEM ; -if (!serv) - goto out_err; - - ret =svc_create_xprt (serv,"tcp" , nfs_callback_set_tcpport, -SVC_SOCK_ANONYMOUS ); -if (ret <=0 ) +if (!serv) { + ret = -ENOMEM ; goto out_err; - nfs_callback_tcpport = ret; -dprintk ("NFS: Callback listener port = %u (af %u)\n" , - nfs_callback_tcpport, nfs_callback_family); + } - nfs_callback_info.rqst =svc_prepare_thread (serv, &serv->sv_pools[0 ]); -if (IS_ERR (nfs_callback_info.rqst)) { - ret =PTR_ERR (nfs_callback_info.rqst); - nfs_callback_info.rqst =NULL ; +/* FIXME: either 4.0 or 4.1 callback service can be up at a time +* need to monitor and control them both */ +if (!minorversion) { + rqstp =nfs4_callback_up (serv); + callback_svc = nfs4_callback_svc; + }else { +BUG ();/* for now */ + } +if (IS_ERR (rqstp)) { + ret =PTR_ERR (rqstp); goto out_err; }svc_sock_update_bufs (serv); - nfs_callback_info.task =kthread_run (nfs_callback_svc, +sprintf (svc_name,"nfsv4.%u-svc" , minorversion); + nfs_callback_info.rqst = rqstp; + nfs_callback_info.task =kthread_run (callback_svc, nfs_callback_info.rqst, -"nfsv4-svc" ); + svc_name);if (IS_ERR (nfs_callback_info.task)) { ret =PTR_ERR (nfs_callback_info.task);svc_exit_thread (nfs_callback_info.rqst);
fs/nfs/callback.h +1 -1
@@ -63,7 +63,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getatextern __be32 nfs4_callback_recall (struct cb_recallargs *args,void *dummy);#ifdef CONFIG_NFS_V4 -extern int nfs_callback_up (void ); +extern int nfs_callback_up (u32 minorversion,void *args);extern void nfs_callback_down (void );#else #define nfs_callback_up () (0)
fs/nfs/client.c +12 -11
@@ -129,12 +129,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ clp->rpc_ops = cl_init->rpc_ops; -if (cl_init->rpc_ops->version ==4 ) { -if (nfs_callback_up () <0 ) - goto error_2; -__set_bit (NFS_CS_CALLBACK , &clp->cl_res_state); - } -atomic_set (&clp->cl_count,1 ); clp->cl_cons_state =NFS_CS_INITING ;
@@ -144,7 +138,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_if (cl_init->hostname) { clp->cl_hostname =kstrdup (cl_init->hostname,GFP_KERNEL );if (!clp->cl_hostname) - goto error_3; + goto error_cleanup; }INIT_LIST_HEAD (&clp->cl_superblocks);
@@ -167,10 +161,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_return clp; -error_3: -if (__test_and_clear_bit (NFS_CS_CALLBACK , &clp->cl_res_state)) -nfs_callback_down (); -error_2: +error_cleanup:kfree (clp); error_0:return NULL ;
@@ -1008,6 +999,16 @@ static int nfs4_init_client(struct nfs_client *clp, goto error;memcpy (clp->cl_ipaddr, ip_addr,sizeof (clp->cl_ipaddr)); +/* Start the callback server */ + error =nfs_callback_up (clp->cl_minorversion, + clp->cl_rpcclient->cl_xprt); +if (error <0 ) { +dprintk ("%s: failed to start callback. Error = %d\n" , + __func__, error); + goto error; + } +__set_bit (NFS_CS_CALLBACK , &clp->cl_res_state); + error =nfs_idmap_new (clp);if (error <0 ) { dprintk("%s: failed to create idmapper. Error = %d\n",
Signature · 1 line
1.6.0.2
RFC 56/85 nfs41: client callback structures
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Adds new list of rpc_xprt structures, and a readers/writers lock to protect the list. The list is used to preallocate resources for the backchannel during backchannel requests. Callbacks are not expected to cause significant latency, so only one callback will be allowed at this time.
It also adds a pointer to the NFS callback service so that requests can be directed to it for processing.
nfs41: NFSv4.1 callback support
New callback members added to svc_serv. The NFSv4.1 callback service will sleep on the svc_serv->svc_cb_waitq until new callback requests arrive. The request will be queued in svc_serv->svc_cb_list. This patch adds this list, the sleep queue and spinlock to svc_serv.
--- include/linux/sunrpc/svc.h | 10 ++++++++++ include/linux/sunrpc/xprt.h | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 0 deletions(-)
include/linux/sunrpc/svc.h +10 -0
@@ -81,6 +81,16 @@ struct svc_serv {struct module * sv_module;/* optional module to count when * adding threads */ svc_thread_fn sv_function;/* main function for threads */ +#if defined(CONFIG_NFS_V4_1 ) +struct list_head sv_cb_list;/* queue for callback requests +* that arrive over the same +* connection +*/ +spinlock_t sv_cb_lock;/* protects the svc_cb_list */ +wait_queue_head_t sv_cb_waitq;/* sleep here if there are no +* entries in the svc_cb_list +*/ +#endif /* CONFIG_NFS_V4_1 */ };/*
include/linux/sunrpc/xprt.h +22 -0
@@ -97,6 +97,12 @@ struct rpc_rqst {unsigned long rq_xtime;/* when transmitted */ int rq_ntrans; + +#if defined(CONFIG_NFS_V4_1 ) +struct list_head rq_bc_list;/* Callback service list */ +unsigned long rq_bc_pa_state;/* Backchannel prealloc state */ +struct list_head rq_bc_pa_list;/* Backchannel prealloc list */ +#endif /* CONFIG_NFS_V4_1 */ };#define rq_svec rq_snd_buf.head#define rq_slen rq_snd_buf.len
@@ -174,6 +180,14 @@ struct rpc_xprt {spinlock_t reserve_lock;/* lock slot table */ u32 xid;/* Next XID value to use */ struct rpc_task * snd_task;/* Task blocked in send */ +#if defined(CONFIG_NFS_V4_1 ) +struct svc_serv *bc_serv;/* The RPC service which will */ +/* process the callback */ +spinlock_t bc_pa_lock;/* Protects the preallocated */ +/* items */ +struct list_head bc_pa_list;/* List of preallocated */ +/* backchannel rpc_rqst's */ +#endif /* CONFIG_NFS_V4_1 */ struct list_head recv;struct {
@@ -192,6 +206,14 @@ struct rpc_xprt {const char *address_strings[RPC_DISPLAY_MAX ]; }; +#if defined(CONFIG_NFS_V4_1 ) +/* +* Backchannel flags +*/ +#define RPC_BC_PA_IN_USE 0x0001/* Preallocated backchannel */ +/* buffer in use */ +#endif /* CONFIG_NFS_V4_1 */ +struct xprt_create {int ident;/* XPRT_TRANSPORT identifier */ struct sockaddr * srcaddr;/* optional local address */
Signature · 1 line
1.6.0.2
RFC 57/85 nfs41: Initialize new rpc_xprt callback related fields
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
--- net/sunrpc/xprt.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
net/sunrpc/xprt.c +5 -0
@@ -1034,6 +1034,11 @@ found:INIT_LIST_HEAD (&xprt->free);INIT_LIST_HEAD (&xprt->recv); +#if defined(CONFIG_NFS_V4_1 ) +spin_lock_init (&xprt->bc_pa_lock); +INIT_LIST_HEAD (&xprt->bc_pa_list); +#endif /* CONFIG_NFS_V4_1 */ +INIT_WORK (&xprt->task_cleanup, xprt_autoclose);setup_timer (&xprt->timer, xprt_init_autodisconnect, (unsigned long )xprt);
Signature · 1 line
1.6.0.2
RFC 58/85 nfs41: New backchannel helper routines
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
This patch introduces support to setup the callback xprt on the client side. It allocates/ destroys the preallocated memory structures used to process backchannel requests.
At setup time, xprt_setup_backchannel() is invoked to allocate one or more rpc_rqst structures and substructures. This ensures that they are available when an RPC callback arrives. The rpc_rqst structures are maintained in a linked list attached to the rpc_xprt structure. We keep track of the number of allocations so that they can be correctly removed when the channel is destroyed.
When an RPC callback arrives, xprt_alloc_bc_request() is invoked to obtain a preallocated rpc_rqst structure. An rpc_xprt structure is returned, and its RPC_BC_PREALLOC_IN_USE bit is set in rpc_xprt->bc_flags. The structure is removed from the the list since it is now in use, and it will be later added back when its user is done with it.
After the RPC callback replies, the rpc_rqst structure is returned by invoking xprt_free_bc_request(). This clears the RPC_BC_PREALLOC_IN_USE bit and adds it back to the list, allowing it to be reused by a subsequent RPC callback request.
--- include/linux/sunrpc/xprt.h | 1 + net/sunrpc/Makefile | 1 + net/sunrpc/backchannel_rqst.c | 268 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+), 0 deletions(-) create mode 100644 net/sunrpc/backchannel_rqst.c
include/linux/sunrpc/xprt.h +1 -0
@@ -183,6 +183,7 @@ struct rpc_xprt {#if defined(CONFIG_NFS_V4_1 )struct svc_serv *bc_serv;/* The RPC service which will */ /* process the callback */ +unsigned int bc_alloc_count;/* Total number of preallocs */ spinlock_t bc_pa_lock;/* Protects the preallocated */ /* items */ struct list_head bc_pa_list;/* List of preallocated */
net/sunrpc/Makefile +1 -0
@@ -13,5 +13,6 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o +sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.o
net/sunrpc/backchannel_rqst.c new file +268 -0
268 lines not on this page · raw message
Signature · 1 line
1.6.0.2
RFC 59/85 nfs41: New include/linux/sunrpc/bc_xprt.h
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Contains prototype for backchannel helper routines.
--- include/linux/sunrpc/bc_xprt.h | 40 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 40 insertions(+), 0 deletions(-) create mode 100644 include/linux/sunrpc/bc_xprt.h
include/linux/sunrpc/bc_xprt.h new file +40 -0
@@ -0,0 +1,40 @@ +/****************************************************************************** + +(c) 2008 Network Appliance, Inc. All Rights Reserved. + +Network Appliance provides this source code under the GPL v2 License. +The GPL v2 license is available at +http://opensource.org/licenses/gpl-license.php. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +/* +* Functions to create and manage the backchannel +*/ + +#ifndef _LINUX_SUNRPC_BC_XPRT_H +#define _LINUX_SUNRPC_BC_XPRT_H + +#include <linux/sunrpc/svcsock.h> +#include <linux/sunrpc/xprt.h> + +#ifdef CONFIG_NFS_V4_1 +struct rpc_rqst *xprt_alloc_bc_request (struct rpc_xprt *xprt); +void xprt_free_bc_request (struct rpc_rqst *req); +int xprt_setup_backchannel (struct rpc_xprt *,unsigned int min_reqs); +void xprt_destroy_backchannel (struct rpc_xprt *,int max_reqs); +#endif /* CONFIG_NFS_V4_1 */ +#endif /* _LINUX_SUNRPC_BC_XPRT_H */ +
Signature · 1 line
1.6.0.2
RFC 60/85 nfs41: New xs_tcp_read_data()
In reply to Benny HalevyHandles RPC replies and backchannel callbacks. Traditionally the NFS client has expected only RPC replies on its open connections. With NFSv4.1, callbacks can arrive over an existing open connection.
This patch refactors the old xs_tcp_read_request() into an RPC reply handler:xs_tcp_read_reply(), a new backchannel callback handler: xs_tcp_read_callback(), and a common routine to read the data off the transport: xs_tcp_read_common(). The new xs_tcp_read_callback() queues callback requests onto a queue where the callback service (a separate thread) is listening for the processing.
This patch incorporates work and suggestions from Rahul Iyer ([email protected]) and Benny Halevy ([email protected]).
Note that we need to update the printk warning message to throttle the number of warnings printed to avoid overflowing syslog with it.
--- net/sunrpc/xprtsock.c | 139 ++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 121 insertions(+), 18 deletions(-)
net/sunrpc/xprtsock.c +121 -18
@@ -34,6 +34,9 @@#include <linux/sunrpc/sched.h> #include <linux/sunrpc/xprtsock.h> #include <linux/file.h> +#ifdef CONFIG_NFS_V4_1 +#include <linux/sunrpc/bc_xprt.h> +#endif #include <net/sock.h> #include <net/checksum.h>
@@ -997,25 +1000,16 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,xs_tcp_check_fraghdr (transport); } -static inline void xs_tcp_read_request (struct rpc_xprt *xprt,struct xdr_skb_reader *desc) +static inline void xs_tcp_read_common (struct rpc_xprt *xprt, +struct xdr_skb_reader *desc, +struct rpc_rqst *req) { - struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); -struct rpc_rqst *req; +struct sock_xprt *transport = + container_of(xprt, struct sock_xprt, xprt);struct xdr_buf *rcvbuf;size_t len;ssize_t r; -/* Find and lock the request corresponding to this xid */ -spin_lock (&xprt->transport_lock); - req =xprt_lookup_rqst (xprt, transport->tcp_xid); -if (!req) { - transport->tcp_flags &= ~TCP_RCV_COPY_DATA ; -dprintk ("RPC: XID %08x request not found!\n" , -ntohl (transport->tcp_xid)); -spin_unlock (&xprt->transport_lock); -return ; - } - rcvbuf = &req->rq_private_buf; len = desc->count;if (len > transport->tcp_reclen - transport->tcp_offset) {
@@ -1053,7 +1047,7 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea"tcp_offset = %u, tcp_reclen = %u\n" , xprt, transport->tcp_copied, transport->tcp_offset, transport->tcp_reclen); - goto out; +return ; } dprintk("RPC: XID %08x read %Zd bytes\n",
@@ -1069,11 +1063,120 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea transport->tcp_flags &= ~TCP_RCV_COPY_DATA ; } -out: +return ; +} + +/* +* Finds the request corresponding to the RPC xid and invokes the common +* tcp read code to read the data. +*/ +static inline int xs_tcp_read_reply (struct rpc_xprt *xprt, +struct xdr_skb_reader *desc) +{ +struct sock_xprt *transport = + container_of(xprt, struct sock_xprt, xprt); +struct rpc_rqst *req; + +dprintk ("RPC: read reply XID %08x\n" ,ntohl (transport->tcp_xid)); + +/* Find and lock the request corresponding to this xid */ +spin_lock (&xprt->transport_lock); + req =xprt_lookup_rqst (xprt, transport->tcp_xid); +if (!req) { +dprintk ("RPC: XID %08x request not found!\n" , +ntohl (transport->tcp_xid)); +spin_unlock (&xprt->transport_lock); +return -1 ; + } + +xs_tcp_read_common (xprt, desc, req); +if (!(transport->tcp_flags &TCP_RCV_COPY_DATA ))xprt_complete_rqst (req->rq_task, transport->tcp_copied); +spin_unlock (&xprt->transport_lock); -xs_tcp_check_fraghdr (transport); +return 0 ; +} + +#if defined(CONFIG_NFS_V4_1 ) +/* +* Obtains an rpc_rqst previously allocated and invokes the common +* tcp read code to read the data. The result is placed in the callback +* queue. +* If we're unable to obtain the rpc_rqst we schedule the closing of the +* connection and return -1. +*/ +static inline int xs_tcp_read_callback (struct rpc_xprt *xprt, +struct xdr_skb_reader *desc) +{ +struct sock_xprt *transport = + container_of(xprt, struct sock_xprt, xprt); +struct rpc_rqst *req; + + req =xprt_alloc_bc_request (xprt); +if (req ==NULL ) { +/* +* Schedule an autoclose RPC call +*/ +printk (KERN_WARNING "Callback slot table overflowed\n" ); +set_bit (XPRT_CLOSE_WAIT , &xprt->state); +if (test_and_set_bit (XPRT_LOCKED , &xprt->state) ==0 ) +queue_work (rpciod_workqueue, &xprt->task_cleanup); +return -1 ; + } + + req->rq_xid = transport->tcp_xid; +dprintk ("RPC: read callback XID %08x\n" ,ntohl (req->rq_xid)); +xs_tcp_read_common (xprt, desc, req); + +if (!(transport->tcp_flags &TCP_RCV_COPY_DATA )) { +struct svc_serv *bc_serv = xprt->bc_serv; + +/* +* Add callback request to callback list. The callback +* service sleeps on the sv_cb_waitq waiting for new +* requests. Wake it up after adding enqueing the +* request. +*/ +dprintk ("RPC: add callback request to list\n" ); +spin_lock (&bc_serv->sv_cb_lock); +list_add (&req->rq_bc_list, &bc_serv->sv_cb_list); +spin_unlock (&bc_serv->sv_cb_lock); +wake_up (&bc_serv->sv_cb_waitq); + } + +return 0 ; +} +#endif /* CONFIG_NFS_V4_1 */ + +/* +* Read data off the transport. This can be either an RPC_CALL or an +* RPC_REPLY. Relay the processing to helper functions. +*/ +static void xs_tcp_read_data (struct rpc_xprt *xprt, +struct xdr_skb_reader *desc) +{ +struct sock_xprt *transport = + container_of(xprt, struct sock_xprt, xprt); +int status; + +#if defined(CONFIG_NFS_V4_1 ) + status = (transport->tcp_calldir ==RPC_REPLY ) ? +xs_tcp_read_reply (xprt, desc) : +xs_tcp_read_callback (xprt, desc); +#else + status =xs_tcp_read_reply (xprt, desc); +#endif /* CONFIG_NFS_V4_1 */ + +if (status ==0 ) +xs_tcp_check_fraghdr (transport); +else { +/* +* The transport_lock protects the request handling. +* There's no need to hold it to update the tcp_flags. +*/ + transport->tcp_flags &= ~TCP_RCV_COPY_DATA ; + } }static inline void xs_tcp_read_discard (struct sock_xprt *transport,struct xdr_skb_reader *desc)
@@ -1120,7 +1223,7 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns }/* Read in the request data */ if (transport->tcp_flags &TCP_RCV_COPY_DATA ) { -xs_tcp_read_request (xprt, &desc); +xs_tcp_read_data (xprt, &desc);continue ; }/* Skip over any trailing bytes on short reads */
Signature · 1 line
1.6.0.2
RFC 61/85 nfs41: Add backchannel processing support to RPC state machine
In reply to Benny HalevyAdds rpc_run_bc_task() which is called by the NFS callback service to process backchannel requests. It performs similar work to rpc_run_task() though "schedules" the backchannel task to be executed starting at the call_trasmit state in the RPC state machine.
It also introduces some miscellaneous updates to the argument validation, call_transmit, and transport cleanup functions to take into account that there are now forechannel and backchannel tasks.
Backchannel requests do not carry an RPC message structure, since the payload has already been XDR encoded using the existing NFSv4 callback mechanism.
--- include/linux/sunrpc/sched.h | 2 + include/linux/sunrpc/xprt.h | 12 +++++++++ net/sunrpc/clnt.c | 52 ++++++++++++++++++++++++++++++++++++++++- net/sunrpc/stats.c | 6 +++- net/sunrpc/sunrpc.h | 35 ++++++++++++++++++++++++++++ net/sunrpc/xprt.c | 36 ++++++++++++++++++++++++----- 6 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 net/sunrpc/sunrpc.h
include/linux/sunrpc/sched.h +2 -0
@@ -210,6 +210,8 @@ struct rpc_wait_queue {*/ struct rpc_task *rpc_new_task (const struct rpc_task_setup *);struct rpc_task *rpc_run_task (const struct rpc_task_setup *); +struct rpc_task *rpc_run_bc_task (struct rpc_rqst *req, +const struct rpc_call_ops *ops);void rpc_put_task (struct rpc_task *);void rpc_exit_task (struct rpc_task *);void rpc_release_calldata (const struct rpc_call_ops *,void *);
include/linux/sunrpc/xprt.h +12 -0
@@ -215,6 +215,18 @@ struct rpc_xprt {/* buffer in use */ #endif /* CONFIG_NFS_V4_1 */ +#if defined(CONFIG_NFS_V4_1 ) +static inline int bc_prealloc (struct rpc_rqst *req) +{ +return test_bit (RPC_BC_PA_IN_USE , &req->rq_bc_pa_state); +} +#else +static inline int bc_prealloc (struct rpc_rqst *req) +{ +return 0 ; +} +#endif /* CONFIG_NFS_V4_1 */ +struct xprt_create {int ident;/* XPRT_TRANSPORT identifier */ struct sockaddr * srcaddr;/* optional local address */
net/sunrpc/clnt.c +50 -2
73 lines not on this page · raw message
net/sunrpc/stats.c +4 -2
@@ -141,12 +141,14 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats);void rpc_count_iostats (struct rpc_task *task) {struct rpc_rqst *req = task->tk_rqstp; -struct rpc_iostats *stats = task->tk_client->cl_metrics; +struct rpc_iostats *stats;struct rpc_iostats *op_metrics;long rtt, execute, queue; -if (!stats || !req) +if (!task->tk_client || task->tk_client->cl_metrics || !req)return ; + + stats = task->tk_client->cl_metrics; op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; op_metrics->om_ops++;
net/sunrpc/sunrpc.h new file +35 -0
@@ -0,0 +1,35 @@ +/****************************************************************************** + +(c) 2008 Network Appliance, Inc. All Rights Reserved. + +Network Appliance provides this source code under the GPL v2 License. +The GPL v2 license is available at +http://opensource.org/licenses/gpl-license.php. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +/* +* Functions and macros used internally by RPC +*/ + +#ifndef _NET_SUNRPC_SUNRPC_H +#define _NET_SUNRPC_SUNRPC_H + +#define rpc_reply_expected (task) \ + (((task)->tk_msg.rpc_proc != NULL) && \ + ((task)->tk_msg.rpc_proc->p_decode != NULL)) + +#endif /* _NET_SUNRPC_SUNRPC_H */ +
net/sunrpc/xprt.c +30 -6
@@ -12,8 +12,9 @@* - Next, the caller puts together the RPC message, stuffs it into * the request struct, and calls xprt_transmit(). * - xprt_transmit sends the message and installs the caller on the -* transport's wait list. At the same time, it installs a timer that -* is run after the packet's timeout has expired. +* transport's wait list. At the same time, if a reply is expected, +* it installs a timer that is run after the packet's timeout has +* expired. * - When a packet arrives, the data_ready handler walks the list of * pending requests for that transport. If a matching XID is found, the * caller is woken up, and the timer removed.
@@ -46,6 +47,8 @@#include <linux/sunrpc/clnt.h> #include <linux/sunrpc/metrics.h> +#include "sunrpc.h" +/* * Local variables */
@@ -852,7 +855,10 @@ void xprt_transmit(struct rpc_task *task)dprintk ("RPC: %5u xprt_transmit(%u)\n" , task->tk_pid, req->rq_slen);if (!req->rq_received) { -if (list_empty (&req->rq_list)) { +if (list_empty (&req->rq_list) &&rpc_reply_expected (task)) { +/* +* Add to the list only if we're expecting a reply +*/ spin_lock_bh (&xprt->transport_lock);/* Update the softirq receive buffer */ memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
@@ -883,8 +889,13 @@ void xprt_transmit(struct rpc_task *task)/* Don't race with disconnect */ if (!xprt_connected (xprt)) task->tk_status = -ENOTCONN ; -else if (!req->rq_received) +else if (!req->rq_received &&rpc_reply_expected (task)) { +/* +* Sleep on the pending queue since +* we're expecting a reply. +*/ rpc_sleep_on (&xprt->pending, task, xprt_timer); + }spin_unlock_bh (&xprt->transport_lock);return ; }
@@ -967,11 +978,15 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)*/ void xprt_release (struct rpc_task *task) { -struct rpc_xprt *xprt = task->tk_xprt; +struct rpc_xprt *xprt;struct rpc_rqst *req; +int prealloc; +BUG_ON (atomic_read (&task->tk_count) <0 );if (!(req = task->tk_rqstp))return ; + prealloc =bc_prealloc (req);/* Preallocated backchannel request? */ + xprt = req->rq_xprt;rpc_count_iostats (task);spin_lock_bh (&xprt->transport_lock); xprt->ops->release_xprt (xprt, task);
@@ -984,10 +999,19 @@ void xprt_release(struct rpc_task *task)mod_timer (&xprt->timer, xprt->last_used + xprt->idle_timeout);spin_unlock_bh (&xprt->transport_lock); - xprt->ops->buf_free (req->rq_buffer); +if (!bc_prealloc (req)) + xprt->ops->buf_free (req->rq_buffer); task->tk_rqstp =NULL ;if (req->rq_release_snd_buf) req->rq_release_snd_buf (req); + +/* +* Early exit if this is a backchannel preallocated request. +* There is no need to have it added to the RPC slot list. +*/ +if (prealloc) +return ; +memset (req,0 ,sizeof (*req));/* mark unused */ dprintk ("RPC: %5u release request %p\n" , task->tk_pid, req);
Signature · 1 line
1.6.0.2
RFC 62/85 nfs41: Backchannel callback service helper routines
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Executes the backchannel task on the RPC state machine using the existing open connection previously established by the client.
nfs41: Add bc_svc.o to sunrpc Makefile.
--- include/linux/sunrpc/bc_xprt.h | 3 + net/sunrpc/Makefile | 2 +- net/sunrpc/bc_svc.c | 81 ++++++++++++++++++++++++++++++++++++++++ net/sunrpc/xprtsock.c | 3 + 4 files changed, 88 insertions(+), 1 deletions(-) create mode 100644 net/sunrpc/bc_svc.c
include/linux/sunrpc/bc_xprt.h +3 -0
@@ -29,12 +29,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/xprt.h> +#include <linux/sunrpc/sched.h> #ifdef CONFIG_NFS_V4_1 struct rpc_rqst *xprt_alloc_bc_request (struct rpc_xprt *xprt);void xprt_free_bc_request (struct rpc_rqst *req);int xprt_setup_backchannel (struct rpc_xprt *,unsigned int min_reqs);void xprt_destroy_backchannel (struct rpc_xprt *,int max_reqs); +void bc_release_request (struct rpc_task *); +int bc_send (struct rpc_rqst *req);#endif /* CONFIG_NFS_V4_1 */ #endif /* _LINUX_SUNRPC_BC_XPRT_H */
net/sunrpc/Makefile +1 -1
@@ -13,6 +13,6 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ rpcb_clnt.o timer.o xdr.o \ sunrpc_syms.o cache.o rpc_pipe.o \ svc_xprt.o -sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o +sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o bc_svc.o sunrpc-$(CONFIG_PROC_FS) += stats.o sunrpc-$(CONFIG_SYSCTL) += sysctl.o
net/sunrpc/bc_svc.c new file +81 -0
81 lines not on this page · raw message
net/sunrpc/xprtsock.c +3 -0
@@ -2046,6 +2046,9 @@ static struct rpc_xprt_ops xs_tcp_ops = { .buf_free = rpc_free, .send_request = xs_tcp_send_request, .set_retrans_timeout = xprt_set_retrans_timeout_def, +#if defined(CONFIG_NFS_V4_1 ) + .release_request = bc_release_request, +#endif /* CONFIG_NFS_V4_1 */ .close = xs_tcp_shutdown, .destroy = xs_destroy, .print_stats = xs_tcp_print_stats,
Signature · 1 line
1.6.0.2
RFC 63/85 FIXME: nfs41: sunrpc: handle clnt==NULL in call_status
In reply to Benny HalevyFIXME: pending discussion. This patch might not be needed if backchannel usage of rpc mechanisms for sending bc_svc replies (on the nfs client / callback svc side)
On the following error path task->tk_client == NULL causing NULL deref:
Nov 4 14:14:32 tl1 kernel: Callback slot table overflowed Nov 4 14:14:32 tl1 kernel: BUG: unable to handle kernel NULL pointer dereference at 0000000000000078 Nov 4 14:14:32 tl1 kernel: IP: [<ffffffffa02b4dd2>] call_status+0xe1/0x145 [sunrpc] Nov 4 14:14:32 tl1 kernel: PGD 2f973067 PUD 2f974067 PMD 0 Nov 4 14:14:32 tl1 kernel: Oops: 0000 [1] SMP Nov 4 14:14:32 tl1 kernel: CPU 0 Nov 4 14:14:32 tl1 kernel: Modules linked in: panfs(P) panlayoutdriver nfslayoutdriver nfsd auth_rpcgss exportfs nfs lockd nfs_acl fuse sunrpc ipv6 cpufreq_ondemand powernow_k8 freq_table dm_mirror dm_log dm_multipath dm_mod snd_hda_intel snd_seq_dummy sr_mod snd_seq_oss cdrom snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc snd_hwdep snd pcspkr serio_raw k8temp hwmon forcedeth soundcore pata_amd sg jedec_probe cfi_probe gen_probe mtd i2c_nforce2 chipreg i2c_core button map_funcs sata_nv ata_generic pata_acpi libata sd_mod scsi_mod ext3 jbd mbcache uhci_hcd ohci_hcd ehci_hcd [last unloaded: scsi_wait_scan] Nov 4 14:14:32 tl1 kernel: Pid: 3405, comm: nfsv4.1-svc Tainted: P 2.6.27-pnfs #1 Nov 4 14:14:32 tl1 kernel: RIP: 0010:[<ffffffffa02b4dd2>] [<ffffffffa02b4dd2>] call_status+0xe1/0x145 [sunrpc] Nov 4 14:14:32 tl1 kernel: RSP: 0018:ffff88002a70bd60 EFLAGS: 00010246 Nov 4 14:14:32 tl1 kernel: RAX: 0000000000000000 RBX: 00000000ffffff95 RCX: 0000000000000000 Nov 4 14:14:32 tl1 kernel: RDX: ffff88002a70bd10 RSI: ffff88002fc52dc0 RDI: ffff88002fc52dc0 Nov 4 14:14:32 tl1 kernel: RBP: ffff88002a70bd80 R08: ffff88002f9dae40 R09: ffffffff81489e60 Nov 4 14:14:32 tl1 kernel: R10: ffff880038497800 R11: ffff88002a70bd30 R12: ffff88002fc52dc0 Nov 4 14:14:32 tl1 kernel: R13: 0000000000000000 R14: ffff88002f57fa00 R15: ffff88002fc52e50 Nov 4 14:14:32 tl1 kernel: FS: 00007fe78ffac6f0(0000) GS:ffffffff8148da80(0000) knlGS:0000000000000000 Nov 4 14:14:32 tl1 kernel: CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b Nov 4 14:14:32 tl1 kernel: CR2: 0000000000000078 CR3: 000000002f971000 CR4: 00000000000006e0 Nov 4 14:14:32 tl1 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 Nov 4 14:14:32 tl1 kernel: DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Nov 4 14:14:32 tl1 kernel: Process nfsv4.1-svc (pid: 3405, threadinfo ffff88002a70a000, task ffff88003694d900) Nov 4 14:14:32 tl1 kernel: Stack: 0000000000000000 ffff88002f57fa00 ffff88002fc52dc0 ffff880030450ce8 Nov 4 14:14:32 tl1 kernel: ffff88002a70bdc0 ffffffffa02bb9db ffff88002a70bdf0 ffff88002fc52dc0 Nov 4 14:14:32 tl1 kernel: ffff88002f57fa00 ffff88002f57fa00 ffff880030450ce8 ffff88002a734000 Nov 4 14:14:32 tl1 kernel: Call Trace: Nov 4 14:14:32 tl1 kernel: [<ffffffffa02bb9db>] __rpc_execute+0x7e/0x21f [sunrpc] Nov 4 14:14:32 tl1 kernel: [<ffffffffa02bbba4>] rpc_execute+0x28/0x2c [sunrpc] Nov 4 14:14:32 tl1 kernel: [<ffffffffa02b5596>] rpc_run_bc_task+0x88/0xae [sunrpc] Nov 4 14:14:32 tl1 kernel: [<ffffffffa02c923d>] bc_send+0x35/0x5a [sunrpc] Nov 4 14:14:32 tl1 kernel: [<ffffffffa02bdc92>] bc_svc_process+0xf6/0x101 [sunrpc] Nov 4 14:14:32 tl1 kernel: [<ffffffff81048a6c>] ? prepare_to_wait+0x5c/0x65 Nov 4 14:14:32 tl1 kernel: [<ffffffffa033a4c9>] nfs41_callback_svc+0xda/0x131 [nfs] Nov 4 14:14:32 tl1 kernel: [<ffffffff810488a0>] ? autoremove_wake_function+0x0/0x38 Nov 4 14:14:32 tl1 kernel: [<ffffffffa033a3ef>] ? nfs41_callback_svc+0x0/0x131 [nfs] Nov 4 14:14:32 tl1 kernel: [<ffffffff81048561>] kthread+0x49/0x76 Nov 4 14:14:32 tl1 kernel: [<ffffffff8100cf49>] child_rip+0xa/0x11 Nov 4 14:14:32 tl1 kernel: [<ffffffff8102a401>] ? pick_next_task_fair+0x93/0xa3 Nov 4 14:14:32 tl1 kernel: [<ffffffff81048518>] ? kthread+0x0/0x76 Nov 4 14:14:32 tl1 kernel: [<ffffffff8100cf3f>] ? child_rip+0x0/0x11 Nov 4 14:14:32 tl1 kernel: Nov 4 14:14:32 tl1 kernel: Nov 4 14:14:32 tl1 kernel: Code: e8 7c 70 00 00 49 8b 44 24 20 49 c7 44 24 68 dc 48 2b a0 f6 40 78 02 74 6d 41 8b b6 34 01 00 00 48 8b 78 30 e8 b9 2a 00 00 eb 5b <41> f6 45 78 04 74 13 49 8b 55 30 48 8d 82 80 04 00 00 f0 80 a2 Nov 4 14:14:32 tl1 kernel: RIP [<ffffffffa02b4dd2>] call_status+0xe1/0x145 [sunrpc] Nov 4 14:14:32 tl1 kernel: RSP <ffff88002a70bd60> Nov 4 14:14:32 tl1 kernel: CR2: 0000000000000078 Nov 4 14:14:32 tl1 kernel: ---[ end trace 1584c489f2573aaf ]---
--- net/sunrpc/clnt.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-)
net/sunrpc/clnt.c +5 -3
@@ -1204,7 +1204,8 @@ call_status(struct rpc_task *task)break ;case -ECONNREFUSED :case -ENOTCONN : -rpc_force_rebind (clnt); +if (clnt) +rpc_force_rebind (clnt); task->tk_action = call_bind;break ;case -EAGAIN :
@@ -1215,9 +1216,10 @@ call_status(struct rpc_task *task)rpc_exit (task, status);break ;default : -if (clnt->cl_chatty) +if (!clnt || clnt->cl_chatty)printk ("%s: RPC call returned error %d\n" , - clnt->cl_protname, -status); + clnt ? clnt->cl_protname :"<unknown protocol>" , + -status);rpc_exit (task, status); } }
Signature · 1 line
1.6.0.2
RFC 64/85 nfs41: Refactor svc_process()
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
net/sunrpc/svc.c:svc_process() is used by the NFSv4 callback service to process RPC requests arriving over connections initiated by the server. NFSv4.1 supports callbacks over the backchannel on connections initiated by the client. This patch refactors svc_process() so that common code can also be used by the backchannel.
--- fs/nfs/callback.c | 10 +++--- net/sunrpc/svc.c | 80 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 35 deletions(-)
fs/nfs/callback.c +5 -5
@@ -132,7 +132,7 @@ nfs4_callback_up(struct svc_serv *serv)int nfs_callback_up (u32 minorversion,void *args) {struct svc_serv *serv =NULL ; -struct svc_rqst *rqstp; +struct svc_rqst *rqst;int (* callback_svc)(void *vrqstp);char svc_name[12 ];int ret =0 ;
@@ -150,20 +150,20 @@ int nfs_callback_up(u32 minorversion, void *args)/* FIXME: either 4.0 or 4.1 callback service can be up at a time * need to monitor and control them both */ if (!minorversion) { - rqstp =nfs4_callback_up (serv); + rqst =nfs4_callback_up (serv); callback_svc = nfs4_callback_svc; }else {BUG ();/* for now */ } -if (IS_ERR (rqstp)) { - ret =PTR_ERR (rqstp); +if (IS_ERR (rqst)) { + ret =PTR_ERR (rqst); goto out_err; }svc_sock_update_bufs (serv);sprintf (svc_name,"nfsv4.%u-svc" , minorversion); - nfs_callback_info.rqst = rqstp; + nfs_callback_info.rqst = rqst; nfs_callback_info.task =kthread_run (callback_svc, nfs_callback_info.rqst, svc_name);
net/sunrpc/svc.c +50 -30
131 lines not on this page · raw message
Signature · 1 line
1.6.0.2
RFC 65/85 nfs41: Backchannel bc_svc_process()
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Implement the NFSv4.1 backchannel service. Invokes the common callback processing logic svc_process_common() to authenticate the call and dispatch the appropriate NFSv4.1 XDR decoder and operation procedure. It then invokes bc_send() to send the reply over the same connection. bc_send() is implemented in a separate patch.
At this time there is no slot validation or reply cache handling.
--- net/sunrpc/svc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 49 insertions(+), 0 deletions(-)
net/sunrpc/svc.c +49 -0
@@ -25,6 +25,7 @@#include <linux/sunrpc/stats.h> #include <linux/sunrpc/svcsock.h> #include <linux/sunrpc/clnt.h> +#include <linux/sunrpc/bc_xprt.h> #define RPCDBG_FACILITY RPCDBG_SVCDSP
@@ -1253,6 +1254,54 @@ svc_process(struct svc_rqst *rqstp)return svc_send (rqstp); } +#if defined(CONFIG_NFS_V4_1 ) +/* +* Process a backchannel RPC request that arrived over an existing +* outbound connection +*/ +int +bc_svc_process (struct svc_serv *serv,struct rpc_rqst *req, +struct svc_rqst *rqstp) +{ +struct kvec *argv = &rqstp->rq_arg.head[0 ]; +struct kvec *resv = &rqstp->rq_res.head[0 ]; +int error; + +/* Build the svc_rqst used by the common processing routine */ + rqstp->rq_xid = req->rq_xid; + rqstp->rq_prot = req->rq_xprt->prot; + rqstp->rq_server = serv; + + rqstp->rq_addrlen =sizeof (req->rq_xprt->addr); +memcpy (&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); +memcpy (&rqstp->rq_arg, &req->rq_private_buf,sizeof (rqstp->rq_arg)); +memcpy (&rqstp->rq_res, &req->rq_snd_buf,sizeof (rqstp->rq_res)); + +/* reset result send buffer "put" position */ + resv->iov_len =0 ; + +if (rqstp->rq_prot !=IPPROTO_TCP ) { +printk (KERN_ERR "No support for Non-TCP transports!\n" ); +BUG (); + } + +/* +* Skip the next two words because they've already been +* processed in the trasport +*/ +svc_getu32 (argv);/* XID */ +svc_getnl (argv);/* CALLDIR */ + + error =svc_process_common (rqstp, argv, resv); +if (error <=0 ) +return error; + +memcpy (&req->rq_snd_buf, &rqstp->rq_res,sizeof (req->rq_snd_buf)); +return bc_send (req); +} +EXPORT_SYMBOL (bc_svc_process); +#endif /* CONFIG_NFS_V4_1 */ +/* * Return (transport-specific) limit on the rpc payload. */
Signature · 1 line
1.6.0.2
RFC 66/85 nfs41: Implement NFSv4.1 callback service process.
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
nfs41_callback_up() initializes the necessary queues and creates the new nfs41_callback_svc thread. This thread executes the callback service which waits for requests to arrive on the svc_serv->sv_cb_list.
NFS41_BC_MIN_CALLBACKS is set to 1 because we expect callbacks to not cause substantial latency.
The actual processing of the callback will be implemented as a separate patch.
--- fs/nfs/callback.c | 76 +++++++++++++++++++++++++++++++++++++++++++- fs/nfs/callback.h | 8 +++++ include/linux/sunrpc/svc.h | 2 + 3 files changed, 85 insertions(+), 1 deletions(-)
fs/nfs/callback.c +75 -1
@@ -16,6 +16,9 @@#include <linux/mutex.h> #include <linux/freezer.h> #include <linux/kthread.h> +#if defined(CONFIG_NFS_V4_1 ) +#include <linux/sunrpc/bc_xprt.h> +#endif #include <net/inet_sock.h>
@@ -126,6 +129,69 @@ nfs4_callback_up(struct svc_serv *serv)return svc_prepare_thread (serv, &serv->sv_pools[0 ]); } +#if defined(CONFIG_NFS_V4_1 ) +/* +* The callback service for NFSv4.1 callbacks +*/ +static int +nfs41_callback_svc (void *vrqstp) +{ +struct svc_rqst *rqstp = vrqstp; +struct svc_serv *serv = rqstp->rq_server; +struct rpc_rqst *req; +int error; +DEFINE_WAIT (wq); + +set_freezable (); + +/* +* FIXME: do we really need to run this under the BKL? If so, please +* add a comment about what it's intended to protect. +*/ +lock_kernel (); +while (!kthread_should_stop ()) { +prepare_to_wait (&serv->sv_cb_waitq, &wq,TASK_INTERRUPTIBLE ); +spin_lock_bh (&serv->sv_cb_lock); +if (!list_empty (&serv->sv_cb_list)) { + req =list_first_entry (&serv->sv_cb_list, + struct rpc_rqst, rq_bc_list); +list_del (&req->rq_bc_list); +spin_unlock_bh (&serv->sv_cb_lock); +dprintk ("Invoking bc_svc_process()\n" ); + error =bc_svc_process (serv, req, rqstp); +dprintk ("bc_svc_process() returned w/ error code= %d\n" , + error); + }else { +spin_unlock_bh (&serv->sv_cb_lock); +schedule (); + } +finish_wait (&serv->sv_cb_waitq, &wq); + } +unlock_kernel (); + nfs_callback_info.task =NULL ; +svc_exit_thread (rqstp); +return 0 ; +} + +/* +* Bring up the NFSv4.1 callback service +*/ +struct svc_rqst * +nfs41_callback_up (struct svc_serv *serv,struct rpc_xprt *xprt) +{ +/* +* Save the svc_serv in the transport so that it can +* be referenced when the session backchannel is initialized +*/ + xprt->bc_serv = serv; + +INIT_LIST_HEAD (&serv->sv_cb_list); +spin_lock_init (&serv->sv_cb_lock); +init_waitqueue_head (&serv->sv_cb_waitq); +return svc_prepare_thread (serv, &serv->sv_pools[0 ]); +} +#endif /* CONFIG_NFS_V4_1 */ +/* * Bring up the callback thread if it is not already up. */
@@ -136,6 +202,9 @@ int nfs_callback_up(u32 minorversion, void *args)int (* callback_svc)(void *vrqstp);char svc_name[12 ];int ret =0 ; +#if defined(CONFIG_NFS_V4_1 ) +struct rpc_xprt *xprt = (struct rpc_xprt *)args; +#endif /* CONFIG_NFS_V4_1 */ mutex_lock (&nfs_callback_mutex);if (nfs_callback_info.users++ || nfs_callback_info.task !=NULL )
@@ -153,7 +222,12 @@ int nfs_callback_up(u32 minorversion, void *args) rqst =nfs4_callback_up (serv); callback_svc = nfs4_callback_svc; }else { -BUG ();/* for now */ +#if defined(CONFIG_NFS_V4_1 ) + rqst =nfs41_callback_up (serv, xprt); + callback_svc = nfs41_callback_svc; +#else /* CONFIG_NFS_V4_1 */ +BUG (); +#endif /* CONFIG_NFS_V4_1 */ }if (IS_ERR (rqst)) { ret =PTR_ERR (rqst);
fs/nfs/callback.h +8 -0
@@ -70,6 +70,14 @@ extern void nfs_callback_down(void);#define nfs_callback_down () do {} while(0)#endif +#ifdef CONFIG_NFS_V4_1 +/* +* Callbacks are expected to not cause substantial latency, +* so we limit their concurrency to 1. +*/ +#define NFS41_BC_MIN_CALLBACKS 1 +#endif /* CONFIG_NFS_V4_1 */ +extern unsigned int nfs_callback_set_tcpport;extern unsigned short nfs_callback_tcpport;
include/linux/sunrpc/svc.h +2 -0
@@ -403,6 +403,8 @@ struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,int svc_set_num_threads (struct svc_serv *,struct svc_pool *,int );void svc_destroy (struct svc_serv *);int svc_process (struct svc_rqst *); +int bc_svc_process (struct svc_serv *,struct rpc_rqst *, +struct svc_rqst *);int svc_register (const struct svc_serv *,const unsigned short ,const unsigned short );
Signature · 1 line
1.6.0.2
RFC 67/85 nfs41: sunrpc: provide functions to create and destroy a svc_xprt for backchannel use
In reply to Benny HalevyFor nfs41 callbacks we need an svc_xprt to process requests coming up the backchannel socket as rpc_rqst's that are transformed into svc_rqst's that need a rq_xprt to be processed.
The svc_{udp,tcp}_create methods are too heavy for this job as svc_create_socket creates an actual socket to listen on while for nfs41 we're "reusing" the fore channel's socket.
--- include/linux/sunrpc/svcsock.h | 2 ++ net/sunrpc/svcsock.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 0 deletions(-)
include/linux/sunrpc/svcsock.h +2 -0
@@ -42,6 +42,8 @@ int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);int svc_addsock (struct svc_serv *serv,int fd,char *name_return);void svc_init_xprt_sock (void );void svc_cleanup_xprt_sock (void ); +struct svc_xprt *svc_sock_create (struct svc_serv *serv,int prot); +void svc_sock_destroy (struct svc_xprt *);/* * svc_makesock socket characteristics
net/sunrpc/svcsock.c +39 -0
@@ -1298,3 +1298,42 @@ static void svc_sock_free(struct svc_xprt *xprt)sock_release (svsk->sk_sock);kfree (svsk); } + +/* +* Create a svc_xprt. +* +* For internal use only (e.g. nfsv4.1 backchannel). +* Callers should typically use the xpo_create() method. +*/ +struct svc_xprt *svc_sock_create (struct svc_serv *serv,int prot) +{ +struct svc_sock *svsk; +struct svc_xprt *xprt =NULL ; + +dprintk ("svc: %s\n" , __func__); + svsk =kzalloc (sizeof (*svsk),GFP_KERNEL ); +if (!svsk) + goto out; + + xprt = &svsk->sk_xprt; +if (prot ==IPPROTO_TCP ) +svc_xprt_init (&svc_tcp_class, xprt, serv); +else if (prot ==IPPROTO_UDP ) +svc_xprt_init (&svc_udp_class, xprt, serv); +else +BUG (); +out: +dprintk ("svc: %s return %p\n" , __func__, xprt); +return xprt; +} +EXPORT_SYMBOL_GPL (svc_sock_create); + +/* +* Destroy a svc_sock. +*/ +void svc_sock_destroy (struct svc_xprt *xprt) +{ +if (xprt) + kfree(container_of(xprt, struct svc_sock, sk_xprt)); +} +EXPORT_SYMBOL_GPL (svc_sock_destroy);
Signature · 1 line
1.6.0.2
RFC 68/85 nfs41: sunrpc: add a struct svc_xprt pointer to struct svc_serv for backchannel use
In reply to Benny HalevyThis svc_xprt is passed on to the callback service thread to be later used to processes incoming svc_rqst's
--- include/linux/sunrpc/svc.h | 1 + net/sunrpc/svc.c | 4 ++++ 2 files changed, 5 insertions(+), 0 deletions(-)
include/linux/sunrpc/svc.h +1 -0
@@ -90,6 +90,7 @@ struct svc_serv {wait_queue_head_t sv_cb_waitq;/* sleep here if there are no * entries in the svc_cb_list */ +struct svc_xprt *bc_xprt;#endif /* CONFIG_NFS_V4_1 */ };
net/sunrpc/svc.c +4 -0
@@ -489,6 +489,10 @@ svc_destroy(struct svc_serv *serv)if (svc_serv_is_pooled (serv))svc_pool_map_put (); +#if defined(CONFIG_NFS_V4_1 ) +svc_sock_destroy (serv->bc_xprt); +#endif /* CONFIG_NFS_V4_1 */ +svc_unregister (serv);kfree (serv->sv_pools);kfree (serv);
Signature · 1 line
1.6.0.2
RFC 69/85 nfs41: create a svc_xprt for nfs41 callback thread and use for incoming callbacks
In reply to Benny Halevy--- fs/nfs/callback.c | 17 ++++++++++++++++- net/sunrpc/svc.c | 1 + 2 files changed, 17 insertions(+), 1 deletions(-)
fs/nfs/callback.c +16 -1
@@ -179,16 +179,31 @@ nfs41_callback_svc(void *vrqstp)struct svc_rqst *nfs41_callback_up (struct svc_serv *serv,struct rpc_xprt *xprt) { +struct svc_xprt *bc_xprt; +struct svc_rqst *rqstp =ERR_PTR (-ENOMEM ); + +dprintk ("--> %s\n" , __func__); +/* Create a svc_sock for the service */ + bc_xprt =svc_sock_create (serv, xprt->prot); +if (!bc_xprt) + goto out; +/* * Save the svc_serv in the transport so that it can * be referenced when the session backchannel is initialized */ + serv->bc_xprt = bc_xprt; xprt->bc_serv = serv;INIT_LIST_HEAD (&serv->sv_cb_list);spin_lock_init (&serv->sv_cb_lock);init_waitqueue_head (&serv->sv_cb_waitq); -return svc_prepare_thread (serv, &serv->sv_pools[0 ]); + rqstp =svc_prepare_thread (serv, &serv->sv_pools[0 ]); +if (IS_ERR (rqstp)) +svc_sock_destroy (bc_xprt); +out: +dprintk ("--> %s return %p\n" , __func__, rqstp); +return rqstp; }#endif /* CONFIG_NFS_V4_1 */
net/sunrpc/svc.c +1 -0
@@ -1272,6 +1272,7 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,int error;/* Build the svc_rqst used by the common processing routine */ + rqstp->rq_xprt = serv->bc_xprt; rqstp->rq_xid = req->rq_xid; rqstp->rq_prot = req->rq_xprt->prot; rqstp->rq_server = serv;
Signature · 1 line
1.6.0.2
RFC 70/85 nfs41: save svc_serv in nfs_callback_info
In reply to Benny HalevyWe need to pass the svc_serv* to the xprt when nfs_callback_info.users > 0
--- fs/nfs/callback.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
fs/nfs/callback.c +4 -0
@@ -30,6 +30,7 @@struct nfs_callback_data {unsigned int users; +struct svc_serv *serv;struct svc_rqst *rqst;struct task_struct *task; };
@@ -252,6 +253,7 @@ int nfs_callback_up(u32 minorversion, void *args)svc_sock_update_bufs (serv);sprintf (svc_name,"nfsv4.%u-svc" , minorversion); + nfs_callback_info.serv = serv; nfs_callback_info.rqst = rqst; nfs_callback_info.task = kthread_run(callback_svc, nfs_callback_info.rqst,
@@ -259,6 +261,7 @@ int nfs_callback_up(u32 minorversion, void *args)if (IS_ERR (nfs_callback_info.task)) { ret =PTR_ERR (nfs_callback_info.task);svc_exit_thread (nfs_callback_info.rqst); + nfs_callback_info.serv =NULL ; nfs_callback_info.rqst =NULL ; nfs_callback_info.task =NULL ; goto out_err;
@@ -291,6 +294,7 @@ void nfs_callback_down(void)if (nfs_callback_info.users ==0 && nfs_callback_info.task !=NULL ) {kthread_stop (nfs_callback_info.task);svc_exit_thread (nfs_callback_info.rqst); + nfs_callback_info.serv =NULL ; nfs_callback_info.rqst =NULL ; nfs_callback_info.task =NULL ; }
Signature · 1 line
1.6.0.2
RFC 71/85 nfs41: Add a reference to svc_serv during callback service bring up
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
There is only one NFSv4.1 callback service. The first caller of nfs4_callback_up() creates the service, subsequent callers increment a reference count on the service. The service is destroyed when the last caller invokes nfs_callback_down().
The transport needs to hold a reference to the callback service in order to invoke it during callback processing. Currently this reference is only obtained when the service is first created. This is incorrect, since subsequent registrations for other transports will leave the xprt->serv pointer uninitialized, leading to an oops when a callback arrives on the "unreferenced" transport.
This patch fixes the problem by ensuring that a reference to the service is saved in xprt->serv, either because the service is created by this invocation to nfs4_callback_up() or by a prior invocation.
--- fs/nfs/callback.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-)
fs/nfs/callback.c +6 -1
@@ -223,8 +223,13 @@ int nfs_callback_up(u32 minorversion, void *args)#endif /* CONFIG_NFS_V4_1 */ mutex_lock (&nfs_callback_mutex); -if (nfs_callback_info.users++ || nfs_callback_info.task !=NULL ) +if (nfs_callback_info.users++ || nfs_callback_info.task !=NULL ) { +#if defined(CONFIG_NFS_V4_1 ) +if (minorversion) + xprt->bc_serv = nfs_callback_info.serv; +#endif /* CONFIG_NFS_V4_1 */ goto out; + } serv =svc_create (&nfs4_callback_program,NFS4_CALLBACK_BUFSIZE , nfs_callback_family,NULL );if (!serv) {
Signature · 1 line
1.6.0.2
RFC 72/85 nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Tracks the nfs_callback_info for both versions, enabling the callback service for v4 and v4.1 to run concurrently and be stopped independently of each other.
--- fs/nfs/callback.c | 50 ++++++++++++++++++++++++-------------------------- fs/nfs/callback.h | 7 ++----- fs/nfs/client.c | 4 +++- 3 files changed, 29 insertions(+), 32 deletions(-)
fs/nfs/callback.c +24 -26
@@ -35,7 +35,7 @@ struct nfs_callback_data {struct task_struct *task; }; -static struct nfs_callback_data nfs_callback_info; +static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION +1 ];static DEFINE_MUTEX (nfs_callback_mutex);static struct svc_program nfs4_callback_program;
@@ -68,7 +68,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int, &nfs_callback_set_tcpport, 0644);/* -* This is the callback kernel thread. +* This is the NFSv4 callback kernel thread. */ static int nfs4_callback_svc (void *vrqstp)
@@ -169,8 +169,6 @@ nfs41_callback_svc(void *vrqstp)finish_wait (&serv->sv_cb_waitq, &wq); }unlock_kernel (); - nfs_callback_info.task =NULL ; -svc_exit_thread (rqstp);return 0 ; }
@@ -216,6 +214,7 @@ int nfs_callback_up(u32 minorversion, void *args)struct svc_serv *serv =NULL ;struct svc_rqst *rqst;int (* callback_svc)(void *vrqstp); +struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];char svc_name[12 ];int ret =0 ;#if defined(CONFIG_NFS_V4_1 )
@@ -223,10 +222,10 @@ int nfs_callback_up(u32 minorversion, void *args)#endif /* CONFIG_NFS_V4_1 */ mutex_lock (&nfs_callback_mutex); -if (nfs_callback_info.users++ || nfs_callback_info.task !=NULL ) { +if (cb_info->users++ || cb_info->task !=NULL ) {#if defined(CONFIG_NFS_V4_1 )if (minorversion) - xprt->bc_serv = nfs_callback_info.serv; + xprt->bc_serv = cb_info->serv;#endif /* CONFIG_NFS_V4_1 */ goto out; }
@@ -258,17 +257,14 @@ int nfs_callback_up(u32 minorversion, void *args)svc_sock_update_bufs (serv);sprintf (svc_name,"nfsv4.%u-svc" , minorversion); - nfs_callback_info.serv = serv; - nfs_callback_info.rqst = rqst; - nfs_callback_info.task =kthread_run (callback_svc, - nfs_callback_info.rqst, - svc_name); -if (IS_ERR (nfs_callback_info.task)) { - ret =PTR_ERR (nfs_callback_info.task); -svc_exit_thread (nfs_callback_info.rqst); - nfs_callback_info.serv =NULL ; - nfs_callback_info.rqst =NULL ; - nfs_callback_info.task =NULL ; + cb_info->serv = serv; + cb_info->rqst = rqst; + cb_info->task =kthread_run (callback_svc, cb_info->rqst, svc_name); +if (IS_ERR (cb_info->task)) { + ret =PTR_ERR (cb_info->task); +svc_exit_thread (cb_info->rqst); + cb_info->rqst =NULL ; + cb_info->task =NULL ; goto out_err; } out:
@@ -285,23 +281,25 @@ out: out_err:dprintk ("NFS: Couldn't create callback socket or server thread; " "err = %d\n" , ret); - nfs_callback_info.users--; + cb_info->users--; goto out; }/* * Kill the callback thread if it's no longer being used. */ -void nfs_callback_down (void ) +void nfs_callback_down (int minorversion) { +struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; +mutex_lock (&nfs_callback_mutex); - nfs_callback_info.users--; -if (nfs_callback_info.users ==0 && nfs_callback_info.task !=NULL ) { -kthread_stop (nfs_callback_info.task); -svc_exit_thread (nfs_callback_info.rqst); - nfs_callback_info.serv =NULL ; - nfs_callback_info.rqst =NULL ; - nfs_callback_info.task =NULL ; + cb_info->users--; +if (cb_info->users ==0 && cb_info->task !=NULL ) { +kthread_stop (cb_info->task); +svc_exit_thread (cb_info->rqst); + cb_info->serv =NULL ; + cb_info->rqst =NULL ; + cb_info->task =NULL ; }mutex_unlock (&nfs_callback_mutex); }
fs/nfs/callback.h +2 -5
@@ -64,11 +64,8 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);#ifdef CONFIG_NFS_V4 extern int nfs_callback_up (u32 minorversion,void *args); -extern void nfs_callback_down (void ); -#else -#define nfs_callback_up () (0) -#define nfs_callback_down () do {} while(0) -#endif +extern void nfs_callback_down (int minorversion); +#endif /* CONFIG_NFS_V4 */ #ifdef CONFIG_NFS_V4_1 /*
fs/nfs/client.c +3 -1
@@ -193,8 +193,10 @@ static void nfs_free_client(struct nfs_client *clp)if (!IS_ERR (clp->cl_rpcclient))rpc_shutdown_client (clp->cl_rpcclient); +#ifdef CONFIG_NFS_V4 if (__test_and_clear_bit (NFS_CS_CALLBACK , &clp->cl_res_state)) -nfs_callback_down (); +nfs_callback_down (clp->cl_minorversion); +#endif /* CONFIG_NFS_V4 */ if (clp->cl_machine_cred !=NULL )put_rpccred (clp->cl_machine_cred);
Signature · 1 line
1.6.0.2
RFC 73/85 nfs41: Setup the backchannel
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
The NFS v4.1 callback service has already been setup, and rpc_xprt->serv points to the svc_serv structure describing it. Invoke the xprt_setup_backchannel() initialization to pre- allocate the necessary backchannel structures.
--- fs/nfs/client.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
fs/nfs/client.c +8 -1
@@ -39,6 +39,7 @@#include <linux/nfs_xdr.h> #if defined(CONFIG_NFS_V4_1 )#include <linux/nfs41_session_recovery.h> +#include <linux/sunrpc/bc_xprt.h> #endif /* CONFIG_NFS_V4_1 */ #include <asm/system.h>
@@ -1125,7 +1126,7 @@ error: }/* -* Allocate and initialize a session if required +* Allocate and initialize a session if required, including its backchannel. */ int nfs4_init_session (struct nfs_client *clp,struct rpc_clnt *clnt) {
@@ -1145,6 +1146,12 @@ int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt)else { session->clnt = clnt; session->clp = clp; + + error =xprt_setup_backchannel (clnt->cl_xprt, +NFS41_BC_MIN_CALLBACKS ); +if (error <0 ) +/* nfs4_put session sets the session to NULL */ +nfs4_put_session (&session); } clp->cl_session = session; }
Signature · 1 line
1.6.0.2
RFC 74/85 nfs41: Client indicates presence of NFSv4.1 callback channel.
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Set the SESSION4_BACK_CHAN flag to indicate the client supports a backchannel.
--- fs/nfs/nfs4proc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
fs/nfs/nfs4proc.c +1 -1
@@ -4679,7 +4679,7 @@ static int _nfs4_proc_create_session(struct nfs4_session *session)int status;nfs4_init_channel_attrs (clp, &args.fc_attrs, &args.bc_attrs); - args.flags = (SESSION4_PERSIST ); + args.flags = (SESSION4_PERSIST |SESSION4_BACK_CHAN ); status =rpc_call_sync (session->clnt, &msg,0 );
Signature · 1 line
1.6.0.2
RFC 75/85 nfs41: Get the rpc_xprt * from the rpc_rqst instead of the rpc_clnt.
In reply to Benny HalevyFrom: Rahul Iyer <[email protected]>
Obtain the rpc_xprt from the rpc_rqst so that calls and callback replies can both use the same code path. A client needs the rpc_xprt in order to reply to a callback.
--- net/sunrpc/xprt.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
net/sunrpc/xprt.c +2 -2
@@ -164,8 +164,8 @@ EXPORT_SYMBOL_GPL(xprt_unregister_transport);*/ int xprt_reserve_xprt (struct rpc_task *task) { -struct rpc_xprt *xprt = task->tk_xprt;struct rpc_rqst *req = task->tk_rqstp; +struct rpc_xprt *xprt = req->rq_xprt;if (test_and_set_bit (XPRT_LOCKED , &xprt->state)) {if (task == xprt->snd_task)
@@ -837,7 +837,7 @@ out_unlock:void xprt_end_transmit (struct rpc_task *task) { -xprt_release_write (task->tk_xprt, task); +xprt_release_write (task->tk_rqstp->rq_xprt, task); }/**
Signature · 1 line
1.6.0.2
RFC 76/85 nfs41: Release backchannel resources associated with session
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Frees the preallocated backchannel resources that are associated with this session when the session is destroyed.
A backchannel is currently created once per session. Destroy the backchannel only when the session is destroyed.
--- fs/nfs/nfs4proc.c | 6 ++++++ fs/nfs/super.c | 1 - 2 files changed, 6 insertions(+), 1 deletions(-)
fs/nfs/nfs4proc.c +6 -0
@@ -57,6 +57,7 @@#if defined(CONFIG_NFS_V4_1 )#include "callback.h" #include <linux/nfs41_session_recovery.h> +#include <linux/sunrpc/bc_xprt.h> #endif /* CONFIG_NFS_V4_1 */ #define NFSDBG_FACILITY NFSDBG_PROC
@@ -4588,6 +4589,11 @@ void nfs4_put_session(struct nfs4_session **session) {dprintk ("--> nfs4_put_session()\n" );if (atomic_dec_and_test (&((*session)->ref_count))) { +nfs4_proc_destroy_session (*session); +dprintk ("%s Destroy backchannel for xprt%p\n" , + __func__, (*session)->clnt->cl_xprt); +xprt_destroy_backchannel ((*session)->clnt->cl_xprt, +NFS41_BC_MIN_CALLBACKS );nfs4_destroy_slot_table (&((*session)->fore_channel));nfs4_free_session (*session); *session =NULL ;
fs/nfs/super.c +0 -1
@@ -2434,7 +2434,6 @@ static void nfs4_kill_super(struct super_block *sb)dprintk ("--> %s\n" , __func__);nfs_return_all_delegations (sb);kill_anon_super (sb); -nfs4_renewd_prepare_shutdown (server);nfs_free_server (server);dprintk ("<-- %s\n" , __func__);
Signature · 1 line
1.6.0.2
RFC 77/85 nfs41: store minorversion in cb_compound_hdr_arg
In reply to Benny Halevy--- fs/nfs/callback.h | 1 + fs/nfs/callback_xdr.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-)
fs/nfs/callback.h +1 -0
@@ -26,6 +26,7 @@ enum nfs4_callback_opnum {struct cb_compound_hdr_arg {unsigned int taglen;const char *tag; +unsigned int minorversion;unsigned int callback_ident;unsigned nops; };
fs/nfs/callback_xdr.c +7 -5
@@ -132,7 +132,6 @@ static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)static __be32 decode_compound_hdr_arg (struct xdr_stream *xdr,struct cb_compound_hdr_arg *hdr) {__be32 *p; -unsigned int minor_version;__be32 status; status =decode_string (xdr, &hdr->taglen, &hdr->tag);
@@ -147,15 +146,18 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound p =read_buf (xdr,12 );if (unlikely (p ==NULL ))return htonl (NFS4ERR_RESOURCE ); - minor_version =ntohl (*p++); + hdr->minorversion =ntohl (*p++);/* Check minor version is zero. */ -if (minor_version !=0 ) { -printk (KERN_WARNING "%s: NFSv4 server callback with illegal minor version %u!\n" , - __func__, minor_version); +if (hdr->minorversion !=0 ) { +printk (KERN_WARNING "%s: NFSv4 server callback with " +"illegal minor version %u!\n" , + __func__, hdr->minorversion);return htonl (NFS4ERR_MINOR_VERS_MISMATCH ); } hdr->callback_ident =ntohl (*p++); hdr->nops =ntohl (*p); +dprintk ("%s: minorversion %d nops %d\n" , __func__, + hdr->minorversion, hdr->nops);return 0 ; }
Signature · 1 line
1.6.0.2
RFC 78/85 nfs41: decode minorversion 1 cb_compound header
In reply to Benny Halevydecode cb_compound header conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Get rid of cb_compound_hdr_arg.callback_ident
callback_ident is not used anywhere so we shouldn't waste any memory to store it.
--- fs/nfs/callback.h | 1 - fs/nfs/callback_xdr.c | 12 ++++++++---- 2 files changed, 8 insertions(+), 5 deletions(-)
fs/nfs/callback.h +0 -1
@@ -27,7 +27,6 @@ struct cb_compound_hdr_arg {unsigned int taglen;const char *tag;unsigned int minorversion; -unsigned int callback_ident;unsigned nops; };
fs/nfs/callback_xdr.c +8 -4
@@ -143,18 +143,22 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound __func__, hdr->taglen);return htonl (NFS4ERR_RESOURCE ); } - p =read_buf (xdr,12 ); + p =read_buf (xdr,4 );if (unlikely (p ==NULL ))return htonl (NFS4ERR_RESOURCE ); hdr->minorversion =ntohl (*p++); -/* Check minor version is zero. */ -if (hdr->minorversion !=0 ) { +/* Check minor version is zero or one. */ +if (hdr->minorversion <=1 ) { + p =read_buf (xdr,8 ); +if (unlikely (p ==NULL )) +return htonl (NFS4ERR_RESOURCE ); + p++;/* skip callback_ident */ + }else {printk (KERN_WARNING "%s: NFSv4 server callback with " "illegal minor version %u!\n" , __func__, hdr->minorversion);return htonl (NFS4ERR_MINOR_VERS_MISMATCH ); } - hdr->callback_ident =ntohl (*p++); hdr->nops =ntohl (*p);dprintk ("%s: minorversion %d nops %d\n" , __func__, hdr->minorversion, hdr->nops);
Signature · 1 line
1.6.0.2
RFC 79/85 nfs41: callback numbers definitions
In reply to Benny Halevy--- fs/nfs/callback.h | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
fs/nfs/callback.h +10 -0
@@ -20,6 +20,16 @@ enum nfs4_callback_procnum {enum nfs4_callback_opnum {OP_CB_GETATTR =3 ,OP_CB_RECALL =4 , +/* Callback operations new to NFSv4.1 */ +OP_CB_LAYOUTRECALL =5 , +OP_CB_NOTIFY =6 , +OP_CB_PUSH_DELEG =7 , +OP_CB_RECALL_ANY =8 , +OP_CB_RECALLABLE_OBJ_AVAIL =9 , +OP_CB_RECALL_SLOT =10 , +OP_CB_SEQUENCE =11 , +OP_CB_WANTS_CANCELLED =12 , +OP_CB_NOTIFY_LOCK =13 ,OP_CB_ILLEGAL =10044 , };
Signature · 1 line
1.6.0.2
RFC 80/85 nfs41: consider minorversion in callback_xdr:process_op
In reply to Benny Halevy--- fs/nfs/callback_xdr.c | 63 ++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 50 insertions(+), 13 deletions(-)
fs/nfs/callback_xdr.c +50 -13
@@ -359,31 +359,61 @@ out:return status; } -static __be32 process_op (struct svc_rqst *rqstp, +static __be32 process_op (uint32_t minorversion,int nop, +struct svc_rqst *rqstp,struct xdr_stream *xdr_in,void *argp,struct xdr_stream *xdr_out,void *resp) {struct callback_op *op = &callback_ops[0 ];unsigned int op_nr =OP_CB_ILLEGAL ; -__be32 status =0 ; +__be32 status;long maxlen;__be32 res;dprintk ("%s: start\n" , __func__); status =decode_op_hdr (xdr_in, &op_nr); -if (likely (status ==0 )) { +if (unlikely (status)) + goto out_illegal; + +dprintk ("%s: minorversion=%d nop=%d op_nr=%u\n" , + __func__, minorversion, nop, op_nr); +#if defined(CONFIG_NFS_V4_1 ) +if (minorversion ==1 ) {switch (op_nr) { -case OP_CB_GETATTR : -case OP_CB_RECALL : - op = &callback_ops[op_nr]; -break ; -default : - op_nr =OP_CB_ILLEGAL ; - op = &callback_ops[0 ]; - status =htonl (NFS4ERR_OP_ILLEGAL ); +case OP_CB_GETATTR : +case OP_CB_RECALL : + op = &callback_ops[op_nr]; +break ; + +case OP_CB_LAYOUTRECALL : +case OP_CB_NOTIFY : +case OP_CB_PUSH_DELEG : +case OP_CB_RECALL_ANY : +case OP_CB_RECALLABLE_OBJ_AVAIL : +case OP_CB_RECALL_SLOT : +case OP_CB_SEQUENCE : +case OP_CB_WANTS_CANCELLED : +case OP_CB_NOTIFY_LOCK : + op = &callback_ops[0 ]; + status =htonl (NFS4ERR_NOTSUPP ); +break ; +default : + goto out_illegal; } - } + goto out; + } +#endif /* defined(CONFIG_NFS_V4_1) */ + +switch (op_nr) { +case OP_CB_GETATTR : +case OP_CB_RECALL : + op = &callback_ops[op_nr]; +break ; +default : + goto out_illegal; + } +out: maxlen = xdr_out->end - xdr_out->p;if (maxlen >0 && maxlen <PAGE_SIZE ) {if (likely (status ==0 && op->decode_args !=NULL ))
@@ -400,6 +430,12 @@ static __be32 process_op(struct svc_rqst *rqstp, status = op->encode_res (rqstp, xdr_out, resp);dprintk ("%s: done, status = %d\n" , __func__,ntohl (status));return status; + +out_illegal: + op_nr =OP_CB_ILLEGAL ; + op = &callback_ops[0 ]; + status =htonl (NFS4ERR_OP_ILLEGAL ); + goto out; }/*
@@ -431,7 +467,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *rreturn rpc_system_err;while (status ==0 && nops != hdr_arg.nops) { - status =process_op (rqstp, &xdr_in, argp, &xdr_out, resp); + status =process_op (hdr_arg.minorversion, nops, + rqstp, &xdr_in, argp, &xdr_out, resp); nops++; }
Signature · 1 line
1.6.0.2
RFC 81/85 nfs41: define CB_NOTIFY_DEVICEID as not supported
In reply to Benny HalevyFrom: Ricardo Labiaga <[email protected]>
Need to return NFS4ERR_NOTSUPP for CB_NOTIFY_DEVICEID rather than NFS4ERR_OP_ILLEGAL.
--- fs/nfs/callback.h | 1 + fs/nfs/callback_xdr.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-)
fs/nfs/callback.h +1 -0
@@ -30,6 +30,7 @@ enum nfs4_callback_opnum {OP_CB_SEQUENCE =11 ,OP_CB_WANTS_CANCELLED =12 ,OP_CB_NOTIFY_LOCK =13 , +OP_CB_NOTIFY_DEVICEID =14 , OP_CB_ILLEGAL = 10044, };
fs/nfs/callback_xdr.c +1 -0
@@ -394,6 +394,7 @@ static __be32 process_op(uint32_t minorversion, int nop,case OP_CB_SEQUENCE :case OP_CB_WANTS_CANCELLED :case OP_CB_NOTIFY_LOCK : +case OP_CB_NOTIFY_DEVICEID : op = &callback_ops[0 ]; status =htonl (NFS4ERR_NOTSUPP );break ;
Signature · 1 line
1.6.0.2
RFC 82/85 nfs41: cb_sequence protocol level data structures
In reply to Benny Halevy--- fs/nfs/callback.h | 35 +++++++++++++++++++++++++++++++++++ 1 files changed, 35 insertions(+), 0 deletions(-)
fs/nfs/callback.h +35 -0
@@ -70,6 +70,41 @@ struct cb_recallargs {uint32_t truncate; }; +#if defined(CONFIG_NFS_V4_1 ) + +struct referring_call { +uint32_t rc_sequenceid; +uint32_t rc_slotid; +}; + +struct referring_call_list { +nfs41_sessionid rcl_sessionid; +uint32_t rcl_nrefcalls; +struct referring_call *rcl_refcalls; +}; + +struct cb_sequenceargs { +struct sockaddr_in *csa_addr; +nfs41_sessionid csa_sessionid; +uint32_t csa_sequenceid; +uint32_t csa_slotid; +uint32_t csa_highestslotid; +uint32_t csa_cachethis; +uint32_t csa_nrclists; +struct referring_call_list *csa_rclists; +}; + +struct cb_sequenceres { +uint32_t csr_status; +nfs41_sessionid csr_sessionid; +uint32_t csr_sequenceid; +uint32_t csr_slotid; +uint32_t csr_highestslotid; +uint32_t csr_target_highestslotid; +}; + +#endif /* CONFIG_NFS_V4_1 */ +extern __be32 nfs4_callback_getattr (struct cb_getattrargs *args,struct cb_getattrres *res);extern __be32 nfs4_callback_recall (struct cb_recallargs *args,void *dummy);
Signature · 1 line
1.6.0.2
RFC 83/85 nfs41: cb_sequence proc implementation
In reply to Benny HalevyCurrently, just free up any referring calls information.
--- fs/nfs/callback.h | 4 ++++ fs/nfs/callback_proc.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 0 deletions(-)
fs/nfs/callback.h +4 -0
@@ -119,6 +119,10 @@ extern void nfs_callback_down(int minorversion);* so we limit their concurrency to 1. */ #define NFS41_BC_MIN_CALLBACKS 1 +#define NFS41_BC_MAX_CALLBACKS 1 + +extern unsigned nfs4_callback_sequence (struct cb_sequenceargs *args, +struct cb_sequenceres *res);#endif /* CONFIG_NFS_V4_1 */ extern unsigned int nfs_callback_set_tcpport;
fs/nfs/callback_proc.c +30 -0
@@ -101,3 +101,33 @@ out:dprintk ("%s: exit with status = %d\n" , __func__,ntohl (res));return res; } + +#if defined(CONFIG_NFS_V4_1 ) + +/* FIXME: validate args->cbs_{sequence,slot}id */ +/* FIXME: referring calls should be processed */ +unsigned nfs4_callback_sequence (struct cb_sequenceargs *args, +struct cb_sequenceres *res) +{ +int i; +unsigned status =0 ; + +for (i =0 ; i < args->csa_nrclists; i++) +kfree (args->csa_rclists[i].rcl_refcalls); +kfree (args->csa_rclists); + +memcpy (&res->csr_sessionid, &args->csa_sessionid, +sizeof (res->csr_sessionid)); + res->csr_sequenceid = args->csa_sequenceid; + res->csr_slotid = args->csa_slotid; + res->csr_highestslotid =NFS41_BC_MAX_CALLBACKS ; +if (res->csr_highestslotid > args->csa_highestslotid) + res->csr_highestslotid = args->csa_highestslotid; + res->csr_target_highestslotid =NFS41_BC_MAX_CALLBACKS ; + +dprintk ("%s: exit with status = %d\n" , __func__,ntohl (status)); + res->csr_status = status; +return status; +} + +#endif /* CONFIG_NFS_V4_1 */
Signature · 1 line
1.6.0.2
RFC 84/85 nfs41: cb_sequence xdr implementation
In reply to Benny Halevy--- fs/nfs/callback_xdr.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 189 insertions(+), 2 deletions(-)
fs/nfs/callback_xdr.c +189 -2
@@ -20,8 +20,28 @@ 2 + 2 + 3 + 3)#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ) +#if defined(CONFIG_NFS_V4_1 ) +#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \ + 4 + 1 + 3) +#endif /* CONFIG_NFS_V4_1 */ +#define NFSDBG_FACILITY NFSDBG_CALLBACK +#define READ64 (x) do { \ + (x) = (u64)ntohl(*p++) << 32; \ + (x) |= ntohl(*p++); \ +} while (0) + +#define READMEM (x,nbytes) do { \ + x = (char *)p; \ + p += XDR_QUADLEN(nbytes); \ +} while (0) + +#define COPYMEM (x,nbytes) do { \ + memcpy((x), p, nbytes); \ + p += XDR_QUADLEN(nbytes); \ +} while (0) +typedef __be32 (*callback_process_op_t )(void *,void *);typedef __be32 (*callback_decode_arg_t )(struct svc_rqst *,struct xdr_stream *,void *);typedef __be32 (*callback_encode_res_t )(struct svc_rqst *,struct xdr_stream *,void *);
@@ -210,6 +230,122 @@ out:return status; } +#if defined(CONFIG_NFS_V4_1 ) + +static unsigned decode_sessionid (struct xdr_stream *xdr, +nfs41_sessionid *sid) +{ +uint32_t *p; +int len =16 ; + + p =read_buf (xdr, len); +if (unlikely (p ==NULL )) +return htonl (NFS4ERR_RESOURCE );; + +memcpy (sid, p, len); +return 0 ; +} + +static unsigned decode_rc_list (struct xdr_stream *xdr, +struct referring_call_list *rc_list) +{ +uint32_t *p; +int i; +unsigned status; + + status =decode_sessionid (xdr, &rc_list->rcl_sessionid); +if (status) + goto out; + + status =htonl (NFS4ERR_RESOURCE ); + p =read_buf (xdr,sizeof (uint32_t )); +if (unlikely (p ==NULL )) + goto out; + + rc_list->rcl_nrefcalls =ntohl (*p++); +if (rc_list->rcl_nrefcalls) { + p =read_buf (xdr, + rc_list->rcl_nrefcalls *2 *sizeof (uint32_t )); +if (unlikely (p ==NULL )) + goto out; + rc_list->rcl_refcalls =kmalloc (rc_list->rcl_nrefcalls * +sizeof (*rc_list->rcl_refcalls), +GFP_KERNEL ); +if (unlikely (rc_list->rcl_refcalls ==NULL )) + goto out; +for (i =0 ; i < rc_list->rcl_nrefcalls; i++) { + rc_list->rcl_refcalls[i].rc_sequenceid =ntohl (*p++); + rc_list->rcl_refcalls[i].rc_slotid =ntohl (*p++); + } + } + status =0 ; + +out: +return status; +} + +static unsigned decode_cb_sequence_args (struct svc_rqst *rqstp, +struct xdr_stream *xdr, +struct cb_sequenceargs *args) +{ +uint32_t *p; +int i; +unsigned status; + + status =decode_sessionid (xdr, &args->csa_sessionid); +if (status) + goto out; + + status =htonl (NFS4ERR_RESOURCE ); + p =read_buf (xdr,5 *sizeof (uint32_t )); +if (unlikely (p ==NULL )) + goto out; + + args->csa_addr =svc_addr_in (rqstp); + args->csa_sequenceid =ntohl (*p++); + args->csa_slotid =ntohl (*p++); + args->csa_highestslotid =ntohl (*p++); + args->csa_cachethis =ntohl (*p++); + args->csa_nrclists =ntohl (*p++); + args->csa_rclists =NULL ; +if (args->csa_nrclists) { + args->csa_rclists =kmalloc (args->csa_nrclists * +sizeof (*args->csa_rclists), +GFP_KERNEL ); +if (unlikely (args->csa_rclists ==NULL )) + goto out; + +for (i =0 ; i < args->csa_nrclists; i++) { + status =decode_rc_list (xdr, &args->csa_rclists[i]); +if (status) + goto out_free; + } + } + status =0 ; + +dprintk ("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u " +"highestslotid %u cachethis %d nrclists %u\n" , + __func__, + ((u32 *)&args->csa_sessionid)[0 ], + ((u32 *)&args->csa_sessionid)[1 ], + ((u32 *)&args->csa_sessionid)[2 ], + ((u32 *)&args->csa_sessionid)[3 ], + args->csa_sequenceid, args->csa_slotid, + args->csa_highestslotid, args->csa_cachethis, + args->csa_nrclists); +out: +dprintk ("%s: exit with status = %d\n" , __func__,ntohl (status)); +return status; + +out_free: +for (i =0 ; i < args->csa_nrclists; i++) +kfree (args->csa_rclists[i].rcl_refcalls); +kfree (args->csa_rclists); + goto out; +} + +#endif /* CONFIG_NFS_V4_1 */ +static __be32 encode_string (struct xdr_stream *xdr,unsigned int len,const char *str) {__be32 *p;
@@ -359,6 +495,49 @@ out:return status; } +#if defined(CONFIG_NFS_V4_1 ) + +static unsigned encode_sessionid (struct xdr_stream *xdr, +const nfs41_sessionid *sid) +{ +uint32_t *p; +int len =4 *sizeof (uint32_t ); + + p =xdr_reserve_space (xdr, len); +if (unlikely (p ==NULL )) +return htonl (NFS4ERR_RESOURCE ); + +memcpy (p, sid, len); +return 0 ; +} + +static unsigned encode_cb_sequence_res (struct svc_rqst *rqstp, +struct xdr_stream *xdr, +const struct cb_sequenceres *res) +{ +uint32_t *p; +unsigned status = res->csr_status; + +if (unlikely (status !=0 )) + goto out; + +encode_sessionid (xdr, &res->csr_sessionid); + + p =xdr_reserve_space (xdr,4 *sizeof (uint32_t )); +if (unlikely (p ==NULL )) +return htonl (NFS4ERR_RESOURCE ); + + *p++ =htonl (res->csr_sequenceid); + *p++ =htonl (res->csr_slotid); + *p++ =htonl (res->csr_highestslotid); + *p++ =htonl (res->csr_target_highestslotid); +out: +dprintk ("%s: exit with status = %d\n" , __func__,ntohl (status)); +return status; +} + +#endif /* CONFIG_NFS_V4_1 */ + static __be32 process_op(uint32_t minorversion, int nop, struct svc_rqst *rqstp, struct xdr_stream *xdr_in, void *argp,
@@ -382,6 +561,7 @@ static __be32 process_op(uint32_t minorversion, int nop,switch (op_nr) {case OP_CB_GETATTR :case OP_CB_RECALL : +case OP_CB_SEQUENCE : op = &callback_ops[op_nr];break ;
@@ -391,7 +571,6 @@ static __be32 process_op(uint32_t minorversion, int nop,case OP_CB_RECALL_ANY :case OP_CB_RECALLABLE_OBJ_AVAIL :case OP_CB_RECALL_SLOT : -case OP_CB_SEQUENCE :case OP_CB_WANTS_CANCELLED :case OP_CB_NOTIFY_LOCK :case OP_CB_NOTIFY_DEVICEID :
@@ -496,7 +675,15 @@ static struct callback_op callback_ops[] = { .process_op = (callback_process_op_t)nfs4_callback_recall, .decode_args = (callback_decode_arg_t)decode_recall_args, .res_maxsize = CB_OP_RECALL_RES_MAXSZ, - } + }, +#if defined(CONFIG_NFS_V4_1 ) + [OP_CB_SEQUENCE] = { + .process_op = (callback_process_op_t)nfs4_callback_sequence, + .decode_args = (callback_decode_arg_t)decode_cb_sequence_args, + .encode_res = (callback_encode_res_t)encode_cb_sequence_res, + .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ, + }, +#endif /* CONFIG_NFS_V4_1 */ };/*
Signature · 1 line
1.6.0.2
RFC 85/85 nfs41: verify CB_SEQUENCE position in callback compound
In reply to Benny HalevyCB_SEQUENCE must appear first in the callback compound RPC. If it is not the first operation NFS4ERR_SEQUENCE_POS must be returned. If the first operation ni the CB_COMPOUND is not CB_SEQUENCE then NFS4ERR_OP_NOT_IN_SESSION must be returned.
--- fs/nfs/callback_xdr.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
fs/nfs/callback_xdr.c +8 -0
@@ -558,6 +558,14 @@ static __be32 process_op(uint32_t minorversion, int nop, __func__, minorversion, nop, op_nr);#if defined(CONFIG_NFS_V4_1 )if (minorversion ==1 ) { +if (op_nr ==OP_CB_SEQUENCE ) { +if (nop !=0 ) { + status =htonl (NFS4ERR_SEQUENCE_POS ); + goto out; + } + }else if (nop ==0 ) + status =htonl (NFS4ERR_OP_NOT_IN_SESSION ); +switch (op_nr) {case OP_CB_GETATTR :case OP_CB_RECALL :
Signature · 1 line
1.6.0.2
The patchset is also available ongit://linux-nfs.org/~bhalevy/linux-pnfs.git nfs41-2.6.28-review
Cumulated diff for the client side changes:
Benny
Quoted 125 lines · Benny Halevy
Trond,
Here's the patch series for nfs41 client side, rebased over 2.6.28 for review.
I've cleaned up the patch as much as I could in the given time frame but surely there's more work to be done.
I encourage others to comment on the patches as well.
Thanks,
Benny
pre-nfs41 patches:
[RFC 01/85] sunrpc: get rid of rpc_rqst.rq_bufsize
[RFC 02/85] nfs: return compound hdr.status when there are no op replies [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routinegeneral defs:
[RFC 05/85] nfs41: AddKconfigsymbols for NFSv4.1
[RFC 06/85] nfs41: common protocol definitions
[RFC 07/85] nfs41: defineNFS4_MAX_MINOR_VERSIONbased onCONFIG_NFS_V4_1[RFC 08/85] nfs41: client xdr definitionsbasic support for minorversion != 0:
[RFC 09/85] nfs41: add mount command option minorvers
[RFC 10/85] nfs41: structnfs_serverminorversion
[RFC 11/85] nfs41: nfs_client.cl_minorversion
[RFC 12/85] nfs41: setnfs_clientrpc_opsbased on minorversion
[RFC 13/85] nfs41: use ptr to rpc procedures via structnfs_client
[RFC 14/85] nfs41: sunrpc: support minorversion forrpc_clntversion table. [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops
[RFC 16/85] nfs41: pass recovery status from reclaimer kthread up tonfs4_wait_clnt_recover[RFC 17/85] nfs41: fallback to lower minorversion ifnfs4_create_serverfailssessions basic functionality:
[RFC 18/85] nfs41: sessions client infrastructure [RFC 19/85] nfs41: share client sessions across mounts [RFC 20/85] nfs41: slot table init and destroy [RFC 21/85] nfs41: find slot
[RFC 22/85] nfs41: free slotsupport for sequence for legacy ops:
[RFC 23/85] nfs41: minorversion support for xdr [RFC 24/85] nfs41: stubs for nfs41 procedures [RFC 25/85] nfs41: makenfs4_wait_bit_killablepublic [RFC 26/85] nfs41: introducenfs4_call_sync[RFC 27/85] nfs41:nfs4_setup_sequence
[RFC 28/85] nfs41:setup_sequencemethod
[RFC 29/85] nfs41:nfs41_sequence_done
[RFC 30/85] nfs41:nfs41_call_sync_done
[RFC 31/85] nfs41: separate free slot from sequence done [RFC 32/85] nfs41: sequence setup/done support [RFC 33/85] nfs41: Support sessions withO_DIRECT.nfs41 ops:
[RFC 34/85] nfs41:exchange_idoperation
[RFC 35/85] nfs41:get_lease_time
[RFC 36/85] nfs41:create_sessionoperation
[RFC 37/85] nfs41:destroy_sessionoperation
[RFC 38/85] nfs41: sequence operationsession setup and recovery:
[RFC 39/85] nfs41: session recovery infrastructure
[RFC 40/85] nfs41: schedule async session reset
[RFC 41/85] nfs41: lease renewal
[RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset [RFC 43/85] nfs41: use rpc prepare call state for session reset [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors [RFC 45/85] nfs41: start session recovery fromnfs4_setup_sequence[RFC 46/85] nfs41: introduceget_state_renewal_cred
[RFC 47/85] nfs41: get cred inexchange_idwhen cred arg is NULL [RFC 48/85] nfs41: establish sessions-based clientid
[RFC 49/85] nfs41: recover lease in_nfs4_lookup_root
[RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session [RFC 51/85] nfs41: state reclaimer renew lease error handling [RFC 52/85] nfs41: increment_{open,lock}_seqidbackchannel:
[RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream. [RFC 54/85] nfs41: Skip past the RPC call direction
[RFC 55/85] nfs41: Refactor NFSv4 callback service
[RFC 56/85] nfs41: client callback structures
[RFC 57/85] nfs41: Initialize newrpc_xprtcallback related fields [RFC 58/85] nfs41: New backchannel helper routines
[RFC 59/85] nfs41: Newinclude/linux/sunrpc/bc_xprt.h
[RFC 60/85] nfs41: Newxs_tcp_read_data()
[RFC 61/85] nfs41: Add backchannel processing support to RPC state machine [RFC 62/85] nfs41: Backchannel callback service helper routines [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL incall_statuscallback service:
[RFC 64/85] nfs41: Refactorsvc_process()
[RFC 65/85] nfs41: Backchannelbc_svc_process()
[RFC 66/85] nfs41: Implement NFSv4.1 callback service process.
[RFC 67/85] nfs41: sunrpc: provide functions to create and destroy asvc_xprtfor backchannel use [RFC 68/85] nfs41: sunrpc: add a structsvc_xprtpointer to structsvc_servfor backchannel use [RFC 69/85] nfs41: create asvc_xprtfor nfs41 callback thread and use for incoming callbacks [RFC 70/85] nfs41: savesvc_servinnfs_callback_info
[RFC 71/85] nfs41: Add a reference tosvc_servduring callback service bring up [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
[RFC 73/85] nfs41: Setup the backchannel
[RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel.
[RFC 75/85] nfs41: Get therpc_xprt* from therpc_rqstinstead of therpc_clnt. [RFC 76/85] nfs41: Release backchannel resources associated with sessioncallback processing:
[RFC 77/85] nfs41: store minorversion incb_compound_hdr_arg[RFC 78/85] nfs41: decode minorversion 1cb_compoundheader [RFC 79/85] nfs41: callback numbers definitions
[RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op [RFC 81/85] nfs41: defineCB_NOTIFY_DEVICEIDas not supported [RFC 82/85] nfs41:cb_sequenceprotocol level data structures [RFC 83/85] nfs41:cb_sequenceproc implementation
[RFC 84/85] nfs41:cb_sequencexdr implementation
[RFC 85/85] nfs41: verifyCB_SEQUENCEposition in callback compound
_______________________________________________
pNFS mailing list
[email protected]
http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
Quoted 9 lines · Benny Halevy
Trond,
Here's the patch series for nfs41 client side, rebased over 2.6.28 for review.
I've cleaned up the patch as much as I could in the given time frame but surely there's more work to be done.
I encourage others to comment on the patches as well.
Yipes! Well, no shortage of reading material now....
--b.
Quoted 116 lines
Thanks,
Benny
pre-nfs41 patches:
[RFC 01/85] sunrpc: get rid of rpc_rqst.rq_bufsize
[RFC 02/85] nfs: return compound hdr.status when there are no op replies [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routinegeneral defs:
[RFC 05/85] nfs41: AddKconfigsymbols for NFSv4.1
[RFC 06/85] nfs41: common protocol definitions
[RFC 07/85] nfs41: defineNFS4_MAX_MINOR_VERSIONbased onCONFIG_NFS_V4_1[RFC 08/85] nfs41: client xdr definitionsbasic support for minorversion != 0:
[RFC 09/85] nfs41: add mount command option minorvers
[RFC 10/85] nfs41: structnfs_serverminorversion
[RFC 11/85] nfs41: nfs_client.cl_minorversion
[RFC 12/85] nfs41: setnfs_clientrpc_opsbased on minorversion
[RFC 13/85] nfs41: use ptr to rpc procedures via structnfs_client
[RFC 14/85] nfs41: sunrpc: support minorversion forrpc_clntversion table. [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops
[RFC 16/85] nfs41: pass recovery status from reclaimer kthread up tonfs4_wait_clnt_recover[RFC 17/85] nfs41: fallback to lower minorversion ifnfs4_create_serverfailssessions basic functionality:
[RFC 18/85] nfs41: sessions client infrastructure [RFC 19/85] nfs41: share client sessions across mounts [RFC 20/85] nfs41: slot table init and destroy [RFC 21/85] nfs41: find slot
[RFC 22/85] nfs41: free slotsupport for sequence for legacy ops:
[RFC 23/85] nfs41: minorversion support for xdr [RFC 24/85] nfs41: stubs for nfs41 procedures [RFC 25/85] nfs41: makenfs4_wait_bit_killablepublic [RFC 26/85] nfs41: introducenfs4_call_sync[RFC 27/85] nfs41:nfs4_setup_sequence
[RFC 28/85] nfs41:setup_sequencemethod
[RFC 29/85] nfs41:nfs41_sequence_done
[RFC 30/85] nfs41:nfs41_call_sync_done
[RFC 31/85] nfs41: separate free slot from sequence done [RFC 32/85] nfs41: sequence setup/done support [RFC 33/85] nfs41: Support sessions withO_DIRECT.nfs41 ops:
[RFC 34/85] nfs41:exchange_idoperation
[RFC 35/85] nfs41:get_lease_time
[RFC 36/85] nfs41:create_sessionoperation
[RFC 37/85] nfs41:destroy_sessionoperation
[RFC 38/85] nfs41: sequence operationsession setup and recovery:
[RFC 39/85] nfs41: session recovery infrastructure
[RFC 40/85] nfs41: schedule async session reset
[RFC 41/85] nfs41: lease renewal
[RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset [RFC 43/85] nfs41: use rpc prepare call state for session reset [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors [RFC 45/85] nfs41: start session recovery fromnfs4_setup_sequence[RFC 46/85] nfs41: introduceget_state_renewal_cred
[RFC 47/85] nfs41: get cred inexchange_idwhen cred arg is NULL [RFC 48/85] nfs41: establish sessions-based clientid
[RFC 49/85] nfs41: recover lease in_nfs4_lookup_root
[RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session [RFC 51/85] nfs41: state reclaimer renew lease error handling [RFC 52/85] nfs41: increment_{open,lock}_seqidbackchannel:
[RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream. [RFC 54/85] nfs41: Skip past the RPC call direction
[RFC 55/85] nfs41: Refactor NFSv4 callback service
[RFC 56/85] nfs41: client callback structures
[RFC 57/85] nfs41: Initialize newrpc_xprtcallback related fields [RFC 58/85] nfs41: New backchannel helper routines
[RFC 59/85] nfs41: Newinclude/linux/sunrpc/bc_xprt.h
[RFC 60/85] nfs41: Newxs_tcp_read_data()
[RFC 61/85] nfs41: Add backchannel processing support to RPC state machine [RFC 62/85] nfs41: Backchannel callback service helper routines [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL incall_statuscallback service:
[RFC 64/85] nfs41: Refactorsvc_process()
[RFC 65/85] nfs41: Backchannelbc_svc_process()
[RFC 66/85] nfs41: Implement NFSv4.1 callback service process.
[RFC 67/85] nfs41: sunrpc: provide functions to create and destroy asvc_xprtfor backchannel use [RFC 68/85] nfs41: sunrpc: add a structsvc_xprtpointer to structsvc_servfor backchannel use [RFC 69/85] nfs41: create asvc_xprtfor nfs41 callback thread and use for incoming callbacks [RFC 70/85] nfs41: savesvc_servinnfs_callback_info
[RFC 71/85] nfs41: Add a reference tosvc_servduring callback service bring up [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
[RFC 73/85] nfs41: Setup the backchannel
[RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel.
[RFC 75/85] nfs41: Get therpc_xprt* from therpc_rqstinstead of therpc_clnt. [RFC 76/85] nfs41: Release backchannel resources associated with sessioncallback processing:
[RFC 77/85] nfs41: store minorversion incb_compound_hdr_arg[RFC 78/85] nfs41: decode minorversion 1cb_compoundheader [RFC 79/85] nfs41: callback numbers definitions
[RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op [RFC 81/85] nfs41: defineCB_NOTIFY_DEVICEIDas not supported [RFC 82/85] nfs41:cb_sequenceprotocol level data structures [RFC 83/85] nfs41:cb_sequenceproc implementation
[RFC 84/85] nfs41:cb_sequencexdr implementation
[RFC 85/85] nfs41: verifyCB_SEQUENCEposition in callback compound
_______________________________________________
pNFS mailing list
[email protected]
http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
RE: [pnfs] [RFC 43/85] nfs41: use rpc prepare call state for sessionreset
In reply to Benny Halevyhttp://linux-nfs.org/pipermail/pnfs/2008-November/005264.html
from Andy should probably be squashed into this patch.
Benny
________________________________
From: [email protected] on behalf of Benny Halevy
Sent: Mon 2008-11-10 22:25
To: [email protected]
Cc: [email protected]; [email protected]
Subject: [pnfs] [RFC 43/85] nfs41: use rpc prepare call state for sessionreset
From: Andy Adamson <[email protected]>
--- fs/nfs/internal.h | 4 ++++ fs/nfs/nfs4proc.c | 22 +++++++++++++++++----- fs/nfs/read.c | 2 +- fs/nfs/unlink.c | 2 +- fs/nfs/write.c | 2 +- 5 files changed, 24 insertions(+), 8 deletions(-)
fs/nfs/internal.h +4 -0
@@ -130,6 +130,10 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);extern struct rpc_procinfo nfs3_procedures[];extern __be32 *nfs3_decode_dirent (__be32 *,struct nfs_entry *,int ); +/* nfs4proc.c */ +extern void nfs4_restart_rpc (struct rpc_task *task, +const struct nfs_server *server); +/* nfs4xdr.c */ #ifdef CONFIG_NFS_V4 extern __be32 *nfs4_decode_dirent (__be32 *p,struct nfs_entry *entry,int plus);
fs/nfs/nfs4proc.c +17 -5
@@ -593,6 +593,18 @@ static void nfs4_sequence_done(const struct nfs_server *server,#endif /* CONFIG_NFS_V4_1 */ } +void nfs4_restart_rpc (struct rpc_task *task,const struct nfs_server *server) +{ +#ifdef CONFIG_NFS_V4_1 +if (server->nfs_client->cl_minorversion && +nfs41_test_session_reset (server->nfs_client->cl_session)) { +rpc_restart_call_prepare (task); +return ; + } +#endif /* CONFIG_NFS_V4_1 */ +rpc_restart_call (task); +} +static void update_changeattr (struct inode *dir,struct nfs4_change_info *cinfo) {struct nfs_inode *nfsi =NFS_I (dir);
@@ -1638,7 +1650,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)break ;default :if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);return ; } }
@@ -2871,7 +2883,7 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)/* nfs4_sequence_free_slot called in the read rpc_call_done */ nfs4_sequence_done (server, &data->res.seq_res, task->tk_status);if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);dprintk ("<-- %s status= %d\n" , __func__, -EAGAIN );return -EAGAIN ; }
@@ -2899,7 +2911,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)/* slot is freed in nfs_writeback_done */ nfs4_sequence_done (server, &data->res.seq_res, task->tk_status);if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);return -EAGAIN ; }if (task->tk_status >=0 ) {
@@ -2927,7 +2939,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)nfs4_sequence_done (server, &data->res.seq_res, task->tk_status);if (nfs4_async_handle_error (task, server) == -EAGAIN ) { -rpc_restart_call (task); +nfs4_restart_rpc (task, server);return -EAGAIN ; }nfs4_sequence_free_slot (server, &data->res.seq_res);
@@ -3701,7 +3713,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)break ;default :if (nfs4_async_handle_error (task, server) == -EAGAIN ) -rpc_restart_call (task); +nfs4_restart_rpc (task, server); }nfs4_sequence_free_slot (server, &calldata->res.seq_res); }
fs/nfs/read.c +1 -1
@@ -367,7 +367,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data argp->offset += resp->count; argp->pgbase += resp->count; argp->count -= resp->count; -rpc_restart_call (task); +nfs4_restart_rpc (task,NFS_SERVER (data->inode));return ; out:nfs4_sequence_free_slot (NFS_SERVER (data->inode), &data->res.seq_res);
fs/nfs/unlink.c +1 -1
@@ -83,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)struct inode *dir = data->dir;if (!NFS_PROTO (dir)->unlink_done (task, dir)) -rpc_restart_call (task); +nfs4_restart_rpc (task,NFS_SERVER (dir)); }/**
fs/nfs/write.c +1 -1
@@ -1179,7 +1179,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)*/ argp->stable =NFS_FILE_SYNC ; } -rpc_restart_call (task); +nfs4_restart_rpc (task,NFS_SERVER (data->inode));return -EAGAIN ; }if (time_before (complain, jiffies)) {
--
1.6.0.2
_______________________________________________
pNFS mailing list
[email protected]
http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
Re: [pnfs] [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status
In reply to Benny HalevyQuoted 5 lines · Benny Halevy
3 call sites look at hdr.status before returning success. hdr.status must be zero in this case so there's no point in this.
Currently, hdr.status is correctly processed at
decode_op_hdrtime if the op status cannot be decoded.
review 11-14: send to Trond
Quoted 37 lines
Signed-off-by Benny Halevy <[email protected]>--- fs/nfs/nfs4xdr.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)fs/nfs/nfs4xdr.c +0
-6@@ -4423,8 +4423,6 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf status =decode_putfh (&xdr);if (!status) status =decode_fsinfo (&xdr, fsinfo); -if (!status) - status =nfs4_stat_to_errno (hdr.status);return status; }@@ -4513,8 +4511,6 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p, status =decode_compound_hdr (&xdr, &hdr);if (!status) status =decode_setclientid (&xdr, clp); -if (!status) - status =nfs4_stat_to_errno (hdr.status);return status; }@@ -4535,8 +4531,6 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str status =decode_putrootfh (&xdr);if (!status) status =decode_fsinfo (&xdr, fsinfo); -if (!status) - status =nfs4_stat_to_errno (hdr.status);return status; }
Re: [pnfs] [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine
In reply to Benny HalevyQuoted 11 lines · Benny Halevy
From: Andy Adamson <[email protected]>
FIXME: bhalevy: is this a good opportunity for a cleanup-only patch to fix whitespacing?
Pass in the
compound_hdrand bump the number of operations in each encode_* subroutine so as to allow us to more easily construct new compound statements.Fix tabs, do not fix 'do not use assignment in if condition' warnings.
Signed-off-by Andy Adamson<[email protected]>Signed-off-by Benny Halevy <[email protected]>
review 11-14: andy will submit:
* whitespace clenaup
* status removal
* move nops ptr into compound_hdr
Quoted 1,525 lines
--- fs/nfs/nfs4xdr.c | 630 ++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 401 insertions(+), 229 deletions(-)fs/nfs/nfs4xdr.c +401
-229@@ -578,9 +578,10 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *xdr_encode_opaque (p, str, len); } -static int encode_compound_hdr (struct xdr_stream *xdr,struct compound_hdr *hdr) +static __u32 * +encode_compound_hdr (struct xdr_stream *xdr,struct compound_hdr *hdr) { -__be32 *p; +__be32 *p, *nops;dprintk ("encode_compound: tag=%.*s\n" , (int )hdr->taglen, hdr->tag);BUG_ON (hdr->taglen >NFS4_MAXTAGLEN );@@ -588,8 +589,14 @@ static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)WRITE32 (hdr->taglen);WRITEMEM (hdr->tag, hdr->taglen);WRITE32 (NFS4_MINOR_VERSION ); + nops = p;WRITE32 (hdr->nops); -return 0 ; +return nops; +} + +static inline void encode_nops (__be32 *nops,struct compound_hdr *hdr) +{ + *nops =htonl (hdr->nops); }static void encode_nfs4_verifier (struct xdr_stream *xdr,const nfs4_verifier *verf)@@ -728,18 +735,22 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const sreturn status; } -static int encode_access (struct xdr_stream *xdr,u32 access) +static int +encode_access (struct xdr_stream *xdr,u32 access,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (8 );WRITE32 (OP_ACCESS );WRITE32 (access); - + hdr->nops++; +return 0 ; } -static int encode_close (struct xdr_stream *xdr,const struct nfs_closeargs *arg) +static int +encode_close (struct xdr_stream *xdr,const struct nfs_closeargs *arg, +struct compound_hdr *hdr) {__be32 *p;@@ -747,23 +758,29 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)WRITE32 (OP_CLOSE );WRITE32 (arg->seqid->sequence->counter);WRITEMEM (arg->stateid->data,NFS4_STATEID_SIZE ); + hdr->nops++;return 0 ; } -static int encode_commit (struct xdr_stream *xdr,const struct nfs_writeargs *args) +static int +encode_commit (struct xdr_stream *xdr,const struct nfs_writeargs *args, +struct compound_hdr *hdr) {__be32 *p; -RESERVE_SPACE (16 ); -WRITE32 (OP_COMMIT ); -WRITE64 (args->offset); -WRITE32 (args->count); +RESERVE_SPACE (16 ); +WRITE32 (OP_COMMIT ); +WRITE64 (args->offset); +WRITE32 (args->count); + hdr->nops++; -return 0 ; +return 0 ; } -static int encode_create (struct xdr_stream *xdr,const struct nfs4_create_arg *create) +static int +encode_create (struct xdr_stream *xdr,const struct nfs4_create_arg *create, +struct compound_hdr *hdr) {__be32 *p;@@ -791,11 +808,14 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *cRESERVE_SPACE (4 + create->name->len);WRITE32 (create->name->len);WRITEMEM (create->name->name, create->name->len); + hdr->nops++;return encode_attrs (xdr, create->attrs, create->server); } -static int encode_getattr_one (struct xdr_stream *xdr,uint32_t bitmap) +static int +encode_getattr_one (struct xdr_stream *xdr,uint32_t bitmap, +struct compound_hdr *hdr) {__be32 *p;@@ -803,10 +823,13 @@ static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)WRITE32 (OP_GETATTR );WRITE32 (1 );WRITE32 (bitmap); + hdr->nops++;return 0 ; } -static int encode_getattr_two (struct xdr_stream *xdr,uint32_t bm0,uint32_t bm1) +static int +encode_getattr_two (struct xdr_stream *xdr,uint32_t bm0,uint32_t bm1, +struct compound_hdr *hdr) {__be32 *p;@@ -815,40 +838,51 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1WRITE32 (2 );WRITE32 (bm0);WRITE32 (bm1); + hdr->nops++;return 0 ; } -static int encode_getfattr (struct xdr_stream *xdr,const u32 * bitmask) +static int +encode_getfattr (struct xdr_stream *xdr,const u32 *bitmask, +struct compound_hdr *hdr) {return encode_getattr_two (xdr, bitmask[0 ] & nfs4_fattr_bitmap[0 ], - bitmask[1 ] & nfs4_fattr_bitmap[1 ]); + bitmask[1 ] & nfs4_fattr_bitmap[1 ], hdr); } -static int encode_fsinfo (struct xdr_stream *xdr,const u32 * bitmask) +static int +encode_fsinfo (struct xdr_stream *xdr,const u32 *bitmask, +struct compound_hdr *hdr) {return encode_getattr_two (xdr, bitmask[0 ] & nfs4_fsinfo_bitmap[0 ], - bitmask[1 ] & nfs4_fsinfo_bitmap[1 ]); + bitmask[1 ] & nfs4_fsinfo_bitmap[1 ], hdr); } -static int encode_fs_locations (struct xdr_stream *xdr,const u32 * bitmask) +static int +encode_fs_locations (struct xdr_stream *xdr,const u32 *bitmask, +struct compound_hdr *hdr) {return encode_getattr_two (xdr, bitmask[0 ] & nfs4_fs_locations_bitmap[0 ], - bitmask[1 ] & nfs4_fs_locations_bitmap[1 ]); + bitmask[1 ] & nfs4_fs_locations_bitmap[1 ], + hdr); } -static int encode_getfh (struct xdr_stream *xdr) +static int encode_getfh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_GETFH ); + hdr->nops++;return 0 ; } -static int encode_link (struct xdr_stream *xdr,const struct qstr *name) +static int +encode_link (struct xdr_stream *xdr,const struct qstr *name, +struct compound_hdr *hdr) {__be32 *p;@@ -856,6 +890,7 @@ static int encode_link(struct xdr_stream *xdr, const struct qstr *name)WRITE32 (OP_LINK );WRITE32 (name->len);WRITEMEM (name->name, name->len); + hdr->nops++;return 0 ; }@@ -878,7 +913,9 @@ static inline uint64_t nfs4_lock_length(struct file_lock *fl)* opcode,type,reclaim,offset,length,new_lock_owner = 32 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 */ -static int encode_lock (struct xdr_stream *xdr,const struct nfs_lock_args *args) +static int +encode_lock (struct xdr_stream *xdr,const struct nfs_lock_args *args, +struct compound_hdr *hdr) {__be32 *p;@@ -904,11 +941,14 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)WRITEMEM (args->lock_stateid->data,NFS4_STATEID_SIZE );WRITE32 (args->lock_seqid->sequence->counter); } + hdr->nops++;return 0 ; } -static int encode_lockt (struct xdr_stream *xdr,const struct nfs_lockt_args *args) +static int +encode_lockt (struct xdr_stream *xdr,const struct nfs_lockt_args *args, +struct compound_hdr *hdr) {__be32 *p;@@ -921,11 +961,14 @@ static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *argWRITE32 (16 );WRITEMEM ("lock id:" ,8 );WRITE64 (args->lock_owner.id); + hdr->nops++;return 0 ; } -static int encode_locku (struct xdr_stream *xdr,const struct nfs_locku_args *args) +static int +encode_locku (struct xdr_stream *xdr,const struct nfs_locku_args *args, +struct compound_hdr *hdr) {__be32 *p;@@ -936,11 +979,14 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *argWRITEMEM (args->stateid->data,NFS4_STATEID_SIZE );WRITE64 (args->fl->fl_start);WRITE64 (nfs4_lock_length (args->fl)); + hdr->nops++;return 0 ; } -static int encode_lookup (struct xdr_stream *xdr,const struct qstr *name) +static int +encode_lookup (struct xdr_stream *xdr,const struct qstr *name, +struct compound_hdr *hdr) {int len = name->len;__be32 *p;@@ -949,6 +995,7 @@ static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)WRITE32 (OP_LOOKUP );WRITE32 (len);WRITEMEM (name->name, len); + hdr->nops++;return 0 ; }@@ -1072,7 +1119,9 @@ static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const strucencode_string (xdr, name->len, name->name); } -static int encode_open (struct xdr_stream *xdr,const struct nfs_openargs *arg) +static int +encode_open (struct xdr_stream *xdr,const struct nfs_openargs *arg, +struct compound_hdr *hdr) {encode_openhdr (xdr, arg);encode_opentype (xdr, arg);@@ -1089,10 +1138,14 @@ static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)default :BUG (); } + hdr->nops++;return 0 ; } -static int encode_open_confirm (struct xdr_stream *xdr,const struct nfs_open_confirmargs *arg) +static int +encode_open_confirm (struct xdr_stream *xdr, +const struct nfs_open_confirmargs *arg, +struct compound_hdr *hdr) {__be32 *p;@@ -1100,11 +1153,14 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_conWRITE32 (OP_OPEN_CONFIRM );WRITEMEM (arg->stateid->data,NFS4_STATEID_SIZE );WRITE32 (arg->seqid->sequence->counter); + hdr->nops++;return 0 ; } -static int encode_open_downgrade (struct xdr_stream *xdr,const struct nfs_closeargs *arg) +static int +encode_open_downgrade (struct xdr_stream *xdr,const struct nfs_closeargs *arg, +struct compound_hdr *hdr) {__be32 *p;@@ -1113,11 +1169,13 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeaWRITEMEM (arg->stateid->data,NFS4_STATEID_SIZE );WRITE32 (arg->seqid->sequence->counter);encode_share_access (xdr, arg->open_flags); + hdr->nops++;return 0 ; }static int -encode_putfh (struct xdr_stream *xdr,const struct nfs_fh *fh) +encode_putfh (struct xdr_stream *xdr,const struct nfs_fh *fh, +struct compound_hdr *hdr) {int len = fh->size;__be32 *p;@@ -1126,21 +1184,24 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)WRITE32 (OP_PUTFH );WRITE32 (len);WRITEMEM (fh->data, len); + hdr->nops++;return 0 ; } -static int encode_putrootfh (struct xdr_stream *xdr) +static int encode_putrootfh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_PUTROOTFH ); + hdr->nops++;return 0 ; } -static void encode_stateid (struct xdr_stream *xdr,const struct nfs_open_context *ctx) +static void +encode_stateid (struct xdr_stream *xdr,const struct nfs_open_context *ctx) {nfs4_stateid stateid;__be32 *p;@@ -1153,7 +1214,9 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_contextWRITEMEM (zero_stateid.data,NFS4_STATEID_SIZE ); } -static int encode_read (struct xdr_stream *xdr,const struct nfs_readargs *args) +static int +encode_read (struct xdr_stream *xdr,const struct nfs_readargs *args, +struct compound_hdr *hdr) {__be32 *p;@@ -1165,11 +1228,14 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)RESERVE_SPACE (12 );WRITE64 (args->offset);WRITE32 (args->count); + hdr->nops++;return 0 ; } -static int encode_readdir (struct xdr_stream *xdr,const struct nfs4_readdir_arg *readdir,struct rpc_rqst *req) +static int +encode_readdir (struct xdr_stream *xdr,const struct nfs4_readdir_arg *readdir, +struct rpc_rqst *req,struct compound_hdr *hdr) {uint32_t attrs[2 ] = {FATTR4_WORD0_RDATTR_ERROR |FATTR4_WORD0_FILEID ,@@ -1191,6 +1257,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg attrs[1 ] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID ;WRITE32 (attrs[0 ] & readdir->bitmask[0 ]);WRITE32 (attrs[1 ] & readdir->bitmask[1 ]); + hdr->nops++; dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", __func__, (unsigned long long)readdir->cookie,@@ -1202,17 +1269,22 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_argreturn 0 ; } -static int encode_readlink (struct xdr_stream *xdr,const struct nfs4_readlink *readlink,struct rpc_rqst *req) +static int +encode_readlink (struct xdr_stream *xdr,const struct nfs4_readlink *readlink, +struct rpc_rqst *req,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_READLINK ); + hdr->nops++;return 0 ; } -static int encode_remove (struct xdr_stream *xdr,const struct qstr *name) +static int +encode_remove (struct xdr_stream *xdr,const struct qstr *name, +struct compound_hdr *hdr) {__be32 *p;@@ -1220,11 +1292,14 @@ static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)WRITE32 (OP_REMOVE );WRITE32 (name->len);WRITEMEM (name->name, name->len); + hdr->nops++;return 0 ; } -static int encode_rename (struct xdr_stream *xdr,const struct qstr *oldname,const struct qstr *newname) +static int +encode_rename (struct xdr_stream *xdr,const struct qstr *oldname, +const struct qstr *newname,struct compound_hdr *hdr) {__be32 *p;@@ -1236,34 +1311,40 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, conRESERVE_SPACE (4 + newname->len);WRITE32 (newname->len);WRITEMEM (newname->name, newname->len); + hdr->nops++;return 0 ; } -static int encode_renew (struct xdr_stream *xdr,const struct nfs_client *client_stateid) +static int +encode_renew (struct xdr_stream *xdr,const struct nfs_client *client_stateid, +struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (12 );WRITE32 (OP_RENEW );WRITE64 (client_stateid->cl_clientid); + hdr->nops++;return 0 ; }static int -encode_restorefh (struct xdr_stream *xdr) +encode_restorefh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_RESTOREFH ); + hdr->nops++;return 0 ; }static int -encode_setacl (struct xdr_stream *xdr,struct nfs_setaclargs *arg) +encode_setacl (struct xdr_stream *xdr,struct nfs_setaclargs *arg, +struct compound_hdr *hdr) {__be32 *p;@@ -1278,21 +1359,25 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)RESERVE_SPACE (4 );WRITE32 (arg->acl_len);xdr_write_pages (xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); + hdr->nops++;return 0 ; }static int -encode_savefh (struct xdr_stream *xdr) +encode_savefh (struct xdr_stream *xdr,struct compound_hdr *hdr) {__be32 *p;RESERVE_SPACE (4 );WRITE32 (OP_SAVEFH ); + hdr->nops++;return 0 ; } -static int encode_setattr (struct xdr_stream *xdr,const struct nfs_setattrargs *arg,const struct nfs_server *server) +static int +encode_setattr (struct xdr_stream *xdr,const struct nfs_setattrargs *arg, +const struct nfs_server *server,struct compound_hdr *hdr) {int status;__be32 *p;@@ -1300,6 +1385,7 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *RESERVE_SPACE (4 +NFS4_STATEID_SIZE );WRITE32 (OP_SETATTR );WRITEMEM (arg->stateid.data,NFS4_STATEID_SIZE ); + hdr->nops++;if ((status =encode_attrs (xdr, arg->iap, server)))return status;@@ -1307,7 +1393,10 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *return 0 ; } -static int encode_setclientid (struct xdr_stream *xdr,const struct nfs4_setclientid *setclientid) +static int +encode_setclientid (struct xdr_stream *xdr, +const struct nfs4_setclientid *setclientid, +struct compound_hdr *hdr) {__be32 *p;@@ -1322,11 +1411,15 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclienencode_string (xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);RESERVE_SPACE (4 );WRITE32 (setclientid->sc_cb_ident); + hdr->nops++;return 0 ; } -static int encode_setclientid_confirm (struct xdr_stream *xdr,const struct nfs_client *client_state) +static int +encode_setclientid_confirm (struct xdr_stream *xdr, +const struct nfs_client *client_state, +struct compound_hdr *hdr) {__be32 *p;@@ -1334,11 +1427,14 @@ static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_cWRITE32 (OP_SETCLIENTID_CONFIRM );WRITE64 (client_state->cl_clientid);WRITEMEM (client_state->cl_confirm.data,NFS4_VERIFIER_SIZE ); + hdr->nops++;return 0 ; } -static int encode_write (struct xdr_stream *xdr,const struct nfs_writeargs *args) +static int +encode_write (struct xdr_stream *xdr,const struct nfs_writeargs *args, +struct compound_hdr *hdr) {__be32 *p;@@ -1353,11 +1449,14 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *argsWRITE32 (args->count);xdr_write_pages (xdr, args->pages, args->pgbase, args->count); + hdr->nops++;return 0 ; } -static int encode_delegreturn (struct xdr_stream *xdr,const nfs4_stateid *stateid) +static int +encode_delegreturn (struct xdr_stream *xdr,const nfs4_stateid *stateid, +struct compound_hdr *hdr) {__be32 *p;@@ -1365,6 +1464,7 @@ static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateiWRITE32 (OP_DELEGRETURN );WRITEMEM (stateid->data,NFS4_STATEID_SIZE ); + hdr->nops++;return 0 ; }@@ -1379,20 +1479,22 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status !=0 ) goto out; - status =encode_access (&xdr, args->access); + status =encode_access (&xdr, args->access, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1403,20 +1505,22 @@ static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =4 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_lookup (&xdr, args->name)) !=0 ) +if ((status =encode_lookup (&xdr, args->name, &hdr)) !=0 ) goto out; -if ((status =encode_getfh (&xdr)) !=0 ) +if ((status =encode_getfh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1427,17 +1531,19 @@ static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struc {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putrootfh (&xdr)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putrootfh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_getfh (&xdr)) ==0 ) - status =encode_getfattr (&xdr, args->bitmask); +if ((status =encode_getfh (&xdr, &hdr)) ==0 ) + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1448,18 +1554,20 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->fh, &hdr)) !=0 ) goto out; -if ((status =encode_remove (&xdr, &args->name)) !=0 ) +if ((status =encode_remove (&xdr, &args->name, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1470,26 +1578,29 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->old_dir)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->old_dir, &hdr)) !=0 ) goto out; -if ((status =encode_savefh (&xdr)) !=0 ) +if ((status =encode_savefh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_putfh (&xdr, args->new_dir)) !=0 ) +if ((status =encode_putfh (&xdr, args->new_dir, &hdr)) !=0 ) goto out; -if ((status =encode_rename (&xdr, args->old_name, args->new_name)) !=0 ) +if ((status =encode_rename (&xdr, args->old_name, args->new_name, + &hdr)) !=0 ) goto out; -if ((status =encode_getfattr (&xdr, args->bitmask)) !=0 ) +if ((status =encode_getfattr (&xdr, args->bitmask, &hdr)) !=0 ) goto out; -if ((status =encode_restorefh (&xdr)) !=0 ) +if ((status =encode_restorefh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1500,26 +1611,28 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->fh, &hdr)) !=0 ) goto out; -if ((status =encode_savefh (&xdr)) !=0 ) +if ((status =encode_savefh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_link (&xdr, args->name)) !=0 ) +if ((status =encode_link (&xdr, args->name, &hdr)) !=0 ) goto out; -if ((status =encode_getfattr (&xdr, args->bitmask)) !=0 ) +if ((status =encode_getfattr (&xdr, args->bitmask, &hdr)) !=0 ) goto out; -if ((status =encode_restorefh (&xdr)) !=0 ) +if ((status =encode_restorefh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1530,26 +1643,28 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_savefh (&xdr)) !=0 ) +if ((status =encode_savefh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_create (&xdr, args)) !=0 ) +if ((status =encode_create (&xdr, args, &hdr)) !=0 ) goto out; -if ((status =encode_getfh (&xdr)) !=0 ) +if ((status =encode_getfh (&xdr, &hdr)) !=0 ) goto out; -if ((status =encode_getfattr (&xdr, args->bitmask)) !=0 ) +if ((status =encode_getfattr (&xdr, args->bitmask, &hdr)) !=0 ) goto out; -if ((status =encode_restorefh (&xdr)) !=0 ) +if ((status =encode_restorefh (&xdr, &hdr)) !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1568,14 +1683,16 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->fh)) ==0 ) - status =encode_getfattr (&xdr, args->bitmask); + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->fh, &hdr)) ==0 ) + status =encode_getfattr (&xdr, args->bitmask, &hdr); +encode_nops (nops, &hdr);return status; }@@ -1586,20 +1703,22 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closea {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_close (&xdr, args); + status =encode_close (&xdr, args, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1610,32 +1729,34 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openarg {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =7 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_savefh (&xdr); + status =encode_savefh (&xdr, &hdr);if (status) goto out; - status =encode_open (&xdr, args); + status =encode_open (&xdr, args, &hdr);if (status) goto out; - status =encode_getfh (&xdr); + status =encode_getfh (&xdr, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr);if (status) goto out; - status =encode_restorefh (&xdr); + status =encode_restorefh (&xdr, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1646,17 +1767,19 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_open_confirm (&xdr, args); + status =encode_open_confirm (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1667,20 +1790,22 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_open (&xdr, args); + status =encode_open (&xdr, args, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1691,20 +1816,22 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct n {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_open_downgrade (&xdr, args); + status =encode_open_downgrade (&xdr, args, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1715,17 +1842,19 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_ar {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_lock (&xdr, args); + status =encode_lock (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1736,17 +1865,19 @@ static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_lockt (&xdr, args); + status =encode_lockt (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1757,17 +1888,19 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_ {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_locku (&xdr, args); + status =encode_locku (&xdr, args, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1778,18 +1911,19 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;unsigned int replen;int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_readlink (&xdr, args, req); + status =encode_readlink (&xdr, args, req, &hdr);/* set up reply kvec * toplevel_status + taglen + rescount + OP_PUTFH + status @@ -1800,6 +1934,7 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n args->pgbase, args->pglen); out: +encode_nops (nops, &hdr);return status; }@@ -1810,18 +1945,19 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;int replen;int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_readdir (&xdr, args, req); + status =encode_readdir (&xdr, args, req, &hdr);/* set up reply kvec * toplevel_status + taglen + rescount + OP_PUTFH + status @@ -1835,6 +1971,7 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf args->pgbase, args->count); out: +encode_nops (nops, &hdr);return status; }@@ -1846,16 +1983,17 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargstruct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int replen, status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_read (&xdr, args); + status =encode_read (&xdr, args, &hdr);if (status) goto out;@@ -1868,6 +2006,7 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readarg args->pages, args->pgbase, args->count); req->rq_rcv_buf.flags |=XDRBUF_READ ; out: +encode_nops (nops, &hdr);return status; }@@ -1877,23 +2016,25 @@ out:static int nfs4_xdr_enc_setattr (struct rpc_rqst *req,__be32 *p,struct nfs_setattrargs *args) { -struct xdr_stream xdr; -struct compound_hdr hdr = { - .nops =3 , - }; -int status; +struct xdr_stream xdr; +struct compound_hdr hdr = { + .nops =0 , + }; +int status; +__be32 *nops; -xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); -if (status) - goto out; - status =encode_setattr (&xdr, args, args->server); -if (status) - goto out; - status =encode_getfattr (&xdr, args->bitmask); +xdr_init_encode (&xdr, &req->rq_snd_buf, p); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr); +if (status) + goto out; + status =encode_setattr (&xdr, args, args->server, &hdr); +if (status) + goto out; + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: -return status; +encode_nops (nops, &hdr); +return status; }/* @@ -1906,21 +2047,23 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,struct xdr_stream xdr;struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int replen, status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_getattr_two (&xdr,FATTR4_WORD0_ACL ,0 ); + status =encode_getattr_two (&xdr,FATTR4_WORD0_ACL ,0 , &hdr);/* set up reply buffer: */ replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) <<2 ;xdr_inline_pages (&req->rq_rcv_buf, replen, args->acl_pages, args->acl_pgbase, args->acl_len); out: +encode_nops (nops, &hdr);return status; }@@ -1931,21 +2074,23 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writea {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_write (&xdr, args); + status =encode_write (&xdr, args, &hdr);if (status) goto out; req->rq_snd_buf.flags |=XDRBUF_WRITE ; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1956,20 +2101,22 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_write {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status) goto out; - status =encode_commit (&xdr, args); + status =encode_commit (&xdr, args, &hdr);if (status) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -1980,15 +2127,17 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (!status) - status =encode_fsinfo (&xdr, args->bitmask); + status =encode_fsinfo (&xdr, args->bitmask, &hdr); +encode_nops (nops, &hdr);return status; }@@ -1999,16 +2148,19 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (!status) status =encode_getattr_one (&xdr, - args->bitmask[0 ] & nfs4_pathconf_bitmap[0 ]); + args->bitmask[0 ] & nfs4_pathconf_bitmap[0 ], + &hdr); +encode_nops (nops, &hdr);return status; }@@ -2019,17 +2171,19 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr);if (status ==0 ) status =encode_getattr_two (&xdr, args->bitmask[0 ] & nfs4_statfs_bitmap[0 ], - args->bitmask[1 ] & nfs4_statfs_bitmap[1 ]); + args->bitmask[1 ] & nfs4_statfs_bitmap[1 ], &hdr); +encode_nops (nops, &hdr);return status; }@@ -2040,18 +2194,20 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struc {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =2 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, fhandle); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, fhandle, &hdr);if (status ==0 ) status =encode_getattr_one (&xdr,FATTR4_WORD0_SUPPORTED_ATTRS |FATTR4_WORD0_LINK_SUPPORT |FATTR4_WORD0_SYMLINK_SUPPORT | -FATTR4_WORD0_ACLSUPPORT ); +FATTR4_WORD0_ACLSUPPORT , &hdr); +encode_nops (nops, &hdr);return status; }@@ -2062,12 +2218,16 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =1 , + .nops =0 , }; +int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -return encode_renew (&xdr, clp); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_renew (&xdr, clp, &hdr); +encode_nops (nops, &hdr); +return status; }/* @@ -2077,12 +2237,16 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4 {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =1 , + .nops =0 , }; +int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -return encode_setclientid (&xdr, sc); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_setclientid (&xdr, sc, &hdr); +encode_nops (nops, &hdr); +return status; }/* @@ -2092,18 +2256,20 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };const u32 lease_bitmap[2 ] = {FATTR4_WORD0_LEASE_TIME ,0 };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_setclientid_confirm (&xdr, clp); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_setclientid_confirm (&xdr, clp, &hdr);if (!status) - status =encode_putrootfh (&xdr); + status =encode_putrootfh (&xdr, &hdr);if (!status) - status =encode_fsinfo (&xdr, lease_bitmap); + status =encode_fsinfo (&xdr, lease_bitmap, &hdr); +encode_nops (nops, &hdr);return status; }@@ -2114,20 +2280,22 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struc {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fhandle); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fhandle, &hdr);if (status !=0 ) goto out; - status =encode_delegreturn (&xdr, args->stateid); + status =encode_delegreturn (&xdr, args->stateid, &hdr);if (status !=0 ) goto out; - status =encode_getfattr (&xdr, args->bitmask); + status =encode_getfattr (&xdr, args->bitmask, &hdr); out: +encode_nops (nops, &hdr);return status; }@@ -2138,19 +2306,20 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs {struct xdr_stream xdr;struct compound_hdr hdr = { - .nops =3 , + .nops =0 , };struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;int replen;int status; +__be32 *nops;xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); -if ((status =encode_putfh (&xdr, args->dir_fh)) !=0 ) + nops =encode_compound_hdr (&xdr, &hdr); +if ((status =encode_putfh (&xdr, args->dir_fh, &hdr)) !=0 ) goto out; -if ((status =encode_lookup (&xdr, args->name)) !=0 ) +if ((status =encode_lookup (&xdr, args->name, &hdr)) !=0 ) goto out; -if ((status =encode_fs_locations (&xdr, args->bitmask)) !=0 ) +if ((status =encode_fs_locations (&xdr, args->bitmask, &hdr)) !=0 ) goto out;/* set up reply * toplevel_status + OP_PUTFH + status @@ -2160,6 +2329,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfsxdr_inline_pages (&req->rq_rcv_buf, replen, &args->page,0 ,PAGE_SIZE ); out: +encode_nops (nops, &hdr);return status; }@@ -4036,20 +4206,22 @@ out:static int nfs4_xdr_enc_setacl (struct rpc_rqst *req,__be32 *p,struct nfs_setaclargs *args) { -struct xdr_stream xdr; -struct compound_hdr hdr = { - .nops =2 , - }; -int status; +struct xdr_stream xdr; +struct compound_hdr hdr = { + .nops =0 , + }; +int status; +__be32 *nops; -xdr_init_encode (&xdr, &req->rq_snd_buf, p); -encode_compound_hdr (&xdr, &hdr); - status =encode_putfh (&xdr, args->fh); -if (status) - goto out; - status =encode_setacl (&xdr, args); +xdr_init_encode (&xdr, &req->rq_snd_buf, p); + nops =encode_compound_hdr (&xdr, &hdr); + status =encode_putfh (&xdr, args->fh, &hdr); +if (status) + goto out; + status =encode_setacl (&xdr, args, &hdr); out: -return status; +encode_nops (nops, &hdr); +return status; }/* * Decode SETACL response Signature · 1 line
1.6.0.1
Re: [pnfs] [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1
In reply to Benny HalevyQuoted 14 lines · Benny Halevy
From: Ricardo Labiaga <[email protected]>
Added
CONFIG_NFS_V4_1and made it depend uponCONFIG_NFS_V4and EXPERIMENTAL.Signed-off-by Benny Halevy <[email protected]>--- fs/Kconfig | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)fs/Kconfig +0
-0
fs/Kconfig config NFS_V4 · line 1220
Quoted 5 lines
fs/Kconfig +2
-0@@ -1216,6 +1216,15 @@ config NFS_V4 If unsure, say N. +config NFS_V4_1 + bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
review 11-14: s/EXPERIMENTAL/DEVELOPER ONLY/
fs/Kconfig config NFS_V4 · line 1225
Quoted 5 lines
fs/Kconfig +5
-0+ depends on NFS_V4 && EXPERIMENTAL + help + This option enables support for minor version 1 of the NFSv4 protocol + (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client. +
Unless you're an NFS developer, say N.
Quoted 5 lines
fs/Kconfig +2
-0+ If unsure, say N. + config ROOT_NFS bool "Root file system on NFS" depends on NFS_FS=y && IP_PNP