Linux Audio

Check our new training course

Loading...
v3.15
 
   1/*
   2 * XDR support for nfsd/protocol version 3.
   3 *
   4 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
   5 *
   6 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
   7 */
   8
   9#include <linux/namei.h>
  10#include <linux/sunrpc/svc_xprt.h>
  11#include "xdr3.h"
  12#include "auth.h"
  13#include "netns.h"
  14#include "vfs.h"
  15
  16#define NFSDDBG_FACILITY		NFSDDBG_XDR
 
 
 
 
 
  17
 
 
 
 
 
 
 
 
  18
  19/*
  20 * Mapping of S_IF* types to NFS file types
  21 */
  22static u32	nfs3_ftypes[] = {
  23	NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
  24	NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
  25	NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
  26	NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
  27};
  28
 
  29/*
  30 * XDR functions for basic NFS types
  31 */
 
  32static __be32 *
  33encode_time3(__be32 *p, struct timespec *time)
  34{
  35	*p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
 
 
  36	return p;
  37}
  38
  39static __be32 *
  40decode_time3(__be32 *p, struct timespec *time)
  41{
  42	time->tv_sec = ntohl(*p++);
  43	time->tv_nsec = ntohl(*p++);
  44	return p;
 
 
 
 
 
 
  45}
  46
  47static __be32 *
  48decode_fh(__be32 *p, struct svc_fh *fhp)
 
 
 
 
 
 
 
 
 
  49{
  50	unsigned int size;
  51	fh_init(fhp, NFS3_FHSIZE);
  52	size = ntohl(*p++);
  53	if (size > NFS3_FHSIZE)
  54		return NULL;
  55
  56	memcpy(&fhp->fh_handle.fh_base, p, size);
 
 
 
 
 
 
 
  57	fhp->fh_handle.fh_size = size;
  58	return p + XDR_QUADLEN(size);
 
 
  59}
  60
  61/* Helper function for NFSv3 ACL code */
  62__be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp)
 
 
 
 
 
 
 
 
 
  63{
  64	return decode_fh(p, fhp);
 
 
 
 
 
 
 
  65}
  66
  67static __be32 *
  68encode_fh(__be32 *p, struct svc_fh *fhp)
  69{
  70	unsigned int size = fhp->fh_handle.fh_size;
  71	*p++ = htonl(size);
  72	if (size) p[XDR_QUADLEN(size)-1]=0;
  73	memcpy(p, &fhp->fh_handle.fh_base, size);
  74	return p + XDR_QUADLEN(size);
 
 
 
 
 
 
 
  75}
  76
  77/*
  78 * Decode a file name and make sure that the path contains
  79 * no slashes or null bytes.
  80 */
  81static __be32 *
  82decode_filename(__be32 *p, char **namp, unsigned int *lenp)
 
 
 
 
 
 
 
  83{
  84	char		*name;
  85	unsigned int	i;
  86
  87	if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
  88		for (i = 0, name = *namp; i < *lenp; i++, name++) {
  89			if (*name == '\0' || *name == '/')
  90				return NULL;
  91		}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  92	}
  93
  94	return p;
  95}
  96
  97static __be32 *
  98decode_sattr3(__be32 *p, struct iattr *iap)
 
 
 
 
 
 
 
 
 
  99{
 100	u32	tmp;
 101
 102	iap->ia_valid = 0;
 103
 104	if (*p++) {
 
 
 
 
 
 
 105		iap->ia_valid |= ATTR_MODE;
 106		iap->ia_mode = ntohl(*p++);
 107	}
 108	if (*p++) {
 109		iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++));
 
 
 
 
 
 
 110		if (uid_valid(iap->ia_uid))
 111			iap->ia_valid |= ATTR_UID;
 112	}
 113	if (*p++) {
 114		iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++));
 
 
 
 
 
 
 115		if (gid_valid(iap->ia_gid))
 116			iap->ia_valid |= ATTR_GID;
 117	}
 118	if (*p++) {
 119		u64	newsize;
 
 
 120
 
 
 121		iap->ia_valid |= ATTR_SIZE;
 122		p = xdr_decode_hyper(p, &newsize);
 123		if (newsize <= NFS_OFFSET_MAX)
 124			iap->ia_size = newsize;
 125		else
 126			iap->ia_size = NFS_OFFSET_MAX;
 127	}
 128	if ((tmp = ntohl(*p++)) == 1) {	/* set to server time */
 
 
 
 
 
 129		iap->ia_valid |= ATTR_ATIME;
 130	} else if (tmp == 2) {		/* set to client time */
 
 
 
 131		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
 132		iap->ia_atime.tv_sec = ntohl(*p++);
 133		iap->ia_atime.tv_nsec = ntohl(*p++);
 
 134	}
 135	if ((tmp = ntohl(*p++)) == 1) {	/* set to server time */
 
 
 
 
 
 136		iap->ia_valid |= ATTR_MTIME;
 137	} else if (tmp == 2) {		/* set to client time */
 
 
 
 138		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
 139		iap->ia_mtime.tv_sec = ntohl(*p++);
 140		iap->ia_mtime.tv_nsec = ntohl(*p++);
 
 141	}
 142	return p;
 
 143}
 144
 145static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp)
 
 146{
 147	u64 f;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 148	switch(fsid_source(fhp)) {
 149	default:
 150	case FSIDSOURCE_DEV:
 151		p = xdr_encode_hyper(p, (u64)huge_encode_dev
 152				     (fhp->fh_dentry->d_inode->i_sb->s_dev));
 153		break;
 154	case FSIDSOURCE_FSID:
 155		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
 156		break;
 157	case FSIDSOURCE_UUID:
 158		f = ((u64*)fhp->fh_export->ex_uuid)[0];
 159		f ^= ((u64*)fhp->fh_export->ex_uuid)[1];
 160		p = xdr_encode_hyper(p, f);
 161		break;
 
 
 162	}
 163	return p;
 164}
 165
 166static __be32 *
 167encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
 168	      struct kstat *stat)
 169{
 170	*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
 171	*p++ = htonl((u32) (stat->mode & S_IALLUGO));
 172	*p++ = htonl((u32) stat->nlink);
 173	*p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
 174	*p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
 175	if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
 176		p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
 177	} else {
 178		p = xdr_encode_hyper(p, (u64) stat->size);
 179	}
 180	p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
 181	*p++ = htonl((u32) MAJOR(stat->rdev));
 182	*p++ = htonl((u32) MINOR(stat->rdev));
 183	p = encode_fsid(p, fhp);
 184	p = xdr_encode_hyper(p, stat->ino);
 185	p = encode_time3(p, &stat->atime);
 186	p = encode_time3(p, &stat->mtime);
 187	p = encode_time3(p, &stat->ctime);
 188
 189	return p;
 
 
 
 
 190}
 191
 192static __be32 *
 193encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 194{
 195	/* Attributes to follow */
 196	*p++ = xdr_one;
 197	return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr);
 
 
 
 
 
 
 
 198}
 199
 200/*
 201 * Encode post-operation attributes.
 202 * The inode may be NULL if the call failed because of a stale file
 203 * handle. In this case, no attributes are returned.
 204 */
 205static __be32 *
 206encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 207{
 208	struct dentry *dentry = fhp->fh_dentry;
 209	if (dentry && dentry->d_inode) {
 210	        __be32 err;
 211		struct kstat stat;
 212
 213		err = fh_getattr(fhp, &stat);
 214		if (!err) {
 215			*p++ = xdr_one;		/* attributes follow */
 216			lease_get_mtime(dentry->d_inode, &stat.mtime);
 217			return encode_fattr3(rqstp, p, fhp, &stat);
 218		}
 219	}
 220	*p++ = xdr_zero;
 221	return p;
 222}
 223
 224/* Helper for NFSv3 ACLs */
 225__be32 *
 226nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 227{
 228	return encode_post_op_attr(rqstp, p, fhp);
 229}
 230
 231/*
 232 * Enocde weak cache consistency data
 
 
 
 
 
 
 
 233 */
 234static __be32 *
 235encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 
 236{
 237	struct dentry	*dentry = fhp->fh_dentry;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 238
 239	if (dentry && dentry->d_inode && fhp->fh_post_saved) {
 240		if (fhp->fh_pre_saved) {
 241			*p++ = xdr_one;
 242			p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
 243			p = encode_time3(p, &fhp->fh_pre_mtime);
 244			p = encode_time3(p, &fhp->fh_pre_ctime);
 245		} else {
 246			*p++ = xdr_zero;
 247		}
 248		return encode_saved_post_attr(rqstp, p, fhp);
 249	}
 250	/* no pre- or post-attrs */
 251	*p++ = xdr_zero;
 252	return encode_post_op_attr(rqstp, p, fhp);
 253}
 254
 255/*
 256 * Fill in the post_op attr for the wcc data
 257 */
 258void fill_post_wcc(struct svc_fh *fhp)
 
 
 259{
 260	__be32 err;
 261
 262	if (fhp->fh_post_saved)
 263		printk("nfsd: inode locked twice during operation.\n");
 264
 265	err = fh_getattr(fhp, &fhp->fh_post_attr);
 266	fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
 267	if (err) {
 268		fhp->fh_post_saved = 0;
 269		/* Grab the ctime anyway - set_change_info might use it */
 270		fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
 271	} else
 272		fhp->fh_post_saved = 1;
 
 
 
 
 
 
 
 
 
 
 
 273}
 274
 275/*
 276 * XDR decode functions
 277 */
 278int
 279nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args)
 280{
 281	if (!(p = decode_fh(p, &args->fh)))
 282		return 0;
 283	return xdr_argsize_check(rqstp, p);
 284}
 285
 286int
 287nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
 288					struct nfsd3_sattrargs *args)
 289{
 290	if (!(p = decode_fh(p, &args->fh)))
 291		return 0;
 292	p = decode_sattr3(p, &args->attrs);
 293
 294	if ((args->check_guard = ntohl(*p++)) != 0) { 
 295		struct timespec time; 
 296		p = decode_time3(p, &time);
 297		args->guardtime = time.tv_sec;
 298	}
 299
 300	return xdr_argsize_check(rqstp, p);
 301}
 302
 303int
 304nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
 305					struct nfsd3_diropargs *args)
 306{
 307	if (!(p = decode_fh(p, &args->fh))
 308	 || !(p = decode_filename(p, &args->name, &args->len)))
 309		return 0;
 310
 311	return xdr_argsize_check(rqstp, p);
 
 
 312}
 313
 314int
 315nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
 316					struct nfsd3_accessargs *args)
 317{
 318	if (!(p = decode_fh(p, &args->fh)))
 319		return 0;
 320	args->access = ntohl(*p++);
 321
 322	return xdr_argsize_check(rqstp, p);
 323}
 324
 325int
 326nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
 327					struct nfsd3_readargs *args)
 328{
 329	unsigned int len;
 330	int v;
 331	u32 max_blocksize = svc_max_payload(rqstp);
 332
 333	if (!(p = decode_fh(p, &args->fh)))
 334		return 0;
 335	p = xdr_decode_hyper(p, &args->offset);
 
 336
 337	len = args->count = ntohl(*p++);
 
 338
 339	if (len > max_blocksize)
 340		len = max_blocksize;
 
 
 341
 342	/* set up the kvec */
 343	v=0;
 344	while (len > 0) {
 345		struct page *p = *(rqstp->rq_next_page++);
 
 
 346
 347		rqstp->rq_vec[v].iov_base = page_address(p);
 348		rqstp->rq_vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE;
 349		len -= rqstp->rq_vec[v].iov_len;
 350		v++;
 351	}
 352	args->vlen = v;
 353	return xdr_argsize_check(rqstp, p);
 354}
 355
 356int
 357nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
 358					struct nfsd3_writeargs *args)
 359{
 360	unsigned int len, v, hdr, dlen;
 361	u32 max_blocksize = svc_max_payload(rqstp);
 362
 363	if (!(p = decode_fh(p, &args->fh)))
 364		return 0;
 365	p = xdr_decode_hyper(p, &args->offset);
 366
 367	args->count = ntohl(*p++);
 368	args->stable = ntohl(*p++);
 369	len = args->len = ntohl(*p++);
 370	/*
 371	 * The count must equal the amount of data passed.
 372	 */
 373	if (args->count != args->len)
 374		return 0;
 375
 376	/*
 377	 * Check to make sure that we got the right number of
 378	 * bytes.
 379	 */
 380	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
 381	dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
 382		- hdr;
 383	/*
 384	 * Round the length of the data which was specified up to
 385	 * the next multiple of XDR units and then compare that
 386	 * against the length which was actually received.
 387	 * Note that when RPCSEC/GSS (for example) is used, the
 388	 * data buffer can be padded so dlen might be larger
 389	 * than required.  It must never be smaller.
 390	 */
 391	if (dlen < XDR_QUADLEN(len)*4)
 392		return 0;
 393
 
 
 
 394	if (args->count > max_blocksize) {
 395		args->count = max_blocksize;
 396		len = args->len = max_blocksize;
 397	}
 398	rqstp->rq_vec[0].iov_base = (void*)p;
 399	rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
 400	v = 0;
 401	while (len > rqstp->rq_vec[v].iov_len) {
 402		len -= rqstp->rq_vec[v].iov_len;
 403		v++;
 404		rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_pages[v]);
 405		rqstp->rq_vec[v].iov_len = PAGE_SIZE;
 406	}
 407	rqstp->rq_vec[v].iov_len = len;
 408	args->vlen = v + 1;
 409	return 1;
 410}
 411
 412int
 413nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
 414					struct nfsd3_createargs *args)
 415{
 416	if (!(p = decode_fh(p, &args->fh))
 417	 || !(p = decode_filename(p, &args->name, &args->len)))
 418		return 0;
 419
 420	switch (args->createmode = ntohl(*p++)) {
 
 
 
 
 
 
 
 
 
 
 
 
 421	case NFS3_CREATE_UNCHECKED:
 422	case NFS3_CREATE_GUARDED:
 423		p = decode_sattr3(p, &args->attrs);
 424		break;
 425	case NFS3_CREATE_EXCLUSIVE:
 426		args->verf = p;
 427		p += 2;
 
 428		break;
 429	default:
 430		return 0;
 431	}
 432
 433	return xdr_argsize_check(rqstp, p);
 434}
 435int
 436nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p,
 437					struct nfsd3_createargs *args)
 438{
 439	if (!(p = decode_fh(p, &args->fh)) ||
 440	    !(p = decode_filename(p, &args->name, &args->len)))
 441		return 0;
 442	p = decode_sattr3(p, &args->attrs);
 443
 444	return xdr_argsize_check(rqstp, p);
 
 
 445}
 446
 447int
 448nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
 449					struct nfsd3_symlinkargs *args)
 450{
 451	unsigned int len, avail;
 452	char *old, *new;
 453	struct kvec *vec;
 454
 455	if (!(p = decode_fh(p, &args->ffh)) ||
 456	    !(p = decode_filename(p, &args->fname, &args->flen))
 457		)
 458		return 0;
 459	p = decode_sattr3(p, &args->attrs);
 460
 461	/* now decode the pathname, which might be larger than the first page.
 462	 * As we have to check for nul's anyway, we copy it into a new page
 463	 * This page appears in the rq_res.pages list, but as pages_len is always
 464	 * 0, it won't get in the way
 465	 */
 466	len = ntohl(*p++);
 467	if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE)
 468		return 0;
 469	args->tname = new = page_address(*(rqstp->rq_next_page++));
 470	args->tlen = len;
 471	/* first copy and check from the first page */
 472	old = (char*)p;
 473	vec = &rqstp->rq_arg.head[0];
 474	avail = vec->iov_len - (old - (char*)vec->iov_base);
 475	while (len && avail && *old) {
 476		*new++ = *old++;
 477		len--;
 478		avail--;
 479	}
 480	/* now copy next page if there is one */
 481	if (len && !avail && rqstp->rq_arg.page_len) {
 482		avail = rqstp->rq_arg.page_len;
 483		if (avail > PAGE_SIZE)
 484			avail = PAGE_SIZE;
 485		old = page_address(rqstp->rq_arg.pages[0]);
 486	}
 487	while (len && avail && *old) {
 488		*new++ = *old++;
 489		len--;
 490		avail--;
 491	}
 492	*new = '\0';
 493	if (len)
 494		return 0;
 495
 496	return 1;
 
 
 
 497}
 498
 499int
 500nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p,
 501					struct nfsd3_mknodargs *args)
 502{
 503	if (!(p = decode_fh(p, &args->fh))
 504	 || !(p = decode_filename(p, &args->name, &args->len)))
 505		return 0;
 506
 507	args->ftype = ntohl(*p++);
 508
 509	if (args->ftype == NF3BLK  || args->ftype == NF3CHR
 510	 || args->ftype == NF3SOCK || args->ftype == NF3FIFO)
 511		p = decode_sattr3(p, &args->attrs);
 512
 513	if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
 514		args->major = ntohl(*p++);
 515		args->minor = ntohl(*p++);
 
 
 
 
 
 
 
 
 
 
 
 516	}
 517
 518	return xdr_argsize_check(rqstp, p);
 519}
 520
 521int
 522nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p,
 523					struct nfsd3_renameargs *args)
 524{
 525	if (!(p = decode_fh(p, &args->ffh))
 526	 || !(p = decode_filename(p, &args->fname, &args->flen))
 527	 || !(p = decode_fh(p, &args->tfh))
 528	 || !(p = decode_filename(p, &args->tname, &args->tlen)))
 529		return 0;
 530
 531	return xdr_argsize_check(rqstp, p);
 532}
 533
 534int
 535nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
 536					struct nfsd3_readlinkargs *args)
 537{
 538	if (!(p = decode_fh(p, &args->fh)))
 539		return 0;
 540	args->buffer = page_address(*(rqstp->rq_next_page++));
 541
 542	return xdr_argsize_check(rqstp, p);
 
 
 
 543}
 544
 545int
 546nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p,
 547					struct nfsd3_linkargs *args)
 548{
 549	if (!(p = decode_fh(p, &args->ffh))
 550	 || !(p = decode_fh(p, &args->tfh))
 551	 || !(p = decode_filename(p, &args->tname, &args->tlen)))
 552		return 0;
 553
 554	return xdr_argsize_check(rqstp, p);
 
 
 555}
 556
 557int
 558nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
 559					struct nfsd3_readdirargs *args)
 560{
 561	if (!(p = decode_fh(p, &args->fh)))
 562		return 0;
 563	p = xdr_decode_hyper(p, &args->cookie);
 564	args->verf   = p; p += 2;
 565	args->dircount = ~0;
 566	args->count  = ntohl(*p++);
 567
 568	if (args->count > PAGE_SIZE)
 569		args->count = PAGE_SIZE;
 
 
 
 
 
 
 
 570
 571	args->buffer = page_address(*(rqstp->rq_next_page++));
 572
 573	return xdr_argsize_check(rqstp, p);
 574}
 575
 576int
 577nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
 578					struct nfsd3_readdirargs *args)
 579{
 580	int len;
 581	u32 max_blocksize = svc_max_payload(rqstp);
 582
 583	if (!(p = decode_fh(p, &args->fh)))
 584		return 0;
 585	p = xdr_decode_hyper(p, &args->cookie);
 586	args->verf     = p; p += 2;
 587	args->dircount = ntohl(*p++);
 588	args->count    = ntohl(*p++);
 
 
 
 
 
 
 589
 590	len = (args->count > max_blocksize) ? max_blocksize :
 591						  args->count;
 592	args->count = len;
 593
 594	while (len > 0) {
 595		struct page *p = *(rqstp->rq_next_page++);
 596		if (!args->buffer)
 597			args->buffer = page_address(p);
 598		len -= PAGE_SIZE;
 599	}
 600
 601	return xdr_argsize_check(rqstp, p);
 602}
 603
 604int
 605nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p,
 606					struct nfsd3_commitargs *args)
 607{
 608	if (!(p = decode_fh(p, &args->fh)))
 609		return 0;
 610	p = xdr_decode_hyper(p, &args->offset);
 611	args->count = ntohl(*p++);
 
 
 
 
 612
 613	return xdr_argsize_check(rqstp, p);
 614}
 615
 616/*
 617 * XDR encode functions
 618 */
 619/*
 620 * There must be an encoding function for void results so svc_process
 621 * will work properly.
 622 */
 623int
 624nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 625{
 626	return xdr_ressize_check(rqstp, p);
 627}
 628
 629/* GETATTR */
 630int
 631nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
 632					struct nfsd3_attrstat *resp)
 633{
 634	if (resp->status == 0) {
 635		lease_get_mtime(resp->fh.fh_dentry->d_inode,
 636				&resp->stat.mtime);
 637		p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
 
 
 
 
 
 638	}
 639	return xdr_ressize_check(rqstp, p);
 
 640}
 641
 642/* SETATTR, REMOVE, RMDIR */
 643int
 644nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p,
 645					struct nfsd3_attrstat *resp)
 646{
 647	p = encode_wcc_data(rqstp, p, &resp->fh);
 648	return xdr_ressize_check(rqstp, p);
 
 
 649}
 650
 651/* LOOKUP */
 652int
 653nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p,
 654					struct nfsd3_diropres *resp)
 655{
 656	if (resp->status == 0) {
 657		p = encode_fh(p, &resp->fh);
 658		p = encode_post_op_attr(rqstp, p, &resp->fh);
 
 
 
 
 
 
 
 
 
 
 
 
 659	}
 660	p = encode_post_op_attr(rqstp, p, &resp->dirfh);
 661	return xdr_ressize_check(rqstp, p);
 662}
 663
 664/* ACCESS */
 665int
 666nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,
 667					struct nfsd3_accessres *resp)
 668{
 669	p = encode_post_op_attr(rqstp, p, &resp->fh);
 670	if (resp->status == 0)
 671		*p++ = htonl(resp->access);
 672	return xdr_ressize_check(rqstp, p);
 
 
 
 
 
 
 
 
 
 
 
 
 673}
 674
 675/* READLINK */
 676int
 677nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p,
 678					struct nfsd3_readlinkres *resp)
 679{
 680	p = encode_post_op_attr(rqstp, p, &resp->fh);
 681	if (resp->status == 0) {
 682		*p++ = htonl(resp->len);
 683		xdr_ressize_check(rqstp, p);
 684		rqstp->rq_res.page_len = resp->len;
 685		if (resp->len & 3) {
 686			/* need to pad the tail */
 687			rqstp->rq_res.tail[0].iov_base = p;
 688			*p = 0;
 689			rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
 690		}
 691		return 1;
 692	} else
 693		return xdr_ressize_check(rqstp, p);
 
 
 
 
 
 
 
 694}
 695
 696/* READ */
 697int
 698nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
 699					struct nfsd3_readres *resp)
 700{
 701	p = encode_post_op_attr(rqstp, p, &resp->fh);
 702	if (resp->status == 0) {
 703		*p++ = htonl(resp->count);
 704		*p++ = htonl(resp->eof);
 705		*p++ = htonl(resp->count);	/* xdr opaque count */
 706		xdr_ressize_check(rqstp, p);
 707		/* now update rqstp->rq_res to reflect data as well */
 708		rqstp->rq_res.page_len = resp->count;
 709		if (resp->count & 3) {
 710			/* need to pad the tail */
 711			rqstp->rq_res.tail[0].iov_base = p;
 712			*p = 0;
 713			rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3);
 714		}
 715		return 1;
 716	} else
 717		return xdr_ressize_check(rqstp, p);
 
 
 
 
 
 
 
 
 
 718}
 719
 720/* WRITE */
 721int
 722nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p,
 723					struct nfsd3_writeres *resp)
 724{
 725	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 726
 727	p = encode_wcc_data(rqstp, p, &resp->fh);
 728	if (resp->status == 0) {
 729		*p++ = htonl(resp->count);
 730		*p++ = htonl(resp->committed);
 731		*p++ = htonl(nn->nfssvc_boot.tv_sec);
 732		*p++ = htonl(nn->nfssvc_boot.tv_usec);
 
 
 
 
 
 
 
 
 
 733	}
 734	return xdr_ressize_check(rqstp, p);
 
 735}
 736
 737/* CREATE, MKDIR, SYMLINK, MKNOD */
 738int
 739nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p,
 740					struct nfsd3_diropres *resp)
 741{
 742	if (resp->status == 0) {
 743		*p++ = xdr_one;
 744		p = encode_fh(p, &resp->fh);
 745		p = encode_post_op_attr(rqstp, p, &resp->fh);
 
 
 
 
 
 
 
 
 
 
 
 746	}
 747	p = encode_wcc_data(rqstp, p, &resp->dirfh);
 748	return xdr_ressize_check(rqstp, p);
 749}
 750
 751/* RENAME */
 752int
 753nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p,
 754					struct nfsd3_renameres *resp)
 755{
 756	p = encode_wcc_data(rqstp, p, &resp->ffh);
 757	p = encode_wcc_data(rqstp, p, &resp->tfh);
 758	return xdr_ressize_check(rqstp, p);
 
 759}
 760
 761/* LINK */
 762int
 763nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p,
 764					struct nfsd3_linkres *resp)
 765{
 766	p = encode_post_op_attr(rqstp, p, &resp->fh);
 767	p = encode_wcc_data(rqstp, p, &resp->tfh);
 768	return xdr_ressize_check(rqstp, p);
 769}
 770
 771/* READDIR */
 772int
 773nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
 774					struct nfsd3_readdirres *resp)
 775{
 776	p = encode_post_op_attr(rqstp, p, &resp->fh);
 777
 778	if (resp->status == 0) {
 779		/* stupid readdir cookie */
 780		memcpy(p, resp->verf, 8); p += 2;
 781		xdr_ressize_check(rqstp, p);
 782		if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE)
 783			return 1; /*No room for trailer */
 784		rqstp->rq_res.page_len = (resp->count) << 2;
 785
 786		/* add the 'tail' to the end of the 'head' page - page 0. */
 787		rqstp->rq_res.tail[0].iov_base = p;
 788		*p++ = 0;		/* no more entries */
 789		*p++ = htonl(resp->common.err == nfserr_eof);
 790		rqstp->rq_res.tail[0].iov_len = 2<<2;
 791		return 1;
 792	} else
 793		return xdr_ressize_check(rqstp, p);
 794}
 795
 796static __be32 *
 797encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
 798	     int namlen, u64 ino)
 799{
 800	*p++ = xdr_one;				 /* mark entry present */
 801	p    = xdr_encode_hyper(p, ino);	 /* file id */
 802	p    = xdr_encode_array(p, name, namlen);/* name length & name */
 803
 804	cd->offset = p;				/* remember pointer */
 805	p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 806
 807	return p;
 808}
 809
 810static __be32
 811compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
 812		const char *name, int namlen)
 813{
 814	struct svc_export	*exp;
 815	struct dentry		*dparent, *dchild;
 816	__be32 rv = nfserr_noent;
 817
 818	dparent = cd->fh.fh_dentry;
 819	exp  = cd->fh.fh_export;
 820
 821	if (isdotent(name, namlen)) {
 822		if (namlen == 2) {
 823			dchild = dget_parent(dparent);
 824			/* filesystem root - cannot return filehandle for ".." */
 
 
 
 825			if (dchild == dparent)
 826				goto out;
 
 
 827		} else
 828			dchild = dget(dparent);
 829	} else
 830		dchild = lookup_one_len(name, dparent, namlen);
 831	if (IS_ERR(dchild))
 832		return rv;
 833	if (d_mountpoint(dchild))
 834		goto out;
 835	if (!dchild->d_inode)
 836		goto out;
 837	rv = fh_compose(fhp, exp, dchild, &cd->fh);
 838out:
 839	dput(dchild);
 840	return rv;
 841}
 842
 843static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
 
 
 
 
 
 
 
 
 844{
 845	struct svc_fh	*fh = &cd->scratch;
 846	__be32 err;
 847
 848	fh_init(fh, NFS3_FHSIZE);
 849	err = compose_entry_fh(cd, fh, name, namlen);
 850	if (err) {
 851		*p++ = 0;
 852		*p++ = 0;
 853		goto out;
 854	}
 855	p = encode_post_op_attr(cd->rqstp, p, fh);
 856	*p++ = xdr_one;			/* yes, a file handle follows */
 857	p = encode_fh(p, fh);
 858out:
 859	fh_put(fh);
 860	return p;
 861}
 862
 863/*
 864 * Encode a directory entry. This one works for both normal readdir
 865 * and readdirplus.
 866 * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
 867 * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
 868 * 
 869 * The readdirplus baggage is 1+21 words for post_op_attr, plus the
 870 * file handle.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 871 */
 
 
 
 
 
 
 
 
 872
 873#define NFS3_ENTRY_BAGGAGE	(2 + 1 + 2 + 1)
 874#define NFS3_ENTRYPLUS_BAGGAGE	(1 + 21 + 1 + (NFS3_FHSIZE >> 2))
 875static int
 876encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
 877	     loff_t offset, u64 ino, unsigned int d_type, int plus)
 878{
 879	struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
 880		       					common);
 881	__be32		*p = cd->buffer;
 882	caddr_t		curr_page_addr = NULL;
 883	struct page **	page;
 884	int		slen;		/* string (name) length */
 885	int		elen;		/* estimated entry length in words */
 886	int		num_entry_words = 0;	/* actual number of words */
 887
 888	if (cd->offset) {
 889		u64 offset64 = offset;
 890
 891		if (unlikely(cd->offset1)) {
 892			/* we ended up with offset on a page boundary */
 893			*cd->offset = htonl(offset64 >> 32);
 894			*cd->offset1 = htonl(offset64 & 0xffffffff);
 895			cd->offset1 = NULL;
 896		} else {
 897			xdr_encode_hyper(cd->offset, offset64);
 898		}
 899	}
 900
 901	/*
 902	dprintk("encode_entry(%.*s @%ld%s)\n",
 903		namlen, name, (long) offset, plus? " plus" : "");
 904	 */
 905
 906	/* truncate filename if too long */
 907	if (namlen > NFS3_MAXNAMLEN)
 908		namlen = NFS3_MAXNAMLEN;
 909
 910	slen = XDR_QUADLEN(namlen);
 911	elen = slen + NFS3_ENTRY_BAGGAGE
 912		+ (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
 913
 914	if (cd->buflen < elen) {
 915		cd->common.err = nfserr_toosmall;
 916		return -EINVAL;
 917	}
 918
 919	/* determine which page in rq_respages[] we are currently filling */
 920	for (page = cd->rqstp->rq_respages + 1;
 921				page < cd->rqstp->rq_next_page; page++) {
 922		curr_page_addr = page_address(*page);
 
 
 
 
 
 
 
 
 
 
 923
 924		if (((caddr_t)cd->buffer >= curr_page_addr) &&
 925		    ((caddr_t)cd->buffer <  curr_page_addr + PAGE_SIZE))
 926			break;
 927	}
 928
 929	if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) {
 930		/* encode entry in current page */
 
 
 
 931
 932		p = encode_entry_baggage(cd, p, name, namlen, ino);
 
 
 933
 934		if (plus)
 935			p = encode_entryplus_baggage(cd, p, name, namlen);
 936		num_entry_words = p - cd->buffer;
 937	} else if (*(page+1) != NULL) {
 938		/* temporarily encode entry into next page, then move back to
 939		 * current and next page in rq_respages[] */
 940		__be32 *p1, *tmp;
 941		int len1, len2;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 942
 943		/* grab next page for temporary storage of entry */
 944		p1 = tmp = page_address(*(page+1));
 
 945
 946		p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 947
 948		if (plus)
 949			p1 = encode_entryplus_baggage(cd, p1, name, namlen);
 950
 951		/* determine entry word length and lengths to go in pages */
 952		num_entry_words = p1 - tmp;
 953		len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer;
 954		if ((num_entry_words << 2) < len1) {
 955			/* the actual number of words in the entry is less
 956			 * than elen and can still fit in the current page
 957			 */
 958			memmove(p, tmp, num_entry_words << 2);
 959			p += num_entry_words;
 960
 961			/* update offset */
 962			cd->offset = cd->buffer + (cd->offset - tmp);
 963		} else {
 964			unsigned int offset_r = (cd->offset - tmp) << 2;
 965
 966			/* update pointer to offset location.
 967			 * This is a 64bit quantity, so we need to
 968			 * deal with 3 cases:
 969			 *  -	entirely in first page
 970			 *  -	entirely in second page
 971			 *  -	4 bytes in each page
 972			 */
 973			if (offset_r + 8 <= len1) {
 974				cd->offset = p + (cd->offset - tmp);
 975			} else if (offset_r >= len1) {
 976				cd->offset -= len1 >> 2;
 977			} else {
 978				/* sitting on the fence */
 979				BUG_ON(offset_r != len1 - 4);
 980				cd->offset = p + (cd->offset - tmp);
 981				cd->offset1 = tmp;
 982			}
 983
 984			len2 = (num_entry_words << 2) - len1;
 985
 986			/* move from temp page to current and next pages */
 987			memmove(p, tmp, len1);
 988			memmove(tmp, (caddr_t)tmp+len1, len2);
 989
 990			p = tmp + (len2 >> 2);
 991		}
 992	}
 993	else {
 994		cd->common.err = nfserr_toosmall;
 995		return -EINVAL;
 996	}
 997
 998	cd->buflen -= num_entry_words;
 999	cd->buffer = p;
