1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com> 4 */ 5#ifndef __LINUX_FS_NFS_NFS4_2XDR_H 6#define __LINUX_FS_NFS_NFS4_2XDR_H 7 8#include "nfs42.h" 9 10#define encode_fallocate_maxsz (encode_stateid_maxsz + \ 11 2 /* offset */ + \ 12 2 /* length */) 13#define NFS42_WRITE_RES_SIZE (1 /* wr_callback_id size */ +\ 14 XDR_QUADLEN(NFS4_STATEID_SIZE) + \ 15 2 /* wr_count */ + \ 16 1 /* wr_committed */ + \ 17 XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 18#define encode_allocate_maxsz (op_encode_hdr_maxsz + \ 19 encode_fallocate_maxsz) 20#define decode_allocate_maxsz (op_decode_hdr_maxsz) 21#define encode_copy_maxsz (op_encode_hdr_maxsz + \ 22 XDR_QUADLEN(NFS4_STATEID_SIZE) + \ 23 XDR_QUADLEN(NFS4_STATEID_SIZE) + \ 24 2 + 2 + 2 + 1 + 1 + 1 +\ 25 1 + /* One cnr_source_server */\ 26 1 + /* nl4_type */ \ 27 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT)) 28#define decode_copy_maxsz (op_decode_hdr_maxsz + \ 29 NFS42_WRITE_RES_SIZE + \ 30 1 /* cr_consecutive */ + \ 31 1 /* cr_synchronous */) 32#define encode_offload_cancel_maxsz (op_encode_hdr_maxsz + \ 33 XDR_QUADLEN(NFS4_STATEID_SIZE)) 34#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)) 45#define encode_deallocate_maxsz (op_encode_hdr_maxsz + \ 46 encode_fallocate_maxsz) 47#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) 57#define encode_seek_maxsz (op_encode_hdr_maxsz + \ 58 encode_stateid_maxsz + \ 59 2 /* offset */ + \ 60 1 /* whence */) 61#define decode_seek_maxsz (op_decode_hdr_maxsz + \ 62 1 /* eof */ + \ 63 1 /* whence */ + \ 64 2 /* offset */ + \ 65 2 /* length */) 66#define encode_io_info_maxsz 4 67#define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \ 68 2 /* offset */ + \ 69 2 /* length */ + \ 70 encode_stateid_maxsz + \ 71 encode_io_info_maxsz + \ 72 encode_io_info_maxsz + \ 73 1 /* opaque devaddr4 length */ + \ 74 XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE)) 75#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) 85#define encode_clone_maxsz (encode_stateid_maxsz + \ 86 encode_stateid_maxsz + \ 87 2 /* src offset */ + \ 88 2 /* dst offset */ + \ 89 2 /* count */) 90#define decode_clone_maxsz (op_decode_hdr_maxsz) 91 92#define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ 93 encode_sequence_maxsz + \ 94 encode_putfh_maxsz + \ 95 encode_allocate_maxsz + \ 96 encode_getattr_maxsz) 97#define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ 98 decode_sequence_maxsz + \ 99 decode_putfh_maxsz + \ 100 decode_allocate_maxsz + \ 101 decode_getattr_maxsz) 102#define NFS4_enc_copy_sz (compound_encode_hdr_maxsz + \ 103 encode_sequence_maxsz + \ 104 encode_putfh_maxsz + \ 105 encode_savefh_maxsz + \ 106 encode_putfh_maxsz + \ 107 encode_copy_maxsz + \ 108 encode_commit_maxsz) 109#define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \ 110 decode_sequence_maxsz + \ 111 decode_putfh_maxsz + \ 112 decode_savefh_maxsz + \ 113 decode_putfh_maxsz + \ 114 decode_copy_maxsz + \ 115 decode_commit_maxsz) 116#define NFS4_enc_offload_cancel_sz (compound_encode_hdr_maxsz + \ 117 encode_sequence_maxsz + \ 118 encode_putfh_maxsz + \ 119 encode_offload_cancel_maxsz) 120#define NFS4_dec_offload_cancel_sz (compound_decode_hdr_maxsz + \ 121 decode_sequence_maxsz + \ 122 decode_putfh_maxsz + \ 123 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) 130#define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ 131 encode_sequence_maxsz + \ 132 encode_putfh_maxsz + \ 133 encode_deallocate_maxsz + \ 134 encode_getattr_maxsz) 135#define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ 136 decode_sequence_maxsz + \ 137 decode_putfh_maxsz + \ 138 decode_deallocate_maxsz + \ 139 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) 148#define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ 149 encode_sequence_maxsz + \ 150 encode_putfh_maxsz + \ 151 encode_seek_maxsz) 152#define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \ 153 decode_sequence_maxsz + \ 154 decode_putfh_maxsz + \ 155 decode_seek_maxsz) 156#define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \ 157 encode_sequence_maxsz + \ 158 encode_putfh_maxsz + \ 159 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz) 160#define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \ 161 decode_sequence_maxsz + \ 162 decode_putfh_maxsz + \ 163 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) 174#define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \ 175 encode_sequence_maxsz + \ 176 encode_putfh_maxsz + \ 177 encode_savefh_maxsz + \ 178 encode_putfh_maxsz + \ 179 encode_clone_maxsz + \ 180 encode_getattr_maxsz) 181#define NFS4_dec_clone_sz (compound_decode_hdr_maxsz + \ 182 decode_sequence_maxsz + \ 183 decode_putfh_maxsz + \ 184 decode_savefh_maxsz + \ 185 decode_putfh_maxsz + \ 186 decode_clone_maxsz + \ 187 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 */ 244const 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 251const 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 256const 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); 260 261static void encode_fallocate(struct xdr_stream *xdr, 262 const struct nfs42_falloc_args *args) 263{ 264 encode_nfs4_stateid(xdr, &args->falloc_stateid); 265 encode_uint64(xdr, args->falloc_offset); 266 encode_uint64(xdr, args->falloc_length); 267} 268 269static void encode_allocate(struct xdr_stream *xdr, 270 const struct nfs42_falloc_args *args, 271 struct compound_hdr *hdr) 272{ 273 encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr); 274 encode_fallocate(xdr, args); 275} 276 277static 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 297static void encode_copy(struct xdr_stream *xdr, 298 const struct nfs42_copy_args *args, 299 struct compound_hdr *hdr) 300{ 301 encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr); 302 encode_nfs4_stateid(xdr, &args->src_stateid); 303 encode_nfs4_stateid(xdr, &args->dst_stateid); 304 305 encode_uint64(xdr, args->src_pos); 306 encode_uint64(xdr, args->dst_pos); 307 encode_uint64(xdr, args->count); 308 309 encode_uint32(xdr, 1); /* consecutive = true */ 310 encode_uint32(xdr, args->sync); 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); 317} 318 319static void encode_offload_cancel(struct xdr_stream *xdr, 320 const struct nfs42_offload_status_args *args, 321 struct compound_hdr *hdr) 322{ 323 encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr); 324 encode_nfs4_stateid(xdr, &args->osa_stateid); 325} 326 327static 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 336static void encode_deallocate(struct xdr_stream *xdr, 337 const struct nfs42_falloc_args *args, 338 struct compound_hdr *hdr) 339{ 340 encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr); 341 encode_fallocate(xdr, args); 342} 343 344static 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); 352} 353 354static void encode_seek(struct xdr_stream *xdr, 355 const struct nfs42_seek_args *args, 356 struct compound_hdr *hdr) 357{ 358 encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr); 359 encode_nfs4_stateid(xdr, &args->sa_stateid); 360 encode_uint64(xdr, args->sa_offset); 361 encode_uint32(xdr, args->sa_what); 362} 363 364static void encode_layoutstats(struct xdr_stream *xdr, 365 const struct nfs42_layoutstat_args *args, 366 struct nfs42_layoutstat_devinfo *devinfo, 367 struct compound_hdr *hdr) 368{ 369 __be32 *p; 370 371 encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr); 372 p = reserve_space(xdr, 8 + 8); 373 p = xdr_encode_hyper(p, devinfo->offset); 374 p = xdr_encode_hyper(p, devinfo->length); 375 encode_nfs4_stateid(xdr, &args->stateid); 376 p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4); 377 p = xdr_encode_hyper(p, devinfo->read_count); 378 p = xdr_encode_hyper(p, devinfo->read_bytes); 379 p = xdr_encode_hyper(p, devinfo->write_count); 380 p = xdr_encode_hyper(p, devinfo->write_bytes); 381 p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data, 382 NFS4_DEVICEID4_SIZE); 383 /* Encode layoutupdate4 */ 384 *p++ = cpu_to_be32(devinfo->layout_type); 385 if (devinfo->ld_private.ops) 386 devinfo->ld_private.ops->encode(xdr, args, 387 &devinfo->ld_private); 388 else 389 encode_uint32(xdr, 0); 390} 391 392static void encode_clone(struct xdr_stream *xdr, 393 const struct nfs42_clone_args *args, 394 struct compound_hdr *hdr) 395{ 396 __be32 *p; 397 398 encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr); 399 encode_nfs4_stateid(xdr, &args->src_stateid); 400 encode_nfs4_stateid(xdr, &args->dst_stateid); 401 p = reserve_space(xdr, 3*8); 402 p = xdr_encode_hyper(p, args->src_offset); 403 p = xdr_encode_hyper(p, args->dst_offset); 404 xdr_encode_hyper(p, args->count); 405} 406 407static 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 419static 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 435static 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 454static 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); 463out: 464 return status; 465} 466 467 468static 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 475static 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 506static 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 514static 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); 524out: 525 return status; 526} 527 528static 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 549static 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 632out: 633 if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX) 634 status = -E2BIG; 635 636 return status; 637} 638 639/* 640 * Encode ALLOCATE request 641 */ 642static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, 643 struct xdr_stream *xdr, 644 const void *data) 645{ 646 const struct nfs42_falloc_args *args = data; 647 struct compound_hdr hdr = { 648 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 649 }; 650 651 encode_compound_hdr(xdr, req, &hdr); 652 encode_sequence(xdr, &args->seq_args, &hdr); 653 encode_putfh(xdr, args->falloc_fh, &hdr); 654 encode_allocate(xdr, args, &hdr); 655 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 656 encode_nops(&hdr); 657} 658 659static void encode_copy_commit(struct xdr_stream *xdr, 660 const struct nfs42_copy_args *args, 661 struct compound_hdr *hdr) 662{ 663 __be32 *p; 664 665 encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); 666 p = reserve_space(xdr, 12); 667 p = xdr_encode_hyper(p, args->dst_pos); 668 *p = cpu_to_be32(args->count); 669} 670 671/* 672 * Encode COPY request 673 */ 674static void nfs4_xdr_enc_copy(struct rpc_rqst *req, 675 struct xdr_stream *xdr, 676 const void *data) 677{ 678 const struct nfs42_copy_args *args = data; 679 struct compound_hdr hdr = { 680 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 681 }; 682 683 encode_compound_hdr(xdr, req, &hdr); 684 encode_sequence(xdr, &args->seq_args, &hdr); 685 encode_putfh(xdr, args->src_fh, &hdr); 686 encode_savefh(xdr, &hdr); 687 encode_putfh(xdr, args->dst_fh, &hdr); 688 encode_copy(xdr, args, &hdr); 689 if (args->sync) 690 encode_copy_commit(xdr, args, &hdr); 691 encode_nops(&hdr); 692} 693 694/* 695 * Encode OFFLOAD_CANEL request 696 */ 697static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req, 698 struct xdr_stream *xdr, 699 const void *data) 700{ 701 const struct nfs42_offload_status_args *args = data; 702 struct compound_hdr hdr = { 703 .minorversion = nfs4_xdr_minorversion(&args->osa_seq_args), 704 }; 705 706 encode_compound_hdr(xdr, req, &hdr); 707 encode_sequence(xdr, &args->osa_seq_args, &hdr); 708 encode_putfh(xdr, args->osa_src_fh, &hdr); 709 encode_offload_cancel(xdr, args, &hdr); 710 encode_nops(&hdr); 711} 712 713/* 714 * Encode COPY_NOTIFY request 715 */ 716static 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/* 733 * Encode DEALLOCATE request 734 */ 735static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, 736 struct xdr_stream *xdr, 737 const void *data) 738{ 739 const struct nfs42_falloc_args *args = data; 740 struct compound_hdr hdr = { 741 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 742 }; 743 744 encode_compound_hdr(xdr, req, &hdr); 745 encode_sequence(xdr, &args->seq_args, &hdr); 746 encode_putfh(xdr, args->falloc_fh, &hdr); 747 encode_deallocate(xdr, args, &hdr); 748 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 749 encode_nops(&hdr); 750} 751 752/* 753 * Encode READ_PLUS request 754 */ 755static 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); 771 encode_nops(&hdr); 772} 773 774/* 775 * Encode SEEK request 776 */ 777static void nfs4_xdr_enc_seek(struct rpc_rqst *req, 778 struct xdr_stream *xdr, 779 const void *data) 780{ 781 const struct nfs42_seek_args *args = data; 782 struct compound_hdr hdr = { 783 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 784 }; 785 786 encode_compound_hdr(xdr, req, &hdr); 787 encode_sequence(xdr, &args->seq_args, &hdr); 788 encode_putfh(xdr, args->sa_fh, &hdr); 789 encode_seek(xdr, args, &hdr); 790 encode_nops(&hdr); 791} 792 793/* 794 * Encode LAYOUTSTATS request 795 */ 796static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, 797 struct xdr_stream *xdr, 798 const void *data) 799{ 800 const struct nfs42_layoutstat_args *args = data; 801 int i; 802 803 struct compound_hdr hdr = { 804 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 805 }; 806 807 encode_compound_hdr(xdr, req, &hdr); 808 encode_sequence(xdr, &args->seq_args, &hdr); 809 encode_putfh(xdr, args->fh, &hdr); 810 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 811 for (i = 0; i < args->num_dev; i++) 812 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr); 813 encode_nops(&hdr); 814} 815 816/* 817 * Encode CLONE request 818 */ 819static void nfs4_xdr_enc_clone(struct rpc_rqst *req, 820 struct xdr_stream *xdr, 821 const void *data) 822{ 823 const struct nfs42_clone_args *args = data; 824 struct compound_hdr hdr = { 825 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 826 }; 827 828 encode_compound_hdr(xdr, req, &hdr); 829 encode_sequence(xdr, &args->seq_args, &hdr); 830 encode_putfh(xdr, args->src_fh, &hdr); 831 encode_savefh(xdr, &hdr); 832 encode_putfh(xdr, args->dst_fh, &hdr); 833 encode_clone(xdr, args, &hdr); 834 encode_getfattr(xdr, args->dst_bitmask, &hdr); 835 encode_nops(&hdr); 836} 837 838/* 839 * Encode LAYOUTERROR request 840 */ 841static 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 859static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 860{ 861 return decode_op_hdr(xdr, OP_ALLOCATE); 862} 863 864static int decode_write_response(struct xdr_stream *xdr, 865 struct nfs42_write_res *res) 866{ 867 __be32 *p; 868 int status, count; 869 870 p = xdr_inline_decode(xdr, 4); 871 if (unlikely(!p)) 872 return -EIO; 873 count = be32_to_cpup(p); 874 if (count > 1) 875 return -EREMOTEIO; 876 else if (count == 1) { 877 status = decode_opaque_fixed(xdr, &res->stateid, 878 NFS4_STATEID_SIZE); 879 if (unlikely(status)) 880 return -EIO; 881 } 882 p = xdr_inline_decode(xdr, 8 + 4); 883 if (unlikely(!p)) 884 return -EIO; 885 p = xdr_decode_hyper(p, &res->count); 886 res->verifier.committed = be32_to_cpup(p); 887 return decode_verifier(xdr, &res->verifier.verifier); 888} 889 890static 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; 940} 941 942static int decode_copy_requirements(struct xdr_stream *xdr, 943 struct nfs42_copy_res *res) { 944 __be32 *p; 945 946 p = xdr_inline_decode(xdr, 4 + 4); 947 if (unlikely(!p)) 948 return -EIO; 949 950 res->consecutive = be32_to_cpup(p++); 951 res->synchronous = be32_to_cpup(p++); 952 return 0; 953} 954 955static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res) 956{ 957 int status; 958 959 status = decode_op_hdr(xdr, OP_COPY); 960 if (status == NFS4ERR_OFFLOAD_NO_REQS) { 961 status = decode_copy_requirements(xdr, res); 962 if (status) 963 return status; 964 return NFS4ERR_OFFLOAD_NO_REQS; 965 } else if (status) 966 return status; 967 968 status = decode_write_response(xdr, &res->write_res); 969 if (status) 970 return status; 971 972 return decode_copy_requirements(xdr, res); 973} 974 975static int decode_offload_cancel(struct xdr_stream *xdr, 976 struct nfs42_offload_status_res *res) 977{ 978 return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL); 979} 980 981static 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 1017static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 1018{ 1019 return decode_op_hdr(xdr, OP_DEALLOCATE); 1020} 1021 1022static 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 1043static 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 1063static 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 1101out: 1102 res->eof = eof; 1103 return 0; 1104early_out: 1105 if (unlikely(!i)) 1106 return -EIO; 1107 res->eof = 0; 1108 return 0; 1109} 1110 1111static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) 1112{ 1113 int status; 1114 __be32 *p; 1115 1116 status = decode_op_hdr(xdr, OP_SEEK); 1117 if (status) 1118 return status; 1119 1120 p = xdr_inline_decode(xdr, 4 + 8); 1121 if (unlikely(!p)) 1122 return -EIO; 1123 1124 res->sr_eof = be32_to_cpup(p++); 1125 p = xdr_decode_hyper(p, &res->sr_offset); 1126 return 0; 1127} 1128 1129static int decode_layoutstats(struct xdr_stream *xdr) 1130{ 1131 return decode_op_hdr(xdr, OP_LAYOUTSTATS); 1132} 1133 1134static int decode_clone(struct xdr_stream *xdr) 1135{ 1136 return decode_op_hdr(xdr, OP_CLONE); 1137} 1138 1139static int decode_layouterror(struct xdr_stream *xdr) 1140{ 1141 return decode_op_hdr(xdr, OP_LAYOUTERROR); 1142} 1143 1144/* 1145 * Decode ALLOCATE request 1146 */ 1147static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, 1148 struct xdr_stream *xdr, 1149 void *data) 1150{ 1151 struct nfs42_falloc_res *res = data; 1152 struct compound_hdr hdr; 1153 int status; 1154 1155 status = decode_compound_hdr(xdr, &hdr); 1156 if (status) 1157 goto out; 1158 status = decode_sequence(xdr, &res->seq_res, rqstp); 1159 if (status) 1160 goto out; 1161 status = decode_putfh(xdr); 1162 if (status) 1163 goto out; 1164 status = decode_allocate(xdr, res); 1165 if (status) 1166 goto out; 1167 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 1168out: 1169 return status; 1170} 1171 1172/* 1173 * Decode COPY response 1174 */ 1175static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp, 1176 struct xdr_stream *xdr, 1177 void *data) 1178{ 1179 struct nfs42_copy_res *res = data; 1180 struct compound_hdr hdr; 1181 int status; 1182 1183 status = decode_compound_hdr(xdr, &hdr); 1184 if (status) 1185 goto out; 1186 status = decode_sequence(xdr, &res->seq_res, rqstp); 1187 if (status) 1188 goto out; 1189 status = decode_putfh(xdr); 1190 if (status) 1191 goto out; 1192 status = decode_savefh(xdr); 1193 if (status) 1194 goto out; 1195 status = decode_putfh(xdr); 1196 if (status) 1197 goto out; 1198 status = decode_copy(xdr, res); 1199 if (status) 1200 goto out; 1201 if (res->commit_res.verf) 1202 status = decode_commit(xdr, &res->commit_res); 1203out: 1204 return status; 1205} 1206 1207/* 1208 * Decode OFFLOAD_CANCEL response 1209 */ 1210static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp, 1211 struct xdr_stream *xdr, 1212 void *data) 1213{ 1214 struct nfs42_offload_status_res *res = data; 1215 struct compound_hdr hdr; 1216 int status; 1217 1218 status = decode_compound_hdr(xdr, &hdr); 1219 if (status) 1220 goto out; 1221 status = decode_sequence(xdr, &res->osr_seq_res, rqstp); 1222 if (status) 1223 goto out; 1224 status = decode_putfh(xdr); 1225 if (status) 1226 goto out; 1227 status = decode_offload_cancel(xdr, res); 1228 1229out: 1230 return status; 1231} 1232 1233/* 1234 * Decode COPY_NOTIFY response 1235 */ 1236static 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 1255out: 1256 return status; 1257} 1258 1259/* 1260 * Decode DEALLOCATE request 1261 */ 1262static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, 1263 struct xdr_stream *xdr, 1264 void *data) 1265{ 1266 struct nfs42_falloc_res *res = data; 1267 struct compound_hdr hdr; 1268 int status; 1269 1270 status = decode_compound_hdr(xdr, &hdr); 1271 if (status) 1272 goto out; 1273 status = decode_sequence(xdr, &res->seq_res, rqstp); 1274 if (status) 1275 goto out; 1276 status = decode_putfh(xdr); 1277 if (status) 1278 goto out; 1279 status = decode_deallocate(xdr, res); 1280 if (status) 1281 goto out; 1282 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 1283out: 1284 return status; 1285} 1286 1287/* 1288 * Decode READ_PLUS request 1289 */ 1290static 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; 1310out: 1311 return status; 1312} 1313 1314/* 1315 * Decode SEEK request 1316 */ 1317static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, 1318 struct xdr_stream *xdr, 1319 void *data) 1320{ 1321 struct nfs42_seek_res *res = data; 1322 struct compound_hdr hdr; 1323 int status; 1324 1325 status = decode_compound_hdr(xdr, &hdr); 1326 if (status) 1327 goto out; 1328 status = decode_sequence(xdr, &res->seq_res, rqstp); 1329 if (status) 1330 goto out; 1331 status = decode_putfh(xdr); 1332 if (status) 1333 goto out; 1334 status = decode_seek(xdr, res); 1335out: 1336 return status; 1337} 1338 1339/* 1340 * Decode LAYOUTSTATS request 1341 */ 1342static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, 1343 struct xdr_stream *xdr, 1344 void *data) 1345{ 1346 struct nfs42_layoutstat_res *res = data; 1347 struct compound_hdr hdr; 1348 int status, i; 1349 1350 status = decode_compound_hdr(xdr, &hdr); 1351 if (status) 1352 goto out; 1353 status = decode_sequence(xdr, &res->seq_res, rqstp); 1354 if (status) 1355 goto out; 1356 status = decode_putfh(xdr); 1357 if (status) 1358 goto out; 1359 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 1360 for (i = 0; i < res->num_dev; i++) { 1361 status = decode_layoutstats(xdr); 1362 if (status) 1363 goto out; 1364 } 1365out: 1366 res->rpc_status = status; 1367 return status; 1368} 1369 1370/* 1371 * Decode CLONE request 1372 */ 1373static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, 1374 struct xdr_stream *xdr, 1375 void *data) 1376{ 1377 struct nfs42_clone_res *res = data; 1378 struct compound_hdr hdr; 1379 int status; 1380 1381 status = decode_compound_hdr(xdr, &hdr); 1382 if (status) 1383 goto out; 1384 status = decode_sequence(xdr, &res->seq_res, rqstp); 1385 if (status) 1386 goto out; 1387 status = decode_putfh(xdr); 1388 if (status) 1389 goto out; 1390 status = decode_savefh(xdr); 1391 if (status) 1392 goto out; 1393 status = decode_putfh(xdr); 1394 if (status) 1395 goto out; 1396 status = decode_clone(xdr); 1397 if (status) 1398 goto out; 1399 decode_getfattr(xdr, res->dst_fattr, res->server); 1400out: 1401 res->rpc_status = status; 1402 return status; 1403} 1404 1405/* 1406 * Decode LAYOUTERROR request 1407 */ 1408static 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); 1426out: 1427 res->rpc_status = status; 1428 return status; 1429} 1430 1431#ifdef CONFIG_NFS_V4_2 1432static 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 1447static 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); 1465out: 1466 return status; 1467} 1468 1469static 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 1492static 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); 1509out: 1510 return status; 1511} 1512 1513static 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 1532static 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); 1551out: 1552 return status; 1553} 1554 1555static 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 1570static 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); 1588out: 1589 return status; 1590} 1591#endif 1592#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ 1593