2020 2 + 2 + 3 + 3)
2121#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
2222
23+ #if defined(CONFIG_NFS_V4_1 )
24+ #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
25+ 4 + 1 + 3)
26+ #endif /* CONFIG_NFS_V4_1 */
27+
2328#define NFSDBG_FACILITY NFSDBG_CALLBACK
2429
2530typedef __be32 (* callback_process_op_t )(void * , void * );
@@ -207,6 +212,122 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
207212 return status ;
208213}
209214
215+ #if defined(CONFIG_NFS_V4_1 )
216+
217+ static unsigned decode_sessionid (struct xdr_stream * xdr ,
218+ struct nfs4_sessionid * sid )
219+ {
220+ uint32_t * p ;
221+ int len = NFS4_MAX_SESSIONID_LEN ;
222+
223+ p = read_buf (xdr , len );
224+ if (unlikely (p == NULL ))
225+ return htonl (NFS4ERR_RESOURCE );;
226+
227+ memcpy (sid -> data , p , len );
228+ return 0 ;
229+ }
230+
231+ static unsigned decode_rc_list (struct xdr_stream * xdr ,
232+ struct referring_call_list * rc_list )
233+ {
234+ uint32_t * p ;
235+ int i ;
236+ unsigned status ;
237+
238+ status = decode_sessionid (xdr , & rc_list -> rcl_sessionid );
239+ if (status )
240+ goto out ;
241+
242+ status = htonl (NFS4ERR_RESOURCE );
243+ p = read_buf (xdr , sizeof (uint32_t ));
244+ if (unlikely (p == NULL ))
245+ goto out ;
246+
247+ rc_list -> rcl_nrefcalls = ntohl (* p ++ );
248+ if (rc_list -> rcl_nrefcalls ) {
249+ p = read_buf (xdr ,
250+ rc_list -> rcl_nrefcalls * 2 * sizeof (uint32_t ));
251+ if (unlikely (p == NULL ))
252+ goto out ;
253+ rc_list -> rcl_refcalls = kmalloc (rc_list -> rcl_nrefcalls *
254+ sizeof (* rc_list -> rcl_refcalls ),
255+ GFP_KERNEL );
256+ if (unlikely (rc_list -> rcl_refcalls == NULL ))
257+ goto out ;
258+ for (i = 0 ; i < rc_list -> rcl_nrefcalls ; i ++ ) {
259+ rc_list -> rcl_refcalls [i ].rc_sequenceid = ntohl (* p ++ );
260+ rc_list -> rcl_refcalls [i ].rc_slotid = ntohl (* p ++ );
261+ }
262+ }
263+ status = 0 ;
264+
265+ out :
266+ return status ;
267+ }
268+
269+ static unsigned decode_cb_sequence_args (struct svc_rqst * rqstp ,
270+ struct xdr_stream * xdr ,
271+ struct cb_sequenceargs * args )
272+ {
273+ uint32_t * p ;
274+ int i ;
275+ unsigned status ;
276+
277+ status = decode_sessionid (xdr , & args -> csa_sessionid );
278+ if (status )
279+ goto out ;
280+
281+ status = htonl (NFS4ERR_RESOURCE );
282+ p = read_buf (xdr , 5 * sizeof (uint32_t ));
283+ if (unlikely (p == NULL ))
284+ goto out ;
285+
286+ args -> csa_addr = svc_addr_in (rqstp );
287+ args -> csa_sequenceid = ntohl (* p ++ );
288+ args -> csa_slotid = ntohl (* p ++ );
289+ args -> csa_highestslotid = ntohl (* p ++ );
290+ args -> csa_cachethis = ntohl (* p ++ );
291+ args -> csa_nrclists = ntohl (* p ++ );
292+ args -> csa_rclists = NULL ;
293+ if (args -> csa_nrclists ) {
294+ args -> csa_rclists = kmalloc (args -> csa_nrclists *
295+ sizeof (* args -> csa_rclists ),
296+ GFP_KERNEL );
297+ if (unlikely (args -> csa_rclists == NULL ))
298+ goto out ;
299+
300+ for (i = 0 ; i < args -> csa_nrclists ; i ++ ) {
301+ status = decode_rc_list (xdr , & args -> csa_rclists [i ]);
302+ if (status )
303+ goto out_free ;
304+ }
305+ }
306+ status = 0 ;
307+
308+ dprintk ("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
309+ "highestslotid %u cachethis %d nrclists %u\n" ,
310+ __func__ ,
311+ ((u32 * )& args -> csa_sessionid )[0 ],
312+ ((u32 * )& args -> csa_sessionid )[1 ],
313+ ((u32 * )& args -> csa_sessionid )[2 ],
314+ ((u32 * )& args -> csa_sessionid )[3 ],
315+ args -> csa_sequenceid , args -> csa_slotid ,
316+ args -> csa_highestslotid , args -> csa_cachethis ,
317+ args -> csa_nrclists );
318+ out :
319+ dprintk ("%s: exit with status = %d\n" , __func__ , ntohl (status ));
320+ return status ;
321+
322+ out_free :
323+ for (i = 0 ; i < args -> csa_nrclists ; i ++ )
324+ kfree (args -> csa_rclists [i ].rcl_refcalls );
325+ kfree (args -> csa_rclists );
326+ goto out ;
327+ }
328+
329+ #endif /* CONFIG_NFS_V4_1 */
330+
210331static __be32 encode_string (struct xdr_stream * xdr , unsigned int len , const char * str )
211332{
212333 __be32 * p ;
@@ -358,12 +479,52 @@ static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
358479
359480#if defined(CONFIG_NFS_V4_1 )
360481
482+ static unsigned encode_sessionid (struct xdr_stream * xdr ,
483+ const struct nfs4_sessionid * sid )
484+ {
485+ uint32_t * p ;
486+ int len = NFS4_MAX_SESSIONID_LEN ;
487+
488+ p = xdr_reserve_space (xdr , len );
489+ if (unlikely (p == NULL ))
490+ return htonl (NFS4ERR_RESOURCE );
491+
492+ memcpy (p , sid , len );
493+ return 0 ;
494+ }
495+
496+ static unsigned encode_cb_sequence_res (struct svc_rqst * rqstp ,
497+ struct xdr_stream * xdr ,
498+ const struct cb_sequenceres * res )
499+ {
500+ uint32_t * p ;
501+ unsigned status = res -> csr_status ;
502+
503+ if (unlikely (status != 0 ))
504+ goto out ;
505+
506+ encode_sessionid (xdr , & res -> csr_sessionid );
507+
508+ p = xdr_reserve_space (xdr , 4 * sizeof (uint32_t ));
509+ if (unlikely (p == NULL ))
510+ return htonl (NFS4ERR_RESOURCE );
511+
512+ * p ++ = htonl (res -> csr_sequenceid );
513+ * p ++ = htonl (res -> csr_slotid );
514+ * p ++ = htonl (res -> csr_highestslotid );
515+ * p ++ = htonl (res -> csr_target_highestslotid );
516+ out :
517+ dprintk ("%s: exit with status = %d\n" , __func__ , ntohl (status ));
518+ return status ;
519+ }
520+
361521static __be32
362522preprocess_nfs41_op (int nop , unsigned int op_nr , struct callback_op * * op )
363523{
364524 switch (op_nr ) {
365525 case OP_CB_GETATTR :
366526 case OP_CB_RECALL :
527+ case OP_CB_SEQUENCE :
367528 * op = & callback_ops [op_nr ];
368529 break ;
369530
@@ -374,7 +535,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
374535 case OP_CB_RECALL_ANY :
375536 case OP_CB_RECALLABLE_OBJ_AVAIL :
376537 case OP_CB_RECALL_SLOT :
377- case OP_CB_SEQUENCE :
378538 case OP_CB_WANTS_CANCELLED :
379539 case OP_CB_NOTIFY_LOCK :
380540 return htonl (NFS4ERR_NOTSUPP );
@@ -512,7 +672,15 @@ static struct callback_op callback_ops[] = {
512672 .process_op = (callback_process_op_t )nfs4_callback_recall ,
513673 .decode_args = (callback_decode_arg_t )decode_recall_args ,
514674 .res_maxsize = CB_OP_RECALL_RES_MAXSZ ,
515- }
675+ },
676+ #if defined(CONFIG_NFS_V4_1 )
677+ [OP_CB_SEQUENCE ] = {
678+ .process_op = (callback_process_op_t )nfs4_callback_sequence ,
679+ .decode_args = (callback_decode_arg_t )decode_cb_sequence_args ,
680+ .encode_res = (callback_encode_res_t )encode_cb_sequence_res ,
681+ .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ ,
682+ },
683+ #endif /* CONFIG_NFS_V4_1 */
516684};
517685
518686/*
0 commit comments