1000	cd->common.err = nfs_ok;
1001	return 0;
1002
 
1003}
1004
1005int
1006nfs3svc_encode_entry(void *cd, const char *name,
1007		     int namlen, loff_t offset, u64 ino, unsigned int d_type)
1008{
1009	return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1010}
1011
1012int
1013nfs3svc_encode_entry_plus(void *cd, const char *name,
1014			  int namlen, loff_t offset, u64 ino,
1015			  unsigned int d_type)
1016{
1017	return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
1018}
1019
1020/* FSSTAT */
1021int
1022nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p,
1023					struct nfsd3_fsstatres *resp)
1024{
1025	struct kstatfs	*s = &resp->stats;
1026	u64		bs = s->f_bsize;
1027
1028	*p++ = xdr_zero;	/* no post_op_attr */
1029
1030	if (resp->status == 0) {
1031		p = xdr_encode_hyper(p, bs * s->f_blocks);	/* total bytes */
1032		p = xdr_encode_hyper(p, bs * s->f_bfree);	/* free bytes */
1033		p = xdr_encode_hyper(p, bs * s->f_bavail);	/* user available bytes */
1034		p = xdr_encode_hyper(p, s->f_files);	/* total inodes */
1035		p = xdr_encode_hyper(p, s->f_ffree);	/* free inodes */
1036		p = xdr_encode_hyper(p, s->f_ffree);	/* user available inodes */
1037		*p++ = htonl(resp->invarsec);	/* mean unchanged time */
1038	}
1039	return xdr_ressize_check(rqstp, p);
 
1040}
1041
1042/* FSINFO */
1043int
1044nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p,
1045					struct nfsd3_fsinfores *resp)
1046{
1047	*p++ = xdr_zero;	/* no post_op_attr */
1048
1049	if (resp->status == 0) {
1050		*p++ = htonl(resp->f_rtmax);
1051		*p++ = htonl(resp->f_rtpref);
1052		*p++ = htonl(resp->f_rtmult);
1053		*p++ = htonl(resp->f_wtmax);
1054		*p++ = htonl(resp->f_wtpref);
1055		*p++ = htonl(resp->f_wtmult);
1056		*p++ = htonl(resp->f_dtpref);
1057		p = xdr_encode_hyper(p, resp->f_maxfilesize);
1058		*p++ = xdr_one;
1059		*p++ = xdr_zero;
1060		*p++ = htonl(resp->f_properties);
1061	}
1062
1063	return xdr_ressize_check(rqstp, p);
 
 
 
 
 
 
 
 
 
 
1064}
1065
1066/* PATHCONF */
1067int
1068nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p,
1069					struct nfsd3_pathconfres *resp)
1070{
1071	*p++ = xdr_zero;	/* no post_op_attr */
1072
1073	if (resp->status == 0) {
1074		*p++ = htonl(resp->p_link_max);
1075		*p++ = htonl(resp->p_name_max);
1076		*p++ = htonl(resp->p_no_trunc);
1077		*p++ = htonl(resp->p_chown_restricted);
1078		*p++ = htonl(resp->p_case_insensitive);
1079		*p++ = htonl(resp->p_case_preserving);
 
 
 
 
1080	}
1081
1082	return xdr_ressize_check(rqstp, p);
1083}
1084
1085/* COMMIT */
1086int
1087nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p,
1088					struct nfsd3_commitres *resp)
1089{
1090	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1091
1092	p = encode_wcc_data(rqstp, p, &resp->fh);
1093	/* Write verifier */
1094	if (resp->status == 0) {
1095		*p++ = htonl(nn->nfssvc_boot.tv_sec);
1096		*p++ = htonl(nn->nfssvc_boot.tv_usec);
 
 
 
 
 
 
1097	}
1098	return xdr_ressize_check(rqstp, p);
 
1099}
1100
1101/*
1102 * XDR release functions
1103 */
1104int
1105nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
1106					struct nfsd3_attrstat *resp)
1107{
 
 
1108	fh_put(&resp->fh);
1109	return 1;
1110}
1111
1112int
1113nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p,
1114					struct nfsd3_fhandle_pair *resp)
1115{
 
 
1116	fh_put(&resp->fh1);
1117	fh_put(&resp->fh2);
1118	return 1;
1119}
v6.8
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * XDR support for nfsd/protocol version 3.
   4 *
   5 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
   6 *
   7 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
   8 */
   9
  10#include <linux/namei.h>
  11#include <linux/sunrpc/svc_xprt.h>
  12#include "xdr3.h"
  13#include "auth.h"
  14#include "netns.h"
  15#include "vfs.h"
  16
  17/*
  18 * Force construction of an empty post-op attr
  19 */
  20static const struct svc_fh nfs3svc_null_fh = {
  21	.fh_no_wcc	= true,
  22};
  23
  24/*
  25 * time_delta. {1, 0} means the server is accurate only
  26 * to the nearest second.
  27 */
  28static const struct timespec64 nfs3svc_time_delta = {
  29	.tv_sec		= 1,
  30	.tv_nsec	= 0,
  31};
  32
  33/*
  34 * Mapping of S_IF* types to NFS file types
  35 */
  36static const u32 nfs3_ftypes[] = {
  37	NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
  38	NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
  39	NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
  40	NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
  41};
  42
  43
  44/*
  45 * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6)
  46 */
  47
  48static __be32 *
  49encode_nfstime3(__be32 *p, const struct timespec64 *time)
  50{
  51	*p++ = cpu_to_be32((u32)time->tv_sec);
  52	*p++ = cpu_to_be32(time->tv_nsec);
  53
  54	return p;
  55}
  56
  57static bool
  58svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep)
  59{
  60	__be32 *p;
  61
  62	p = xdr_inline_decode(xdr, XDR_UNIT * 2);
  63	if (!p)
  64		return false;
  65	timep->tv_sec = be32_to_cpup(p++);
  66	timep->tv_nsec = be32_to_cpup(p);
  67
  68	return true;
  69}
  70
  71/**
  72 * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle
  73 * @xdr: XDR stream positioned at an undecoded NFSv3 FH
  74 * @fhp: OUT: filled-in server file handle
  75 *
  76 * Return values:
  77 *  %false: The encoded file handle was not valid
  78 *  %true: @fhp has been initialized
  79 */
  80bool
  81svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
  82{
  83	__be32 *p;
  84	u32 size;
 
 
 
  85
  86	if (xdr_stream_decode_u32(xdr, &size) < 0)
  87		return false;
  88	if (size == 0 || size > NFS3_FHSIZE)
  89		return false;
  90	p = xdr_inline_decode(xdr, size);
  91	if (!p)
  92		return false;
  93	fh_init(fhp, NFS3_FHSIZE);
  94	fhp->fh_handle.fh_size = size;
  95	memcpy(&fhp->fh_handle.fh_raw, p, size);
  96
  97	return true;
  98}
  99
 100/**
 101 * svcxdr_encode_nfsstat3 - Encode an NFSv3 status code
 102 * @xdr: XDR stream
 103 * @status: status value to encode
 104 *
 105 * Return values:
 106 *   %false: Send buffer space was exhausted
 107 *   %true: Success
 108 */
 109bool
 110svcxdr_encode_nfsstat3(struct xdr_stream *xdr, __be32 status)
 111{
 112	__be32 *p;
 113
 114	p = xdr_reserve_space(xdr, sizeof(status));
 115	if (!p)
 116		return false;
 117	*p = status;
 118
 119	return true;
 120}
 121
 122static bool
 123svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
 124{
 125	u32 size = fhp->fh_handle.fh_size;
 126	__be32 *p;
 127
 128	p = xdr_reserve_space(xdr, XDR_UNIT + size);
 129	if (!p)
 130		return false;
 131	*p++ = cpu_to_be32(size);
 132	if (size)
 133		p[XDR_QUADLEN(size) - 1] = 0;
 134	memcpy(p, &fhp->fh_handle.fh_raw, size);
 135
 136	return true;
 137}
 138
 139static bool
 140svcxdr_encode_post_op_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
 141{
 142	if (xdr_stream_encode_item_present(xdr) < 0)
 143		return false;
 144	if (!svcxdr_encode_nfs_fh3(xdr, fhp))
 145		return false;
 146
 147	return true;
 148}
 149
 150static bool
 151svcxdr_encode_cookieverf3(struct xdr_stream *xdr, const __be32 *verf)
 152{
 153	__be32 *p;
 
 154
 155	p = xdr_reserve_space(xdr, NFS3_COOKIEVERFSIZE);
 156	if (!p)
 157		return false;
 158	memcpy(p, verf, NFS3_COOKIEVERFSIZE);
 159
 160	return true;
 161}
 162
 163static bool
 164svcxdr_encode_writeverf3(struct xdr_stream *xdr, const __be32 *verf)
 165{
 166	__be32 *p;
 167
 168	p = xdr_reserve_space(xdr, NFS3_WRITEVERFSIZE);
 169	if (!p)
 170		return false;
 171	memcpy(p, verf, NFS3_WRITEVERFSIZE);
 172
 173	return true;
 174}
 175
 176static bool
 177svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len)
 178{
 179	u32 size, i;
 180	__be32 *p;
 181	char *c;
 182
 183	if (xdr_stream_decode_u32(xdr, &size) < 0)
 184		return false;
 185	if (size == 0 || size > NFS3_MAXNAMLEN)
 186		return false;
 187	p = xdr_inline_decode(xdr, size);
 188	if (!p)
 189		return false;
 190
 191	*len = size;
 192	*name = (char *)p;
 193	for (i = 0, c = *name; i < size; i++, c++) {
 194		if (*c == '\0' || *c == '/')
 195			return false;
 196	}
 197
 198	return true;
 199}
 200
 201static bool
 202svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp,
 203			 char **name, unsigned int *len)
 204{
 205	return svcxdr_decode_nfs_fh3(xdr, fhp) &&
 206		svcxdr_decode_filename3(xdr, name, len);
 207}
 208
 209static bool
 210svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 211		     struct iattr *iap)
 212{
 213	u32 set_it;
 214
 215	iap->ia_valid = 0;
 216
 217	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 218		return false;
 219	if (set_it) {
 220		u32 mode;
 221
 222		if (xdr_stream_decode_u32(xdr, &mode) < 0)
 223			return false;
 224		iap->ia_valid |= ATTR_MODE;
 225		iap->ia_mode = mode;
 226	}
 227	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 228		return false;
 229	if (set_it) {
 230		u32 uid;
 231
 232		if (xdr_stream_decode_u32(xdr, &uid) < 0)
 233			return false;
 234		iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid);
 235		if (uid_valid(iap->ia_uid))
 236			iap->ia_valid |= ATTR_UID;
 237	}
 238	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 239		return false;
 240	if (set_it) {
 241		u32 gid;
 242
 243		if (xdr_stream_decode_u32(xdr, &gid) < 0)
 244			return false;
 245		iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid);
 246		if (gid_valid(iap->ia_gid))
 247			iap->ia_valid |= ATTR_GID;
 248	}
 249	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
 250		return false;
 251	if (set_it) {
 252		u64 newsize;
 253
 254		if (xdr_stream_decode_u64(xdr, &newsize) < 0)
 255			return false;
 256		iap->ia_valid |= ATTR_SIZE;
 257		iap->ia_size = newsize;
 
 
 
 
 258	}
 259	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
 260		return false;
 261	switch (set_it) {
 262	case DONT_CHANGE:
 263		break;
 264	case SET_TO_SERVER_TIME:
 265		iap->ia_valid |= ATTR_ATIME;
 266		break;
 267	case SET_TO_CLIENT_TIME:
 268		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime))
 269			return false;
 270		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
 271		break;
 272	default:
 273		return false;
 274	}
 275	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
 276		return false;
 277	switch (set_it) {
 278	case DONT_CHANGE:
 279		break;
 280	case SET_TO_SERVER_TIME:
 281		iap->ia_valid |= ATTR_MTIME;
 282		break;
 283	case SET_TO_CLIENT_TIME:
 284		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime))
 285			return false;
 286		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
 287		break;
 288	default:
 289		return false;
 290	}
 291
 292	return true;
 293}
 294
 295static bool
 296svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args)
 297{
 298	__be32 *p;
 299	u32 check;
 300
 301	if (xdr_stream_decode_bool(xdr, &check) < 0)
 302		return false;
 303	if (check) {
 304		p = xdr_inline_decode(xdr, XDR_UNIT * 2);
 305		if (!p)
 306			return false;
 307		args->check_guard = 1;
 308		args->guardtime = be32_to_cpup(p);
 309	} else
 310		args->check_guard = 0;
 311
 312	return true;
 313}
 314
 315static bool
 316svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args)
 317{
 318	__be32 *p;
 319
 320	p = xdr_inline_decode(xdr, XDR_UNIT * 2);
 321	if (!p)
 322		return false;
 323	args->major = be32_to_cpup(p++);
 324	args->minor = be32_to_cpup(p);
 325
 326	return true;
 327}
 328
 329static bool
 330svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 331			  struct nfsd3_mknodargs *args)
 332{
 333	return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
 334		svcxdr_decode_specdata3(xdr, args);
 335}
 336
 337static bool
 338svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 339		     const struct svc_fh *fhp, const struct kstat *stat)
 340{
 341	struct user_namespace *userns = nfsd_user_namespace(rqstp);
 342	__be32 *p;
 343	u64 fsid;
 344
 345	p = xdr_reserve_space(xdr, XDR_UNIT * 21);
 346	if (!p)
 347		return false;
 348
 349	*p++ = cpu_to_be32(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
 350	*p++ = cpu_to_be32((u32)(stat->mode & S_IALLUGO));
 351	*p++ = cpu_to_be32((u32)stat->nlink);
 352	*p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid));
 353	*p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid));
 354	if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN)
 355		p = xdr_encode_hyper(p, (u64)NFS3_MAXPATHLEN);
 356	else
 357		p = xdr_encode_hyper(p, (u64)stat->size);
 358
 359	/* used */
 360	p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
 361
 362	/* rdev */
 363	*p++ = cpu_to_be32((u32)MAJOR(stat->rdev));
 364	*p++ = cpu_to_be32((u32)MINOR(stat->rdev));
 365
 366	switch(fsid_source(fhp)) {
 
 
 
 
 
 367	case FSIDSOURCE_FSID:
 368		fsid = (u64)fhp->fh_export->ex_fsid;
 369		break;
 370	case FSIDSOURCE_UUID:
 371		fsid = ((u64 *)fhp->fh_export->ex_uuid)[0];
 372		fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1];
 
 373		break;
 374	default:
 375		fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev);
 376	}
 377	p = xdr_encode_hyper(p, fsid);
 
 378
 379	/* fileid */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 380	p = xdr_encode_hyper(p, stat->ino);
 
 
 
 381
 382	p = encode_nfstime3(p, &stat->atime);
 383	p = encode_nfstime3(p, &stat->mtime);
 384	encode_nfstime3(p, &stat->ctime);
 385
 386	return true;
 387}
 388
 389static bool
 390svcxdr_encode_wcc_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
 391{
 392	__be32 *p;
 393
 394	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
 395	if (!p)
 396		return false;
 397	p = xdr_encode_hyper(p, (u64)fhp->fh_pre_size);
 398	p = encode_nfstime3(p, &fhp->fh_pre_mtime);
 399	encode_nfstime3(p, &fhp->fh_pre_ctime);
 400
 401	return true;
 402}
 403
 404static bool
 405svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
 
 
 
 
 
 406{
 407	if (!fhp->fh_pre_saved) {
 408		if (xdr_stream_encode_item_absent(xdr) < 0)
 409			return false;
 410		return true;
 
 
 
 
 
 
 
 411	}
 
 
 
 412
 413	if (xdr_stream_encode_item_present(xdr) < 0)
 414		return false;
 415	return svcxdr_encode_wcc_attr(xdr, fhp);
 
 
 416}
 417
 418/**
 419 * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes
 420 * @rqstp: Context of a completed RPC transaction
 421 * @xdr: XDR stream
 422 * @fhp: File handle to encode
 423 *
 424 * Return values:
 425 *   %false: Send buffer space was exhausted
 426 *   %true: Success
 427 */
 428bool
 429svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 430			   const struct svc_fh *fhp)
 431{
 432	struct dentry *dentry = fhp->fh_dentry;
 433	struct kstat stat;
 434
 435	/*
 436	 * The inode may be NULL if the call failed because of a
 437	 * stale file handle. In this case, no attributes are
 438	 * returned.
 439	 */
 440	if (fhp->fh_no_wcc || !dentry || !d_really_is_positive(dentry))
 441		goto no_post_op_attrs;
 442	if (fh_getattr(fhp, &stat) != nfs_ok)
 443		goto no_post_op_attrs;
 444
 445	if (xdr_stream_encode_item_present(xdr) < 0)
 446		return false;
 447	lease_get_mtime(d_inode(dentry), &stat.mtime);
 448	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &stat))
 449		return false;
 450
 451	return true;
 452
 453no_post_op_attrs:
 454	return xdr_stream_encode_item_absent(xdr) > 0;
 
 
 
 
 
 
 
 
 
 
 455}
 456
 457/*
 458 * Encode weak cache consistency data
 459 */
 460static bool
 461svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 462		       const struct svc_fh *fhp)
 463{
 464	struct dentry *dentry = fhp->fh_dentry;
 465
 466	if (!dentry || !d_really_is_positive(dentry) || !fhp->fh_post_saved)
 467		goto neither;
 468
 469	/* before */
 470	if (!svcxdr_encode_pre_op_attr(xdr, fhp))
 471		return false;
 472
 473	/* after */
 474	if (xdr_stream_encode_item_present(xdr) < 0)
 475		return false;
 476	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &fhp->fh_post_attr))
 477		return false;
 478
 479	return true;
 480
 481neither:
 482	if (xdr_stream_encode_item_absent(xdr) < 0)
 483		return false;
 484	if (!svcxdr_encode_post_op_attr(rqstp, xdr, fhp))
 485		return false;
 486
 487	return true;
 488}
 489
 490/*
 491 * XDR decode functions
 492 */
 
 
 
 
 
 
 
 493
 494bool
 495nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 496{
 497	struct nfsd_fhandle *args = rqstp->rq_argp;
 
 
 
 
 
 
 
 
 498
 499	return svcxdr_decode_nfs_fh3(xdr, &args->fh);
 500}
 501
 502bool
 503nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 504{
 505	struct nfsd3_sattrargs *args = rqstp->rq_argp;
 
 
 506
 507	return svcxdr_decode_nfs_fh3(xdr, &args->fh) &&
 508		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
 509		svcxdr_decode_sattrguard3(xdr, args);
 510}
 511
 512bool
 513nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 514{
 515	struct nfsd3_diropargs *args = rqstp->rq_argp;
 
 
 516
 517	return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
 518}
 519
 520bool
 521nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 522{
 523	struct nfsd3_accessargs *args = rqstp->rq_argp;
 
 
 524
 525	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 526		return false;
 527	if (xdr_stream_decode_u32(xdr, &args->access) < 0)
 528		return false;
 529
 530	return true;
 531}
 532
 533bool
 534nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 535{
 536	struct nfsd3_readargs *args = rqstp->rq_argp;
 537
 538	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 539		return false;
 540	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 541		return false;
 542	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 543		return false;
 544
 545	return true;
 
 
 
 
 
 
 546}
 547
 548bool
 549nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 550{
 551	struct nfsd3_writeargs *args = rqstp->rq_argp;
 552	u32 max_blocksize = svc_max_payload(rqstp);
 553
 554	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 555		return false;
 556	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 557		return false;
 558	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 559		return false;
 560	if (xdr_stream_decode_u32(xdr, &args->stable) < 0)
 561		return false;
 562
 563	/* opaque data */
 564	if (xdr_stream_decode_u32(xdr, &args->len) < 0)
 565		return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 566
 567	/* request sanity */
 568	if (args->count != args->len)
 569		return false;
 570	if (args->count > max_blocksize) {
 571		args->count = max_blocksize;
 572		args->len = max_blocksize;
 573	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 574
 575	return xdr_stream_subsegment(xdr, &args->payload, args->count);
 576}
 577
 578bool
 579nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 580{
 581	struct nfsd3_createargs *args = rqstp->rq_argp;
 582
 583	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
 584		return false;
 585	if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
 586		return false;
 587	switch (args->createmode) {
 588	case NFS3_CREATE_UNCHECKED:
 589	case NFS3_CREATE_GUARDED:
 590		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 
 591	case NFS3_CREATE_EXCLUSIVE:
 592		args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
 593		if (!args->verf)
 594			return false;
 595		break;
 596	default:
 597		return false;
 598	}
 599	return true;
 
 600}
 601
 602bool
 603nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 604{
 605	struct nfsd3_createargs *args = rqstp->rq_argp;
 
 
 
 606
 607	return svcxdr_decode_diropargs3(xdr, &args->fh,
 608					&args->name, &args->len) &&
 609		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 610}
 611
 612bool
 613nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 614{
 615	struct nfsd3_symlinkargs *args = rqstp->rq_argp;
 616	struct kvec *head = rqstp->rq_arg.head;
 
 
 
 
 
 
 
 617
 618	if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
 619		return false;
 620	if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
 621		return false;
 622	if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
 623		return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 624
 625	/* symlink_data */
 626	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
 627	args->first.iov_base = xdr_inline_decode(xdr, args->tlen);
 628	return args->first.iov_base != NULL;
 629}
 630
 631bool
 632nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 633{
 634	struct nfsd3_mknodargs *args = rqstp->rq_argp;
 
 
 
 
 635
 636	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
 637		return false;
 638	if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
 639		return false;
 640	switch (args->ftype) {
 641	case NF3CHR:
 642	case NF3BLK:
 643		return svcxdr_decode_devicedata3(rqstp, xdr, args);
 644	case NF3SOCK:
 645	case NF3FIFO:
 646		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
 647	case NF3REG:
 648	case NF3DIR:
 649	case NF3LNK:
 650		/* Valid XDR but illegal file types */
 651		break;
 652	default:
 653		return false;
 654	}
 655
 656	return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 657}
 658
 659bool
 660nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 661{
 662	struct nfsd3_renameargs *args = rqstp->rq_argp;
 
 
 663
 664	return svcxdr_decode_diropargs3(xdr, &args->ffh,
 665					&args->fname, &args->flen) &&
 666		svcxdr_decode_diropargs3(xdr, &args->tfh,
 667					 &args->tname, &args->tlen);
 668}
 669
 670bool
 671nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 672{
 673	struct nfsd3_linkargs *args = rqstp->rq_argp;
 
 
 
 674
 675	return svcxdr_decode_nfs_fh3(xdr, &args->ffh) &&
 676		svcxdr_decode_diropargs3(xdr, &args->tfh,
 677					 &args->tname, &args->tlen);
 678}
 679
 680bool
 681nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 682{
 683	struct nfsd3_readdirargs *args = rqstp->rq_argp;
 
 
 
 
 
 684
 685	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 686		return false;
 687	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
 688		return false;
 689	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 690	if (!args->verf)
 691		return false;
 692	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 693		return false;
 694
 695	return true;
 
 
 696}
 697
 698bool
 699nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 700{
 701	struct nfsd3_readdirargs *args = rqstp->rq_argp;
 702	u32 dircount;
 703
 704	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 705		return false;
 706	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
 707		return false;
 708	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
 709	if (!args->verf)
 710		return false;
 711	/* dircount is ignored */
 712	if (xdr_stream_decode_u32(xdr, &dircount) < 0)
 713		return false;
 714	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 715		return false;
 716
 717	return true;
 
 
 
 
 
 
 
 
 
 
 
 718}
 719
 720bool
 721nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 722{
 723	struct nfsd3_commitargs *args = rqstp->rq_argp;
 724
 725	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
 726		return false;
 727	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
 728		return false;
 729	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
 730		return false;
 731
 732	return true;
 733}
 734
 735/*
 736 * XDR encode functions
 737 */
 
 
 
 
 
 
 
 
 
 738
 739/* GETATTR */
 740bool
 741nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 742{
 743	struct nfsd3_attrstat *resp = rqstp->rq_resp;
 744
 745	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 746		return false;
 747	switch (resp->status) {
 748	case nfs_ok:
 749		lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime);
 750		if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat))
 751			return false;
 752		break;
 753	}
 754
 755	return true;
 756}
 757
 758/* SETATTR, REMOVE, RMDIR */
 759bool
 760nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
 761{
 762	struct nfsd3_attrstat *resp = rqstp->rq_resp;
 763
 764	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
 765		svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh);
 766}
 767
 768/* LOOKUP */
 769bool
 770nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 771{
 772	struct nfsd3_diropres *resp = rqstp->rq_resp;
 773
 774	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 775		return false;
 776	switch (resp->status) {
 777	case nfs_ok:
 778		if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh))
 779			return false;
 780		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 781			return false;
 782		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
 783			return false;
 784		break;
 785	default:
 786		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
 787			return false;
 788	}
 789
 790	return true;
 791}
 792
 793/* ACCESS */
 794bool
 795nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 796{
 797	struct nfsd3_accessres *resp = rqstp->rq_resp;
 798
 799	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 800		return false;
 801	switch (resp->status) {
 802	case nfs_ok:
 803		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 804			return false;
 805		if (xdr_stream_encode_u32(xdr, resp->access) < 0)
 806			return false;
 807		break;
 808	default:
 809		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 810			return false;
 811	}
 812
 813	return true;
 814}
 815
 816/* READLINK */
 817bool
 818nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 819{
 820	struct nfsd3_readlinkres *resp = rqstp->rq_resp;
 821	struct kvec *head = rqstp->rq_res.head;
 822
 823	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 824		return false;
 825	switch (resp->status) {
 826	case nfs_ok:
 827		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 828			return false;
 829		if (xdr_stream_encode_u32(xdr, resp->len) < 0)
 830			return false;
 831		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 0,
 832					   resp->len);
 833		if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
 834			return false;
 835		break;
 836	default:
 837		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 838			return false;
 839	}
 840
 841	return true;
 842}
 843
 844/* READ */
 845bool
 846nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 847{
 848	struct nfsd3_readres *resp = rqstp->rq_resp;
 849	struct kvec *head = rqstp->rq_res.head;
 850
 851	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 852		return false;
 853	switch (resp->status) {
 854	case nfs_ok:
 855		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 856			return false;
 857		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 858			return false;
 859		if (xdr_stream_encode_bool(xdr, resp->eof) < 0)
 860			return false;
 861		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 862			return false;
 863		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages,
 864					   rqstp->rq_res.page_base,
 865					   resp->count);
 866		if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
 867			return false;
 868		break;
 869	default:
 870		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 871			return false;
 872	}
 873
 874	return true;
 875}
 876
 877/* WRITE */
 878bool
 879nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 880{
 881	struct nfsd3_writeres *resp = rqstp->rq_resp;
 882
 883	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 884		return false;
 885	switch (resp->status) {
 886	case nfs_ok:
 887		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
 888			return false;
 889		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
 890			return false;
 891		if (xdr_stream_encode_u32(xdr, resp->committed) < 0)
 892			return false;
 893		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
 894			return false;
 895		break;
 896	default:
 897		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
 898			return false;
 899	}
 900
 901	return true;
 902}
 903
 904/* CREATE, MKDIR, SYMLINK, MKNOD */
 905bool
 906nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 907{
 908	struct nfsd3_diropres *resp = rqstp->rq_resp;
 909
 910	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 911		return false;
 912	switch (resp->status) {
 913	case nfs_ok:
 914		if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh))
 915			return false;
 916		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 917			return false;
 918		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
 919			return false;
 920		break;
 921	default:
 922		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
 923			return false;
 924	}
 925
 926	return true;
 927}
 928
 929/* RENAME */
 930bool
 931nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 932{
 933	struct nfsd3_renameres *resp = rqstp->rq_resp;
 934
 935	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
 936		svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) &&
 937		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
 938}
 939
 940/* LINK */
 941bool
 942nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 943{
 944	struct nfsd3_linkres *resp = rqstp->rq_resp;
 
 
 
 
 945
 946	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
 947		svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) &&
 948		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 949}
 950
 951/* READDIR */
 952bool
 953nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 954{
 955	struct nfsd3_readdirres *resp = rqstp->rq_resp;
 956	struct xdr_buf *dirlist = &resp->dirlist;
 
 957
 958	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
 959		return false;
 960	switch (resp->status) {
 961	case nfs_ok:
 962		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 963			return false;
 964		if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
 965			return false;
 966		svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0,
 967					   dirlist->len);
 968		/* no more entries */
 969		if (xdr_stream_encode_item_absent(xdr) < 0)
 970			return false;
 971		if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
 972			return false;
 973		break;
 974	default:
 975		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
 976			return false;
 977	}
 978
 979	return true;
 980}
 981
 982static __be32
 983compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
 984		 const char *name, int namlen, u64 ino)
 985{
 986	struct svc_export	*exp;
 987	struct dentry		*dparent, *dchild;
 988	__be32 rv = nfserr_noent;
 989
 990	dparent = cd->fh.fh_dentry;
 991	exp  = cd->fh.fh_export;
 992
 993	if (isdotent(name, namlen)) {
 994		if (namlen == 2) {
 995			dchild = dget_parent(dparent);
 996			/*
 997			 * Don't return filehandle for ".." if we're at
 998			 * the filesystem or export root:
 999			 */
1000			if (dchild == dparent)
1001				goto out;
1002			if (dparent == exp->ex_path.dentry)
1003				goto out;
1004		} else
1005			dchild = dget(dparent);
1006	} else
1007		dchild = lookup_positive_unlocked(name, dparent, namlen);
1008	if (IS_ERR(dchild))
1009		return rv;
1010	if (d_mountpoint(dchild))
1011		goto out;
1012	if (dchild->d_inode->i_ino != ino)
1013		goto out;
1014	rv = fh_compose(fhp, exp, dchild, &cd->fh);
1015out:
1016	dput(dchild);
1017	return rv;
1018}
1019
1020/**
1021 * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1022 * @resp: readdir result context
1023 * @offset: offset cookie to encode
1024 *
1025 * The buffer space for the offset cookie has already been reserved
1026 * by svcxdr_encode_entry3_common().
1027 */
1028void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset)
1029{
1030	__be64 cookie = cpu_to_be64(offset);
 
1031
1032	if (!resp->cookie_offset)
1033		return;
1034	write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
1035			       sizeof(cookie));
1036	resp->cookie_offset = 0;
1037}
1038
1039static bool
1040svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name,
1041			    int namlen, loff_t offset, u64 ino)
1042{
1043	struct xdr_buf *dirlist = &resp->dirlist;
1044	struct xdr_stream *xdr = &resp->xdr;
1045
1046	if (xdr_stream_encode_item_present(xdr) < 0)
1047		return false;
1048	/* fileid */
1049	if (xdr_stream_encode_u64(xdr, ino) < 0)
1050		return false;
1051	/* name */
1052	if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0)
1053		return false;
1054	/* cookie */
1055	resp->cookie_offset = dirlist->len;
1056	if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0)
1057		return false;
1058
1059	return true;
1060}
1061
1062/**
1063 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1064 * @data: directory context
1065 * @name: name of the object to be encoded
1066 * @namlen: length of that name, in bytes
1067 * @offset: the offset of the previous entry
1068 * @ino: the fileid of this entry
1069 * @d_type: unused
1070 *
1071 * Return values:
1072 *   %0: Entry was successfully encoded.
1073 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1074 *
1075 * On exit, the following fields are updated:
1076 *   - resp->xdr
1077 *   - resp->common.err
1078 *   - resp->cookie_offset
1079 */
1080int nfs3svc_encode_entry3(void *data, const char *name, int namlen,
1081			  loff_t offset, u64 ino, unsigned int d_type)
1082{
1083	struct readdir_cd *ccd = data;
1084	struct nfsd3_readdirres *resp = container_of(ccd,
1085						     struct nfsd3_readdirres,
1086						     common);
1087	unsigned int starting_length = resp->dirlist.len;
1088
1089	/* The offset cookie for the previous entry */
1090	nfs3svc_encode_cookie3(resp, offset);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1091
1092	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1093		goto out_toosmall;
 
1094
1095	xdr_commit_encode(&resp->xdr);
1096	resp->common.err = nfs_ok;
1097	return 0;
 
1098
1099out_toosmall:
1100	resp->cookie_offset = 0;
1101	resp->common.err = nfserr_toosmall;
1102	resp->dirlist.len = starting_length;
1103	return -EINVAL;
1104}
1105
1106static bool
1107svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name,
1108			  int namlen, u64 ino)
1109{
1110	struct xdr_stream *xdr = &resp->xdr;
1111	struct svc_fh *fhp = &resp->scratch;
1112	bool result;
1113
1114	result = false;
1115	fh_init(fhp, NFS3_FHSIZE);
1116	if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok)
1117		goto out_noattrs;
1118
1119	if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp))
1120		goto out;
1121	if (!svcxdr_encode_post_op_fh3(xdr, fhp))
1122		goto out;
1123	result = true;
1124
1125out:
1126	fh_put(fhp);
1127	return result;
1128
1129out_noattrs:
1130	if (xdr_stream_encode_item_absent(xdr) < 0)
1131		return false;
1132	if (xdr_stream_encode_item_absent(xdr) < 0)
1133		return false;
1134	return true;
1135}
1136
1137/**
1138 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1139 * @data: directory context
1140 * @name: name of the object to be encoded
1141 * @namlen: length of that name, in bytes
1142 * @offset: the offset of the previous entry
1143 * @ino: the fileid of this entry
1144 * @d_type: unused
1145 *
1146 * Return values:
1147 *   %0: Entry was successfully encoded.
1148 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1149 *
1150 * On exit, the following fields are updated:
1151 *   - resp->xdr
1152 *   - resp->common.err
1153 *   - resp->cookie_offset
1154 */
1155int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,
1156			      loff_t offset, u64 ino, unsigned int d_type)
1157{
1158	struct readdir_cd *ccd = data;
1159	struct nfsd3_readdirres *resp = container_of(ccd,
1160						     struct nfsd3_readdirres,
1161						     common);
1162	unsigned int starting_length = resp->dirlist.len;
1163
1164	/* The offset cookie for the previous entry */
1165	nfs3svc_encode_cookie3(resp, offset);
1166
1167	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1168		goto out_toosmall;
1169	if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino))
1170		goto out_toosmall;
1171
1172	xdr_commit_encode(&resp->xdr);
1173	resp->common.err = nfs_ok;
1174	return 0;
1175
1176out_toosmall:
1177	resp->cookie_offset = 0;
1178	resp->common.err = nfserr_toosmall;
1179	resp->dirlist.len = starting_length;
1180	return -EINVAL;
1181}
1182
1183static bool
1184svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
1185			   const struct nfsd3_fsstatres *resp)
1186{
1187	const struct kstatfs *s = &resp->stats;
1188	u64 bs = s->f_bsize;
1189	__be32 *p;
1190
1191	p = xdr_reserve_space(xdr, XDR_UNIT * 13);
1192	if (!p)
1193		return false;
1194	p = xdr_encode_hyper(p, bs * s->f_blocks);	/* total bytes */
1195	p = xdr_encode_hyper(p, bs * s->f_bfree);	/* free bytes */
1196	p = xdr_encode_hyper(p, bs * s->f_bavail);	/* user available bytes */
1197	p = xdr_encode_hyper(p, s->f_files);		/* total inodes */
1198	p = xdr_encode_hyper(p, s->f_ffree);		/* free inodes */
1199	p = xdr_encode_hyper(p, s->f_ffree);		/* user available inodes */
1200	*p = cpu_to_be32(resp->invarsec);		/* mean unchanged time */
1201
1202	return true;
1203}
1204
1205/* FSSTAT */
1206bool
1207nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1208{
1209	struct nfsd3_fsstatres *resp = rqstp->rq_resp;
 
 
 
 
1210
1211	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1212		return false;
1213	switch (resp->status) {
1214	case nfs_ok:
1215		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1216			return false;
1217		if (!svcxdr_encode_fsstat3resok(xdr, resp))
1218			return false;
1219		break;
1220	default:
1221		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1222			return false;
1223	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1224
1225	return true;
1226}
1227
1228static bool
1229svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
1230			   const struct nfsd3_fsinfores *resp)
1231{
1232	__be32 *p;
1233
1234	p = xdr_reserve_space(xdr, XDR_UNIT * 12);
1235	if (!p)
1236		return false;
1237	*p++ = cpu_to_be32(resp->f_rtmax);
1238	*p++ = cpu_to_be32(resp->f_rtpref);
1239	*p++ = cpu_to_be32(resp->f_rtmult);
1240	*p++ = cpu_to_be32(resp->f_wtmax);
1241	*p++ = cpu_to_be32(resp->f_wtpref);
1242	*p++ = cpu_to_be32(resp->f_wtmult);
1243	*p++ = cpu_to_be32(resp->f_dtpref);
1244	p = xdr_encode_hyper(p, resp->f_maxfilesize);
1245	p = encode_nfstime3(p, &nfs3svc_time_delta);
1246	*p = cpu_to_be32(resp->f_properties);
1247
1248	return true;
1249}
1250
1251/* FSINFO */
1252bool
1253nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr)
 
