2 * linux/fs/nfs/callback_xdr.c
4 * Copyright (C) 2004 Trond Myklebust
6 * NFSv4 callback encode/decode procedures
8 #include <linux/kernel.h>
9 #include <linux/sunrpc/svc.h>
10 #include <linux/nfs4.h>
11 #include <linux/nfs_fs.h>
15 #define CB_OP_TAGLEN_MAXSZ (512)
16 #define CB_OP_HDR_RES_MAXSZ (2 + CB_OP_TAGLEN_MAXSZ)
17 #define CB_OP_GETATTR_BITMAP_MAXSZ (4)
18 #define CB_OP_GETATTR_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
19 CB_OP_GETATTR_BITMAP_MAXSZ + \
21 #define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
23 #if defined(CONFIG_NFS_V4_1)
24 #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
26 #define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
27 #endif /* CONFIG_NFS_V4_1 */
29 #define NFSDBG_FACILITY NFSDBG_CALLBACK
31 typedef __be32 (*callback_process_op_t
)(void *, void *);
32 typedef __be32 (*callback_decode_arg_t
)(struct svc_rqst
*, struct xdr_stream
*, void *);
33 typedef __be32 (*callback_encode_res_t
)(struct svc_rqst
*, struct xdr_stream
*, void *);
37 callback_process_op_t process_op
;
38 callback_decode_arg_t decode_args
;
39 callback_encode_res_t encode_res
;
43 static struct callback_op callback_ops
[];
45 static __be32
nfs4_callback_null(struct svc_rqst
*rqstp
, void *argp
, void *resp
)
47 return htonl(NFS4_OK
);
50 static int nfs4_decode_void(struct svc_rqst
*rqstp
, __be32
*p
, void *dummy
)
52 return xdr_argsize_check(rqstp
, p
);
55 static int nfs4_encode_void(struct svc_rqst
*rqstp
, __be32
*p
, void *dummy
)
57 return xdr_ressize_check(rqstp
, p
);
60 static __be32
*read_buf(struct xdr_stream
*xdr
, int nbytes
)
64 p
= xdr_inline_decode(xdr
, nbytes
);
65 if (unlikely(p
== NULL
))
66 printk(KERN_WARNING
"NFSv4 callback reply buffer overflowed!\n");
70 static __be32
decode_string(struct xdr_stream
*xdr
, unsigned int *len
, const char **str
)
75 if (unlikely(p
== NULL
))
76 return htonl(NFS4ERR_RESOURCE
);
80 p
= read_buf(xdr
, *len
);
81 if (unlikely(p
== NULL
))
82 return htonl(NFS4ERR_RESOURCE
);
83 *str
= (const char *)p
;
90 static __be32
decode_fh(struct xdr_stream
*xdr
, struct nfs_fh
*fh
)
95 if (unlikely(p
== NULL
))
96 return htonl(NFS4ERR_RESOURCE
);
98 if (fh
->size
> NFS4_FHSIZE
)
99 return htonl(NFS4ERR_BADHANDLE
);
100 p
= read_buf(xdr
, fh
->size
);
101 if (unlikely(p
== NULL
))
102 return htonl(NFS4ERR_RESOURCE
);
103 memcpy(&fh
->data
[0], p
, fh
->size
);
104 memset(&fh
->data
[fh
->size
], 0, sizeof(fh
->data
) - fh
->size
);
108 static __be32
decode_bitmap(struct xdr_stream
*xdr
, uint32_t *bitmap
)
111 unsigned int attrlen
;
113 p
= read_buf(xdr
, 4);
114 if (unlikely(p
== NULL
))
115 return htonl(NFS4ERR_RESOURCE
);
117 p
= read_buf(xdr
, attrlen
<< 2);
118 if (unlikely(p
== NULL
))
119 return htonl(NFS4ERR_RESOURCE
);
120 if (likely(attrlen
> 0))
121 bitmap
[0] = ntohl(*p
++);
123 bitmap
[1] = ntohl(*p
);
127 static __be32
decode_stateid(struct xdr_stream
*xdr
, nfs4_stateid
*stateid
)
131 p
= read_buf(xdr
, 16);
132 if (unlikely(p
== NULL
))
133 return htonl(NFS4ERR_RESOURCE
);
134 memcpy(stateid
->data
, p
, 16);
138 static __be32
decode_compound_hdr_arg(struct xdr_stream
*xdr
, struct cb_compound_hdr_arg
*hdr
)
143 status
= decode_string(xdr
, &hdr
->taglen
, &hdr
->tag
);
144 if (unlikely(status
!= 0))
146 /* We do not like overly long tags! */
147 if (hdr
->taglen
> CB_OP_TAGLEN_MAXSZ
- 12) {
148 printk("NFSv4 CALLBACK %s: client sent tag of length %u\n",
149 __func__
, hdr
->taglen
);
150 return htonl(NFS4ERR_RESOURCE
);
152 p
= read_buf(xdr
, 12);
153 if (unlikely(p
== NULL
))
154 return htonl(NFS4ERR_RESOURCE
);
155 hdr
->minorversion
= ntohl(*p
++);
156 /* Check minor version is zero or one. */
157 if (hdr
->minorversion
<= 1) {
158 p
++; /* skip callback_ident */
160 printk(KERN_WARNING
"%s: NFSv4 server callback with "
161 "illegal minor version %u!\n",
162 __func__
, hdr
->minorversion
);
163 return htonl(NFS4ERR_MINOR_VERS_MISMATCH
);
165 hdr
->nops
= ntohl(*p
);
166 dprintk("%s: minorversion %d nops %d\n", __func__
,
167 hdr
->minorversion
, hdr
->nops
);
171 static __be32
decode_op_hdr(struct xdr_stream
*xdr
, unsigned int *op
)
174 p
= read_buf(xdr
, 4);
175 if (unlikely(p
== NULL
))
176 return htonl(NFS4ERR_RESOURCE
);
181 static __be32
decode_getattr_args(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
, struct cb_getattrargs
*args
)
185 status
= decode_fh(xdr
, &args
->fh
);
186 if (unlikely(status
!= 0))
188 args
->addr
= svc_addr(rqstp
);
189 status
= decode_bitmap(xdr
, args
->bitmap
);
191 dprintk("%s: exit with status = %d\n", __func__
, ntohl(status
));
195 static __be32
decode_recall_args(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
, struct cb_recallargs
*args
)
200 args
->addr
= svc_addr(rqstp
);
201 status
= decode_stateid(xdr
, &args
->stateid
);
202 if (unlikely(status
!= 0))
204 p
= read_buf(xdr
, 4);
205 if (unlikely(p
== NULL
)) {
206 status
= htonl(NFS4ERR_RESOURCE
);
209 args
->truncate
= ntohl(*p
);
210 status
= decode_fh(xdr
, &args
->fh
);
212 dprintk("%s: exit with status = %d\n", __func__
, ntohl(status
));
216 #if defined(CONFIG_NFS_V4_1)
218 static unsigned decode_sessionid(struct xdr_stream
*xdr
,
219 struct nfs4_sessionid
*sid
)
222 int len
= NFS4_MAX_SESSIONID_LEN
;
224 p
= read_buf(xdr
, len
);
225 if (unlikely(p
== NULL
))
226 return htonl(NFS4ERR_RESOURCE
);
228 memcpy(sid
->data
, p
, len
);
232 static unsigned decode_rc_list(struct xdr_stream
*xdr
,
233 struct referring_call_list
*rc_list
)
239 status
= decode_sessionid(xdr
, &rc_list
->rcl_sessionid
);
243 status
= htonl(NFS4ERR_RESOURCE
);
244 p
= read_buf(xdr
, sizeof(uint32_t));
245 if (unlikely(p
== NULL
))
248 rc_list
->rcl_nrefcalls
= ntohl(*p
++);
249 if (rc_list
->rcl_nrefcalls
) {
251 rc_list
->rcl_nrefcalls
* 2 * sizeof(uint32_t));
252 if (unlikely(p
== NULL
))
254 rc_list
->rcl_refcalls
= kmalloc(rc_list
->rcl_nrefcalls
*
255 sizeof(*rc_list
->rcl_refcalls
),
257 if (unlikely(rc_list
->rcl_refcalls
== NULL
))
259 for (i
= 0; i
< rc_list
->rcl_nrefcalls
; i
++) {
260 rc_list
->rcl_refcalls
[i
].rc_sequenceid
= ntohl(*p
++);
261 rc_list
->rcl_refcalls
[i
].rc_slotid
= ntohl(*p
++);
270 static unsigned decode_cb_sequence_args(struct svc_rqst
*rqstp
,
271 struct xdr_stream
*xdr
,
272 struct cb_sequenceargs
*args
)
278 status
= decode_sessionid(xdr
, &args
->csa_sessionid
);
282 status
= htonl(NFS4ERR_RESOURCE
);
283 p
= read_buf(xdr
, 5 * sizeof(uint32_t));
284 if (unlikely(p
== NULL
))
287 args
->csa_addr
= svc_addr(rqstp
);
288 args
->csa_sequenceid
= ntohl(*p
++);
289 args
->csa_slotid
= ntohl(*p
++);
290 args
->csa_highestslotid
= ntohl(*p
++);
291 args
->csa_cachethis
= ntohl(*p
++);
292 args
->csa_nrclists
= ntohl(*p
++);
293 args
->csa_rclists
= NULL
;
294 if (args
->csa_nrclists
) {
295 args
->csa_rclists
= kmalloc(args
->csa_nrclists
*
296 sizeof(*args
->csa_rclists
),
298 if (unlikely(args
->csa_rclists
== NULL
))
301 for (i
= 0; i
< args
->csa_nrclists
; i
++) {
302 status
= decode_rc_list(xdr
, &args
->csa_rclists
[i
]);
309 dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
310 "highestslotid %u cachethis %d nrclists %u\n",
312 ((u32
*)&args
->csa_sessionid
)[0],
313 ((u32
*)&args
->csa_sessionid
)[1],
314 ((u32
*)&args
->csa_sessionid
)[2],
315 ((u32
*)&args
->csa_sessionid
)[3],
316 args
->csa_sequenceid
, args
->csa_slotid
,
317 args
->csa_highestslotid
, args
->csa_cachethis
,
320 dprintk("%s: exit with status = %d\n", __func__
, ntohl(status
));
324 for (i
= 0; i
< args
->csa_nrclists
; i
++)
325 kfree(args
->csa_rclists
[i
].rcl_refcalls
);
326 kfree(args
->csa_rclists
);
330 static unsigned decode_recallany_args(struct svc_rqst
*rqstp
,
331 struct xdr_stream
*xdr
,
332 struct cb_recallanyargs
*args
)
336 args
->craa_addr
= svc_addr(rqstp
);
337 p
= read_buf(xdr
, 4);
338 if (unlikely(p
== NULL
))
339 return htonl(NFS4ERR_BADXDR
);
340 args
->craa_objs_to_keep
= ntohl(*p
++);
341 p
= read_buf(xdr
, 4);
342 if (unlikely(p
== NULL
))
343 return htonl(NFS4ERR_BADXDR
);
344 args
->craa_type_mask
= ntohl(*p
);
349 #endif /* CONFIG_NFS_V4_1 */
351 static __be32
encode_string(struct xdr_stream
*xdr
, unsigned int len
, const char *str
)
355 p
= xdr_reserve_space(xdr
, 4 + len
);
356 if (unlikely(p
== NULL
))
357 return htonl(NFS4ERR_RESOURCE
);
358 xdr_encode_opaque(p
, str
, len
);
362 #define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE)
363 #define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY)
364 static __be32
encode_attr_bitmap(struct xdr_stream
*xdr
, const uint32_t *bitmap
, __be32
**savep
)
369 bm
[0] = htonl(bitmap
[0] & CB_SUPPORTED_ATTR0
);
370 bm
[1] = htonl(bitmap
[1] & CB_SUPPORTED_ATTR1
);
372 p
= xdr_reserve_space(xdr
, 16);
373 if (unlikely(p
== NULL
))
374 return htonl(NFS4ERR_RESOURCE
);
378 } else if (bm
[0] != 0) {
379 p
= xdr_reserve_space(xdr
, 12);
380 if (unlikely(p
== NULL
))
381 return htonl(NFS4ERR_RESOURCE
);
385 p
= xdr_reserve_space(xdr
, 8);
386 if (unlikely(p
== NULL
))
387 return htonl(NFS4ERR_RESOURCE
);
394 static __be32
encode_attr_change(struct xdr_stream
*xdr
, const uint32_t *bitmap
, uint64_t change
)
398 if (!(bitmap
[0] & FATTR4_WORD0_CHANGE
))
400 p
= xdr_reserve_space(xdr
, 8);
402 return htonl(NFS4ERR_RESOURCE
);
403 p
= xdr_encode_hyper(p
, change
);
407 static __be32
encode_attr_size(struct xdr_stream
*xdr
, const uint32_t *bitmap
, uint64_t size
)
411 if (!(bitmap
[0] & FATTR4_WORD0_SIZE
))
413 p
= xdr_reserve_space(xdr
, 8);
415 return htonl(NFS4ERR_RESOURCE
);
416 p
= xdr_encode_hyper(p
, size
);
420 static __be32
encode_attr_time(struct xdr_stream
*xdr
, const struct timespec
*time
)
424 p
= xdr_reserve_space(xdr
, 12);
426 return htonl(NFS4ERR_RESOURCE
);
427 p
= xdr_encode_hyper(p
, time
->tv_sec
);
428 *p
= htonl(time
->tv_nsec
);
432 static __be32
encode_attr_ctime(struct xdr_stream
*xdr
, const uint32_t *bitmap
, const struct timespec
*time
)
434 if (!(bitmap
[1] & FATTR4_WORD1_TIME_METADATA
))
436 return encode_attr_time(xdr
,time
);
439 static __be32
encode_attr_mtime(struct xdr_stream
*xdr
, const uint32_t *bitmap
, const struct timespec
*time
)
441 if (!(bitmap
[1] & FATTR4_WORD1_TIME_MODIFY
))
443 return encode_attr_time(xdr
,time
);
446 static __be32
encode_compound_hdr_res(struct xdr_stream
*xdr
, struct cb_compound_hdr_res
*hdr
)
450 hdr
->status
= xdr_reserve_space(xdr
, 4);
451 if (unlikely(hdr
->status
== NULL
))
452 return htonl(NFS4ERR_RESOURCE
);
453 status
= encode_string(xdr
, hdr
->taglen
, hdr
->tag
);
454 if (unlikely(status
!= 0))
456 hdr
->nops
= xdr_reserve_space(xdr
, 4);
457 if (unlikely(hdr
->nops
== NULL
))
458 return htonl(NFS4ERR_RESOURCE
);
462 static __be32
encode_op_hdr(struct xdr_stream
*xdr
, uint32_t op
, __be32 res
)
466 p
= xdr_reserve_space(xdr
, 8);
467 if (unlikely(p
== NULL
))
468 return htonl(NFS4ERR_RESOURCE
);
474 static __be32
encode_getattr_res(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
, const struct cb_getattrres
*res
)
476 __be32
*savep
= NULL
;
477 __be32 status
= res
->status
;
479 if (unlikely(status
!= 0))
481 status
= encode_attr_bitmap(xdr
, res
->bitmap
, &savep
);
482 if (unlikely(status
!= 0))
484 status
= encode_attr_change(xdr
, res
->bitmap
, res
->change_attr
);
485 if (unlikely(status
!= 0))
487 status
= encode_attr_size(xdr
, res
->bitmap
, res
->size
);
488 if (unlikely(status
!= 0))
490 status
= encode_attr_ctime(xdr
, res
->bitmap
, &res
->ctime
);
491 if (unlikely(status
!= 0))
493 status
= encode_attr_mtime(xdr
, res
->bitmap
, &res
->mtime
);
494 *savep
= htonl((unsigned int)((char *)xdr
->p
- (char *)(savep
+1)));
496 dprintk("%s: exit with status = %d\n", __func__
, ntohl(status
));
500 #if defined(CONFIG_NFS_V4_1)
502 static unsigned encode_sessionid(struct xdr_stream
*xdr
,
503 const struct nfs4_sessionid
*sid
)
506 int len
= NFS4_MAX_SESSIONID_LEN
;
508 p
= xdr_reserve_space(xdr
, len
);
509 if (unlikely(p
== NULL
))
510 return htonl(NFS4ERR_RESOURCE
);
516 static unsigned encode_cb_sequence_res(struct svc_rqst
*rqstp
,
517 struct xdr_stream
*xdr
,
518 const struct cb_sequenceres
*res
)
521 unsigned status
= res
->csr_status
;
523 if (unlikely(status
!= 0))
526 encode_sessionid(xdr
, &res
->csr_sessionid
);
528 p
= xdr_reserve_space(xdr
, 4 * sizeof(uint32_t));
529 if (unlikely(p
== NULL
))
530 return htonl(NFS4ERR_RESOURCE
);
532 *p
++ = htonl(res
->csr_sequenceid
);
533 *p
++ = htonl(res
->csr_slotid
);
534 *p
++ = htonl(res
->csr_highestslotid
);
535 *p
++ = htonl(res
->csr_target_highestslotid
);
537 dprintk("%s: exit with status = %d\n", __func__
, ntohl(status
));
542 preprocess_nfs41_op(int nop
, unsigned int op_nr
, struct callback_op
**op
)
544 if (op_nr
== OP_CB_SEQUENCE
) {
546 return htonl(NFS4ERR_SEQUENCE_POS
);
549 return htonl(NFS4ERR_OP_NOT_IN_SESSION
);
556 case OP_CB_RECALL_ANY
:
557 *op
= &callback_ops
[op_nr
];
560 case OP_CB_LAYOUTRECALL
:
561 case OP_CB_NOTIFY_DEVICEID
:
563 case OP_CB_PUSH_DELEG
:
564 case OP_CB_RECALLABLE_OBJ_AVAIL
:
565 case OP_CB_RECALL_SLOT
:
566 case OP_CB_WANTS_CANCELLED
:
567 case OP_CB_NOTIFY_LOCK
:
568 return htonl(NFS4ERR_NOTSUPP
);
571 return htonl(NFS4ERR_OP_ILLEGAL
);
574 return htonl(NFS_OK
);
577 #else /* CONFIG_NFS_V4_1 */
580 preprocess_nfs41_op(int nop
, unsigned int op_nr
, struct callback_op
**op
)
582 return htonl(NFS4ERR_MINOR_VERS_MISMATCH
);
585 #endif /* CONFIG_NFS_V4_1 */
588 preprocess_nfs4_op(unsigned int op_nr
, struct callback_op
**op
)
593 *op
= &callback_ops
[op_nr
];
596 return htonl(NFS4ERR_OP_ILLEGAL
);
599 return htonl(NFS_OK
);
602 static __be32
process_op(uint32_t minorversion
, int nop
,
603 struct svc_rqst
*rqstp
,
604 struct xdr_stream
*xdr_in
, void *argp
,
605 struct xdr_stream
*xdr_out
, void *resp
)
607 struct callback_op
*op
= &callback_ops
[0];
608 unsigned int op_nr
= OP_CB_ILLEGAL
;
613 dprintk("%s: start\n", __func__
);
614 status
= decode_op_hdr(xdr_in
, &op_nr
);
615 if (unlikely(status
)) {
616 status
= htonl(NFS4ERR_OP_ILLEGAL
);
620 dprintk("%s: minorversion=%d nop=%d op_nr=%u\n",
621 __func__
, minorversion
, nop
, op_nr
);
623 status
= minorversion
? preprocess_nfs41_op(nop
, op_nr
, &op
) :
624 preprocess_nfs4_op(op_nr
, &op
);
625 if (status
== htonl(NFS4ERR_OP_ILLEGAL
))
626 op_nr
= OP_CB_ILLEGAL
;
628 maxlen
= xdr_out
->end
- xdr_out
->p
;
629 if (maxlen
> 0 && maxlen
< PAGE_SIZE
) {
630 if (likely(status
== 0 && op
->decode_args
!= NULL
))
631 status
= op
->decode_args(rqstp
, xdr_in
, argp
);
632 if (likely(status
== 0 && op
->process_op
!= NULL
))
633 status
= op
->process_op(argp
, resp
);
635 status
= htonl(NFS4ERR_RESOURCE
);
637 res
= encode_op_hdr(xdr_out
, op_nr
, status
);
640 if (op
->encode_res
!= NULL
&& status
== 0)
641 status
= op
->encode_res(rqstp
, xdr_out
, resp
);
642 dprintk("%s: done, status = %d\n", __func__
, ntohl(status
));
647 * Decode, process and encode a COMPOUND
649 static __be32
nfs4_callback_compound(struct svc_rqst
*rqstp
, void *argp
, void *resp
)
651 struct cb_compound_hdr_arg hdr_arg
= { 0 };
652 struct cb_compound_hdr_res hdr_res
= { NULL
};
653 struct xdr_stream xdr_in
, xdr_out
;
656 unsigned int nops
= 0;
658 dprintk("%s: start\n", __func__
);
660 xdr_init_decode(&xdr_in
, &rqstp
->rq_arg
, rqstp
->rq_arg
.head
[0].iov_base
);
662 p
= (__be32
*)((char *)rqstp
->rq_res
.head
[0].iov_base
+ rqstp
->rq_res
.head
[0].iov_len
);
663 xdr_init_encode(&xdr_out
, &rqstp
->rq_res
, p
);
665 status
= decode_compound_hdr_arg(&xdr_in
, &hdr_arg
);
666 if (status
== __constant_htonl(NFS4ERR_RESOURCE
))
667 return rpc_garbage_args
;
669 hdr_res
.taglen
= hdr_arg
.taglen
;
670 hdr_res
.tag
= hdr_arg
.tag
;
671 if (encode_compound_hdr_res(&xdr_out
, &hdr_res
) != 0)
672 return rpc_system_err
;
674 while (status
== 0 && nops
!= hdr_arg
.nops
) {
675 status
= process_op(hdr_arg
.minorversion
, nops
,
676 rqstp
, &xdr_in
, argp
, &xdr_out
, resp
);
680 *hdr_res
.status
= status
;
681 *hdr_res
.nops
= htonl(nops
);
682 dprintk("%s: done, status = %u\n", __func__
, ntohl(status
));
687 * Define NFS4 callback COMPOUND ops.
689 static struct callback_op callback_ops
[] = {
691 .res_maxsize
= CB_OP_HDR_RES_MAXSZ
,
694 .process_op
= (callback_process_op_t
)nfs4_callback_getattr
,
695 .decode_args
= (callback_decode_arg_t
)decode_getattr_args
,
696 .encode_res
= (callback_encode_res_t
)encode_getattr_res
,
697 .res_maxsize
= CB_OP_GETATTR_RES_MAXSZ
,
700 .process_op
= (callback_process_op_t
)nfs4_callback_recall
,
701 .decode_args
= (callback_decode_arg_t
)decode_recall_args
,
702 .res_maxsize
= CB_OP_RECALL_RES_MAXSZ
,
704 #if defined(CONFIG_NFS_V4_1)
706 .process_op
= (callback_process_op_t
)nfs4_callback_sequence
,
707 .decode_args
= (callback_decode_arg_t
)decode_cb_sequence_args
,
708 .encode_res
= (callback_encode_res_t
)encode_cb_sequence_res
,
709 .res_maxsize
= CB_OP_SEQUENCE_RES_MAXSZ
,
711 [OP_CB_RECALL_ANY
] = {
712 .process_op
= (callback_process_op_t
)nfs4_callback_recallany
,
713 .decode_args
= (callback_decode_arg_t
)decode_recallany_args
,
714 .res_maxsize
= CB_OP_RECALLANY_RES_MAXSZ
,
716 #endif /* CONFIG_NFS_V4_1 */
720 * Define NFS4 callback procedures
722 static struct svc_procedure nfs4_callback_procedures1
[] = {
724 .pc_func
= nfs4_callback_null
,
725 .pc_decode
= (kxdrproc_t
)nfs4_decode_void
,
726 .pc_encode
= (kxdrproc_t
)nfs4_encode_void
,
730 .pc_func
= nfs4_callback_compound
,
731 .pc_encode
= (kxdrproc_t
)nfs4_encode_void
,
734 .pc_xdrressize
= NFS4_CALLBACK_BUFSIZE
,
738 struct svc_version nfs4_callback_version1
= {
740 .vs_nproc
= ARRAY_SIZE(nfs4_callback_procedures1
),
741 .vs_proc
= nfs4_callback_procedures1
,
742 .vs_xdrsize
= NFS4_CALLBACK_XDRSIZE
,
746 struct svc_version nfs4_callback_version4
= {
748 .vs_nproc
= ARRAY_SIZE(nfs4_callback_procedures1
),
749 .vs_proc
= nfs4_callback_procedures1
,
750 .vs_xdrsize
= NFS4_CALLBACK_XDRSIZE
,