linux/fs/nfsd/nfs3xdr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * XDR support for nfsd/protocol version 3.
   4 *
   5 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
   6 *
   7 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
   8 */
   9
  10#include <linux/namei.h>
  11#include <linux/sunrpc/svc_xprt.h>
  12#include "xdr3.h"
  13#include "auth.h"
  14#include "netns.h"
  15#include "vfs.h"
  16
  17/*
  18 * Force construction of an empty post-op attr
  19 */
  20static const struct svc_fh nfs3svc_null_fh = {
  21        .fh_no_wcc      = true,
  22};
  23
  24/*
  25 * time_delta. {1, 0} means the server is accurate only
  26 * to the nearest second.
  27 */
  28static const struct timespec64 nfs3svc_time_delta = {
  29        .tv_sec         = 1,
  30        .tv_nsec        = 0,
  31};
  32
  33/*
  34 * Mapping of S_IF* types to NFS file types
  35 */
  36static const u32 nfs3_ftypes[] = {
  37        NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
  38        NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
  39        NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
  40        NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
  41};
  42
  43
  44/*
  45 * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6)
  46 */
  47
  48static __be32 *
  49encode_nfstime3(__be32 *p, const struct timespec64 *time)
  50{
  51        *p++ = cpu_to_be32((u32)time->tv_sec);
  52        *p++ = cpu_to_be32(time->tv_nsec);
  53
  54        return p;
  55}
  56
  57static bool
  58svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep)
  59{
  60        __be32 *p;
  61
  62        p = xdr_inline_decode(xdr, XDR_UNIT * 2);
  63        if (!p)
  64                return false;
  65        timep->tv_sec = be32_to_cpup(p++);
  66        timep->tv_nsec = be32_to_cpup(p);
  67
  68        return true;
  69}
  70
  71/**
  72 * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle
  73 * @xdr: XDR stream positioned at an undecoded NFSv3 FH
  74 * @fhp: OUT: filled-in server file handle
  75 *
  76 * Return values:
  77 *  %false: The encoded file handle was not valid
  78 *  %true: @fhp has been initialized
  79 */
  80bool
  81svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
  82{
  83        __be32 *p;
  84        u32 size;
  85
  86        if (xdr_stream_decode_u32(xdr, &size) < 0)
  87                return false;
  88        if (size == 0 || size > NFS3_FHSIZE)
  89                return false;
  90        p = xdr_inline_decode(xdr, size);
  91        if (!p)
  92                return false;
  93        fh_init(fhp, NFS3_FHSIZE);
  94        fhp->fh_handle.fh_size = size;
  95        memcpy(&fhp->fh_handle.fh_base, p, size);
  96
  97        return true;
  98}
  99
 100/**
 101 * svcxdr_encode_nfsstat3 - Encode an NFSv3 status code
 102 * @xdr: XDR stream
 103 * @status: status value to encode
 104 *
 105 * Return values:
 106 *   %false: Send buffer space was exhausted
 107 *   %true: Success
 108 */
 109bool
 110svcxdr_encode_nfsstat3(struct xdr_stream *xdr, __be32 status)
 111{
 112        __be32 *p;
 113
 114        p = xdr_reserve_space(xdr, sizeof(status));
 115        if (!p)
 116                return false;
 117        *p = status;
 118
 119        return true;
 120}
 121
 122static bool
 123svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
 124{
 125        u32 size = fhp->fh_handle.fh_size;
 126        __be32 *p;
 127
 128        p = xdr_reserve_space(xdr, XDR_UNIT + size);
 129        if (!p)
 130                return false;
 131        *p++ = cpu_to_be32(size);
 132        if (size)
 133                p[XDR_QUADLEN(size) - 1] = 0;
 134        memcpy(p, &fhp->fh_handle.fh_base, size);
 135
 136        return true;
 137}
 138
 139static bool
 140svcxdr_encode_post_op_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
 141{
 142        if (xdr_stream_encode_item_present(xdr) < 0)
 143                return false;
 144        if (!svcxdr_encode_nfs_fh3(xdr, fhp))
 145                return false;
 146
 147        return true;
 148}
 149
 150static bool
 151svcxdr_encode_cookieverf3(struct xdr_stream *xdr, const __be32 *verf)
 152{
 153        __be32 *p;
 154
 155        p = xdr_reserve_space(xdr, NFS3_COOKIEVERFSIZE);
 156        if (!p)
 157                return false;
 158        memcpy(p, verf, NFS3_COOKIEVERFSIZE);
 159
 160        return true;
 161}
 162
 163static bool
 164svcxdr_encode_writeverf3(struct xdr_stream *xdr, const __be32 *verf)
 165{
 166        __be32 *p;
 167
 168        p = xdr_reserve_space(xdr, NFS3_WRITEVERFSIZE);
 169        if (!p)
 170                return false;
 171        memcpy(p, verf, NFS3_WRITEVERFSIZE);
 172
 173        return true;
 174}
 175
 176static bool
 177svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len)
 178{
 179        u32 size, i;
 180        __be32 *p;
 181        char *c;
 182
 183        if (xdr_stream_decode_u32(xdr, &size) < 0)
 184                return false;
 185        if (size == 0 || size > NFS3_MAXNAMLEN)
 186                return false;
 187        p = xdr_inline_decode(xdr, size);
 188        if (!p)
 189                return false;
 190
 191        *len = size;
 192        *name = (char *)p;
 193        for (i = 0, c = *name; i < size; i++, c++) {
 194                if (*c == '\0' || *c == '/')
 195                        return false;
 196        }
 197
 198        return true;
 199}
 200
 201static bool
 202svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp,
 203                         char **name, unsigned int *len)
 204{
 205        return svcxdr_decode_nfs_fh3(xdr, fhp) &&
 206                svcxdr_decode_filename3(xdr, name, len);
 207}
 208
 209static bool
 210svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 211                     struct iattr *iap)
 212{
 213        u32 set_it;
 214
 215        iap->ia_valid = 0;
 216
 217        if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 218                return false;
 219        if (set_it) {
 220                u32 mode;
 221
 222                if (xdr_stream_decode_u32(xdr, &mode) < 0)
 223                        return false;
 224                iap->ia_valid |= ATTR_MODE;
 225                iap->ia_mode = mode;
 226        }
 227        if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 228                return false;
 229        if (set_it) {
 230                u32 uid;
 231
 232                if (xdr_stream_decode_u32(xdr, &uid) < 0)
 233                        return false;
 234                iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid);
 235                if (uid_valid(iap->ia_uid))
 236                        iap->ia_valid |= ATTR_UID;
 237        }
 238        if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 239                return false;
 240        if (set_it) {
 241                u32 gid;
 242
 243                if (xdr_stream_decode_u32(xdr, &gid) < 0)
 244                        return false;
 245                iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid);
 246                if (gid_valid(iap->ia_gid))
 247                        iap->ia_valid |= ATTR_GID;
 248        }
 249        if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 250                return false;
 251        if (set_it) {
 252                u64 newsize;
 253
 254                if (xdr_stream_decode_u64(xdr, &newsize) < 0)
 255                        return false;
 256                iap->ia_valid |= ATTR_SIZE;
 257                iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX);
 258        }
 259        if (xdr_stream_decode_u32(xdr, &set_it) < 0)
 260                return false;
 261        switch (set_it) {
 262        case DONT_CHANGE:
 263                break;
 264        case SET_TO_SERVER_TIME:
 265                iap->ia_valid |= ATTR_ATIME;
 266                break;
 267        case SET_TO_CLIENT_TIME:
 268                if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime))
 269                        return false;
 270                iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
 271                break;
 272        default:
 273                return false;
 274        }
 275        if (xdr_stream_decode_u32(xdr, &set_it) < 0)
 276                return false;
 277        switch (set_it) {
 278        case DONT_CHANGE:
 279                break;
 280        case SET_TO_SERVER_TIME:
 281                iap->ia_valid |= ATTR_MTIME;
 282                break;
 283        case SET_TO_CLIENT_TIME:
 284                if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime))
 285                        return false;
 286                iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
 287                break;
 288        default:
 289                return false;
 290        }
 291
 292        return true;
 293}
 294
 295static bool
 296svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args)
 297{
 298        __be32 *p;
 299        u32 check;
 300
 301        if (xdr_stream_decode_bool(xdr, &check) < 0)
 302                return false;
 303        if (check) {
 304                p = xdr_inline_decode(xdr, XDR_UNIT * 2);
 305                if (!p)
 306                        return false;
 307                args->check_guard = 1;
 308                args->guardtime = be32_to_cpup(p);
 309        } else
 310                args->check_guard = 0;
 311
 312        return true;
 313}
 314
 315static bool
 316svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args)
 317{
 318        __be32 *p;
 319
 320        p = xdr_inline_decode(xdr, XDR_UNIT * 2);
 321        if (!p)
 322                return false;
 323        args->major = be32_to_cpup(p++);
 324        args->minor = be32_to_cpup(p);
 325
 326        return true;
 327}
 328
 329static bool
 330svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 331                          struct nfsd3_mknodargs *args)
 332{
 333        return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
 334                svcxdr_decode_specdata3(xdr, args);
 335}
 336
 337static bool
 338svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 339                     const struct svc_fh *fhp, const struct kstat *stat)
 340{
 341        struct user_namespace *userns = nfsd_user_namespace(rqstp);
 342        __be32 *p;
 343        u64 fsid;
 344
 345        p = xdr_reserve_space(xdr, XDR_UNIT * 21);
 346        if (!p)
 347                return false;
 348
 349        *p++ = cpu_to_be32(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
 350        *p++ = cpu_to_be32((u32)(stat->mode & S_IALLUGO));
 351        *p++ = cpu_to_be32((u32)stat->nlink);
 352        *p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid));
 353        *p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid));
 354        if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN)
 355                p = xdr_encode_hyper(p, (u64)NFS3_MAXPATHLEN);
 356        else
 357                p = xdr_encode_hyper(p, (u64)stat->size);
 358
 359        /* used */
 360        p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
 361
 362        /* rdev */
 363        *p++ = cpu_to_be32((u32)MAJOR(stat->rdev));
 364        *p++ = cpu_to_be32((u32)MINOR(stat->rdev));
 365
 366        switch(fsid_source(fhp)) {
 367        case FSIDSOURCE_FSID:
 368                fsid = (u64)fhp->fh_export->ex_fsid;
 369                break;
 370        case FSIDSOURCE_UUID:
 371                fsid = ((u64 *)fhp->fh_export->ex_uuid)[0];
 372                fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1];
 373                break;
 374        default:
 375                fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev);
 376        }
 377        p = xdr_encode_hyper(p, fsid);
 378
 379        /* fileid */
 380        p = xdr_encode_hyper(p, stat->ino);
 381
 382        p = encode_nfstime3(p, &stat->atime);
 383        p = encode_nfstime3(p, &stat->mtime);
 384        encode_nfstime3(p, &stat->ctime);
 385
 386        return true;
 387}
 388
 389static bool
 390svcxdr_encode_wcc_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
 391{
 392        __be32 *p;
 393
 394        p = xdr_reserve_space(xdr, XDR_UNIT * 6);
 395        if (!p)
 396                return false;
 397        p = xdr_encode_hyper(p, (u64)fhp->fh_pre_size);
 398        p = encode_nfstime3(p, &fhp->fh_pre_mtime);
 399        encode_nfstime3(p, &fhp->fh_pre_ctime);
 400
 401        return true;
 402}
 403
 404static bool
 405svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
 406{
 407        if (!fhp->fh_pre_saved) {
 408                if (xdr_stream_encode_item_absent(xdr) < 0)
 409                        return false;
 410                return true;
 411        }
 412
 413        if (xdr_stream_encode_item_present(xdr) < 0)
 414                return false;
 415        return svcxdr_encode_wcc_attr(xdr, fhp);
 416}
 417
 418/**
 419 * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes
 420 * @rqstp: Context of a completed RPC transaction
 421 * @xdr: XDR stream
 422 * @fhp: File handle to encode
 423 *
 424 * Return values:
 425 *   %false: Send buffer space was exhausted
 426 *   %true: Success
 427 */
 428bool
 429svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 430                           const struct svc_fh *fhp)
 431{
 432        struct dentry *dentry = fhp->fh_dentry;
 433        struct kstat stat;
 434
 435        /*
 436         * The inode may be NULL if the call failed because of a
 437         * stale file handle. In this case, no attributes are
 438         * returned.
 439         */
 440        if (fhp->fh_no_wcc || !dentry || !d_really_is_positive(dentry))
 441                goto no_post_op_attrs;
 442        if (fh_getattr(fhp, &stat) != nfs_ok)
 443                goto no_post_op_attrs;
 444
 445        if (xdr_stream_encode_item_present(xdr) < 0)
 446                return false;
 447        lease_get_mtime(d_inode(dentry), &stat.mtime);
 448        if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &stat))
 449                return false;
 450
 451        return true;
 452
 453no_post_op_attrs:
 454        return xdr_stream_encode_item_absent(xdr) > 0;
 455}
 456
 457/*
 458 * Encode weak cache consistency data
 459 */
 460static bool
 461svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 462                       const struct svc_fh *fhp)
 463{
 464        struct dentry *dentry = fhp->fh_dentry;
 465
 466        if (!dentry || !d_really_is_positive(dentry) || !fhp->fh_post_saved)
 467                goto neither;
 468
 469        /* before */
 470        if (!svcxdr_encode_pre_op_attr(xdr, fhp))
 471                return false;
 472
 473        /* after */
 474        if (xdr_stream_encode_item_present(xdr) < 0)
 475                return false;
 476        if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &fhp->fh_post_attr))
 477                return false;
 478
 479        return true;
 480
 481neither:
 482        if (xdr_stream_encode_item_absent(xdr) < 0)
 483                return false;
 484        if (!svcxdr_encode_post_op_attr(rqstp, xdr, fhp))
 485                return false;
 486
 487        return true;
 488}
 489
 490static bool fs_supports_change_attribute(struct super_block *sb)
 491{
 492        return sb->s_flags & SB_I_VERSION || sb->s_export_op->fetch_iversion;
 493}
 494
 495/*
 496 * Fill in the pre_op attr for the wcc data
 497 */
 498void fill_pre_wcc(struct svc_fh *fhp)
 499{
 500        struct inode    *inode;
 501        struct kstat    stat;
 502        bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
 503
 504        if (fhp->fh_no_wcc || fhp->fh_pre_saved)
 505                return;
 506        inode = d_inode(fhp->fh_dentry);
 507        if (fs_supports_change_attribute(inode->i_sb) || !v4) {
 508                __be32 err = fh_getattr(fhp, &stat);
 509
 510                if (err) {
 511                        /* Grab the times from inode anyway */
 512                        stat.mtime = inode->i_mtime;
 513                        stat.ctime = inode->i_ctime;
 514                        stat.size  = inode->i_size;
 515                }
 516                fhp->fh_pre_mtime = stat.mtime;
 517                fhp->fh_pre_ctime = stat.ctime;
 518                fhp->fh_pre_size  = stat.size;
 519        }
 520        if (v4)
 521                fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
 522
 523        fhp->fh_pre_saved = true;
 524}
 525
 526/*
 527 * Fill in the post_op attr for the wcc data
 528 */
 529void fill_post_wcc(struct svc_fh *fhp)
 530{
 531        bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE);
 532        struct inode *inode = d_inode(fhp->fh_dentry);
 533
 534        if (fhp->fh_no_wcc)
 535                return;
 536
 537        if (fhp->fh_post_saved)
 538                printk("nfsd: inode locked twice during operation.\n");
 539
 540        fhp->fh_post_saved = true;
 541
 542        if (fs_supports_change_attribute(inode->i_sb) || !v4) {
 543                __be32 err = fh_getattr(fhp, &fhp->fh_post_attr);
 544
 545                if (err) {
 546                        fhp->fh_post_saved = false;
 547                        fhp->fh_post_attr.ctime = inode->i_ctime;
 548                }
 549        }
 550        if (v4)
 551                fhp->fh_post_change =
 552                        nfsd4_change_attribute(&fhp->fh_post_attr, inode);
 553}
 554
 555/*
 556 * XDR decode functions
 557 */
 558
 559int
 560nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
 561{
 562        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 563        struct nfsd_fhandle *args = rqstp->rq_argp;
 564
 565        return svcxdr_decode_nfs_fh3(xdr, &args->fh);
 566}
 567
 568int
 569nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
 570{
 571        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 572        struct nfsd3_sattrargs *args = rqstp->rq_argp;
 573
 574        return svcxdr_decode_nfs_fh3(xdr, &args->fh) &&
 575                svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
 576                svcxdr_decode_sattrguard3(xdr, args);
 577}
 578
 579int
 580nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
 581{
 582        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 583        struct nfsd3_diropargs *args = rqstp->rq_argp;
 584
 585        return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
 586}
 587
 588int
 589nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p)
 590{
 591        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 592        struct nfsd3_accessargs *args = rqstp->rq_argp;
 593
 594        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 595                return 0;
 596        if (xdr_stream_decode_u32(xdr, &args->access) < 0)
 597                return 0;
 598
 599        return 1;
 600}
 601
 602int
 603nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
 604{
 605        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 606        struct nfsd3_readargs *args = rqstp->rq_argp;
 607
 608        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 609                return 0;
 610        if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 611                return 0;
 612        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 613                return 0;
 614
 615        return 1;
 616}
 617
 618int
 619nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
 620{
 621        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 622        struct nfsd3_writeargs *args = rqstp->rq_argp;
 623        u32 max_blocksize = svc_max_payload(rqstp);
 624        struct kvec *head = rqstp->rq_arg.head;
 625        struct kvec *tail = rqstp->rq_arg.tail;
 626        size_t remaining;
 627
 628        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 629                return 0;
 630        if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 631                return 0;
 632        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 633                return 0;
 634        if (xdr_stream_decode_u32(xdr, &args->stable) < 0)
 635                return 0;
 636
 637        /* opaque data */
 638        if (xdr_stream_decode_u32(xdr, &args->len) < 0)
 639                return 0;
 640
 641        /* request sanity */
 642        if (args->count != args->len)
 643                return 0;
 644        remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
 645        remaining -= xdr_stream_pos(xdr);
 646        if (remaining < xdr_align_size(args->len))
 647                return 0;
 648        if (args->count > max_blocksize) {
 649                args->count = max_blocksize;
 650                args->len = max_blocksize;
 651        }
 652
 653        args->first.iov_base = xdr->p;
 654        args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 655
 656        return 1;
 657}
 658
 659int
 660nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
 661{
 662        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 663        struct nfsd3_createargs *args = rqstp->rq_argp;
 664
 665        if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
 666                return 0;
 667        if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
 668                return 0;
 669        switch (args->createmode) {
 670        case NFS3_CREATE_UNCHECKED:
 671        case NFS3_CREATE_GUARDED:
 672                return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 673        case NFS3_CREATE_EXCLUSIVE:
 674                args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
 675                if (!args->verf)
 676                        return 0;
 677                break;
 678        default:
 679                return 0;
 680        }
 681        return 1;
 682}
 683
 684int
 685nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p)
 686{
 687        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 688        struct nfsd3_createargs *args = rqstp->rq_argp;
 689
 690        return svcxdr_decode_diropargs3(xdr, &args->fh,
 691                                        &args->name, &args->len) &&
 692                svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 693}
 694
 695int
 696nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
 697{
 698        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 699        struct nfsd3_symlinkargs *args = rqstp->rq_argp;
 700        struct kvec *head = rqstp->rq_arg.head;
 701        struct kvec *tail = rqstp->rq_arg.tail;
 702        size_t remaining;
 703
 704        if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
 705                return 0;
 706        if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
 707                return 0;
 708        if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
 709                return 0;
 710
 711        /* request sanity */
 712        remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
 713        remaining -= xdr_stream_pos(xdr);
 714        if (remaining < xdr_align_size(args->tlen))
 715                return 0;
 716
 717        args->first.iov_base = xdr->p;
 718        args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 719
 720        return 1;
 721}
 722
 723int
 724nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p)
 725{
 726        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 727        struct nfsd3_mknodargs *args = rqstp->rq_argp;
 728
 729        if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
 730                return 0;
 731        if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
 732                return 0;
 733        switch (args->ftype) {
 734        case NF3CHR:
 735        case NF3BLK:
 736                return svcxdr_decode_devicedata3(rqstp, xdr, args);
 737        case NF3SOCK:
 738        case NF3FIFO:
 739                return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 740        case NF3REG:
 741        case NF3DIR:
 742        case NF3LNK:
 743                /* Valid XDR but illegal file types */
 744                break;
 745        default:
 746                return 0;
 747        }
 748
 749        return 1;
 750}
 751
 752int
 753nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 754{
 755        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 756        struct nfsd3_renameargs *args = rqstp->rq_argp;
 757
 758        return svcxdr_decode_diropargs3(xdr, &args->ffh,
 759                                        &args->fname, &args->flen) &&
 760                svcxdr_decode_diropargs3(xdr, &args->tfh,
 761                                         &args->tname, &args->tlen);
 762}
 763
 764int
 765nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 766{
 767        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 768        struct nfsd3_linkargs *args = rqstp->rq_argp;
 769
 770        return svcxdr_decode_nfs_fh3(xdr, &args->ffh) &&
 771                svcxdr_decode_diropargs3(xdr, &args->tfh,
 772                                         &args->tname, &args->tlen);
 773}
 774
 775int
 776nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 777{
 778        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 779        struct nfsd3_readdirargs *args = rqstp->rq_argp;
 780
 781        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 782                return 0;
 783        if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
 784                return 0;
 785        args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 786        if (!args->verf)
 787                return 0;
 788        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 789                return 0;
 790
 791        return 1;
 792}
 793
 794int
 795nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p)
 796{
 797        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 798        struct nfsd3_readdirargs *args = rqstp->rq_argp;
 799        u32 dircount;
 800
 801        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 802                return 0;
 803        if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
 804                return 0;
 805        args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 806        if (!args->verf)
 807                return 0;
 808        /* dircount is ignored */
 809        if (xdr_stream_decode_u32(xdr, &dircount) < 0)
 810                return 0;
 811        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 812                return 0;
 813
 814        return 1;
 815}
 816
 817int
 818nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p)
 819{
 820        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 821        struct nfsd3_commitargs *args = rqstp->rq_argp;
 822
 823        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 824                return 0;
 825        if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 826                return 0;
 827        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 828                return 0;
 829
 830        return 1;
 831}
 832
 833/*
 834 * XDR encode functions
 835 */
 836
 837/* GETATTR */
 838int
 839nfs3svc_encode_getattrres(struct svc_rqst *rqstp, __be32 *p)
 840{
 841        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 842        struct nfsd3_attrstat *resp = rqstp->rq_resp;
 843
 844        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 845                return 0;
 846        switch (resp->status) {
 847        case nfs_ok:
 848                lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime);
 849                if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat))
 850                        return 0;
 851                break;
 852        }
 853
 854        return 1;
 855}
 856
 857/* SETATTR, REMOVE, RMDIR */
 858int
 859nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p)
 860{
 861        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 862        struct nfsd3_attrstat *resp = rqstp->rq_resp;
 863
 864        return svcxdr_encode_nfsstat3(xdr, resp->status) &&
 865                svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh);
 866}
 867
 868/* LOOKUP */
 869int nfs3svc_encode_lookupres(struct svc_rqst *rqstp, __be32 *p)
 870{
 871        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 872        struct nfsd3_diropres *resp = rqstp->rq_resp;
 873
 874        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 875                return 0;
 876        switch (resp->status) {
 877        case nfs_ok:
 878                if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh))
 879                        return 0;
 880                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 881                        return 0;
 882                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
 883                        return 0;
 884                break;
 885        default:
 886                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
 887                        return 0;
 888        }
 889
 890        return 1;
 891}
 892
 893/* ACCESS */
 894int
 895nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p)
 896{
 897        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 898        struct nfsd3_accessres *resp = rqstp->rq_resp;
 899
 900        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 901                return 0;
 902        switch (resp->status) {
 903        case nfs_ok:
 904                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 905                        return 0;
 906                if (xdr_stream_encode_u32(xdr, resp->access) < 0)
 907                        return 0;
 908                break;
 909        default:
 910                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 911                        return 0;
 912        }
 913
 914        return 1;
 915}
 916
 917/* READLINK */
 918int
 919nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
 920{
 921        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 922        struct nfsd3_readlinkres *resp = rqstp->rq_resp;
 923        struct kvec *head = rqstp->rq_res.head;
 924
 925        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 926                return 0;
 927        switch (resp->status) {
 928        case nfs_ok:
 929                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 930                        return 0;
 931                if (xdr_stream_encode_u32(xdr, resp->len) < 0)
 932                        return 0;
 933                xdr_write_pages(xdr, resp->pages, 0, resp->len);
 934                if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
 935                        return 0;
 936                break;
 937        default:
 938                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 939                        return 0;
 940        }
 941
 942        return 1;
 943}
 944
 945/* READ */
 946int
 947nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
 948{
 949        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 950        struct nfsd3_readres *resp = rqstp->rq_resp;
 951        struct kvec *head = rqstp->rq_res.head;
 952
 953        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 954                return 0;
 955        switch (resp->status) {
 956        case nfs_ok:
 957                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 958                        return 0;
 959                if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 960                        return 0;
 961                if (xdr_stream_encode_bool(xdr, resp->eof) < 0)
 962                        return 0;
 963                if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 964                        return 0;
 965                xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
 966                                resp->count);
 967                if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
 968                        return 0;
 969                break;
 970        default:
 971                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 972                        return 0;
 973        }
 974
 975        return 1;
 976}
 977
 978/* WRITE */
 979int
 980nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p)
 981{
 982        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 983        struct nfsd3_writeres *resp = rqstp->rq_resp;
 984
 985        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 986                return 0;
 987        switch (resp->status) {
 988        case nfs_ok:
 989                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
 990                        return 0;
 991                if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 992                        return 0;
 993                if (xdr_stream_encode_u32(xdr, resp->committed) < 0)
 994                        return 0;
 995                if (!svcxdr_encode_writeverf3(xdr, resp->verf))
 996                        return 0;
 997                break;
 998        default:
 999                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1000                        return 0;
1001        }
1002
1003        return 1;
1004}
1005
1006/* CREATE, MKDIR, SYMLINK, MKNOD */
1007int
1008nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p)
1009{
1010        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1011        struct nfsd3_diropres *resp = rqstp->rq_resp;
1012
1013        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1014                return 0;
1015        switch (resp->status) {
1016        case nfs_ok:
1017                if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh))
1018                        return 0;
1019                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
1020                        return 0;
1021                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
1022                        return 0;
1023                break;
1024        default:
1025                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
1026                        return 0;
1027        }
1028
1029        return 1;
1030}
1031
1032/* RENAME */
1033int
1034nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p)
1035{
1036        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1037        struct nfsd3_renameres *resp = rqstp->rq_resp;
1038
1039        return svcxdr_encode_nfsstat3(xdr, resp->status) &&
1040                svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) &&
1041                svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
1042}
1043
1044/* LINK */
1045int
1046nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p)
1047{
1048        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1049        struct nfsd3_linkres *resp = rqstp->rq_resp;
1050
1051        return svcxdr_encode_nfsstat3(xdr, resp->status) &&
1052                svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) &&
1053                svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
1054}
1055
1056/* READDIR */
1057int
1058nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
1059{
1060        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1061        struct nfsd3_readdirres *resp = rqstp->rq_resp;
1062        struct xdr_buf *dirlist = &resp->dirlist;
1063
1064        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1065                return 0;
1066        switch (resp->status) {
1067        case nfs_ok:
1068                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
1069                        return 0;
1070                if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
1071                        return 0;
1072                xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len);
1073                /* no more entries */
1074                if (xdr_stream_encode_item_absent(xdr) < 0)
1075                        return 0;
1076                if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
1077                        return 0;
1078                break;
1079        default:
1080                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
1081                        return 0;
1082        }
1083
1084        return 1;
1085}
1086
1087static __be32
1088compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
1089                 const char *name, int namlen, u64 ino)
1090{
1091        struct svc_export       *exp;
1092        struct dentry           *dparent, *dchild;
1093        __be32 rv = nfserr_noent;
1094
1095        dparent = cd->fh.fh_dentry;
1096        exp  = cd->fh.fh_export;
1097
1098        if (isdotent(name, namlen)) {
1099                if (namlen == 2) {
1100                        dchild = dget_parent(dparent);
1101                        /*
1102                         * Don't return filehandle for ".." if we're at
1103                         * the filesystem or export root:
1104                         */
1105                        if (dchild == dparent)
1106                                goto out;
1107                        if (dparent == exp->ex_path.dentry)
1108                                goto out;
1109                } else
1110                        dchild = dget(dparent);
1111        } else
1112                dchild = lookup_positive_unlocked(name, dparent, namlen);
1113        if (IS_ERR(dchild))
1114                return rv;
1115        if (d_mountpoint(dchild))
1116                goto out;
1117        if (dchild->d_inode->i_ino != ino)
1118                goto out;
1119        rv = fh_compose(fhp, exp, dchild, &cd->fh);
1120out:
1121        dput(dchild);
1122        return rv;
1123}
1124
1125/**
1126 * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1127 * @resp: readdir result context
1128 * @offset: offset cookie to encode
1129 *
1130 * The buffer space for the offset cookie has already been reserved
1131 * by svcxdr_encode_entry3_common().
1132 */
1133void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset)
1134{
1135        __be64 cookie = cpu_to_be64(offset);
1136
1137        if (!resp->cookie_offset)
1138                return;
1139        write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
1140                               sizeof(cookie));
1141        resp->cookie_offset = 0;
1142}
1143
1144static bool
1145svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name,
1146                            int namlen, loff_t offset, u64 ino)
1147{
1148        struct xdr_buf *dirlist = &resp->dirlist;
1149        struct xdr_stream *xdr = &resp->xdr;
1150
1151        if (xdr_stream_encode_item_present(xdr) < 0)
1152                return false;
1153        /* fileid */
1154        if (xdr_stream_encode_u64(xdr, ino) < 0)
1155                return false;
1156        /* name */
1157        if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0)
1158                return false;
1159        /* cookie */
1160        resp->cookie_offset = dirlist->len;
1161        if (xdr_stream_encode_u64(xdr, NFS_OFFSET_MAX) < 0)
1162                return false;
1163
1164        return true;
1165}
1166
1167/**
1168 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1169 * @data: directory context
1170 * @name: name of the object to be encoded
1171 * @namlen: length of that name, in bytes
1172 * @offset: the offset of the previous entry
1173 * @ino: the fileid of this entry
1174 * @d_type: unused
1175 *
1176 * Return values:
1177 *   %0: Entry was successfully encoded.
1178 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1179 *
1180 * On exit, the following fields are updated:
1181 *   - resp->xdr
1182 *   - resp->common.err
1183 *   - resp->cookie_offset
1184 */
1185int nfs3svc_encode_entry3(void *data, const char *name, int namlen,
1186                          loff_t offset, u64 ino, unsigned int d_type)
1187{
1188        struct readdir_cd *ccd = data;
1189        struct nfsd3_readdirres *resp = container_of(ccd,
1190                                                     struct nfsd3_readdirres,
1191                                                     common);
1192        unsigned int starting_length = resp->dirlist.len;
1193
1194        /* The offset cookie for the previous entry */
1195        nfs3svc_encode_cookie3(resp, offset);
1196
1197        if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1198                goto out_toosmall;
1199
1200        xdr_commit_encode(&resp->xdr);
1201        resp->common.err = nfs_ok;
1202        return 0;
1203
1204out_toosmall:
1205        resp->cookie_offset = 0;
1206        resp->common.err = nfserr_toosmall;
1207        resp->dirlist.len = starting_length;
1208        return -EINVAL;
1209}
1210
1211static bool
1212svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name,
1213                          int namlen, u64 ino)
1214{
1215        struct xdr_stream *xdr = &resp->xdr;
1216        struct svc_fh *fhp = &resp->scratch;
1217        bool result;
1218
1219        result = false;
1220        fh_init(fhp, NFS3_FHSIZE);
1221        if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok)
1222                goto out_noattrs;
1223
1224        if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp))
1225                goto out;
1226        if (!svcxdr_encode_post_op_fh3(xdr, fhp))
1227                goto out;
1228        result = true;
1229
1230out:
1231        fh_put(fhp);
1232        return result;
1233
1234out_noattrs:
1235        if (xdr_stream_encode_item_absent(xdr) < 0)
1236                return false;
1237        if (xdr_stream_encode_item_absent(xdr) < 0)
1238                return false;
1239        return true;
1240}
1241
1242/**
1243 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1244 * @data: directory context
1245 * @name: name of the object to be encoded
1246 * @namlen: length of that name, in bytes
1247 * @offset: the offset of the previous entry
1248 * @ino: the fileid of this entry
1249 * @d_type: unused
1250 *
1251 * Return values:
1252 *   %0: Entry was successfully encoded.
1253 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1254 *
1255 * On exit, the following fields are updated:
1256 *   - resp->xdr
1257 *   - resp->common.err
1258 *   - resp->cookie_offset
1259 */
1260int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,
1261                              loff_t offset, u64 ino, unsigned int d_type)
1262{
1263        struct readdir_cd *ccd = data;
1264        struct nfsd3_readdirres *resp = container_of(ccd,
1265                                                     struct nfsd3_readdirres,
1266                                                     common);
1267        unsigned int starting_length = resp->dirlist.len;
1268
1269        /* The offset cookie for the previous entry */
1270        nfs3svc_encode_cookie3(resp, offset);
1271
1272        if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1273                goto out_toosmall;
1274        if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino))
1275                goto out_toosmall;
1276
1277        xdr_commit_encode(&resp->xdr);
1278        resp->common.err = nfs_ok;
1279        return 0;
1280
1281out_toosmall:
1282        resp->cookie_offset = 0;
1283        resp->common.err = nfserr_toosmall;
1284        resp->dirlist.len = starting_length;
1285        return -EINVAL;
1286}
1287
1288static bool
1289svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
1290                           const struct nfsd3_fsstatres *resp)
1291{
1292        const struct kstatfs *s = &resp->stats;
1293        u64 bs = s->f_bsize;
1294        __be32 *p;
1295
1296        p = xdr_reserve_space(xdr, XDR_UNIT * 13);
1297        if (!p)
1298                return false;
1299        p = xdr_encode_hyper(p, bs * s->f_blocks);      /* total bytes */
1300        p = xdr_encode_hyper(p, bs * s->f_bfree);       /* free bytes */
1301        p = xdr_encode_hyper(p, bs * s->f_bavail);      /* user available bytes */
1302        p = xdr_encode_hyper(p, s->f_files);            /* total inodes */
1303        p = xdr_encode_hyper(p, s->f_ffree);            /* free inodes */
1304        p = xdr_encode_hyper(p, s->f_ffree);            /* user available inodes */
1305        *p = cpu_to_be32(resp->invarsec);               /* mean unchanged time */
1306
1307        return true;
1308}
1309
1310/* FSSTAT */
1311int
1312nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p)
1313{
1314        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1315        struct nfsd3_fsstatres *resp = rqstp->rq_resp;
1316
1317        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1318                return 0;
1319        switch (resp->status) {
1320        case nfs_ok:
1321                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1322                        return 0;
1323                if (!svcxdr_encode_fsstat3resok(xdr, resp))
1324                        return 0;
1325                break;
1326        default:
1327                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1328                        return 0;
1329        }
1330
1331        return 1;
1332}
1333
1334static bool
1335svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
1336                           const struct nfsd3_fsinfores *resp)
1337{
1338        __be32 *p;
1339
1340        p = xdr_reserve_space(xdr, XDR_UNIT * 12);
1341        if (!p)
1342                return false;
1343        *p++ = cpu_to_be32(resp->f_rtmax);
1344        *p++ = cpu_to_be32(resp->f_rtpref);
1345        *p++ = cpu_to_be32(resp->f_rtmult);
1346        *p++ = cpu_to_be32(resp->f_wtmax);
1347        *p++ = cpu_to_be32(resp->f_wtpref);
1348        *p++ = cpu_to_be32(resp->f_wtmult);
1349        *p++ = cpu_to_be32(resp->f_dtpref);
1350        p = xdr_encode_hyper(p, resp->f_maxfilesize);
1351        p = encode_nfstime3(p, &nfs3svc_time_delta);
1352        *p = cpu_to_be32(resp->f_properties);
1353
1354        return true;
1355}
1356
1357/* FSINFO */
1358int
1359nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p)
1360{
1361        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1362        struct nfsd3_fsinfores *resp = rqstp->rq_resp;
1363
1364        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1365                return 0;
1366        switch (resp->status) {
1367        case nfs_ok:
1368                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1369                        return 0;
1370                if (!svcxdr_encode_fsinfo3resok(xdr, resp))
1371                        return 0;
1372                break;
1373        default:
1374                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1375                        return 0;
1376        }
1377
1378        return 1;
1379}
1380
1381static bool
1382svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
1383                             const struct nfsd3_pathconfres *resp)
1384{
1385        __be32 *p;
1386
1387        p = xdr_reserve_space(xdr, XDR_UNIT * 6);
1388        if (!p)
1389                return false;
1390        *p++ = cpu_to_be32(resp->p_link_max);
1391        *p++ = cpu_to_be32(resp->p_name_max);
1392        p = xdr_encode_bool(p, resp->p_no_trunc);
1393        p = xdr_encode_bool(p, resp->p_chown_restricted);
1394        p = xdr_encode_bool(p, resp->p_case_insensitive);
1395        xdr_encode_bool(p, resp->p_case_preserving);
1396
1397        return true;
1398}
1399
1400/* PATHCONF */
1401int
1402nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p)
1403{
1404        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1405        struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1406
1407        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1408                return 0;
1409        switch (resp->status) {
1410        case nfs_ok:
1411                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1412                        return 0;
1413                if (!svcxdr_encode_pathconf3resok(xdr, resp))
1414                        return 0;
1415                break;
1416        default:
1417                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1418                        return 0;
1419        }
1420
1421        return 1;
1422}
1423
1424/* COMMIT */
1425int
1426nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p)
1427{
1428        struct xdr_stream *xdr = &rqstp->rq_res_stream;
1429        struct nfsd3_commitres *resp = rqstp->rq_resp;
1430
1431        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1432                return 0;
1433        switch (resp->status) {
1434        case nfs_ok:
1435                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1436                        return 0;
1437                if (!svcxdr_encode_writeverf3(xdr, resp->verf))
1438                        return 0;
1439                break;
1440        default:
1441                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1442                        return 0;
1443        }
1444
1445        return 1;
1446}
1447
1448/*
1449 * XDR release functions
1450 */
1451void
1452nfs3svc_release_fhandle(struct svc_rqst *rqstp)
1453{
1454        struct nfsd3_attrstat *resp = rqstp->rq_resp;
1455
1456        fh_put(&resp->fh);
1457}
1458
1459void
1460nfs3svc_release_fhandle2(struct svc_rqst *rqstp)
1461{
1462        struct nfsd3_fhandle_pair *resp = rqstp->rq_resp;
1463
1464        fh_put(&resp->fh1);
1465        fh_put(&resp->fh2);
1466}
1467