Linux Audio

Check our new training course

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