PageRenderTime 79ms CodeModel.GetById 19ms app.highlight 51ms RepoModel.GetById 0ms app.codeStats 0ms

/fs/nfs/nfs3xdr.c

https://bitbucket.org/emiliolopez/linux
C | 2619 lines | 1530 code | 235 blank | 854 comment | 202 complexity | a835e2644dce104062f9300ac141c121 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * linux/fs/nfs/nfs3xdr.c
   4 *
   5 * XDR functions to encode/decode NFSv3 RPC arguments and results.
   6 *
   7 * Copyright (C) 1996, 1997 Olaf Kirch
   8 */
   9
  10#include <linux/param.h>
  11#include <linux/time.h>
  12#include <linux/mm.h>
  13#include <linux/errno.h>
  14#include <linux/string.h>
  15#include <linux/in.h>
  16#include <linux/pagemap.h>
  17#include <linux/proc_fs.h>
  18#include <linux/kdev_t.h>
  19#include <linux/sunrpc/clnt.h>
  20#include <linux/nfs.h>
  21#include <linux/nfs3.h>
  22#include <linux/nfs_fs.h>
  23#include <linux/nfsacl.h>
  24#include "internal.h"
  25
  26#define NFSDBG_FACILITY		NFSDBG_XDR
  27
  28/* Mapping from NFS error code to "errno" error code. */
  29#define errno_NFSERR_IO		EIO
  30
  31/*
  32 * Declare the space requirements for NFS arguments and replies as
  33 * number of 32bit-words
  34 */
  35#define NFS3_fhandle_sz		(1+16)
  36#define NFS3_fh_sz		(NFS3_fhandle_sz)	/* shorthand */
  37#define NFS3_sattr_sz		(15)
  38#define NFS3_filename_sz	(1+(NFS3_MAXNAMLEN>>2))
  39#define NFS3_path_sz		(1+(NFS3_MAXPATHLEN>>2))
  40#define NFS3_fattr_sz		(21)
  41#define NFS3_cookieverf_sz	(NFS3_COOKIEVERFSIZE>>2)
  42#define NFS3_wcc_attr_sz	(6)
  43#define NFS3_pre_op_attr_sz	(1+NFS3_wcc_attr_sz)
  44#define NFS3_post_op_attr_sz	(1+NFS3_fattr_sz)
  45#define NFS3_wcc_data_sz	(NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
  46#define NFS3_diropargs_sz	(NFS3_fh_sz+NFS3_filename_sz)
  47
  48#define NFS3_getattrargs_sz	(NFS3_fh_sz)
  49#define NFS3_setattrargs_sz	(NFS3_fh_sz+NFS3_sattr_sz+3)
  50#define NFS3_lookupargs_sz	(NFS3_fh_sz+NFS3_filename_sz)
  51#define NFS3_accessargs_sz	(NFS3_fh_sz+1)
  52#define NFS3_readlinkargs_sz	(NFS3_fh_sz)
  53#define NFS3_readargs_sz	(NFS3_fh_sz+3)
  54#define NFS3_writeargs_sz	(NFS3_fh_sz+5)
  55#define NFS3_createargs_sz	(NFS3_diropargs_sz+NFS3_sattr_sz)
  56#define NFS3_mkdirargs_sz	(NFS3_diropargs_sz+NFS3_sattr_sz)
  57#define NFS3_symlinkargs_sz	(NFS3_diropargs_sz+1+NFS3_sattr_sz)
  58#define NFS3_mknodargs_sz	(NFS3_diropargs_sz+2+NFS3_sattr_sz)
  59#define NFS3_removeargs_sz	(NFS3_fh_sz+NFS3_filename_sz)
  60#define NFS3_renameargs_sz	(NFS3_diropargs_sz+NFS3_diropargs_sz)
  61#define NFS3_linkargs_sz		(NFS3_fh_sz+NFS3_diropargs_sz)
  62#define NFS3_readdirargs_sz	(NFS3_fh_sz+NFS3_cookieverf_sz+3)
  63#define NFS3_readdirplusargs_sz	(NFS3_fh_sz+NFS3_cookieverf_sz+4)
  64#define NFS3_commitargs_sz	(NFS3_fh_sz+3)
  65
  66#define NFS3_getattrres_sz	(1+NFS3_fattr_sz)
  67#define NFS3_setattrres_sz	(1+NFS3_wcc_data_sz)
  68#define NFS3_removeres_sz	(NFS3_setattrres_sz)
  69#define NFS3_lookupres_sz	(1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
  70#define NFS3_accessres_sz	(1+NFS3_post_op_attr_sz+1)
  71#define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz+1)
  72#define NFS3_readres_sz		(1+NFS3_post_op_attr_sz+3)
  73#define NFS3_writeres_sz	(1+NFS3_wcc_data_sz+4)
  74#define NFS3_createres_sz	(1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
  75#define NFS3_renameres_sz	(1+(2 * NFS3_wcc_data_sz))
  76#define NFS3_linkres_sz		(1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
  77#define NFS3_readdirres_sz	(1+NFS3_post_op_attr_sz+2)
  78#define NFS3_fsstatres_sz	(1+NFS3_post_op_attr_sz+13)
  79#define NFS3_fsinfores_sz	(1+NFS3_post_op_attr_sz+12)
  80#define NFS3_pathconfres_sz	(1+NFS3_post_op_attr_sz+6)
  81#define NFS3_commitres_sz	(1+NFS3_wcc_data_sz+2)
  82
  83#define ACL3_getaclargs_sz	(NFS3_fh_sz+1)
  84#define ACL3_setaclargs_sz	(NFS3_fh_sz+1+ \
  85				XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
  86#define ACL3_getaclres_sz	(1+NFS3_post_op_attr_sz+1+ \
  87				XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
  88#define ACL3_setaclres_sz	(1+NFS3_post_op_attr_sz)
  89
  90static int nfs3_stat_to_errno(enum nfs_stat);
  91
  92/*
  93 * Map file type to S_IFMT bits
  94 */
  95static const umode_t nfs_type2fmt[] = {
  96	[NF3BAD] = 0,
  97	[NF3REG] = S_IFREG,
  98	[NF3DIR] = S_IFDIR,
  99	[NF3BLK] = S_IFBLK,
 100	[NF3CHR] = S_IFCHR,
 101	[NF3LNK] = S_IFLNK,
 102	[NF3SOCK] = S_IFSOCK,
 103	[NF3FIFO] = S_IFIFO,
 104};
 105
 106/*
 107 * While encoding arguments, set up the reply buffer in advance to
 108 * receive reply data directly into the page cache.
 109 */
 110static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
 111				 unsigned int base, unsigned int len,
 112				 unsigned int bufsize)
 113{
 114	struct rpc_auth	*auth = req->rq_cred->cr_auth;
 115	unsigned int replen;
 116
 117	replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
 118	xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
 119}
 120
 121/*
 122 * Handle decode buffer overflows out-of-line.
 123 */
 124static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
 125{
 126	dprintk("NFS: %s prematurely hit the end of our receive buffer. "
 127		"Remaining buffer length is %tu words.\n",
 128		func, xdr->end - xdr->p);
 129}
 130
 131
 132/*
 133 * Encode/decode NFSv3 basic data types
 134 *
 135 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
 136 * "NFS Version 3 Protocol Specification".
 137 *
 138 * Not all basic data types have their own encoding and decoding
 139 * functions.  For run-time efficiency, some data types are encoded
 140 * or decoded inline.
 141 */
 142
 143static void encode_uint32(struct xdr_stream *xdr, u32 value)
 144{
 145	__be32 *p = xdr_reserve_space(xdr, 4);
 146	*p = cpu_to_be32(value);
 147}
 148
 149static int decode_uint32(struct xdr_stream *xdr, u32 *value)
 150{
 151	__be32 *p;
 152
 153	p = xdr_inline_decode(xdr, 4);
 154	if (unlikely(p == NULL))
 155		goto out_overflow;
 156	*value = be32_to_cpup(p);
 157	return 0;
 158out_overflow:
 159	print_overflow_msg(__func__, xdr);
 160	return -EIO;
 161}
 162
 163static int decode_uint64(struct xdr_stream *xdr, u64 *value)
 164{
 165	__be32 *p;
 166
 167	p = xdr_inline_decode(xdr, 8);
 168	if (unlikely(p == NULL))
 169		goto out_overflow;
 170	xdr_decode_hyper(p, value);
 171	return 0;
 172out_overflow:
 173	print_overflow_msg(__func__, xdr);
 174	return -EIO;
 175}
 176
 177/*
 178 * fileid3
 179 *
 180 *	typedef uint64 fileid3;
 181 */
 182static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid)
 183{
 184	return xdr_decode_hyper(p, fileid);
 185}
 186
 187static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
 188{
 189	return decode_uint64(xdr, fileid);
 190}
 191
 192/*
 193 * filename3
 194 *
 195 *	typedef string filename3<>;
 196 */
 197static void encode_filename3(struct xdr_stream *xdr,
 198			     const char *name, u32 length)
 199{
 200	__be32 *p;
 201
 202	WARN_ON_ONCE(length > NFS3_MAXNAMLEN);
 203	p = xdr_reserve_space(xdr, 4 + length);
 204	xdr_encode_opaque(p, name, length);
 205}
 206
 207static int decode_inline_filename3(struct xdr_stream *xdr,
 208				   const char **name, u32 *length)
 209{
 210	__be32 *p;
 211	u32 count;
 212
 213	p = xdr_inline_decode(xdr, 4);
 214	if (unlikely(p == NULL))
 215		goto out_overflow;
 216	count = be32_to_cpup(p);
 217	if (count > NFS3_MAXNAMLEN)
 218		goto out_nametoolong;
 219	p = xdr_inline_decode(xdr, count);
 220	if (unlikely(p == NULL))
 221		goto out_overflow;
 222	*name = (const char *)p;
 223	*length = count;
 224	return 0;
 225
 226out_nametoolong:
 227	dprintk("NFS: returned filename too long: %u\n", count);
 228	return -ENAMETOOLONG;
 229out_overflow:
 230	print_overflow_msg(__func__, xdr);
 231	return -EIO;
 232}
 233
 234/*
 235 * nfspath3
 236 *
 237 *	typedef string nfspath3<>;
 238 */
 239static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
 240			    const u32 length)
 241{
 242	encode_uint32(xdr, length);
 243	xdr_write_pages(xdr, pages, 0, length);
 244}
 245
 246static int decode_nfspath3(struct xdr_stream *xdr)
 247{
 248	u32 recvd, count;
 249	__be32 *p;
 250
 251	p = xdr_inline_decode(xdr, 4);
 252	if (unlikely(p == NULL))
 253		goto out_overflow;
 254	count = be32_to_cpup(p);
 255	if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
 256		goto out_nametoolong;
 257	recvd = xdr_read_pages(xdr, count);
 258	if (unlikely(count > recvd))
 259		goto out_cheating;
 260	xdr_terminate_string(xdr->buf, count);
 261	return 0;
 262
 263out_nametoolong:
 264	dprintk("NFS: returned pathname too long: %u\n", count);
 265	return -ENAMETOOLONG;
 266out_cheating:
 267	dprintk("NFS: server cheating in pathname result: "
 268		"count %u > recvd %u\n", count, recvd);
 269	return -EIO;
 270out_overflow:
 271	print_overflow_msg(__func__, xdr);
 272	return -EIO;
 273}
 274
 275/*
 276 * cookie3
 277 *
 278 *	typedef uint64 cookie3
 279 */
 280static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
 281{
 282	return xdr_encode_hyper(p, cookie);
 283}
 284
 285static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
 286{
 287	return decode_uint64(xdr, cookie);
 288}
 289
 290/*
 291 * cookieverf3
 292 *
 293 *	typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
 294 */
 295static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
 296{
 297	memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
 298	return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
 299}
 300
 301static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
 302{
 303	__be32 *p;
 304
 305	p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 306	if (unlikely(p == NULL))
 307		goto out_overflow;
 308	memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
 309	return 0;
 310out_overflow:
 311	print_overflow_msg(__func__, xdr);
 312	return -EIO;
 313}
 314
 315/*
 316 * createverf3
 317 *
 318 *	typedef opaque createverf3[NFS3_CREATEVERFSIZE];
 319 */
 320static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
 321{
 322	__be32 *p;
 323
 324	p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
 325	memcpy(p, verifier, NFS3_CREATEVERFSIZE);
 326}
 327
 328static int decode_writeverf3(struct xdr_stream *xdr, struct nfs_write_verifier *verifier)
 329{
 330	__be32 *p;
 331
 332	p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
 333	if (unlikely(p == NULL))
 334		goto out_overflow;
 335	memcpy(verifier->data, p, NFS3_WRITEVERFSIZE);
 336	return 0;
 337out_overflow:
 338	print_overflow_msg(__func__, xdr);
 339	return -EIO;
 340}
 341
 342/*
 343 * size3
 344 *
 345 *	typedef uint64 size3;
 346 */
 347static __be32 *xdr_decode_size3(__be32 *p, u64 *size)
 348{
 349	return xdr_decode_hyper(p, size);
 350}
 351
 352/*
 353 * nfsstat3
 354 *
 355 *	enum nfsstat3 {
 356 *		NFS3_OK = 0,
 357 *		...
 358 *	}
 359 */
 360#define NFS3_OK		NFS_OK
 361
 362static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
 363{
 364	__be32 *p;
 365
 366	p = xdr_inline_decode(xdr, 4);
 367	if (unlikely(p == NULL))
 368		goto out_overflow;
 369	*status = be32_to_cpup(p);
 370	return 0;
 371out_overflow:
 372	print_overflow_msg(__func__, xdr);
 373	return -EIO;
 374}
 375
 376/*
 377 * ftype3
 378 *
 379 *	enum ftype3 {
 380 *		NF3REG	= 1,
 381 *		NF3DIR	= 2,
 382 *		NF3BLK	= 3,
 383 *		NF3CHR	= 4,
 384 *		NF3LNK	= 5,
 385 *		NF3SOCK	= 6,
 386 *		NF3FIFO	= 7
 387 *	};
 388 */
 389static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
 390{
 391	encode_uint32(xdr, type);
 392}
 393
 394static __be32 *xdr_decode_ftype3(__be32 *p, umode_t *mode)
 395{
 396	u32 type;
 397
 398	type = be32_to_cpup(p++);
 399	if (type > NF3FIFO)
 400		type = NF3NON;
 401	*mode = nfs_type2fmt[type];
 402	return p;
 403}
 404
 405/*
 406 * specdata3
 407 *
 408 *     struct specdata3 {
 409 *             uint32  specdata1;
 410 *             uint32  specdata2;
 411 *     };
 412 */
 413static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
 414{
 415	__be32 *p;
 416
 417	p = xdr_reserve_space(xdr, 8);
 418	*p++ = cpu_to_be32(MAJOR(rdev));
 419	*p = cpu_to_be32(MINOR(rdev));
 420}
 421
 422static __be32 *xdr_decode_specdata3(__be32 *p, dev_t *rdev)
 423{
 424	unsigned int major, minor;
 425
 426	major = be32_to_cpup(p++);
 427	minor = be32_to_cpup(p++);
 428	*rdev = MKDEV(major, minor);
 429	if (MAJOR(*rdev) != major || MINOR(*rdev) != minor)
 430		*rdev = 0;
 431	return p;
 432}
 433
 434/*
 435 * nfs_fh3
 436 *
 437 *	struct nfs_fh3 {
 438 *		opaque       data<NFS3_FHSIZE>;
 439 *	};
 440 */
 441static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
 442{
 443	__be32 *p;
 444
 445	WARN_ON_ONCE(fh->size > NFS3_FHSIZE);
 446	p = xdr_reserve_space(xdr, 4 + fh->size);
 447	xdr_encode_opaque(p, fh->data, fh->size);
 448}
 449
 450static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
 451{
 452	u32 length;
 453	__be32 *p;
 454
 455	p = xdr_inline_decode(xdr, 4);
 456	if (unlikely(p == NULL))
 457		goto out_overflow;
 458	length = be32_to_cpup(p++);
 459	if (unlikely(length > NFS3_FHSIZE))
 460		goto out_toobig;
 461	p = xdr_inline_decode(xdr, length);
 462	if (unlikely(p == NULL))
 463		goto out_overflow;
 464	fh->size = length;
 465	memcpy(fh->data, p, length);
 466	return 0;
 467out_toobig:
 468	dprintk("NFS: file handle size (%u) too big\n", length);
 469	return -E2BIG;
 470out_overflow:
 471	print_overflow_msg(__func__, xdr);
 472	return -EIO;
 473}
 474
 475static void zero_nfs_fh3(struct nfs_fh *fh)
 476{
 477	memset(fh, 0, sizeof(*fh));
 478}
 479
 480/*
 481 * nfstime3
 482 *
 483 *	struct nfstime3 {
 484 *		uint32	seconds;
 485 *		uint32	nseconds;
 486 *	};
 487 */
 488static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep)
 489{
 490	*p++ = cpu_to_be32(timep->tv_sec);
 491	*p++ = cpu_to_be32(timep->tv_nsec);
 492	return p;
 493}
 494
 495static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep)
 496{
 497	timep->tv_sec = be32_to_cpup(p++);
 498	timep->tv_nsec = be32_to_cpup(p++);
 499	return p;
 500}
 501
 502/*
 503 * sattr3
 504 *
 505 *	enum time_how {
 506 *		DONT_CHANGE		= 0,
 507 *		SET_TO_SERVER_TIME	= 1,
 508 *		SET_TO_CLIENT_TIME	= 2
 509 *	};
 510 *
 511 *	union set_mode3 switch (bool set_it) {
 512 *	case TRUE:
 513 *		mode3	mode;
 514 *	default:
 515 *		void;
 516 *	};
 517 *
 518 *	union set_uid3 switch (bool set_it) {
 519 *	case TRUE:
 520 *		uid3	uid;
 521 *	default:
 522 *		void;
 523 *	};
 524 *
 525 *	union set_gid3 switch (bool set_it) {
 526 *	case TRUE:
 527 *		gid3	gid;
 528 *	default:
 529 *		void;
 530 *	};
 531 *
 532 *	union set_size3 switch (bool set_it) {
 533 *	case TRUE:
 534 *		size3	size;
 535 *	default:
 536 *		void;
 537 *	};
 538 *
 539 *	union set_atime switch (time_how set_it) {
 540 *	case SET_TO_CLIENT_TIME:
 541 *		nfstime3	atime;
 542 *	default:
 543 *		void;
 544 *	};
 545 *
 546 *	union set_mtime switch (time_how set_it) {
 547 *	case SET_TO_CLIENT_TIME:
 548 *		nfstime3  mtime;
 549 *	default:
 550 *		void;
 551 *	};
 552 *
 553 *	struct sattr3 {
 554 *		set_mode3	mode;
 555 *		set_uid3	uid;
 556 *		set_gid3	gid;
 557 *		set_size3	size;
 558 *		set_atime	atime;
 559 *		set_mtime	mtime;
 560 *	};
 561 */
 562static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
 563{
 564	u32 nbytes;
 565	__be32 *p;
 566
 567	/*
 568	 * In order to make only a single xdr_reserve_space() call,
 569	 * pre-compute the total number of bytes to be reserved.
 570	 * Six boolean values, one for each set_foo field, are always
 571	 * present in the encoded result, so start there.
 572	 */
 573	nbytes = 6 * 4;
 574	if (attr->ia_valid & ATTR_MODE)
 575		nbytes += 4;
 576	if (attr->ia_valid & ATTR_UID)
 577		nbytes += 4;
 578	if (attr->ia_valid & ATTR_GID)
 579		nbytes += 4;
 580	if (attr->ia_valid & ATTR_SIZE)
 581		nbytes += 8;
 582	if (attr->ia_valid & ATTR_ATIME_SET)
 583		nbytes += 8;
 584	if (attr->ia_valid & ATTR_MTIME_SET)
 585		nbytes += 8;
 586	p = xdr_reserve_space(xdr, nbytes);
 587
 588	if (attr->ia_valid & ATTR_MODE) {
 589		*p++ = xdr_one;
 590		*p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO);
 591	} else
 592		*p++ = xdr_zero;
 593
 594	if (attr->ia_valid & ATTR_UID) {
 595		*p++ = xdr_one;
 596		*p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
 597	} else
 598		*p++ = xdr_zero;
 599
 600	if (attr->ia_valid & ATTR_GID) {
 601		*p++ = xdr_one;
 602		*p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
 603	} else
 604		*p++ = xdr_zero;
 605
 606	if (attr->ia_valid & ATTR_SIZE) {
 607		*p++ = xdr_one;
 608		p = xdr_encode_hyper(p, (u64)attr->ia_size);
 609	} else
 610		*p++ = xdr_zero;
 611
 612	if (attr->ia_valid & ATTR_ATIME_SET) {
 613		*p++ = xdr_two;
 614		p = xdr_encode_nfstime3(p, &attr->ia_atime);
 615	} else if (attr->ia_valid & ATTR_ATIME) {
 616		*p++ = xdr_one;
 617	} else
 618		*p++ = xdr_zero;
 619
 620	if (attr->ia_valid & ATTR_MTIME_SET) {
 621		*p++ = xdr_two;
 622		xdr_encode_nfstime3(p, &attr->ia_mtime);
 623	} else if (attr->ia_valid & ATTR_MTIME) {
 624		*p = xdr_one;
 625	} else
 626		*p = xdr_zero;
 627}
 628
 629/*
 630 * fattr3
 631 *
 632 *	struct fattr3 {
 633 *		ftype3		type;
 634 *		mode3		mode;
 635 *		uint32		nlink;
 636 *		uid3		uid;
 637 *		gid3		gid;
 638 *		size3		size;
 639 *		size3		used;
 640 *		specdata3	rdev;
 641 *		uint64		fsid;
 642 *		fileid3		fileid;
 643 *		nfstime3	atime;
 644 *		nfstime3	mtime;
 645 *		nfstime3	ctime;
 646 *	};
 647 */
 648static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 649{
 650	umode_t fmode;
 651	__be32 *p;
 652
 653	p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
 654	if (unlikely(p == NULL))
 655		goto out_overflow;
 656
 657	p = xdr_decode_ftype3(p, &fmode);
 658
 659	fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
 660	fattr->nlink = be32_to_cpup(p++);
 661	fattr->uid = make_kuid(&init_user_ns, be32_to_cpup(p++));
 662	if (!uid_valid(fattr->uid))
 663		goto out_uid;
 664	fattr->gid = make_kgid(&init_user_ns, be32_to_cpup(p++));
 665	if (!gid_valid(fattr->gid))
 666		goto out_gid;
 667
 668	p = xdr_decode_size3(p, &fattr->size);
 669	p = xdr_decode_size3(p, &fattr->du.nfs3.used);
 670	p = xdr_decode_specdata3(p, &fattr->rdev);
 671
 672	p = xdr_decode_hyper(p, &fattr->fsid.major);
 673	fattr->fsid.minor = 0;
 674
 675	p = xdr_decode_fileid3(p, &fattr->fileid);
 676	p = xdr_decode_nfstime3(p, &fattr->atime);
 677	p = xdr_decode_nfstime3(p, &fattr->mtime);
 678	xdr_decode_nfstime3(p, &fattr->ctime);
 679	fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
 680
 681	fattr->valid |= NFS_ATTR_FATTR_V3;
 682	return 0;
 683out_uid:
 684	dprintk("NFS: returned invalid uid\n");
 685	return -EINVAL;
 686out_gid:
 687	dprintk("NFS: returned invalid gid\n");
 688	return -EINVAL;
 689out_overflow:
 690	print_overflow_msg(__func__, xdr);
 691	return -EIO;
 692}
 693
 694/*
 695 * post_op_attr
 696 *
 697 *	union post_op_attr switch (bool attributes_follow) {
 698 *	case TRUE:
 699 *		fattr3	attributes;
 700 *	case FALSE:
 701 *		void;
 702 *	};
 703 */
 704static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 705{
 706	__be32 *p;
 707
 708	p = xdr_inline_decode(xdr, 4);
 709	if (unlikely(p == NULL))
 710		goto out_overflow;
 711	if (*p != xdr_zero)
 712		return decode_fattr3(xdr, fattr);
 713	return 0;
 714out_overflow:
 715	print_overflow_msg(__func__, xdr);
 716	return -EIO;
 717}
 718
 719/*
 720 * wcc_attr
 721 *	struct wcc_attr {
 722 *		size3		size;
 723 *		nfstime3	mtime;
 724 *		nfstime3	ctime;
 725 *	};
 726 */
 727static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 728{
 729	__be32 *p;
 730
 731	p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
 732	if (unlikely(p == NULL))
 733		goto out_overflow;
 734
 735	fattr->valid |= NFS_ATTR_FATTR_PRESIZE
 736		| NFS_ATTR_FATTR_PRECHANGE
 737		| NFS_ATTR_FATTR_PREMTIME
 738		| NFS_ATTR_FATTR_PRECTIME;
 739
 740	p = xdr_decode_size3(p, &fattr->pre_size);
 741	p = xdr_decode_nfstime3(p, &fattr->pre_mtime);
 742	xdr_decode_nfstime3(p, &fattr->pre_ctime);
 743	fattr->pre_change_attr = nfs_timespec_to_change_attr(&fattr->pre_ctime);
 744
 745	return 0;
 746out_overflow:
 747	print_overflow_msg(__func__, xdr);
 748	return -EIO;
 749}
 750
 751/*
 752 * pre_op_attr
 753 *	union pre_op_attr switch (bool attributes_follow) {
 754 *	case TRUE:
 755 *		wcc_attr	attributes;
 756 *	case FALSE:
 757 *		void;
 758 *	};
 759 *
 760 * wcc_data
 761 *
 762 *	struct wcc_data {
 763 *		pre_op_attr	before;
 764 *		post_op_attr	after;
 765 *	};
 766 */
 767static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 768{
 769	__be32 *p;
 770
 771	p = xdr_inline_decode(xdr, 4);
 772	if (unlikely(p == NULL))
 773		goto out_overflow;
 774	if (*p != xdr_zero)
 775		return decode_wcc_attr(xdr, fattr);
 776	return 0;
 777out_overflow:
 778	print_overflow_msg(__func__, xdr);
 779	return -EIO;
 780}
 781
 782static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 783{
 784	int error;
 785
 786	error = decode_pre_op_attr(xdr, fattr);
 787	if (unlikely(error))
 788		goto out;
 789	error = decode_post_op_attr(xdr, fattr);
 790out:
 791	return error;
 792}
 793
 794/*
 795 * post_op_fh3
 796 *
 797 *	union post_op_fh3 switch (bool handle_follows) {
 798 *	case TRUE:
 799 *		nfs_fh3  handle;
 800 *	case FALSE:
 801 *		void;
 802 *	};
 803 */
 804static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
 805{
 806	__be32 *p = xdr_inline_decode(xdr, 4);
 807	if (unlikely(p == NULL))
 808		goto out_overflow;
 809	if (*p != xdr_zero)
 810		return decode_nfs_fh3(xdr, fh);
 811	zero_nfs_fh3(fh);
 812	return 0;
 813out_overflow:
 814	print_overflow_msg(__func__, xdr);
 815	return -EIO;
 816}
 817
 818/*
 819 * diropargs3
 820 *
 821 *	struct diropargs3 {
 822 *		nfs_fh3		dir;
 823 *		filename3	name;
 824 *	};
 825 */
 826static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
 827			      const char *name, u32 length)
 828{
 829	encode_nfs_fh3(xdr, fh);
 830	encode_filename3(xdr, name, length);
 831}
 832
 833
 834/*
 835 * NFSv3 XDR encode functions
 836 *
 837 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
 838 * "NFS Version 3 Protocol Specification".
 839 */
 840
 841/*
 842 * 3.3.1  GETATTR3args
 843 *
 844 *	struct GETATTR3args {
 845 *		nfs_fh3  object;
 846 *	};
 847 */
 848static void nfs3_xdr_enc_getattr3args(struct rpc_rqst *req,
 849				      struct xdr_stream *xdr,
 850				      const void *data)
 851{
 852	const struct nfs_fh *fh = data;
 853
 854	encode_nfs_fh3(xdr, fh);
 855}
 856
 857/*
 858 * 3.3.2  SETATTR3args
 859 *
 860 *	union sattrguard3 switch (bool check) {
 861 *	case TRUE:
 862 *		nfstime3  obj_ctime;
 863 *	case FALSE:
 864 *		void;
 865 *	};
 866 *
 867 *	struct SETATTR3args {
 868 *		nfs_fh3		object;
 869 *		sattr3		new_attributes;
 870 *		sattrguard3	guard;
 871 *	};
 872 */
 873static void encode_sattrguard3(struct xdr_stream *xdr,
 874			       const struct nfs3_sattrargs *args)
 875{
 876	__be32 *p;
 877
 878	if (args->guard) {
 879		p = xdr_reserve_space(xdr, 4 + 8);
 880		*p++ = xdr_one;
 881		xdr_encode_nfstime3(p, &args->guardtime);
 882	} else {
 883		p = xdr_reserve_space(xdr, 4);
 884		*p = xdr_zero;
 885	}
 886}
 887
 888static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req,
 889				      struct xdr_stream *xdr,
 890				      const void *data)
 891{
 892	const struct nfs3_sattrargs *args = data;
 893	encode_nfs_fh3(xdr, args->fh);
 894	encode_sattr3(xdr, args->sattr);
 895	encode_sattrguard3(xdr, args);
 896}
 897
 898/*
 899 * 3.3.3  LOOKUP3args
 900 *
 901 *	struct LOOKUP3args {
 902 *		diropargs3  what;
 903 *	};
 904 */
 905static void nfs3_xdr_enc_lookup3args(struct rpc_rqst *req,
 906				     struct xdr_stream *xdr,
 907				     const void *data)
 908{
 909	const struct nfs3_diropargs *args = data;
 910
 911	encode_diropargs3(xdr, args->fh, args->name, args->len);
 912}
 913
 914/*
 915 * 3.3.4  ACCESS3args
 916 *
 917 *	struct ACCESS3args {
 918 *		nfs_fh3		object;
 919 *		uint32		access;
 920 *	};
 921 */
 922static void encode_access3args(struct xdr_stream *xdr,
 923			       const struct nfs3_accessargs *args)
 924{
 925	encode_nfs_fh3(xdr, args->fh);
 926	encode_uint32(xdr, args->access);
 927}
 928
 929static void nfs3_xdr_enc_access3args(struct rpc_rqst *req,
 930				     struct xdr_stream *xdr,
 931				     const void *data)
 932{
 933	const struct nfs3_accessargs *args = data;
 934
 935	encode_access3args(xdr, args);
 936}
 937
 938/*
 939 * 3.3.5  READLINK3args
 940 *
 941 *	struct READLINK3args {
 942 *		nfs_fh3	symlink;
 943 *	};
 944 */
 945static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
 946				       struct xdr_stream *xdr,
 947				       const void *data)
 948{
 949	const struct nfs3_readlinkargs *args = data;
 950
 951	encode_nfs_fh3(xdr, args->fh);
 952	prepare_reply_buffer(req, args->pages, args->pgbase,
 953					args->pglen, NFS3_readlinkres_sz);
 954}
 955
 956/*
 957 * 3.3.6  READ3args
 958 *
 959 *	struct READ3args {
 960 *		nfs_fh3		file;
 961 *		offset3		offset;
 962 *		count3		count;
 963 *	};
 964 */
 965static void encode_read3args(struct xdr_stream *xdr,
 966			     const struct nfs_pgio_args *args)
 967{
 968	__be32 *p;
 969
 970	encode_nfs_fh3(xdr, args->fh);
 971
 972	p = xdr_reserve_space(xdr, 8 + 4);
 973	p = xdr_encode_hyper(p, args->offset);
 974	*p = cpu_to_be32(args->count);
 975}
 976
 977static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
 978				   struct xdr_stream *xdr,
 979				   const void *data)
 980{
 981	const struct nfs_pgio_args *args = data;
 982
 983	encode_read3args(xdr, args);
 984	prepare_reply_buffer(req, args->pages, args->pgbase,
 985					args->count, NFS3_readres_sz);
 986	req->rq_rcv_buf.flags |= XDRBUF_READ;
 987}
 988
 989/*
 990 * 3.3.7  WRITE3args
 991 *
 992 *	enum stable_how {
 993 *		UNSTABLE  = 0,
 994 *		DATA_SYNC = 1,
 995 *		FILE_SYNC = 2
 996 *	};
 997 *
 998 *	struct WRITE3args {
 999 *		nfs_fh3		file;
1000 *		offset3		offset;
1001 *		count3		count;
1002 *		stable_how	stable;
1003 *		opaque		data<>;
1004 *	};
1005 */
1006static void encode_write3args(struct xdr_stream *xdr,
1007			      const struct nfs_pgio_args *args)
1008{
1009	__be32 *p;
1010
1011	encode_nfs_fh3(xdr, args->fh);
1012
1013	p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
1014	p = xdr_encode_hyper(p, args->offset);
1015	*p++ = cpu_to_be32(args->count);
1016	*p++ = cpu_to_be32(args->stable);
1017	*p = cpu_to_be32(args->count);
1018	xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1019}
1020
1021static void nfs3_xdr_enc_write3args(struct rpc_rqst *req,
1022				    struct xdr_stream *xdr,
1023				    const void *data)
1024{
1025	const struct nfs_pgio_args *args = data;
1026
1027	encode_write3args(xdr, args);
1028	xdr->buf->flags |= XDRBUF_WRITE;
1029}
1030
1031/*
1032 * 3.3.8  CREATE3args
1033 *
1034 *	enum createmode3 {
1035 *		UNCHECKED = 0,
1036 *		GUARDED   = 1,
1037 *		EXCLUSIVE = 2
1038 *	};
1039 *
1040 *	union createhow3 switch (createmode3 mode) {
1041 *	case UNCHECKED:
1042 *	case GUARDED:
1043 *		sattr3       obj_attributes;
1044 *	case EXCLUSIVE:
1045 *		createverf3  verf;
1046 *	};
1047 *
1048 *	struct CREATE3args {
1049 *		diropargs3	where;
1050 *		createhow3	how;
1051 *	};
1052 */
1053static void encode_createhow3(struct xdr_stream *xdr,
1054			      const struct nfs3_createargs *args)
1055{
1056	encode_uint32(xdr, args->createmode);
1057	switch (args->createmode) {
1058	case NFS3_CREATE_UNCHECKED:
1059	case NFS3_CREATE_GUARDED:
1060		encode_sattr3(xdr, args->sattr);
1061		break;
1062	case NFS3_CREATE_EXCLUSIVE:
1063		encode_createverf3(xdr, args->verifier);
1064		break;
1065	default:
1066		BUG();
1067	}
1068}
1069
1070static void nfs3_xdr_enc_create3args(struct rpc_rqst *req,
1071				     struct xdr_stream *xdr,
1072				     const void *data)
1073{
1074	const struct nfs3_createargs *args = data;
1075
1076	encode_diropargs3(xdr, args->fh, args->name, args->len);
1077	encode_createhow3(xdr, args);
1078}
1079
1080/*
1081 * 3.3.9  MKDIR3args
1082 *
1083 *	struct MKDIR3args {
1084 *		diropargs3	where;
1085 *		sattr3		attributes;
1086 *	};
1087 */
1088static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req,
1089				    struct xdr_stream *xdr,
1090				    const void *data)
1091{
1092	const struct nfs3_mkdirargs *args = data;
1093
1094	encode_diropargs3(xdr, args->fh, args->name, args->len);
1095	encode_sattr3(xdr, args->sattr);
1096}
1097
1098/*
1099 * 3.3.10  SYMLINK3args
1100 *
1101 *	struct symlinkdata3 {
1102 *		sattr3		symlink_attributes;
1103 *		nfspath3	symlink_data;
1104 *	};
1105 *
1106 *	struct SYMLINK3args {
1107 *		diropargs3	where;
1108 *		symlinkdata3	symlink;
1109 *	};
1110 */
1111static void encode_symlinkdata3(struct xdr_stream *xdr,
1112				const void *data)
1113{
1114	const struct nfs3_symlinkargs *args = data;
1115
1116	encode_sattr3(xdr, args->sattr);
1117	encode_nfspath3(xdr, args->pages, args->pathlen);
1118}
1119
1120static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req,
1121				      struct xdr_stream *xdr,
1122				      const void *data)
1123{
1124	const struct nfs3_symlinkargs *args = data;
1125
1126	encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen);
1127	encode_symlinkdata3(xdr, args);
1128	xdr->buf->flags |= XDRBUF_WRITE;
1129}
1130
1131/*
1132 * 3.3.11  MKNOD3args
1133 *
1134 *	struct devicedata3 {
1135 *		sattr3		dev_attributes;
1136 *		specdata3	spec;
1137 *	};
1138 *
1139 *	union mknoddata3 switch (ftype3 type) {
1140 *	case NF3CHR:
1141 *	case NF3BLK:
1142 *		devicedata3	device;
1143 *	case NF3SOCK:
1144 *	case NF3FIFO:
1145 *		sattr3		pipe_attributes;
1146 *	default:
1147 *		void;
1148 *	};
1149 *
1150 *	struct MKNOD3args {
1151 *		diropargs3	where;
1152 *		mknoddata3	what;
1153 *	};
1154 */
1155static void encode_devicedata3(struct xdr_stream *xdr,
1156			       const struct nfs3_mknodargs *args)
1157{
1158	encode_sattr3(xdr, args->sattr);
1159	encode_specdata3(xdr, args->rdev);
1160}
1161
1162static void encode_mknoddata3(struct xdr_stream *xdr,
1163			      const struct nfs3_mknodargs *args)
1164{
1165	encode_ftype3(xdr, args->type);
1166	switch (args->type) {
1167	case NF3CHR:
1168	case NF3BLK:
1169		encode_devicedata3(xdr, args);
1170		break;
1171	case NF3SOCK:
1172	case NF3FIFO:
1173		encode_sattr3(xdr, args->sattr);
1174		break;
1175	case NF3REG:
1176	case NF3DIR:
1177		break;
1178	default:
1179		BUG();
1180	}
1181}
1182
1183static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req,
1184				    struct xdr_stream *xdr,
1185				    const void *data)
1186{
1187	const struct nfs3_mknodargs *args = data;
1188
1189	encode_diropargs3(xdr, args->fh, args->name, args->len);
1190	encode_mknoddata3(xdr, args);
1191}
1192
1193/*
1194 * 3.3.12  REMOVE3args
1195 *
1196 *	struct REMOVE3args {
1197 *		diropargs3  object;
1198 *	};
1199 */
1200static void nfs3_xdr_enc_remove3args(struct rpc_rqst *req,
1201				     struct xdr_stream *xdr,
1202				     const void *data)
1203{
1204	const struct nfs_removeargs *args = data;
1205
1206	encode_diropargs3(xdr, args->fh, args->name.name, args->name.len);
1207}
1208
1209/*
1210 * 3.3.14  RENAME3args
1211 *
1212 *	struct RENAME3args {
1213 *		diropargs3	from;
1214 *		diropargs3	to;
1215 *	};
1216 */
1217static void nfs3_xdr_enc_rename3args(struct rpc_rqst *req,
1218				     struct xdr_stream *xdr,
1219				     const void *data)
1220{
1221	const struct nfs_renameargs *args = data;
1222	const struct qstr *old = args->old_name;
1223	const struct qstr *new = args->new_name;
1224
1225	encode_diropargs3(xdr, args->old_dir, old->name, old->len);
1226	encode_diropargs3(xdr, args->new_dir, new->name, new->len);
1227}
1228
1229/*
1230 * 3.3.15  LINK3args
1231 *
1232 *	struct LINK3args {
1233 *		nfs_fh3		file;
1234 *		diropargs3	link;
1235 *	};
1236 */
1237static void nfs3_xdr_enc_link3args(struct rpc_rqst *req,
1238				   struct xdr_stream *xdr,
1239				   const void *data)
1240{
1241	const struct nfs3_linkargs *args = data;
1242
1243	encode_nfs_fh3(xdr, args->fromfh);
1244	encode_diropargs3(xdr, args->tofh, args->toname, args->tolen);
1245}
1246
1247/*
1248 * 3.3.16  READDIR3args
1249 *
1250 *	struct READDIR3args {
1251 *		nfs_fh3		dir;
1252 *		cookie3		cookie;
1253 *		cookieverf3	cookieverf;
1254 *		count3		count;
1255 *	};
1256 */
1257static void encode_readdir3args(struct xdr_stream *xdr,
1258				const struct nfs3_readdirargs *args)
1259{
1260	__be32 *p;
1261
1262	encode_nfs_fh3(xdr, args->fh);
1263
1264	p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1265	p = xdr_encode_cookie3(p, args->cookie);
1266	p = xdr_encode_cookieverf3(p, args->verf);
1267	*p = cpu_to_be32(args->count);
1268}
1269
1270static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
1271				      struct xdr_stream *xdr,
1272				      const void *data)
1273{
1274	const struct nfs3_readdirargs *args = data;
1275
1276	encode_readdir3args(xdr, args);
1277	prepare_reply_buffer(req, args->pages, 0,
1278				args->count, NFS3_readdirres_sz);
1279}
1280
1281/*
1282 * 3.3.17  READDIRPLUS3args
1283 *
1284 *	struct READDIRPLUS3args {
1285 *		nfs_fh3		dir;
1286 *		cookie3		cookie;
1287 *		cookieverf3	cookieverf;
1288 *		count3		dircount;
1289 *		count3		maxcount;
1290 *	};
1291 */
1292static void encode_readdirplus3args(struct xdr_stream *xdr,
1293				    const struct nfs3_readdirargs *args)
1294{
1295	__be32 *p;
1296
1297	encode_nfs_fh3(xdr, args->fh);
1298
1299	p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1300	p = xdr_encode_cookie3(p, args->cookie);
1301	p = xdr_encode_cookieverf3(p, args->verf);
1302
1303	/*
1304	 * readdirplus: need dircount + buffer size.
1305	 * We just make sure we make dircount big enough
1306	 */
1307	*p++ = cpu_to_be32(args->count >> 3);
1308
1309	*p = cpu_to_be32(args->count);
1310}
1311
1312static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
1313					  struct xdr_stream *xdr,
1314					  const void *data)
1315{
1316	const struct nfs3_readdirargs *args = data;
1317
1318	encode_readdirplus3args(xdr, args);
1319	prepare_reply_buffer(req, args->pages, 0,
1320				args->count, NFS3_readdirres_sz);
1321}
1322
1323/*
1324 * 3.3.21  COMMIT3args
1325 *
1326 *	struct COMMIT3args {
1327 *		nfs_fh3		file;
1328 *		offset3		offset;
1329 *		count3		count;
1330 *	};
1331 */
1332static void encode_commit3args(struct xdr_stream *xdr,
1333			       const struct nfs_commitargs *args)
1334{
1335	__be32 *p;
1336
1337	encode_nfs_fh3(xdr, args->fh);
1338
1339	p = xdr_reserve_space(xdr, 8 + 4);
1340	p = xdr_encode_hyper(p, args->offset);
1341	*p = cpu_to_be32(args->count);
1342}
1343
1344static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req,
1345				     struct xdr_stream *xdr,
1346				     const void *data)
1347{
1348	const struct nfs_commitargs *args = data;
1349
1350	encode_commit3args(xdr, args);
1351}
1352
1353#ifdef CONFIG_NFS_V3_ACL
1354
1355static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
1356				     struct xdr_stream *xdr,
1357				     const void *data)
1358{
1359	const struct nfs3_getaclargs *args = data;
1360
1361	encode_nfs_fh3(xdr, args->fh);
1362	encode_uint32(xdr, args->mask);
1363	if (args->mask & (NFS_ACL | NFS_DFACL))
1364		prepare_reply_buffer(req, args->pages, 0,
1365					NFSACL_MAXPAGES << PAGE_SHIFT,
1366					ACL3_getaclres_sz);
1367}
1368
1369static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
1370				     struct xdr_stream *xdr,
1371				     const void *data)
1372{
1373	const struct nfs3_setaclargs *args = data;
1374	unsigned int base;
1375	int error;
1376
1377	encode_nfs_fh3(xdr, NFS_FH(args->inode));
1378	encode_uint32(xdr, args->mask);
1379
1380	base = req->rq_slen;
1381	if (args->npages != 0)
1382		xdr_write_pages(xdr, args->pages, 0, args->len);
1383	else
1384		xdr_reserve_space(xdr, args->len);
1385
1386	error = nfsacl_encode(xdr->buf, base, args->inode,
1387			    (args->mask & NFS_ACL) ?
1388			    args->acl_access : NULL, 1, 0);
1389	/* FIXME: this is just broken */
1390	BUG_ON(error < 0);
1391	error = nfsacl_encode(xdr->buf, base + error, args->inode,
1392			    (args->mask & NFS_DFACL) ?
1393			    args->acl_default : NULL, 1,
1394			    NFS_ACL_DEFAULT);
1395	BUG_ON(error < 0);
1396}
1397
1398#endif  /* CONFIG_NFS_V3_ACL */
1399
1400/*
1401 * NFSv3 XDR decode functions
1402 *
1403 * NFSv3 result types are defined in section 3.3 of RFC 1813:
1404 * "NFS Version 3 Protocol Specification".
1405 */
1406
1407/*
1408 * 3.3.1  GETATTR3res
1409 *
1410 *	struct GETATTR3resok {
1411 *		fattr3		obj_attributes;
1412 *	};
1413 *
1414 *	union GETATTR3res switch (nfsstat3 status) {
1415 *	case NFS3_OK:
1416 *		GETATTR3resok  resok;
1417 *	default:
1418 *		void;
1419 *	};
1420 */
1421static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req,
1422				    struct xdr_stream *xdr,
1423				    void *result)
1424{
1425	enum nfs_stat status;
1426	int error;
1427
1428	error = decode_nfsstat3(xdr, &status);
1429	if (unlikely(error))
1430		goto out;
1431	if (status != NFS3_OK)
1432		goto out_default;
1433	error = decode_fattr3(xdr, result);
1434out:
1435	return error;
1436out_default:
1437	return nfs3_stat_to_errno(status);
1438}
1439
1440/*
1441 * 3.3.2  SETATTR3res
1442 *
1443 *	struct SETATTR3resok {
1444 *		wcc_data  obj_wcc;
1445 *	};
1446 *
1447 *	struct SETATTR3resfail {
1448 *		wcc_data  obj_wcc;
1449 *	};
1450 *
1451 *	union SETATTR3res switch (nfsstat3 status) {
1452 *	case NFS3_OK:
1453 *		SETATTR3resok   resok;
1454 *	default:
1455 *		SETATTR3resfail resfail;
1456 *	};
1457 */
1458static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req,
1459				    struct xdr_stream *xdr,
1460				    void *result)
1461{
1462	enum nfs_stat status;
1463	int error;
1464
1465	error = decode_nfsstat3(xdr, &status);
1466	if (unlikely(error))
1467		goto out;
1468	error = decode_wcc_data(xdr, result);
1469	if (unlikely(error))
1470		goto out;
1471	if (status != NFS3_OK)
1472		goto out_status;
1473out:
1474	return error;
1475out_status:
1476	return nfs3_stat_to_errno(status);
1477}
1478
1479/*
1480 * 3.3.3  LOOKUP3res
1481 *
1482 *	struct LOOKUP3resok {
1483 *		nfs_fh3		object;
1484 *		post_op_attr	obj_attributes;
1485 *		post_op_attr	dir_attributes;
1486 *	};
1487 *
1488 *	struct LOOKUP3resfail {
1489 *		post_op_attr	dir_attributes;
1490 *	};
1491 *
1492 *	union LOOKUP3res switch (nfsstat3 status) {
1493 *	case NFS3_OK:
1494 *		LOOKUP3resok	resok;
1495 *	default:
1496 *		LOOKUP3resfail	resfail;
1497 *	};
1498 */
1499static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req,
1500				   struct xdr_stream *xdr,
1501				   void *data)
1502{
1503	struct nfs3_diropres *result = data;
1504	enum nfs_stat status;
1505	int error;
1506
1507	error = decode_nfsstat3(xdr, &status);
1508	if (unlikely(error))
1509		goto out;
1510	if (status != NFS3_OK)
1511		goto out_default;
1512	error = decode_nfs_fh3(xdr, result->fh);
1513	if (unlikely(error))
1514		goto out;
1515	error = decode_post_op_attr(xdr, result->fattr);
1516	if (unlikely(error))
1517		goto out;
1518	error = decode_post_op_attr(xdr, result->dir_attr);
1519out:
1520	return error;
1521out_default:
1522	error = decode_post_op_attr(xdr, result->dir_attr);
1523	if (unlikely(error))
1524		goto out;
1525	return nfs3_stat_to_errno(status);
1526}
1527
1528/*
1529 * 3.3.4  ACCESS3res
1530 *
1531 *	struct ACCESS3resok {
1532 *		post_op_attr	obj_attributes;
1533 *		uint32		access;
1534 *	};
1535 *
1536 *	struct ACCESS3resfail {
1537 *		post_op_attr	obj_attributes;
1538 *	};
1539 *
1540 *	union ACCESS3res switch (nfsstat3 status) {
1541 *	case NFS3_OK:
1542 *		ACCESS3resok	resok;
1543 *	default:
1544 *		ACCESS3resfail	resfail;
1545 *	};
1546 */
1547static int nfs3_xdr_dec_access3res(struct rpc_rqst *req,
1548				   struct xdr_stream *xdr,
1549				   void *data)
1550{
1551	struct nfs3_accessres *result = data;
1552	enum nfs_stat status;
1553	int error;
1554
1555	error = decode_nfsstat3(xdr, &status);
1556	if (unlikely(error))
1557		goto out;
1558	error = decode_post_op_attr(xdr, result->fattr);
1559	if (unlikely(error))
1560		goto out;
1561	if (status != NFS3_OK)
1562		goto out_default;
1563	error = decode_uint32(xdr, &result->access);
1564out:
1565	return error;
1566out_default:
1567	return nfs3_stat_to_errno(status);
1568}
1569
1570/*
1571 * 3.3.5  READLINK3res
1572 *
1573 *	struct READLINK3resok {
1574 *		post_op_attr	symlink_attributes;
1575 *		nfspath3	data;
1576 *	};
1577 *
1578 *	struct READLINK3resfail {
1579 *		post_op_attr	symlink_attributes;
1580 *	};
1581 *
1582 *	union READLINK3res switch (nfsstat3 status) {
1583 *	case NFS3_OK:
1584 *		READLINK3resok	resok;
1585 *	default:
1586 *		READLINK3resfail resfail;
1587 *	};
1588 */
1589static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req,
1590				     struct xdr_stream *xdr,
1591				     void *result)
1592{
1593	enum nfs_stat status;
1594	int error;
1595
1596	error = decode_nfsstat3(xdr, &status);
1597	if (unlikely(error))
1598		goto out;
1599	error = decode_post_op_attr(xdr, result);
1600	if (unlikely(error))
1601		goto out;
1602	if (status != NFS3_OK)
1603		goto out_default;
1604	error = decode_nfspath3(xdr);
1605out:
1606	return error;
1607out_default:
1608	return nfs3_stat_to_errno(status);
1609}
1610
1611/*
1612 * 3.3.6  READ3res
1613 *
1614 *	struct READ3resok {
1615 *		post_op_attr	file_attributes;
1616 *		count3		count;
1617 *		bool		eof;
1618 *		opaque		data<>;
1619 *	};
1620 *
1621 *	struct READ3resfail {
1622 *		post_op_attr	file_attributes;
1623 *	};
1624 *
1625 *	union READ3res switch (nfsstat3 status) {
1626 *	case NFS3_OK:
1627 *		READ3resok	resok;
1628 *	default:
1629 *		READ3resfail	resfail;
1630 *	};
1631 */
1632static int decode_read3resok(struct xdr_stream *xdr,
1633			     struct nfs_pgio_res *result)
1634{
1635	u32 eof, count, ocount, recvd;
1636	__be32 *p;
1637
1638	p = xdr_inline_decode(xdr, 4 + 4 + 4);
1639	if (unlikely(p == NULL))
1640		goto out_overflow;
1641	count = be32_to_cpup(p++);
1642	eof = be32_to_cpup(p++);
1643	ocount = be32_to_cpup(p++);
1644	if (unlikely(ocount != count))
1645		goto out_mismatch;
1646	recvd = xdr_read_pages(xdr, count);
1647	if (unlikely(count > recvd))
1648		goto out_cheating;
1649out:
1650	result->eof = eof;
1651	result->count = count;
1652	return count;
1653out_mismatch:
1654	dprintk("NFS: READ count doesn't match length of opaque: "
1655		"count %u != ocount %u\n", count, ocount);
1656	return -EIO;
1657out_cheating:
1658	dprintk("NFS: server cheating in read result: "
1659		"count %u > recvd %u\n", count, recvd);
1660	count = recvd;
1661	eof = 0;
1662	goto out;
1663out_overflow:
1664	print_overflow_msg(__func__, xdr);
1665	return -EIO;
1666}
1667
1668static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1669				 void *data)
1670{
1671	struct nfs_pgio_res *result = data;
1672	enum nfs_stat status;
1673	int error;
1674
1675	error = decode_nfsstat3(xdr, &status);
1676	if (unlikely(error))
1677		goto out;
1678	error = decode_post_op_attr(xdr, result->fattr);
1679	if (unlikely(error))
1680		goto out;
1681	result->op_status = status;
1682	if (status != NFS3_OK)
1683		goto out_status;
1684	error = decode_read3resok(xdr, result);
1685out:
1686	return error;
1687out_status:
1688	return nfs3_stat_to_errno(status);
1689}
1690
1691/*
1692 * 3.3.7  WRITE3res
1693 *
1694 *	enum stable_how {
1695 *		UNSTABLE  = 0,
1696 *		DATA_SYNC = 1,
1697 *		FILE_SYNC = 2
1698 *	};
1699 *
1700 *	struct WRITE3resok {
1701 *		wcc_data	file_wcc;
1702 *		count3		count;
1703 *		stable_how	committed;
1704 *		writeverf3	verf;
1705 *	};
1706 *
1707 *	struct WRITE3resfail {
1708 *		wcc_data	file_wcc;
1709 *	};
1710 *
1711 *	union WRITE3res switch (nfsstat3 status) {
1712 *	case NFS3_OK:
1713 *		WRITE3resok	resok;
1714 *	default:
1715 *		WRITE3resfail	resfail;
1716 *	};
1717 */
1718static int decode_write3resok(struct xdr_stream *xdr,
1719			      struct nfs_pgio_res *result)
1720{
1721	__be32 *p;
1722
1723	p = xdr_inline_decode(xdr, 4 + 4);
1724	if (unlikely(p == NULL))
1725		goto out_overflow;
1726	result->count = be32_to_cpup(p++);
1727	result->verf->committed = be32_to_cpup(p++);
1728	if (unlikely(result->verf->committed > NFS_FILE_SYNC))
1729		goto out_badvalue;
1730	if (decode_writeverf3(xdr, &result->verf->verifier))
1731		goto out_eio;
1732	return result->count;
1733out_badvalue:
1734	dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
1735	return -EIO;
1736out_overflow:
1737	print_overflow_msg(__func__, xdr);
1738out_eio:
1739	return -EIO;
1740}
1741
1742static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1743				  void *data)
1744{
1745	struct nfs_pgio_res *result = data;
1746	enum nfs_stat status;
1747	int error;
1748
1749	error = decode_nfsstat3(xdr, &status);
1750	if (unlikely(error))
1751		goto out;
1752	error = decode_wcc_data(xdr, result->fattr);
1753	if (unlikely(error))
1754		goto out;
1755	result->op_status = status;
1756	if (status != NFS3_OK)
1757		goto out_status;
1758	error = decode_write3resok(xdr, result);
1759out:
1760	return error;
1761out_status:
1762	return nfs3_stat_to_errno(status);
1763}
1764
1765/*
1766 * 3.3.8  CREATE3res
1767 *
1768 *	struct CREATE3resok {
1769 *		post_op_fh3	obj;
1770 *		post_op_attr	obj_attributes;
1771 *		wcc_data	dir_wcc;
1772 *	};
1773 *
1774 *	struct CREATE3resfail {
1775 *		wcc_data	dir_wcc;
1776 *	};
1777 *
1778 *	union CREATE3res switch (nfsstat3 status) {
1779 *	case NFS3_OK:
1780 *		CREATE3resok	resok;
1781 *	default:
1782 *		CREATE3resfail	resfail;
1783 *	};
1784 */
1785static int decode_create3resok(struct xdr_stream *xdr,
1786			       struct nfs3_diropres *result)
1787{
1788	int error;
1789
1790	error = decode_post_op_fh3(xdr, result->fh);
1791	if (unlikely(error))
1792		goto out;
1793	error = decode_post_op_attr(xdr, result->fattr);
1794	if (unlikely(error))
1795		goto out;
1796	/* The server isn't required to return a file handle.
1797	 * If it didn't, force the client to perform a LOOKUP
1798	 * to determine the correct file handle and attribute
1799	 * values for the new object. */
1800	if (result->fh->size == 0)
1801		result->fattr->valid = 0;
1802	error = decode_wcc_data(xdr, result->dir_attr);
1803out:
1804	return error;
1805}
1806
1807static int nfs3_xdr_dec_create3res(struct rpc_rqst *req,
1808				   struct xdr_stream *xdr,
1809				   void *data)
1810{
1811	struct nfs3_diropres *result = data;
1812	enum nfs_stat status;
1813	int error;
1814
1815	error = decode_nfsstat3(xdr, &status);
1816	if (unlikely(error))
1817		goto out;
1818	if (status != NFS3_OK)
1819		goto out_default;
1820	error = decode_create3resok(xdr, result);
1821out:
1822	return error;
1823out_default:
1824	error = decode_wcc_data(xdr, result->dir_attr);
1825	if (unlikely(error))
1826		goto out;
1827	return nfs3_stat_to_errno(status);
1828}
1829
1830/*
1831 * 3.3.12  REMOVE3res
1832 *
1833 *	struct REMOVE3resok {
1834 *		wcc_data    dir_wcc;
1835 *	};
1836 *
1837 *	struct REMOVE3resfail {
1838 *		wcc_data    dir_wcc;
1839 *	};
1840 *
1841 *	union REMOVE3res switch (nfsstat3 status) {
1842 *	case NFS3_OK:
1843 *		REMOVE3resok   resok;
1844 *	default:
1845 *		REMOVE3resfail resfail;
1846 *	};
1847 */
1848static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req,
1849				   struct xdr_stream *xdr,
1850				   void *data)
1851{
1852	struct nfs_removeres *result = data;
1853	enum nfs_stat status;
1854	int error;
1855
1856	error = decode_nfsstat3(xdr, &status);
1857	if (unlikely(error))
1858		goto out;
1859	error = decode_wcc_data(xdr, result->dir_attr);
1860	if (unlikely(error))
1861		goto out;
1862	if (status != NFS3_OK)
1863		goto out_status;
1864out:
1865	return error;
1866out_status:
1867	return nfs3_stat_to_errno(status);
1868}
1869
1870/*
1871 * 3.3.14  RENAME3res
1872 *
1873 *	struct RENAME3resok {
1874 *		wcc_data	fromdir_wcc;
1875 *		wcc_data	todir_wcc;
1876 *	};
1877 *
1878 *	struct RENAME3resfail {
1879 *		wcc_data	fromdir_wcc;
1880 *		wcc_data	todir_wcc;
1881 *	};
1882 *
1883 *	union RENAME3res switch (nfsstat3 status) {
1884 *	case NFS3_OK:
1885 *		RENAME3resok   resok;
1886 *	default:
1887 *		RENAME3resfail resfail;
1888 *	};
1889 */
1890static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
1891				   struct xdr_stream *xdr,
1892				   void *data)
1893{
1894	struct nfs_renameres *result = data;
1895	enum nfs_stat status;
1896	int error;
1897
1898	error = decode_nfsstat3(xdr, &status);
1899	if (unlikely(error))
1900		goto out;
1901	error = decode_wcc_data(xdr, result->old_fattr);
1902	if (unlikely(error))
1903		goto out;
1904	error = decode_wcc_data(xdr, result->new_fattr);
1905	if (unlikely(error))
1906		goto out;
1907	if (status != NFS3_OK)
1908		goto out_status;
1909out:
1910	return error;
1911out_status:
1912	return nfs3_stat_to_errno(status);
1913}
1914
1915/*
1916 * 3.3.15  LINK3res
1917 *
1918 *	struct LINK3resok {
1919 *		post_op_attr	file_attributes;
1920 *		wcc_data	linkdir_wcc;
1921 *	};
1922 *
1923 *	struct LINK3resfail {
1924 *		post_op_attr	file_attributes;
1925 *		wcc_data	linkdir_wcc;
1926 *	};
1927 *
1928 *	union LINK3res switch (nfsstat3 status) {
1929 *	case NFS3_OK:
1930 *		LINK3resok	resok;
1931 *	default:
1932 *		LINK3resfail	resfail;
1933 *	};
1934 */
1935static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1936				 void *data)
1937{
1938	struct nfs3_linkres *result = data;
1939	enum nfs_stat status;
1940	int error;
1941
1942	error = decode_nfsstat3(xdr, &status);
1943	if (unlikely(error))
1944		goto out;
1945	error = decode_post_op_attr(xdr, result->fattr);
1946	if (unlikely(error))
1947		goto out;
1948	error = decode_wcc_data(xdr, result->dir_attr);
1949	if (unlikely(error))
1950		goto out;
1951	if (status != NFS3_OK)
1952		goto out_status;
1953out:
1954	return error;
1955out_status:
1956	return nfs3_stat_to_errno(status);
1957}
1958
1959/**
1960 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
1961 *			the local page cache
1962 * @xdr: XDR stream where entry resides
1963 * @entry: buffer to fill in with entry data
1964 * @plus: boolean indicating whether this should be a readdirplus entry
1965 *
1966 * Returns zero if successful, otherwise a negative errno value is
1967 * returned.
1968 *
1969 * This function is not invoked during READDIR reply decoding, but
1970 * rather whenever an application invokes the getdents(2) system call
1971 * on a directory already in our cache.
1972 *
1973 * 3.3.16  entry3
1974 *
1975 *	struct entry3 {
1976 *		fileid3		fileid;
1977 *		filename3	name;
1978 *		cookie3		cookie;
1979 *		fhandle3	filehandle;
1980 *		post_op_attr3	attributes;
1981 *		entry3		*nextentry;
1982 *	};
1983 *
1984 * 3.3.17  entryplus3
1985 *	struct entryplus3 {
1986 *		fileid3		fileid;
1987 *		filename3	name;
1988 *		cookie3		cookie;
1989 *		post_op_attr	name_attributes;
1990 *		post_op_fh3	name_handle;
1991 *		entryplus3	*nextentry;
1992 *	};
1993 */
1994int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
1995		       bool plus)
1996{
1997	struct nfs_entry old = *entry;
1998	__be32 *p;
1999	int error;
2000
2001	p = xdr_inline_decode(xdr, 4);
2002	if (unlikely(p == NULL))
2003		goto out_overflow;
2004	if (*p == xdr_zero) {
2005		p = xdr_inline_decode(xdr, 4);
2006		if (unlikely(p == NULL))
2007			goto out_overflow;
2008		if (*p == xdr_zero)
2009			return -EAGAIN;
2010		entry->eof = 1;
2011		return -EBADCOOKIE;
2012	}
2013
2014	error = decode_fileid3(xdr, &entry->ino);
2015	if (unlikely(error))
2016		return error;
2017
2018	error = decode_inline_filename3(xdr, &entry->name, &entry->len);
2019	if (unlikely(error))
2020		return error;
2021
2022	entry->prev_cookie = entry->cookie;
2023	error = decode_cookie3(xdr, &entry->cookie);
2024	if (unlikely(error))
2025		return error;
2026
2027	entry->d_type = DT_UNKNOWN;
2028
2029	if (plus) {
2030		entry->fattr->valid = 0;
2031		error = decode_post_op_attr(xdr, entry->fattr);
2032		if (unlikely(error))
2033			return error;
2034		if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
2035			entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
2036
2037		if (entry->fattr->fileid != entry->ino) {
2038			entry->fattr->mounted_on_fileid = entry->ino;
2039			entry->fattr->valid |= NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
2040		}
2041
2042		/* In fact, a post_op_fh3: */
2043		p = xdr_inline_decode(xdr, 4);
2044		if (unlikely(p == NULL))
2045			goto out_overflow;
2046		if (*p != xdr_zero) {
2047			error = decode_nfs_fh3(xdr, entry->fh);
2048			if (unlikely(error)) {
2049				if (error == -E2BIG)
2050					goto out_truncated;
2051				return error;
2052			}
2053		} else
2054			zero_nfs_fh3(entry->fh);
2055	}
2056
2057	return 0;
2058
2059out_overflow:
2060	print_overflow_msg(__func__, xdr);
2061	return -EAGAIN;
2062out_truncated:
2063	dprintk("NFS: directory entry contains invalid file handle\n");
2064	*entry = old;
2065	return -EAGAIN;
2066}
2067
2068/*
2069 * 3.3.16  READDIR3res
2070 *
2071 *	struct dirlist3 {
2072 *		entry3		*entries;
2073 *		bool		eof;
2074 *	};
2075 *
2076 *	struct READDIR3resok {
2077 *		post_op_attr	dir_attributes;
2078 *		cookieverf3	cookieverf;
2079 *		dirlist3	reply;
2080 *	};
2081 *
2082 *	struct READDIR3resfail {
2083 *		post_op_attr	dir_attributes;
2084 *	};
2085 *
2086 *	union READDIR3res switch (nfsstat3 status) {
2087 *	case NFS3_OK:
2088 *		READDIR3resok	resok;
2089 *	default:
2090 *		READDIR3resfail	resfail;
2091 *	};
2092 *
2093 * Read the directory contents into the page cache, but otherwise
2094 * don't touch them.  The actual decoding is done by nfs3_decode_entry()
2095 * during subsequent nfs_readdir() calls.
2096 */
2097static int decode_dirlist3(struct xdr_stream *xdr)
2098{
2099	return xdr_read_pages(xdr, xdr->buf->page_len);
2100}
2101
2102static int decode_readdir3resok(struct xdr_stream *xdr,
2103				struct nfs3_readdirres *result)
2104{
2105	int error;
2106
2107	error = decode_post_op_attr(xdr, result->dir_attr);
2108	if (unlikely(error))
2109		goto out;
2110	/* XXX: do we need to check if result->verf != NULL ? */
2111	error = decode_cookieverf3(xdr, result->verf);
2112	if (unlikely(error))
2113		goto out;
2114	error = decode_dirlist3(xdr);
2115out:
2116	return error;
2117}
2118
2119static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req,
2120				    struct xdr_stream *xdr,
2121				    void *data)
2122{
2123	struct nfs3_readdirres *result = data;
2124	enum nfs_stat status;
2125	int error;
2126
2127	error = decode_nfsstat3(xdr, &status);
2128	if (unlikely(error))
2129		goto out;
2130	if (status != NFS3_OK)
2131		goto out_default;
2132	error = decode_readdir3resok(xdr, result);
2133out:
2134	return error;
2135out_default:
2136	error = decode_post_op_attr(xdr, result->dir_attr);
2137	if (unlikely(error))
2138		goto out;
2139	return nfs3_stat_to_errno(status);
2140}
2141
2142/*
2143 * 3.3.18  FSSTAT3res
2144 *
2145 *	struct FSSTAT3resok {
2146 *		post_op_attr	obj_attributes;
2147 *		size3		tbytes;
2148 *		size3		fbytes;
2149 *		size3		abytes;
2150 *		size3		tfiles;
2151 *		size3		ffiles;
2152 *		size3		afiles;
2153 *		uint32		invarsec;
2154 *	};
2155 *
2156 *	struct FSSTAT3resfail {
2157 *		post_op_attr	obj_attributes;
2158 *	};
2159 *
2160 *	union FSSTAT3res switch (nfsstat3 status) {
2161 *	case NFS3_OK:
2162 *		FSSTAT3resok	resok;
2163 *	default:
2164 *		FSSTAT3resfail	resfail;
2165 *	};
2166 */
2167static int decode_fsstat3resok(struct xdr_stream *xdr,
2168			       struct nfs_fsstat *result)
2169{
2170	__be32 *p;
2171
2172	p = xdr_inline_decode(xdr, 8 * 6 + 4);
2173	if (unlikely(p == NULL))
2174		goto out_overflow;
2175	p = xdr_decode_size3(p, &result->tbytes);
2176	p = xdr_decode_size3(p, &result->fbytes);
2177	p = xdr_decode_size3(p, &result->abytes);
2178	p = xdr_decode_size3(p, &result->tfiles);
2179	p = xdr_decode_size3(p, &result->ffiles);
2180	xdr_decode_size3(p, &result->afiles);
2181	/* ignore invarsec */
2182	return 0;
2183out_overflow:
2184	print_overflow_msg(__func__, xdr);
2185	return -EIO;
2186}
2187
2188static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req,
2189				   struct xdr_stream *xdr,
2190				   void *data)
2191{
2192	struct nfs_fsstat *result = data;
2193	enum nfs_stat status;
2194	int error;
2195
2196	error = decode_nfsstat3(xdr, &status);
2197	if (unlikely(error))
2198		goto out;
2199	error = decode_post_op_attr(xdr, result->fattr);
2200	if (unlikely(error))
2201		goto out;
2202	if (status != NFS3_OK)
2203		goto out_status;
2204	error = decode_fsstat3resok(xdr, result);
2205out:
2206	return error;
2207out_status:
2208	return nfs3_stat_to_errno(status);
2209}
2210
2211/*
2212 * 3.3.19  FSINFO3res
2213 *
2214 *	struct FSINFO3resok {
2215 *		post_op_attr	obj_attributes;
2216 *		uint32		rtmax;
2217 *		uint32		rtpref;
2218 *		uint32		rtmult;
2219 *		uint32		wtmax;
2220 *		uint32		wtpref;
2221 *		uint32		wtmult;
2222 *		uint32		dtpref;
2223 *		size3		maxfilesize;
2224 *		nfstime3	time_delta;
2225 *		uint32		properties;
2226 *	};
2227 *
2228 *	struct FSINFO3resfail {
2229 *		post_op_attr	obj_attributes;
2230 *	};
2231 *
2232 *	union FSINFO3res switch (nfsstat3 status) {
2233 *	case NFS3_OK:
2234 *		FSINFO3resok	resok;
2235 *	default:
2236 *		FSINFO3resfail	resfail;
2237 *	};
2238 */
2239static int decode_fsinfo3resok(struct xdr_stream *xdr,
2240			       struct nfs_fsinfo *result)
2241{
2242	__be32 *p;
2243
2244	p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
2245	if (unlikely(p == NULL))
2246		goto out_overflow;
2247	result->rtmax  = be32_to_cpup(p++);
2248	result->rtpref = be32_to_cpup(p++);
2249	result->rtmult = be32_to_cpup(p++);
2250	result->wtmax  = be32_to_cpup(p++);
2251	result->wtpref = be32_to_cpup(p++);
2252	result->wtmult = be32_to_cpup(p++);
2253	result->dtpref = be32_to_cpup(p++);
2254	p = xdr_decode_size3(p, &result->maxfilesize);
2255	xdr_decode_nfstime3(p, &result->time_delta);
2256
2257	/* ignore properties */
2258	result->lease_time = 0;
2259	return 0;
2260out_overflow:
2261	print_overflow_msg(__func__, xdr);
2262	return -EIO;
2263}
2264
2265static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req,
2266				   struct xdr_stream *xdr,
2267				   void *data)
2268{
2269	struct nfs_fsinfo *result = data;
2270	enum nfs_stat status;
2271	int error;
2272
2273	error = decode_nfsstat3(xdr, &status);
2274	if (unlikely(error))
2275		goto out;
2276	error = decode_post_op_attr(xdr, result->fattr);
2277	if (unlikely(error))
2278		goto out;
2279	if (status != NFS3_OK)
2280		goto out_status;
2281	error = decode_fsinfo3resok(xdr, result);
2282out:
2283	return error;
2284out_status:
2285	return nfs3_stat_to_errno(status);
2286}
2287
2288/*
2289 * 3.3.20  PATHCONF3res
2290 *
2291 *	struct PATHCONF3resok {
2292 *		post_op_attr	obj_attributes;
2293 *		uint32		linkmax;
2294 *		uint32		name_max;
2295 *		bool		no_trunc;
2296 *		bool		chown_restricted;
2297 *		bool		case_insensitive;
2298 *		bool		case_preserving;
2299 *	};
2300 *
2301 *	struct PATHCONF3resfail {
2302 *		post_op_attr	obj_attributes;
2303 *	};
2304 *
2305 *	union PATHCONF3res switch (nfsstat3 status) {
2306 *	case NFS3_OK:
2307 *		PATHCONF3resok	resok;
2308 *	default:
2309 *		PATHCONF3resfail resfail;
2310 *	};
2311 */
2312static int decode_pathconf3resok(struct xdr_stream *xdr,
2313				 struct nfs_pathconf *result)
2314{
2315	__be32 *p;
2316
2317	p = xdr_inline_decode(xdr, 4 * 6);
2318	if (unlikely(p == NULL))
2319		goto out_overflow;
2320	result->max_link = be32_to_cpup(p++);
2321	result->max_namelen = be32_to_cpup(p);
2322	/* ignore remaining fields */
2323	return 0;
2324out_overflow:
2325	print_overflow_msg(__func__, xdr);
2326	return -EIO;
2327}
2328
2329static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req,
2330				     struct xdr_stream *xdr,
2331				     void *data)
2332{
2333	struct nfs_pathconf *result = 

Large files files are truncated, but you can click here to view the full file