File Index
Files and directories
Sign in
FILE

nfs42xdr.c

File preview with syntax highlighting.

linux-6.19.14/fs/nfs/nfs42xdr.c C
   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/* Not limited by NFS itself, limited by the generic xattr code */
  11#define nfs4_xattr_name_maxsz   XDR_QUADLEN(XATTR_NAME_MAX)
  12
  13#define encode_fallocate_maxsz		(encode_stateid_maxsz + \
  14					 2 /* offset */ + \
  15					 2 /* length */)
  16#define NFS42_WRITE_RES_SIZE		(1 /* wr_callback_id size */ +\
  17					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  18					 2 /* wr_count */ + \
  19					 1 /* wr_committed */ + \
  20					 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
  21#define encode_allocate_maxsz		(op_encode_hdr_maxsz + \
  22					 encode_fallocate_maxsz)
  23#define decode_allocate_maxsz		(op_decode_hdr_maxsz)
  24#define encode_copy_maxsz		(op_encode_hdr_maxsz +          \
  25					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  26					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  27					 2 + 2 + 2 + 1 + 1 + 1 +\
  28					 1 + /* One cnr_source_server */\
  29					 1 + /* nl4_type */ \
  30					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
  31#define decode_copy_maxsz		(op_decode_hdr_maxsz + \
  32					 NFS42_WRITE_RES_SIZE + \
  33					 1 /* cr_consecutive */ + \
  34					 1 /* cr_synchronous */)
  35#define encode_offload_cancel_maxsz	(op_encode_hdr_maxsz + \
  36					 XDR_QUADLEN(NFS4_STATEID_SIZE))
  37#define decode_offload_cancel_maxsz	(op_decode_hdr_maxsz)
  38#define encode_offload_status_maxsz	(op_encode_hdr_maxsz + \
  39					 XDR_QUADLEN(NFS4_STATEID_SIZE))
  40#define decode_offload_status_maxsz	(op_decode_hdr_maxsz + \
  41					 2 /* osr_count */ + \
  42					 2 /* osr_complete */)
  43#define encode_copy_notify_maxsz	(op_encode_hdr_maxsz + \
  44					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  45					 1 + /* nl4_type */ \
  46					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
  47#define decode_copy_notify_maxsz	(op_decode_hdr_maxsz + \
  48					 3 + /* cnr_lease_time */\
  49					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  50					 1 + /* Support 1 cnr_source_server */\
  51					 1 + /* nl4_type */ \
  52					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
  53#define encode_deallocate_maxsz		(op_encode_hdr_maxsz + \
  54					 encode_fallocate_maxsz)
  55#define decode_deallocate_maxsz		(op_decode_hdr_maxsz)
  56#define encode_read_plus_maxsz		(op_encode_hdr_maxsz + \
  57					 encode_stateid_maxsz + 3)
  58#define NFS42_READ_PLUS_DATA_SEGMENT_SIZE \
  59					(1 /* data_content4 */ + \
  60					 2 /* data_info4.di_offset */ + \
  61					 1 /* data_info4.di_length */)
  62#define NFS42_READ_PLUS_HOLE_SEGMENT_SIZE \
  63					(1 /* data_content4 */ + \
  64					 2 /* data_info4.di_offset */ + \
  65					 2 /* data_info4.di_length */)
  66#define READ_PLUS_SEGMENT_SIZE_DIFF	(NFS42_READ_PLUS_HOLE_SEGMENT_SIZE - \
  67					 NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
  68#define decode_read_plus_maxsz		(op_decode_hdr_maxsz + \
  69					 1 /* rpr_eof */ + \
  70					 1 /* rpr_contents count */ + \
  71					 NFS42_READ_PLUS_HOLE_SEGMENT_SIZE)
  72#define encode_seek_maxsz		(op_encode_hdr_maxsz + \
  73					 encode_stateid_maxsz + \
  74					 2 /* offset */ + \
  75					 1 /* whence */)
  76#define decode_seek_maxsz		(op_decode_hdr_maxsz + \
  77					 1 /* eof */ + \
  78					 1 /* whence */ + \
  79					 2 /* offset */ + \
  80					 2 /* length */)
  81#define encode_io_info_maxsz		4
  82#define encode_layoutstats_maxsz	(op_decode_hdr_maxsz + \
  83					2 /* offset */ + \
  84					2 /* length */ + \
  85					encode_stateid_maxsz + \
  86					encode_io_info_maxsz + \
  87					encode_io_info_maxsz + \
  88					1 /* opaque devaddr4 length */ + \
  89					XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
  90#define decode_layoutstats_maxsz	(op_decode_hdr_maxsz)
  91#define encode_device_error_maxsz	(XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
  92					1 /* status */ + 1 /* opnum */)
  93#define encode_layouterror_maxsz	(op_decode_hdr_maxsz + \
  94					2 /* offset */ + \
  95					2 /* length */ + \
  96					encode_stateid_maxsz + \
  97					1 /* Array size */ + \
  98					encode_device_error_maxsz)
  99#define decode_layouterror_maxsz	(op_decode_hdr_maxsz)
 100#define encode_clone_maxsz		(encode_stateid_maxsz + \
 101					encode_stateid_maxsz + \
 102					2 /* src offset */ + \
 103					2 /* dst offset */ + \
 104					2 /* count */)
 105#define decode_clone_maxsz		(op_decode_hdr_maxsz)
 106#define encode_getxattr_maxsz		(op_encode_hdr_maxsz + 1 + \
 107					 nfs4_xattr_name_maxsz)
 108#define decode_getxattr_maxsz		(op_decode_hdr_maxsz + 1 + pagepad_maxsz)
 109#define encode_setxattr_maxsz		(op_encode_hdr_maxsz + \
 110					 1 + nfs4_xattr_name_maxsz + 1)
 111#define decode_setxattr_maxsz		(op_decode_hdr_maxsz + decode_change_info_maxsz)
 112#define encode_listxattrs_maxsz		(op_encode_hdr_maxsz + 2 + 1)
 113#define decode_listxattrs_maxsz		(op_decode_hdr_maxsz + 2 + 1 + 1 + 1)
 114#define encode_removexattr_maxsz	(op_encode_hdr_maxsz + 1 + \
 115					 nfs4_xattr_name_maxsz)
 116#define decode_removexattr_maxsz	(op_decode_hdr_maxsz + \
 117					 decode_change_info_maxsz)
 118
 119#define NFS4_enc_allocate_sz		(compound_encode_hdr_maxsz + \
 120					 encode_sequence_maxsz + \
 121					 encode_putfh_maxsz + \
 122					 encode_allocate_maxsz + \
 123					 encode_getattr_maxsz)
 124#define NFS4_dec_allocate_sz		(compound_decode_hdr_maxsz + \
 125					 decode_sequence_maxsz + \
 126					 decode_putfh_maxsz + \
 127					 decode_allocate_maxsz + \
 128					 decode_getattr_maxsz)
 129#define NFS4_enc_copy_sz		(compound_encode_hdr_maxsz + \
 130					 encode_sequence_maxsz + \
 131					 encode_putfh_maxsz + \
 132					 encode_savefh_maxsz + \
 133					 encode_putfh_maxsz + \
 134					 encode_copy_maxsz + \
 135					 encode_commit_maxsz)
 136#define NFS4_dec_copy_sz		(compound_decode_hdr_maxsz + \
 137					 decode_sequence_maxsz + \
 138					 decode_putfh_maxsz + \
 139					 decode_savefh_maxsz + \
 140					 decode_putfh_maxsz + \
 141					 decode_copy_maxsz + \
 142					 decode_commit_maxsz)
 143#define NFS4_enc_offload_cancel_sz	(compound_encode_hdr_maxsz + \
 144					 encode_sequence_maxsz + \
 145					 encode_putfh_maxsz + \
 146					 encode_offload_cancel_maxsz)
 147#define NFS4_dec_offload_cancel_sz	(compound_decode_hdr_maxsz + \
 148					 decode_sequence_maxsz + \
 149					 decode_putfh_maxsz + \
 150					 decode_offload_cancel_maxsz)
 151#define NFS4_enc_offload_status_sz	(compound_encode_hdr_maxsz + \
 152					 encode_sequence_maxsz + \
 153					 encode_putfh_maxsz + \
 154					 encode_offload_status_maxsz)
 155#define NFS4_dec_offload_status_sz	(compound_decode_hdr_maxsz + \
 156					 decode_sequence_maxsz + \
 157					 decode_putfh_maxsz + \
 158					 decode_offload_status_maxsz)
 159#define NFS4_enc_copy_notify_sz		(compound_encode_hdr_maxsz + \
 160					 encode_sequence_maxsz + \
 161					 encode_putfh_maxsz + \
 162					 encode_copy_notify_maxsz)
 163#define NFS4_dec_copy_notify_sz		(compound_decode_hdr_maxsz + \
 164					 decode_sequence_maxsz + \
 165					 decode_putfh_maxsz + \
 166					 decode_copy_notify_maxsz)
 167#define NFS4_enc_deallocate_sz		(compound_encode_hdr_maxsz + \
 168					 encode_sequence_maxsz + \
 169					 encode_putfh_maxsz + \
 170					 encode_deallocate_maxsz + \
 171					 encode_getattr_maxsz)
 172#define NFS4_dec_deallocate_sz		(compound_decode_hdr_maxsz + \
 173					 decode_sequence_maxsz + \
 174					 decode_putfh_maxsz + \
 175					 decode_deallocate_maxsz + \
 176					 decode_getattr_maxsz)
 177#define NFS4_enc_zero_range_sz		(compound_encode_hdr_maxsz + \
 178					 encode_sequence_maxsz + \
 179					 encode_putfh_maxsz + \
 180					 encode_deallocate_maxsz + \
 181					 encode_allocate_maxsz + \
 182					 encode_getattr_maxsz)
 183#define NFS4_dec_zero_range_sz		(compound_decode_hdr_maxsz + \
 184					 decode_sequence_maxsz + \
 185					 decode_putfh_maxsz + \
 186					 decode_deallocate_maxsz + \
 187					 decode_allocate_maxsz + \
 188					 decode_getattr_maxsz)
 189#define NFS4_enc_read_plus_sz		(compound_encode_hdr_maxsz + \
 190					 encode_sequence_maxsz + \
 191					 encode_putfh_maxsz + \
 192					 encode_read_plus_maxsz)
 193#define NFS4_dec_read_plus_sz		(compound_decode_hdr_maxsz + \
 194					 decode_sequence_maxsz + \
 195					 decode_putfh_maxsz + \
 196					 decode_read_plus_maxsz)
 197#define NFS4_enc_seek_sz		(compound_encode_hdr_maxsz + \
 198					 encode_sequence_maxsz + \
 199					 encode_putfh_maxsz + \
 200					 encode_seek_maxsz)
 201#define NFS4_dec_seek_sz		(compound_decode_hdr_maxsz + \
 202					 decode_sequence_maxsz + \
 203					 decode_putfh_maxsz + \
 204					 decode_seek_maxsz)
 205#define NFS4_enc_layoutstats_sz		(compound_encode_hdr_maxsz + \
 206					 encode_sequence_maxsz + \
 207					 encode_putfh_maxsz + \
 208					 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
 209#define NFS4_dec_layoutstats_sz		(compound_decode_hdr_maxsz + \
 210					 decode_sequence_maxsz + \
 211					 decode_putfh_maxsz + \
 212					 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
 213#define NFS4_enc_layouterror_sz		(compound_encode_hdr_maxsz + \
 214					 encode_sequence_maxsz + \
 215					 encode_putfh_maxsz + \
 216					 NFS42_LAYOUTERROR_MAX * \
 217					 encode_layouterror_maxsz)
 218#define NFS4_dec_layouterror_sz		(compound_decode_hdr_maxsz + \
 219					 decode_sequence_maxsz + \
 220					 decode_putfh_maxsz + \
 221					 NFS42_LAYOUTERROR_MAX * \
 222					 decode_layouterror_maxsz)
 223#define NFS4_enc_clone_sz		(compound_encode_hdr_maxsz + \
 224					 encode_sequence_maxsz + \
 225					 encode_putfh_maxsz + \
 226					 encode_savefh_maxsz + \
 227					 encode_putfh_maxsz + \
 228					 encode_clone_maxsz + \
 229					 encode_getattr_maxsz)
 230#define NFS4_dec_clone_sz		(compound_decode_hdr_maxsz + \
 231					 decode_sequence_maxsz + \
 232					 decode_putfh_maxsz + \
 233					 decode_savefh_maxsz + \
 234					 decode_putfh_maxsz + \
 235					 decode_clone_maxsz + \
 236					 decode_getattr_maxsz)
 237#define NFS4_enc_getxattr_sz		(compound_encode_hdr_maxsz + \
 238					 encode_sequence_maxsz + \
 239					 encode_putfh_maxsz + \
 240					 encode_getxattr_maxsz)
 241#define NFS4_dec_getxattr_sz		(compound_decode_hdr_maxsz + \
 242					 decode_sequence_maxsz + \
 243					 decode_putfh_maxsz + \
 244					 decode_getxattr_maxsz)
 245#define NFS4_enc_setxattr_sz		(compound_encode_hdr_maxsz + \
 246					 encode_sequence_maxsz + \
 247					 encode_putfh_maxsz + \
 248					 encode_setxattr_maxsz + \
 249					 encode_getattr_maxsz)
 250#define NFS4_dec_setxattr_sz		(compound_decode_hdr_maxsz + \
 251					 decode_sequence_maxsz + \
 252					 decode_putfh_maxsz + \
 253					 decode_setxattr_maxsz + \
 254					 decode_getattr_maxsz)
 255#define NFS4_enc_listxattrs_sz		(compound_encode_hdr_maxsz + \
 256					 encode_sequence_maxsz + \
 257					 encode_putfh_maxsz + \
 258					 encode_listxattrs_maxsz)
 259#define NFS4_dec_listxattrs_sz		(compound_decode_hdr_maxsz + \
 260					 decode_sequence_maxsz + \
 261					 decode_putfh_maxsz + \
 262					 decode_listxattrs_maxsz)
 263#define NFS4_enc_removexattr_sz		(compound_encode_hdr_maxsz + \
 264					 encode_sequence_maxsz + \
 265					 encode_putfh_maxsz + \
 266					 encode_removexattr_maxsz)
 267#define NFS4_dec_removexattr_sz		(compound_decode_hdr_maxsz + \
 268					 decode_sequence_maxsz + \
 269					 decode_putfh_maxsz + \
 270					 decode_removexattr_maxsz)
 271
 272/*
 273 * These values specify the maximum amount of data that is not
 274 * associated with the extended attribute name or extended
 275 * attribute list in the SETXATTR, GETXATTR and LISTXATTR
 276 * respectively.
 277 */
 278const u32 nfs42_maxsetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 279					compound_encode_hdr_maxsz +
 280					encode_sequence_maxsz +
 281					encode_putfh_maxsz + 1 +
 282					nfs4_xattr_name_maxsz)
 283					* XDR_UNIT);
 284
 285const u32 nfs42_maxgetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 286					compound_decode_hdr_maxsz +
 287					decode_sequence_maxsz +
 288					decode_putfh_maxsz + 1) * XDR_UNIT);
 289
 290const u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 291					compound_decode_hdr_maxsz +
 292					decode_sequence_maxsz +
 293					decode_putfh_maxsz + 3) * XDR_UNIT);
 294
 295static void encode_fallocate(struct xdr_stream *xdr,
 296			     const struct nfs42_falloc_args *args)
 297{
 298	encode_nfs4_stateid(xdr, &args->falloc_stateid);
 299	encode_uint64(xdr, args->falloc_offset);
 300	encode_uint64(xdr, args->falloc_length);
 301}
 302
 303static void encode_allocate(struct xdr_stream *xdr,
 304			    const struct nfs42_falloc_args *args,
 305			    struct compound_hdr *hdr)
 306{
 307	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
 308	encode_fallocate(xdr, args);
 309}
 310
 311static void encode_nl4_server(struct xdr_stream *xdr,
 312			      const struct nl4_server *ns)
 313{
 314	encode_uint32(xdr, ns->nl4_type);
 315	switch (ns->nl4_type) {
 316	case NL4_NAME:
 317	case NL4_URL:
 318		encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
 319		break;
 320	case NL4_NETADDR:
 321		encode_string(xdr, ns->u.nl4_addr.netid_len,
 322			      ns->u.nl4_addr.netid);
 323		encode_string(xdr, ns->u.nl4_addr.addr_len,
 324			      ns->u.nl4_addr.addr);
 325		break;
 326	default:
 327		WARN_ON_ONCE(1);
 328	}
 329}
 330
 331static void encode_copy(struct xdr_stream *xdr,
 332			const struct nfs42_copy_args *args,
 333			struct compound_hdr *hdr)
 334{
 335	encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
 336	encode_nfs4_stateid(xdr, &args->src_stateid);
 337	encode_nfs4_stateid(xdr, &args->dst_stateid);
 338
 339	encode_uint64(xdr, args->src_pos);
 340	encode_uint64(xdr, args->dst_pos);
 341	encode_uint64(xdr, args->count);
 342
 343	encode_uint32(xdr, 1); /* consecutive = true */
 344	encode_uint32(xdr, args->sync);
 345	if (args->cp_src == NULL) { /* intra-ssc */
 346		encode_uint32(xdr, 0); /* no src server list */
 347		return;
 348	}
 349	encode_uint32(xdr, 1); /* supporting 1 server */
 350	encode_nl4_server(xdr, args->cp_src);
 351}
 352
 353static void encode_copy_commit(struct xdr_stream *xdr,
 354			  const struct nfs42_copy_args *args,
 355			  struct compound_hdr *hdr)
 356{
 357	__be32 *p;
 358
 359	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
 360	p = reserve_space(xdr, 12);
 361	p = xdr_encode_hyper(p, args->dst_pos);
 362	*p = cpu_to_be32(args->count);
 363}
 364
 365static void encode_offload_cancel(struct xdr_stream *xdr,
 366				  const struct nfs42_offload_status_args *args,
 367				  struct compound_hdr *hdr)
 368{
 369	encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
 370	encode_nfs4_stateid(xdr, &args->osa_stateid);
 371}
 372
 373static void encode_offload_status(struct xdr_stream *xdr,
 374				  const struct nfs42_offload_status_args *args,
 375				  struct compound_hdr *hdr)
 376{
 377	encode_op_hdr(xdr, OP_OFFLOAD_STATUS, decode_offload_status_maxsz, hdr);
 378	encode_nfs4_stateid(xdr, &args->osa_stateid);
 379}
 380
 381static void encode_copy_notify(struct xdr_stream *xdr,
 382			       const struct nfs42_copy_notify_args *args,
 383			       struct compound_hdr *hdr)
 384{
 385	encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
 386	encode_nfs4_stateid(xdr, &args->cna_src_stateid);
 387	encode_nl4_server(xdr, &args->cna_dst);
 388}
 389
 390static void encode_deallocate(struct xdr_stream *xdr,
 391			      const struct nfs42_falloc_args *args,
 392			      struct compound_hdr *hdr)
 393{
 394	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
 395	encode_fallocate(xdr, args);
 396}
 397
 398static void encode_read_plus(struct xdr_stream *xdr,
 399			     const struct nfs_pgio_args *args,
 400			     struct compound_hdr *hdr)
 401{
 402	encode_op_hdr(xdr, OP_READ_PLUS, decode_read_plus_maxsz, hdr);
 403	encode_nfs4_stateid(xdr, &args->stateid);
 404	encode_uint64(xdr, args->offset);
 405	encode_uint32(xdr, args->count);
 406}
 407
 408static void encode_seek(struct xdr_stream *xdr,
 409			const struct nfs42_seek_args *args,
 410			struct compound_hdr *hdr)
 411{
 412	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
 413	encode_nfs4_stateid(xdr, &args->sa_stateid);
 414	encode_uint64(xdr, args->sa_offset);
 415	encode_uint32(xdr, args->sa_what);
 416}
 417
 418static void encode_layoutstats(struct xdr_stream *xdr,
 419			       const struct nfs42_layoutstat_args *args,
 420			       struct nfs42_layoutstat_devinfo *devinfo,
 421			       struct compound_hdr *hdr)
 422{
 423	__be32 *p;
 424
 425	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
 426	p = reserve_space(xdr, 8 + 8);
 427	p = xdr_encode_hyper(p, devinfo->offset);
 428	p = xdr_encode_hyper(p, devinfo->length);
 429	encode_nfs4_stateid(xdr, &args->stateid);
 430	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
 431	p = xdr_encode_hyper(p, devinfo->read_count);
 432	p = xdr_encode_hyper(p, devinfo->read_bytes);
 433	p = xdr_encode_hyper(p, devinfo->write_count);
 434	p = xdr_encode_hyper(p, devinfo->write_bytes);
 435	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
 436			NFS4_DEVICEID4_SIZE);
 437	/* Encode layoutupdate4 */
 438	*p++ = cpu_to_be32(devinfo->layout_type);
 439	if (devinfo->ld_private.ops)
 440		devinfo->ld_private.ops->encode(xdr, args,
 441				&devinfo->ld_private);
 442	else
 443		encode_uint32(xdr, 0);
 444}
 445
 446static void encode_clone(struct xdr_stream *xdr,
 447			 const struct nfs42_clone_args *args,
 448			 struct compound_hdr *hdr)
 449{
 450	__be32 *p;
 451
 452	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
 453	encode_nfs4_stateid(xdr, &args->src_stateid);
 454	encode_nfs4_stateid(xdr, &args->dst_stateid);
 455	p = reserve_space(xdr, 3*8);
 456	p = xdr_encode_hyper(p, args->src_offset);
 457	p = xdr_encode_hyper(p, args->dst_offset);
 458	xdr_encode_hyper(p, args->count);
 459}
 460
 461static void encode_device_error(struct xdr_stream *xdr,
 462				const struct nfs42_device_error *error)
 463{
 464	__be32 *p;
 465
 466	p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
 467	p = xdr_encode_opaque_fixed(p, error->dev_id.data,
 468			NFS4_DEVICEID4_SIZE);
 469	*p++ = cpu_to_be32(error->status);
 470	*p = cpu_to_be32(error->opnum);
 471}
 472
 473static void encode_layouterror(struct xdr_stream *xdr,
 474			       const struct nfs42_layout_error *args,
 475			       struct compound_hdr *hdr)
 476{
 477	__be32 *p;
 478
 479	encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
 480	p = reserve_space(xdr, 8 + 8);
 481	p = xdr_encode_hyper(p, args->offset);
 482	p = xdr_encode_hyper(p, args->length);
 483	encode_nfs4_stateid(xdr, &args->stateid);
 484	p = reserve_space(xdr, 4);
 485	*p = cpu_to_be32(1);
 486	encode_device_error(xdr, &args->errors[0]);
 487}
 488
 489static void encode_setxattr(struct xdr_stream *xdr,
 490			    const struct nfs42_setxattrargs *arg,
 491			    struct compound_hdr *hdr)
 492{
 493	__be32 *p;
 494
 495	BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
 496	BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
 497
 498	encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
 499	p = reserve_space(xdr, 4);
 500	*p = cpu_to_be32(arg->xattr_flags);
 501	encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
 502	p = reserve_space(xdr, 4);
 503	*p = cpu_to_be32(arg->xattr_len);
 504	if (arg->xattr_len)
 505		xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
 506}
 507
 508static void encode_getxattr(struct xdr_stream *xdr, const char *name,
 509			    struct compound_hdr *hdr)
 510{
 511	encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
 512	encode_string(xdr, strlen(name), name);
 513}
 514
 515static void encode_removexattr(struct xdr_stream *xdr, const char *name,
 516			       struct compound_hdr *hdr)
 517{
 518	encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
 519	encode_string(xdr, strlen(name), name);
 520}
 521
 522static void encode_listxattrs(struct xdr_stream *xdr,
 523			     const struct nfs42_listxattrsargs *arg,
 524			     struct compound_hdr *hdr)
 525{
 526	__be32 *p;
 527
 528	encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr);
 529
 530	p = reserve_space(xdr, 12);
 531	if (unlikely(!p))
 532		return;
 533
 534	p = xdr_encode_hyper(p, arg->cookie);
 535	/*
 536	 * RFC 8276 says to specify the full max length of the LISTXATTRS
 537	 * XDR reply. Count is set to the XDR length of the names array
 538	 * plus the EOF marker. So, add the cookie and the names count.
 539	 */
 540	*p = cpu_to_be32(arg->count + 8 + 4);
 541}
 542
 543/*
 544 * Encode ALLOCATE request
 545 */
 546static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
 547				  struct xdr_stream *xdr,
 548				  const void *data)
 549{
 550	const struct nfs42_falloc_args *args = data;
 551	struct compound_hdr hdr = {
 552		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 553	};
 554
 555	encode_compound_hdr(xdr, req, &hdr);
 556	encode_sequence(xdr, &args->seq_args, &hdr);
 557	encode_putfh(xdr, args->falloc_fh, &hdr);
 558	encode_allocate(xdr, args, &hdr);
 559	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
 560	encode_nops(&hdr);
 561}
 562
 563/*
 564 * Encode COPY request
 565 */
 566static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
 567			      struct xdr_stream *xdr,
 568			      const void *data)
 569{
 570	const struct nfs42_copy_args *args = data;
 571	struct compound_hdr hdr = {
 572		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 573	};
 574
 575	encode_compound_hdr(xdr, req, &hdr);
 576	encode_sequence(xdr, &args->seq_args, &hdr);
 577	encode_putfh(xdr, args->src_fh, &hdr);
 578	encode_savefh(xdr, &hdr);
 579	encode_putfh(xdr, args->dst_fh, &hdr);
 580	encode_copy(xdr, args, &hdr);
 581	if (args->sync)
 582		encode_copy_commit(xdr, args, &hdr);
 583	encode_nops(&hdr);
 584}
 585
 586/*
 587 * Encode OFFLOAD_CANCEL request
 588 */
 589static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
 590					struct xdr_stream *xdr,
 591					const void *data)
 592{
 593	const struct nfs42_offload_status_args *args = data;
 594	struct compound_hdr hdr = {
 595		.minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
 596	};
 597
 598	encode_compound_hdr(xdr, req, &hdr);
 599	encode_sequence(xdr, &args->osa_seq_args, &hdr);
 600	encode_putfh(xdr, args->osa_src_fh, &hdr);
 601	encode_offload_cancel(xdr, args, &hdr);
 602	encode_nops(&hdr);
 603}
 604
 605/*
 606 * Encode OFFLOAD_STATUS request
 607 */
 608static void nfs4_xdr_enc_offload_status(struct rpc_rqst *req,
 609					struct xdr_stream *xdr,
 610					const void *data)
 611{
 612	const struct nfs42_offload_status_args *args = data;
 613	struct compound_hdr hdr = {
 614		.minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
 615	};
 616
 617	encode_compound_hdr(xdr, req, &hdr);
 618	encode_sequence(xdr, &args->osa_seq_args, &hdr);
 619	encode_putfh(xdr, args->osa_src_fh, &hdr);
 620	encode_offload_status(xdr, args, &hdr);
 621	encode_nops(&hdr);
 622}
 623
 624/*
 625 * Encode COPY_NOTIFY request
 626 */
 627static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
 628				     struct xdr_stream *xdr,
 629				     const void *data)
 630{
 631	const struct nfs42_copy_notify_args *args = data;
 632	struct compound_hdr hdr = {
 633		.minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
 634	};
 635
 636	encode_compound_hdr(xdr, req, &hdr);
 637	encode_sequence(xdr, &args->cna_seq_args, &hdr);
 638	encode_putfh(xdr, args->cna_src_fh, &hdr);
 639	encode_copy_notify(xdr, args, &hdr);
 640	encode_nops(&hdr);
 641}
 642
 643/*
 644 * Encode DEALLOCATE request
 645 */
 646static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
 647				    struct xdr_stream *xdr,
 648				    const void *data)
 649{
 650	const struct nfs42_falloc_args *args = data;
 651	struct compound_hdr hdr = {
 652		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 653	};
 654
 655	encode_compound_hdr(xdr, req, &hdr);
 656	encode_sequence(xdr, &args->seq_args, &hdr);
 657	encode_putfh(xdr, args->falloc_fh, &hdr);
 658	encode_deallocate(xdr, args, &hdr);
 659	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
 660	encode_nops(&hdr);
 661}
 662
 663/*
 664 * Encode ZERO_RANGE request
 665 */
 666static void nfs4_xdr_enc_zero_range(struct rpc_rqst *req,
 667				    struct xdr_stream *xdr,
 668				    const void *data)
 669{
 670	const struct nfs42_falloc_args *args = data;
 671	struct compound_hdr hdr = {
 672		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 673	};
 674
 675	encode_compound_hdr(xdr, req, &hdr);
 676	encode_sequence(xdr, &args->seq_args, &hdr);
 677	encode_putfh(xdr, args->falloc_fh, &hdr);
 678	encode_deallocate(xdr, args, &hdr);
 679	encode_allocate(xdr, args, &hdr);
 680	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
 681	encode_nops(&hdr);
 682}
 683
 684/*
 685 * Encode READ_PLUS request
 686 */
 687static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
 688				   struct xdr_stream *xdr,
 689				   const void *data)
 690{
 691	const struct nfs_pgio_args *args = data;
 692	struct compound_hdr hdr = {
 693		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 694	};
 695
 696	encode_compound_hdr(xdr, req, &hdr);
 697	encode_sequence(xdr, &args->seq_args, &hdr);
 698	encode_putfh(xdr, args->fh, &hdr);
 699	encode_read_plus(xdr, args, &hdr);
 700
 701	rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
 702				hdr.replen - READ_PLUS_SEGMENT_SIZE_DIFF);
 703	encode_nops(&hdr);
 704}
 705
 706/*
 707 * Encode SEEK request
 708 */
 709static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
 710			      struct xdr_stream *xdr,
 711			      const void *data)
 712{
 713	const struct nfs42_seek_args *args = data;
 714	struct compound_hdr hdr = {
 715		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 716	};
 717
 718	encode_compound_hdr(xdr, req, &hdr);
 719	encode_sequence(xdr, &args->seq_args, &hdr);
 720	encode_putfh(xdr, args->sa_fh, &hdr);
 721	encode_seek(xdr, args, &hdr);
 722	encode_nops(&hdr);
 723}
 724
 725/*
 726 * Encode LAYOUTSTATS request
 727 */
 728static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
 729				     struct xdr_stream *xdr,
 730				     const void *data)
 731{
 732	const struct nfs42_layoutstat_args *args = data;
 733	int i;
 734
 735	struct compound_hdr hdr = {
 736		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 737	};
 738
 739	encode_compound_hdr(xdr, req, &hdr);
 740	encode_sequence(xdr, &args->seq_args, &hdr);
 741	encode_putfh(xdr, args->fh, &hdr);
 742	WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
 743	for (i = 0; i < args->num_dev; i++)
 744		encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
 745	encode_nops(&hdr);
 746}
 747
 748/*
 749 * Encode CLONE request
 750 */
 751static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
 752			       struct xdr_stream *xdr,
 753			       const void *data)
 754{
 755	const struct nfs42_clone_args *args = data;
 756	struct compound_hdr hdr = {
 757		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 758	};
 759
 760	encode_compound_hdr(xdr, req, &hdr);
 761	encode_sequence(xdr, &args->seq_args, &hdr);
 762	encode_putfh(xdr, args->src_fh, &hdr);
 763	encode_savefh(xdr, &hdr);
 764	encode_putfh(xdr, args->dst_fh, &hdr);
 765	encode_clone(xdr, args, &hdr);
 766	encode_getfattr(xdr, args->dst_bitmask, &hdr);
 767	encode_nops(&hdr);
 768}
 769
 770/*
 771 * Encode LAYOUTERROR request
 772 */
 773static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
 774				     struct xdr_stream *xdr,
 775				     const void *data)
 776{
 777	const struct nfs42_layouterror_args *args = data;
 778	struct compound_hdr hdr = {
 779		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 780	};
 781	int i;
 782
 783	encode_compound_hdr(xdr, req, &hdr);
 784	encode_sequence(xdr, &args->seq_args, &hdr);
 785	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
 786	for (i = 0; i < args->num_errors; i++)
 787		encode_layouterror(xdr, &args->errors[i], &hdr);
 788	encode_nops(&hdr);
 789}
 790
 791/*
 792 * Encode SETXATTR request
 793 */
 794static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
 795				  const void *data)
 796{
 797	const struct nfs42_setxattrargs *args = data;
 798	struct compound_hdr hdr = {
 799		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 800	};
 801
 802	encode_compound_hdr(xdr, req, &hdr);
 803	encode_sequence(xdr, &args->seq_args, &hdr);
 804	encode_putfh(xdr, args->fh, &hdr);
 805	encode_setxattr(xdr, args, &hdr);
 806	encode_getfattr(xdr, args->bitmask, &hdr);
 807	encode_nops(&hdr);
 808}
 809
 810/*
 811 * Encode GETXATTR request
 812 */
 813static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
 814				  const void *data)
 815{
 816	const struct nfs42_getxattrargs *args = data;
 817	struct compound_hdr hdr = {
 818		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 819	};
 820	uint32_t replen;
 821
 822	encode_compound_hdr(xdr, req, &hdr);
 823	encode_sequence(xdr, &args->seq_args, &hdr);
 824	encode_putfh(xdr, args->fh, &hdr);
 825	replen = hdr.replen + op_decode_hdr_maxsz + 1;
 826	encode_getxattr(xdr, args->xattr_name, &hdr);
 827
 828	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->xattr_len,
 829				replen);
 830
 831	encode_nops(&hdr);
 832}
 833
 834/*
 835 * Encode LISTXATTR request
 836 */
 837static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
 838				    struct xdr_stream *xdr, const void *data)
 839{
 840	const struct nfs42_listxattrsargs *args = data;
 841	struct compound_hdr hdr = {
 842		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 843	};
 844	uint32_t replen;
 845
 846	encode_compound_hdr(xdr, req, &hdr);
 847	encode_sequence(xdr, &args->seq_args, &hdr);
 848	encode_putfh(xdr, args->fh, &hdr);
 849	replen = hdr.replen + op_decode_hdr_maxsz + 2 + 1;
 850	encode_listxattrs(xdr, args, &hdr);
 851
 852	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count, replen);
 853
 854	encode_nops(&hdr);
 855}
 856
 857/*
 858 * Encode REMOVEXATTR request
 859 */
 860static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
 861				     struct xdr_stream *xdr, const void *data)
 862{
 863	const struct nfs42_removexattrargs *args = data;
 864	struct compound_hdr hdr = {
 865		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 866	};
 867
 868	encode_compound_hdr(xdr, req, &hdr);
 869	encode_sequence(xdr, &args->seq_args, &hdr);
 870	encode_putfh(xdr, args->fh, &hdr);
 871	encode_removexattr(xdr, args->xattr_name, &hdr);
 872	encode_nops(&hdr);
 873}
 874
 875static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
 876{
 877	return decode_op_hdr(xdr, OP_ALLOCATE);
 878}
 879
 880static int decode_write_response(struct xdr_stream *xdr,
 881				 struct nfs42_write_res *res)
 882{
 883	__be32 *p;
 884	int status, count;
 885
 886	p = xdr_inline_decode(xdr, 4);
 887	if (unlikely(!p))
 888		return -EIO;
 889	count = be32_to_cpup(p);
 890	if (count > 1)
 891		return -EREMOTEIO;
 892	else if (count == 1) {
 893		status = decode_opaque_fixed(xdr, &res->stateid,
 894				NFS4_STATEID_SIZE);
 895		if (unlikely(status))
 896			return -EIO;
 897	}
 898	p = xdr_inline_decode(xdr, 8 + 4);
 899	if (unlikely(!p))
 900		return -EIO;
 901	p = xdr_decode_hyper(p, &res->count);
 902	res->verifier.committed = be32_to_cpup(p);
 903	return decode_verifier(xdr, &res->verifier.verifier);
 904}
 905
 906static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
 907{
 908	struct nfs42_netaddr *naddr;
 909	uint32_t dummy;
 910	char *dummy_str;
 911	__be32 *p;
 912	int status;
 913
 914	/* nl_type */
 915	p = xdr_inline_decode(xdr, 4);
 916	if (unlikely(!p))
 917		return -EIO;
 918	ns->nl4_type = be32_to_cpup(p);
 919	switch (ns->nl4_type) {
 920	case NL4_NAME:
 921	case NL4_URL:
 922		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 923		if (unlikely(status))
 924			return status;
 925		if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
 926			return -EIO;
 927		memcpy(&ns->u.nl4_str, dummy_str, dummy);
 928		ns->u.nl4_str_sz = dummy;
 929		break;
 930	case NL4_NETADDR:
 931		naddr = &ns->u.nl4_addr;
 932
 933		/* netid string */
 934		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 935		if (unlikely(status))
 936			return status;
 937		if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
 938			return -EIO;
 939		naddr->netid_len = dummy;
 940		memcpy(naddr->netid, dummy_str, naddr->netid_len);
 941
 942		/* uaddr string */
 943		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 944		if (unlikely(status))
 945			return status;
 946		if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
 947			return -EIO;
 948		naddr->addr_len = dummy;
 949		memcpy(naddr->addr, dummy_str, naddr->addr_len);
 950		break;
 951	default:
 952		WARN_ON_ONCE(1);
 953		return -EIO;
 954	}
 955	return 0;
 956}
 957
 958static int decode_copy_requirements(struct xdr_stream *xdr,
 959				    struct nfs42_copy_res *res) {
 960	__be32 *p;
 961
 962	p = xdr_inline_decode(xdr, 4 + 4);
 963	if (unlikely(!p))
 964		return -EIO;
 965
 966	res->consecutive = be32_to_cpup(p++);
 967	res->synchronous = be32_to_cpup(p++);
 968	return 0;
 969}
 970
 971static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
 972{
 973	int status;
 974
 975	status = decode_op_hdr(xdr, OP_COPY);
 976	if (status == NFS4ERR_OFFLOAD_NO_REQS) {
 977		status = decode_copy_requirements(xdr, res);
 978		if (status)
 979			return status;
 980		return NFS4ERR_OFFLOAD_NO_REQS;
 981	} else if (status)
 982		return status;
 983
 984	status = decode_write_response(xdr, &res->write_res);
 985	if (status)
 986		return status;
 987
 988	return decode_copy_requirements(xdr, res);
 989}
 990
 991static int decode_offload_cancel(struct xdr_stream *xdr,
 992				 struct nfs42_offload_status_res *res)
 993{
 994	return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
 995}
 996
 997static int decode_offload_status(struct xdr_stream *xdr,
 998				 struct nfs42_offload_status_res *res)
 999{
1000	ssize_t result;
1001	int status;
1002
1003	status = decode_op_hdr(xdr, OP_OFFLOAD_STATUS);
1004	if (status)
1005		return status;
1006	/* osr_count */
1007	if (xdr_stream_decode_u64(xdr, &res->osr_count) < 0)
1008		return -EIO;
1009	/* osr_complete<1> */
1010	result = xdr_stream_decode_uint32_array(xdr, &res->osr_complete, 1);
1011	if (result < 0)
1012		return -EIO;
1013	res->complete_count = result;
1014	return 0;
1015}
1016
1017static int decode_copy_notify(struct xdr_stream *xdr,
1018			      struct nfs42_copy_notify_res *res)
1019{
1020	__be32 *p;
1021	int status, count;
1022
1023	status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
1024	if (status)
1025		return status;
1026	/* cnr_lease_time */
1027	p = xdr_inline_decode(xdr, 12);
1028	if (unlikely(!p))
1029		return -EIO;
1030	p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
1031	res->cnr_lease_time.nseconds = be32_to_cpup(p);
1032
1033	status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
1034	if (unlikely(status))
1035		return -EIO;
1036
1037	/* number of source addresses */
1038	p = xdr_inline_decode(xdr, 4);
1039	if (unlikely(!p))
1040		return -EIO;
1041
1042	count = be32_to_cpup(p);
1043	if (count > 1)
1044		pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
1045			 __func__, count);
1046
1047	status = decode_nl4_server(xdr, &res->cnr_src);
1048	if (unlikely(status))
1049		return -EIO;
1050	return 0;
1051}
1052
1053static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
1054{
1055	return decode_op_hdr(xdr, OP_DEALLOCATE);
1056}
1057
1058struct read_plus_segment {
1059	enum data_content4 type;
1060	uint64_t offset;
1061	union {
1062		struct {
1063			uint64_t length;
1064		} hole;
1065
1066		struct {
1067			uint32_t length;
1068			unsigned int from;
1069		} data;
1070	};
1071};
1072
1073static inline uint64_t read_plus_segment_length(struct read_plus_segment *seg)
1074{
1075	return seg->type == NFS4_CONTENT_DATA ? seg->data.length : seg->hole.length;
1076}
1077
1078static int decode_read_plus_segment(struct xdr_stream *xdr,
1079				    struct read_plus_segment *seg)
1080{
1081	__be32 *p;
1082
1083	p = xdr_inline_decode(xdr, 4);
1084	if (!p)
1085		return -EIO;
1086	seg->type = be32_to_cpup(p++);
1087
1088	p = xdr_inline_decode(xdr, seg->type == NFS4_CONTENT_DATA ? 12 : 16);
1089	if (!p)
1090		return -EIO;
1091	p = xdr_decode_hyper(p, &seg->offset);
1092
1093	if (seg->type == NFS4_CONTENT_DATA) {
1094		struct xdr_buf buf;
1095		uint32_t len = be32_to_cpup(p);
1096
1097		seg->data.length = len;
1098		seg->data.from = xdr_stream_pos(xdr);
1099
1100		if (!xdr_stream_subsegment(xdr, &buf, xdr_align_size(len)))
1101			return -EIO;
1102	} else if (seg->type == NFS4_CONTENT_HOLE) {
1103		xdr_decode_hyper(p, &seg->hole.length);
1104	} else
1105		return -EINVAL;
1106	return 0;
1107}
1108
1109static int process_read_plus_segment(struct xdr_stream *xdr,
1110				     struct nfs_pgio_args *args,
1111				     struct nfs_pgio_res *res,
1112				     struct read_plus_segment *seg)
1113{
1114	unsigned long offset = seg->offset;
1115	unsigned long length = read_plus_segment_length(seg);
1116	unsigned int bufpos;
1117
1118	if (offset + length < args->offset)
1119		return 0;
1120	else if (offset > args->offset + args->count) {
1121		res->eof = 0;
1122		return 0;
1123	} else if (offset < args->offset) {
1124		length -= (args->offset - offset);
1125		offset = args->offset;
1126	} else if (offset + length > args->offset + args->count) {
1127		length = (args->offset + args->count) - offset;
1128		res->eof = 0;
1129	}
1130
1131	bufpos = xdr->buf->head[0].iov_len + (offset - args->offset);
1132	if (seg->type == NFS4_CONTENT_HOLE)
1133		return xdr_stream_zero(xdr, bufpos, length);
1134	else
1135		return xdr_stream_move_subsegment(xdr, seg->data.from, bufpos, length);
1136}
1137
1138static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
1139{
1140	struct nfs_pgio_header *hdr =
1141		container_of(res, struct nfs_pgio_header, res);
1142	struct nfs_pgio_args *args = &hdr->args;
1143	uint32_t segments;
1144	struct read_plus_segment *segs;
1145	int status, i;
1146	__be32 *p;
1147
1148	status = decode_op_hdr(xdr, OP_READ_PLUS);
1149	if (status)
1150		return status;
1151
1152	p = xdr_inline_decode(xdr, 4 + 4);
1153	if (unlikely(!p))
1154		return -EIO;
1155
1156	res->count = 0;
1157	res->eof = be32_to_cpup(p++);
1158	segments = be32_to_cpup(p++);
1159	if (segments == 0)
1160		return 0;
1161
1162	segs = kmalloc_array(segments, sizeof(*segs), GFP_KERNEL);
1163	if (!segs)
1164		return -ENOMEM;
1165
1166	for (i = 0; i < segments; i++) {
1167		status = decode_read_plus_segment(xdr, &segs[i]);
1168		if (status < 0)
1169			goto out;
1170	}
1171
1172	xdr_set_pagelen(xdr, xdr_align_size(args->count));
1173	for (i = segments; i > 0; i--)
1174		res->count += process_read_plus_segment(xdr, args, res, &segs[i-1]);
1175	status = 0;
1176
1177out:
1178	kfree(segs);
1179	return status;
1180}
1181
1182static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
1183{
1184	int status;
1185	__be32 *p;
1186
1187	status = decode_op_hdr(xdr, OP_SEEK);
1188	if (status)
1189		return status;
1190
1191	p = xdr_inline_decode(xdr, 4 + 8);
1192	if (unlikely(!p))
1193		return -EIO;
1194
1195	res->sr_eof = be32_to_cpup(p++);
1196	p = xdr_decode_hyper(p, &res->sr_offset);
1197	return 0;
1198}
1199
1200static int decode_layoutstats(struct xdr_stream *xdr)
1201{
1202	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
1203}
1204
1205static int decode_clone(struct xdr_stream *xdr)
1206{
1207	return decode_op_hdr(xdr, OP_CLONE);
1208}
1209
1210static int decode_layouterror(struct xdr_stream *xdr)
1211{
1212	return decode_op_hdr(xdr, OP_LAYOUTERROR);
1213}
1214
1215static int decode_setxattr(struct xdr_stream *xdr,
1216			   struct nfs4_change_info *cinfo)
1217{
1218	int status;
1219
1220	status = decode_op_hdr(xdr, OP_SETXATTR);
1221	if (status)
1222		goto out;
1223	status = decode_change_info(xdr, cinfo);
1224out:
1225	return status;
1226}
1227
1228static int decode_getxattr(struct xdr_stream *xdr,
1229			   struct nfs42_getxattrres *res,
1230			   struct rpc_rqst *req)
1231{
1232	int status;
1233	__be32 *p;
1234	u32 len, rdlen;
1235
1236	status = decode_op_hdr(xdr, OP_GETXATTR);
1237	if (status)
1238		return status;
1239
1240	p = xdr_inline_decode(xdr, 4);
1241	if (unlikely(!p))
1242		return -EIO;
1243
1244	len = be32_to_cpup(p);
1245
1246	/*
1247	 * Only check against the page length here. The actual
1248	 * requested length may be smaller, but that is only
1249	 * checked against after possibly caching a valid reply.
1250	 */
1251	if (len > req->rq_rcv_buf.page_len)
1252		return -ERANGE;
1253
1254	res->xattr_len = len;
1255
1256	if (len > 0) {
1257		rdlen = xdr_read_pages(xdr, len);
1258		if (rdlen < len)
1259			return -EIO;
1260	}
1261
1262	return 0;
1263}
1264
1265static int decode_removexattr(struct xdr_stream *xdr,
1266			   struct nfs4_change_info *cinfo)
1267{
1268	int status;
1269
1270	status = decode_op_hdr(xdr, OP_REMOVEXATTR);
1271	if (status)
1272		goto out;
1273
1274	status = decode_change_info(xdr, cinfo);
1275out:
1276	return status;
1277}
1278
1279static int decode_listxattrs(struct xdr_stream *xdr,
1280			    struct nfs42_listxattrsres *res)
1281{
1282	int status;
1283	__be32 *p;
1284	u32 count, len, ulen;
1285	size_t left, copied;
1286	char *buf;
1287
1288	status = decode_op_hdr(xdr, OP_LISTXATTRS);
1289	if (status) {
1290		/*
1291		 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
1292		 * should be translated to ERANGE.
1293		 */
1294		if (status == -ETOOSMALL)
1295			status = -ERANGE;
1296		/*
1297		 * Special case: for LISTXATTRS, NFS4ERR_NOXATTR
1298		 * should be translated to success with zero-length reply.
1299		 */
1300		if (status == -ENODATA) {
1301			res->eof = true;
1302			status = 0;
1303		}
1304		goto out;
1305	}
1306
1307	p = xdr_inline_decode(xdr, 8);
1308	if (unlikely(!p))
1309		return -EIO;
1310
1311	xdr_decode_hyper(p, &res->cookie);
1312
1313	p = xdr_inline_decode(xdr, 4);
1314	if (unlikely(!p))
1315		return -EIO;
1316
1317	left = res->xattr_len;
1318	buf = res->xattr_buf;
1319
1320	count = be32_to_cpup(p);
1321	copied = 0;
1322
1323	/*
1324	 * We have asked for enough room to encode the maximum number
1325	 * of possible attribute names, so everything should fit.
1326	 *
1327	 * But, don't rely on that assumption. Just decode entries
1328	 * until they don't fit anymore, just in case the server did
1329	 * something odd.
1330	 */
1331	while (count--) {
1332		p = xdr_inline_decode(xdr, 4);
1333		if (unlikely(!p))
1334			return -EIO;
1335
1336		len = be32_to_cpup(p);
1337		if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
1338			status = -ERANGE;
1339			goto out;
1340		}
1341
1342		p = xdr_inline_decode(xdr, len);
1343		if (unlikely(!p))
1344			return -EIO;
1345
1346		ulen = len + XATTR_USER_PREFIX_LEN + 1;
1347		if (buf) {
1348			if (ulen > left) {
1349				status = -ERANGE;
1350				goto out;
1351			}
1352
1353			memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
1354			memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
1355
1356			buf[ulen - 1] = 0;
1357			buf += ulen;
1358			left -= ulen;
1359		}
1360		copied += ulen;
1361	}
1362
1363	p = xdr_inline_decode(xdr, 4);
1364	if (unlikely(!p))
1365		return -EIO;
1366
1367	res->eof = be32_to_cpup(p);
1368	res->copied = copied;
1369
1370out:
1371	if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
1372		status = -E2BIG;
1373
1374	return status;
1375}
1376
1377/*
1378 * Decode ALLOCATE request
1379 */
1380static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
1381				 struct xdr_stream *xdr,
1382				 void *data)
1383{
1384	struct nfs42_falloc_res *res = data;
1385	struct compound_hdr hdr;
1386	int status;
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	status = decode_allocate(xdr, res);
1398	if (status)
1399		goto out;
1400	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1401out:
1402	return status;
1403}
1404
1405/*
1406 * Decode COPY response
1407 */
1408static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
1409			     struct xdr_stream *xdr,
1410			     void *data)
1411{
1412	struct nfs42_copy_res *res = data;
1413	struct compound_hdr hdr;
1414	int status;
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	if (status)
1424		goto out;
1425	status = decode_savefh(xdr);
1426	if (status)
1427		goto out;
1428	status = decode_putfh(xdr);
1429	if (status)
1430		goto out;
1431	status = decode_copy(xdr, res);
1432	if (status)
1433		goto out;
1434	if (res->commit_res.verf)
1435		status = decode_commit(xdr, &res->commit_res);
1436out:
1437	return status;
1438}
1439
1440/*
1441 * Decode OFFLOAD_CANCEL response
1442 */
1443static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
1444				       struct xdr_stream *xdr,
1445				       void *data)
1446{
1447	struct nfs42_offload_status_res *res = data;
1448	struct compound_hdr hdr;
1449	int status;
1450
1451	status = decode_compound_hdr(xdr, &hdr);
1452	if (status)
1453		goto out;
1454	status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
1455	if (status)
1456		goto out;
1457	status = decode_putfh(xdr);
1458	if (status)
1459		goto out;
1460	status = decode_offload_cancel(xdr, res);
1461
1462out:
1463	return status;
1464}
1465
1466/*
1467 * Decode OFFLOAD_STATUS response
1468 */
1469static int nfs4_xdr_dec_offload_status(struct rpc_rqst *rqstp,
1470				       struct xdr_stream *xdr,
1471				       void *data)
1472{
1473	struct nfs42_offload_status_res *res = data;
1474	struct compound_hdr hdr;
1475	int status;
1476
1477	status = decode_compound_hdr(xdr, &hdr);
1478	if (status)
1479		goto out;
1480	status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
1481	if (status)
1482		goto out;
1483	status = decode_putfh(xdr);
1484	if (status)
1485		goto out;
1486	status = decode_offload_status(xdr, res);
1487
1488out:
1489	return status;
1490}
1491
1492/*
1493 * Decode COPY_NOTIFY response
1494 */
1495static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
1496				    struct xdr_stream *xdr,
1497				    void *data)
1498{
1499	struct nfs42_copy_notify_res *res = data;
1500	struct compound_hdr hdr;
1501	int status;
1502
1503	status = decode_compound_hdr(xdr, &hdr);
1504	if (status)
1505		goto out;
1506	status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
1507	if (status)
1508		goto out;
1509	status = decode_putfh(xdr);
1510	if (status)
1511		goto out;
1512	status = decode_copy_notify(xdr, res);
1513
1514out:
1515	return status;
1516}
1517
1518/*
1519 * Decode DEALLOCATE request
1520 */
1521static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
1522				   struct xdr_stream *xdr,
1523				   void *data)
1524{
1525	struct nfs42_falloc_res *res = data;
1526	struct compound_hdr hdr;
1527	int status;
1528
1529	status = decode_compound_hdr(xdr, &hdr);
1530	if (status)
1531		goto out;
1532	status = decode_sequence(xdr, &res->seq_res, rqstp);
1533	if (status)
1534		goto out;
1535	status = decode_putfh(xdr);
1536	if (status)
1537		goto out;
1538	status = decode_deallocate(xdr, res);
1539	if (status)
1540		goto out;
1541	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1542out:
1543	return status;
1544}
1545
1546/*
1547 * Decode ZERO_RANGE request
1548 */
1549static int nfs4_xdr_dec_zero_range(struct rpc_rqst *rqstp,
1550				   struct xdr_stream *xdr,
1551				   void *data)
1552{
1553	struct nfs42_falloc_res *res = data;
1554	struct compound_hdr hdr;
1555	int status;
1556
1557	status = decode_compound_hdr(xdr, &hdr);
1558	if (status)
1559		goto out;
1560	status = decode_sequence(xdr, &res->seq_res, rqstp);
1561	if (status)
1562		goto out;
1563	status = decode_putfh(xdr);
1564	if (status)
1565		goto out;
1566	status = decode_deallocate(xdr, res);
1567	if (status)
1568		goto out;
1569	status = decode_allocate(xdr, res);
1570	if (status)
1571		goto out;
1572	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1573out:
1574	return status;
1575}
1576
1577/*
1578 * Decode READ_PLUS request
1579 */
1580static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
1581				  struct xdr_stream *xdr,
1582				  void *data)
1583{
1584	struct nfs_pgio_res *res = data;
1585	struct compound_hdr hdr;
1586	int status;
1587
1588	xdr_set_scratch_buffer(xdr, res->scratch, READ_PLUS_SCRATCH_SIZE);
1589
1590	status = decode_compound_hdr(xdr, &hdr);
1591	if (status)
1592		goto out;
1593	status = decode_sequence(xdr, &res->seq_res, rqstp);
1594	if (status)
1595		goto out;
1596	status = decode_putfh(xdr);
1597	if (status)
1598		goto out;
1599	status = decode_read_plus(xdr, res);
1600	if (!status)
1601		status = res->count;
1602out:
1603	return status;
1604}
1605
1606/*
1607 * Decode SEEK request
1608 */
1609static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
1610			     struct xdr_stream *xdr,
1611			     void *data)
1612{
1613	struct nfs42_seek_res *res = data;
1614	struct compound_hdr hdr;
1615	int status;
1616
1617	status = decode_compound_hdr(xdr, &hdr);
1618	if (status)
1619		goto out;
1620	status = decode_sequence(xdr, &res->seq_res, rqstp);
1621	if (status)
1622		goto out;
1623	status = decode_putfh(xdr);
1624	if (status)
1625		goto out;
1626	status = decode_seek(xdr, res);
1627out:
1628	return status;
1629}
1630
1631/*
1632 * Decode LAYOUTSTATS request
1633 */
1634static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
1635				    struct xdr_stream *xdr,
1636				    void *data)
1637{
1638	struct nfs42_layoutstat_res *res = data;
1639	struct compound_hdr hdr;
1640	int status, i;
1641
1642	status = decode_compound_hdr(xdr, &hdr);
1643	if (status)
1644		goto out;
1645	status = decode_sequence(xdr, &res->seq_res, rqstp);
1646	if (status)
1647		goto out;
1648	status = decode_putfh(xdr);
1649	if (status)
1650		goto out;
1651	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
1652	for (i = 0; i < res->num_dev; i++) {
1653		status = decode_layoutstats(xdr);
1654		if (status)
1655			goto out;
1656	}
1657out:
1658	res->rpc_status = status;
1659	return status;
1660}
1661
1662/*
1663 * Decode CLONE request
1664 */
1665static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
1666			      struct xdr_stream *xdr,
1667			      void *data)
1668{
1669	struct nfs42_clone_res *res = data;
1670	struct compound_hdr hdr;
1671	int status;
1672
1673	status = decode_compound_hdr(xdr, &hdr);
1674	if (status)
1675		goto out;
1676	status = decode_sequence(xdr, &res->seq_res, rqstp);
1677	if (status)
1678		goto out;
1679	status = decode_putfh(xdr);
1680	if (status)
1681		goto out;
1682	status = decode_savefh(xdr);
1683	if (status)
1684		goto out;
1685	status = decode_putfh(xdr);
1686	if (status)
1687		goto out;
1688	status = decode_clone(xdr);
1689	if (status)
1690		goto out;
1691	decode_getfattr(xdr, res->dst_fattr, res->server);
1692out:
1693	res->rpc_status = status;
1694	return status;
1695}
1696
1697/*
1698 * Decode LAYOUTERROR request
1699 */
1700static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
1701				    struct xdr_stream *xdr,
1702				    void *data)
1703{
1704	struct nfs42_layouterror_res *res = data;
1705	struct compound_hdr hdr;
1706	int status, i;
1707
1708	status = decode_compound_hdr(xdr, &hdr);
1709	if (status)
1710		goto out;
1711	status = decode_sequence(xdr, &res->seq_res, rqstp);
1712	if (status)
1713		goto out;
1714	status = decode_putfh(xdr);
1715
1716	for (i = 0; i < res->num_errors && status == 0; i++)
1717		status = decode_layouterror(xdr);
1718out:
1719	res->rpc_status = status;
1720	return status;
1721}
1722
1723/*
1724 * Decode SETXATTR request
1725 */
1726static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1727				 void *data)
1728{
1729	struct nfs42_setxattrres *res = data;
1730	struct compound_hdr hdr;
1731	int status;
1732
1733	status = decode_compound_hdr(xdr, &hdr);
1734	if (status)
1735		goto out;
1736	status = decode_sequence(xdr, &res->seq_res, req);
1737	if (status)
1738		goto out;
1739	status = decode_putfh(xdr);
1740	if (status)
1741		goto out;
1742	status = decode_setxattr(xdr, &res->cinfo);
1743	if (status)
1744		goto out;
1745	status = decode_getfattr(xdr, res->fattr, res->server);
1746out:
1747	return status;
1748}
1749
1750/*
1751 * Decode GETXATTR request
1752 */
1753static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1754				 struct xdr_stream *xdr, void *data)
1755{
1756	struct nfs42_getxattrres *res = data;
1757	struct compound_hdr hdr;
1758	int status;
1759
1760	status = decode_compound_hdr(xdr, &hdr);
1761	if (status)
1762		goto out;
1763	status = decode_sequence(xdr, &res->seq_res, rqstp);
1764	if (status)
1765		goto out;
1766	status = decode_putfh(xdr);
1767	if (status)
1768		goto out;
1769	status = decode_getxattr(xdr, res, rqstp);
1770out:
1771	return status;
1772}
1773
1774/*
1775 * Decode LISTXATTR request
1776 */
1777static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1778				   struct xdr_stream *xdr, void *data)
1779{
1780	struct nfs42_listxattrsres *res = data;
1781	struct compound_hdr hdr;
1782	int status;
1783
1784	xdr_set_scratch_folio(xdr, res->scratch);
1785
1786	status = decode_compound_hdr(xdr, &hdr);
1787	if (status)
1788		goto out;
1789	status = decode_sequence(xdr, &res->seq_res, rqstp);
1790	if (status)
1791		goto out;
1792	status = decode_putfh(xdr);
1793	if (status)
1794		goto out;
1795	status = decode_listxattrs(xdr, res);
1796out:
1797	return status;
1798}
1799
1800/*
1801 * Decode REMOVEXATTR request
1802 */
1803static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1804				    struct xdr_stream *xdr, void *data)
1805{
1806	struct nfs42_removexattrres *res = data;
1807	struct compound_hdr hdr;
1808	int status;
1809
1810	status = decode_compound_hdr(xdr, &hdr);
1811	if (status)
1812		goto out;
1813	status = decode_sequence(xdr, &res->seq_res, req);
1814	if (status)
1815		goto out;
1816	status = decode_putfh(xdr);
1817	if (status)
1818		goto out;
1819
1820	status = decode_removexattr(xdr, &res->cinfo);
1821out:
1822	return status;
1823}
1824#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
~/ Read-only file preview.