linux/fs/nfs/nfs2xdr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * linux/fs/nfs/nfs2xdr.c
   4 *
   5 * XDR functions to encode/decode NFS RPC arguments and results.
   6 *
   7 * Copyright (C) 1992, 1993, 1994  Rick Sladkey
   8 * Copyright (C) 1996 Olaf Kirch
   9 * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>
  10 *              FIFO's need special handling in NFSv2
  11 */
  12
  13#include <linux/param.h>
  14#include <linux/time.h>
  15#include <linux/mm.h>
  16#include <linux/errno.h>
  17#include <linux/string.h>
  18#include <linux/in.h>
  19#include <linux/pagemap.h>
  20#include <linux/proc_fs.h>
  21#include <linux/sunrpc/clnt.h>
  22#include <linux/nfs.h>
  23#include <linux/nfs2.h>
  24#include <linux/nfs_fs.h>
  25#include "nfstrace.h"
  26#include "internal.h"
  27
  28#define NFSDBG_FACILITY         NFSDBG_XDR
  29
  30/* Mapping from NFS error code to "errno" error code. */
  31#define errno_NFSERR_IO         EIO
  32
  33/*
  34 * Declare the space requirements for NFS arguments and replies as
  35 * number of 32bit-words
  36 */
  37#define NFS_pagepad_sz          (1) /* Page padding */
  38#define NFS_fhandle_sz          (8)
  39#define NFS_sattr_sz            (8)
  40#define NFS_filename_sz         (1+(NFS2_MAXNAMLEN>>2))
  41#define NFS_path_sz             (1+(NFS2_MAXPATHLEN>>2))
  42#define NFS_fattr_sz            (17)
  43#define NFS_info_sz             (5)
  44#define NFS_entry_sz            (NFS_filename_sz+3)
  45
  46#define NFS_diropargs_sz        (NFS_fhandle_sz+NFS_filename_sz)
  47#define NFS_removeargs_sz       (NFS_fhandle_sz+NFS_filename_sz)
  48#define NFS_sattrargs_sz        (NFS_fhandle_sz+NFS_sattr_sz)
  49#define NFS_readlinkargs_sz     (NFS_fhandle_sz)
  50#define NFS_readargs_sz         (NFS_fhandle_sz+3)
  51#define NFS_writeargs_sz        (NFS_fhandle_sz+4)
  52#define NFS_createargs_sz       (NFS_diropargs_sz+NFS_sattr_sz)
  53#define NFS_renameargs_sz       (NFS_diropargs_sz+NFS_diropargs_sz)
  54#define NFS_linkargs_sz         (NFS_fhandle_sz+NFS_diropargs_sz)
  55#define NFS_symlinkargs_sz      (NFS_diropargs_sz+1+NFS_sattr_sz)
  56#define NFS_readdirargs_sz      (NFS_fhandle_sz+2)
  57
  58#define NFS_attrstat_sz         (1+NFS_fattr_sz)
  59#define NFS_diropres_sz         (1+NFS_fhandle_sz+NFS_fattr_sz)
  60#define NFS_readlinkres_sz      (2+NFS_pagepad_sz)
  61#define NFS_readres_sz          (1+NFS_fattr_sz+1+NFS_pagepad_sz)
  62#define NFS_writeres_sz         (NFS_attrstat_sz)
  63#define NFS_stat_sz             (1)
  64#define NFS_readdirres_sz       (1+NFS_pagepad_sz)
  65#define NFS_statfsres_sz        (1+NFS_info_sz)
  66
  67static int nfs_stat_to_errno(enum nfs_stat);
  68
  69/*
  70 * Encode/decode NFSv2 basic data types
  71 *
  72 * Basic NFSv2 data types are defined in section 2.3 of RFC 1094:
  73 * "NFS: Network File System Protocol Specification".
  74 *
  75 * Not all basic data types have their own encoding and decoding
  76 * functions.  For run-time efficiency, some data types are encoded
  77 * or decoded inline.
  78 */
  79
  80static struct user_namespace *rpc_userns(const struct rpc_clnt *clnt)
  81{
  82        if (clnt && clnt->cl_cred)
  83                return clnt->cl_cred->user_ns;
  84        return &init_user_ns;
  85}
  86
  87static struct user_namespace *rpc_rqst_userns(const struct rpc_rqst *rqstp)
  88{
  89        if (rqstp->rq_task)
  90                return rpc_userns(rqstp->rq_task->tk_client);
  91        return &init_user_ns;
  92}
  93
  94/*
  95 *      typedef opaque  nfsdata<>;
  96 */
  97static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result)
  98{
  99        u32 recvd, count;
 100        __be32 *p;
 101
 102        p = xdr_inline_decode(xdr, 4);
 103        if (unlikely(!p))
 104                return -EIO;
 105        count = be32_to_cpup(p);
 106        recvd = xdr_read_pages(xdr, count);
 107        if (unlikely(count > recvd))
 108                goto out_cheating;
 109out:
 110        result->eof = 0;        /* NFSv2 does not pass EOF flag on the wire. */
 111        result->count = count;
 112        return count;
 113out_cheating:
 114        dprintk("NFS: server cheating in read result: "
 115                "count %u > recvd %u\n", count, recvd);
 116        count = recvd;
 117        goto out;
 118}
 119
 120/*
 121 *      enum stat {
 122 *              NFS_OK = 0,
 123 *              NFSERR_PERM = 1,
 124 *              NFSERR_NOENT = 2,
 125 *              NFSERR_IO = 5,
 126 *              NFSERR_NXIO = 6,
 127 *              NFSERR_ACCES = 13,
 128 *              NFSERR_EXIST = 17,
 129 *              NFSERR_NODEV = 19,
 130 *              NFSERR_NOTDIR = 20,
 131 *              NFSERR_ISDIR = 21,
 132 *              NFSERR_FBIG = 27,
 133 *              NFSERR_NOSPC = 28,
 134 *              NFSERR_ROFS = 30,
 135 *              NFSERR_NAMETOOLONG = 63,
 136 *              NFSERR_NOTEMPTY = 66,
 137 *              NFSERR_DQUOT = 69,
 138 *              NFSERR_STALE = 70,
 139 *              NFSERR_WFLUSH = 99
 140 *      };
 141 */
 142static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
 143{
 144        __be32 *p;
 145
 146        p = xdr_inline_decode(xdr, 4);
 147        if (unlikely(!p))
 148                return -EIO;
 149        if (unlikely(*p != cpu_to_be32(NFS_OK)))
 150                goto out_status;
 151        *status = 0;
 152        return 0;
 153out_status:
 154        *status = be32_to_cpup(p);
 155        trace_nfs_xdr_status(xdr, (int)*status);
 156        return 0;
 157}
 158
 159/*
 160 * 2.3.2.  ftype
 161 *
 162 *      enum ftype {
 163 *              NFNON = 0,
 164 *              NFREG = 1,
 165 *              NFDIR = 2,
 166 *              NFBLK = 3,
 167 *              NFCHR = 4,
 168 *              NFLNK = 5
 169 *      };
 170 *
 171 */
 172static __be32 *xdr_decode_ftype(__be32 *p, u32 *type)
 173{
 174        *type = be32_to_cpup(p++);
 175        if (unlikely(*type > NF2FIFO))
 176                *type = NFBAD;
 177        return p;
 178}
 179
 180/*
 181 * 2.3.3.  fhandle
 182 *
 183 *      typedef opaque fhandle[FHSIZE];
 184 */
 185static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
 186{
 187        __be32 *p;
 188
 189        p = xdr_reserve_space(xdr, NFS2_FHSIZE);
 190        memcpy(p, fh->data, NFS2_FHSIZE);
 191}
 192
 193static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
 194{
 195        __be32 *p;
 196
 197        p = xdr_inline_decode(xdr, NFS2_FHSIZE);
 198        if (unlikely(!p))
 199                return -EIO;
 200        fh->size = NFS2_FHSIZE;
 201        memcpy(fh->data, p, NFS2_FHSIZE);
 202        return 0;
 203}
 204
 205/*
 206 * 2.3.4.  timeval
 207 *
 208 *      struct timeval {
 209 *              unsigned int seconds;
 210 *              unsigned int useconds;
 211 *      };
 212 */
 213static __be32 *xdr_encode_time(__be32 *p, const struct timespec64 *timep)
 214{
 215        *p++ = cpu_to_be32((u32)timep->tv_sec);
 216        if (timep->tv_nsec != 0)
 217                *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC);
 218        else
 219                *p++ = cpu_to_be32(0);
 220        return p;
 221}
 222
 223/*
 224 * Passing the invalid value useconds=1000000 is a Sun convention for
 225 * "set to current server time".  It's needed to make permissions checks
 226 * for the "touch" program across v2 mounts to Solaris and Irix servers
 227 * work correctly.  See description of sattr in section 6.1 of "NFS
 228 * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5.
 229 */
 230static __be32 *xdr_encode_current_server_time(__be32 *p,
 231                                              const struct timespec64 *timep)
 232{
 233        *p++ = cpu_to_be32(timep->tv_sec);
 234        *p++ = cpu_to_be32(1000000);
 235        return p;
 236}
 237
 238static __be32 *xdr_decode_time(__be32 *p, struct timespec64 *timep)
 239{
 240        timep->tv_sec = be32_to_cpup(p++);
 241        timep->tv_nsec = be32_to_cpup(p++) * NSEC_PER_USEC;
 242        return p;
 243}
 244
 245/*
 246 * 2.3.5.  fattr
 247 *
 248 *      struct fattr {
 249 *              ftype           type;
 250 *              unsigned int    mode;
 251 *              unsigned int    nlink;
 252 *              unsigned int    uid;
 253 *              unsigned int    gid;
 254 *              unsigned int    size;
 255 *              unsigned int    blocksize;
 256 *              unsigned int    rdev;
 257 *              unsigned int    blocks;
 258 *              unsigned int    fsid;
 259 *              unsigned int    fileid;
 260 *              timeval         atime;
 261 *              timeval         mtime;
 262 *              timeval         ctime;
 263 *      };
 264 *
 265 */
 266static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
 267                struct user_namespace *userns)
 268{
 269        u32 rdev, type;
 270        __be32 *p;
 271
 272        p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
 273        if (unlikely(!p))
 274                return -EIO;
 275
 276        fattr->valid |= NFS_ATTR_FATTR_V2;
 277
 278        p = xdr_decode_ftype(p, &type);
 279
 280        fattr->mode = be32_to_cpup(p++);
 281        fattr->nlink = be32_to_cpup(p++);
 282        fattr->uid = make_kuid(userns, be32_to_cpup(p++));
 283        if (!uid_valid(fattr->uid))
 284                goto out_uid;
 285        fattr->gid = make_kgid(userns, be32_to_cpup(p++));
 286        if (!gid_valid(fattr->gid))
 287                goto out_gid;
 288                
 289        fattr->size = be32_to_cpup(p++);
 290        fattr->du.nfs2.blocksize = be32_to_cpup(p++);
 291
 292        rdev = be32_to_cpup(p++);
 293        fattr->rdev = new_decode_dev(rdev);
 294        if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) {
 295                fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
 296                fattr->rdev = 0;
 297        }
 298
 299        fattr->du.nfs2.blocks = be32_to_cpup(p++);
 300        fattr->fsid.major = be32_to_cpup(p++);
 301        fattr->fsid.minor = 0;
 302        fattr->fileid = be32_to_cpup(p++);
 303
 304        p = xdr_decode_time(p, &fattr->atime);
 305        p = xdr_decode_time(p, &fattr->mtime);
 306        xdr_decode_time(p, &fattr->ctime);
 307        fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
 308
 309        return 0;
 310out_uid:
 311        dprintk("NFS: returned invalid uid\n");
 312        return -EINVAL;
 313out_gid:
 314        dprintk("NFS: returned invalid gid\n");
 315        return -EINVAL;
 316}
 317
 318/*
 319 * 2.3.6.  sattr
 320 *
 321 *      struct sattr {
 322 *              unsigned int    mode;
 323 *              unsigned int    uid;
 324 *              unsigned int    gid;
 325 *              unsigned int    size;
 326 *              timeval         atime;
 327 *              timeval         mtime;
 328 *      };
 329 */
 330
 331#define NFS2_SATTR_NOT_SET      (0xffffffff)
 332
 333static __be32 *xdr_time_not_set(__be32 *p)
 334{
 335        *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 336        *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 337        return p;
 338}
 339
 340static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr,
 341                struct user_namespace *userns)
 342{
 343        __be32 *p;
 344
 345        p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
 346
 347        if (attr->ia_valid & ATTR_MODE)
 348                *p++ = cpu_to_be32(attr->ia_mode);
 349        else
 350                *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 351        if (attr->ia_valid & ATTR_UID)
 352                *p++ = cpu_to_be32(from_kuid_munged(userns, attr->ia_uid));
 353        else
 354                *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 355        if (attr->ia_valid & ATTR_GID)
 356                *p++ = cpu_to_be32(from_kgid_munged(userns, attr->ia_gid));
 357        else
 358                *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 359        if (attr->ia_valid & ATTR_SIZE)
 360                *p++ = cpu_to_be32((u32)attr->ia_size);
 361        else
 362                *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 363
 364        if (attr->ia_valid & ATTR_ATIME_SET)
 365                p = xdr_encode_time(p, &attr->ia_atime);
 366        else if (attr->ia_valid & ATTR_ATIME)
 367                p = xdr_encode_current_server_time(p, &attr->ia_atime);
 368        else
 369                p = xdr_time_not_set(p);
 370        if (attr->ia_valid & ATTR_MTIME_SET)
 371                xdr_encode_time(p, &attr->ia_mtime);
 372        else if (attr->ia_valid & ATTR_MTIME)
 373                xdr_encode_current_server_time(p, &attr->ia_mtime);
 374        else
 375                xdr_time_not_set(p);
 376}
 377
 378/*
 379 * 2.3.7.  filename
 380 *
 381 *      typedef string filename<MAXNAMLEN>;
 382 */
 383static void encode_filename(struct xdr_stream *xdr,
 384                            const char *name, u32 length)
 385{
 386        __be32 *p;
 387
 388        WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
 389        p = xdr_reserve_space(xdr, 4 + length);
 390        xdr_encode_opaque(p, name, length);
 391}
 392
 393static int decode_filename_inline(struct xdr_stream *xdr,
 394                                  const char **name, u32 *length)
 395{
 396        __be32 *p;
 397        u32 count;
 398
 399        p = xdr_inline_decode(xdr, 4);
 400        if (unlikely(!p))
 401                return -EIO;
 402        count = be32_to_cpup(p);
 403        if (count > NFS3_MAXNAMLEN)
 404                goto out_nametoolong;
 405        p = xdr_inline_decode(xdr, count);
 406        if (unlikely(!p))
 407                return -EIO;
 408        *name = (const char *)p;
 409        *length = count;
 410        return 0;
 411out_nametoolong:
 412        dprintk("NFS: returned filename too long: %u\n", count);
 413        return -ENAMETOOLONG;
 414}
 415
 416/*
 417 * 2.3.8.  path
 418 *
 419 *      typedef string path<MAXPATHLEN>;
 420 */
 421static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
 422{
 423        __be32 *p;
 424
 425        p = xdr_reserve_space(xdr, 4);
 426        *p = cpu_to_be32(length);
 427        xdr_write_pages(xdr, pages, 0, length);
 428}
 429
 430static int decode_path(struct xdr_stream *xdr)
 431{
 432        u32 length, recvd;
 433        __be32 *p;
 434
 435        p = xdr_inline_decode(xdr, 4);
 436        if (unlikely(!p))
 437                return -EIO;
 438        length = be32_to_cpup(p);
 439        if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
 440                goto out_size;
 441        recvd = xdr_read_pages(xdr, length);
 442        if (unlikely(length > recvd))
 443                goto out_cheating;
 444        xdr_terminate_string(xdr->buf, length);
 445        return 0;
 446out_size:
 447        dprintk("NFS: returned pathname too long: %u\n", length);
 448        return -ENAMETOOLONG;
 449out_cheating:
 450        dprintk("NFS: server cheating in pathname result: "
 451                "length %u > received %u\n", length, recvd);
 452        return -EIO;
 453}
 454
 455/*
 456 * 2.3.9.  attrstat
 457 *
 458 *      union attrstat switch (stat status) {
 459 *      case NFS_OK:
 460 *              fattr attributes;
 461 *      default:
 462 *              void;
 463 *      };
 464 */
 465static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result,
 466                           __u32 *op_status,
 467                           struct user_namespace *userns)
 468{
 469        enum nfs_stat status;
 470        int error;
 471
 472        error = decode_stat(xdr, &status);
 473        if (unlikely(error))
 474                goto out;
 475        if (op_status)
 476                *op_status = status;
 477        if (status != NFS_OK)
 478                goto out_default;
 479        error = decode_fattr(xdr, result, userns);
 480out:
 481        return error;
 482out_default:
 483        return nfs_stat_to_errno(status);
 484}
 485
 486/*
 487 * 2.3.10.  diropargs
 488 *
 489 *      struct diropargs {
 490 *              fhandle  dir;
 491 *              filename name;
 492 *      };
 493 */
 494static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
 495                             const char *name, u32 length)
 496{
 497        encode_fhandle(xdr, fh);
 498        encode_filename(xdr, name, length);
 499}
 500
 501/*
 502 * 2.3.11.  diropres
 503 *
 504 *      union diropres switch (stat status) {
 505 *      case NFS_OK:
 506 *              struct {
 507 *                      fhandle file;
 508 *                      fattr   attributes;
 509 *              } diropok;
 510 *      default:
 511 *              void;
 512 *      };
 513 */
 514static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result,
 515                struct user_namespace *userns)
 516{
 517        int error;
 518
 519        error = decode_fhandle(xdr, result->fh);
 520        if (unlikely(error))
 521                goto out;
 522        error = decode_fattr(xdr, result->fattr, userns);
 523out:
 524        return error;
 525}
 526
 527static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result,
 528                struct user_namespace *userns)
 529{
 530        enum nfs_stat status;
 531        int error;
 532
 533        error = decode_stat(xdr, &status);
 534        if (unlikely(error))
 535                goto out;
 536        if (status != NFS_OK)
 537                goto out_default;
 538        error = decode_diropok(xdr, result, userns);
 539out:
 540        return error;
 541out_default:
 542        return nfs_stat_to_errno(status);
 543}
 544
 545
 546/*
 547 * NFSv2 XDR encode functions
 548 *
 549 * NFSv2 argument types are defined in section 2.2 of RFC 1094:
 550 * "NFS: Network File System Protocol Specification".
 551 */
 552
 553static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req,
 554                                 struct xdr_stream *xdr,
 555                                 const void *data)
 556{
 557        const struct nfs_fh *fh = data;
 558
 559        encode_fhandle(xdr, fh);
 560}
 561
 562/*
 563 * 2.2.3.  sattrargs
 564 *
 565 *      struct sattrargs {
 566 *              fhandle file;
 567 *              sattr attributes;
 568 *      };
 569 */
 570static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
 571                                   struct xdr_stream *xdr,
 572                                   const void *data)
 573{
 574        const struct nfs_sattrargs *args = data;
 575
 576        encode_fhandle(xdr, args->fh);
 577        encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
 578}
 579
 580static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
 581                                   struct xdr_stream *xdr,
 582                                   const void *data)
 583{
 584        const struct nfs_diropargs *args = data;
 585
 586        encode_diropargs(xdr, args->fh, args->name, args->len);
 587}
 588
 589static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
 590                                      struct xdr_stream *xdr,
 591                                      const void *data)
 592{
 593        const struct nfs_readlinkargs *args = data;
 594
 595        encode_fhandle(xdr, args->fh);
 596        rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->pglen,
 597                                NFS_readlinkres_sz - NFS_pagepad_sz);
 598}
 599
 600/*
 601 * 2.2.7.  readargs
 602 *
 603 *      struct readargs {
 604 *              fhandle file;
 605 *              unsigned offset;
 606 *              unsigned count;
 607 *              unsigned totalcount;
 608 *      };
 609 */
 610static void encode_readargs(struct xdr_stream *xdr,
 611                            const struct nfs_pgio_args *args)
 612{
 613        u32 offset = args->offset;
 614        u32 count = args->count;
 615        __be32 *p;
 616
 617        encode_fhandle(xdr, args->fh);
 618
 619        p = xdr_reserve_space(xdr, 4 + 4 + 4);
 620        *p++ = cpu_to_be32(offset);
 621        *p++ = cpu_to_be32(count);
 622        *p = cpu_to_be32(count);
 623}
 624
 625static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
 626                                  struct xdr_stream *xdr,
 627                                  const void *data)
 628{
 629        const struct nfs_pgio_args *args = data;
 630
 631        encode_readargs(xdr, args);
 632        rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
 633                                NFS_readres_sz - NFS_pagepad_sz);
 634        req->rq_rcv_buf.flags |= XDRBUF_READ;
 635}
 636
 637/*
 638 * 2.2.9.  writeargs
 639 *
 640 *      struct writeargs {
 641 *              fhandle file;
 642 *              unsigned beginoffset;
 643 *              unsigned offset;
 644 *              unsigned totalcount;
 645 *              nfsdata data;
 646 *      };
 647 */
 648static void encode_writeargs(struct xdr_stream *xdr,
 649                             const struct nfs_pgio_args *args)
 650{
 651        u32 offset = args->offset;
 652        u32 count = args->count;
 653        __be32 *p;
 654
 655        encode_fhandle(xdr, args->fh);
 656
 657        p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
 658        *p++ = cpu_to_be32(offset);
 659        *p++ = cpu_to_be32(offset);
 660        *p++ = cpu_to_be32(count);
 661
 662        /* nfsdata */
 663        *p = cpu_to_be32(count);
 664        xdr_write_pages(xdr, args->pages, args->pgbase, count);
 665}
 666
 667static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
 668                                   struct xdr_stream *xdr,
 669                                   const void *data)
 670{
 671        const struct nfs_pgio_args *args = data;
 672
 673        encode_writeargs(xdr, args);
 674        xdr->buf->flags |= XDRBUF_WRITE;
 675}
 676
 677/*
 678 * 2.2.10.  createargs
 679 *
 680 *      struct createargs {
 681 *              diropargs where;
 682 *              sattr attributes;
 683 *      };
 684 */
 685static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
 686                                    struct xdr_stream *xdr,
 687                                    const void *data)
 688{
 689        const struct nfs_createargs *args = data;
 690
 691        encode_diropargs(xdr, args->fh, args->name, args->len);
 692        encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
 693}
 694
 695static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
 696                                    struct xdr_stream *xdr,
 697                                    const void *data)
 698{
 699        const struct nfs_removeargs *args = data;
 700
 701        encode_diropargs(xdr, args->fh, args->name.name, args->name.len);
 702}
 703
 704/*
 705 * 2.2.12.  renameargs
 706 *
 707 *      struct renameargs {
 708 *              diropargs from;
 709 *              diropargs to;
 710 *      };
 711 */
 712static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req,
 713                                    struct xdr_stream *xdr,
 714                                    const void *data)
 715{
 716        const struct nfs_renameargs *args = data;
 717        const struct qstr *old = args->old_name;
 718        const struct qstr *new = args->new_name;
 719
 720        encode_diropargs(xdr, args->old_dir, old->name, old->len);
 721        encode_diropargs(xdr, args->new_dir, new->name, new->len);
 722}
 723
 724/*
 725 * 2.2.13.  linkargs
 726 *
 727 *      struct linkargs {
 728 *              fhandle from;
 729 *              diropargs to;
 730 *      };
 731 */
 732static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req,
 733                                  struct xdr_stream *xdr,
 734                                  const void *data)
 735{
 736        const struct nfs_linkargs *args = data;
 737
 738        encode_fhandle(xdr, args->fromfh);
 739        encode_diropargs(xdr, args->tofh, args->toname, args->tolen);
 740}
 741
 742/*
 743 * 2.2.14.  symlinkargs
 744 *
 745 *      struct symlinkargs {
 746 *              diropargs from;
 747 *              path to;
 748 *              sattr attributes;
 749 *      };
 750 */
 751static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
 752                                     struct xdr_stream *xdr,
 753                                     const void *data)
 754{
 755        const struct nfs_symlinkargs *args = data;
 756
 757        encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
 758        encode_path(xdr, args->pages, args->pathlen);
 759        encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
 760}
 761
 762/*
 763 * 2.2.17.  readdirargs
 764 *
 765 *      struct readdirargs {
 766 *              fhandle dir;
 767 *              nfscookie cookie;
 768 *              unsigned count;
 769 *      };
 770 */
 771static void encode_readdirargs(struct xdr_stream *xdr,
 772                               const struct nfs_readdirargs *args)
 773{
 774        __be32 *p;
 775
 776        encode_fhandle(xdr, args->fh);
 777
 778        p = xdr_reserve_space(xdr, 4 + 4);
 779        *p++ = cpu_to_be32(args->cookie);
 780        *p = cpu_to_be32(args->count);
 781}
 782
 783static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
 784                                     struct xdr_stream *xdr,
 785                                     const void *data)
 786{
 787        const struct nfs_readdirargs *args = data;
 788
 789        encode_readdirargs(xdr, args);
 790        rpc_prepare_reply_pages(req, args->pages, 0, args->count,
 791                                NFS_readdirres_sz - NFS_pagepad_sz);
 792}
 793
 794/*
 795 * NFSv2 XDR decode functions
 796 *
 797 * NFSv2 result types are defined in section 2.2 of RFC 1094:
 798 * "NFS: Network File System Protocol Specification".
 799 */
 800
 801static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
 802                             void *__unused)
 803{
 804        enum nfs_stat status;
 805        int error;
 806
 807        error = decode_stat(xdr, &status);
 808        if (unlikely(error))
 809                goto out;
 810        if (status != NFS_OK)
 811                goto out_default;
 812out:
 813        return error;
 814out_default:
 815        return nfs_stat_to_errno(status);
 816}
 817
 818static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
 819                                 void *result)
 820{
 821        return decode_attrstat(xdr, result, NULL, rpc_rqst_userns(req));
 822}
 823
 824static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
 825                                 void *result)
 826{
 827        return decode_diropres(xdr, result, rpc_rqst_userns(req));
 828}
 829
 830/*
 831 * 2.2.6.  readlinkres
 832 *
 833 *      union readlinkres switch (stat status) {
 834 *      case NFS_OK:
 835 *              path data;
 836 *      default:
 837 *              void;
 838 *      };
 839 */
 840static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req,
 841                                    struct xdr_stream *xdr, void *__unused)
 842{
 843        enum nfs_stat status;
 844        int error;
 845
 846        error = decode_stat(xdr, &status);
 847        if (unlikely(error))
 848                goto out;
 849        if (status != NFS_OK)
 850                goto out_default;
 851        error = decode_path(xdr);
 852out:
 853        return error;
 854out_default:
 855        return nfs_stat_to_errno(status);
 856}
 857
 858/*
 859 * 2.2.7.  readres
 860 *
 861 *      union readres switch (stat status) {
 862 *      case NFS_OK:
 863 *              fattr attributes;
 864 *              nfsdata data;
 865 *      default:
 866 *              void;
 867 *      };
 868 */
 869static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
 870                                void *data)
 871{
 872        struct nfs_pgio_res *result = data;
 873        enum nfs_stat status;
 874        int error;
 875
 876        error = decode_stat(xdr, &status);
 877        if (unlikely(error))
 878                goto out;
 879        result->op_status = status;
 880        if (status != NFS_OK)
 881                goto out_default;
 882        error = decode_fattr(xdr, result->fattr, rpc_rqst_userns(req));
 883        if (unlikely(error))
 884                goto out;
 885        error = decode_nfsdata(xdr, result);
 886out:
 887        return error;
 888out_default:
 889        return nfs_stat_to_errno(status);
 890}
 891
 892static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
 893                                 void *data)
 894{
 895        struct nfs_pgio_res *result = data;
 896
 897        /* All NFSv2 writes are "file sync" writes */
 898        result->verf->committed = NFS_FILE_SYNC;
 899        return decode_attrstat(xdr, result->fattr, &result->op_status,
 900                        rpc_rqst_userns(req));
 901}
 902
 903/**
 904 * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
 905 *                      the local page cache.
 906 * @xdr: XDR stream where entry resides
 907 * @entry: buffer to fill in with entry data
 908 * @plus: boolean indicating whether this should be a readdirplus entry
 909 *
 910 * Returns zero if successful, otherwise a negative errno value is
 911 * returned.
 912 *
 913 * This function is not invoked during READDIR reply decoding, but
 914 * rather whenever an application invokes the getdents(2) system call
 915 * on a directory already in our cache.
 916 *
 917 * 2.2.17.  entry
 918 *
 919 *      struct entry {
 920 *              unsigned        fileid;
 921 *              filename        name;
 922 *              nfscookie       cookie;
 923 *              entry           *nextentry;
 924 *      };
 925 */
 926int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
 927                       bool plus)
 928{
 929        __be32 *p;
 930        int error;
 931
 932        p = xdr_inline_decode(xdr, 4);
 933        if (unlikely(!p))
 934                return -EAGAIN;
 935        if (*p++ == xdr_zero) {
 936                p = xdr_inline_decode(xdr, 4);
 937                if (unlikely(!p))
 938                        return -EAGAIN;
 939                if (*p++ == xdr_zero)
 940                        return -EAGAIN;
 941                entry->eof = 1;
 942                return -EBADCOOKIE;
 943        }
 944
 945        p = xdr_inline_decode(xdr, 4);
 946        if (unlikely(!p))
 947                return -EAGAIN;
 948        entry->ino = be32_to_cpup(p);
 949
 950        error = decode_filename_inline(xdr, &entry->name, &entry->len);
 951        if (unlikely(error))
 952                return error;
 953
 954        /*
 955         * The type (size and byte order) of nfscookie isn't defined in
 956         * RFC 1094.  This implementation assumes that it's an XDR uint32.
 957         */
 958        entry->prev_cookie = entry->cookie;
 959        p = xdr_inline_decode(xdr, 4);
 960        if (unlikely(!p))
 961                return -EAGAIN;
 962        entry->cookie = be32_to_cpup(p);
 963
 964        entry->d_type = DT_UNKNOWN;
 965
 966        return 0;
 967}
 968
 969/*
 970 * 2.2.17.  readdirres
 971 *
 972 *      union readdirres switch (stat status) {
 973 *      case NFS_OK:
 974 *              struct {
 975 *                      entry *entries;
 976 *                      bool eof;
 977 *              } readdirok;
 978 *      default:
 979 *              void;
 980 *      };
 981 *
 982 * Read the directory contents into the page cache, but don't
 983 * touch them.  The actual decoding is done by nfs2_decode_dirent()
 984 * during subsequent nfs_readdir() calls.
 985 */
 986static int decode_readdirok(struct xdr_stream *xdr)
 987{
 988        return xdr_read_pages(xdr, xdr->buf->page_len);
 989}
 990
 991static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
 992                                   struct xdr_stream *xdr, void *__unused)
 993{
 994        enum nfs_stat status;
 995        int error;
 996
 997        error = decode_stat(xdr, &status);
 998        if (unlikely(error))
 999                goto out;
1000        if (status != NFS_OK)
1001                goto out_default;
1002        error = decode_readdirok(xdr);
1003out:
1004        return error;
1005out_default:
1006        return nfs_stat_to_errno(status);
1007}
1008
1009/*
1010 * 2.2.18.  statfsres
1011 *
1012 *      union statfsres (stat status) {
1013 *      case NFS_OK:
1014 *              struct {
1015 *                      unsigned tsize;
1016 *                      unsigned bsize;
1017 *                      unsigned blocks;
1018 *                      unsigned bfree;
1019 *                      unsigned bavail;
1020 *              } info;
1021 *      default:
1022 *              void;
1023 *      };
1024 */
1025static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1026{
1027        __be32 *p;
1028
1029        p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1030        if (unlikely(!p))
1031                return -EIO;
1032        result->tsize  = be32_to_cpup(p++);
1033        result->bsize  = be32_to_cpup(p++);
1034        result->blocks = be32_to_cpup(p++);
1035        result->bfree  = be32_to_cpup(p++);
1036        result->bavail = be32_to_cpup(p);
1037        return 0;
1038}
1039
1040static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
1041                                  void *result)
1042{
1043        enum nfs_stat status;
1044        int error;
1045
1046        error = decode_stat(xdr, &status);
1047        if (unlikely(error))
1048                goto out;
1049        if (status != NFS_OK)
1050                goto out_default;
1051        error = decode_info(xdr, result);
1052out:
1053        return error;
1054out_default:
1055        return nfs_stat_to_errno(status);
1056}
1057
1058
1059/*
1060 * We need to translate between nfs status return values and
1061 * the local errno values which may not be the same.
1062 */
1063static const struct {
1064        int stat;
1065        int errno;
1066} nfs_errtbl[] = {
1067        { NFS_OK,               0               },
1068        { NFSERR_PERM,          -EPERM          },
1069        { NFSERR_NOENT,         -ENOENT         },
1070        { NFSERR_IO,            -errno_NFSERR_IO},
1071        { NFSERR_NXIO,          -ENXIO          },
1072/*      { NFSERR_EAGAIN,        -EAGAIN         }, */
1073        { NFSERR_ACCES,         -EACCES         },
1074        { NFSERR_EXIST,         -EEXIST         },
1075        { NFSERR_XDEV,          -EXDEV          },
1076        { NFSERR_NODEV,         -ENODEV         },
1077        { NFSERR_NOTDIR,        -ENOTDIR        },
1078        { NFSERR_ISDIR,         -EISDIR         },
1079        { NFSERR_INVAL,         -EINVAL         },
1080        { NFSERR_FBIG,          -EFBIG          },
1081        { NFSERR_NOSPC,         -ENOSPC         },
1082        { NFSERR_ROFS,          -EROFS          },
1083        { NFSERR_MLINK,         -EMLINK         },
1084        { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
1085        { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
1086        { NFSERR_DQUOT,         -EDQUOT         },
1087        { NFSERR_STALE,         -ESTALE         },
1088        { NFSERR_REMOTE,        -EREMOTE        },
1089#ifdef EWFLUSH
1090        { NFSERR_WFLUSH,        -EWFLUSH        },
1091#endif
1092        { NFSERR_BADHANDLE,     -EBADHANDLE     },
1093        { NFSERR_NOT_SYNC,      -ENOTSYNC       },
1094        { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
1095        { NFSERR_NOTSUPP,       -ENOTSUPP       },
1096        { NFSERR_TOOSMALL,      -ETOOSMALL      },
1097        { NFSERR_SERVERFAULT,   -EREMOTEIO      },
1098        { NFSERR_BADTYPE,       -EBADTYPE       },
1099        { NFSERR_JUKEBOX,       -EJUKEBOX       },
1100        { -1,                   -EIO            }
1101};
1102
1103/**
1104 * nfs_stat_to_errno - convert an NFS status code to a local errno
1105 * @status: NFS status code to convert
1106 *
1107 * Returns a local errno value, or -EIO if the NFS status code is
1108 * not recognized.  This function is used jointly by NFSv2 and NFSv3.
1109 */
1110static int nfs_stat_to_errno(enum nfs_stat status)
1111{
1112        int i;
1113
1114        for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1115                if (nfs_errtbl[i].stat == (int)status)
1116                        return nfs_errtbl[i].errno;
1117        }
1118        dprintk("NFS: Unrecognized nfs status value: %u\n", status);
1119        return nfs_errtbl[i].errno;
1120}
1121
1122#define PROC(proc, argtype, restype, timer)                             \
1123[NFSPROC_##proc] = {                                                    \
1124        .p_proc     =  NFSPROC_##proc,                                  \
1125        .p_encode   =  nfs2_xdr_enc_##argtype,                          \
1126        .p_decode   =  nfs2_xdr_dec_##restype,                          \
1127        .p_arglen   =  NFS_##argtype##_sz,                              \
1128        .p_replen   =  NFS_##restype##_sz,                              \
1129        .p_timer    =  timer,                                           \
1130        .p_statidx  =  NFSPROC_##proc,                                  \
1131        .p_name     =  #proc,                                           \
1132        }
1133const struct rpc_procinfo nfs_procedures[] = {
1134        PROC(GETATTR,   fhandle,        attrstat,       1),
1135        PROC(SETATTR,   sattrargs,      attrstat,       0),
1136        PROC(LOOKUP,    diropargs,      diropres,       2),
1137        PROC(READLINK,  readlinkargs,   readlinkres,    3),
1138        PROC(READ,      readargs,       readres,        3),
1139        PROC(WRITE,     writeargs,      writeres,       4),
1140        PROC(CREATE,    createargs,     diropres,       0),
1141        PROC(REMOVE,    removeargs,     stat,           0),
1142        PROC(RENAME,    renameargs,     stat,           0),
1143        PROC(LINK,      linkargs,       stat,           0),
1144        PROC(SYMLINK,   symlinkargs,    stat,           0),
1145        PROC(MKDIR,     createargs,     diropres,       0),
1146        PROC(RMDIR,     diropargs,      stat,           0),
1147        PROC(READDIR,   readdirargs,    readdirres,     3),
1148        PROC(STATFS,    fhandle,        statfsres,      0),
1149};
1150
1151static unsigned int nfs_version2_counts[ARRAY_SIZE(nfs_procedures)];
1152const struct rpc_version nfs_version2 = {
1153        .number                 = 2,
1154        .nrprocs                = ARRAY_SIZE(nfs_procedures),
1155        .procs                  = nfs_procedures,
1156        .counts                 = nfs_version2_counts,
1157};
1158