PageRenderTime 5ms CodeModel.GetById 8ms app.highlight 82ms RepoModel.GetById 2ms app.codeStats 0ms

/fs/nfs/nfs3xdr.c

https://bitbucket.org/digetx/picasso-kernel
C | 2546 lines | 1476 code | 217 blank | 853 comment | 198 complexity | f4f6c9ba0973f35e1312ba3031b74e1d MD5 | raw file

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

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