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/slab.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 "internal.h"
  26
  27#define NFSDBG_FACILITY         NFSDBG_XDR
  28
  29/* Mapping from NFS error code to "errno" error code. */
  30#define errno_NFSERR_IO         EIO
  31
  32/*
  33 * Declare the space requirements for NFS arguments and replies as
  34 * number of 32bit-words
  35 */
  36#define NFS_fhandle_sz          (8)
  37#define NFS_sattr_sz            (8)
  38#define NFS_filename_sz         (1+(NFS2_MAXNAMLEN>>2))
  39#define NFS_path_sz             (1+(NFS2_MAXPATHLEN>>2))
  40#define NFS_fattr_sz            (17)
  41#define NFS_info_sz             (5)
  42#define NFS_entry_sz            (NFS_filename_sz+3)
  43
  44#define NFS_diropargs_sz        (NFS_fhandle_sz+NFS_filename_sz)
  45#define NFS_removeargs_sz       (NFS_fhandle_sz+NFS_filename_sz)
  46#define NFS_sattrargs_sz        (NFS_fhandle_sz+NFS_sattr_sz)
  47#define NFS_readlinkargs_sz     (NFS_fhandle_sz)
  48#define NFS_readargs_sz         (NFS_fhandle_sz+3)
  49#define NFS_writeargs_sz        (NFS_fhandle_sz+4)
  50#define NFS_createargs_sz       (NFS_diropargs_sz+NFS_sattr_sz)
  51#define NFS_renameargs_sz       (NFS_diropargs_sz+NFS_diropargs_sz)
  52#define NFS_linkargs_sz         (NFS_fhandle_sz+NFS_diropargs_sz)
  53#define NFS_symlinkargs_sz      (NFS_diropargs_sz+1+NFS_sattr_sz)
  54#define NFS_readdirargs_sz      (NFS_fhandle_sz+2)
  55
  56#define NFS_attrstat_sz         (1+NFS_fattr_sz)
  57#define NFS_diropres_sz         (1+NFS_fhandle_sz+NFS_fattr_sz)
  58#define NFS_readlinkres_sz      (2)
  59#define NFS_readres_sz          (1+NFS_fattr_sz+1)
  60#define NFS_writeres_sz         (NFS_attrstat_sz)
  61#define NFS_stat_sz             (1)
  62#define NFS_readdirres_sz       (1)
  63#define NFS_statfsres_sz        (1+NFS_info_sz)
  64
  65/*
  66 * Common NFS XDR functions as inlines
  67 */
  68static inline __be32 *
  69xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fhandle)
  70{
  71        memcpy(p, fhandle->data, NFS2_FHSIZE);
  72        return p + XDR_QUADLEN(NFS2_FHSIZE);
  73}
  74
  75static inline __be32 *
  76xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle)
  77{
  78        /* NFSv2 handles have a fixed length */
  79        fhandle->size = NFS2_FHSIZE;
  80        memcpy(fhandle->data, p, NFS2_FHSIZE);
  81        return p + XDR_QUADLEN(NFS2_FHSIZE);
  82}
  83
  84static inline __be32*
  85xdr_encode_time(__be32 *p, struct timespec *timep)
  86{
  87        *p++ = htonl(timep->tv_sec);
  88        /* Convert nanoseconds into microseconds */
  89        *p++ = htonl(timep->tv_nsec ? timep->tv_nsec / 1000 : 0);
  90        return p;
  91}
  92
  93static inline __be32*
  94xdr_encode_current_server_time(__be32 *p, struct timespec *timep)
  95{
  96        /*
  97         * Passing the invalid value useconds=1000000 is a
  98         * Sun convention for "set to current server time".
  99         * It's needed to make permissions checks for the
 100         * "touch" program across v2 mounts to Solaris and
 101         * Irix boxes work correctly. See description of
 102         * sattr in section 6.1 of "NFS Illustrated" by
 103         * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
 104         */
 105        *p++ = htonl(timep->tv_sec);
 106        *p++ = htonl(1000000);
 107        return p;
 108}
 109
 110static inline __be32*
 111xdr_decode_time(__be32 *p, struct timespec *timep)
 112{
 113        timep->tv_sec = ntohl(*p++);
 114        /* Convert microseconds into nanoseconds */
 115        timep->tv_nsec = ntohl(*p++) * 1000;
 116        return p;
 117}
 118
 119static __be32 *
 120xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
 121{
 122        u32 rdev, type;
 123        type = ntohl(*p++);
 124        fattr->mode = ntohl(*p++);
 125        fattr->nlink = ntohl(*p++);
 126        fattr->uid = ntohl(*p++);
 127        fattr->gid = ntohl(*p++);
 128        fattr->size = ntohl(*p++);
 129        fattr->du.nfs2.blocksize = ntohl(*p++);
 130        rdev = ntohl(*p++);
 131        fattr->du.nfs2.blocks = ntohl(*p++);
 132        fattr->fsid.major = ntohl(*p++);
 133        fattr->fsid.minor = 0;
 134        fattr->fileid = ntohl(*p++);
 135        p = xdr_decode_time(p, &fattr->atime);
 136        p = xdr_decode_time(p, &fattr->mtime);
 137        p = xdr_decode_time(p, &fattr->ctime);
 138        fattr->valid |= NFS_ATTR_FATTR_V2;
 139        fattr->rdev = new_decode_dev(rdev);
 140        if (type == NFCHR && rdev == NFS2_FIFO_DEV) {
 141                fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
 142                fattr->rdev = 0;
 143        }
 144        return p;
 145}
 146
 147static inline __be32 *
 148xdr_encode_sattr(__be32 *p, struct iattr *attr)
 149{
 150        const __be32 not_set = __constant_htonl(0xFFFFFFFF);
 151
 152        *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
 153        *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
 154        *p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set;
 155        *p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set;
 156
 157        if (attr->ia_valid & ATTR_ATIME_SET) {
 158                p = xdr_encode_time(p, &attr->ia_atime);
 159        } else if (attr->ia_valid & ATTR_ATIME) {
 160                p = xdr_encode_current_server_time(p, &attr->ia_atime);
 161        } else {
 162                *p++ = not_set;
 163                *p++ = not_set;
 164        }
 165
 166        if (attr->ia_valid & ATTR_MTIME_SET) {
 167                p = xdr_encode_time(p, &attr->ia_mtime);
 168        } else if (attr->ia_valid & ATTR_MTIME) {
 169                p = xdr_encode_current_server_time(p, &attr->ia_mtime);
 170        } else {
 171                *p++ = not_set; 
 172                *p++ = not_set;
 173        }
 174        return p;
 175}
 176
 177/*
 178 * NFS encode functions
 179 */
 180/*
 181 * Encode file handle argument
 182 * GETATTR, READLINK, STATFS
 183 */
 184static int
 185nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
 186{
 187        p = xdr_encode_fhandle(p, fh);
 188        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 189        return 0;
 190}
 191
 192/*
 193 * Encode SETATTR arguments
 194 */
 195static int
 196nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
 197{
 198        p = xdr_encode_fhandle(p, args->fh);
 199        p = xdr_encode_sattr(p, args->sattr);
 200        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 201        return 0;
 202}
 203
 204/*
 205 * Encode directory ops argument
 206 * LOOKUP, RMDIR
 207 */
 208static int
 209nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
 210{
 211        p = xdr_encode_fhandle(p, args->fh);
 212        p = xdr_encode_array(p, args->name, args->len);
 213        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 214        return 0;
 215}
 216
 217/*
 218 * Encode REMOVE argument
 219 */
 220static int
 221nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
 222{
 223        p = xdr_encode_fhandle(p, args->fh);
 224        p = xdr_encode_array(p, args->name.name, args->name.len);
 225        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 226        return 0;
 227}
 228
 229/*
 230 * Arguments to a READ call. Since we read data directly into the page
 231 * cache, we also set up the reply iovec here so that iov[1] points
 232 * exactly to the page we want to fetch.
 233 */
 234static int
 235nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
 236{
 237        struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 238        unsigned int replen;
 239        u32 offset = (u32)args->offset;
 240        u32 count = args->count;
 241
 242        p = xdr_encode_fhandle(p, args->fh);
 243        *p++ = htonl(offset);
 244        *p++ = htonl(count);
 245        *p++ = htonl(count);
 246        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 247
 248        /* Inline the page array */
 249        replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
 250        xdr_inline_pages(&req->rq_rcv_buf, replen,
 251                         args->pages, args->pgbase, count);
 252        req->rq_rcv_buf.flags |= XDRBUF_READ;
 253        return 0;
 254}
 255
 256/*
 257 * Decode READ reply
 258 */
 259static int
 260nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
 261{
 262        struct kvec *iov = req->rq_rcv_buf.head;
 263        size_t hdrlen;
 264        u32 count, recvd;
 265        int status;
 266
 267        if ((status = ntohl(*p++)))
 268                return nfs_stat_to_errno(status);
 269        p = xdr_decode_fattr(p, res->fattr);
 270
 271        count = ntohl(*p++);
 272        res->eof = 0;
 273        hdrlen = (u8 *) p - (u8 *) iov->iov_base;
 274        if (iov->iov_len < hdrlen) {
 275                dprintk("NFS: READ reply header overflowed:"
 276                                "length %Zu > %Zu\n", hdrlen, iov->iov_len);
 277                return -errno_NFSERR_IO;
 278        } else if (iov->iov_len != hdrlen) {
 279                dprintk("NFS: READ header is short. iovec will be shifted.\n");
 280                xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
 281        }
 282
 283        recvd = req->rq_rcv_buf.len - hdrlen;
 284        if (count > recvd) {
 285                dprintk("NFS: server cheating in read reply: "
 286                        "count %u > recvd %u\n", count, recvd);
 287                count = recvd;
 288        }
 289
 290        dprintk("RPC:      readres OK count %u\n", count);
 291        if (count < res->count)
 292                res->count = count;
 293
 294        return count;
 295}
 296
 297
 298/*
 299 * Write arguments. Splice the buffer to be written into the iovec.
 300 */
 301static int
 302nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
 303{
 304        struct xdr_buf *sndbuf = &req->rq_snd_buf;
 305        u32 offset = (u32)args->offset;
 306        u32 count = args->count;
 307
 308        p = xdr_encode_fhandle(p, args->fh);
 309        *p++ = htonl(offset);
 310        *p++ = htonl(offset);
 311        *p++ = htonl(count);
 312        *p++ = htonl(count);
 313        sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
 314
 315        /* Copy the page array */
 316        xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
 317        sndbuf->flags |= XDRBUF_WRITE;
 318        return 0;
 319}
 320
 321/*
 322 * Encode create arguments
 323 * CREATE, MKDIR
 324 */
 325static int
 326nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
 327{
 328        p = xdr_encode_fhandle(p, args->fh);
 329        p = xdr_encode_array(p, args->name, args->len);
 330        p = xdr_encode_sattr(p, args->sattr);
 331        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 332        return 0;
 333}
 334
 335/*
 336 * Encode RENAME arguments
 337 */
 338static int
 339nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 340{
 341        p = xdr_encode_fhandle(p, args->fromfh);
 342        p = xdr_encode_array(p, args->fromname, args->fromlen);
 343        p = xdr_encode_fhandle(p, args->tofh);
 344        p = xdr_encode_array(p, args->toname, args->tolen);
 345        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 346        return 0;
 347}
 348
 349/*
 350 * Encode LINK arguments
 351 */
 352static int
 353nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args)
 354{
 355        p = xdr_encode_fhandle(p, args->fromfh);
 356        p = xdr_encode_fhandle(p, args->tofh);
 357        p = xdr_encode_array(p, args->toname, args->tolen);
 358        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 359        return 0;
 360}
 361
 362/*
 363 * Encode SYMLINK arguments
 364 */
 365static int
 366nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args)
 367{
 368        struct xdr_buf *sndbuf = &req->rq_snd_buf;
 369        size_t pad;
 370
 371        p = xdr_encode_fhandle(p, args->fromfh);
 372        p = xdr_encode_array(p, args->fromname, args->fromlen);
 373        *p++ = htonl(args->pathlen);
 374        sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
 375
 376        xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen);
 377
 378        /*
 379         * xdr_encode_pages may have added a few bytes to ensure the
 380         * pathname ends on a 4-byte boundary.  Start encoding the
 381         * attributes after the pad bytes.
 382         */
 383        pad = sndbuf->tail->iov_len;
 384        if (pad > 0)
 385                p++;
 386        p = xdr_encode_sattr(p, args->sattr);
 387        sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad;
 388        return 0;
 389}
 390
 391/*
 392 * Encode arguments to readdir call
 393 */
 394static int
 395nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
 396{
 397        struct rpc_task *task = req->rq_task;
 398        struct rpc_auth *auth = task->tk_msg.rpc_cred->cr_auth;
 399        unsigned int replen;
 400        u32 count = args->count;
 401
 402        p = xdr_encode_fhandle(p, args->fh);
 403        *p++ = htonl(args->cookie);
 404        *p++ = htonl(count); /* see above */
 405        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 406
 407        /* Inline the page array */
 408        replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
 409        xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
 410        return 0;
 411}
 412
 413/*
 414 * Decode the result of a readdir call.
 415 * We're not really decoding anymore, we just leave the buffer untouched
 416 * and only check that it is syntactically correct.
 417 * The real decoding happens in nfs_decode_entry below, called directly
 418 * from nfs_readdir for each entry.
 419 */
 420static int
 421nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
 422{
 423        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 424        struct kvec *iov = rcvbuf->head;
 425        struct page **page;
 426        size_t hdrlen;
 427        unsigned int pglen, recvd;
 428        u32 len;
 429        int status, nr = 0;
 430        __be32 *end, *entry, *kaddr;
 431
 432        if ((status = ntohl(*p++)))
 433                return nfs_stat_to_errno(status);
 434
 435        hdrlen = (u8 *) p - (u8 *) iov->iov_base;
 436        if (iov->iov_len < hdrlen) {
 437                dprintk("NFS: READDIR reply header overflowed:"
 438                                "length %Zu > %Zu\n", hdrlen, iov->iov_len);
 439                return -errno_NFSERR_IO;
 440        } else if (iov->iov_len != hdrlen) {
 441                dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
 442                xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
 443        }
 444
 445        pglen = rcvbuf->page_len;
 446        recvd = rcvbuf->len - hdrlen;
 447        if (pglen > recvd)
 448                pglen = recvd;
 449        page = rcvbuf->pages;
 450        kaddr = p = kmap_atomic(*page, KM_USER0);
 451        end = (__be32 *)((char *)p + pglen);
 452        entry = p;
 453
 454        /* Make sure the packet actually has a value_follows and EOF entry */
 455        if ((entry + 1) > end)
 456                goto short_pkt;
 457
 458        for (; *p++; nr++) {
 459                if (p + 2 > end)
 460                        goto short_pkt;
 461                p++; /* fileid */
 462                len = ntohl(*p++);
 463                p += XDR_QUADLEN(len) + 1;      /* name plus cookie */
 464                if (len > NFS2_MAXNAMLEN) {
 465                        dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
 466                                                len);
 467                        goto err_unmap;
 468                }
 469                if (p + 2 > end)
 470                        goto short_pkt;
 471                entry = p;
 472        }
 473
 474        /*
 475         * Apparently some server sends responses that are a valid size, but
 476         * contain no entries, and have value_follows==0 and EOF==0. For
 477         * those, just set the EOF marker.
 478         */
 479        if (!nr && entry[1] == 0) {
 480                dprintk("NFS: readdir reply truncated!\n");
 481                entry[1] = 1;
 482        }
 483 out:
 484        kunmap_atomic(kaddr, KM_USER0);
 485        return nr;
 486 short_pkt:
 487        /*
 488         * When we get a short packet there are 2 possibilities. We can
 489         * return an error, or fix up the response to look like a valid
 490         * response and return what we have so far. If there are no
 491         * entries and the packet was short, then return -EIO. If there
 492         * are valid entries in the response, return them and pretend that
 493         * the call was successful, but incomplete. The caller can retry the
 494         * readdir starting at the last cookie.
 495         */
 496        entry[0] = entry[1] = 0;
 497        if (!nr)
 498                nr = -errno_NFSERR_IO;
 499        goto out;
 500err_unmap:
 501        nr = -errno_NFSERR_IO;
 502        goto out;
 503}
 504
 505__be32 *
 506nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
 507{
 508        if (!*p++) {
 509                if (!*p)
 510                        return ERR_PTR(-EAGAIN);
 511                entry->eof = 1;
 512                return ERR_PTR(-EBADCOOKIE);
 513        }
 514
 515        entry->ino        = ntohl(*p++);
 516        entry->len        = ntohl(*p++);
 517        entry->name       = (const char *) p;
 518        p                += XDR_QUADLEN(entry->len);
 519        entry->prev_cookie        = entry->cookie;
 520        entry->cookie     = ntohl(*p++);
 521        entry->eof        = !p[0] && p[1];
 522
 523        return p;
 524}
 525
 526/*
 527 * NFS XDR decode functions
 528 */
 529/*
 530 * Decode simple status reply
 531 */
 532static int
 533nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
 534{
 535        int     status;
 536
 537        if ((status = ntohl(*p++)) != 0)
 538                status = nfs_stat_to_errno(status);
 539        return status;
 540}
 541
 542/*
 543 * Decode attrstat reply
 544 * GETATTR, SETATTR, WRITE
 545 */
 546static int
 547nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
 548{
 549        int     status;
 550
 551        if ((status = ntohl(*p++)))
 552                return nfs_stat_to_errno(status);
 553        xdr_decode_fattr(p, fattr);
 554        return 0;
 555}
 556
 557/*
 558 * Decode diropres reply
 559 * LOOKUP, CREATE, MKDIR
 560 */
 561static int
 562nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
 563{
 564        int     status;
 565
 566        if ((status = ntohl(*p++)))
 567                return nfs_stat_to_errno(status);
 568        p = xdr_decode_fhandle(p, res->fh);
 569        xdr_decode_fattr(p, res->fattr);
 570        return 0;
 571}
 572
 573/*
 574 * Encode READLINK args
 575 */
 576static int
 577nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
 578{
 579        struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
 580        unsigned int replen;
 581
 582        p = xdr_encode_fhandle(p, args->fh);
 583        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
 584
 585        /* Inline the page array */
 586        replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
 587        xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
 588        return 0;
 589}
 590
 591/*
 592 * Decode READLINK reply
 593 */
 594static int
 595nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
 596{
 597        struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 598        struct kvec *iov = rcvbuf->head;
 599        size_t hdrlen;
 600        u32 len, recvd;
 601        char    *kaddr;
 602        int     status;
 603
 604        if ((status = ntohl(*p++)))
 605                return nfs_stat_to_errno(status);
 606        /* Convert length of symlink */
 607        len = ntohl(*p++);
 608        if (len >= rcvbuf->page_len) {
 609                dprintk("nfs: server returned giant symlink!\n");
 610                return -ENAMETOOLONG;
 611        }
 612        hdrlen = (u8 *) p - (u8 *) iov->iov_base;
 613        if (iov->iov_len < hdrlen) {
 614                dprintk("NFS: READLINK reply header overflowed:"
 615                                "length %Zu > %Zu\n", hdrlen, iov->iov_len);
 616                return -errno_NFSERR_IO;
 617        } else if (iov->iov_len != hdrlen) {
 618                dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
 619                xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
 620        }
 621        recvd = req->rq_rcv_buf.len - hdrlen;
 622        if (recvd < len) {
 623                dprintk("NFS: server cheating in readlink reply: "
 624                                "count %u > recvd %u\n", len, recvd);
 625                return -EIO;
 626        }
 627
 628        /* NULL terminate the string we got */
 629        kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
 630        kaddr[len+rcvbuf->page_base] = '\0';
 631        kunmap_atomic(kaddr, KM_USER0);
 632        return 0;
 633}
 634
 635/*
 636 * Decode WRITE reply
 637 */
 638static int
 639nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
 640{
 641        res->verf->committed = NFS_FILE_SYNC;
 642        return nfs_xdr_attrstat(req, p, res->fattr);
 643}
 644
 645/*
 646 * Decode STATFS reply
 647 */
 648static int
 649nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
 650{
 651        int     status;
 652
 653        if ((status = ntohl(*p++)))
 654                return nfs_stat_to_errno(status);
 655
 656        res->tsize  = ntohl(*p++);
 657        res->bsize  = ntohl(*p++);
 658        res->blocks = ntohl(*p++);
 659        res->bfree  = ntohl(*p++);
 660        res->bavail = ntohl(*p++);
 661        return 0;
 662}
 663
 664/*
 665 * We need to translate between nfs status return values and
 666 * the local errno values which may not be the same.
 667 */
 668static struct {
 669        int stat;
 670        int errno;
 671} nfs_errtbl[] = {
 672        { NFS_OK,               0               },
 673        { NFSERR_PERM,          -EPERM          },
 674        { NFSERR_NOENT,         -ENOENT         },
 675        { NFSERR_IO,            -errno_NFSERR_IO},
 676        { NFSERR_NXIO,          -ENXIO          },
 677/*      { NFSERR_EAGAIN,        -EAGAIN         }, */
 678        { NFSERR_ACCES,         -EACCES         },
 679        { NFSERR_EXIST,         -EEXIST         },
 680        { NFSERR_XDEV,          -EXDEV          },
 681        { NFSERR_NODEV,         -ENODEV         },
 682        { NFSERR_NOTDIR,        -ENOTDIR        },
 683        { NFSERR_ISDIR,         -EISDIR         },
 684        { NFSERR_INVAL,         -EINVAL         },
 685        { NFSERR_FBIG,          -EFBIG          },
 686        { NFSERR_NOSPC,         -ENOSPC         },
 687        { NFSERR_ROFS,          -EROFS          },
 688        { NFSERR_MLINK,         -EMLINK         },
 689        { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
 690        { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
 691        { NFSERR_DQUOT,         -EDQUOT         },
 692        { NFSERR_STALE,         -ESTALE         },
 693        { NFSERR_REMOTE,        -EREMOTE        },
 694#ifdef EWFLUSH
 695        { NFSERR_WFLUSH,        -EWFLUSH        },
 696#endif
 697        { NFSERR_BADHANDLE,     -EBADHANDLE     },
 698        { NFSERR_NOT_SYNC,      -ENOTSYNC       },
 699        { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
 700        { NFSERR_NOTSUPP,       -ENOTSUPP       },
 701        { NFSERR_TOOSMALL,      -ETOOSMALL      },
 702        { NFSERR_SERVERFAULT,   -ESERVERFAULT   },
 703        { NFSERR_BADTYPE,       -EBADTYPE       },
 704        { NFSERR_JUKEBOX,       -EJUKEBOX       },
 705        { -1,                   -EIO            }
 706};
 707
 708/*
 709 * Convert an NFS error code to a local one.
 710 * This one is used jointly by NFSv2 and NFSv3.
 711 */
 712int
 713nfs_stat_to_errno(int stat)
 714{
 715        int i;
 716
 717        for (i = 0; nfs_errtbl[i].stat != -1; i++) {
 718                if (nfs_errtbl[i].stat == stat)
 719                        return nfs_errtbl[i].errno;
 720        }
 721        dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
 722        return nfs_errtbl[i].errno;
 723}
 724
 725#define PROC(proc, argtype, restype, timer)                             \
 726[NFSPROC_##proc] = {                                                    \
 727        .p_proc     =  NFSPROC_##proc,                                  \
 728        .p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,                  \
 729        .p_decode   =  (kxdrproc_t) nfs_xdr_##restype,                  \
 730        .p_arglen   =  NFS_##argtype##_sz,                              \
 731        .p_replen   =  NFS_##restype##_sz,                              \
 732        .p_timer    =  timer,                                           \
 733        .p_statidx  =  NFSPROC_##proc,                                  \
 734        .p_name     =  #proc,                                           \
 735        }
 736struct rpc_procinfo     nfs_procedures[] = {
 737    PROC(GETATTR,       fhandle,        attrstat, 1),
 738    PROC(SETATTR,       sattrargs,      attrstat, 0),
 739    PROC(LOOKUP,        diropargs,      diropres, 2),
 740    PROC(READLINK,      readlinkargs,   readlinkres, 3),
 741    PROC(READ,          readargs,       readres, 3),
 742    PROC(WRITE,         writeargs,      writeres, 4),
 743    PROC(CREATE,        createargs,     diropres, 0),
 744    PROC(REMOVE,        removeargs,     stat, 0),
 745    PROC(RENAME,        renameargs,     stat, 0),
 746    PROC(LINK,          linkargs,       stat, 0),
 747    PROC(SYMLINK,       symlinkargs,    stat, 0),
 748    PROC(MKDIR,         createargs,     diropres, 0),
 749    PROC(RMDIR,         diropargs,      stat, 0),
 750    PROC(READDIR,       readdirargs,    readdirres, 3),
 751    PROC(STATFS,        fhandle,        statfsres, 0),
 752};
 753
 754struct rpc_version              nfs_version2 = {
 755        .number                 = 2,
 756        .nrprocs                = ARRAY_SIZE(nfs_procedures),
 757        .procs                  = nfs_procedures
 758};
 759