8 #include <linux/kernel.h>
10 #include <linux/nfs4.h>
11 #include <linux/nfs_fs.h>
14 #include <linux/slab.h>
20 #define CB_OP_TAGLEN_MAXSZ (512)
21 #define CB_OP_HDR_RES_MAXSZ (2 + CB_OP_TAGLEN_MAXSZ)
22 #define CB_OP_GETATTR_BITMAP_MAXSZ (4)
23 #define CB_OP_GETATTR_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
24 CB_OP_GETATTR_BITMAP_MAXSZ + \
26 #define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
28 #if defined(CONFIG_NFS_V4_1)
29 #define CB_OP_LAYOUTRECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
30 #define CB_OP_DEVICENOTIFY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
31 #define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
33 #define CB_OP_RECALLANY_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
34 #define CB_OP_RECALLSLOT_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
37 #define NFSDBG_FACILITY NFSDBG_CALLBACK
40 #define NFS4ERR_RESOURCE_HDR 11050
64 return xdr_argsize_check(rqstp, p);
69 return xdr_ressize_check(rqstp, p);
72 static __be32 *read_buf(
struct xdr_stream *xdr,
int nbytes)
82 static __be32 decode_string(
struct xdr_stream *xdr,
unsigned int *len,
const char **
str)
92 p = read_buf(xdr, *len);
95 *str = (
const char *)p;
102 static __be32 decode_fh(
struct xdr_stream *xdr,
struct nfs_fh *fh)
106 p = read_buf(xdr, 4);
112 p = read_buf(xdr, fh->
size);
123 unsigned int attrlen;
125 p = read_buf(xdr, 4);
129 p = read_buf(xdr, attrlen << 2);
133 bitmap[0] =
ntohl(*p++);
135 bitmap[1] =
ntohl(*p);
155 status = decode_string(xdr, &hdr->
taglen, &hdr->
tag);
160 printk(
"NFS: NFSv4 CALLBACK %s: client sent tag of length %u\n",
164 p = read_buf(xdr, 12);
173 "illegal minor version %u!\n",
178 dprintk(
"%s: minorversion %d nops %d\n", __func__,
183 static __be32 decode_op_hdr(
struct xdr_stream *xdr,
unsigned int *
op)
186 p = read_buf(xdr, 4);
197 status = decode_fh(xdr, &args->
fh);
200 args->
addr = svc_addr(rqstp);
201 status = decode_bitmap(xdr, args->
bitmap);
203 dprintk(
"%s: exit with status = %d\n", __func__,
ntohl(status));
212 args->
addr = svc_addr(rqstp);
213 status = decode_stateid(xdr, &args->
stateid);
216 p = read_buf(xdr, 4);
222 status = decode_fh(xdr, &args->
fh);
224 dprintk(
"%s: exit with status = %d\n", __func__,
ntohl(status));
228 #if defined(CONFIG_NFS_V4_1)
231 struct xdr_stream *xdr,
232 struct cb_layoutrecallargs *args)
238 args->cbl_addr = svc_addr(rqstp);
239 p = read_buf(xdr, 4 *
sizeof(
uint32_t));
245 args->cbl_layout_type =
ntohl(*p++);
249 iomode =
ntohl(*p++);
250 args->cbl_layoutchanged =
ntohl(*p++);
251 args->cbl_recall_type =
ntohl(*p++);
254 args->cbl_range.iomode = iomode;
255 status = decode_fh(xdr, &args->cbl_fh);
259 p = read_buf(xdr, 2 *
sizeof(
uint64_t));
264 p = xdr_decode_hyper(p, &args->cbl_range.offset);
265 p = xdr_decode_hyper(p, &args->cbl_range.length);
266 status = decode_stateid(xdr, &args->cbl_stateid);
270 p = read_buf(xdr, 2 *
sizeof(
uint64_t));
275 p = xdr_decode_hyper(p, &args->cbl_fsid.major);
276 p = xdr_decode_hyper(p, &args->cbl_fsid.minor);
277 }
else if (args->cbl_recall_type !=
RETURN_ALL) {
281 dprintk(
"%s: ltype 0x%x iomode %d changed %d recall_type %d\n",
283 args->cbl_layout_type, iomode,
284 args->cbl_layoutchanged, args->cbl_recall_type);
286 dprintk(
"%s: exit with status = %d\n", __func__,
ntohl(status));
292 struct xdr_stream *xdr,
293 struct cb_devicenotifyargs *args)
302 p = read_buf(xdr,
sizeof(
uint32_t));
310 if (n >
ULONG_MAX /
sizeof(*args->devs)) {
322 for (i = 0; i <
n; i++) {
323 struct cb_devicenotifyitem *
dev = &args->devs[
i];
336 dev->cbd_notify_type =
ntohl(*p++);
351 dev->cbd_layout_type =
ntohl(*p++);
356 p = read_buf(xdr,
sizeof(
uint32_t));
361 dev->cbd_immediate =
ntohl(*p++);
363 dev->cbd_immediate = 0;
368 dprintk(
"%s: type %d layout 0x%x immediate %d\n",
369 __func__, dev->cbd_notify_type, dev->cbd_layout_type,
373 dprintk(
"%s: status %d ndevs %d\n",
374 __func__,
ntohl(status), args->ndevs);
381 static __be32 decode_sessionid(
struct xdr_stream *xdr,
387 p = read_buf(xdr, len);
395 static __be32 decode_rc_list(
struct xdr_stream *xdr,
396 struct referring_call_list *rc_list)
402 status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
407 p = read_buf(xdr,
sizeof(
uint32_t));
411 rc_list->rcl_nrefcalls =
ntohl(*p++);
412 if (rc_list->rcl_nrefcalls) {
414 rc_list->rcl_nrefcalls * 2 *
sizeof(
uint32_t));
417 rc_list->rcl_refcalls =
kmalloc(rc_list->rcl_nrefcalls *
418 sizeof(*rc_list->rcl_refcalls),
422 for (i = 0; i < rc_list->rcl_nrefcalls; i++) {
423 rc_list->rcl_refcalls[
i].rc_sequenceid =
ntohl(*p++);
424 rc_list->rcl_refcalls[
i].rc_slotid =
ntohl(*p++);
434 struct xdr_stream *xdr,
435 struct cb_sequenceargs *args)
441 status = decode_sessionid(xdr, &args->csa_sessionid);
446 p = read_buf(xdr, 5 *
sizeof(
uint32_t));
450 args->csa_addr = svc_addr(rqstp);
451 args->csa_sequenceid =
ntohl(*p++);
452 args->csa_slotid =
ntohl(*p++);
453 args->csa_highestslotid =
ntohl(*p++);
454 args->csa_cachethis =
ntohl(*p++);
455 args->csa_nrclists =
ntohl(*p++);
456 args->csa_rclists =
NULL;
457 if (args->csa_nrclists) {
458 args->csa_rclists = kmalloc_array(args->csa_nrclists,
459 sizeof(*args->csa_rclists),
464 for (i = 0; i < args->csa_nrclists; i++) {
465 status = decode_rc_list(xdr, &args->csa_rclists[i]);
472 dprintk(
"%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
473 "highestslotid %u cachethis %d nrclists %u\n",
475 ((
u32 *)&args->csa_sessionid)[0],
476 ((
u32 *)&args->csa_sessionid)[1],
477 ((
u32 *)&args->csa_sessionid)[2],
478 ((
u32 *)&args->csa_sessionid)[3],
479 args->csa_sequenceid, args->csa_slotid,
480 args->csa_highestslotid, args->csa_cachethis,
483 dprintk(
"%s: exit with status = %d\n", __func__,
ntohl(status));
487 for (i = 0; i < args->csa_nrclists; i++)
488 kfree(args->csa_rclists[i].rcl_refcalls);
489 kfree(args->csa_rclists);
494 struct xdr_stream *xdr,
495 struct cb_recallanyargs *args)
500 args->craa_addr = svc_addr(rqstp);
501 p = read_buf(xdr, 4);
504 args->craa_objs_to_keep =
ntohl(*p++);
505 status = decode_bitmap(xdr, bitmap);
508 args->craa_type_mask = bitmap[0];
514 struct xdr_stream *xdr,
515 struct cb_recallslotargs *args)
519 args->crsa_addr = svc_addr(rqstp);
520 p = read_buf(xdr, 4);
523 args->crsa_target_max_slots =
ntohl(*p++);
529 static __be32 encode_string(
struct xdr_stream *xdr,
unsigned int len,
const char *str)
540 #define CB_SUPPORTED_ATTR0 (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE)
541 #define CB_SUPPORTED_ATTR1 (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY)
542 static __be32 encode_attr_bitmap(
struct xdr_stream *xdr,
const uint32_t *bitmap,
__be32 **savep)
556 }
else if (bm[0] != 0) {
581 p = xdr_encode_hyper(p, change);
594 p = xdr_encode_hyper(p, size);
605 p = xdr_encode_hyper(p, time->
tv_sec);
610 static __be32 encode_attr_ctime(
struct xdr_stream *xdr,
const uint32_t *bitmap,
const struct timespec *time)
614 return encode_attr_time(xdr,time);
617 static __be32 encode_attr_mtime(
struct xdr_stream *xdr,
const uint32_t *bitmap,
const struct timespec *time)
621 return encode_attr_time(xdr,time);
631 status = encode_string(xdr, hdr->
taglen, hdr->
tag);
659 status = encode_attr_bitmap(xdr, res->
bitmap, &savep);
665 status = encode_attr_size(xdr, res->
bitmap, res->
size);
668 status = encode_attr_ctime(xdr, res->
bitmap, &res->
ctime);
671 status = encode_attr_mtime(xdr, res->
bitmap, &res->
mtime);
672 *savep =
htonl((
unsigned int)((
char *)xdr->p - (
char *)(savep+1)));
674 dprintk(
"%s: exit with status = %d\n", __func__,
ntohl(status));
678 #if defined(CONFIG_NFS_V4_1)
680 static __be32 encode_sessionid(
struct xdr_stream *xdr,
695 struct xdr_stream *xdr,
696 const struct cb_sequenceres *res)
699 __be32 status = res->csr_status;
704 encode_sessionid(xdr, &res->csr_sessionid);
710 *p++ =
htonl(res->csr_sequenceid);
711 *p++ =
htonl(res->csr_slotid);
712 *p++ =
htonl(res->csr_highestslotid);
713 *p++ =
htonl(res->csr_target_highestslotid);
715 dprintk(
"%s: exit with status = %d\n", __func__,
ntohl(status));
720 preprocess_nfs41_op(
int nop,
unsigned int op_nr,
struct callback_op **op)
738 *op = &callback_ops[op_nr];
755 static void nfs4_callback_free_slot(
struct nfs4_session *session)
757 struct nfs4_slot_table *tbl = &session->bc_slot_table;
759 spin_lock(&tbl->slot_tbl_lock);
765 nfs4_check_drain_bc_complete(session);
766 spin_unlock(&tbl->slot_tbl_lock);
772 nfs4_callback_free_slot(cps->
clp->cl_session);
778 preprocess_nfs41_op(
int nop,
unsigned int op_nr,
struct callback_op **op)
789 preprocess_nfs4_op(
unsigned int op_nr,
struct callback_op **op)
794 *op = &callback_ops[op_nr];
805 struct xdr_stream *xdr_in,
void *
argp,
806 struct xdr_stream *xdr_out,
void *
resp,
815 dprintk(
"%s: start\n", __func__);
816 status = decode_op_hdr(xdr_in, &op_nr);
820 dprintk(
"%s: minorversion=%d nop=%d op_nr=%u\n",
821 __func__, minorversion, nop, op_nr);
823 status = minorversion ? preprocess_nfs41_op(nop, op_nr, &op) :
824 preprocess_nfs4_op(op_nr, &op);
835 maxlen = xdr_out->end - xdr_out->p;
844 res = encode_op_hdr(xdr_out, op_nr, status);
848 status = op->
encode_res(rqstp, xdr_out, resp);
849 dprintk(
"%s: done, status = %d\n", __func__,
ntohl(status));
856 static __be32 nfs4_callback_compound(
struct svc_rqst *rqstp,
void *argp,
void *resp)
860 struct xdr_stream xdr_in, xdr_out;
868 unsigned int nops = 0;
870 dprintk(
"%s: start\n", __func__);
874 p = (
__be32*)((
char *)rqstp->
rq_res.head[0].iov_base + rqstp->
rq_res.head[0].iov_len);
877 status = decode_compound_hdr_arg(&xdr_in, &hdr_arg);
879 return rpc_garbage_args;
884 return rpc_drop_reply;
888 hdr_res.
tag = hdr_arg.
tag;
889 if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0)
890 return rpc_system_err;
892 while (status == 0 && nops != hdr_arg.
nops) {
894 &xdr_in, argp, &xdr_out, resp, &cps);
907 nfs4_cb_free_slot(&cps);
909 dprintk(
"%s: done, status = %u\n", __func__,
ntohl(status));
931 #if defined(CONFIG_NFS_V4_1)
936 .res_maxsize = CB_OP_LAYOUTRECALL_RES_MAXSZ,
942 .res_maxsize = CB_OP_DEVICENOTIFY_RES_MAXSZ,
953 .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ,
958 .res_maxsize = CB_OP_RECALLSLOT_RES_MAXSZ,
968 .pc_func = nfs4_callback_null,
969 .pc_decode = (kxdrproc_t)nfs4_decode_void,
970 .
pc_encode = (kxdrproc_t)nfs4_encode_void,
974 .pc_func = nfs4_callback_compound,
975 .pc_encode = (kxdrproc_t)nfs4_encode_void,
984 .vs_nproc =
ARRAY_SIZE(nfs4_callback_procedures1),
985 .vs_proc = nfs4_callback_procedures1,
993 .vs_nproc =
ARRAY_SIZE(nfs4_callback_procedures1),
994 .vs_proc = nfs4_callback_procedures1,