hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/nfs/nfs42xdr.c
....@@ -21,7 +21,10 @@
2121 #define encode_copy_maxsz (op_encode_hdr_maxsz + \
2222 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
2323 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
24
- 2 + 2 + 2 + 1 + 1 + 1)
24
+ 2 + 2 + 2 + 1 + 1 + 1 +\
25
+ 1 + /* One cnr_source_server */\
26
+ 1 + /* nl4_type */ \
27
+ 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
2528 #define decode_copy_maxsz (op_decode_hdr_maxsz + \
2629 NFS42_WRITE_RES_SIZE + \
2730 1 /* cr_consecutive */ + \
....@@ -29,9 +32,28 @@
2932 #define encode_offload_cancel_maxsz (op_encode_hdr_maxsz + \
3033 XDR_QUADLEN(NFS4_STATEID_SIZE))
3134 #define decode_offload_cancel_maxsz (op_decode_hdr_maxsz)
35
+#define encode_copy_notify_maxsz (op_encode_hdr_maxsz + \
36
+ XDR_QUADLEN(NFS4_STATEID_SIZE) + \
37
+ 1 + /* nl4_type */ \
38
+ 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
39
+#define decode_copy_notify_maxsz (op_decode_hdr_maxsz + \
40
+ 3 + /* cnr_lease_time */\
41
+ XDR_QUADLEN(NFS4_STATEID_SIZE) + \
42
+ 1 + /* Support 1 cnr_source_server */\
43
+ 1 + /* nl4_type */ \
44
+ 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
3245 #define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
3346 encode_fallocate_maxsz)
3447 #define decode_deallocate_maxsz (op_decode_hdr_maxsz)
48
+#define encode_read_plus_maxsz (op_encode_hdr_maxsz + \
49
+ encode_stateid_maxsz + 3)
50
+#define NFS42_READ_PLUS_SEGMENT_SIZE (1 /* data_content4 */ + \
51
+ 2 /* data_info4.di_offset */ + \
52
+ 2 /* data_info4.di_length */)
53
+#define decode_read_plus_maxsz (op_decode_hdr_maxsz + \
54
+ 1 /* rpr_eof */ + \
55
+ 1 /* rpr_contents count */ + \
56
+ 2 * NFS42_READ_PLUS_SEGMENT_SIZE)
3557 #define encode_seek_maxsz (op_encode_hdr_maxsz + \
3658 encode_stateid_maxsz + \
3759 2 /* offset */ + \
....@@ -51,6 +73,15 @@
5173 1 /* opaque devaddr4 length */ + \
5274 XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
5375 #define decode_layoutstats_maxsz (op_decode_hdr_maxsz)
76
+#define encode_device_error_maxsz (XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
77
+ 1 /* status */ + 1 /* opnum */)
78
+#define encode_layouterror_maxsz (op_decode_hdr_maxsz + \
79
+ 2 /* offset */ + \
80
+ 2 /* length */ + \
81
+ encode_stateid_maxsz + \
82
+ 1 /* Array size */ + \
83
+ encode_device_error_maxsz)
84
+#define decode_layouterror_maxsz (op_decode_hdr_maxsz)
5485 #define encode_clone_maxsz (encode_stateid_maxsz + \
5586 encode_stateid_maxsz + \
5687 2 /* src offset */ + \
....@@ -90,6 +121,12 @@
90121 decode_sequence_maxsz + \
91122 decode_putfh_maxsz + \
92123 decode_offload_cancel_maxsz)
124
+#define NFS4_enc_copy_notify_sz (compound_encode_hdr_maxsz + \
125
+ encode_putfh_maxsz + \
126
+ encode_copy_notify_maxsz)
127
+#define NFS4_dec_copy_notify_sz (compound_decode_hdr_maxsz + \
128
+ decode_putfh_maxsz + \
129
+ decode_copy_notify_maxsz)
93130 #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \
94131 encode_sequence_maxsz + \
95132 encode_putfh_maxsz + \
....@@ -100,6 +137,14 @@
100137 decode_putfh_maxsz + \
101138 decode_deallocate_maxsz + \
102139 decode_getattr_maxsz)
140
+#define NFS4_enc_read_plus_sz (compound_encode_hdr_maxsz + \
141
+ encode_sequence_maxsz + \
142
+ encode_putfh_maxsz + \
143
+ encode_read_plus_maxsz)
144
+#define NFS4_dec_read_plus_sz (compound_decode_hdr_maxsz + \
145
+ decode_sequence_maxsz + \
146
+ decode_putfh_maxsz + \
147
+ decode_read_plus_maxsz)
103148 #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \
104149 encode_sequence_maxsz + \
105150 encode_putfh_maxsz + \
....@@ -116,6 +161,16 @@
116161 decode_sequence_maxsz + \
117162 decode_putfh_maxsz + \
118163 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
164
+#define NFS4_enc_layouterror_sz (compound_encode_hdr_maxsz + \
165
+ encode_sequence_maxsz + \
166
+ encode_putfh_maxsz + \
167
+ NFS42_LAYOUTERROR_MAX * \
168
+ encode_layouterror_maxsz)
169
+#define NFS4_dec_layouterror_sz (compound_decode_hdr_maxsz + \
170
+ decode_sequence_maxsz + \
171
+ decode_putfh_maxsz + \
172
+ NFS42_LAYOUTERROR_MAX * \
173
+ decode_layouterror_maxsz)
119174 #define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \
120175 encode_sequence_maxsz + \
121176 encode_putfh_maxsz + \
....@@ -130,6 +185,78 @@
130185 decode_putfh_maxsz + \
131186 decode_clone_maxsz + \
132187 decode_getattr_maxsz)
188
+
189
+/* Not limited by NFS itself, limited by the generic xattr code */
190
+#define nfs4_xattr_name_maxsz XDR_QUADLEN(XATTR_NAME_MAX)
191
+
192
+#define encode_getxattr_maxsz (op_encode_hdr_maxsz + 1 + \
193
+ nfs4_xattr_name_maxsz)
194
+#define decode_getxattr_maxsz (op_decode_hdr_maxsz + 1 + 1)
195
+#define encode_setxattr_maxsz (op_encode_hdr_maxsz + \
196
+ 1 + nfs4_xattr_name_maxsz + 1)
197
+#define decode_setxattr_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
198
+#define encode_listxattrs_maxsz (op_encode_hdr_maxsz + 2 + 1)
199
+#define decode_listxattrs_maxsz (op_decode_hdr_maxsz + 2 + 1 + 1 + 1)
200
+#define encode_removexattr_maxsz (op_encode_hdr_maxsz + 1 + \
201
+ nfs4_xattr_name_maxsz)
202
+#define decode_removexattr_maxsz (op_decode_hdr_maxsz + \
203
+ decode_change_info_maxsz)
204
+
205
+#define NFS4_enc_getxattr_sz (compound_encode_hdr_maxsz + \
206
+ encode_sequence_maxsz + \
207
+ encode_putfh_maxsz + \
208
+ encode_getxattr_maxsz)
209
+#define NFS4_dec_getxattr_sz (compound_decode_hdr_maxsz + \
210
+ decode_sequence_maxsz + \
211
+ decode_putfh_maxsz + \
212
+ decode_getxattr_maxsz)
213
+#define NFS4_enc_setxattr_sz (compound_encode_hdr_maxsz + \
214
+ encode_sequence_maxsz + \
215
+ encode_putfh_maxsz + \
216
+ encode_setxattr_maxsz)
217
+#define NFS4_dec_setxattr_sz (compound_decode_hdr_maxsz + \
218
+ decode_sequence_maxsz + \
219
+ decode_putfh_maxsz + \
220
+ decode_setxattr_maxsz)
221
+#define NFS4_enc_listxattrs_sz (compound_encode_hdr_maxsz + \
222
+ encode_sequence_maxsz + \
223
+ encode_putfh_maxsz + \
224
+ encode_listxattrs_maxsz)
225
+#define NFS4_dec_listxattrs_sz (compound_decode_hdr_maxsz + \
226
+ decode_sequence_maxsz + \
227
+ decode_putfh_maxsz + \
228
+ decode_listxattrs_maxsz)
229
+#define NFS4_enc_removexattr_sz (compound_encode_hdr_maxsz + \
230
+ encode_sequence_maxsz + \
231
+ encode_putfh_maxsz + \
232
+ encode_removexattr_maxsz)
233
+#define NFS4_dec_removexattr_sz (compound_decode_hdr_maxsz + \
234
+ decode_sequence_maxsz + \
235
+ decode_putfh_maxsz + \
236
+ decode_removexattr_maxsz)
237
+
238
+/*
239
+ * These values specify the maximum amount of data that is not
240
+ * associated with the extended attribute name or extended
241
+ * attribute list in the SETXATTR, GETXATTR and LISTXATTR
242
+ * respectively.
243
+ */
244
+const u32 nfs42_maxsetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
245
+ compound_encode_hdr_maxsz +
246
+ encode_sequence_maxsz +
247
+ encode_putfh_maxsz + 1 +
248
+ nfs4_xattr_name_maxsz)
249
+ * XDR_UNIT);
250
+
251
+const u32 nfs42_maxgetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
252
+ compound_decode_hdr_maxsz +
253
+ decode_sequence_maxsz +
254
+ decode_putfh_maxsz + 1) * XDR_UNIT);
255
+
256
+const u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
257
+ compound_decode_hdr_maxsz +
258
+ decode_sequence_maxsz +
259
+ decode_putfh_maxsz + 3) * XDR_UNIT);
133260
134261 static void encode_fallocate(struct xdr_stream *xdr,
135262 const struct nfs42_falloc_args *args)
....@@ -147,6 +274,26 @@
147274 encode_fallocate(xdr, args);
148275 }
149276
277
+static void encode_nl4_server(struct xdr_stream *xdr,
278
+ const struct nl4_server *ns)
279
+{
280
+ encode_uint32(xdr, ns->nl4_type);
281
+ switch (ns->nl4_type) {
282
+ case NL4_NAME:
283
+ case NL4_URL:
284
+ encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
285
+ break;
286
+ case NL4_NETADDR:
287
+ encode_string(xdr, ns->u.nl4_addr.netid_len,
288
+ ns->u.nl4_addr.netid);
289
+ encode_string(xdr, ns->u.nl4_addr.addr_len,
290
+ ns->u.nl4_addr.addr);
291
+ break;
292
+ default:
293
+ WARN_ON_ONCE(1);
294
+ }
295
+}
296
+
150297 static void encode_copy(struct xdr_stream *xdr,
151298 const struct nfs42_copy_args *args,
152299 struct compound_hdr *hdr)
....@@ -161,7 +308,12 @@
161308
162309 encode_uint32(xdr, 1); /* consecutive = true */
163310 encode_uint32(xdr, args->sync);
164
- encode_uint32(xdr, 0); /* src server list */
311
+ if (args->cp_src == NULL) { /* intra-ssc */
312
+ encode_uint32(xdr, 0); /* no src server list */
313
+ return;
314
+ }
315
+ encode_uint32(xdr, 1); /* supporting 1 server */
316
+ encode_nl4_server(xdr, args->cp_src);
165317 }
166318
167319 static void encode_offload_cancel(struct xdr_stream *xdr,
....@@ -172,12 +324,31 @@
172324 encode_nfs4_stateid(xdr, &args->osa_stateid);
173325 }
174326
327
+static void encode_copy_notify(struct xdr_stream *xdr,
328
+ const struct nfs42_copy_notify_args *args,
329
+ struct compound_hdr *hdr)
330
+{
331
+ encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
332
+ encode_nfs4_stateid(xdr, &args->cna_src_stateid);
333
+ encode_nl4_server(xdr, &args->cna_dst);
334
+}
335
+
175336 static void encode_deallocate(struct xdr_stream *xdr,
176337 const struct nfs42_falloc_args *args,
177338 struct compound_hdr *hdr)
178339 {
179340 encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
180341 encode_fallocate(xdr, args);
342
+}
343
+
344
+static void encode_read_plus(struct xdr_stream *xdr,
345
+ const struct nfs_pgio_args *args,
346
+ struct compound_hdr *hdr)
347
+{
348
+ encode_op_hdr(xdr, OP_READ_PLUS, decode_read_plus_maxsz, hdr);
349
+ encode_nfs4_stateid(xdr, &args->stateid);
350
+ encode_uint64(xdr, args->offset);
351
+ encode_uint32(xdr, args->count);
181352 }
182353
183354 static void encode_seek(struct xdr_stream *xdr,
....@@ -231,6 +402,238 @@
231402 p = xdr_encode_hyper(p, args->src_offset);
232403 p = xdr_encode_hyper(p, args->dst_offset);
233404 xdr_encode_hyper(p, args->count);
405
+}
406
+
407
+static void encode_device_error(struct xdr_stream *xdr,
408
+ const struct nfs42_device_error *error)
409
+{
410
+ __be32 *p;
411
+
412
+ p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
413
+ p = xdr_encode_opaque_fixed(p, error->dev_id.data,
414
+ NFS4_DEVICEID4_SIZE);
415
+ *p++ = cpu_to_be32(error->status);
416
+ *p = cpu_to_be32(error->opnum);
417
+}
418
+
419
+static void encode_layouterror(struct xdr_stream *xdr,
420
+ const struct nfs42_layout_error *args,
421
+ struct compound_hdr *hdr)
422
+{
423
+ __be32 *p;
424
+
425
+ encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
426
+ p = reserve_space(xdr, 8 + 8);
427
+ p = xdr_encode_hyper(p, args->offset);
428
+ p = xdr_encode_hyper(p, args->length);
429
+ encode_nfs4_stateid(xdr, &args->stateid);
430
+ p = reserve_space(xdr, 4);
431
+ *p = cpu_to_be32(1);
432
+ encode_device_error(xdr, &args->errors[0]);
433
+}
434
+
435
+static void encode_setxattr(struct xdr_stream *xdr,
436
+ const struct nfs42_setxattrargs *arg,
437
+ struct compound_hdr *hdr)
438
+{
439
+ __be32 *p;
440
+
441
+ BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
442
+ BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
443
+
444
+ encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
445
+ p = reserve_space(xdr, 4);
446
+ *p = cpu_to_be32(arg->xattr_flags);
447
+ encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
448
+ p = reserve_space(xdr, 4);
449
+ *p = cpu_to_be32(arg->xattr_len);
450
+ if (arg->xattr_len)
451
+ xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
452
+}
453
+
454
+static int decode_setxattr(struct xdr_stream *xdr,
455
+ struct nfs4_change_info *cinfo)
456
+{
457
+ int status;
458
+
459
+ status = decode_op_hdr(xdr, OP_SETXATTR);
460
+ if (status)
461
+ goto out;
462
+ status = decode_change_info(xdr, cinfo);
463
+out:
464
+ return status;
465
+}
466
+
467
+
468
+static void encode_getxattr(struct xdr_stream *xdr, const char *name,
469
+ struct compound_hdr *hdr)
470
+{
471
+ encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
472
+ encode_string(xdr, strlen(name), name);
473
+}
474
+
475
+static int decode_getxattr(struct xdr_stream *xdr,
476
+ struct nfs42_getxattrres *res,
477
+ struct rpc_rqst *req)
478
+{
479
+ int status;
480
+ __be32 *p;
481
+ u32 len, rdlen;
482
+
483
+ status = decode_op_hdr(xdr, OP_GETXATTR);
484
+ if (status)
485
+ return status;
486
+
487
+ p = xdr_inline_decode(xdr, 4);
488
+ if (unlikely(!p))
489
+ return -EIO;
490
+
491
+ len = be32_to_cpup(p);
492
+ if (len > req->rq_rcv_buf.page_len)
493
+ return -ERANGE;
494
+
495
+ res->xattr_len = len;
496
+
497
+ if (len > 0) {
498
+ rdlen = xdr_read_pages(xdr, len);
499
+ if (rdlen < len)
500
+ return -EIO;
501
+ }
502
+
503
+ return 0;
504
+}
505
+
506
+static void encode_removexattr(struct xdr_stream *xdr, const char *name,
507
+ struct compound_hdr *hdr)
508
+{
509
+ encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
510
+ encode_string(xdr, strlen(name), name);
511
+}
512
+
513
+
514
+static int decode_removexattr(struct xdr_stream *xdr,
515
+ struct nfs4_change_info *cinfo)
516
+{
517
+ int status;
518
+
519
+ status = decode_op_hdr(xdr, OP_REMOVEXATTR);
520
+ if (status)
521
+ goto out;
522
+
523
+ status = decode_change_info(xdr, cinfo);
524
+out:
525
+ return status;
526
+}
527
+
528
+static void encode_listxattrs(struct xdr_stream *xdr,
529
+ const struct nfs42_listxattrsargs *arg,
530
+ struct compound_hdr *hdr)
531
+{
532
+ __be32 *p;
533
+
534
+ encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr);
535
+
536
+ p = reserve_space(xdr, 12);
537
+ if (unlikely(!p))
538
+ return;
539
+
540
+ p = xdr_encode_hyper(p, arg->cookie);
541
+ /*
542
+ * RFC 8276 says to specify the full max length of the LISTXATTRS
543
+ * XDR reply. Count is set to the XDR length of the names array
544
+ * plus the EOF marker. So, add the cookie and the names count.
545
+ */
546
+ *p = cpu_to_be32(arg->count + 8 + 4);
547
+}
548
+
549
+static int decode_listxattrs(struct xdr_stream *xdr,
550
+ struct nfs42_listxattrsres *res)
551
+{
552
+ int status;
553
+ __be32 *p;
554
+ u32 count, len, ulen;
555
+ size_t left, copied;
556
+ char *buf;
557
+
558
+ status = decode_op_hdr(xdr, OP_LISTXATTRS);
559
+ if (status) {
560
+ /*
561
+ * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
562
+ * should be translated to ERANGE.
563
+ */
564
+ if (status == -ETOOSMALL)
565
+ status = -ERANGE;
566
+ goto out;
567
+ }
568
+
569
+ p = xdr_inline_decode(xdr, 8);
570
+ if (unlikely(!p))
571
+ return -EIO;
572
+
573
+ xdr_decode_hyper(p, &res->cookie);
574
+
575
+ p = xdr_inline_decode(xdr, 4);
576
+ if (unlikely(!p))
577
+ return -EIO;
578
+
579
+ left = res->xattr_len;
580
+ buf = res->xattr_buf;
581
+
582
+ count = be32_to_cpup(p);
583
+ copied = 0;
584
+
585
+ /*
586
+ * We have asked for enough room to encode the maximum number
587
+ * of possible attribute names, so everything should fit.
588
+ *
589
+ * But, don't rely on that assumption. Just decode entries
590
+ * until they don't fit anymore, just in case the server did
591
+ * something odd.
592
+ */
593
+ while (count--) {
594
+ p = xdr_inline_decode(xdr, 4);
595
+ if (unlikely(!p))
596
+ return -EIO;
597
+
598
+ len = be32_to_cpup(p);
599
+ if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
600
+ status = -ERANGE;
601
+ goto out;
602
+ }
603
+
604
+ p = xdr_inline_decode(xdr, len);
605
+ if (unlikely(!p))
606
+ return -EIO;
607
+
608
+ ulen = len + XATTR_USER_PREFIX_LEN + 1;
609
+ if (buf) {
610
+ if (ulen > left) {
611
+ status = -ERANGE;
612
+ goto out;
613
+ }
614
+
615
+ memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
616
+ memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
617
+
618
+ buf[ulen - 1] = 0;
619
+ buf += ulen;
620
+ left -= ulen;
621
+ }
622
+ copied += ulen;
623
+ }
624
+
625
+ p = xdr_inline_decode(xdr, 4);
626
+ if (unlikely(!p))
627
+ return -EIO;
628
+
629
+ res->eof = be32_to_cpup(p);
630
+ res->copied = copied;
631
+
632
+out:
633
+ if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
634
+ status = -E2BIG;
635
+
636
+ return status;
234637 }
235638
236639 /*
....@@ -308,6 +711,25 @@
308711 }
309712
310713 /*
714
+ * Encode COPY_NOTIFY request
715
+ */
716
+static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
717
+ struct xdr_stream *xdr,
718
+ const void *data)
719
+{
720
+ const struct nfs42_copy_notify_args *args = data;
721
+ struct compound_hdr hdr = {
722
+ .minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
723
+ };
724
+
725
+ encode_compound_hdr(xdr, req, &hdr);
726
+ encode_sequence(xdr, &args->cna_seq_args, &hdr);
727
+ encode_putfh(xdr, args->cna_src_fh, &hdr);
728
+ encode_copy_notify(xdr, args, &hdr);
729
+ encode_nops(&hdr);
730
+}
731
+
732
+/*
311733 * Encode DEALLOCATE request
312734 */
313735 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
....@@ -324,6 +746,28 @@
324746 encode_putfh(xdr, args->falloc_fh, &hdr);
325747 encode_deallocate(xdr, args, &hdr);
326748 encode_getfattr(xdr, args->falloc_bitmask, &hdr);
749
+ encode_nops(&hdr);
750
+}
751
+
752
+/*
753
+ * Encode READ_PLUS request
754
+ */
755
+static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
756
+ struct xdr_stream *xdr,
757
+ const void *data)
758
+{
759
+ const struct nfs_pgio_args *args = data;
760
+ struct compound_hdr hdr = {
761
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
762
+ };
763
+
764
+ encode_compound_hdr(xdr, req, &hdr);
765
+ encode_sequence(xdr, &args->seq_args, &hdr);
766
+ encode_putfh(xdr, args->fh, &hdr);
767
+ encode_read_plus(xdr, args, &hdr);
768
+
769
+ rpc_prepare_reply_pages(req, args->pages, args->pgbase,
770
+ args->count, hdr.replen);
327771 encode_nops(&hdr);
328772 }
329773
....@@ -391,6 +835,27 @@
391835 encode_nops(&hdr);
392836 }
393837
838
+/*
839
+ * Encode LAYOUTERROR request
840
+ */
841
+static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
842
+ struct xdr_stream *xdr,
843
+ const void *data)
844
+{
845
+ const struct nfs42_layouterror_args *args = data;
846
+ struct compound_hdr hdr = {
847
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
848
+ };
849
+ int i;
850
+
851
+ encode_compound_hdr(xdr, req, &hdr);
852
+ encode_sequence(xdr, &args->seq_args, &hdr);
853
+ encode_putfh(xdr, NFS_FH(args->inode), &hdr);
854
+ for (i = 0; i < args->num_errors; i++)
855
+ encode_layouterror(xdr, &args->errors[i], &hdr);
856
+ encode_nops(&hdr);
857
+}
858
+
394859 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
395860 {
396861 return decode_op_hdr(xdr, OP_ALLOCATE);
....@@ -404,7 +869,7 @@
404869
405870 p = xdr_inline_decode(xdr, 4);
406871 if (unlikely(!p))
407
- goto out_overflow;
872
+ return -EIO;
408873 count = be32_to_cpup(p);
409874 if (count > 1)
410875 return -EREMOTEIO;
....@@ -412,18 +877,66 @@
412877 status = decode_opaque_fixed(xdr, &res->stateid,
413878 NFS4_STATEID_SIZE);
414879 if (unlikely(status))
415
- goto out_overflow;
880
+ return -EIO;
416881 }
417882 p = xdr_inline_decode(xdr, 8 + 4);
418883 if (unlikely(!p))
419
- goto out_overflow;
884
+ return -EIO;
420885 p = xdr_decode_hyper(p, &res->count);
421886 res->verifier.committed = be32_to_cpup(p);
422887 return decode_verifier(xdr, &res->verifier.verifier);
888
+}
423889
424
-out_overflow:
425
- print_overflow_msg(__func__, xdr);
426
- return -EIO;
890
+static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
891
+{
892
+ struct nfs42_netaddr *naddr;
893
+ uint32_t dummy;
894
+ char *dummy_str;
895
+ __be32 *p;
896
+ int status;
897
+
898
+ /* nl_type */
899
+ p = xdr_inline_decode(xdr, 4);
900
+ if (unlikely(!p))
901
+ return -EIO;
902
+ ns->nl4_type = be32_to_cpup(p);
903
+ switch (ns->nl4_type) {
904
+ case NL4_NAME:
905
+ case NL4_URL:
906
+ status = decode_opaque_inline(xdr, &dummy, &dummy_str);
907
+ if (unlikely(status))
908
+ return status;
909
+ if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
910
+ return -EIO;
911
+ memcpy(&ns->u.nl4_str, dummy_str, dummy);
912
+ ns->u.nl4_str_sz = dummy;
913
+ break;
914
+ case NL4_NETADDR:
915
+ naddr = &ns->u.nl4_addr;
916
+
917
+ /* netid string */
918
+ status = decode_opaque_inline(xdr, &dummy, &dummy_str);
919
+ if (unlikely(status))
920
+ return status;
921
+ if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
922
+ return -EIO;
923
+ naddr->netid_len = dummy;
924
+ memcpy(naddr->netid, dummy_str, naddr->netid_len);
925
+
926
+ /* uaddr string */
927
+ status = decode_opaque_inline(xdr, &dummy, &dummy_str);
928
+ if (unlikely(status))
929
+ return status;
930
+ if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
931
+ return -EIO;
932
+ naddr->addr_len = dummy;
933
+ memcpy(naddr->addr, dummy_str, naddr->addr_len);
934
+ break;
935
+ default:
936
+ WARN_ON_ONCE(1);
937
+ return -EIO;
938
+ }
939
+ return 0;
427940 }
428941
429942 static int decode_copy_requirements(struct xdr_stream *xdr,
....@@ -432,14 +945,11 @@
432945
433946 p = xdr_inline_decode(xdr, 4 + 4);
434947 if (unlikely(!p))
435
- goto out_overflow;
948
+ return -EIO;
436949
437950 res->consecutive = be32_to_cpup(p++);
438951 res->synchronous = be32_to_cpup(p++);
439952 return 0;
440
-out_overflow:
441
- print_overflow_msg(__func__, xdr);
442
- return -EIO;
443953 }
444954
445955 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
....@@ -468,9 +978,134 @@
468978 return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
469979 }
470980
981
+static int decode_copy_notify(struct xdr_stream *xdr,
982
+ struct nfs42_copy_notify_res *res)
983
+{
984
+ __be32 *p;
985
+ int status, count;
986
+
987
+ status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
988
+ if (status)
989
+ return status;
990
+ /* cnr_lease_time */
991
+ p = xdr_inline_decode(xdr, 12);
992
+ if (unlikely(!p))
993
+ return -EIO;
994
+ p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
995
+ res->cnr_lease_time.nseconds = be32_to_cpup(p);
996
+
997
+ status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
998
+ if (unlikely(status))
999
+ return -EIO;
1000
+
1001
+ /* number of source addresses */
1002
+ p = xdr_inline_decode(xdr, 4);
1003
+ if (unlikely(!p))
1004
+ return -EIO;
1005
+
1006
+ count = be32_to_cpup(p);
1007
+ if (count > 1)
1008
+ pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
1009
+ __func__, count);
1010
+
1011
+ status = decode_nl4_server(xdr, &res->cnr_src);
1012
+ if (unlikely(status))
1013
+ return -EIO;
1014
+ return 0;
1015
+}
1016
+
4711017 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
4721018 {
4731019 return decode_op_hdr(xdr, OP_DEALLOCATE);
1020
+}
1021
+
1022
+static int decode_read_plus_data(struct xdr_stream *xdr,
1023
+ struct nfs_pgio_res *res)
1024
+{
1025
+ uint32_t count, recvd;
1026
+ uint64_t offset;
1027
+ __be32 *p;
1028
+
1029
+ p = xdr_inline_decode(xdr, 8 + 4);
1030
+ if (!p)
1031
+ return 1;
1032
+
1033
+ p = xdr_decode_hyper(p, &offset);
1034
+ count = be32_to_cpup(p);
1035
+ recvd = xdr_align_data(xdr, res->count, count);
1036
+ res->count += recvd;
1037
+
1038
+ if (count > recvd)
1039
+ return 1;
1040
+ return 0;
1041
+}
1042
+
1043
+static int decode_read_plus_hole(struct xdr_stream *xdr, struct nfs_pgio_res *res,
1044
+ uint32_t *eof)
1045
+{
1046
+ uint64_t offset, length, recvd;
1047
+ __be32 *p;
1048
+
1049
+ p = xdr_inline_decode(xdr, 8 + 8);
1050
+ if (!p)
1051
+ return 1;
1052
+
1053
+ p = xdr_decode_hyper(p, &offset);
1054
+ p = xdr_decode_hyper(p, &length);
1055
+ recvd = xdr_expand_hole(xdr, res->count, length);
1056
+ res->count += recvd;
1057
+
1058
+ if (recvd < length)
1059
+ return 1;
1060
+ return 0;
1061
+}
1062
+
1063
+static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
1064
+{
1065
+ uint32_t eof, segments, type;
1066
+ int status, i;
1067
+ __be32 *p;
1068
+
1069
+ status = decode_op_hdr(xdr, OP_READ_PLUS);
1070
+ if (status)
1071
+ return status;
1072
+
1073
+ p = xdr_inline_decode(xdr, 4 + 4);
1074
+ if (unlikely(!p))
1075
+ return -EIO;
1076
+
1077
+ eof = be32_to_cpup(p++);
1078
+ segments = be32_to_cpup(p++);
1079
+ if (segments == 0)
1080
+ goto out;
1081
+
1082
+ for (i = 0; i < segments; i++) {
1083
+ p = xdr_inline_decode(xdr, 4);
1084
+ if (!p)
1085
+ goto early_out;
1086
+
1087
+ type = be32_to_cpup(p++);
1088
+ if (type == NFS4_CONTENT_DATA)
1089
+ status = decode_read_plus_data(xdr, res);
1090
+ else if (type == NFS4_CONTENT_HOLE)
1091
+ status = decode_read_plus_hole(xdr, res, &eof);
1092
+ else
1093
+ return -EINVAL;
1094
+
1095
+ if (status < 0)
1096
+ return status;
1097
+ if (status > 0)
1098
+ goto early_out;
1099
+ }
1100
+
1101
+out:
1102
+ res->eof = eof;
1103
+ return 0;
1104
+early_out:
1105
+ if (unlikely(!i))
1106
+ return -EIO;
1107
+ res->eof = 0;
1108
+ return 0;
4741109 }
4751110
4761111 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
....@@ -484,15 +1119,11 @@
4841119
4851120 p = xdr_inline_decode(xdr, 4 + 8);
4861121 if (unlikely(!p))
487
- goto out_overflow;
1122
+ return -EIO;
4881123
4891124 res->sr_eof = be32_to_cpup(p++);
4901125 p = xdr_decode_hyper(p, &res->sr_offset);
4911126 return 0;
492
-
493
-out_overflow:
494
- print_overflow_msg(__func__, xdr);
495
- return -EIO;
4961127 }
4971128
4981129 static int decode_layoutstats(struct xdr_stream *xdr)
....@@ -503,6 +1134,11 @@
5031134 static int decode_clone(struct xdr_stream *xdr)
5041135 {
5051136 return decode_op_hdr(xdr, OP_CLONE);
1137
+}
1138
+
1139
+static int decode_layouterror(struct xdr_stream *xdr)
1140
+{
1141
+ return decode_op_hdr(xdr, OP_LAYOUTERROR);
5061142 }
5071143
5081144 /*
....@@ -595,6 +1231,32 @@
5951231 }
5961232
5971233 /*
1234
+ * Decode COPY_NOTIFY response
1235
+ */
1236
+static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
1237
+ struct xdr_stream *xdr,
1238
+ void *data)
1239
+{
1240
+ struct nfs42_copy_notify_res *res = data;
1241
+ struct compound_hdr hdr;
1242
+ int status;
1243
+
1244
+ status = decode_compound_hdr(xdr, &hdr);
1245
+ if (status)
1246
+ goto out;
1247
+ status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
1248
+ if (status)
1249
+ goto out;
1250
+ status = decode_putfh(xdr);
1251
+ if (status)
1252
+ goto out;
1253
+ status = decode_copy_notify(xdr, res);
1254
+
1255
+out:
1256
+ return status;
1257
+}
1258
+
1259
+/*
5981260 * Decode DEALLOCATE request
5991261 */
6001262 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
....@@ -618,6 +1280,33 @@
6181280 if (status)
6191281 goto out;
6201282 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1283
+out:
1284
+ return status;
1285
+}
1286
+
1287
+/*
1288
+ * Decode READ_PLUS request
1289
+ */
1290
+static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
1291
+ struct xdr_stream *xdr,
1292
+ void *data)
1293
+{
1294
+ struct nfs_pgio_res *res = data;
1295
+ struct compound_hdr hdr;
1296
+ int status;
1297
+
1298
+ status = decode_compound_hdr(xdr, &hdr);
1299
+ if (status)
1300
+ goto out;
1301
+ status = decode_sequence(xdr, &res->seq_res, rqstp);
1302
+ if (status)
1303
+ goto out;
1304
+ status = decode_putfh(xdr);
1305
+ if (status)
1306
+ goto out;
1307
+ status = decode_read_plus(xdr, res);
1308
+ if (!status)
1309
+ status = res->count;
6211310 out:
6221311 return status;
6231312 }
....@@ -713,4 +1402,191 @@
7131402 return status;
7141403 }
7151404
1405
+/*
1406
+ * Decode LAYOUTERROR request
1407
+ */
1408
+static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
1409
+ struct xdr_stream *xdr,
1410
+ void *data)
1411
+{
1412
+ struct nfs42_layouterror_res *res = data;
1413
+ struct compound_hdr hdr;
1414
+ int status, i;
1415
+
1416
+ status = decode_compound_hdr(xdr, &hdr);
1417
+ if (status)
1418
+ goto out;
1419
+ status = decode_sequence(xdr, &res->seq_res, rqstp);
1420
+ if (status)
1421
+ goto out;
1422
+ status = decode_putfh(xdr);
1423
+
1424
+ for (i = 0; i < res->num_errors && status == 0; i++)
1425
+ status = decode_layouterror(xdr);
1426
+out:
1427
+ res->rpc_status = status;
1428
+ return status;
1429
+}
1430
+
1431
+#ifdef CONFIG_NFS_V4_2
1432
+static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1433
+ const void *data)
1434
+{
1435
+ const struct nfs42_setxattrargs *args = data;
1436
+ struct compound_hdr hdr = {
1437
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1438
+ };
1439
+
1440
+ encode_compound_hdr(xdr, req, &hdr);
1441
+ encode_sequence(xdr, &args->seq_args, &hdr);
1442
+ encode_putfh(xdr, args->fh, &hdr);
1443
+ encode_setxattr(xdr, args, &hdr);
1444
+ encode_nops(&hdr);
1445
+}
1446
+
1447
+static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1448
+ void *data)
1449
+{
1450
+ struct nfs42_setxattrres *res = data;
1451
+ struct compound_hdr hdr;
1452
+ int status;
1453
+
1454
+ status = decode_compound_hdr(xdr, &hdr);
1455
+ if (status)
1456
+ goto out;
1457
+ status = decode_sequence(xdr, &res->seq_res, req);
1458
+ if (status)
1459
+ goto out;
1460
+ status = decode_putfh(xdr);
1461
+ if (status)
1462
+ goto out;
1463
+
1464
+ status = decode_setxattr(xdr, &res->cinfo);
1465
+out:
1466
+ return status;
1467
+}
1468
+
1469
+static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1470
+ const void *data)
1471
+{
1472
+ const struct nfs42_getxattrargs *args = data;
1473
+ struct compound_hdr hdr = {
1474
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1475
+ };
1476
+ size_t plen;
1477
+
1478
+ encode_compound_hdr(xdr, req, &hdr);
1479
+ encode_sequence(xdr, &args->seq_args, &hdr);
1480
+ encode_putfh(xdr, args->fh, &hdr);
1481
+ encode_getxattr(xdr, args->xattr_name, &hdr);
1482
+
1483
+ plen = args->xattr_len ? args->xattr_len : XATTR_SIZE_MAX;
1484
+
1485
+ rpc_prepare_reply_pages(req, args->xattr_pages, 0, plen,
1486
+ hdr.replen);
1487
+ req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
1488
+
1489
+ encode_nops(&hdr);
1490
+}
1491
+
1492
+static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1493
+ struct xdr_stream *xdr, void *data)
1494
+{
1495
+ struct nfs42_getxattrres *res = data;
1496
+ struct compound_hdr hdr;
1497
+ int status;
1498
+
1499
+ status = decode_compound_hdr(xdr, &hdr);
1500
+ if (status)
1501
+ goto out;
1502
+ status = decode_sequence(xdr, &res->seq_res, rqstp);
1503
+ if (status)
1504
+ goto out;
1505
+ status = decode_putfh(xdr);
1506
+ if (status)
1507
+ goto out;
1508
+ status = decode_getxattr(xdr, res, rqstp);
1509
+out:
1510
+ return status;
1511
+}
1512
+
1513
+static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
1514
+ struct xdr_stream *xdr, const void *data)
1515
+{
1516
+ const struct nfs42_listxattrsargs *args = data;
1517
+ struct compound_hdr hdr = {
1518
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1519
+ };
1520
+
1521
+ encode_compound_hdr(xdr, req, &hdr);
1522
+ encode_sequence(xdr, &args->seq_args, &hdr);
1523
+ encode_putfh(xdr, args->fh, &hdr);
1524
+ encode_listxattrs(xdr, args, &hdr);
1525
+
1526
+ rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count,
1527
+ hdr.replen);
1528
+
1529
+ encode_nops(&hdr);
1530
+}
1531
+
1532
+static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1533
+ struct xdr_stream *xdr, void *data)
1534
+{
1535
+ struct nfs42_listxattrsres *res = data;
1536
+ struct compound_hdr hdr;
1537
+ int status;
1538
+
1539
+ xdr_set_scratch_buffer(xdr, page_address(res->scratch), PAGE_SIZE);
1540
+
1541
+ status = decode_compound_hdr(xdr, &hdr);
1542
+ if (status)
1543
+ goto out;
1544
+ status = decode_sequence(xdr, &res->seq_res, rqstp);
1545
+ if (status)
1546
+ goto out;
1547
+ status = decode_putfh(xdr);
1548
+ if (status)
1549
+ goto out;
1550
+ status = decode_listxattrs(xdr, res);
1551
+out:
1552
+ return status;
1553
+}
1554
+
1555
+static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
1556
+ struct xdr_stream *xdr, const void *data)
1557
+{
1558
+ const struct nfs42_removexattrargs *args = data;
1559
+ struct compound_hdr hdr = {
1560
+ .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1561
+ };
1562
+
1563
+ encode_compound_hdr(xdr, req, &hdr);
1564
+ encode_sequence(xdr, &args->seq_args, &hdr);
1565
+ encode_putfh(xdr, args->fh, &hdr);
1566
+ encode_removexattr(xdr, args->xattr_name, &hdr);
1567
+ encode_nops(&hdr);
1568
+}
1569
+
1570
+static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1571
+ struct xdr_stream *xdr, void *data)
1572
+{
1573
+ struct nfs42_removexattrres *res = data;
1574
+ struct compound_hdr hdr;
1575
+ int status;
1576
+
1577
+ status = decode_compound_hdr(xdr, &hdr);
1578
+ if (status)
1579
+ goto out;
1580
+ status = decode_sequence(xdr, &res->seq_res, req);
1581
+ if (status)
1582
+ goto out;
1583
+ status = decode_putfh(xdr);
1584
+ if (status)
1585
+ goto out;
1586
+
1587
+ status = decode_removexattr(xdr, &res->cinfo);
1588
+out:
1589
+ return status;
1590
+}
1591
+#endif
7161592 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */