@@ -85,7 +85,21 @@ static void encode_uint32(struct xdr_stream *xdr, u32 n)
8585static void encode_bitmap4 (struct xdr_stream * xdr , const __u32 * bitmap ,
8686 size_t len )
8787{
88- WARN_ON_ONCE (xdr_stream_encode_uint32_array (xdr , bitmap , len ) < 0 );
88+ xdr_stream_encode_uint32_array (xdr , bitmap , len );
89+ }
90+
91+ static int decode_cb_fattr4 (struct xdr_stream * xdr , uint32_t * bitmap ,
92+ struct nfs4_cb_fattr * fattr )
93+ {
94+ fattr -> ncf_cb_change = 0 ;
95+ fattr -> ncf_cb_fsize = 0 ;
96+ if (bitmap [0 ] & FATTR4_WORD0_CHANGE )
97+ if (xdr_stream_decode_u64 (xdr , & fattr -> ncf_cb_change ) < 0 )
98+ return - NFSERR_BAD_XDR ;
99+ if (bitmap [0 ] & FATTR4_WORD0_SIZE )
100+ if (xdr_stream_decode_u64 (xdr , & fattr -> ncf_cb_fsize ) < 0 )
101+ return - NFSERR_BAD_XDR ;
102+ return 0 ;
89103}
90104
91105static void encode_nfs_cb_opnum4 (struct xdr_stream * xdr , enum nfs_cb_opnum4 op )
@@ -333,6 +347,30 @@ encode_cb_recallany4args(struct xdr_stream *xdr,
333347 hdr -> nops ++ ;
334348}
335349
350+ /*
351+ * CB_GETATTR4args
352+ * struct CB_GETATTR4args {
353+ * nfs_fh4 fh;
354+ * bitmap4 attr_request;
355+ * };
356+ *
357+ * The size and change attributes are the only one
358+ * guaranteed to be serviced by the client.
359+ */
360+ static void
361+ encode_cb_getattr4args (struct xdr_stream * xdr , struct nfs4_cb_compound_hdr * hdr ,
362+ struct nfs4_cb_fattr * fattr )
363+ {
364+ struct nfs4_delegation * dp =
365+ container_of (fattr , struct nfs4_delegation , dl_cb_fattr );
366+ struct knfsd_fh * fh = & dp -> dl_stid .sc_file -> fi_fhandle ;
367+
368+ encode_nfs_cb_opnum4 (xdr , OP_CB_GETATTR );
369+ encode_nfs_fh4 (xdr , fh );
370+ encode_bitmap4 (xdr , fattr -> ncf_cb_bmap , ARRAY_SIZE (fattr -> ncf_cb_bmap ));
371+ hdr -> nops ++ ;
372+ }
373+
336374/*
337375 * CB_SEQUENCE4args
338376 *
@@ -468,6 +506,26 @@ static void nfs4_xdr_enc_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
468506 xdr_reserve_space (xdr , 0 );
469507}
470508
509+ /*
510+ * 20.1. Operation 3: CB_GETATTR - Get Attributes
511+ */
512+ static void nfs4_xdr_enc_cb_getattr (struct rpc_rqst * req ,
513+ struct xdr_stream * xdr , const void * data )
514+ {
515+ const struct nfsd4_callback * cb = data ;
516+ struct nfs4_cb_fattr * ncf =
517+ container_of (cb , struct nfs4_cb_fattr , ncf_getattr );
518+ struct nfs4_cb_compound_hdr hdr = {
519+ .ident = cb -> cb_clp -> cl_cb_ident ,
520+ .minorversion = cb -> cb_clp -> cl_minorversion ,
521+ };
522+
523+ encode_cb_compound4args (xdr , & hdr );
524+ encode_cb_sequence4args (xdr , cb , & hdr );
525+ encode_cb_getattr4args (xdr , & hdr , ncf );
526+ encode_cb_nops (& hdr );
527+ }
528+
471529/*
472530 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
473531 */
@@ -523,6 +581,42 @@ static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
523581 return 0 ;
524582}
525583
584+ /*
585+ * 20.1. Operation 3: CB_GETATTR - Get Attributes
586+ */
587+ static int nfs4_xdr_dec_cb_getattr (struct rpc_rqst * rqstp ,
588+ struct xdr_stream * xdr ,
589+ void * data )
590+ {
591+ struct nfsd4_callback * cb = data ;
592+ struct nfs4_cb_compound_hdr hdr ;
593+ int status ;
594+ u32 bitmap [3 ] = {0 };
595+ u32 attrlen ;
596+ struct nfs4_cb_fattr * ncf =
597+ container_of (cb , struct nfs4_cb_fattr , ncf_getattr );
598+
599+ status = decode_cb_compound4res (xdr , & hdr );
600+ if (unlikely (status ))
601+ return status ;
602+
603+ status = decode_cb_sequence4res (xdr , cb );
604+ if (unlikely (status || cb -> cb_seq_status ))
605+ return status ;
606+
607+ status = decode_cb_op_status (xdr , OP_CB_GETATTR , & cb -> cb_status );
608+ if (status )
609+ return status ;
610+ if (xdr_stream_decode_uint32_array (xdr , bitmap , 3 ) < 0 )
611+ return - NFSERR_BAD_XDR ;
612+ if (xdr_stream_decode_u32 (xdr , & attrlen ) < 0 )
613+ return - NFSERR_BAD_XDR ;
614+ if (attrlen > (sizeof (ncf -> ncf_cb_change ) + sizeof (ncf -> ncf_cb_fsize )))
615+ return - NFSERR_BAD_XDR ;
616+ status = decode_cb_fattr4 (xdr , bitmap , ncf );
617+ return status ;
618+ }
619+
526620/*
527621 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
528622 */
@@ -831,6 +925,7 @@ static const struct rpc_procinfo nfs4_cb_procedures[] = {
831925 PROC (CB_NOTIFY_LOCK , COMPOUND , cb_notify_lock , cb_notify_lock ),
832926 PROC (CB_OFFLOAD , COMPOUND , cb_offload , cb_offload ),
833927 PROC (CB_RECALL_ANY , COMPOUND , cb_recall_any , cb_recall_any ),
928+ PROC (CB_GETATTR , COMPOUND , cb_getattr , cb_getattr ),
834929};
835930
836931static unsigned int nfs4_cb_counts [ARRAY_SIZE (nfs4_cb_procedures )];
0 commit comments