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_raw, 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_raw, 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 = newsize;
 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
 490/*
 491 * XDR decode functions
 492 */
 493
 494bool
 495nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 496{
 497        struct nfsd_fhandle *args = rqstp->rq_argp;
 498
 499        return svcxdr_decode_nfs_fh3(xdr, &args->fh);
 500}
 501
 502bool
 503nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 504{
 505        struct nfsd3_sattrargs *args = rqstp->rq_argp;
 506
 507        return svcxdr_decode_nfs_fh3(xdr, &args->fh) &&
 508                svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
 509                svcxdr_decode_sattrguard3(xdr, args);
 510}
 511
 512bool
 513nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 514{
 515        struct nfsd3_diropargs *args = rqstp->rq_argp;
 516
 517        return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
 518}
 519
 520bool
 521nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 522{
 523        struct nfsd3_accessargs *args = rqstp->rq_argp;
 524
 525        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 526                return false;
 527        if (xdr_stream_decode_u32(xdr, &args->access) < 0)
 528                return false;
 529
 530        return true;
 531}
 532
 533bool
 534nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 535{
 536        struct nfsd3_readargs *args = rqstp->rq_argp;
 537
 538        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 539                return false;
 540        if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 541                return false;
 542        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 543                return false;
 544
 545        return true;
 546}
 547
 548bool
 549nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 550{
 551        struct nfsd3_writeargs *args = rqstp->rq_argp;
 552        u32 max_blocksize = svc_max_payload(rqstp);
 553
 554        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 555                return false;
 556        if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 557                return false;
 558        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 559                return false;
 560        if (xdr_stream_decode_u32(xdr, &args->stable) < 0)
 561                return false;
 562
 563        /* opaque data */
 564        if (xdr_stream_decode_u32(xdr, &args->len) < 0)
 565                return false;
 566
 567        /* request sanity */
 568        if (args->count != args->len)
 569                return false;
 570        if (args->count > max_blocksize) {
 571                args->count = max_blocksize;
 572                args->len = max_blocksize;
 573        }
 574        if (!xdr_stream_subsegment(xdr, &args->payload, args->count))
 575                return false;
 576
 577        return true;
 578}
 579
 580bool
 581nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 582{
 583        struct nfsd3_createargs *args = rqstp->rq_argp;
 584
 585        if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
 586                return false;
 587        if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
 588                return false;
 589        switch (args->createmode) {
 590        case NFS3_CREATE_UNCHECKED:
 591        case NFS3_CREATE_GUARDED:
 592                return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 593        case NFS3_CREATE_EXCLUSIVE:
 594                args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
 595                if (!args->verf)
 596                        return false;
 597                break;
 598        default:
 599                return false;
 600        }
 601        return true;
 602}
 603
 604bool
 605nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 606{
 607        struct nfsd3_createargs *args = rqstp->rq_argp;
 608
 609        return svcxdr_decode_diropargs3(xdr, &args->fh,
 610                                        &args->name, &args->len) &&
 611                svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 612}
 613
 614bool
 615nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 616{
 617        struct nfsd3_symlinkargs *args = rqstp->rq_argp;
 618        struct kvec *head = rqstp->rq_arg.head;
 619        struct kvec *tail = rqstp->rq_arg.tail;
 620        size_t remaining;
 621
 622        if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
 623                return false;
 624        if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
 625                return false;
 626        if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
 627                return false;
 628
 629        /* request sanity */
 630        remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
 631        remaining -= xdr_stream_pos(xdr);
 632        if (remaining < xdr_align_size(args->tlen))
 633                return false;
 634
 635        args->first.iov_base = xdr->p;
 636        args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 637
 638        return true;
 639}
 640
 641bool
 642nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 643{
 644        struct nfsd3_mknodargs *args = rqstp->rq_argp;
 645
 646        if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
 647                return false;
 648        if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
 649                return false;
 650        switch (args->ftype) {
 651        case NF3CHR:
 652        case NF3BLK:
 653                return svcxdr_decode_devicedata3(rqstp, xdr, args);
 654        case NF3SOCK:
 655        case NF3FIFO:
 656                return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 657        case NF3REG:
 658        case NF3DIR:
 659        case NF3LNK:
 660                /* Valid XDR but illegal file types */
 661                break;
 662        default:
 663                return false;
 664        }
 665
 666        return true;
 667}
 668
 669bool
 670nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 671{
 672        struct nfsd3_renameargs *args = rqstp->rq_argp;
 673
 674        return svcxdr_decode_diropargs3(xdr, &args->ffh,
 675                                        &args->fname, &args->flen) &&
 676                svcxdr_decode_diropargs3(xdr, &args->tfh,
 677                                         &args->tname, &args->tlen);
 678}
 679
 680bool
 681nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 682{
 683        struct nfsd3_linkargs *args = rqstp->rq_argp;
 684
 685        return svcxdr_decode_nfs_fh3(xdr, &args->ffh) &&
 686                svcxdr_decode_diropargs3(xdr, &args->tfh,
 687                                         &args->tname, &args->tlen);
 688}
 689
 690bool
 691nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 692{
 693        struct nfsd3_readdirargs *args = rqstp->rq_argp;
 694
 695        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 696                return false;
 697        if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
 698                return false;
 699        args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 700        if (!args->verf)
 701                return false;
 702        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 703                return false;
 704
 705        return true;
 706}
 707
 708bool
 709nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 710{
 711        struct nfsd3_readdirargs *args = rqstp->rq_argp;
 712        u32 dircount;
 713
 714        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 715                return false;
 716        if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
 717                return false;
 718        args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 719        if (!args->verf)
 720                return false;
 721        /* dircount is ignored */
 722        if (xdr_stream_decode_u32(xdr, &dircount) < 0)
 723                return false;
 724        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 725                return false;
 726
 727        return true;
 728}
 729
 730bool
 731nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 732{
 733        struct nfsd3_commitargs *args = rqstp->rq_argp;
 734
 735        if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 736                return false;
 737        if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 738                return false;
 739        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 740                return false;
 741
 742        return true;
 743}
 744
 745/*
 746 * XDR encode functions
 747 */
 748
 749/* GETATTR */
 750bool
 751nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 752{
 753        struct nfsd3_attrstat *resp = rqstp->rq_resp;
 754
 755        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 756                return false;
 757        switch (resp->status) {
 758        case nfs_ok:
 759                lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime);
 760                if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat))
 761                        return false;
 762                break;
 763        }
 764
 765        return true;
 766}
 767
 768/* SETATTR, REMOVE, RMDIR */
 769bool
 770nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 771{
 772        struct nfsd3_attrstat *resp = rqstp->rq_resp;
 773
 774        return svcxdr_encode_nfsstat3(xdr, resp->status) &&
 775                svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh);
 776}
 777
 778/* LOOKUP */
 779bool
 780nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 781{
 782        struct nfsd3_diropres *resp = rqstp->rq_resp;
 783
 784        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 785                return false;
 786        switch (resp->status) {
 787        case nfs_ok:
 788                if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh))
 789                        return false;
 790                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 791                        return false;
 792                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
 793                        return false;
 794                break;
 795        default:
 796                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
 797                        return false;
 798        }
 799
 800        return true;
 801}
 802
 803/* ACCESS */
 804bool
 805nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 806{
 807        struct nfsd3_accessres *resp = rqstp->rq_resp;
 808
 809        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 810                return false;
 811        switch (resp->status) {
 812        case nfs_ok:
 813                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 814                        return false;
 815                if (xdr_stream_encode_u32(xdr, resp->access) < 0)
 816                        return false;
 817                break;
 818        default:
 819                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 820                        return false;
 821        }
 822
 823        return true;
 824}
 825
 826/* READLINK */
 827bool
 828nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 829{
 830        struct nfsd3_readlinkres *resp = rqstp->rq_resp;
 831        struct kvec *head = rqstp->rq_res.head;
 832
 833        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 834                return false;
 835        switch (resp->status) {
 836        case nfs_ok:
 837                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 838                        return false;
 839                if (xdr_stream_encode_u32(xdr, resp->len) < 0)
 840                        return false;
 841                xdr_write_pages(xdr, resp->pages, 0, resp->len);
 842                if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
 843                        return false;
 844                break;
 845        default:
 846                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 847                        return false;
 848        }
 849
 850        return true;
 851}
 852
 853/* READ */
 854bool
 855nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 856{
 857        struct nfsd3_readres *resp = rqstp->rq_resp;
 858        struct kvec *head = rqstp->rq_res.head;
 859
 860        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 861                return false;
 862        switch (resp->status) {
 863        case nfs_ok:
 864                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 865                        return false;
 866                if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 867                        return false;
 868                if (xdr_stream_encode_bool(xdr, resp->eof) < 0)
 869                        return false;
 870                if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 871                        return false;
 872                xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
 873                                resp->count);
 874                if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
 875                        return false;
 876                break;
 877        default:
 878                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 879                        return false;
 880        }
 881
 882        return true;
 883}
 884
 885/* WRITE */
 886bool
 887nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 888{
 889        struct nfsd3_writeres *resp = rqstp->rq_resp;
 890
 891        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 892                return false;
 893        switch (resp->status) {
 894        case nfs_ok:
 895                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
 896                        return false;
 897                if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 898                        return false;
 899                if (xdr_stream_encode_u32(xdr, resp->committed) < 0)
 900                        return false;
 901                if (!svcxdr_encode_writeverf3(xdr, resp->verf))
 902                        return false;
 903                break;
 904        default:
 905                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
 906                        return false;
 907        }
 908
 909        return true;
 910}
 911
 912/* CREATE, MKDIR, SYMLINK, MKNOD */
 913bool
 914nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 915{
 916        struct nfsd3_diropres *resp = rqstp->rq_resp;
 917
 918        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 919                return false;
 920        switch (resp->status) {
 921        case nfs_ok:
 922                if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh))
 923                        return false;
 924                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 925                        return false;
 926                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
 927                        return false;
 928                break;
 929        default:
 930                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
 931                        return false;
 932        }
 933
 934        return true;
 935}
 936
 937/* RENAME */
 938bool
 939nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 940{
 941        struct nfsd3_renameres *resp = rqstp->rq_resp;
 942
 943        return svcxdr_encode_nfsstat3(xdr, resp->status) &&
 944                svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) &&
 945                svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
 946}
 947
 948/* LINK */
 949bool
 950nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 951{
 952        struct nfsd3_linkres *resp = rqstp->rq_resp;
 953
 954        return svcxdr_encode_nfsstat3(xdr, resp->status) &&
 955                svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) &&
 956                svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
 957}
 958
 959/* READDIR */
 960bool
 961nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 962{
 963        struct nfsd3_readdirres *resp = rqstp->rq_resp;
 964        struct xdr_buf *dirlist = &resp->dirlist;
 965
 966        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 967                return false;
 968        switch (resp->status) {
 969        case nfs_ok:
 970                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 971                        return false;
 972                if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
 973                        return false;
 974                xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len);
 975                /* no more entries */
 976                if (xdr_stream_encode_item_absent(xdr) < 0)
 977                        return false;
 978                if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
 979                        return false;
 980                break;
 981        default:
 982                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 983                        return false;
 984        }
 985
 986        return true;
 987}
 988
 989static __be32
 990compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
 991                 const char *name, int namlen, u64 ino)
 992{
 993        struct svc_export       *exp;
 994        struct dentry           *dparent, *dchild;
 995        __be32 rv = nfserr_noent;
 996
 997        dparent = cd->fh.fh_dentry;
 998        exp  = cd->fh.fh_export;
 999
1000        if (isdotent(name, namlen)) {
1001                if (namlen == 2) {
1002                        dchild = dget_parent(dparent);
1003                        /*
1004                         * Don't return filehandle for ".." if we're at
1005                         * the filesystem or export root:
1006                         */
1007                        if (dchild == dparent)
1008                                goto out;
1009                        if (dparent == exp->ex_path.dentry)
1010                                goto out;
1011                } else
1012                        dchild = dget(dparent);
1013        } else
1014                dchild = lookup_positive_unlocked(name, dparent, namlen);
1015        if (IS_ERR(dchild))
1016                return rv;
1017        if (d_mountpoint(dchild))
1018                goto out;
1019        if (dchild->d_inode->i_ino != ino)
1020                goto out;
1021        rv = fh_compose(fhp, exp, dchild, &cd->fh);
1022out:
1023        dput(dchild);
1024        return rv;
1025}
1026
1027/**
1028 * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1029 * @resp: readdir result context
1030 * @offset: offset cookie to encode
1031 *
1032 * The buffer space for the offset cookie has already been reserved
1033 * by svcxdr_encode_entry3_common().
1034 */
1035void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset)
1036{
1037        __be64 cookie = cpu_to_be64(offset);
1038
1039        if (!resp->cookie_offset)
1040                return;
1041        write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
1042                               sizeof(cookie));
1043        resp->cookie_offset = 0;
1044}
1045
1046static bool
1047svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name,
1048                            int namlen, loff_t offset, u64 ino)
1049{
1050        struct xdr_buf *dirlist = &resp->dirlist;
1051        struct xdr_stream *xdr = &resp->xdr;
1052
1053        if (xdr_stream_encode_item_present(xdr) < 0)
1054                return false;
1055        /* fileid */
1056        if (xdr_stream_encode_u64(xdr, ino) < 0)
1057                return false;
1058        /* name */
1059        if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0)
1060                return false;
1061        /* cookie */
1062        resp->cookie_offset = dirlist->len;
1063        if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0)
1064                return false;
1065
1066        return true;
1067}
1068
1069/**
1070 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1071 * @data: directory context
1072 * @name: name of the object to be encoded
1073 * @namlen: length of that name, in bytes
1074 * @offset: the offset of the previous entry
1075 * @ino: the fileid of this entry
1076 * @d_type: unused
1077 *
1078 * Return values:
1079 *   %0: Entry was successfully encoded.
1080 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1081 *
1082 * On exit, the following fields are updated:
1083 *   - resp->xdr
1084 *   - resp->common.err
1085 *   - resp->cookie_offset
1086 */
1087int nfs3svc_encode_entry3(void *data, const char *name, int namlen,
1088                          loff_t offset, u64 ino, unsigned int d_type)
1089{
1090        struct readdir_cd *ccd = data;
1091        struct nfsd3_readdirres *resp = container_of(ccd,
1092                                                     struct nfsd3_readdirres,
1093                                                     common);
1094        unsigned int starting_length = resp->dirlist.len;
1095
1096        /* The offset cookie for the previous entry */
1097        nfs3svc_encode_cookie3(resp, offset);
1098
1099        if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1100                goto out_toosmall;
1101
1102        xdr_commit_encode(&resp->xdr);
1103        resp->common.err = nfs_ok;
1104        return 0;
1105
1106out_toosmall:
1107        resp->cookie_offset = 0;
1108        resp->common.err = nfserr_toosmall;
1109        resp->dirlist.len = starting_length;
1110        return -EINVAL;
1111}
1112
1113static bool
1114svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name,
1115                          int namlen, u64 ino)
1116{
1117        struct xdr_stream *xdr = &resp->xdr;
1118        struct svc_fh *fhp = &resp->scratch;
1119        bool result;
1120
1121        result = false;
1122        fh_init(fhp, NFS3_FHSIZE);
1123        if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok)
1124                goto out_noattrs;
1125
1126        if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp))
1127                goto out;
1128        if (!svcxdr_encode_post_op_fh3(xdr, fhp))
1129                goto out;
1130        result = true;
1131
1132out:
1133        fh_put(fhp);
1134        return result;
1135
1136out_noattrs:
1137        if (xdr_stream_encode_item_absent(xdr) < 0)
1138                return false;
1139        if (xdr_stream_encode_item_absent(xdr) < 0)
1140                return false;
1141        return true;
1142}
1143
1144/**
1145 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1146 * @data: directory context
1147 * @name: name of the object to be encoded
1148 * @namlen: length of that name, in bytes
1149 * @offset: the offset of the previous entry
1150 * @ino: the fileid of this entry
1151 * @d_type: unused
1152 *
1153 * Return values:
1154 *   %0: Entry was successfully encoded.
1155 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1156 *
1157 * On exit, the following fields are updated:
1158 *   - resp->xdr
1159 *   - resp->common.err
1160 *   - resp->cookie_offset
1161 */
1162int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,
1163                              loff_t offset, u64 ino, unsigned int d_type)
1164{
1165        struct readdir_cd *ccd = data;
1166        struct nfsd3_readdirres *resp = container_of(ccd,
1167                                                     struct nfsd3_readdirres,
1168                                                     common);
1169        unsigned int starting_length = resp->dirlist.len;
1170
1171        /* The offset cookie for the previous entry */
1172        nfs3svc_encode_cookie3(resp, offset);
1173
1174        if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1175                goto out_toosmall;
1176        if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino))
1177                goto out_toosmall;
1178
1179        xdr_commit_encode(&resp->xdr);
1180        resp->common.err = nfs_ok;
1181        return 0;
1182
1183out_toosmall:
1184        resp->cookie_offset = 0;
1185        resp->common.err = nfserr_toosmall;
1186        resp->dirlist.len = starting_length;
1187        return -EINVAL;
1188}
1189
1190static bool
1191svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
1192                           const struct nfsd3_fsstatres *resp)
1193{
1194        const struct kstatfs *s = &resp->stats;
1195        u64 bs = s->f_bsize;
1196        __be32 *p;
1197
1198        p = xdr_reserve_space(xdr, XDR_UNIT * 13);
1199        if (!p)
1200                return false;
1201        p = xdr_encode_hyper(p, bs * s->f_blocks);      /* total bytes */
1202        p = xdr_encode_hyper(p, bs * s->f_bfree);       /* free bytes */
1203        p = xdr_encode_hyper(p, bs * s->f_bavail);      /* user available bytes */
1204        p = xdr_encode_hyper(p, s->f_files);            /* total inodes */
1205        p = xdr_encode_hyper(p, s->f_ffree);            /* free inodes */
1206        p = xdr_encode_hyper(p, s->f_ffree);            /* user available inodes */
1207        *p = cpu_to_be32(resp->invarsec);               /* mean unchanged time */
1208
1209        return true;
1210}
1211
1212/* FSSTAT */
1213bool
1214nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1215{
1216        struct nfsd3_fsstatres *resp = rqstp->rq_resp;
1217
1218        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1219                return false;
1220        switch (resp->status) {
1221        case nfs_ok:
1222                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1223                        return false;
1224                if (!svcxdr_encode_fsstat3resok(xdr, resp))
1225                        return false;
1226                break;
1227        default:
1228                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1229                        return false;
1230        }
1231
1232        return true;
1233}
1234
1235static bool
1236svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
1237                           const struct nfsd3_fsinfores *resp)
1238{
1239        __be32 *p;
1240
1241        p = xdr_reserve_space(xdr, XDR_UNIT * 12);
1242        if (!p)
1243                return false;
1244        *p++ = cpu_to_be32(resp->f_rtmax);
1245        *p++ = cpu_to_be32(resp->f_rtpref);
1246        *p++ = cpu_to_be32(resp->f_rtmult);
1247        *p++ = cpu_to_be32(resp->f_wtmax);
1248        *p++ = cpu_to_be32(resp->f_wtpref);
1249        *p++ = cpu_to_be32(resp->f_wtmult);
1250        *p++ = cpu_to_be32(resp->f_dtpref);
1251        p = xdr_encode_hyper(p, resp->f_maxfilesize);
1252        p = encode_nfstime3(p, &nfs3svc_time_delta);
1253        *p = cpu_to_be32(resp->f_properties);
1254
1255        return true;
1256}
1257
1258/* FSINFO */
1259bool
1260nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1261{
1262        struct nfsd3_fsinfores *resp = rqstp->rq_resp;
1263
1264        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1265                return false;
1266        switch (resp->status) {
1267        case nfs_ok:
1268                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1269                        return false;
1270                if (!svcxdr_encode_fsinfo3resok(xdr, resp))
1271                        return false;
1272                break;
1273        default:
1274                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1275                        return false;
1276        }
1277
1278        return true;
1279}
1280
1281static bool
1282svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
1283                             const struct nfsd3_pathconfres *resp)
1284{
1285        __be32 *p;
1286
1287        p = xdr_reserve_space(xdr, XDR_UNIT * 6);
1288        if (!p)
1289                return false;
1290        *p++ = cpu_to_be32(resp->p_link_max);
1291        *p++ = cpu_to_be32(resp->p_name_max);
1292        p = xdr_encode_bool(p, resp->p_no_trunc);
1293        p = xdr_encode_bool(p, resp->p_chown_restricted);
1294        p = xdr_encode_bool(p, resp->p_case_insensitive);
1295        xdr_encode_bool(p, resp->p_case_preserving);
1296
1297        return true;
1298}
1299
1300/* PATHCONF */
1301bool
1302nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1303{
1304        struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1305
1306        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1307                return false;
1308        switch (resp->status) {
1309        case nfs_ok:
1310                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1311                        return false;
1312                if (!svcxdr_encode_pathconf3resok(xdr, resp))
1313                        return false;
1314                break;
1315        default:
1316                if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1317                        return false;
1318        }
1319
1320        return true;
1321}
1322
1323/* COMMIT */
1324bool
1325nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1326{
1327        struct nfsd3_commitres *resp = rqstp->rq_resp;
1328
1329        if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1330                return false;
1331        switch (resp->status) {
1332        case nfs_ok:
1333                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1334                        return false;
1335                if (!svcxdr_encode_writeverf3(xdr, resp->verf))
1336                        return false;
1337                break;
1338        default:
1339                if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1340                        return false;
1341        }
1342
1343        return true;
1344}
1345
1346/*
1347 * XDR release functions
1348 */
1349void
1350nfs3svc_release_fhandle(struct svc_rqst *rqstp)
1351{
1352        struct nfsd3_attrstat *resp = rqstp->rq_resp;
1353
1354        fh_put(&resp->fh);
1355}
1356
1357void
1358nfs3svc_release_fhandle2(struct svc_rqst *rqstp)
1359{
1360        struct nfsd3_fhandle_pair *resp = rqstp->rq_resp;
1361
1362        fh_put(&resp->fh1);
1363        fh_put(&resp->fh2);
1364}
1365