1254{
1255	struct nfsd3_fsinfores *resp = rqstp->rq_resp;
 
1256
1257	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1258		return false;
1259	switch (resp->status) {
1260	case nfs_ok:
1261		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1262			return false;
1263		if (!svcxdr_encode_fsinfo3resok(xdr, resp))
1264			return false;
1265		break;
1266	default:
1267		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1268			return false;
 
 
 
 
 
 
1269	}
1270
1271	return true;
1272}
1273
1274static bool
1275svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
1276			     const struct nfsd3_pathconfres *resp)
1277{
1278	__be32 *p;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1279
1280	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
1281	if (!p)
1282		return false;
1283	*p++ = cpu_to_be32(resp->p_link_max);
1284	*p++ = cpu_to_be32(resp->p_name_max);
1285	p = xdr_encode_bool(p, resp->p_no_trunc);
1286	p = xdr_encode_bool(p, resp->p_chown_restricted);
1287	p = xdr_encode_bool(p, resp->p_case_insensitive);
1288	xdr_encode_bool(p, resp->p_case_preserving);
1289
1290	return true;
1291}
1292
1293/* PATHCONF */
1294bool
1295nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1296{
1297	struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1298
1299	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1300		return false;
1301	switch (resp->status) {
1302	case nfs_ok:
1303		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1304			return false;
1305		if (!svcxdr_encode_pathconf3resok(xdr, resp))
1306			return false;
1307		break;
1308	default:
1309		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1310			return false;
1311	}
1312
1313	return true;
1314}
1315
1316/* COMMIT */
1317bool
1318nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1319{
1320	struct nfsd3_commitres *resp = rqstp->rq_resp;
1321
1322	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1323		return false;
1324	switch (resp->status) {
1325	case nfs_ok:
1326		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1327			return false;
1328		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
1329			return false;
1330		break;
1331	default:
1332		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1333			return false;
1334	}
1335
1336	return true;
1337}
1338
1339/*
1340 * XDR release functions
1341 */
1342void
1343nfs3svc_release_fhandle(struct svc_rqst *rqstp)
 
1344{
1345	struct nfsd3_attrstat *resp = rqstp->rq_resp;
1346
1347	fh_put(&resp->fh);
 
1348}
1349
1350void
1351nfs3svc_release_fhandle2(struct svc_rqst *rqstp)
 
1352{
1353	struct nfsd3_fhandle_pair *resp = rqstp->rq_resp;
1354
1355	fh_put(&resp->fh1);
1356	fh_put(&resp->fh2);
 
1357}