Linux Audio

Check our new training course

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