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