@@ -84,7 +84,21 @@ static void encode_uint32(struct xdr_stream *xdr, u32 n)
8484static void encode_bitmap4 (struct xdr_stream * xdr , const __u32 * bitmap ,
8585 size_t len )
8686{
87- WARN_ON_ONCE (xdr_stream_encode_uint32_array (xdr , bitmap , len ) < 0 );
87+ xdr_stream_encode_uint32_array (xdr , bitmap , len );
88+ }
89+
90+ static int decode_cb_fattr4 (struct xdr_stream * xdr , uint32_t * bitmap ,
91+ struct nfs4_cb_fattr * fattr )
92+ {
93+ fattr -> ncf_cb_change = 0 ;
94+ fattr -> ncf_cb_fsize = 0 ;
95+ if (bitmap [0 ] & FATTR4_WORD0_CHANGE )
96+ if (xdr_stream_decode_u64 (xdr , & fattr -> ncf_cb_change ) < 0 )
97+ return - NFSERR_BAD_XDR ;
98+ if (bitmap [0 ] & FATTR4_WORD0_SIZE )
99+ if (xdr_stream_decode_u64 (xdr , & fattr -> ncf_cb_fsize ) < 0 )
100+ return - NFSERR_BAD_XDR ;
101+ return 0 ;
88102}
89103
90104/*
@@ -357,6 +371,30 @@ encode_cb_recallany4args(struct xdr_stream *xdr,
357371 hdr -> nops ++ ;
358372}
359373
374+ /*
375+ * CB_GETATTR4args
376+ * struct CB_GETATTR4args {
377+ * nfs_fh4 fh;
378+ * bitmap4 attr_request;
379+ * };
380+ *
381+ * The size and change attributes are the only one
382+ * guaranteed to be serviced by the client.
383+ */
384+ static void
385+ encode_cb_getattr4args (struct xdr_stream * xdr , struct nfs4_cb_compound_hdr * hdr ,
386+ struct nfs4_cb_fattr * fattr )
387+ {
388+ struct nfs4_delegation * dp =
389+ container_of (fattr , struct nfs4_delegation , dl_cb_fattr );
390+ struct knfsd_fh * fh = & dp -> dl_stid .sc_file -> fi_fhandle ;
391+
392+ encode_nfs_cb_opnum4 (xdr , OP_CB_GETATTR );
393+ encode_nfs_fh4 (xdr , fh );
394+ encode_bitmap4 (xdr , fattr -> ncf_cb_bmap , ARRAY_SIZE (fattr -> ncf_cb_bmap ));
395+ hdr -> nops ++ ;
396+ }
397+
360398/*
361399 * CB_SEQUENCE4args
362400 *
@@ -492,6 +530,26 @@ static void nfs4_xdr_enc_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
492530 xdr_reserve_space (xdr , 0 );
493531}
494532
533+ /*
534+ * 20.1. Operation 3: CB_GETATTR - Get Attributes
535+ */
536+ static void nfs4_xdr_enc_cb_getattr (struct rpc_rqst * req ,
537+ struct xdr_stream * xdr , const void * data )
538+ {
539+ const struct nfsd4_callback * cb = data ;
540+ struct nfs4_cb_fattr * ncf =
541+ container_of (cb , struct nfs4_cb_fattr , ncf_getattr );
542+ struct nfs4_cb_compound_hdr hdr = {
543+ .ident = cb -> cb_clp -> cl_cb_ident ,
544+ .minorversion = cb -> cb_clp -> cl_minorversion ,
545+ };
546+
547+ encode_cb_compound4args (xdr , & hdr );
548+ encode_cb_sequence4args (xdr , cb , & hdr );
549+ encode_cb_getattr4args (xdr , & hdr , ncf );
550+ encode_cb_nops (& hdr );
551+ }
552+
495553/*
496554 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
497555 */
@@ -547,6 +605,42 @@ static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
547605 return 0 ;
548606}
549607
608+ /*
609+ * 20.1. Operation 3: CB_GETATTR - Get Attributes
610+ */
611+ static int nfs4_xdr_dec_cb_getattr (struct rpc_rqst * rqstp ,
612+ struct xdr_stream * xdr ,
613+ void * data )
614+ {
615+ struct nfsd4_callback * cb = data ;
616+ struct nfs4_cb_compound_hdr hdr ;
617+ int status ;
618+ u32 bitmap [3 ] = {0 };
619+ u32 attrlen ;
620+ struct nfs4_cb_fattr * ncf =
621+ container_of (cb , struct nfs4_cb_fattr , ncf_getattr );
622+
623+ status = decode_cb_compound4res (xdr , & hdr );
624+ if (unlikely (status ))
625+ return status ;
626+
627+ status = decode_cb_sequence4res (xdr , cb );
628+ if (unlikely (status || cb -> cb_seq_status ))
629+ return status ;
630+
631+ status = decode_cb_op_status (xdr , OP_CB_GETATTR , & cb -> cb_status );
632+ if (status )
633+ return status ;
634+ if (xdr_stream_decode_uint32_array (xdr , bitmap , 3 ) < 0 )
635+ return - NFSERR_BAD_XDR ;
636+ if (xdr_stream_decode_u32 (xdr , & attrlen ) < 0 )
637+ return - NFSERR_BAD_XDR ;
638+ if (attrlen > (sizeof (ncf -> ncf_cb_change ) + sizeof (ncf -> ncf_cb_fsize )))
639+ return - NFSERR_BAD_XDR ;
640+ status = decode_cb_fattr4 (xdr , bitmap , ncf );
641+ return status ;
642+ }
643+
550644/*
551645 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
552646 */
@@ -855,6 +949,7 @@ static const struct rpc_procinfo nfs4_cb_procedures[] = {
855949 PROC (CB_NOTIFY_LOCK , COMPOUND , cb_notify_lock , cb_notify_lock ),
856950 PROC (CB_OFFLOAD , COMPOUND , cb_offload , cb_offload ),
857951 PROC (CB_RECALL_ANY , COMPOUND , cb_recall_any , cb_recall_any ),
952+ PROC (CB_GETATTR , COMPOUND , cb_getattr , cb_getattr ),
858953};
859954
860955static unsigned int nfs4_cb_counts [ARRAY_SIZE (nfs4_cb_procedures )];
0 commit comments