PageRenderTime 101ms CodeModel.GetById 19ms app.highlight 74ms RepoModel.GetById 0ms app.codeStats 1ms

/fs/nfs/nfs3xdr.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 2498 lines | 1444 code | 214 blank | 840 comment | 194 complexity | 5d8e77c8f5d197f5d6c8adaaa681b728 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0

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

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

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