Linux Audio

Check our new training course

Loading...
   1/*
   2 * linux/fs/nfs/nfs2xdr.c
   3 *
   4 * XDR functions to encode/decode NFS RPC arguments and results.
   5 *
   6 * Copyright (C) 1992, 1993, 1994  Rick Sladkey
   7 * Copyright (C) 1996 Olaf Kirch
   8 * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>
   9 * 		FIFO's need special handling in NFSv2
  10 */
  11
  12#include <linux/param.h>
  13#include <linux/time.h>
  14#include <linux/mm.h>
  15#include <linux/errno.h>
  16#include <linux/string.h>
  17#include <linux/in.h>
  18#include <linux/pagemap.h>
  19#include <linux/proc_fs.h>
  20#include <linux/sunrpc/clnt.h>
  21#include <linux/nfs.h>
  22#include <linux/nfs2.h>
  23#include <linux/nfs_fs.h>
  24#include "internal.h"
  25
  26#define NFSDBG_FACILITY		NFSDBG_XDR
  27
  28/* Mapping from NFS error code to "errno" error code. */
  29#define errno_NFSERR_IO		EIO
  30
  31/*
  32 * Declare the space requirements for NFS arguments and replies as
  33 * number of 32bit-words
  34 */
  35#define NFS_fhandle_sz		(8)
  36#define NFS_sattr_sz		(8)
  37#define NFS_filename_sz		(1+(NFS2_MAXNAMLEN>>2))
  38#define NFS_path_sz		(1+(NFS2_MAXPATHLEN>>2))
  39#define NFS_fattr_sz		(17)
  40#define NFS_info_sz		(5)
  41#define NFS_entry_sz		(NFS_filename_sz+3)
  42
  43#define NFS_diropargs_sz	(NFS_fhandle_sz+NFS_filename_sz)
  44#define NFS_removeargs_sz	(NFS_fhandle_sz+NFS_filename_sz)
  45#define NFS_sattrargs_sz	(NFS_fhandle_sz+NFS_sattr_sz)
  46#define NFS_readlinkargs_sz	(NFS_fhandle_sz)
  47#define NFS_readargs_sz		(NFS_fhandle_sz+3)
  48#define NFS_writeargs_sz	(NFS_fhandle_sz+4)
  49#define NFS_createargs_sz	(NFS_diropargs_sz+NFS_sattr_sz)
  50#define NFS_renameargs_sz	(NFS_diropargs_sz+NFS_diropargs_sz)
  51#define NFS_linkargs_sz		(NFS_fhandle_sz+NFS_diropargs_sz)
  52#define NFS_symlinkargs_sz	(NFS_diropargs_sz+1+NFS_sattr_sz)
  53#define NFS_readdirargs_sz	(NFS_fhandle_sz+2)
  54
  55#define NFS_attrstat_sz		(1+NFS_fattr_sz)
  56#define NFS_diropres_sz		(1+NFS_fhandle_sz+NFS_fattr_sz)
  57#define NFS_readlinkres_sz	(2)
  58#define NFS_readres_sz		(1+NFS_fattr_sz+1)
  59#define NFS_writeres_sz         (NFS_attrstat_sz)
  60#define NFS_stat_sz		(1)
  61#define NFS_readdirres_sz	(1)
  62#define NFS_statfsres_sz	(1+NFS_info_sz)
  63
  64static int nfs_stat_to_errno(enum nfs_stat);
  65
  66/*
  67 * While encoding arguments, set up the reply buffer in advance to
  68 * receive reply data directly into the page cache.
  69 */
  70static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
  71				 unsigned int base, unsigned int len,
  72				 unsigned int bufsize)
  73{
  74	struct rpc_auth	*auth = req->rq_cred->cr_auth;
  75	unsigned int replen;
  76
  77	replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
  78	xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
  79}
  80
  81/*
  82 * Handle decode buffer overflows out-of-line.
  83 */
  84static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
  85{
  86	dprintk("NFS: %s prematurely hit the end of our receive buffer. "
  87		"Remaining buffer length is %tu words.\n",
  88		func, xdr->end - xdr->p);
  89}
  90
  91
  92/*
  93 * Encode/decode NFSv2 basic data types
  94 *
  95 * Basic NFSv2 data types are defined in section 2.3 of RFC 1094:
  96 * "NFS: Network File System Protocol Specification".
  97 *
  98 * Not all basic data types have their own encoding and decoding
  99 * functions.  For run-time efficiency, some data types are encoded
 100 * or decoded inline.
 101 */
 102
 103/*
 104 *	typedef opaque	nfsdata<>;
 105 */
 106static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
 107{
 108	u32 recvd, count;
 109	size_t hdrlen;
 110	__be32 *p;
 111
 112	p = xdr_inline_decode(xdr, 4);
 113	if (unlikely(p == NULL))
 114		goto out_overflow;
 115	count = be32_to_cpup(p);
 116	hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
 117	recvd = xdr->buf->len - hdrlen;
 118	if (unlikely(count > recvd))
 119		goto out_cheating;
 120out:
 121	xdr_read_pages(xdr, count);
 122	result->eof = 0;	/* NFSv2 does not pass EOF flag on the wire. */
 123	result->count = count;
 124	return count;
 125out_cheating:
 126	dprintk("NFS: server cheating in read result: "
 127		"count %u > recvd %u\n", count, recvd);
 128	count = recvd;
 129	goto out;
 130out_overflow:
 131	print_overflow_msg(__func__, xdr);
 132	return -EIO;
 133}
 134
 135/*
 136 *	enum stat {
 137 *		NFS_OK = 0,
 138 *		NFSERR_PERM = 1,
 139 *		NFSERR_NOENT = 2,
 140 *		NFSERR_IO = 5,
 141 *		NFSERR_NXIO = 6,
 142 *		NFSERR_ACCES = 13,
 143 *		NFSERR_EXIST = 17,
 144 *		NFSERR_NODEV = 19,
 145 *		NFSERR_NOTDIR = 20,
 146 *		NFSERR_ISDIR = 21,
 147 *		NFSERR_FBIG = 27,
 148 *		NFSERR_NOSPC = 28,
 149 *		NFSERR_ROFS = 30,
 150 *		NFSERR_NAMETOOLONG = 63,
 151 *		NFSERR_NOTEMPTY = 66,
 152 *		NFSERR_DQUOT = 69,
 153 *		NFSERR_STALE = 70,
 154 *		NFSERR_WFLUSH = 99
 155 *	};
 156 */
 157static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
 158{
 159	__be32 *p;
 160
 161	p = xdr_inline_decode(xdr, 4);
 162	if (unlikely(p == NULL))
 163		goto out_overflow;
 164	*status = be32_to_cpup(p);
 165	return 0;
 166out_overflow:
 167	print_overflow_msg(__func__, xdr);
 168	return -EIO;
 169}
 170
 171/*
 172 * 2.3.2.  ftype
 173 *
 174 *	enum ftype {
 175 *		NFNON = 0,
 176 *		NFREG = 1,
 177 *		NFDIR = 2,
 178 *		NFBLK = 3,
 179 *		NFCHR = 4,
 180 *		NFLNK = 5
 181 *	};
 182 *
 183 */
 184static __be32 *xdr_decode_ftype(__be32 *p, u32 *type)
 185{
 186	*type = be32_to_cpup(p++);
 187	if (unlikely(*type > NF2FIFO))
 188		*type = NFBAD;
 189	return p;
 190}
 191
 192/*
 193 * 2.3.3.  fhandle
 194 *
 195 *	typedef opaque fhandle[FHSIZE];
 196 */
 197static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
 198{
 199	__be32 *p;
 200
 201	BUG_ON(fh->size != NFS2_FHSIZE);
 202	p = xdr_reserve_space(xdr, NFS2_FHSIZE);
 203	memcpy(p, fh->data, NFS2_FHSIZE);
 204}
 205
 206static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
 207{
 208	__be32 *p;
 209
 210	p = xdr_inline_decode(xdr, NFS2_FHSIZE);
 211	if (unlikely(p == NULL))
 212		goto out_overflow;
 213	fh->size = NFS2_FHSIZE;
 214	memcpy(fh->data, p, NFS2_FHSIZE);
 215	return 0;
 216out_overflow:
 217	print_overflow_msg(__func__, xdr);
 218	return -EIO;
 219}
 220
 221/*
 222 * 2.3.4.  timeval
 223 *
 224 *	struct timeval {
 225 *		unsigned int seconds;
 226 *		unsigned int useconds;
 227 *	};
 228 */
 229static __be32 *xdr_encode_time(__be32 *p, const struct timespec *timep)
 230{
 231	*p++ = cpu_to_be32(timep->tv_sec);
 232	if (timep->tv_nsec != 0)
 233		*p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC);
 234	else
 235		*p++ = cpu_to_be32(0);
 236	return p;
 237}
 238
 239/*
 240 * Passing the invalid value useconds=1000000 is a Sun convention for
 241 * "set to current server time".  It's needed to make permissions checks
 242 * for the "touch" program across v2 mounts to Solaris and Irix servers
 243 * work correctly.  See description of sattr in section 6.1 of "NFS
 244 * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5.
 245 */
 246static __be32 *xdr_encode_current_server_time(__be32 *p,
 247					      const struct timespec *timep)
 248{
 249	*p++ = cpu_to_be32(timep->tv_sec);
 250	*p++ = cpu_to_be32(1000000);
 251	return p;
 252}
 253
 254static __be32 *xdr_decode_time(__be32 *p, struct timespec *timep)
 255{
 256	timep->tv_sec = be32_to_cpup(p++);
 257	timep->tv_nsec = be32_to_cpup(p++) * NSEC_PER_USEC;
 258	return p;
 259}
 260
 261/*
 262 * 2.3.5.  fattr
 263 *
 264 *	struct fattr {
 265 *		ftype		type;
 266 *		unsigned int	mode;
 267 *		unsigned int	nlink;
 268 *		unsigned int	uid;
 269 *		unsigned int	gid;
 270 *		unsigned int	size;
 271 *		unsigned int	blocksize;
 272 *		unsigned int	rdev;
 273 *		unsigned int	blocks;
 274 *		unsigned int	fsid;
 275 *		unsigned int	fileid;
 276 *		timeval		atime;
 277 *		timeval		mtime;
 278 *		timeval		ctime;
 279 *	};
 280 *
 281 */
 282static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 283{
 284	u32 rdev, type;
 285	__be32 *p;
 286
 287	p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
 288	if (unlikely(p == NULL))
 289		goto out_overflow;
 290
 291	fattr->valid |= NFS_ATTR_FATTR_V2;
 292
 293	p = xdr_decode_ftype(p, &type);
 294
 295	fattr->mode = be32_to_cpup(p++);
 296	fattr->nlink = be32_to_cpup(p++);
 297	fattr->uid = be32_to_cpup(p++);
 298	fattr->gid = be32_to_cpup(p++);
 299	fattr->size = be32_to_cpup(p++);
 300	fattr->du.nfs2.blocksize = be32_to_cpup(p++);
 301
 302	rdev = be32_to_cpup(p++);
 303	fattr->rdev = new_decode_dev(rdev);
 304	if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) {
 305		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
 306		fattr->rdev = 0;
 307	}
 308
 309	fattr->du.nfs2.blocks = be32_to_cpup(p++);
 310	fattr->fsid.major = be32_to_cpup(p++);
 311	fattr->fsid.minor = 0;
 312	fattr->fileid = be32_to_cpup(p++);
 313
 314	p = xdr_decode_time(p, &fattr->atime);
 315	p = xdr_decode_time(p, &fattr->mtime);
 316	xdr_decode_time(p, &fattr->ctime);
 317	fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
 318
 319	return 0;
 320out_overflow:
 321	print_overflow_msg(__func__, xdr);
 322	return -EIO;
 323}
 324
 325/*
 326 * 2.3.6.  sattr
 327 *
 328 *	struct sattr {
 329 *		unsigned int	mode;
 330 *		unsigned int	uid;
 331 *		unsigned int	gid;
 332 *		unsigned int	size;
 333 *		timeval		atime;
 334 *		timeval		mtime;
 335 *	};
 336 */
 337
 338#define NFS2_SATTR_NOT_SET	(0xffffffff)
 339
 340static __be32 *xdr_time_not_set(__be32 *p)
 341{
 342	*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 343	*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 344	return p;
 345}
 346
 347static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
 348{
 349	__be32 *p;
 350
 351	p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
 352
 353	if (attr->ia_valid & ATTR_MODE)
 354		*p++ = cpu_to_be32(attr->ia_mode);
 355	else
 356		*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 357	if (attr->ia_valid & ATTR_UID)
 358		*p++ = cpu_to_be32(attr->ia_uid);
 359	else
 360		*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 361	if (attr->ia_valid & ATTR_GID)
 362		*p++ = cpu_to_be32(attr->ia_gid);
 363	else
 364		*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 365	if (attr->ia_valid & ATTR_SIZE)
 366		*p++ = cpu_to_be32((u32)attr->ia_size);
 367	else
 368		*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 369
 370	if (attr->ia_valid & ATTR_ATIME_SET)
 371		p = xdr_encode_time(p, &attr->ia_atime);
 372	else if (attr->ia_valid & ATTR_ATIME)
 373		p = xdr_encode_current_server_time(p, &attr->ia_atime);
 374	else
 375		p = xdr_time_not_set(p);
 376	if (attr->ia_valid & ATTR_MTIME_SET)
 377		xdr_encode_time(p, &attr->ia_mtime);
 378	else if (attr->ia_valid & ATTR_MTIME)
 379		xdr_encode_current_server_time(p, &attr->ia_mtime);
 380	else
 381		xdr_time_not_set(p);
 382}
 383
 384/*
 385 * 2.3.7.  filename
 386 *
 387 *	typedef string filename<MAXNAMLEN>;
 388 */
 389static void encode_filename(struct xdr_stream *xdr,
 390			    const char *name, u32 length)
 391{
 392	__be32 *p;
 393
 394	BUG_ON(length > NFS2_MAXNAMLEN);
 395	p = xdr_reserve_space(xdr, 4 + length);
 396	xdr_encode_opaque(p, name, length);
 397}
 398
 399static int decode_filename_inline(struct xdr_stream *xdr,
 400				  const char **name, u32 *length)
 401{
 402	__be32 *p;
 403	u32 count;
 404
 405	p = xdr_inline_decode(xdr, 4);
 406	if (unlikely(p == NULL))
 407		goto out_overflow;
 408	count = be32_to_cpup(p);
 409	if (count > NFS3_MAXNAMLEN)
 410		goto out_nametoolong;
 411	p = xdr_inline_decode(xdr, count);
 412	if (unlikely(p == NULL))
 413		goto out_overflow;
 414	*name = (const char *)p;
 415	*length = count;
 416	return 0;
 417out_nametoolong:
 418	dprintk("NFS: returned filename too long: %u\n", count);
 419	return -ENAMETOOLONG;
 420out_overflow:
 421	print_overflow_msg(__func__, xdr);
 422	return -EIO;
 423}
 424
 425/*
 426 * 2.3.8.  path
 427 *
 428 *	typedef string path<MAXPATHLEN>;
 429 */
 430static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
 431{
 432	__be32 *p;
 433
 434	BUG_ON(length > NFS2_MAXPATHLEN);
 435	p = xdr_reserve_space(xdr, 4);
 436	*p = cpu_to_be32(length);
 437	xdr_write_pages(xdr, pages, 0, length);
 438}
 439
 440static int decode_path(struct xdr_stream *xdr)
 441{
 442	u32 length, recvd;
 443	size_t hdrlen;
 444	__be32 *p;
 445
 446	p = xdr_inline_decode(xdr, 4);
 447	if (unlikely(p == NULL))
 448		goto out_overflow;
 449	length = be32_to_cpup(p);
 450	if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
 451		goto out_size;
 452	hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
 453	recvd = xdr->buf->len - hdrlen;
 454	if (unlikely(length > recvd))
 455		goto out_cheating;
 456
 457	xdr_read_pages(xdr, length);
 458	xdr_terminate_string(xdr->buf, length);
 459	return 0;
 460out_size:
 461	dprintk("NFS: returned pathname too long: %u\n", length);
 462	return -ENAMETOOLONG;
 463out_cheating:
 464	dprintk("NFS: server cheating in pathname result: "
 465		"length %u > received %u\n", length, recvd);
 466	return -EIO;
 467out_overflow:
 468	print_overflow_msg(__func__, xdr);
 469	return -EIO;
 470}
 471
 472/*
 473 * 2.3.9.  attrstat
 474 *
 475 *	union attrstat switch (stat status) {
 476 *	case NFS_OK:
 477 *		fattr attributes;
 478 *	default:
 479 *		void;
 480 *	};
 481 */
 482static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result)
 483{
 484	enum nfs_stat status;
 485	int error;
 486
 487	error = decode_stat(xdr, &status);
 488	if (unlikely(error))
 489		goto out;
 490	if (status != NFS_OK)
 491		goto out_default;
 492	error = decode_fattr(xdr, result);
 493out:
 494	return error;
 495out_default:
 496	return nfs_stat_to_errno(status);
 497}
 498
 499/*
 500 * 2.3.10.  diropargs
 501 *
 502 *	struct diropargs {
 503 *		fhandle  dir;
 504 *		filename name;
 505 *	};
 506 */
 507static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
 508			     const char *name, u32 length)
 509{
 510	encode_fhandle(xdr, fh);
 511	encode_filename(xdr, name, length);
 512}
 513
 514/*
 515 * 2.3.11.  diropres
 516 *
 517 *	union diropres switch (stat status) {
 518 *	case NFS_OK:
 519 *		struct {
 520 *			fhandle file;
 521 *			fattr   attributes;
 522 *		} diropok;
 523 *	default:
 524 *		void;
 525 *	};
 526 */
 527static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result)
 528{
 529	int error;
 530
 531	error = decode_fhandle(xdr, result->fh);
 532	if (unlikely(error))
 533		goto out;
 534	error = decode_fattr(xdr, result->fattr);
 535out:
 536	return error;
 537}
 538
 539static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result)
 540{
 541	enum nfs_stat status;
 542	int error;
 543
 544	error = decode_stat(xdr, &status);
 545	if (unlikely(error))
 546		goto out;
 547	if (status != NFS_OK)
 548		goto out_default;
 549	error = decode_diropok(xdr, result);
 550out:
 551	return error;
 552out_default:
 553	return nfs_stat_to_errno(status);
 554}
 555
 556
 557/*
 558 * NFSv2 XDR encode functions
 559 *
 560 * NFSv2 argument types are defined in section 2.2 of RFC 1094:
 561 * "NFS: Network File System Protocol Specification".
 562 */
 563
 564static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req,
 565				 struct xdr_stream *xdr,
 566				 const struct nfs_fh *fh)
 567{
 568	encode_fhandle(xdr, fh);
 569}
 570
 571/*
 572 * 2.2.3.  sattrargs
 573 *
 574 *	struct sattrargs {
 575 *		fhandle file;
 576 *		sattr attributes;
 577 *	};
 578 */
 579static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
 580				   struct xdr_stream *xdr,
 581				   const struct nfs_sattrargs *args)
 582{
 583	encode_fhandle(xdr, args->fh);
 584	encode_sattr(xdr, args->sattr);
 585}
 586
 587static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
 588				   struct xdr_stream *xdr,
 589				   const struct nfs_diropargs *args)
 590{
 591	encode_diropargs(xdr, args->fh, args->name, args->len);
 592}
 593
 594static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
 595				      struct xdr_stream *xdr,
 596				      const struct nfs_readlinkargs *args)
 597{
 598	encode_fhandle(xdr, args->fh);
 599	prepare_reply_buffer(req, args->pages, args->pgbase,
 600					args->pglen, NFS_readlinkres_sz);
 601}
 602
 603/*
 604 * 2.2.7.  readargs
 605 *
 606 *	struct readargs {
 607 *		fhandle file;
 608 *		unsigned offset;
 609 *		unsigned count;
 610 *		unsigned totalcount;
 611 *	};
 612 */
 613static void encode_readargs(struct xdr_stream *xdr,
 614			    const struct nfs_readargs *args)
 615{
 616	u32 offset = args->offset;
 617	u32 count = args->count;
 618	__be32 *p;
 619
 620	encode_fhandle(xdr, args->fh);
 621
 622	p = xdr_reserve_space(xdr, 4 + 4 + 4);
 623	*p++ = cpu_to_be32(offset);
 624	*p++ = cpu_to_be32(count);
 625	*p = cpu_to_be32(count);
 626}
 627
 628static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
 629				  struct xdr_stream *xdr,
 630				  const struct nfs_readargs *args)
 631{
 632	encode_readargs(xdr, args);
 633	prepare_reply_buffer(req, args->pages, args->pgbase,
 634					args->count, NFS_readres_sz);
 635	req->rq_rcv_buf.flags |= XDRBUF_READ;
 636}
 637
 638/*
 639 * 2.2.9.  writeargs
 640 *
 641 *	struct writeargs {
 642 *		fhandle file;
 643 *		unsigned beginoffset;
 644 *		unsigned offset;
 645 *		unsigned totalcount;
 646 *		nfsdata data;
 647 *	};
 648 */
 649static void encode_writeargs(struct xdr_stream *xdr,
 650			     const struct nfs_writeargs *args)
 651{
 652	u32 offset = args->offset;
 653	u32 count = args->count;
 654	__be32 *p;
 655
 656	encode_fhandle(xdr, args->fh);
 657
 658	p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
 659	*p++ = cpu_to_be32(offset);
 660	*p++ = cpu_to_be32(offset);
 661	*p++ = cpu_to_be32(count);
 662
 663	/* nfsdata */
 664	*p = cpu_to_be32(count);
 665	xdr_write_pages(xdr, args->pages, args->pgbase, count);
 666}
 667
 668static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
 669				   struct xdr_stream *xdr,
 670				   const struct nfs_writeargs *args)
 671{
 672	encode_writeargs(xdr, args);
 673	xdr->buf->flags |= XDRBUF_WRITE;
 674}
 675
 676/*
 677 * 2.2.10.  createargs
 678 *
 679 *	struct createargs {
 680 *		diropargs where;
 681 *		sattr attributes;
 682 *	};
 683 */
 684static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
 685				    struct xdr_stream *xdr,
 686				    const struct nfs_createargs *args)
 687{
 688	encode_diropargs(xdr, args->fh, args->name, args->len);
 689	encode_sattr(xdr, args->sattr);
 690}
 691
 692static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
 693				    struct xdr_stream *xdr,
 694				    const struct nfs_removeargs *args)
 695{
 696	encode_diropargs(xdr, args->fh, args->name.name, args->name.len);
 697}
 698
 699/*
 700 * 2.2.12.  renameargs
 701 *
 702 *	struct renameargs {
 703 *		diropargs from;
 704 *		diropargs to;
 705 *	};
 706 */
 707static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req,
 708				    struct xdr_stream *xdr,
 709				    const struct nfs_renameargs *args)
 710{
 711	const struct qstr *old = args->old_name;
 712	const struct qstr *new = args->new_name;
 713
 714	encode_diropargs(xdr, args->old_dir, old->name, old->len);
 715	encode_diropargs(xdr, args->new_dir, new->name, new->len);
 716}
 717
 718/*
 719 * 2.2.13.  linkargs
 720 *
 721 *	struct linkargs {
 722 *		fhandle from;
 723 *		diropargs to;
 724 *	};
 725 */
 726static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req,
 727				  struct xdr_stream *xdr,
 728				  const struct nfs_linkargs *args)
 729{
 730	encode_fhandle(xdr, args->fromfh);
 731	encode_diropargs(xdr, args->tofh, args->toname, args->tolen);
 732}
 733
 734/*
 735 * 2.2.14.  symlinkargs
 736 *
 737 *	struct symlinkargs {
 738 *		diropargs from;
 739 *		path to;
 740 *		sattr attributes;
 741 *	};
 742 */
 743static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
 744				     struct xdr_stream *xdr,
 745				     const struct nfs_symlinkargs *args)
 746{
 747	encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
 748	encode_path(xdr, args->pages, args->pathlen);
 749	encode_sattr(xdr, args->sattr);
 750}
 751
 752/*
 753 * 2.2.17.  readdirargs
 754 *
 755 *	struct readdirargs {
 756 *		fhandle dir;
 757 *		nfscookie cookie;
 758 *		unsigned count;
 759 *	};
 760 */
 761static void encode_readdirargs(struct xdr_stream *xdr,
 762			       const struct nfs_readdirargs *args)
 763{
 764	__be32 *p;
 765
 766	encode_fhandle(xdr, args->fh);
 767
 768	p = xdr_reserve_space(xdr, 4 + 4);
 769	*p++ = cpu_to_be32(args->cookie);
 770	*p = cpu_to_be32(args->count);
 771}
 772
 773static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
 774				     struct xdr_stream *xdr,
 775				     const struct nfs_readdirargs *args)
 776{
 777	encode_readdirargs(xdr, args);
 778	prepare_reply_buffer(req, args->pages, 0,
 779					args->count, NFS_readdirres_sz);
 780}
 781
 782/*
 783 * NFSv2 XDR decode functions
 784 *
 785 * NFSv2 result types are defined in section 2.2 of RFC 1094:
 786 * "NFS: Network File System Protocol Specification".
 787 */
 788
 789static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
 790			     void *__unused)
 791{
 792	enum nfs_stat status;
 793	int error;
 794
 795	error = decode_stat(xdr, &status);
 796	if (unlikely(error))
 797		goto out;
 798	if (status != NFS_OK)
 799		goto out_default;
 800out:
 801	return error;
 802out_default:
 803	return nfs_stat_to_errno(status);
 804}
 805
 806static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
 807				 struct nfs_fattr *result)
 808{
 809	return decode_attrstat(xdr, result);
 810}
 811
 812static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
 813				 struct nfs_diropok *result)
 814{
 815	return decode_diropres(xdr, result);
 816}
 817
 818/*
 819 * 2.2.6.  readlinkres
 820 *
 821 *	union readlinkres switch (stat status) {
 822 *	case NFS_OK:
 823 *		path data;
 824 *	default:
 825 *		void;
 826 *	};
 827 */
 828static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req,
 829				    struct xdr_stream *xdr, void *__unused)
 830{
 831	enum nfs_stat status;
 832	int error;
 833
 834	error = decode_stat(xdr, &status);
 835	if (unlikely(error))
 836		goto out;
 837	if (status != NFS_OK)
 838		goto out_default;
 839	error = decode_path(xdr);
 840out:
 841	return error;
 842out_default:
 843	return nfs_stat_to_errno(status);
 844}
 845
 846/*
 847 * 2.2.7.  readres
 848 *
 849 *	union readres switch (stat status) {
 850 *	case NFS_OK:
 851 *		fattr attributes;
 852 *		nfsdata data;
 853 *	default:
 854 *		void;
 855 *	};
 856 */
 857static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
 858				struct nfs_readres *result)
 859{
 860	enum nfs_stat status;
 861	int error;
 862
 863	error = decode_stat(xdr, &status);
 864	if (unlikely(error))
 865		goto out;
 866	if (status != NFS_OK)
 867		goto out_default;
 868	error = decode_fattr(xdr, result->fattr);
 869	if (unlikely(error))
 870		goto out;
 871	error = decode_nfsdata(xdr, result);
 872out:
 873	return error;
 874out_default:
 875	return nfs_stat_to_errno(status);
 876}
 877
 878static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
 879				 struct nfs_writeres *result)
 880{
 881	/* All NFSv2 writes are "file sync" writes */
 882	result->verf->committed = NFS_FILE_SYNC;
 883	return decode_attrstat(xdr, result->fattr);
 884}
 885
 886/**
 887 * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
 888 *                      the local page cache.
 889 * @xdr: XDR stream where entry resides
 890 * @entry: buffer to fill in with entry data
 891 * @plus: boolean indicating whether this should be a readdirplus entry
 892 *
 893 * Returns zero if successful, otherwise a negative errno value is
 894 * returned.
 895 *
 896 * This function is not invoked during READDIR reply decoding, but
 897 * rather whenever an application invokes the getdents(2) system call
 898 * on a directory already in our cache.
 899 *
 900 * 2.2.17.  entry
 901 *
 902 *	struct entry {
 903 *		unsigned	fileid;
 904 *		filename	name;
 905 *		nfscookie	cookie;
 906 *		entry		*nextentry;
 907 *	};
 908 */
 909int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
 910		       int plus)
 911{
 912	__be32 *p;
 913	int error;
 914
 915	p = xdr_inline_decode(xdr, 4);
 916	if (unlikely(p == NULL))
 917		goto out_overflow;
 918	if (*p++ == xdr_zero) {
 919		p = xdr_inline_decode(xdr, 4);
 920		if (unlikely(p == NULL))
 921			goto out_overflow;
 922		if (*p++ == xdr_zero)
 923			return -EAGAIN;
 924		entry->eof = 1;
 925		return -EBADCOOKIE;
 926	}
 927
 928	p = xdr_inline_decode(xdr, 4);
 929	if (unlikely(p == NULL))
 930		goto out_overflow;
 931	entry->ino = be32_to_cpup(p);
 932
 933	error = decode_filename_inline(xdr, &entry->name, &entry->len);
 934	if (unlikely(error))
 935		return error;
 936
 937	/*
 938	 * The type (size and byte order) of nfscookie isn't defined in
 939	 * RFC 1094.  This implementation assumes that it's an XDR uint32.
 940	 */
 941	entry->prev_cookie = entry->cookie;
 942	p = xdr_inline_decode(xdr, 4);
 943	if (unlikely(p == NULL))
 944		goto out_overflow;
 945	entry->cookie = be32_to_cpup(p);
 946
 947	entry->d_type = DT_UNKNOWN;
 948
 949	return 0;
 950
 951out_overflow:
 952	print_overflow_msg(__func__, xdr);
 953	return -EAGAIN;
 954}
 955
 956/*
 957 * 2.2.17.  readdirres
 958 *
 959 *	union readdirres switch (stat status) {
 960 *	case NFS_OK:
 961 *		struct {
 962 *			entry *entries;
 963 *			bool eof;
 964 *		} readdirok;
 965 *	default:
 966 *		void;
 967 *	};
 968 *
 969 * Read the directory contents into the page cache, but don't
 970 * touch them.  The actual decoding is done by nfs2_decode_dirent()
 971 * during subsequent nfs_readdir() calls.
 972 */
 973static int decode_readdirok(struct xdr_stream *xdr)
 974{
 975	u32 recvd, pglen;
 976	size_t hdrlen;
 977
 978	pglen = xdr->buf->page_len;
 979	hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
 980	recvd = xdr->buf->len - hdrlen;
 981	if (unlikely(pglen > recvd))
 982		goto out_cheating;
 983out:
 984	xdr_read_pages(xdr, pglen);
 985	return pglen;
 986out_cheating:
 987	dprintk("NFS: server cheating in readdir result: "
 988		"pglen %u > recvd %u\n", pglen, recvd);
 989	pglen = recvd;
 990	goto out;
 991}
 992
 993static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
 994				   struct xdr_stream *xdr, void *__unused)
 995{
 996	enum nfs_stat status;
 997	int error;
 998
 999	error = decode_stat(xdr, &status);
1000	if (unlikely(error))
1001		goto out;
1002	if (status != NFS_OK)
1003		goto out_default;
1004	error = decode_readdirok(xdr);
1005out:
1006	return error;
1007out_default:
1008	return nfs_stat_to_errno(status);
1009}
1010
1011/*
1012 * 2.2.18.  statfsres
1013 *
1014 *	union statfsres (stat status) {
1015 *	case NFS_OK:
1016 *		struct {
1017 *			unsigned tsize;
1018 *			unsigned bsize;
1019 *			unsigned blocks;
1020 *			unsigned bfree;
1021 *			unsigned bavail;
1022 *		} info;
1023 *	default:
1024 *		void;
1025 *	};
1026 */
1027static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1028{
1029	__be32 *p;
1030
1031	p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1032	if (unlikely(p == NULL))
1033		goto out_overflow;
1034	result->tsize  = be32_to_cpup(p++);
1035	result->bsize  = be32_to_cpup(p++);
1036	result->blocks = be32_to_cpup(p++);
1037	result->bfree  = be32_to_cpup(p++);
1038	result->bavail = be32_to_cpup(p);
1039	return 0;
1040out_overflow:
1041	print_overflow_msg(__func__, xdr);
1042	return -EIO;
1043}
1044
1045static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
1046				  struct nfs2_fsstat *result)
1047{
1048	enum nfs_stat status;
1049	int error;
1050
1051	error = decode_stat(xdr, &status);
1052	if (unlikely(error))
1053		goto out;
1054	if (status != NFS_OK)
1055		goto out_default;
1056	error = decode_info(xdr, result);
1057out:
1058	return error;
1059out_default:
1060	return nfs_stat_to_errno(status);
1061}
1062
1063
1064/*
1065 * We need to translate between nfs status return values and
1066 * the local errno values which may not be the same.
1067 */
1068static const struct {
1069	int stat;
1070	int errno;
1071} nfs_errtbl[] = {
1072	{ NFS_OK,		0		},
1073	{ NFSERR_PERM,		-EPERM		},
1074	{ NFSERR_NOENT,		-ENOENT		},
1075	{ NFSERR_IO,		-errno_NFSERR_IO},
1076	{ NFSERR_NXIO,		-ENXIO		},
1077/*	{ NFSERR_EAGAIN,	-EAGAIN		}, */
1078	{ NFSERR_ACCES,		-EACCES		},
1079	{ NFSERR_EXIST,		-EEXIST		},
1080	{ NFSERR_XDEV,		-EXDEV		},
1081	{ NFSERR_NODEV,		-ENODEV		},
1082	{ NFSERR_NOTDIR,	-ENOTDIR	},
1083	{ NFSERR_ISDIR,		-EISDIR		},
1084	{ NFSERR_INVAL,		-EINVAL		},
1085	{ NFSERR_FBIG,		-EFBIG		},
1086	{ NFSERR_NOSPC,		-ENOSPC		},
1087	{ NFSERR_ROFS,		-EROFS		},
1088	{ NFSERR_MLINK,		-EMLINK		},
1089	{ NFSERR_NAMETOOLONG,	-ENAMETOOLONG	},
1090	{ NFSERR_NOTEMPTY,	-ENOTEMPTY	},
1091	{ NFSERR_DQUOT,		-EDQUOT		},
1092	{ NFSERR_STALE,		-ESTALE		},
1093	{ NFSERR_REMOTE,	-EREMOTE	},
1094#ifdef EWFLUSH
1095	{ NFSERR_WFLUSH,	-EWFLUSH	},
1096#endif
1097	{ NFSERR_BADHANDLE,	-EBADHANDLE	},
1098	{ NFSERR_NOT_SYNC,	-ENOTSYNC	},
1099	{ NFSERR_BAD_COOKIE,	-EBADCOOKIE	},
1100	{ NFSERR_NOTSUPP,	-ENOTSUPP	},
1101	{ NFSERR_TOOSMALL,	-ETOOSMALL	},
1102	{ NFSERR_SERVERFAULT,	-EREMOTEIO	},
1103	{ NFSERR_BADTYPE,	-EBADTYPE	},
1104	{ NFSERR_JUKEBOX,	-EJUKEBOX	},
1105	{ -1,			-EIO		}
1106};
1107
1108/**
1109 * nfs_stat_to_errno - convert an NFS status code to a local errno
1110 * @status: NFS status code to convert
1111 *
1112 * Returns a local errno value, or -EIO if the NFS status code is
1113 * not recognized.  This function is used jointly by NFSv2 and NFSv3.
1114 */
1115static int nfs_stat_to_errno(enum nfs_stat status)
1116{
1117	int i;
1118
1119	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1120		if (nfs_errtbl[i].stat == (int)status)
1121			return nfs_errtbl[i].errno;
1122	}
1123	dprintk("NFS: Unrecognized nfs status value: %u\n", status);
1124	return nfs_errtbl[i].errno;
1125}
1126
1127#define PROC(proc, argtype, restype, timer)				\
1128[NFSPROC_##proc] = {							\
1129	.p_proc	    =  NFSPROC_##proc,					\
1130	.p_encode   =  (kxdreproc_t)nfs2_xdr_enc_##argtype,		\
1131	.p_decode   =  (kxdrdproc_t)nfs2_xdr_dec_##restype,		\
1132	.p_arglen   =  NFS_##argtype##_sz,				\
1133	.p_replen   =  NFS_##restype##_sz,				\
1134	.p_timer    =  timer,						\
1135	.p_statidx  =  NFSPROC_##proc,					\
1136	.p_name     =  #proc,						\
1137	}
1138struct rpc_procinfo	nfs_procedures[] = {
1139	PROC(GETATTR,	fhandle,	attrstat,	1),
1140	PROC(SETATTR,	sattrargs,	attrstat,	0),
1141	PROC(LOOKUP,	diropargs,	diropres,	2),
1142	PROC(READLINK,	readlinkargs,	readlinkres,	3),
1143	PROC(READ,	readargs,	readres,	3),
1144	PROC(WRITE,	writeargs,	writeres,	4),
1145	PROC(CREATE,	createargs,	diropres,	0),
1146	PROC(REMOVE,	removeargs,	stat,		0),
1147	PROC(RENAME,	renameargs,	stat,		0),
1148	PROC(LINK,	linkargs,	stat,		0),
1149	PROC(SYMLINK,	symlinkargs,	stat,		0),
1150	PROC(MKDIR,	createargs,	diropres,	0),
1151	PROC(RMDIR,	diropargs,	stat,		0),
1152	PROC(READDIR,	readdirargs,	readdirres,	3),
1153	PROC(STATFS,	fhandle,	statfsres,	0),
1154};
1155
1156const struct rpc_version nfs_version2 = {
1157	.number			= 2,
1158	.nrprocs		= ARRAY_SIZE(nfs_procedures),
1159	.procs			= nfs_procedures
1160};