linux/fs/nfsd/nfsxdr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * XDR support for nfsd
   4 *
   5 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
   6 */
   7
   8#include "vfs.h"
   9#include "xdr.h"
  10#include "auth.h"
  11
  12/*
  13 * Mapping of S_IF* types to NFS file types
  14 */
  15static const u32 nfs_ftypes[] = {
  16        NFNON,  NFCHR,  NFCHR, NFBAD,
  17        NFDIR,  NFBAD,  NFBLK, NFBAD,
  18        NFREG,  NFBAD,  NFLNK, NFBAD,
  19        NFSOCK, NFBAD,  NFLNK, NFBAD,
  20};
  21
  22
  23/*
  24 * Basic NFSv2 data types (RFC 1094 Section 2.3)
  25 */
  26
  27/**
  28 * svcxdr_encode_stat - Encode an NFSv2 status code
  29 * @xdr: XDR stream
  30 * @status: status value to encode
  31 *
  32 * Return values:
  33 *   %false: Send buffer space was exhausted
  34 *   %true: Success
  35 */
  36bool
  37svcxdr_encode_stat(struct xdr_stream *xdr, __be32 status)
  38{
  39        __be32 *p;
  40
  41        p = xdr_reserve_space(xdr, sizeof(status));
  42        if (!p)
  43                return false;
  44        *p = status;
  45
  46        return true;
  47}
  48
  49/**
  50 * svcxdr_decode_fhandle - Decode an NFSv2 file handle
  51 * @xdr: XDR stream positioned at an encoded NFSv2 FH
  52 * @fhp: OUT: filled-in server file handle
  53 *
  54 * Return values:
  55 *  %false: The encoded file handle was not valid
  56 *  %true: @fhp has been initialized
  57 */
  58bool
  59svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp)
  60{
  61        __be32 *p;
  62
  63        p = xdr_inline_decode(xdr, NFS_FHSIZE);
  64        if (!p)
  65                return false;
  66        fh_init(fhp, NFS_FHSIZE);
  67        memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
  68        fhp->fh_handle.fh_size = NFS_FHSIZE;
  69
  70        return true;
  71}
  72
  73static bool
  74svcxdr_encode_fhandle(struct xdr_stream *xdr, const struct svc_fh *fhp)
  75{
  76        __be32 *p;
  77
  78        p = xdr_reserve_space(xdr, NFS_FHSIZE);
  79        if (!p)
  80                return false;
  81        memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
  82
  83        return true;
  84}
  85
  86static __be32 *
  87encode_timeval(__be32 *p, const struct timespec64 *time)
  88{
  89        *p++ = cpu_to_be32((u32)time->tv_sec);
  90        if (time->tv_nsec)
  91                *p++ = cpu_to_be32(time->tv_nsec / NSEC_PER_USEC);
  92        else
  93                *p++ = xdr_zero;
  94        return p;
  95}
  96
  97static bool
  98svcxdr_decode_filename(struct xdr_stream *xdr, char **name, unsigned int *len)
  99{
 100        u32 size, i;
 101        __be32 *p;
 102        char *c;
 103
 104        if (xdr_stream_decode_u32(xdr, &size) < 0)
 105                return false;
 106        if (size == 0 || size > NFS_MAXNAMLEN)
 107                return false;
 108        p = xdr_inline_decode(xdr, size);
 109        if (!p)
 110                return false;
 111
 112        *len = size;
 113        *name = (char *)p;
 114        for (i = 0, c = *name; i < size; i++, c++)
 115                if (*c == '\0' || *c == '/')
 116                        return false;
 117
 118        return true;
 119}
 120
 121static bool
 122svcxdr_decode_diropargs(struct xdr_stream *xdr, struct svc_fh *fhp,
 123                        char **name, unsigned int *len)
 124{
 125        return svcxdr_decode_fhandle(xdr, fhp) &&
 126                svcxdr_decode_filename(xdr, name, len);
 127}
 128
 129static bool
 130svcxdr_decode_sattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 131                    struct iattr *iap)
 132{
 133        u32 tmp1, tmp2;
 134        __be32 *p;
 135
 136        p = xdr_inline_decode(xdr, XDR_UNIT * 8);
 137        if (!p)
 138                return false;
 139
 140        iap->ia_valid = 0;
 141
 142        /*
 143         * Some Sun clients put 0xffff in the mode field when they
 144         * mean 0xffffffff.
 145         */
 146        tmp1 = be32_to_cpup(p++);
 147        if (tmp1 != (u32)-1 && tmp1 != 0xffff) {
 148                iap->ia_valid |= ATTR_MODE;
 149                iap->ia_mode = tmp1;
 150        }
 151
 152        tmp1 = be32_to_cpup(p++);
 153        if (tmp1 != (u32)-1) {
 154                iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), tmp1);
 155                if (uid_valid(iap->ia_uid))
 156                        iap->ia_valid |= ATTR_UID;
 157        }
 158
 159        tmp1 = be32_to_cpup(p++);
 160        if (tmp1 != (u32)-1) {
 161                iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), tmp1);
 162                if (gid_valid(iap->ia_gid))
 163                        iap->ia_valid |= ATTR_GID;
 164        }
 165
 166        tmp1 = be32_to_cpup(p++);
 167        if (tmp1 != (u32)-1) {
 168                iap->ia_valid |= ATTR_SIZE;
 169                iap->ia_size = tmp1;
 170        }
 171
 172        tmp1 = be32_to_cpup(p++);
 173        tmp2 = be32_to_cpup(p++);
 174        if (tmp1 != (u32)-1 && tmp2 != (u32)-1) {
 175                iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
 176                iap->ia_atime.tv_sec = tmp1;
 177                iap->ia_atime.tv_nsec = tmp2 * NSEC_PER_USEC;
 178        }
 179
 180        tmp1 = be32_to_cpup(p++);
 181        tmp2 = be32_to_cpup(p++);
 182        if (tmp1 != (u32)-1 && tmp2 != (u32)-1) {
 183                iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
 184                iap->ia_mtime.tv_sec = tmp1;
 185                iap->ia_mtime.tv_nsec = tmp2 * NSEC_PER_USEC;
 186                /*
 187                 * Passing the invalid value useconds=1000000 for mtime
 188                 * is a Sun convention for "set both mtime and atime to
 189                 * current server time".  It's needed to make permissions
 190                 * checks for the "touch" program across v2 mounts to
 191                 * Solaris and Irix boxes work correctly. See description of
 192                 * sattr in section 6.1 of "NFS Illustrated" by
 193                 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
 194                 */
 195                if (tmp2 == 1000000)
 196                        iap->ia_valid &= ~(ATTR_ATIME_SET|ATTR_MTIME_SET);
 197        }
 198
 199        return true;
 200}
 201
 202/**
 203 * svcxdr_encode_fattr - Encode NFSv2 file attributes
 204 * @rqstp: Context of a completed RPC transaction
 205 * @xdr: XDR stream
 206 * @fhp: File handle to encode
 207 * @stat: Attributes to encode
 208 *
 209 * Return values:
 210 *   %false: Send buffer space was exhausted
 211 *   %true: Success
 212 */
 213bool
 214svcxdr_encode_fattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 215                    const struct svc_fh *fhp, const struct kstat *stat)
 216{
 217        struct user_namespace *userns = nfsd_user_namespace(rqstp);
 218        struct dentry *dentry = fhp->fh_dentry;
 219        int type = stat->mode & S_IFMT;
 220        struct timespec64 time;
 221        __be32 *p;
 222        u32 fsid;
 223
 224        p = xdr_reserve_space(xdr, XDR_UNIT * 17);
 225        if (!p)
 226                return false;
 227
 228        *p++ = cpu_to_be32(nfs_ftypes[type >> 12]);
 229        *p++ = cpu_to_be32((u32)stat->mode);
 230        *p++ = cpu_to_be32((u32)stat->nlink);
 231        *p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid));
 232        *p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid));
 233
 234        if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN)
 235                *p++ = cpu_to_be32(NFS_MAXPATHLEN);
 236        else
 237                *p++ = cpu_to_be32((u32) stat->size);
 238        *p++ = cpu_to_be32((u32) stat->blksize);
 239        if (S_ISCHR(type) || S_ISBLK(type))
 240                *p++ = cpu_to_be32(new_encode_dev(stat->rdev));
 241        else
 242                *p++ = cpu_to_be32(0xffffffff);
 243        *p++ = cpu_to_be32((u32)stat->blocks);
 244
 245        switch (fsid_source(fhp)) {
 246        case FSIDSOURCE_FSID:
 247                fsid = (u32)fhp->fh_export->ex_fsid;
 248                break;
 249        case FSIDSOURCE_UUID:
 250                fsid = ((u32 *)fhp->fh_export->ex_uuid)[0];
 251                fsid ^= ((u32 *)fhp->fh_export->ex_uuid)[1];
 252                fsid ^= ((u32 *)fhp->fh_export->ex_uuid)[2];
 253                fsid ^= ((u32 *)fhp->fh_export->ex_uuid)[3];
 254                break;
 255        default:
 256                fsid = new_encode_dev(stat->dev);
 257                break;
 258        }
 259        *p++ = cpu_to_be32(fsid);
 260
 261        *p++ = cpu_to_be32((u32)stat->ino);
 262        p = encode_timeval(p, &stat->atime);
 263        time = stat->mtime;
 264        lease_get_mtime(d_inode(dentry), &time);
 265        p = encode_timeval(p, &time);
 266        encode_timeval(p, &stat->ctime);
 267
 268        return true;
 269}
 270
 271/*
 272 * XDR decode functions
 273 */
 274
 275int
 276nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p)
 277{
 278        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 279        struct nfsd_fhandle *args = rqstp->rq_argp;
 280
 281        return svcxdr_decode_fhandle(xdr, &args->fh);
 282}
 283
 284int
 285nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
 286{
 287        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 288        struct nfsd_sattrargs *args = rqstp->rq_argp;
 289
 290        return svcxdr_decode_fhandle(xdr, &args->fh) &&
 291                svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
 292}
 293
 294int
 295nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
 296{
 297        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 298        struct nfsd_diropargs *args = rqstp->rq_argp;
 299
 300        return svcxdr_decode_diropargs(xdr, &args->fh, &args->name, &args->len);
 301}
 302
 303int
 304nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
 305{
 306        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 307        struct nfsd_readargs *args = rqstp->rq_argp;
 308        u32 totalcount;
 309
 310        if (!svcxdr_decode_fhandle(xdr, &args->fh))
 311                return 0;
 312        if (xdr_stream_decode_u32(xdr, &args->offset) < 0)
 313                return 0;
 314        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 315                return 0;
 316        /* totalcount is ignored */
 317        if (xdr_stream_decode_u32(xdr, &totalcount) < 0)
 318                return 0;
 319
 320        return 1;
 321}
 322
 323int
 324nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
 325{
 326        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 327        struct nfsd_writeargs *args = rqstp->rq_argp;
 328        struct kvec *head = rqstp->rq_arg.head;
 329        struct kvec *tail = rqstp->rq_arg.tail;
 330        u32 beginoffset, totalcount;
 331        size_t remaining;
 332
 333        if (!svcxdr_decode_fhandle(xdr, &args->fh))
 334                return 0;
 335        /* beginoffset is ignored */
 336        if (xdr_stream_decode_u32(xdr, &beginoffset) < 0)
 337                return 0;
 338        if (xdr_stream_decode_u32(xdr, &args->offset) < 0)
 339                return 0;
 340        /* totalcount is ignored */
 341        if (xdr_stream_decode_u32(xdr, &totalcount) < 0)
 342                return 0;
 343
 344        /* opaque data */
 345        if (xdr_stream_decode_u32(xdr, &args->len) < 0)
 346                return 0;
 347        if (args->len > NFSSVC_MAXBLKSIZE_V2)
 348                return 0;
 349        remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len;
 350        remaining -= xdr_stream_pos(xdr);
 351        if (remaining < xdr_align_size(args->len))
 352                return 0;
 353        args->first.iov_base = xdr->p;
 354        args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 355
 356        return 1;
 357}
 358
 359int
 360nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
 361{
 362        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 363        struct nfsd_createargs *args = rqstp->rq_argp;
 364
 365        return svcxdr_decode_diropargs(xdr, &args->fh,
 366                                       &args->name, &args->len) &&
 367                svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
 368}
 369
 370int
 371nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 372{
 373        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 374        struct nfsd_renameargs *args = rqstp->rq_argp;
 375
 376        return svcxdr_decode_diropargs(xdr, &args->ffh,
 377                                       &args->fname, &args->flen) &&
 378                svcxdr_decode_diropargs(xdr, &args->tfh,
 379                                        &args->tname, &args->tlen);
 380}
 381
 382int
 383nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 384{
 385        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 386        struct nfsd_linkargs *args = rqstp->rq_argp;
 387
 388        return svcxdr_decode_fhandle(xdr, &args->ffh) &&
 389                svcxdr_decode_diropargs(xdr, &args->tfh,
 390                                        &args->tname, &args->tlen);
 391}
 392
 393int
 394nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
 395{
 396        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 397        struct nfsd_symlinkargs *args = rqstp->rq_argp;
 398        struct kvec *head = rqstp->rq_arg.head;
 399
 400        if (!svcxdr_decode_diropargs(xdr, &args->ffh, &args->fname, &args->flen))
 401                return 0;
 402        if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
 403                return 0;
 404        if (args->tlen == 0)
 405                return 0;
 406
 407        args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 408        args->first.iov_base = xdr_inline_decode(xdr, args->tlen);
 409        if (!args->first.iov_base)
 410                return 0;
 411        return svcxdr_decode_sattr(rqstp, xdr, &args->attrs);
 412}
 413
 414int
 415nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 416{
 417        struct xdr_stream *xdr = &rqstp->rq_arg_stream;
 418        struct nfsd_readdirargs *args = rqstp->rq_argp;
 419
 420        if (!svcxdr_decode_fhandle(xdr, &args->fh))
 421                return 0;
 422        if (xdr_stream_decode_u32(xdr, &args->cookie) < 0)
 423                return 0;
 424        if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 425                return 0;
 426
 427        return 1;
 428}
 429
 430/*
 431 * XDR encode functions
 432 */
 433
 434int
 435nfssvc_encode_statres(struct svc_rqst *rqstp, __be32 *p)
 436{
 437        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 438        struct nfsd_stat *resp = rqstp->rq_resp;
 439
 440        return svcxdr_encode_stat(xdr, resp->status);
 441}
 442
 443int
 444nfssvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p)
 445{
 446        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 447        struct nfsd_attrstat *resp = rqstp->rq_resp;
 448
 449        if (!svcxdr_encode_stat(xdr, resp->status))
 450                return 0;
 451        switch (resp->status) {
 452        case nfs_ok:
 453                if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
 454                        return 0;
 455                break;
 456        }
 457
 458        return 1;
 459}
 460
 461int
 462nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
 463{
 464        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 465        struct nfsd_diropres *resp = rqstp->rq_resp;
 466
 467        if (!svcxdr_encode_stat(xdr, resp->status))
 468                return 0;
 469        switch (resp->status) {
 470        case nfs_ok:
 471                if (!svcxdr_encode_fhandle(xdr, &resp->fh))
 472                        return 0;
 473                if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
 474                        return 0;
 475                break;
 476        }
 477
 478        return 1;
 479}
 480
 481int
 482nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
 483{
 484        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 485        struct nfsd_readlinkres *resp = rqstp->rq_resp;
 486        struct kvec *head = rqstp->rq_res.head;
 487
 488        if (!svcxdr_encode_stat(xdr, resp->status))
 489                return 0;
 490        switch (resp->status) {
 491        case nfs_ok:
 492                if (xdr_stream_encode_u32(xdr, resp->len) < 0)
 493                        return 0;
 494                xdr_write_pages(xdr, &resp->page, 0, resp->len);
 495                if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
 496                        return 0;
 497                break;
 498        }
 499
 500        return 1;
 501}
 502
 503int
 504nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
 505{
 506        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 507        struct nfsd_readres *resp = rqstp->rq_resp;
 508        struct kvec *head = rqstp->rq_res.head;
 509
 510        if (!svcxdr_encode_stat(xdr, resp->status))
 511                return 0;
 512        switch (resp->status) {
 513        case nfs_ok:
 514                if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat))
 515                        return 0;
 516                if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 517                        return 0;
 518                xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
 519                                resp->count);
 520                if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
 521                        return 0;
 522                break;
 523        }
 524
 525        return 1;
 526}
 527
 528int
 529nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
 530{
 531        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 532        struct nfsd_readdirres *resp = rqstp->rq_resp;
 533        struct xdr_buf *dirlist = &resp->dirlist;
 534
 535        if (!svcxdr_encode_stat(xdr, resp->status))
 536                return 0;
 537        switch (resp->status) {
 538        case nfs_ok:
 539                xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len);
 540                /* no more entries */
 541                if (xdr_stream_encode_item_absent(xdr) < 0)
 542                        return 0;
 543                if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
 544                        return 0;
 545                break;
 546        }
 547
 548        return 1;
 549}
 550
 551int
 552nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
 553{
 554        struct xdr_stream *xdr = &rqstp->rq_res_stream;
 555        struct nfsd_statfsres *resp = rqstp->rq_resp;
 556        struct kstatfs  *stat = &resp->stats;
 557
 558        if (!svcxdr_encode_stat(xdr, resp->status))
 559                return 0;
 560        switch (resp->status) {
 561        case nfs_ok:
 562                p = xdr_reserve_space(xdr, XDR_UNIT * 5);
 563                if (!p)
 564                        return 0;
 565                *p++ = cpu_to_be32(NFSSVC_MAXBLKSIZE_V2);
 566                *p++ = cpu_to_be32(stat->f_bsize);
 567                *p++ = cpu_to_be32(stat->f_blocks);
 568                *p++ = cpu_to_be32(stat->f_bfree);
 569                *p = cpu_to_be32(stat->f_bavail);
 570                break;
 571        }
 572
 573        return 1;
 574}
 575
 576/**
 577 * nfssvc_encode_nfscookie - Encode a directory offset cookie
 578 * @resp: readdir result context
 579 * @offset: offset cookie to encode
 580 *
 581 * The buffer space for the offset cookie has already been reserved
 582 * by svcxdr_encode_entry_common().
 583 */
 584void nfssvc_encode_nfscookie(struct nfsd_readdirres *resp, u32 offset)
 585{
 586        __be32 cookie = cpu_to_be32(offset);
 587
 588        if (!resp->cookie_offset)
 589                return;
 590
 591        write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
 592                               sizeof(cookie));
 593        resp->cookie_offset = 0;
 594}
 595
 596static bool
 597svcxdr_encode_entry_common(struct nfsd_readdirres *resp, const char *name,
 598                           int namlen, loff_t offset, u64 ino)
 599{
 600        struct xdr_buf *dirlist = &resp->dirlist;
 601        struct xdr_stream *xdr = &resp->xdr;
 602
 603        if (xdr_stream_encode_item_present(xdr) < 0)
 604                return false;
 605        /* fileid */
 606        if (xdr_stream_encode_u32(xdr, (u32)ino) < 0)
 607                return false;
 608        /* name */
 609        if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS2_MAXNAMLEN)) < 0)
 610                return false;
 611        /* cookie */
 612        resp->cookie_offset = dirlist->len;
 613        if (xdr_stream_encode_u32(xdr, ~0U) < 0)
 614                return false;
 615
 616        return true;
 617}
 618
 619/**
 620 * nfssvc_encode_entry - encode one NFSv2 READDIR entry
 621 * @data: directory context
 622 * @name: name of the object to be encoded
 623 * @namlen: length of that name, in bytes
 624 * @offset: the offset of the previous entry
 625 * @ino: the fileid of this entry
 626 * @d_type: unused
 627 *
 628 * Return values:
 629 *   %0: Entry was successfully encoded.
 630 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
 631 *
 632 * On exit, the following fields are updated:
 633 *   - resp->xdr
 634 *   - resp->common.err
 635 *   - resp->cookie_offset
 636 */
 637int nfssvc_encode_entry(void *data, const char *name, int namlen,
 638                        loff_t offset, u64 ino, unsigned int d_type)
 639{
 640        struct readdir_cd *ccd = data;
 641        struct nfsd_readdirres *resp = container_of(ccd,
 642                                                    struct nfsd_readdirres,
 643                                                    common);
 644        unsigned int starting_length = resp->dirlist.len;
 645
 646        /* The offset cookie for the previous entry */
 647        nfssvc_encode_nfscookie(resp, offset);
 648
 649        if (!svcxdr_encode_entry_common(resp, name, namlen, offset, ino))
 650                goto out_toosmall;
 651
 652        xdr_commit_encode(&resp->xdr);
 653        resp->common.err = nfs_ok;
 654        return 0;
 655
 656out_toosmall:
 657        resp->cookie_offset = 0;
 658        resp->common.err = nfserr_toosmall;
 659        resp->dirlist.len = starting_length;
 660        return -EINVAL;
 661}
 662
 663/*
 664 * XDR release functions
 665 */
 666void nfssvc_release_attrstat(struct svc_rqst *rqstp)
 667{
 668        struct nfsd_attrstat *resp = rqstp->rq_resp;
 669
 670        fh_put(&resp->fh);
 671}
 672
 673void nfssvc_release_diropres(struct svc_rqst *rqstp)
 674{
 675        struct nfsd_diropres *resp = rqstp->rq_resp;
 676
 677        fh_put(&resp->fh);
 678}
 679
 680void nfssvc_release_readres(struct svc_rqst *rqstp)
 681{
 682        struct nfsd_readres *resp = rqstp->rq_resp;
 683
 684        fh_put(&resp->fh);
 685}
 686