linux/fs/nfs/nfs42xdr.c
<<
>>
Prefs
   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        status = decode_getfattr(xdr, res->dst_fattr, res->server);
1438
1439out:
1440        res->rpc_status = status;
1441        return status;
1442}
1443
1444/*
1445 * Decode LAYOUTERROR request
1446 */
1447static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
1448                                    struct xdr_stream *xdr,
1449                                    void *data)
1450{
1451        struct nfs42_layouterror_res *res = data;
1452        struct compound_hdr hdr;
1453        int status, i;
1454
1455        status = decode_compound_hdr(xdr, &hdr);
1456        if (status)
1457                goto out;
1458        status = decode_sequence(xdr, &res->seq_res, rqstp);
1459        if (status)
1460                goto out;
1461        status = decode_putfh(xdr);
1462
1463        for (i = 0; i < res->num_errors && status == 0; i++)
1464                status = decode_layouterror(xdr);
1465out:
1466        res->rpc_status = status;
1467        return status;
1468}
1469
1470#ifdef CONFIG_NFS_V4_2
1471static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1472                                  const void *data)
1473{
1474        const struct nfs42_setxattrargs *args = data;
1475        struct compound_hdr hdr = {
1476                .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1477        };
1478
1479        encode_compound_hdr(xdr, req, &hdr);
1480        encode_sequence(xdr, &args->seq_args, &hdr);
1481        encode_putfh(xdr, args->fh, &hdr);
1482        encode_setxattr(xdr, args, &hdr);
1483        encode_nops(&hdr);
1484}
1485
1486static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1487                                 void *data)
1488{
1489        struct nfs42_setxattrres *res = data;
1490        struct compound_hdr hdr;
1491        int status;
1492
1493        status = decode_compound_hdr(xdr, &hdr);
1494        if (status)
1495                goto out;
1496        status = decode_sequence(xdr, &res->seq_res, req);
1497        if (status)
1498                goto out;
1499        status = decode_putfh(xdr);
1500        if (status)
1501                goto out;
1502
1503        status = decode_setxattr(xdr, &res->cinfo);
1504out:
1505        return status;
1506}
1507
1508static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1509                                  const void *data)
1510{
1511        const struct nfs42_getxattrargs *args = data;
1512        struct compound_hdr hdr = {
1513                .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1514        };
1515        uint32_t replen;
1516
1517        encode_compound_hdr(xdr, req, &hdr);
1518        encode_sequence(xdr, &args->seq_args, &hdr);
1519        encode_putfh(xdr, args->fh, &hdr);
1520        replen = hdr.replen + op_decode_hdr_maxsz + 1;
1521        encode_getxattr(xdr, args->xattr_name, &hdr);
1522
1523        rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->xattr_len,
1524                                replen);
1525
1526        encode_nops(&hdr);
1527}
1528
1529static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1530                                 struct xdr_stream *xdr, void *data)
1531{
1532        struct nfs42_getxattrres *res = data;
1533        struct compound_hdr hdr;
1534        int status;
1535
1536        status = decode_compound_hdr(xdr, &hdr);
1537        if (status)
1538                goto out;
1539        status = decode_sequence(xdr, &res->seq_res, rqstp);
1540        if (status)
1541                goto out;
1542        status = decode_putfh(xdr);
1543        if (status)
1544                goto out;
1545        status = decode_getxattr(xdr, res, rqstp);
1546out:
1547        return status;
1548}
1549
1550static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
1551                                    struct xdr_stream *xdr, const void *data)
1552{
1553        const struct nfs42_listxattrsargs *args = data;
1554        struct compound_hdr hdr = {
1555                .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1556        };
1557        uint32_t replen;
1558
1559        encode_compound_hdr(xdr, req, &hdr);
1560        encode_sequence(xdr, &args->seq_args, &hdr);
1561        encode_putfh(xdr, args->fh, &hdr);
1562        replen = hdr.replen + op_decode_hdr_maxsz + 2 + 1;
1563        encode_listxattrs(xdr, args, &hdr);
1564
1565        rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count, replen);
1566
1567        encode_nops(&hdr);
1568}
1569
1570static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1571                                   struct xdr_stream *xdr, void *data)
1572{
1573        struct nfs42_listxattrsres *res = data;
1574        struct compound_hdr hdr;
1575        int status;
1576
1577        xdr_set_scratch_page(xdr, res->scratch);
1578
1579        status = decode_compound_hdr(xdr, &hdr);
1580        if (status)
1581                goto out;
1582        status = decode_sequence(xdr, &res->seq_res, rqstp);
1583        if (status)
1584                goto out;
1585        status = decode_putfh(xdr);
1586        if (status)
1587                goto out;
1588        status = decode_listxattrs(xdr, res);
1589out:
1590        return status;
1591}
1592
1593static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
1594                                     struct xdr_stream *xdr, const void *data)
1595{
1596        const struct nfs42_removexattrargs *args = data;
1597        struct compound_hdr hdr = {
1598                .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1599        };
1600
1601        encode_compound_hdr(xdr, req, &hdr);
1602        encode_sequence(xdr, &args->seq_args, &hdr);
1603        encode_putfh(xdr, args->fh, &hdr);
1604        encode_removexattr(xdr, args->xattr_name, &hdr);
1605        encode_nops(&hdr);
1606}
1607
1608static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1609                                    struct xdr_stream *xdr, void *data)
1610{
1611        struct nfs42_removexattrres *res = data;
1612        struct compound_hdr hdr;
1613        int status;
1614
1615        status = decode_compound_hdr(xdr, &hdr);
1616        if (status)
1617                goto out;
1618        status = decode_sequence(xdr, &res->seq_res, req);
1619        if (status)
1620                goto out;
1621        status = decode_putfh(xdr);
1622        if (status)
1623                goto out;
1624
1625        status = decode_removexattr(xdr, &res->cinfo);
1626out:
1627        return status;
1628}
1629#endif
1630#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
1631