nfs42xdr.c (41883B)
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 + pagepad_maxsz) 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 493 /* 494 * Only check against the page length here. The actual 495 * requested length may be smaller, but that is only 496 * checked against after possibly caching a valid reply. 497 */ 498 if (len > req->rq_rcv_buf.page_len) 499 return -ERANGE; 500 501 res->xattr_len = len; 502 503 if (len > 0) { 504 rdlen = xdr_read_pages(xdr, len); 505 if (rdlen < len) 506 return -EIO; 507 } 508 509 return 0; 510} 511 512static void encode_removexattr(struct xdr_stream *xdr, const char *name, 513 struct compound_hdr *hdr) 514{ 515 encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr); 516 encode_string(xdr, strlen(name), name); 517} 518 519 520static int decode_removexattr(struct xdr_stream *xdr, 521 struct nfs4_change_info *cinfo) 522{ 523 int status; 524 525 status = decode_op_hdr(xdr, OP_REMOVEXATTR); 526 if (status) 527 goto out; 528 529 status = decode_change_info(xdr, cinfo); 530out: 531 return status; 532} 533 534static void encode_listxattrs(struct xdr_stream *xdr, 535 const struct nfs42_listxattrsargs *arg, 536 struct compound_hdr *hdr) 537{ 538 __be32 *p; 539 540 encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr); 541 542 p = reserve_space(xdr, 12); 543 if (unlikely(!p)) 544 return; 545 546 p = xdr_encode_hyper(p, arg->cookie); 547 /* 548 * RFC 8276 says to specify the full max length of the LISTXATTRS 549 * XDR reply. Count is set to the XDR length of the names array 550 * plus the EOF marker. So, add the cookie and the names count. 551 */ 552 *p = cpu_to_be32(arg->count + 8 + 4); 553} 554 555static int decode_listxattrs(struct xdr_stream *xdr, 556 struct nfs42_listxattrsres *res) 557{ 558 int status; 559 __be32 *p; 560 u32 count, len, ulen; 561 size_t left, copied; 562 char *buf; 563 564 status = decode_op_hdr(xdr, OP_LISTXATTRS); 565 if (status) { 566 /* 567 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL 568 * should be translated to ERANGE. 569 */ 570 if (status == -ETOOSMALL) 571 status = -ERANGE; 572 goto out; 573 } 574 575 p = xdr_inline_decode(xdr, 8); 576 if (unlikely(!p)) 577 return -EIO; 578 579 xdr_decode_hyper(p, &res->cookie); 580 581 p = xdr_inline_decode(xdr, 4); 582 if (unlikely(!p)) 583 return -EIO; 584 585 left = res->xattr_len; 586 buf = res->xattr_buf; 587 588 count = be32_to_cpup(p); 589 copied = 0; 590 591 /* 592 * We have asked for enough room to encode the maximum number 593 * of possible attribute names, so everything should fit. 594 * 595 * But, don't rely on that assumption. Just decode entries 596 * until they don't fit anymore, just in case the server did 597 * something odd. 598 */ 599 while (count--) { 600 p = xdr_inline_decode(xdr, 4); 601 if (unlikely(!p)) 602 return -EIO; 603 604 len = be32_to_cpup(p); 605 if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) { 606 status = -ERANGE; 607 goto out; 608 } 609 610 p = xdr_inline_decode(xdr, len); 611 if (unlikely(!p)) 612 return -EIO; 613 614 ulen = len + XATTR_USER_PREFIX_LEN + 1; 615 if (buf) { 616 if (ulen > left) { 617 status = -ERANGE; 618 goto out; 619 } 620 621 memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN); 622 memcpy(buf + XATTR_USER_PREFIX_LEN, p, len); 623 624 buf[ulen - 1] = 0; 625 buf += ulen; 626 left -= ulen; 627 } 628 copied += ulen; 629 } 630 631 p = xdr_inline_decode(xdr, 4); 632 if (unlikely(!p)) 633 return -EIO; 634 635 res->eof = be32_to_cpup(p); 636 res->copied = copied; 637 638out: 639 if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX) 640 status = -E2BIG; 641 642 return status; 643} 644 645/* 646 * Encode ALLOCATE request 647 */ 648static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, 649 struct xdr_stream *xdr, 650 const void *data) 651{ 652 const struct nfs42_falloc_args *args = data; 653 struct compound_hdr hdr = { 654 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 655 }; 656 657 encode_compound_hdr(xdr, req, &hdr); 658 encode_sequence(xdr, &args->seq_args, &hdr); 659 encode_putfh(xdr, args->falloc_fh, &hdr); 660 encode_allocate(xdr, args, &hdr); 661 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 662 encode_nops(&hdr); 663} 664 665static void encode_copy_commit(struct xdr_stream *xdr, 666 const struct nfs42_copy_args *args, 667 struct compound_hdr *hdr) 668{ 669 __be32 *p; 670 671 encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); 672 p = reserve_space(xdr, 12); 673 p = xdr_encode_hyper(p, args->dst_pos); 674 *p = cpu_to_be32(args->count); 675} 676 677/* 678 * Encode COPY request 679 */ 680static void nfs4_xdr_enc_copy(struct rpc_rqst *req, 681 struct xdr_stream *xdr, 682 const void *data) 683{ 684 const struct nfs42_copy_args *args = data; 685 struct compound_hdr hdr = { 686 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 687 }; 688 689 encode_compound_hdr(xdr, req, &hdr); 690 encode_sequence(xdr, &args->seq_args, &hdr); 691 encode_putfh(xdr, args->src_fh, &hdr); 692 encode_savefh(xdr, &hdr); 693 encode_putfh(xdr, args->dst_fh, &hdr); 694 encode_copy(xdr, args, &hdr); 695 if (args->sync) 696 encode_copy_commit(xdr, args, &hdr); 697 encode_nops(&hdr); 698} 699 700/* 701 * Encode OFFLOAD_CANEL request 702 */ 703static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req, 704 struct xdr_stream *xdr, 705 const void *data) 706{ 707 const struct nfs42_offload_status_args *args = data; 708 struct compound_hdr hdr = { 709 .minorversion = nfs4_xdr_minorversion(&args->osa_seq_args), 710 }; 711 712 encode_compound_hdr(xdr, req, &hdr); 713 encode_sequence(xdr, &args->osa_seq_args, &hdr); 714 encode_putfh(xdr, args->osa_src_fh, &hdr); 715 encode_offload_cancel(xdr, args, &hdr); 716 encode_nops(&hdr); 717} 718 719/* 720 * Encode COPY_NOTIFY request 721 */ 722static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req, 723 struct xdr_stream *xdr, 724 const void *data) 725{ 726 const struct nfs42_copy_notify_args *args = data; 727 struct compound_hdr hdr = { 728 .minorversion = nfs4_xdr_minorversion(&args->cna_seq_args), 729 }; 730 731 encode_compound_hdr(xdr, req, &hdr); 732 encode_sequence(xdr, &args->cna_seq_args, &hdr); 733 encode_putfh(xdr, args->cna_src_fh, &hdr); 734 encode_copy_notify(xdr, args, &hdr); 735 encode_nops(&hdr); 736} 737 738/* 739 * Encode DEALLOCATE request 740 */ 741static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, 742 struct xdr_stream *xdr, 743 const void *data) 744{ 745 const struct nfs42_falloc_args *args = data; 746 struct compound_hdr hdr = { 747 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 748 }; 749 750 encode_compound_hdr(xdr, req, &hdr); 751 encode_sequence(xdr, &args->seq_args, &hdr); 752 encode_putfh(xdr, args->falloc_fh, &hdr); 753 encode_deallocate(xdr, args, &hdr); 754 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 755 encode_nops(&hdr); 756} 757 758/* 759 * Encode READ_PLUS request 760 */ 761static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req, 762 struct xdr_stream *xdr, 763 const void *data) 764{ 765 const struct nfs_pgio_args *args = data; 766 struct compound_hdr hdr = { 767 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 768 }; 769 770 encode_compound_hdr(xdr, req, &hdr); 771 encode_sequence(xdr, &args->seq_args, &hdr); 772 encode_putfh(xdr, args->fh, &hdr); 773 encode_read_plus(xdr, args, &hdr); 774 775 rpc_prepare_reply_pages(req, args->pages, args->pgbase, 776 args->count, hdr.replen); 777 encode_nops(&hdr); 778} 779 780/* 781 * Encode SEEK request 782 */ 783static void nfs4_xdr_enc_seek(struct rpc_rqst *req, 784 struct xdr_stream *xdr, 785 const void *data) 786{ 787 const struct nfs42_seek_args *args = data; 788 struct compound_hdr hdr = { 789 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 790 }; 791 792 encode_compound_hdr(xdr, req, &hdr); 793 encode_sequence(xdr, &args->seq_args, &hdr); 794 encode_putfh(xdr, args->sa_fh, &hdr); 795 encode_seek(xdr, args, &hdr); 796 encode_nops(&hdr); 797} 798 799/* 800 * Encode LAYOUTSTATS request 801 */ 802static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, 803 struct xdr_stream *xdr, 804 const void *data) 805{ 806 const struct nfs42_layoutstat_args *args = data; 807 int i; 808 809 struct compound_hdr hdr = { 810 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 811 }; 812 813 encode_compound_hdr(xdr, req, &hdr); 814 encode_sequence(xdr, &args->seq_args, &hdr); 815 encode_putfh(xdr, args->fh, &hdr); 816 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 817 for (i = 0; i < args->num_dev; i++) 818 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr); 819 encode_nops(&hdr); 820} 821 822/* 823 * Encode CLONE request 824 */ 825static void nfs4_xdr_enc_clone(struct rpc_rqst *req, 826 struct xdr_stream *xdr, 827 const void *data) 828{ 829 const struct nfs42_clone_args *args = data; 830 struct compound_hdr hdr = { 831 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 832 }; 833 834 encode_compound_hdr(xdr, req, &hdr); 835 encode_sequence(xdr, &args->seq_args, &hdr); 836 encode_putfh(xdr, args->src_fh, &hdr); 837 encode_savefh(xdr, &hdr); 838 encode_putfh(xdr, args->dst_fh, &hdr); 839 encode_clone(xdr, args, &hdr); 840 encode_getfattr(xdr, args->dst_bitmask, &hdr); 841 encode_nops(&hdr); 842} 843 844/* 845 * Encode LAYOUTERROR request 846 */ 847static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req, 848 struct xdr_stream *xdr, 849 const void *data) 850{ 851 const struct nfs42_layouterror_args *args = data; 852 struct compound_hdr hdr = { 853 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 854 }; 855 int i; 856 857 encode_compound_hdr(xdr, req, &hdr); 858 encode_sequence(xdr, &args->seq_args, &hdr); 859 encode_putfh(xdr, NFS_FH(args->inode), &hdr); 860 for (i = 0; i < args->num_errors; i++) 861 encode_layouterror(xdr, &args->errors[i], &hdr); 862 encode_nops(&hdr); 863} 864 865static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 866{ 867 return decode_op_hdr(xdr, OP_ALLOCATE); 868} 869 870static int decode_write_response(struct xdr_stream *xdr, 871 struct nfs42_write_res *res) 872{ 873 __be32 *p; 874 int status, count; 875 876 p = xdr_inline_decode(xdr, 4); 877 if (unlikely(!p)) 878 return -EIO; 879 count = be32_to_cpup(p); 880 if (count > 1) 881 return -EREMOTEIO; 882 else if (count == 1) { 883 status = decode_opaque_fixed(xdr, &res->stateid, 884 NFS4_STATEID_SIZE); 885 if (unlikely(status)) 886 return -EIO; 887 } 888 p = xdr_inline_decode(xdr, 8 + 4); 889 if (unlikely(!p)) 890 return -EIO; 891 p = xdr_decode_hyper(p, &res->count); 892 res->verifier.committed = be32_to_cpup(p); 893 return decode_verifier(xdr, &res->verifier.verifier); 894} 895 896static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns) 897{ 898 struct nfs42_netaddr *naddr; 899 uint32_t dummy; 900 char *dummy_str; 901 __be32 *p; 902 int status; 903 904 /* nl_type */ 905 p = xdr_inline_decode(xdr, 4); 906 if (unlikely(!p)) 907 return -EIO; 908 ns->nl4_type = be32_to_cpup(p); 909 switch (ns->nl4_type) { 910 case NL4_NAME: 911 case NL4_URL: 912 status = decode_opaque_inline(xdr, &dummy, &dummy_str); 913 if (unlikely(status)) 914 return status; 915 if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) 916 return -EIO; 917 memcpy(&ns->u.nl4_str, dummy_str, dummy); 918 ns->u.nl4_str_sz = dummy; 919 break; 920 case NL4_NETADDR: 921 naddr = &ns->u.nl4_addr; 922 923 /* netid string */ 924 status = decode_opaque_inline(xdr, &dummy, &dummy_str); 925 if (unlikely(status)) 926 return status; 927 if (unlikely(dummy > RPCBIND_MAXNETIDLEN)) 928 return -EIO; 929 naddr->netid_len = dummy; 930 memcpy(naddr->netid, dummy_str, naddr->netid_len); 931 932 /* uaddr string */ 933 status = decode_opaque_inline(xdr, &dummy, &dummy_str); 934 if (unlikely(status)) 935 return status; 936 if (unlikely(dummy > RPCBIND_MAXUADDRLEN)) 937 return -EIO; 938 naddr->addr_len = dummy; 939 memcpy(naddr->addr, dummy_str, naddr->addr_len); 940 break; 941 default: 942 WARN_ON_ONCE(1); 943 return -EIO; 944 } 945 return 0; 946} 947 948static int decode_copy_requirements(struct xdr_stream *xdr, 949 struct nfs42_copy_res *res) { 950 __be32 *p; 951 952 p = xdr_inline_decode(xdr, 4 + 4); 953 if (unlikely(!p)) 954 return -EIO; 955 956 res->consecutive = be32_to_cpup(p++); 957 res->synchronous = be32_to_cpup(p++); 958 return 0; 959} 960 961static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res) 962{ 963 int status; 964 965 status = decode_op_hdr(xdr, OP_COPY); 966 if (status == NFS4ERR_OFFLOAD_NO_REQS) { 967 status = decode_copy_requirements(xdr, res); 968 if (status) 969 return status; 970 return NFS4ERR_OFFLOAD_NO_REQS; 971 } else if (status) 972 return status; 973 974 status = decode_write_response(xdr, &res->write_res); 975 if (status) 976 return status; 977 978 return decode_copy_requirements(xdr, res); 979} 980 981static int decode_offload_cancel(struct xdr_stream *xdr, 982 struct nfs42_offload_status_res *res) 983{ 984 return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL); 985} 986 987static int decode_copy_notify(struct xdr_stream *xdr, 988 struct nfs42_copy_notify_res *res) 989{ 990 __be32 *p; 991 int status, count; 992 993 status = decode_op_hdr(xdr, OP_COPY_NOTIFY); 994 if (status) 995 return status; 996 /* cnr_lease_time */ 997 p = xdr_inline_decode(xdr, 12); 998 if (unlikely(!p)) 999 return -EIO; 1000 p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds); 1001 res->cnr_lease_time.nseconds = be32_to_cpup(p); 1002 1003 status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE); 1004 if (unlikely(status)) 1005 return -EIO; 1006 1007 /* number of source addresses */ 1008 p = xdr_inline_decode(xdr, 4); 1009 if (unlikely(!p)) 1010 return -EIO; 1011 1012 count = be32_to_cpup(p); 1013 if (count > 1) 1014 pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n", 1015 __func__, count); 1016 1017 status = decode_nl4_server(xdr, &res->cnr_src); 1018 if (unlikely(status)) 1019 return -EIO; 1020 return 0; 1021} 1022 1023static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 1024{ 1025 return decode_op_hdr(xdr, OP_DEALLOCATE); 1026} 1027 1028static int decode_read_plus_data(struct xdr_stream *xdr, 1029 struct nfs_pgio_args *args, 1030 struct nfs_pgio_res *res) 1031{ 1032 uint32_t count, recvd; 1033 uint64_t offset; 1034 __be32 *p; 1035 1036 p = xdr_inline_decode(xdr, 8 + 4); 1037 if (!p) 1038 return 1; 1039 1040 p = xdr_decode_hyper(p, &offset); 1041 count = be32_to_cpup(p); 1042 recvd = xdr_align_data(xdr, res->count, xdr_align_size(count)); 1043 if (recvd > count) 1044 recvd = count; 1045 if (res->count + recvd > args->count) { 1046 if (args->count > res->count) 1047 res->count += args->count - res->count; 1048 return 1; 1049 } 1050 res->count += recvd; 1051 if (count > recvd) 1052 return 1; 1053 return 0; 1054} 1055 1056static int decode_read_plus_hole(struct xdr_stream *xdr, 1057 struct nfs_pgio_args *args, 1058 struct nfs_pgio_res *res, uint32_t *eof) 1059{ 1060 uint64_t offset, length, recvd; 1061 __be32 *p; 1062 1063 p = xdr_inline_decode(xdr, 8 + 8); 1064 if (!p) 1065 return 1; 1066 1067 p = xdr_decode_hyper(p, &offset); 1068 p = xdr_decode_hyper(p, &length); 1069 if (offset != args->offset + res->count) { 1070 /* Server returned an out-of-sequence extent */ 1071 if (offset > args->offset + res->count || 1072 offset + length < args->offset + res->count) { 1073 dprintk("NFS: server returned out of sequence extent: " 1074 "offset/size = %llu/%llu != expected %llu\n", 1075 (unsigned long long)offset, 1076 (unsigned long long)length, 1077 (unsigned long long)(args->offset + 1078 res->count)); 1079 return 1; 1080 } 1081 length -= args->offset + res->count - offset; 1082 } 1083 if (length + res->count > args->count) { 1084 *eof = 0; 1085 if (unlikely(res->count >= args->count)) 1086 return 1; 1087 length = args->count - res->count; 1088 } 1089 recvd = xdr_expand_hole(xdr, res->count, length); 1090 res->count += recvd; 1091 1092 if (recvd < length) 1093 return 1; 1094 return 0; 1095} 1096 1097static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res) 1098{ 1099 struct nfs_pgio_header *hdr = 1100 container_of(res, struct nfs_pgio_header, res); 1101 struct nfs_pgio_args *args = &hdr->args; 1102 uint32_t eof, segments, type; 1103 int status, i; 1104 __be32 *p; 1105 1106 status = decode_op_hdr(xdr, OP_READ_PLUS); 1107 if (status) 1108 return status; 1109 1110 p = xdr_inline_decode(xdr, 4 + 4); 1111 if (unlikely(!p)) 1112 return -EIO; 1113 1114 res->count = 0; 1115 eof = be32_to_cpup(p++); 1116 segments = be32_to_cpup(p++); 1117 if (segments == 0) 1118 goto out; 1119 1120 for (i = 0; i < segments; i++) { 1121 p = xdr_inline_decode(xdr, 4); 1122 if (!p) 1123 goto early_out; 1124 1125 type = be32_to_cpup(p++); 1126 if (type == NFS4_CONTENT_DATA) 1127 status = decode_read_plus_data(xdr, args, res); 1128 else if (type == NFS4_CONTENT_HOLE) 1129 status = decode_read_plus_hole(xdr, args, res, &eof); 1130 else 1131 return -EINVAL; 1132 1133 if (status < 0) 1134 return status; 1135 if (status > 0) 1136 goto early_out; 1137 } 1138 1139out: 1140 res->eof = eof; 1141 return 0; 1142early_out: 1143 if (unlikely(!i)) 1144 return -EIO; 1145 res->eof = 0; 1146 return 0; 1147} 1148 1149static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) 1150{ 1151 int status; 1152 __be32 *p; 1153 1154 status = decode_op_hdr(xdr, OP_SEEK); 1155 if (status) 1156 return status; 1157 1158 p = xdr_inline_decode(xdr, 4 + 8); 1159 if (unlikely(!p)) 1160 return -EIO; 1161 1162 res->sr_eof = be32_to_cpup(p++); 1163 p = xdr_decode_hyper(p, &res->sr_offset); 1164 return 0; 1165} 1166 1167static int decode_layoutstats(struct xdr_stream *xdr) 1168{ 1169 return decode_op_hdr(xdr, OP_LAYOUTSTATS); 1170} 1171 1172static int decode_clone(struct xdr_stream *xdr) 1173{ 1174 return decode_op_hdr(xdr, OP_CLONE); 1175} 1176 1177static int decode_layouterror(struct xdr_stream *xdr) 1178{ 1179 return decode_op_hdr(xdr, OP_LAYOUTERROR); 1180} 1181 1182/* 1183 * Decode ALLOCATE request 1184 */ 1185static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, 1186 struct xdr_stream *xdr, 1187 void *data) 1188{ 1189 struct nfs42_falloc_res *res = data; 1190 struct compound_hdr hdr; 1191 int status; 1192 1193 status = decode_compound_hdr(xdr, &hdr); 1194 if (status) 1195 goto out; 1196 status = decode_sequence(xdr, &res->seq_res, rqstp); 1197 if (status) 1198 goto out; 1199 status = decode_putfh(xdr); 1200 if (status) 1201 goto out; 1202 status = decode_allocate(xdr, res); 1203 if (status) 1204 goto out; 1205 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 1206out: 1207 return status; 1208} 1209 1210/* 1211 * Decode COPY response 1212 */ 1213static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp, 1214 struct xdr_stream *xdr, 1215 void *data) 1216{ 1217 struct nfs42_copy_res *res = data; 1218 struct compound_hdr hdr; 1219 int status; 1220 1221 status = decode_compound_hdr(xdr, &hdr); 1222 if (status) 1223 goto out; 1224 status = decode_sequence(xdr, &res->seq_res, rqstp); 1225 if (status) 1226 goto out; 1227 status = decode_putfh(xdr); 1228 if (status) 1229 goto out; 1230 status = decode_savefh(xdr); 1231 if (status) 1232 goto out; 1233 status = decode_putfh(xdr); 1234 if (status) 1235 goto out; 1236 status = decode_copy(xdr, res); 1237 if (status) 1238 goto out; 1239 if (res->commit_res.verf) 1240 status = decode_commit(xdr, &res->commit_res); 1241out: 1242 return status; 1243} 1244 1245/* 1246 * Decode OFFLOAD_CANCEL response 1247 */ 1248static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp, 1249 struct xdr_stream *xdr, 1250 void *data) 1251{ 1252 struct nfs42_offload_status_res *res = data; 1253 struct compound_hdr hdr; 1254 int status; 1255 1256 status = decode_compound_hdr(xdr, &hdr); 1257 if (status) 1258 goto out; 1259 status = decode_sequence(xdr, &res->osr_seq_res, rqstp); 1260 if (status) 1261 goto out; 1262 status = decode_putfh(xdr); 1263 if (status) 1264 goto out; 1265 status = decode_offload_cancel(xdr, res); 1266 1267out: 1268 return status; 1269} 1270 1271/* 1272 * Decode COPY_NOTIFY response 1273 */ 1274static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp, 1275 struct xdr_stream *xdr, 1276 void *data) 1277{ 1278 struct nfs42_copy_notify_res *res = data; 1279 struct compound_hdr hdr; 1280 int status; 1281 1282 status = decode_compound_hdr(xdr, &hdr); 1283 if (status) 1284 goto out; 1285 status = decode_sequence(xdr, &res->cnr_seq_res, rqstp); 1286 if (status) 1287 goto out; 1288 status = decode_putfh(xdr); 1289 if (status) 1290 goto out; 1291 status = decode_copy_notify(xdr, res); 1292 1293out: 1294 return status; 1295} 1296 1297/* 1298 * Decode DEALLOCATE request 1299 */ 1300static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, 1301 struct xdr_stream *xdr, 1302 void *data) 1303{ 1304 struct nfs42_falloc_res *res = data; 1305 struct compound_hdr hdr; 1306 int status; 1307 1308 status = decode_compound_hdr(xdr, &hdr); 1309 if (status) 1310 goto out; 1311 status = decode_sequence(xdr, &res->seq_res, rqstp); 1312 if (status) 1313 goto out; 1314 status = decode_putfh(xdr); 1315 if (status) 1316 goto out; 1317 status = decode_deallocate(xdr, res); 1318 if (status) 1319 goto out; 1320 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 1321out: 1322 return status; 1323} 1324 1325/* 1326 * Decode READ_PLUS request 1327 */ 1328static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp, 1329 struct xdr_stream *xdr, 1330 void *data) 1331{ 1332 struct nfs_pgio_res *res = data; 1333 struct compound_hdr hdr; 1334 int status; 1335 1336 status = decode_compound_hdr(xdr, &hdr); 1337 if (status) 1338 goto out; 1339 status = decode_sequence(xdr, &res->seq_res, rqstp); 1340 if (status) 1341 goto out; 1342 status = decode_putfh(xdr); 1343 if (status) 1344 goto out; 1345 status = decode_read_plus(xdr, res); 1346 if (!status) 1347 status = res->count; 1348out: 1349 return status; 1350} 1351 1352/* 1353 * Decode SEEK request 1354 */ 1355static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, 1356 struct xdr_stream *xdr, 1357 void *data) 1358{ 1359 struct nfs42_seek_res *res = data; 1360 struct compound_hdr hdr; 1361 int status; 1362 1363 status = decode_compound_hdr(xdr, &hdr); 1364 if (status) 1365 goto out; 1366 status = decode_sequence(xdr, &res->seq_res, rqstp); 1367 if (status) 1368 goto out; 1369 status = decode_putfh(xdr); 1370 if (status) 1371 goto out; 1372 status = decode_seek(xdr, res); 1373out: 1374 return status; 1375} 1376 1377/* 1378 * Decode LAYOUTSTATS request 1379 */ 1380static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, 1381 struct xdr_stream *xdr, 1382 void *data) 1383{ 1384 struct nfs42_layoutstat_res *res = data; 1385 struct compound_hdr hdr; 1386 int status, i; 1387 1388 status = decode_compound_hdr(xdr, &hdr); 1389 if (status) 1390 goto out; 1391 status = decode_sequence(xdr, &res->seq_res, rqstp); 1392 if (status) 1393 goto out; 1394 status = decode_putfh(xdr); 1395 if (status) 1396 goto out; 1397 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 1398 for (i = 0; i < res->num_dev; i++) { 1399 status = decode_layoutstats(xdr); 1400 if (status) 1401 goto out; 1402 } 1403out: 1404 res->rpc_status = status; 1405 return status; 1406} 1407 1408/* 1409 * Decode CLONE request 1410 */ 1411static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, 1412 struct xdr_stream *xdr, 1413 void *data) 1414{ 1415 struct nfs42_clone_res *res = data; 1416 struct compound_hdr hdr; 1417 int status; 1418 1419 status = decode_compound_hdr(xdr, &hdr); 1420 if (status) 1421 goto out; 1422 status = decode_sequence(xdr, &res->seq_res, rqstp); 1423 if (status) 1424 goto out; 1425 status = decode_putfh(xdr); 1426 if (status) 1427 goto out; 1428 status = decode_savefh(xdr); 1429 if (status) 1430 goto out; 1431 status = decode_putfh(xdr); 1432 if (status) 1433 goto out; 1434 status = decode_clone(xdr); 1435 if (status) 1436 goto out; 1437 decode_getfattr(xdr, res->dst_fattr, res->server); 1438out: 1439 res->rpc_status = status; 1440 return status; 1441} 1442 1443/* 1444 * Decode LAYOUTERROR request 1445 */ 1446static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp, 1447 struct xdr_stream *xdr, 1448 void *data) 1449{ 1450 struct nfs42_layouterror_res *res = data; 1451 struct compound_hdr hdr; 1452 int status, i; 1453 1454 status = decode_compound_hdr(xdr, &hdr); 1455 if (status) 1456 goto out; 1457 status = decode_sequence(xdr, &res->seq_res, rqstp); 1458 if (status) 1459 goto out; 1460 status = decode_putfh(xdr); 1461 1462 for (i = 0; i < res->num_errors && status == 0; i++) 1463 status = decode_layouterror(xdr); 1464out: 1465 res->rpc_status = status; 1466 return status; 1467} 1468 1469#ifdef CONFIG_NFS_V4_2 1470static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr, 1471 const void *data) 1472{ 1473 const struct nfs42_setxattrargs *args = data; 1474 struct compound_hdr hdr = { 1475 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 1476 }; 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_setxattr(xdr, args, &hdr); 1482 encode_nops(&hdr); 1483} 1484 1485static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr, 1486 void *data) 1487{ 1488 struct nfs42_setxattrres *res = data; 1489 struct compound_hdr hdr; 1490 int status; 1491 1492 status = decode_compound_hdr(xdr, &hdr); 1493 if (status) 1494 goto out; 1495 status = decode_sequence(xdr, &res->seq_res, req); 1496 if (status) 1497 goto out; 1498 status = decode_putfh(xdr); 1499 if (status) 1500 goto out; 1501 1502 status = decode_setxattr(xdr, &res->cinfo); 1503out: 1504 return status; 1505} 1506 1507static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr, 1508 const void *data) 1509{ 1510 const struct nfs42_getxattrargs *args = data; 1511 struct compound_hdr hdr = { 1512 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 1513 }; 1514 uint32_t replen; 1515 1516 encode_compound_hdr(xdr, req, &hdr); 1517 encode_sequence(xdr, &args->seq_args, &hdr); 1518 encode_putfh(xdr, args->fh, &hdr); 1519 replen = hdr.replen + op_decode_hdr_maxsz + 1; 1520 encode_getxattr(xdr, args->xattr_name, &hdr); 1521 1522 rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->xattr_len, 1523 replen); 1524 1525 encode_nops(&hdr); 1526} 1527 1528static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp, 1529 struct xdr_stream *xdr, void *data) 1530{ 1531 struct nfs42_getxattrres *res = data; 1532 struct compound_hdr hdr; 1533 int status; 1534 1535 status = decode_compound_hdr(xdr, &hdr); 1536 if (status) 1537 goto out; 1538 status = decode_sequence(xdr, &res->seq_res, rqstp); 1539 if (status) 1540 goto out; 1541 status = decode_putfh(xdr); 1542 if (status) 1543 goto out; 1544 status = decode_getxattr(xdr, res, rqstp); 1545out: 1546 return status; 1547} 1548 1549static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req, 1550 struct xdr_stream *xdr, const void *data) 1551{ 1552 const struct nfs42_listxattrsargs *args = data; 1553 struct compound_hdr hdr = { 1554 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 1555 }; 1556 uint32_t replen; 1557 1558 encode_compound_hdr(xdr, req, &hdr); 1559 encode_sequence(xdr, &args->seq_args, &hdr); 1560 encode_putfh(xdr, args->fh, &hdr); 1561 replen = hdr.replen + op_decode_hdr_maxsz + 2 + 1; 1562 encode_listxattrs(xdr, args, &hdr); 1563 1564 rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count, replen); 1565 1566 encode_nops(&hdr); 1567} 1568 1569static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp, 1570 struct xdr_stream *xdr, void *data) 1571{ 1572 struct nfs42_listxattrsres *res = data; 1573 struct compound_hdr hdr; 1574 int status; 1575 1576 xdr_set_scratch_page(xdr, res->scratch); 1577 1578 status = decode_compound_hdr(xdr, &hdr); 1579 if (status) 1580 goto out; 1581 status = decode_sequence(xdr, &res->seq_res, rqstp); 1582 if (status) 1583 goto out; 1584 status = decode_putfh(xdr); 1585 if (status) 1586 goto out; 1587 status = decode_listxattrs(xdr, res); 1588out: 1589 return status; 1590} 1591 1592static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req, 1593 struct xdr_stream *xdr, const void *data) 1594{ 1595 const struct nfs42_removexattrargs *args = data; 1596 struct compound_hdr hdr = { 1597 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 1598 }; 1599 1600 encode_compound_hdr(xdr, req, &hdr); 1601 encode_sequence(xdr, &args->seq_args, &hdr); 1602 encode_putfh(xdr, args->fh, &hdr); 1603 encode_removexattr(xdr, args->xattr_name, &hdr); 1604 encode_nops(&hdr); 1605} 1606 1607static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req, 1608 struct xdr_stream *xdr, void *data) 1609{ 1610 struct nfs42_removexattrres *res = data; 1611 struct compound_hdr hdr; 1612 int status; 1613 1614 status = decode_compound_hdr(xdr, &hdr); 1615 if (status) 1616 goto out; 1617 status = decode_sequence(xdr, &res->seq_res, req); 1618 if (status) 1619 goto out; 1620 status = decode_putfh(xdr); 1621 if (status) 1622 goto out; 1623 1624 status = decode_removexattr(xdr, &res->cinfo); 1625out: 1626 return status; 1627} 1628#endif 1629#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */