linux/fs/nfs/nfs3xdr.c
<<
>>
Prefs
   1/*
   2 * linux/fs/nfs/nfs3xdr.c
   3 *
   4 * XDR functions to encode/decode NFSv3 RPC arguments and results.
   5 *
   6 * Copyright (C) 1996, 1997 Olaf Kirch
   7 */
   8
   9#include <linux/param.h>
  10#include <linux/time.h>
  11#include <linux/mm.h>
  12#include <linux/errno.h>
  13#include <linux/string.h>
  14#include <linux/in.h>
  15#include <linux/pagemap.h>
  16#include <linux/proc_fs.h>
  17#include <linux/kdev_t.h>
  18#include <linux/sunrpc/clnt.h>
  19#include <linux/nfs.h>
  20#include <linux/nfs3.h>
  21#include <linux/nfs_fs.h>
  22#include <linux/nfsacl.h>
  23#include "internal.h"
  24
  25#define NFSDBG_FACILITY         NFSDBG_XDR
  26
  27/* Mapping from NFS error code to "errno" error code. */
  28#define errno_NFSERR_IO         EIO
  29
  30/*
  31 * Declare the space requirements for NFS arguments and replies as
  32 * number of 32bit-words
  33 */
  34#define NFS3_fhandle_sz         (1+16)
  35#define NFS3_fh_sz              (NFS3_fhandle_sz)       /* shorthand */
  36#define NFS3_sattr_sz           (15)
  37#define NFS3_filename_sz        (1+(NFS3_MAXNAMLEN>>2))
  38#define NFS3_path_sz            (1+(NFS3_MAXPATHLEN>>2))
  39#define NFS3_fattr_sz           (21)
  40#define NFS3_cookieverf_sz      (NFS3_COOKIEVERFSIZE>>2)
  41#define NFS3_wcc_attr_sz        (6)
  42#define NFS3_pre_op_attr_sz     (1+NFS3_wcc_attr_sz)
  43#define NFS3_post_op_attr_sz    (1+NFS3_fattr_sz)
  44#define NFS3_wcc_data_sz        (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
  45#define NFS3_diropargs_sz       (NFS3_fh_sz+NFS3_filename_sz)
  46
  47#define NFS3_getattrargs_sz     (NFS3_fh_sz)
  48#define NFS3_setattrargs_sz     (NFS3_fh_sz+NFS3_sattr_sz+3)
  49#define NFS3_lookupargs_sz      (NFS3_fh_sz+NFS3_filename_sz)
  50#define NFS3_accessargs_sz      (NFS3_fh_sz+1)
  51#define NFS3_readlinkargs_sz    (NFS3_fh_sz)
  52#define NFS3_readargs_sz        (NFS3_fh_sz+3)
  53#define NFS3_writeargs_sz       (NFS3_fh_sz+5)
  54#define NFS3_createargs_sz      (NFS3_diropargs_sz+NFS3_sattr_sz)
  55#define NFS3_mkdirargs_sz       (NFS3_diropargs_sz+NFS3_sattr_sz)
  56#define NFS3_symlinkargs_sz     (NFS3_diropargs_sz+1+NFS3_sattr_sz)
  57#define NFS3_mknodargs_sz       (NFS3_diropargs_sz+2+NFS3_sattr_sz)
  58#define NFS3_removeargs_sz      (NFS3_fh_sz+NFS3_filename_sz)
  59#define NFS3_renameargs_sz      (NFS3_diropargs_sz+NFS3_diropargs_sz)
  60#define NFS3_linkargs_sz                (NFS3_fh_sz+NFS3_diropargs_sz)
  61#define NFS3_readdirargs_sz     (NFS3_fh_sz+NFS3_cookieverf_sz+3)
  62#define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
  63#define NFS3_commitargs_sz      (NFS3_fh_sz+3)
  64
  65#define NFS3_getattrres_sz      (1+NFS3_fattr_sz)
  66#define NFS3_setattrres_sz      (1+NFS3_wcc_data_sz)
  67#define NFS3_removeres_sz       (NFS3_setattrres_sz)
  68#define NFS3_lookupres_sz       (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
  69#define NFS3_accessres_sz       (1+NFS3_post_op_attr_sz+1)
  70#define NFS3_readlinkres_sz     (1+NFS3_post_op_attr_sz+1)
  71#define NFS3_readres_sz         (1+NFS3_post_op_attr_sz+3)
  72#define NFS3_writeres_sz        (1+NFS3_wcc_data_sz+4)
  73#define NFS3_createres_sz       (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
  74#define NFS3_renameres_sz       (1+(2 * NFS3_wcc_data_sz))
  75#define NFS3_linkres_sz         (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
  76#define NFS3_readdirres_sz      (1+NFS3_post_op_attr_sz+2)
  77#define NFS3_fsstatres_sz       (1+NFS3_post_op_attr_sz+13)
  78#define NFS3_fsinfores_sz       (1+NFS3_post_op_attr_sz+12)
  79#define NFS3_pathconfres_sz     (1+NFS3_post_op_attr_sz+6)
  80#define NFS3_commitres_sz       (1+NFS3_wcc_data_sz+2)
  81
  82#define ACL3_getaclargs_sz      (NFS3_fh_sz+1)
  83#define ACL3_setaclargs_sz      (NFS3_fh_sz+1+ \
  84                                XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
  85#define ACL3_getaclres_sz       (1+NFS3_post_op_attr_sz+1+ \
  86                                XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
  87#define ACL3_setaclres_sz       (1+NFS3_post_op_attr_sz)
  88
  89static int nfs3_stat_to_errno(enum nfs_stat);
  90
  91/*
  92 * Map file type to S_IFMT bits
  93 */
  94static const umode_t nfs_type2fmt[] = {
  95        [NF3BAD] = 0,
  96        [NF3REG] = S_IFREG,
  97        [NF3DIR] = S_IFDIR,
  98        [NF3BLK] = S_IFBLK,
  99        [NF3CHR] = S_IFCHR,
 100        [NF3LNK] = S_IFLNK,
 101        [NF3SOCK] = S_IFSOCK,
 102        [NF3FIFO] = S_IFIFO,
 103};
 104
 105/*
 106 * While encoding arguments, set up the reply buffer in advance to
 107 * receive reply data directly into the page cache.
 108 */
 109static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
 110                                 unsigned int base, unsigned int len,
 111                                 unsigned int bufsize)
 112{
 113        struct rpc_auth *auth = req->rq_cred->cr_auth;
 114        unsigned int replen;
 115
 116        replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
 117        xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
 118}
 119
 120/*
 121 * Handle decode buffer overflows out-of-line.
 122 */
 123static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
 124{
 125        dprintk("NFS: %s prematurely hit the end of our receive buffer. "
 126                "Remaining buffer length is %tu words.\n",
 127                func, xdr->end - xdr->p);
 128}
 129
 130
 131/*
 132 * Encode/decode NFSv3 basic data types
 133 *
 134 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
 135 * "NFS Version 3 Protocol Specification".
 136 *
 137 * Not all basic data types have their own encoding and decoding
 138 * functions.  For run-time efficiency, some data types are encoded
 139 * or decoded inline.
 140 */
 141
 142static void encode_uint32(struct xdr_stream *xdr, u32 value)
 143{
 144        __be32 *p = xdr_reserve_space(xdr, 4);
 145        *p = cpu_to_be32(value);
 146}
 147
 148static int decode_uint32(struct xdr_stream *xdr, u32 *value)
 149{
 150        __be32 *p;
 151
 152        p = xdr_inline_decode(xdr, 4);
 153        if (unlikely(p == NULL))
 154                goto out_overflow;
 155        *value = be32_to_cpup(p);
 156        return 0;
 157out_overflow:
 158        print_overflow_msg(__func__, xdr);
 159        return -EIO;
 160}
 161
 162static int decode_uint64(struct xdr_stream *xdr, u64 *value)
 163{
 164        __be32 *p;
 165
 166        p = xdr_inline_decode(xdr, 8);
 167        if (unlikely(p == NULL))
 168                goto out_overflow;
 169        xdr_decode_hyper(p, value);
 170        return 0;
 171out_overflow:
 172        print_overflow_msg(__func__, xdr);
 173        return -EIO;
 174}
 175
 176/*
 177 * fileid3
 178 *
 179 *      typedef uint64 fileid3;
 180 */
 181static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid)
 182{
 183        return xdr_decode_hyper(p, fileid);
 184}
 185
 186static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
 187{
 188        return decode_uint64(xdr, fileid);
 189}
 190
 191/*
 192 * filename3
 193 *
 194 *      typedef string filename3<>;
 195 */
 196static void encode_filename3(struct xdr_stream *xdr,
 197                             const char *name, u32 length)
 198{
 199        __be32 *p;
 200
 201        BUG_ON(length > NFS3_MAXNAMLEN);
 202        p = xdr_reserve_space(xdr, 4 + length);
 203        xdr_encode_opaque(p, name, length);
 204}
 205
 206static int decode_inline_filename3(struct xdr_stream *xdr,
 207                                   const char **name, u32 *length)
 208{
 209        __be32 *p;
 210        u32 count;
 211
 212        p = xdr_inline_decode(xdr, 4);
 213        if (unlikely(p == NULL))
 214                goto out_overflow;
 215        count = be32_to_cpup(p);
 216        if (count > NFS3_MAXNAMLEN)
 217                goto out_nametoolong;
 218        p = xdr_inline_decode(xdr, count);
 219        if (unlikely(p == NULL))
 220                goto out_overflow;
 221        *name = (const char *)p;
 222        *length = count;
 223        return 0;
 224
 225out_nametoolong:
 226        dprintk("NFS: returned filename too long: %u\n", count);
 227        return -ENAMETOOLONG;
 228out_overflow:
 229        print_overflow_msg(__func__, xdr);
 230        return -EIO;
 231}
 232
 233/*
 234 * nfspath3
 235 *
 236 *      typedef string nfspath3<>;
 237 */
 238static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
 239                            const u32 length)
 240{
 241        BUG_ON(length > NFS3_MAXPATHLEN);
 242        encode_uint32(xdr, length);
 243        xdr_write_pages(xdr, pages, 0, length);
 244}
 245
 246static int decode_nfspath3(struct xdr_stream *xdr)
 247{
 248        u32 recvd, count;
 249        __be32 *p;
 250
 251        p = xdr_inline_decode(xdr, 4);
 252        if (unlikely(p == NULL))
 253                goto out_overflow;
 254        count = be32_to_cpup(p);
 255        if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
 256                goto out_nametoolong;
 257        recvd = xdr_read_pages(xdr, count);
 258        if (unlikely(count > recvd))
 259                goto out_cheating;
 260        xdr_terminate_string(xdr->buf, count);
 261        return 0;
 262
 263out_nametoolong:
 264        dprintk("NFS: returned pathname too long: %u\n", count);
 265        return -ENAMETOOLONG;
 266out_cheating:
 267        dprintk("NFS: server cheating in pathname result: "
 268                "count %u > recvd %u\n", count, recvd);
 269        return -EIO;
 270out_overflow:
 271        print_overflow_msg(__func__, xdr);
 272        return -EIO;
 273}
 274
 275/*
 276 * cookie3
 277 *
 278 *      typedef uint64 cookie3
 279 */
 280static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
 281{
 282        return xdr_encode_hyper(p, cookie);
 283}
 284
 285static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
 286{
 287        return decode_uint64(xdr, cookie);
 288}
 289
 290/*
 291 * cookieverf3
 292 *
 293 *      typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
 294 */
 295static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
 296{
 297        memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
 298        return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
 299}
 300
 301static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
 302{
 303        __be32 *p;
 304
 305        p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 306        if (unlikely(p == NULL))
 307                goto out_overflow;
 308        memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
 309        return 0;
 310out_overflow:
 311        print_overflow_msg(__func__, xdr);
 312        return -EIO;
 313}
 314
 315/*
 316 * createverf3
 317 *
 318 *      typedef opaque createverf3[NFS3_CREATEVERFSIZE];
 319 */
 320static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
 321{
 322        __be32 *p;
 323
 324        p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
 325        memcpy(p, verifier, NFS3_CREATEVERFSIZE);
 326}
 327
 328static int decode_writeverf3(struct xdr_stream *xdr, struct nfs_write_verifier *verifier)
 329{
 330        __be32 *p;
 331
 332        p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
 333        if (unlikely(p == NULL))
 334                goto out_overflow;
 335        memcpy(verifier->data, p, NFS3_WRITEVERFSIZE);
 336        return 0;
 337out_overflow:
 338        print_overflow_msg(__func__, xdr);
 339        return -EIO;
 340}
 341
 342/*
 343 * size3
 344 *
 345 *      typedef uint64 size3;
 346 */
 347static __be32 *xdr_decode_size3(__be32 *p, u64 *size)
 348{
 349        return xdr_decode_hyper(p, size);
 350}
 351
 352/*
 353 * nfsstat3
 354 *
 355 *      enum nfsstat3 {
 356 *              NFS3_OK = 0,
 357 *              ...
 358 *      }
 359 */
 360#define NFS3_OK         NFS_OK
 361
 362static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
 363{
 364        __be32 *p;
 365
 366        p = xdr_inline_decode(xdr, 4);
 367        if (unlikely(p == NULL))
 368                goto out_overflow;
 369        *status = be32_to_cpup(p);
 370        return 0;
 371out_overflow:
 372        print_overflow_msg(__func__, xdr);
 373        return -EIO;
 374}
 375
 376/*
 377 * ftype3
 378 *
 379 *      enum ftype3 {
 380 *              NF3REG  = 1,
 381 *              NF3DIR  = 2,
 382 *              NF3BLK  = 3,
 383 *              NF3CHR  = 4,
 384 *              NF3LNK  = 5,
 385 *              NF3SOCK = 6,
 386 *              NF3FIFO = 7
 387 *      };
 388 */
 389static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
 390{
 391        BUG_ON(type > NF3FIFO);
 392        encode_uint32(xdr, type);
 393}
 394
 395static __be32 *xdr_decode_ftype3(__be32 *p, umode_t *mode)
 396{
 397        u32 type;
 398
 399        type = be32_to_cpup(p++);
 400        if (type > NF3FIFO)
 401                type = NF3NON;
 402        *mode = nfs_type2fmt[type];
 403        return p;
 404}
 405
 406/*
 407 * specdata3
 408 *
 409 *     struct specdata3 {
 410 *             uint32  specdata1;
 411 *             uint32  specdata2;
 412 *     };
 413 */
 414static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
 415{
 416        __be32 *p;
 417
 418        p = xdr_reserve_space(xdr, 8);
 419        *p++ = cpu_to_be32(MAJOR(rdev));
 420        *p = cpu_to_be32(MINOR(rdev));
 421}
 422
 423static __be32 *xdr_decode_specdata3(__be32 *p, dev_t *rdev)
 424{
 425        unsigned int major, minor;
 426
 427        major = be32_to_cpup(p++);
 428        minor = be32_to_cpup(p++);
 429        *rdev = MKDEV(major, minor);
 430        if (MAJOR(*rdev) != major || MINOR(*rdev) != minor)
 431                *rdev = 0;
 432        return p;
 433}
 434
 435/*
 436 * nfs_fh3
 437 *
 438 *      struct nfs_fh3 {
 439 *              opaque       data<NFS3_FHSIZE>;
 440 *      };
 441 */
 442static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
 443{
 444        __be32 *p;
 445
 446        BUG_ON(fh->size > NFS3_FHSIZE);
 447        p = xdr_reserve_space(xdr, 4 + fh->size);
 448        xdr_encode_opaque(p, fh->data, fh->size);
 449}
 450
 451static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
 452{
 453        u32 length;
 454        __be32 *p;
 455
 456        p = xdr_inline_decode(xdr, 4);
 457        if (unlikely(p == NULL))
 458                goto out_overflow;
 459        length = be32_to_cpup(p++);
 460        if (unlikely(length > NFS3_FHSIZE))
 461                goto out_toobig;
 462        p = xdr_inline_decode(xdr, length);
 463        if (unlikely(p == NULL))
 464                goto out_overflow;
 465        fh->size = length;
 466        memcpy(fh->data, p, length);
 467        return 0;
 468out_toobig:
 469        dprintk("NFS: file handle size (%u) too big\n", length);
 470        return -E2BIG;
 471out_overflow:
 472        print_overflow_msg(__func__, xdr);
 473        return -EIO;
 474}
 475
 476static void zero_nfs_fh3(struct nfs_fh *fh)
 477{
 478        memset(fh, 0, sizeof(*fh));
 479}
 480
 481/*
 482 * nfstime3
 483 *
 484 *      struct nfstime3 {
 485 *              uint32  seconds;
 486 *              uint32  nseconds;
 487 *      };
 488 */
 489static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep)
 490{
 491        *p++ = cpu_to_be32(timep->tv_sec);
 492        *p++ = cpu_to_be32(timep->tv_nsec);
 493        return p;
 494}
 495
 496static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep)
 497{
 498        timep->tv_sec = be32_to_cpup(p++);
 499        timep->tv_nsec = be32_to_cpup(p++);
 500        return p;
 501}
 502
 503/*
 504 * sattr3
 505 *
 506 *      enum time_how {
 507 *              DONT_CHANGE             = 0,
 508 *              SET_TO_SERVER_TIME      = 1,
 509 *              SET_TO_CLIENT_TIME      = 2
 510 *      };
 511 *
 512 *      union set_mode3 switch (bool set_it) {
 513 *      case TRUE:
 514 *              mode3   mode;
 515 *      default:
 516 *              void;
 517 *      };
 518 *
 519 *      union set_uid3 switch (bool set_it) {
 520 *      case TRUE:
 521 *              uid3    uid;
 522 *      default:
 523 *              void;
 524 *      };
 525 *
 526 *      union set_gid3 switch (bool set_it) {
 527 *      case TRUE:
 528 *              gid3    gid;
 529 *      default:
 530 *              void;
 531 *      };
 532 *
 533 *      union set_size3 switch (bool set_it) {
 534 *      case TRUE:
 535 *              size3   size;
 536 *      default:
 537 *              void;
 538 *      };
 539 *
 540 *      union set_atime switch (time_how set_it) {
 541 *      case SET_TO_CLIENT_TIME:
 542 *              nfstime3        atime;
 543 *      default:
 544 *              void;
 545 *      };
 546 *
 547 *      union set_mtime switch (time_how set_it) {
 548 *      case SET_TO_CLIENT_TIME:
 549 *              nfstime3  mtime;
 550 *      default:
 551 *              void;
 552 *      };
 553 *
 554 *      struct sattr3 {
 555 *              set_mode3       mode;
 556 *              set_uid3        uid;
 557 *              set_gid3        gid;
 558 *              set_size3       size;
 559 *              set_atime       atime;
 560 *              set_mtime       mtime;
 561 *      };
 562 */
 563static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
 564{
 565        u32 nbytes;
 566        __be32 *p;
 567
 568        /*
 569         * In order to make only a single xdr_reserve_space() call,
 570         * pre-compute the total number of bytes to be reserved.
 571         * Six boolean values, one for each set_foo field, are always
 572         * present in the encoded result, so start there.
 573         */
 574        nbytes = 6 * 4;
 575        if (attr->ia_valid & ATTR_MODE)
 576                nbytes += 4;
 577        if (attr->ia_valid & ATTR_UID)
 578                nbytes += 4;
 579        if (attr->ia_valid & ATTR_GID)
 580                nbytes += 4;
 581        if (attr->ia_valid & ATTR_SIZE)
 582                nbytes += 8;
 583        if (attr->ia_valid & ATTR_ATIME_SET)
 584                nbytes += 8;
 585        if (attr->ia_valid & ATTR_MTIME_SET)
 586                nbytes += 8;
 587        p = xdr_reserve_space(xdr, nbytes);
 588
 589        if (attr->ia_valid & ATTR_MODE) {
 590                *p++ = xdr_one;
 591                *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO);
 592        } else
 593                *p++ = xdr_zero;
 594
 595        if (attr->ia_valid & ATTR_UID) {
 596                *p++ = xdr_one;
 597                *p++ = cpu_to_be32(attr->ia_uid);
 598        } else
 599                *p++ = xdr_zero;
 600
 601        if (attr->ia_valid & ATTR_GID) {
 602                *p++ = xdr_one;
 603                *p++ = cpu_to_be32(attr->ia_gid);
 604        } else
 605                *p++ = xdr_zero;
 606
 607        if (attr->ia_valid & ATTR_SIZE) {
 608                *p++ = xdr_one;
 609                p = xdr_encode_hyper(p, (u64)attr->ia_size);
 610        } else
 611                *p++ = xdr_zero;
 612
 613        if (attr->ia_valid & ATTR_ATIME_SET) {
 614                *p++ = xdr_two;
 615                p = xdr_encode_nfstime3(p, &attr->ia_atime);
 616        } else if (attr->ia_valid & ATTR_ATIME) {
 617                *p++ = xdr_one;
 618        } else
 619                *p++ = xdr_zero;
 620
 621        if (attr->ia_valid & ATTR_MTIME_SET) {
 622                *p++ = xdr_two;
 623                xdr_encode_nfstime3(p, &attr->ia_mtime);
 624        } else if (attr->ia_valid & ATTR_MTIME) {
 625                *p = xdr_one;
 626        } else
 627                *p = xdr_zero;
 628}
 629
 630/*
 631 * fattr3
 632 *
 633 *      struct fattr3 {
 634 *              ftype3          type;
 635 *              mode3           mode;
 636 *              uint32          nlink;
 637 *              uid3            uid;
 638 *              gid3            gid;
 639 *              size3           size;
 640 *              size3           used;
 641 *              specdata3       rdev;
 642 *              uint64          fsid;
 643 *              fileid3         fileid;
 644 *              nfstime3        atime;
 645 *              nfstime3        mtime;
 646 *              nfstime3        ctime;
 647 *      };
 648 */
 649static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 650{
 651        umode_t fmode;
 652        __be32 *p;
 653
 654        p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
 655        if (unlikely(p == NULL))
 656                goto out_overflow;
 657
 658        p = xdr_decode_ftype3(p, &fmode);
 659
 660        fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
 661        fattr->nlink = be32_to_cpup(p++);
 662        fattr->uid = be32_to_cpup(p++);
 663        fattr->gid = be32_to_cpup(p++);
 664
 665        p = xdr_decode_size3(p, &fattr->size);
 666        p = xdr_decode_size3(p, &fattr->du.nfs3.used);
 667        p = xdr_decode_specdata3(p, &fattr->rdev);
 668
 669        p = xdr_decode_hyper(p, &fattr->fsid.major);
 670        fattr->fsid.minor = 0;
 671
 672        p = xdr_decode_fileid3(p, &fattr->fileid);
 673        p = xdr_decode_nfstime3(p, &fattr->atime);
 674        p = xdr_decode_nfstime3(p, &fattr->mtime);
 675        xdr_decode_nfstime3(p, &fattr->ctime);
 676        fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
 677
 678        fattr->valid |= NFS_ATTR_FATTR_V3;
 679        return 0;
 680out_overflow:
 681        print_overflow_msg(__func__, xdr);
 682        return -EIO;
 683}
 684
 685/*
 686 * post_op_attr
 687 *
 688 *      union post_op_attr switch (bool attributes_follow) {
 689 *      case TRUE:
 690 *              fattr3  attributes;
 691 *      case FALSE:
 692 *              void;
 693 *      };
 694 */
 695static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 696{
 697        __be32 *p;
 698
 699        p = xdr_inline_decode(xdr, 4);
 700        if (unlikely(p == NULL))
 701                goto out_overflow;
 702        if (*p != xdr_zero)
 703                return decode_fattr3(xdr, fattr);
 704        return 0;
 705out_overflow:
 706        print_overflow_msg(__func__, xdr);
 707        return -EIO;
 708}
 709
 710/*
 711 * wcc_attr
 712 *      struct wcc_attr {
 713 *              size3           size;
 714 *              nfstime3        mtime;
 715 *              nfstime3        ctime;
 716 *      };
 717 */
 718static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 719{
 720        __be32 *p;
 721
 722        p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
 723        if (unlikely(p == NULL))
 724                goto out_overflow;
 725
 726        fattr->valid |= NFS_ATTR_FATTR_PRESIZE
 727                | NFS_ATTR_FATTR_PRECHANGE
 728                | NFS_ATTR_FATTR_PREMTIME
 729                | NFS_ATTR_FATTR_PRECTIME;
 730
 731        p = xdr_decode_size3(p, &fattr->pre_size);
 732        p = xdr_decode_nfstime3(p, &fattr->pre_mtime);
 733        xdr_decode_nfstime3(p, &fattr->pre_ctime);
 734        fattr->pre_change_attr = nfs_timespec_to_change_attr(&fattr->pre_ctime);
 735
 736        return 0;
 737out_overflow:
 738        print_overflow_msg(__func__, xdr);
 739        return -EIO;
 740}
 741
 742/*
 743 * pre_op_attr
 744 *      union pre_op_attr switch (bool attributes_follow) {
 745 *      case TRUE:
 746 *              wcc_attr        attributes;
 747 *      case FALSE:
 748 *              void;
 749 *      };
 750 *
 751 * wcc_data
 752 *
 753 *      struct wcc_data {
 754 *              pre_op_attr     before;
 755 *              post_op_attr    after;
 756 *      };
 757 */
 758static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 759{
 760        __be32 *p;
 761
 762        p = xdr_inline_decode(xdr, 4);
 763        if (unlikely(p == NULL))
 764                goto out_overflow;
 765        if (*p != xdr_zero)
 766                return decode_wcc_attr(xdr, fattr);
 767        return 0;
 768out_overflow:
 769        print_overflow_msg(__func__, xdr);
 770        return -EIO;
 771}
 772
 773static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 774{
 775        int error;
 776
 777        error = decode_pre_op_attr(xdr, fattr);
 778        if (unlikely(error))
 779                goto out;
 780        error = decode_post_op_attr(xdr, fattr);
 781out:
 782        return error;
 783}
 784
 785/*
 786 * post_op_fh3
 787 *
 788 *      union post_op_fh3 switch (bool handle_follows) {
 789 *      case TRUE:
 790 *              nfs_fh3  handle;
 791 *      case FALSE:
 792 *              void;
 793 *      };
 794 */
 795static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
 796{
 797        __be32 *p = xdr_inline_decode(xdr, 4);
 798        if (unlikely(p == NULL))
 799                goto out_overflow;
 800        if (*p != xdr_zero)
 801                return decode_nfs_fh3(xdr, fh);
 802        zero_nfs_fh3(fh);
 803        return 0;
 804out_overflow:
 805        print_overflow_msg(__func__, xdr);
 806        return -EIO;
 807}
 808
 809/*
 810 * diropargs3
 811 *
 812 *      struct diropargs3 {
 813 *              nfs_fh3         dir;
 814 *              filename3       name;
 815 *      };
 816 */
 817static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
 818                              const char *name, u32 length)
 819{
 820        encode_nfs_fh3(xdr, fh);
 821        encode_filename3(xdr, name, length);
 822}
 823
 824
 825/*
 826 * NFSv3 XDR encode functions
 827 *
 828 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
 829 * "NFS Version 3 Protocol Specification".
 830 */
 831
 832/*
 833 * 3.3.1  GETATTR3args
 834 *
 835 *      struct GETATTR3args {
 836 *              nfs_fh3  object;
 837 *      };
 838 */
 839static void nfs3_xdr_enc_getattr3args(struct rpc_rqst *req,
 840                                      struct xdr_stream *xdr,
 841                                      const struct nfs_fh *fh)
 842{
 843        encode_nfs_fh3(xdr, fh);
 844}
 845
 846/*
 847 * 3.3.2  SETATTR3args
 848 *
 849 *      union sattrguard3 switch (bool check) {
 850 *      case TRUE:
 851 *              nfstime3  obj_ctime;
 852 *      case FALSE:
 853 *              void;
 854 *      };
 855 *
 856 *      struct SETATTR3args {
 857 *              nfs_fh3         object;
 858 *              sattr3          new_attributes;
 859 *              sattrguard3     guard;
 860 *      };
 861 */
 862static void encode_sattrguard3(struct xdr_stream *xdr,
 863                               const struct nfs3_sattrargs *args)
 864{
 865        __be32 *p;
 866
 867        if (args->guard) {
 868                p = xdr_reserve_space(xdr, 4 + 8);
 869                *p++ = xdr_one;
 870                xdr_encode_nfstime3(p, &args->guardtime);
 871        } else {
 872                p = xdr_reserve_space(xdr, 4);
 873                *p = xdr_zero;
 874        }
 875}
 876
 877static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req,
 878                                      struct xdr_stream *xdr,
 879                                      const struct nfs3_sattrargs *args)
 880{
 881        encode_nfs_fh3(xdr, args->fh);
 882        encode_sattr3(xdr, args->sattr);
 883        encode_sattrguard3(xdr, args);
 884}
 885
 886/*
 887 * 3.3.3  LOOKUP3args
 888 *
 889 *      struct LOOKUP3args {
 890 *              diropargs3  what;
 891 *      };
 892 */
 893static void nfs3_xdr_enc_lookup3args(struct rpc_rqst *req,
 894                                     struct xdr_stream *xdr,
 895                                     const struct nfs3_diropargs *args)
 896{
 897        encode_diropargs3(xdr, args->fh, args->name, args->len);
 898}
 899
 900/*
 901 * 3.3.4  ACCESS3args
 902 *
 903 *      struct ACCESS3args {
 904 *              nfs_fh3         object;
 905 *              uint32          access;
 906 *      };
 907 */
 908static void encode_access3args(struct xdr_stream *xdr,
 909                               const struct nfs3_accessargs *args)
 910{
 911        encode_nfs_fh3(xdr, args->fh);
 912        encode_uint32(xdr, args->access);
 913}
 914
 915static void nfs3_xdr_enc_access3args(struct rpc_rqst *req,
 916                                     struct xdr_stream *xdr,
 917                                     const struct nfs3_accessargs *args)
 918{
 919        encode_access3args(xdr, args);
 920}
 921
 922/*
 923 * 3.3.5  READLINK3args
 924 *
 925 *      struct READLINK3args {
 926 *              nfs_fh3 symlink;
 927 *      };
 928 */
 929static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
 930                                       struct xdr_stream *xdr,
 931                                       const struct nfs3_readlinkargs *args)
 932{
 933        encode_nfs_fh3(xdr, args->fh);
 934        prepare_reply_buffer(req, args->pages, args->pgbase,
 935                                        args->pglen, NFS3_readlinkres_sz);
 936}
 937
 938/*
 939 * 3.3.6  READ3args
 940 *
 941 *      struct READ3args {
 942 *              nfs_fh3         file;
 943 *              offset3         offset;
 944 *              count3          count;
 945 *      };
 946 */
 947static void encode_read3args(struct xdr_stream *xdr,
 948                             const struct nfs_readargs *args)
 949{
 950        __be32 *p;
 951
 952        encode_nfs_fh3(xdr, args->fh);
 953
 954        p = xdr_reserve_space(xdr, 8 + 4);
 955        p = xdr_encode_hyper(p, args->offset);
 956        *p = cpu_to_be32(args->count);
 957}
 958
 959static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
 960                                   struct xdr_stream *xdr,
 961                                   const struct nfs_readargs *args)
 962{
 963        encode_read3args(xdr, args);
 964        prepare_reply_buffer(req, args->pages, args->pgbase,
 965                                        args->count, NFS3_readres_sz);
 966        req->rq_rcv_buf.flags |= XDRBUF_READ;
 967}
 968
 969/*
 970 * 3.3.7  WRITE3args
 971 *
 972 *      enum stable_how {
 973 *              UNSTABLE  = 0,
 974 *              DATA_SYNC = 1,
 975 *              FILE_SYNC = 2
 976 *      };
 977 *
 978 *      struct WRITE3args {
 979 *              nfs_fh3         file;
 980 *              offset3         offset;
 981 *              count3          count;
 982 *              stable_how      stable;
 983 *              opaque          data<>;
 984 *      };
 985 */
 986static void encode_write3args(struct xdr_stream *xdr,
 987                              const struct nfs_writeargs *args)
 988{
 989        __be32 *p;
 990
 991        encode_nfs_fh3(xdr, args->fh);
 992
 993        p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
 994        p = xdr_encode_hyper(p, args->offset);
 995        *p++ = cpu_to_be32(args->count);
 996        *p++ = cpu_to_be32(args->stable);
 997        *p = cpu_to_be32(args->count);
 998        xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
 999}
