20
20
2 + 2 + 3 + 3)
21
21
#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
22
22
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
+
23
28
#define NFSDBG_FACILITY NFSDBG_CALLBACK
24
29
25
30
typedef __be32 (* callback_process_op_t )(void * , void * );
@@ -207,6 +212,122 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
207
212
return status ;
208
213
}
209
214
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
+
210
331
static __be32 encode_string (struct xdr_stream * xdr , unsigned int len , const char * str )
211
332
{
212
333
__be32 * p ;
@@ -358,12 +479,52 @@ static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
358
479
359
480
#if defined(CONFIG_NFS_V4_1 )
360
481
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
+
361
521
static __be32
362
522
preprocess_nfs41_op (int nop , unsigned int op_nr , struct callback_op * * op )
363
523
{
364
524
switch (op_nr ) {
365
525
case OP_CB_GETATTR :
366
526
case OP_CB_RECALL :
527
+ case OP_CB_SEQUENCE :
367
528
* op = & callback_ops [op_nr ];
368
529
break ;
369
530
@@ -374,7 +535,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
374
535
case OP_CB_RECALL_ANY :
375
536
case OP_CB_RECALLABLE_OBJ_AVAIL :
376
537
case OP_CB_RECALL_SLOT :
377
- case OP_CB_SEQUENCE :
378
538
case OP_CB_WANTS_CANCELLED :
379
539
case OP_CB_NOTIFY_LOCK :
380
540
return htonl (NFS4ERR_NOTSUPP );
@@ -512,7 +672,15 @@ static struct callback_op callback_ops[] = {
512
672
.process_op = (callback_process_op_t )nfs4_callback_recall ,
513
673
.decode_args = (callback_decode_arg_t )decode_recall_args ,
514
674
.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 */
516
684
};
517
685
518
686
/*
0 commit comments