cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nfs3xdr.c (32068B)


      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}