1000
1001static void nfs3_xdr_enc_write3args(struct rpc_rqst *req,
1002                                    struct xdr_stream *xdr,
1003                                    const struct nfs_writeargs *args)
1004{
1005        encode_write3args(xdr, args);
1006        xdr->buf->flags |= XDRBUF_WRITE;
1007}
1008
1009/*
1010 * 3.3.8  CREATE3args
1011 *
1012 *      enum createmode3 {
1013 *              UNCHECKED = 0,
1014 *              GUARDED   = 1,
1015 *              EXCLUSIVE = 2
1016 *      };
1017 *
1018 *      union createhow3 switch (createmode3 mode) {
1019 *      case UNCHECKED:
1020 *      case GUARDED:
1021 *              sattr3       obj_attributes;
1022 *      case EXCLUSIVE:
1023 *              createverf3  verf;
1024 *      };
1025 *
1026 *      struct CREATE3args {
1027 *              diropargs3      where;
1028 *              createhow3      how;
1029 *      };
1030 */
1031static void encode_createhow3(struct xdr_stream *xdr,
1032                              const struct nfs3_createargs *args)
1033{
1034        encode_uint32(xdr, args->createmode);
1035        switch (args->createmode) {
1036        case NFS3_CREATE_UNCHECKED:
1037        case NFS3_CREATE_GUARDED:
1038                encode_sattr3(xdr, args->sattr);
1039                break;
1040        case NFS3_CREATE_EXCLUSIVE:
1041                encode_createverf3(xdr, args->verifier);
1042                break;
1043        default:
1044                BUG();
1045        }
1046}
1047
1048static void nfs3_xdr_enc_create3args(struct rpc_rqst *req,
1049                                     struct xdr_stream *xdr,
1050                                     const struct nfs3_createargs *args)
1051{
1052        encode_diropargs3(xdr, args->fh, args->name, args->len);
1053        encode_createhow3(xdr, args);
1054}
1055
1056/*
1057 * 3.3.9  MKDIR3args
1058 *
1059 *      struct MKDIR3args {
1060 *              diropargs3      where;
1061 *              sattr3          attributes;
1062 *      };
1063 */
1064static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req,
1065                                    struct xdr_stream *xdr,
1066                                    const struct nfs3_mkdirargs *args)
1067{
1068        encode_diropargs3(xdr, args->fh, args->name, args->len);
1069        encode_sattr3(xdr, args->sattr);
1070}
1071
1072/*
1073 * 3.3.10  SYMLINK3args
1074 *
1075 *      struct symlinkdata3 {
1076 *              sattr3          symlink_attributes;
1077 *              nfspath3        symlink_data;
1078 *      };
1079 *
1080 *      struct SYMLINK3args {
1081 *              diropargs3      where;
1082 *              symlinkdata3    symlink;
1083 *      };
1084 */
1085static void encode_symlinkdata3(struct xdr_stream *xdr,
1086                                const struct nfs3_symlinkargs *args)
1087{
1088        encode_sattr3(xdr, args->sattr);
1089        encode_nfspath3(xdr, args->pages, args->pathlen);
1090}
1091
1092static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req,
1093                                      struct xdr_stream *xdr,
1094                                      const struct nfs3_symlinkargs *args)
1095{
1096        encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen);
1097        encode_symlinkdata3(xdr, args);
1098}
1099
1100/*
1101 * 3.3.11  MKNOD3args
1102 *
1103 *      struct devicedata3 {
1104 *              sattr3          dev_attributes;
1105 *              specdata3       spec;
1106 *      };
1107 *
1108 *      union mknoddata3 switch (ftype3 type) {
1109 *      case NF3CHR:
1110 *      case NF3BLK:
1111 *              devicedata3     device;
1112 *      case NF3SOCK:
1113 *      case NF3FIFO:
1114 *              sattr3          pipe_attributes;
1115 *      default:
1116 *              void;
1117 *      };
1118 *
1119 *      struct MKNOD3args {
1120 *              diropargs3      where;
1121 *              mknoddata3      what;
1122 *      };
1123 */
1124static void encode_devicedata3(struct xdr_stream *xdr,
1125                               const struct nfs3_mknodargs *args)
1126{
1127        encode_sattr3(xdr, args->sattr);
1128        encode_specdata3(xdr, args->rdev);
1129}
1130
1131static void encode_mknoddata3(struct xdr_stream *xdr,
1132                              const struct nfs3_mknodargs *args)
1133{
1134        encode_ftype3(xdr, args->type);
1135        switch (args->type) {
1136        case NF3CHR:
1137        case NF3BLK:
1138                encode_devicedata3(xdr, args);
1139                break;
1140        case NF3SOCK:
1141        case NF3FIFO:
1142                encode_sattr3(xdr, args->sattr);
1143                break;
1144        case NF3REG:
1145        case NF3DIR:
1146                break;
1147        default:
1148                BUG();
1149        }
1150}
1151
1152static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req,
1153                                    struct xdr_stream *xdr,
1154                                    const struct nfs3_mknodargs *args)
1155{
1156        encode_diropargs3(xdr, args->fh, args->name, args->len);
1157        encode_mknoddata3(xdr, args);
1158}
1159
1160/*
1161 * 3.3.12  REMOVE3args
1162 *
1163 *      struct REMOVE3args {
1164 *              diropargs3  object;
1165 *      };
1166 */
1167static void nfs3_xdr_enc_remove3args(struct rpc_rqst *req,
1168                                     struct xdr_stream *xdr,
1169                                     const struct nfs_removeargs *args)
1170{
1171        encode_diropargs3(xdr, args->fh, args->name.name, args->name.len);
1172}
1173
1174/*
1175 * 3.3.14  RENAME3args
1176 *
1177 *      struct RENAME3args {
1178 *              diropargs3      from;
1179 *              diropargs3      to;
1180 *      };
1181 */
1182static void nfs3_xdr_enc_rename3args(struct rpc_rqst *req,
1183                                     struct xdr_stream *xdr,
1184                                     const struct nfs_renameargs *args)
1185{
1186        const struct qstr *old = args->old_name;
1187        const struct qstr *new = args->new_name;
1188
1189        encode_diropargs3(xdr, args->old_dir, old->name, old->len);
1190        encode_diropargs3(xdr, args->new_dir, new->name, new->len);
1191}
1192
1193/*
1194 * 3.3.15  LINK3args
1195 *
1196 *      struct LINK3args {
1197 *              nfs_fh3         file;
1198 *              diropargs3      link;
1199 *      };
1200 */
1201static void nfs3_xdr_enc_link3args(struct rpc_rqst *req,
1202                                   struct xdr_stream *xdr,
1203                                   const struct nfs3_linkargs *args)
1204{
1205        encode_nfs_fh3(xdr, args->fromfh);
1206        encode_diropargs3(xdr, args->tofh, args->toname, args->tolen);
1207}
1208
1209/*
1210 * 3.3.16  READDIR3args
1211 *
1212 *      struct READDIR3args {
1213 *              nfs_fh3         dir;
1214 *              cookie3         cookie;
1215 *              cookieverf3     cookieverf;
1216 *              count3          count;
1217 *      };
1218 */
1219static void encode_readdir3args(struct xdr_stream *xdr,
1220                                const struct nfs3_readdirargs *args)
1221{
1222        __be32 *p;
1223
1224        encode_nfs_fh3(xdr, args->fh);
1225
1226        p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1227        p = xdr_encode_cookie3(p, args->cookie);
1228        p = xdr_encode_cookieverf3(p, args->verf);
1229        *p = cpu_to_be32(args->count);
1230}
1231
1232static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
1233                                      struct xdr_stream *xdr,
1234                                      const struct nfs3_readdirargs *args)
1235{
1236        encode_readdir3args(xdr, args);
1237        prepare_reply_buffer(req, args->pages, 0,
1238                                args->count, NFS3_readdirres_sz);
1239}
1240
1241/*
1242 * 3.3.17  READDIRPLUS3args
1243 *
1244 *      struct READDIRPLUS3args {
1245 *              nfs_fh3         dir;
1246 *              cookie3         cookie;
1247 *              cookieverf3     cookieverf;
1248 *              count3          dircount;
1249 *              count3          maxcount;
1250 *      };
1251 */
1252static void encode_readdirplus3args(struct xdr_stream *xdr,
1253                                    const struct nfs3_readdirargs *args)
1254{
1255        __be32 *p;
1256
1257        encode_nfs_fh3(xdr, args->fh);
1258
1259        p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1260        p = xdr_encode_cookie3(p, args->cookie);
1261        p = xdr_encode_cookieverf3(p, args->verf);
1262
1263        /*
1264         * readdirplus: need dircount + buffer size.
1265         * We just make sure we make dircount big enough
1266         */
1267        *p++ = cpu_to_be32(args->count >> 3);
1268
1269        *p = cpu_to_be32(args->count);
1270}
1271
1272static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
1273                                          struct xdr_stream *xdr,
1274                                          const struct nfs3_readdirargs *args)
1275{
1276        encode_readdirplus3args(xdr, args);
1277        prepare_reply_buffer(req, args->pages, 0,
1278                                args->count, NFS3_readdirres_sz);
1279}
1280
1281/*
1282 * 3.3.21  COMMIT3args
1283 *
1284 *      struct COMMIT3args {
1285 *              nfs_fh3         file;
1286 *              offset3         offset;
1287 *              count3          count;
1288 *      };
1289 */
1290static void encode_commit3args(struct xdr_stream *xdr,
1291                               const struct nfs_commitargs *args)
1292{
1293        __be32 *p;
1294
1295        encode_nfs_fh3(xdr, args->fh);
1296
1297        p = xdr_reserve_space(xdr, 8 + 4);
1298        p = xdr_encode_hyper(p, args->offset);
1299        *p = cpu_to_be32(args->count);
1300}
1301
1302static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req,
1303                                     struct xdr_stream *xdr,
1304                                     const struct nfs_commitargs *args)
1305{
1306        encode_commit3args(xdr, args);
1307}
1308
1309#ifdef CONFIG_NFS_V3_ACL
1310
1311static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
1312                                     struct xdr_stream *xdr,
1313                                     const struct nfs3_getaclargs *args)
1314{
1315        encode_nfs_fh3(xdr, args->fh);
1316        encode_uint32(xdr, args->mask);
1317        if (args->mask & (NFS_ACL | NFS_DFACL))
1318                prepare_reply_buffer(req, args->pages, 0,
1319                                        NFSACL_MAXPAGES << PAGE_SHIFT,
1320                                        ACL3_getaclres_sz);
1321}
1322
1323static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
1324                                     struct xdr_stream *xdr,
1325                                     const struct nfs3_setaclargs *args)
1326{
1327        unsigned int base;
1328        int error;
1329
1330        encode_nfs_fh3(xdr, NFS_FH(args->inode));
1331        encode_uint32(xdr, args->mask);
1332
1333        base = req->rq_slen;
1334        if (args->npages != 0)
1335                xdr_write_pages(xdr, args->pages, 0, args->len);
1336        else
1337                xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE);
1338
1339        error = nfsacl_encode(xdr->buf, base, args->inode,
1340                            (args->mask & NFS_ACL) ?
1341                            args->acl_access : NULL, 1, 0);
1342        BUG_ON(error < 0);
1343        error = nfsacl_encode(xdr->buf, base + error, args->inode,
1344                            (args->mask & NFS_DFACL) ?
1345                            args->acl_default : NULL, 1,
1346                            NFS_ACL_DEFAULT);
1347        BUG_ON(error < 0);
1348}
1349
1350#endif  /* CONFIG_NFS_V3_ACL */
1351
1352/*
1353 * NFSv3 XDR decode functions
1354 *
1355 * NFSv3 result types are defined in section 3.3 of RFC 1813:
1356 * "NFS Version 3 Protocol Specification".
1357 */
1358
1359/*
1360 * 3.3.1  GETATTR3res
1361 *
1362 *      struct GETATTR3resok {
1363 *              fattr3          obj_attributes;
1364 *      };
1365 *
1366 *      union GETATTR3res switch (nfsstat3 status) {
1367 *      case NFS3_OK:
1368 *              GETATTR3resok  resok;
1369 *      default:
1370 *              void;
1371 *      };
1372 */
1373static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req,
1374                                    struct xdr_stream *xdr,
1375                                    struct nfs_fattr *result)
1376{
1377        enum nfs_stat status;
1378        int error;
1379
1380        error = decode_nfsstat3(xdr, &status);
1381        if (unlikely(error))
1382                goto out;
1383        if (status != NFS3_OK)
1384                goto out_default;
1385        error = decode_fattr3(xdr, result);
1386out:
1387        return error;
1388out_default:
1389        return nfs3_stat_to_errno(status);
1390}
1391
1392/*
1393 * 3.3.2  SETATTR3res
1394 *
1395 *      struct SETATTR3resok {
1396 *              wcc_data  obj_wcc;
1397 *      };
1398 *
1399 *      struct SETATTR3resfail {
1400 *              wcc_data  obj_wcc;
1401 *      };
1402 *
1403 *      union SETATTR3res switch (nfsstat3 status) {
1404 *      case NFS3_OK:
1405 *              SETATTR3resok   resok;
1406 *      default:
1407 *              SETATTR3resfail resfail;
1408 *      };
1409 */
1410static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req,
1411                                    struct xdr_stream *xdr,
1412                                    struct nfs_fattr *result)
1413{
1414        enum nfs_stat status;
1415        int error;
1416
1417        error = decode_nfsstat3(xdr, &status);
1418        if (unlikely(error))
1419                goto out;
1420        error = decode_wcc_data(xdr, result);
1421        if (unlikely(error))
1422                goto out;
1423        if (status != NFS3_OK)
1424                goto out_status;
1425out:
1426        return error;
1427out_status:
1428        return nfs3_stat_to_errno(status);
1429}
1430
1431/*
1432 * 3.3.3  LOOKUP3res
1433 *
1434 *      struct LOOKUP3resok {
1435 *              nfs_fh3         object;
1436 *              post_op_attr    obj_attributes;
1437 *              post_op_attr    dir_attributes;
1438 *      };
1439 *
1440 *      struct LOOKUP3resfail {
1441 *              post_op_attr    dir_attributes;
1442 *      };
1443 *
1444 *      union LOOKUP3res switch (nfsstat3 status) {
1445 *      case NFS3_OK:
1446 *              LOOKUP3resok    resok;
1447 *      default:
1448 *              LOOKUP3resfail  resfail;
1449 *      };
1450 */
1451static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req,
1452                                   struct xdr_stream *xdr,
1453                                   struct nfs3_diropres *result)
1454{
1455        enum nfs_stat status;
1456        int error;
1457
1458        error = decode_nfsstat3(xdr, &status);
1459        if (unlikely(error))
1460                goto out;
1461        if (status != NFS3_OK)
1462                goto out_default;
1463        error = decode_nfs_fh3(xdr, result->fh);
1464        if (unlikely(error))
1465                goto out;
1466        error = decode_post_op_attr(xdr, result->fattr);
1467        if (unlikely(error))
1468                goto out;
1469        error = decode_post_op_attr(xdr, result->dir_attr);
1470out:
1471        return error;
1472out_default:
1473        error = decode_post_op_attr(xdr, result->dir_attr);
1474        if (unlikely(error))
1475                goto out;
1476        return nfs3_stat_to_errno(status);
1477}
1478
1479/*
1480 * 3.3.4  ACCESS3res
1481 *
1482 *      struct ACCESS3resok {
1483 *              post_op_attr    obj_attributes;
1484 *              uint32          access;
1485 *      };
1486 *
1487 *      struct ACCESS3resfail {
1488 *              post_op_attr    obj_attributes;
1489 *      };
1490 *
1491 *      union ACCESS3res switch (nfsstat3 status) {
1492 *      case NFS3_OK:
1493 *              ACCESS3resok    resok;
1494 *      default:
1495 *              ACCESS3resfail  resfail;
1496 *      };
1497 */
1498static int nfs3_xdr_dec_access3res(struct rpc_rqst *req,
1499                                   struct xdr_stream *xdr,
1500                                   struct nfs3_accessres *result)
1501{
1502        enum nfs_stat status;
1503        int error;
1504
1505        error = decode_nfsstat3(xdr, &status);
1506        if (unlikely(error))
1507                goto out;
1508        error = decode_post_op_attr(xdr, result->fattr);
1509        if (unlikely(error))
1510                goto out;
1511        if (status != NFS3_OK)
1512                goto out_default;
1513        error = decode_uint32(xdr, &result->access);
1514out:
1515        return error;
1516out_default:
1517        return nfs3_stat_to_errno(status);
1518}
1519
1520/*
1521 * 3.3.5  READLINK3res
1522 *
1523 *      struct READLINK3resok {
1524 *              post_op_attr    symlink_attributes;
1525 *              nfspath3        data;
1526 *      };
1527 *
1528 *      struct READLINK3resfail {
1529 *              post_op_attr    symlink_attributes;
1530 *      };
1531 *
1532 *      union READLINK3res switch (nfsstat3 status) {
1533 *      case NFS3_OK:
1534 *              READLINK3resok  resok;
1535 *      default:
1536 *              READLINK3resfail resfail;
1537 *      };
1538 */
1539static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req,
1540                                     struct xdr_stream *xdr,
1541                                     struct nfs_fattr *result)
1542{
1543        enum nfs_stat status;
1544        int error;
1545
1546        error = decode_nfsstat3(xdr, &status);
1547        if (unlikely(error))
1548                goto out;
1549        error = decode_post_op_attr(xdr, result);
1550        if (unlikely(error))
1551                goto out;
1552        if (status != NFS3_OK)
1553                goto out_default;
1554        error = decode_nfspath3(xdr);
1555out:
1556        return error;
1557out_default:
1558        return nfs3_stat_to_errno(status);
1559}
1560
1561/*
1562 * 3.3.6  READ3res
1563 *
1564 *      struct READ3resok {
1565 *              post_op_attr    file_attributes;
1566 *              count3          count;
1567 *              bool            eof;
1568 *              opaque          data<>;
1569 *      };
1570 *
1571 *      struct READ3resfail {
1572 *              post_op_attr    file_attributes;
1573 *      };
1574 *
1575 *      union READ3res switch (nfsstat3 status) {
1576 *      case NFS3_OK:
1577 *              READ3resok      resok;
1578 *      default:
1579 *              READ3resfail    resfail;
1580 *      };
1581 */
1582static int decode_read3resok(struct xdr_stream *xdr,
1583                             struct nfs_readres *result)
1584{
1585        u32 eof, count, ocount, recvd;
1586        __be32 *p;
1587
1588        p = xdr_inline_decode(xdr, 4 + 4 + 4);
1589        if (unlikely(p == NULL))
1590                goto out_overflow;
1591        count = be32_to_cpup(p++);
1592        eof = be32_to_cpup(p++);
1593        ocount = be32_to_cpup(p++);
1594        if (unlikely(ocount != count))
1595                goto out_mismatch;
1596        recvd = xdr_read_pages(xdr, count);
1597        if (unlikely(count > recvd))
1598                goto out_cheating;
1599out:
1600        result->eof = eof;
1601        result->count = count;
1602        return count;
1603out_mismatch:
1604        dprintk("NFS: READ count doesn't match length of opaque: "
1605                "count %u != ocount %u\n", count, ocount);
1606        return -EIO;
1607out_cheating:
1608        dprintk("NFS: server cheating in read result: "
1609                "count %u > recvd %u\n", count, recvd);
1610        count = recvd;
1611        eof = 0;
1612        goto out;
1613out_overflow:
1614        print_overflow_msg(__func__, xdr);
1615        return -EIO;
1616}
1617
1618static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1619                                 struct nfs_readres *result)
1620{
1621        enum nfs_stat status;
1622        int error;
1623
1624        error = decode_nfsstat3(xdr, &status);
1625        if (unlikely(error))
1626                goto out;
1627        error = decode_post_op_attr(xdr, result->fattr);
1628        if (unlikely(error))
1629                goto out;
1630        if (status != NFS3_OK)
1631                goto out_status;
1632        error = decode_read3resok(xdr, result);
1633out:
1634        return error;
1635out_status:
1636        return nfs3_stat_to_errno(status);
1637}
1638
1639/*
1640 * 3.3.7  WRITE3res
1641 *
1642 *      enum stable_how {
1643 *              UNSTABLE  = 0,
1644 *              DATA_SYNC = 1,
1645 *              FILE_SYNC = 2
1646 *      };
1647 *
1648 *      struct WRITE3resok {
1649 *              wcc_data        file_wcc;
1650 *              count3          count;
1651 *              stable_how      committed;
1652 *              writeverf3      verf;
1653 *      };
1654 *
1655 *      struct WRITE3resfail {
1656 *              wcc_data        file_wcc;
1657 *      };
1658 *
1659 *      union WRITE3res switch (nfsstat3 status) {
1660 *      case NFS3_OK:
1661 *              WRITE3resok     resok;
1662 *      default:
1663 *              WRITE3resfail   resfail;
1664 *      };
1665 */
1666static int decode_write3resok(struct xdr_stream *xdr,
1667                              struct nfs_writeres *result)
1668{
1669        __be32 *p;
1670
1671        p = xdr_inline_decode(xdr, 4 + 4);
1672        if (unlikely(p == NULL))
1673                goto out_overflow;
1674        result->count = be32_to_cpup(p++);
1675        result->verf->committed = be32_to_cpup(p++);
1676        if (unlikely(result->verf->committed > NFS_FILE_SYNC))
1677                goto out_badvalue;
1678        if (decode_writeverf3(xdr, &result->verf->verifier))
1679                goto out_eio;
1680        return result->count;
1681out_badvalue:
1682        dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
1683        return -EIO;
1684out_overflow:
1685        print_overflow_msg(__func__, xdr);
1686out_eio:
1687        return -EIO;
1688}
1689
1690static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1691                                  struct nfs_writeres *result)
1692{
1693        enum nfs_stat status;
1694        int error;
1695
1696        error = decode_nfsstat3(xdr, &status);
1697        if (unlikely(error))
1698                goto out;
1699        error = decode_wcc_data(xdr, result->fattr);
1700        if (unlikely(error))
1701                goto out;
1702        if (status != NFS3_OK)
1703                goto out_status;
1704        error = decode_write3resok(xdr, result);
1705out:
1706        return error;
1707out_status:
1708        return nfs3_stat_to_errno(status);
1709}
1710
1711/*
1712 * 3.3.8  CREATE3res
1713 *
1714 *      struct CREATE3resok {
1715 *              post_op_fh3     obj;
1716 *              post_op_attr    obj_attributes;
1717 *              wcc_data        dir_wcc;
1718 *      };
1719 *
1720 *      struct CREATE3resfail {
1721 *              wcc_data        dir_wcc;
1722 *      };
1723 *
1724 *      union CREATE3res switch (nfsstat3 status) {
1725 *      case NFS3_OK:
1726 *              CREATE3resok    resok;
1727 *      default:
1728 *              CREATE3resfail  resfail;
1729 *      };
1730 */
1731static int decode_create3resok(struct xdr_stream *xdr,
1732                               struct nfs3_diropres *result)
1733{
1734        int error;
1735
1736        error = decode_post_op_fh3(xdr, result->fh);
1737        if (unlikely(error))
1738                goto out;
1739        error = decode_post_op_attr(xdr, result->fattr);
1740        if (unlikely(error))
1741                goto out;
1742        /* The server isn't required to return a file handle.
1743         * If it didn't, force the client to perform a LOOKUP
1744         * to determine the correct file handle and attribute
1745         * values for the new object. */
1746        if (result->fh->size == 0)
1747                result->fattr->valid = 0;
1748        error = decode_wcc_data(xdr, result->dir_attr);
1749out:
1750        return error;
1751}
1752
1753static int nfs3_xdr_dec_create3res(struct rpc_rqst *req,
1754                                   struct xdr_stream *xdr,
1755                                   struct nfs3_diropres *result)
1756{
1757        enum nfs_stat status;
1758        int error;
1759
1760        error = decode_nfsstat3(xdr, &status);
1761        if (unlikely(error))
1762                goto out;
1763        if (status != NFS3_OK)
1764                goto out_default;
1765        error = decode_create3resok(xdr, result);
1766out:
1767        return error;
1768out_default:
1769        error = decode_wcc_data(xdr, result->dir_attr);
1770        if (unlikely(error))
1771                goto out;
1772        return nfs3_stat_to_errno(status);
1773}
1774
1775/*
1776 * 3.3.12  REMOVE3res
1777 *
1778 *      struct REMOVE3resok {
1779 *              wcc_data    dir_wcc;
1780 *      };
1781 *
1782 *      struct REMOVE3resfail {
1783 *              wcc_data    dir_wcc;
1784 *      };
1785 *
1786 *      union REMOVE3res switch (nfsstat3 status) {
1787 *      case NFS3_OK:
1788 *              REMOVE3resok   resok;
1789 *      default:
1790 *              REMOVE3resfail resfail;
1791 *      };
1792 */
1793static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req,
1794                                   struct xdr_stream *xdr,
1795                                   struct nfs_removeres *result)
1796{
1797        enum nfs_stat status;
1798        int error;
1799
1800        error = decode_nfsstat3(xdr, &status);
1801        if (unlikely(error))
1802                goto out;
1803        error = decode_wcc_data(xdr, result->dir_attr);
1804        if (unlikely(error))
1805                goto out;
1806        if (status != NFS3_OK)
1807                goto out_status;
1808out:
1809        return error;
1810out_status:
1811        return nfs3_stat_to_errno(status);
1812}
1813
1814/*
1815 * 3.3.14  RENAME3res
1816 *
1817 *      struct RENAME3resok {
1818 *              wcc_data        fromdir_wcc;
1819 *              wcc_data        todir_wcc;
1820 *      };
1821 *
1822 *      struct RENAME3resfail {
1823 *              wcc_data        fromdir_wcc;
1824 *              wcc_data        todir_wcc;
1825 *      };
1826 *
1827 *      union RENAME3res switch (nfsstat3 status) {
1828 *      case NFS3_OK:
1829 *              RENAME3resok   resok;
1830 *      default:
1831 *              RENAME3resfail resfail;
1832 *      };
1833 */
1834static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
1835                                   struct xdr_stream *xdr,
1836                                   struct nfs_renameres *result)
1837{
1838        enum nfs_stat status;
1839        int error;
1840
1841        error = decode_nfsstat3(xdr, &status);
1842        if (unlikely(error))
1843                goto out;
1844        error = decode_wcc_data(xdr, result->old_fattr);
1845        if (unlikely(error))
1846                goto out;
1847        error = decode_wcc_data(xdr, result->new_fattr);
1848        if (unlikely(error))
1849                goto out;
1850        if (status != NFS3_OK)
1851                goto out_status;
1852out:
1853        return error;
1854out_status:
1855        return nfs3_stat_to_errno(status);
1856}
1857
1858/*
1859 * 3.3.15  LINK3res
1860 *
1861 *      struct LINK3resok {
1862 *              post_op_attr    file_attributes;
1863 *              wcc_data        linkdir_wcc;
1864 *      };
1865 *
1866 *      struct LINK3resfail {
1867 *              post_op_attr    file_attributes;
1868 *              wcc_data        linkdir_wcc;
1869 *      };
1870 *
1871 *      union LINK3res switch (nfsstat3 status) {
1872 *      case NFS3_OK:
1873 *              LINK3resok      resok;
1874 *      default:
1875 *              LINK3resfail    resfail;
1876 *      };
1877 */
1878static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1879                                 struct nfs3_linkres *result)
1880{
1881        enum nfs_stat status;
1882        int error;
1883
1884        error = decode_nfsstat3(xdr, &status);
1885        if (unlikely(error))
1886                goto out;
1887        error = decode_post_op_attr(xdr, result->fattr);
1888        if (unlikely(error))
1889                goto out;
1890        error = decode_wcc_data(xdr, result->dir_attr);
1891        if (unlikely(error))
1892                goto out;
1893        if (status != NFS3_OK)
1894                goto out_status;
1895out:
1896        return error;
1897out_status:
1898        return nfs3_stat_to_errno(status);
1899}
1900
1901/**
1902 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
1903 *                      the local page cache
1904 * @xdr: XDR stream where entry resides
1905 * @entry: buffer to fill in with entry data
1906 * @plus: boolean indicating whether this should be a readdirplus entry
1907 *
1908 * Returns zero if successful, otherwise a negative errno value is
1909 * returned.
1910 *
1911 * This function is not invoked during READDIR reply decoding, but
1912 * rather whenever an application invokes the getdents(2) system call
1913 * on a directory already in our cache.
1914 *
1915 * 3.3.16  entry3
1916 *
1917 *      struct entry3 {
1918 *              fileid3         fileid;
1919 *              filename3       name;
1920 *              cookie3         cookie;
1921 *              fhandle3        filehandle;
1922 *              post_op_attr3   attributes;
1923 *              entry3          *nextentry;
1924 *      };
1925 *
1926 * 3.3.17  entryplus3
1927 *      struct entryplus3 {
1928 *              fileid3         fileid;
1929 *              filename3       name;
1930 *              cookie3         cookie;
1931 *              post_op_attr    name_attributes;
1932 *              post_op_fh3     name_handle;
1933 *              entryplus3      *nextentry;
1934 *      };
1935 */
1936int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
1937                       int plus)
1938{
1939        struct nfs_entry old = *entry;
1940        __be32 *p;
1941        int error;
1942
1943        p = xdr_inline_decode(xdr, 4);
1944        if (unlikely(p == NULL))
1945                goto out_overflow;
1946        if (*p == xdr_zero) {
1947                p = xdr_inline_decode(xdr, 4);
1948                if (unlikely(p == NULL))
1949                        goto out_overflow;
1950                if (*p == xdr_zero)
1951                        return -EAGAIN;
1952                entry->eof = 1;
1953                return -EBADCOOKIE;
1954        }
1955
1956        error = decode_fileid3(xdr, &entry->ino);
1957        if (unlikely(error))
1958                return error;
1959
1960        error = decode_inline_filename3(xdr, &entry->name, &entry->len);
1961        if (unlikely(error))
1962                return error;
1963
1964        entry->prev_cookie = entry->cookie;
1965        error = decode_cookie3(xdr, &entry->cookie);
1966        if (unlikely(error))
1967                return error;
1968
1969        entry->d_type = DT_UNKNOWN;
1970
1971        if (plus) {
1972                entry->fattr->valid = 0;
1973                error = decode_post_op_attr(xdr, entry->fattr);
1974                if (unlikely(error))
1975                        return error;
1976                if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
1977                        entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
1978
1979                /* In fact, a post_op_fh3: */
1980                p = xdr_inline_decode(xdr, 4);
1981                if (unlikely(p == NULL))
1982                        goto out_overflow;
1983                if (*p != xdr_zero) {
1984                        error = decode_nfs_fh3(xdr, entry->fh);
1985                        if (unlikely(error)) {
1986                                if (error == -E2BIG)
1987                                        goto out_truncated;
1988                                return error;
1989                        }
1990                } else
1991                        zero_nfs_fh3(entry->fh);
1992        }
1993
1994        return 0;
1995
1996out_overflow:
1997        print_overflow_msg(__func__, xdr);
1998        return -EAGAIN;
1999out_truncated:
2000        dprintk("NFS: directory entry contains invalid file handle\n");
2001        *entry = old;
2002        return -EAGAIN;
2003}
2004
2005/*
2006 * 3.3.16  READDIR3res
2007 *
2008 *      struct dirlist3 {
2009 *              entry3          *entries;
2010 *              bool            eof;
2011 *      };
2012 *
2013 *      struct READDIR3resok {
2014 *              post_op_attr    dir_attributes;
2015 *              cookieverf3     cookieverf;
2016 *              dirlist3        reply;
2017 *      };
2018 *
2019 *      struct READDIR3resfail {
2020 *              post_op_attr    dir_attributes;
2021 *      };
2022 *
2023 *      union READDIR3res switch (nfsstat3 status) {
2024 *      case NFS3_OK:
2025 *              READDIR3resok   resok;
2026 *      default:
2027 *              READDIR3resfail resfail;
2028 *      };
2029 *
2030 * Read the directory contents into the page cache, but otherwise
2031 * don't touch them.  The actual decoding is done by nfs3_decode_entry()
2032 * during subsequent nfs_readdir() calls.
2033 */
2034static int decode_dirlist3(struct xdr_stream *xdr)
2035{
2036        return xdr_read_pages(xdr, xdr->buf->page_len);
2037}
2038
2039static int decode_readdir3resok(struct xdr_stream *xdr,
2040                                struct nfs3_readdirres *result)
2041{
2042        int error;
2043
2044        error = decode_post_op_attr(xdr, result->dir_attr);
2045        if (unlikely(error))
2046                goto out;
2047        /* XXX: do we need to check if result->verf != NULL ? */
2048        error = decode_cookieverf3(xdr, result->verf);
2049        if (unlikely(error))
2050                goto out;
2051        error = decode_dirlist3(xdr);
2052out:
2053        return error;
2054}
2055
2056static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req,
2057                                    struct xdr_stream *xdr,
2058                                    struct nfs3_readdirres *result)
2059{
2060        enum nfs_stat status;
2061        int error;
2062
2063        error = decode_nfsstat3(xdr, &status);
2064        if (unlikely(error))
2065                goto out;
2066        if (status != NFS3_OK)
2067                goto out_default;
2068        error = decode_readdir3resok(xdr, result);
2069out:
2070        return error;
2071out_default:
2072        error = decode_post_op_attr(xdr, result->dir_attr);
2073        if (unlikely(error))
2074                goto out;
2075        return nfs3_stat_to_errno(status);
2076}
2077
2078/*
2079 * 3.3.18  FSSTAT3res
2080 *
2081 *      struct FSSTAT3resok {
2082 *              post_op_attr    obj_attributes;
2083 *              size3           tbytes;
2084 *              size3           fbytes;
2085 *              size3           abytes;
2086 *              size3           tfiles;
2087 *              size3           ffiles;
2088 *              size3           afiles;
2089 *              uint32          invarsec;
2090 *      };
2091 *
2092 *      struct FSSTAT3resfail {
2093 *              post_op_attr    obj_attributes;
2094 *      };
2095 *
2096 *      union FSSTAT3res switch (nfsstat3 status) {
2097 *      case NFS3_OK:
2098 *              FSSTAT3resok    resok;
2099 *      default:
2100 *              FSSTAT3resfail  resfail;
2101 *      };
2102 */
2103static int decode_fsstat3resok(struct xdr_stream *xdr,
2104                               struct nfs_fsstat *result)
2105{
2106        __be32 *p;
2107
2108        p = xdr_inline_decode(xdr, 8 * 6 + 4);
2109        if (unlikely(p == NULL))
2110                goto out_overflow;
2111        p = xdr_decode_size3(p, &result->tbytes);
2112        p = xdr_decode_size3(p, &result->fbytes);
2113        p = xdr_decode_size3(p, &result->abytes);
2114        p = xdr_decode_size3(p, &result->tfiles);
2115        p = xdr_decode_size3(p, &result->ffiles);
2116        xdr_decode_size3(p, &result->afiles);
2117        /* ignore invarsec */
2118        return 0;
2119out_overflow:
2120        print_overflow_msg(__func__, xdr);
2121        return -EIO;
2122}
2123
2124static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req,
2125                                   struct xdr_stream *xdr,
2126                                   struct nfs_fsstat *result)
2127{
2128        enum nfs_stat status;
2129        int error;
2130
2131        error = decode_nfsstat3(xdr, &status);
2132        if (unlikely(error))
2133                goto out;
2134        error = decode_post_op_attr(xdr, result->fattr);
2135        if (unlikely(error))
2136                goto out;
2137        if (status != NFS3_OK)
2138                goto out_status;
2139        error = decode_fsstat3resok(xdr, result);
2140out:
2141        return error;
2142out_status:
2143        return nfs3_stat_to_errno(status);
2144}
2145
2146/*
2147 * 3.3.19  FSINFO3res
2148 *
2149 *      struct FSINFO3resok {
2150 *              post_op_attr    obj_attributes;
2151 *              uint32          rtmax;
2152 *              uint32          rtpref;
2153 *              uint32          rtmult;
2154 *              uint32          wtmax;
2155 *              uint32          wtpref;
2156 *              uint32          wtmult;
2157 *              uint32          dtpref;
2158 *              size3           maxfilesize;
2159 *              nfstime3        time_delta;
2160 *              uint32          properties;
2161 *      };
2162 *
2163 *      struct FSINFO3resfail {
2164 *              post_op_attr    obj_attributes;
2165 *      };
2166 *
2167 *      union FSINFO3res switch (nfsstat3 status) {
2168 *      case NFS3_OK:
2169 *              FSINFO3resok    resok;
2170 *      default:
2171 *              FSINFO3resfail  resfail;
2172 *      };
2173 */
2174static int decode_fsinfo3resok(struct xdr_stream *xdr,
2175                               struct nfs_fsinfo *result)
2176{
2177        __be32 *p;
2178
2179        p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
2180        if (unlikely(p == NULL))
2181                goto out_overflow;
2182        result->rtmax  = be32_to_cpup(p++);
2183        result->rtpref = be32_to_cpup(p++);
2184        result->rtmult = be32_to_cpup(p++);
2185        result->wtmax  = be32_to_cpup(p++);
2186        result->wtpref = be32_to_cpup(p++);
2187        result->wtmult = be32_to_cpup(p++);
2188        result->dtpref = be32_to_cpup(p++);
2189        p = xdr_decode_size3(p, &result->maxfilesize);
2190        xdr_decode_nfstime3(p, &result->time_delta);
2191
2192        /* ignore properties */
2193        result->lease_time = 0;
2194        return 0;
2195out_overflow:
2196        print_overflow_msg(__func__, xdr);
2197        return -EIO;
2198}
2199
2200static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req,
2201                                   struct xdr_stream *xdr,
2202                                   struct nfs_fsinfo *result)
2203{
2204        enum nfs_stat status;
2205        int error;
2206
2207        error = decode_nfsstat3(xdr, &status);
2208        if (unlikely(error))
2209                goto out;
2210        error = decode_post_op_attr(xdr, result->fattr);
2211        if (unlikely(error))
2212                goto out;
2213        if (status != NFS3_OK)
2214                goto out_status;
2215        error = decode_fsinfo3resok(xdr, result);
2216out:
2217        return error;
2218out_status:
2219        return nfs3_stat_to_errno(status);
2220}
2221
2222/*
2223 * 3.3.20  PATHCONF3res
2224 *
2225 *      struct PATHCONF3resok {
2226 *              post_op_attr    obj_attributes;
2227 *              uint32          linkmax;
2228 *              uint32          name_max;
2229 *              bool            no_trunc;
2230 *              bool            chown_restricted;
2231 *              bool            case_insensitive;
2232 *              bool            case_preserving;
2233 *      };
2234 *
2235 *      struct PATHCONF3resfail {
2236 *              post_op_attr    obj_attributes;
2237 *      };
2238 *
2239 *      union PATHCONF3res switch (nfsstat3 status) {
2240 *      case NFS3_OK:
2241 *              PATHCONF3resok  resok;
2242 *      default:
2243 *              PATHCONF3resfail resfail;
2244 *      };
2245 */
2246static int decode_pathconf3resok(struct xdr_stream *xdr,
2247                                 struct nfs_pathconf *result)
2248{
2249        __be32 *p;
2250
2251        p = xdr_inline_decode(xdr, 4 * 6);
2252        if (unlikely(p == NULL))
2253                goto out_overflow;
2254        result->max_link = be32_to_cpup(p++);
2255        result->max_namelen = be32_to_cpup(p);
2256        /* ignore remaining fields */
2257        return 0;
2258out_overflow:
2259        print_overflow_msg(__func__, xdr);
2260        return -EIO;
2261}
2262
2263static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req,
2264                                     struct xdr_stream *xdr,
2265                                     struct nfs_pathconf *result)
2266{
2267        enum nfs_stat status;
2268        int error;
2269
2270        error = decode_nfsstat3(xdr, &status);
2271        if (unlikely(error))
2272                goto out;
2273        error = decode_post_op_attr(xdr, result->fattr);
2274        if (unlikely(error))
2275                goto out;
2276        if (status != NFS3_OK)
2277                goto out_status;
2278        error = decode_pathconf3resok(xdr, result);
2279out:
2280        return error;
2281out_status:
2282        return nfs3_stat_to_errno(status);
2283}
2284
2285/*
2286 * 3.3.21  COMMIT3res
2287 *
2288 *      struct COMMIT3resok {
2289 *              wcc_data        file_wcc;
2290 *              writeverf3      verf;
2291 *      };
2292 *
2293 *      struct COMMIT3resfail {
2294 *              wcc_data        file_wcc;
2295 *      };
2296 *
2297 *      union COMMIT3res switch (nfsstat3 status) {
2298 *      case NFS3_OK:
2299 *              COMMIT3resok    resok;
2300 *      default:
2301 *              COMMIT3resfail  resfail;
2302 *      };
2303 */
2304static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
2305                                   struct xdr_stream *xdr,
2306                                   struct nfs_commitres *result)
2307{
2308        enum nfs_stat status;
2309        int error;
2310
2311        error = decode_nfsstat3(xdr, &status);
2312        if (unlikely(error))
2313                goto out;
2314        error = decode_wcc_data(xdr, result->fattr);
2315        if (unlikely(error))
2316                goto out;
2317        if (status != NFS3_OK)
2318                goto out_status;
2319        error = decode_writeverf3(xdr, &result->verf->verifier);
2320out:
2321        return error;
2322out_status:
2323        return nfs3_stat_to_errno(status);
2324}
2325
2326#ifdef CONFIG_NFS_V3_ACL
2327
2328static inline int decode_getacl3resok(struct xdr_stream *xdr,
2329                                      struct nfs3_getaclres *result)
2330{
2331        struct posix_acl **acl;
2332        unsigned int *aclcnt;
2333        size_t hdrlen;
2334        int error;
2335
2336        error = decode_post_op_attr(xdr, result->fattr);
2337        if (unlikely(error))
2338                goto out;
2339        error = decode_uint32(xdr, &result->mask);
2340        if (unlikely(error))
2341                goto out;
2342        error = -EINVAL;
2343        if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2344                goto out;
2345
2346        hdrlen = xdr_stream_pos(xdr);
2347
2348        acl = NULL;
2349        if (result->mask & NFS_ACL)
2350                acl = &result->acl_access;
2351        aclcnt = NULL;
2352        if (result->mask & NFS_ACLCNT)
2353                aclcnt = &result->acl_access_count;
2354        error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl);
2355        if (unlikely(error <= 0))
2356                goto out;
2357
2358        acl = NULL;
2359        if (result->mask & NFS_DFACL)
2360                acl = &result->acl_default;
2361        aclcnt = NULL;
2362        if (result->mask & NFS_DFACLCNT)
2363                aclcnt = &result->acl_default_count;
2364        error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl);
2365        if (unlikely(error <= 0))
2366                return error;
2367        error = 0;
2368out:
2369        return error;
2370}
2371
2372static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req,
2373                                   struct xdr_stream *xdr,
2374                                   struct nfs3_getaclres *result)
2375{
2376        enum nfs_stat status;
2377        int error;
2378
2379        error = decode_nfsstat3(xdr, &status);
2380        if (unlikely(error))
2381                goto out;
2382        if (status != NFS3_OK)
2383                goto out_default;
2384        error = decode_getacl3resok(xdr, result);
2385out:
2386        return error;
2387out_default:
2388        return nfs3_stat_to_errno(status);
2389}
2390
2391static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req,
2392                                   struct xdr_stream *xdr,
2393                                   struct nfs_fattr *result)
2394{
2395        enum nfs_stat status;
2396        int error;
2397
2398        error = decode_nfsstat3(xdr, &status);
2399        if (unlikely(error))
2400                goto out;
2401        if (status != NFS3_OK)
2402                goto out_default;
2403        error = decode_post_op_attr(xdr, result);
2404out:
2405        return error;
2406out_default:
2407        return nfs3_stat_to_errno(status);
2408}
2409
2410#endif  /* CONFIG_NFS_V3_ACL */
2411
2412
2413/*
2414 * We need to translate between nfs status return values and
2415 * the local errno values which may not be the same.
2416 */
2417static const struct {
2418        int stat;
2419        int errno;
2420} nfs_errtbl[] = {
2421        { NFS_OK,               0               },
2422        { NFSERR_PERM,          -EPERM          },
2423        { NFSERR_NOENT,         -ENOENT         },
2424        { NFSERR_IO,            -errno_NFSERR_IO},
2425        { NFSERR_NXIO,          -ENXIO          },
2426/*      { NFSERR_EAGAIN,        -EAGAIN         }, */
2427        { NFSERR_ACCES,         -EACCES         },
2428        { NFSERR_EXIST,         -EEXIST         },
2429        { NFSERR_XDEV,          -EXDEV          },
2430        { NFSERR_NODEV,         -ENODEV         },
2431        { NFSERR_NOTDIR,        -ENOTDIR        },
2432        { NFSERR_ISDIR,         -EISDIR         },
2433        { NFSERR_INVAL,         -EINVAL         },
2434        { NFSERR_FBIG,          -EFBIG          },
2435        { NFSERR_NOSPC,         -ENOSPC         },
2436        { NFSERR_ROFS,          -EROFS          },
2437        { NFSERR_MLINK,         -EMLINK         },
2438        { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
2439        { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
2440        { NFSERR_DQUOT,         -EDQUOT         },
2441        { NFSERR_STALE,         -ESTALE         },
2442        { NFSERR_REMOTE,        -EREMOTE        },
2443#ifdef EWFLUSH
2444        { NFSERR_WFLUSH,        -EWFLUSH        },
2445#endif
2446        { NFSERR_BADHANDLE,     -EBADHANDLE     },
2447        { NFSERR_NOT_SYNC,      -ENOTSYNC       },
2448        { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
2449        { NFSERR_NOTSUPP,       -ENOTSUPP       },
2450        { NFSERR_TOOSMALL,      -ETOOSMALL      },
2451        { NFSERR_SERVERFAULT,   -EREMOTEIO      },
2452        { NFSERR_BADTYPE,       -EBADTYPE       },
2453        { NFSERR_JUKEBOX,       -EJUKEBOX       },
2454        { -1,                   -EIO            }
2455};
2456
2457/**
2458 * nfs3_stat_to_errno - convert an NFS status code to a local errno
2459 * @status: NFS status code to convert
2460 *
2461 * Returns a local errno value, or -EIO if the NFS status code is
2462 * not recognized.  This function is used jointly by NFSv2 and NFSv3.
2463 */
2464static int nfs3_stat_to_errno(enum nfs_stat status)
2465{
2466        int i;
2467
2468        for (i = 0; nfs_errtbl[i].stat != -1; i++) {
2469                if (nfs_errtbl[i].stat == (int)status)
2470                        return nfs_errtbl[i].errno;
2471        }
2472        dprintk("NFS: Unrecognized nfs status value: %u\n", status);
2473        return nfs_errtbl[i].errno;
2474}
2475
2476
2477#define PROC(proc, argtype, restype, timer)                             \
2478[NFS3PROC_##proc] = {                                                   \
2479        .p_proc      = NFS3PROC_##proc,                                 \
2480        .p_encode    = (kxdreproc_t)nfs3_xdr_enc_##argtype##3args,      \
2481        .p_decode    = (kxdrdproc_t)nfs3_xdr_dec_##restype##3res,       \
2482        .p_arglen    = NFS3_##argtype##args_sz,                         \
2483        .p_replen    = NFS3_##restype##res_sz,                          \
2484        .p_timer     = timer,                                           \
2485        .p_statidx   = NFS3PROC_##proc,                                 \
2486        .p_name      = #proc,                                           \
2487        }
2488
2489struct rpc_procinfo     nfs3_procedures[] = {
2490        PROC(GETATTR,           getattr,        getattr,        1),
2491        PROC(SETATTR,           setattr,        setattr,        0),
2492        PROC(LOOKUP,            lookup,         lookup,         2),
2493        PROC(ACCESS,            access,         access,         1),
2494        PROC(READLINK,          readlink,       readlink,       3),
2495        PROC(READ,              read,           read,           3),
2496        PROC(WRITE,             write,          write,          4),
2497        PROC(CREATE,            create,         create,         0),
2498        PROC(MKDIR,             mkdir,          create,         0),
2499        PROC(SYMLINK,           symlink,        create,         0),
2500        PROC(MKNOD,             mknod,          create,         0),
2501        PROC(REMOVE,            remove,         remove,         0),
2502        PROC(RMDIR,             lookup,         setattr,        0),
2503        PROC(RENAME,            rename,         rename,         0),
2504        PROC(LINK,              link,           link,           0),
2505        PROC(READDIR,           readdir,        readdir,        3),
2506        PROC(READDIRPLUS,       readdirplus,    readdir,        3),
2507        PROC(FSSTAT,            getattr,        fsstat,         0),
2508        PROC(FSINFO,            getattr,        fsinfo,         0),
2509        PROC(PATHCONF,          getattr,        pathconf,       0),
2510        PROC(COMMIT,            commit,         commit,         5),
2511};
2512
2513const struct rpc_version nfs_version3 = {
2514        .number                 = 3,
2515        .nrprocs                = ARRAY_SIZE(nfs3_procedures),
2516        .procs                  = nfs3_procedures
2517};
2518
2519#ifdef CONFIG_NFS_V3_ACL
2520static struct rpc_procinfo      nfs3_acl_procedures[] = {
2521        [ACLPROC3_GETACL] = {
2522                .p_proc = ACLPROC3_GETACL,
2523                .p_encode = (kxdreproc_t)nfs3_xdr_enc_getacl3args,
2524                .p_decode = (kxdrdproc_t)nfs3_xdr_dec_getacl3res,
2525                .p_arglen = ACL3_getaclargs_sz,
2526                .p_replen = ACL3_getaclres_sz,
2527                .p_timer = 1,
2528                .p_name = "GETACL",
2529        },
2530        [ACLPROC3_SETACL] = {
2531                .p_proc = ACLPROC3_SETACL,
2532                .p_encode = (kxdreproc_t)nfs3_xdr_enc_setacl3args,
2533                .p_decode = (kxdrdproc_t)nfs3_xdr_dec_setacl3res,
2534                .p_arglen = ACL3_setaclargs_sz,
2535                .p_replen = ACL3_setaclres_sz,
2536                .p_timer = 0,
2537                .p_name = "SETACL",
2538        },
2539};
2540
2541const struct rpc_version nfsacl_version3 = {
2542        .number                 = 3,
2543        .nrprocs                = sizeof(nfs3_acl_procedures)/
2544                                  sizeof(nfs3_acl_procedures[0]),
2545        .procs                  = nfs3_acl_procedures,
2546};
2547#endif  /* CONFIG_NFS_V3_ACL */
2548
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.