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   */
20  static 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   */
28  static 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   */
36  static 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  
48  static __be32 *
encode_nfstime3(__be32 * p,const struct timespec64 * time)49  encode_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  
57  static bool
svcxdr_decode_nfstime3(struct xdr_stream * xdr,struct timespec64 * timep)58  svcxdr_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   */
80  bool
svcxdr_decode_nfs_fh3(struct xdr_stream * xdr,struct svc_fh * fhp)81  svcxdr_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   */
109  bool
svcxdr_encode_nfsstat3(struct xdr_stream * xdr,__be32 status)110  svcxdr_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  
122  static bool
svcxdr_encode_nfs_fh3(struct xdr_stream * xdr,const struct svc_fh * fhp)123  svcxdr_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  
139  static bool
svcxdr_encode_post_op_fh3(struct xdr_stream * xdr,const struct svc_fh * fhp)140  svcxdr_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  
150  static bool
svcxdr_encode_cookieverf3(struct xdr_stream * xdr,const __be32 * verf)151  svcxdr_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  
163  static bool
svcxdr_encode_writeverf3(struct xdr_stream * xdr,const __be32 * verf)164  svcxdr_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  
176  static bool
svcxdr_decode_filename3(struct xdr_stream * xdr,char ** name,unsigned int * len)177  svcxdr_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  
201  static bool
svcxdr_decode_diropargs3(struct xdr_stream * xdr,struct svc_fh * fhp,char ** name,unsigned int * len)202  svcxdr_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  
209  static bool
svcxdr_decode_sattr3(struct svc_rqst * rqstp,struct xdr_stream * xdr,struct iattr * iap)210  svcxdr_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  
295  static bool
svcxdr_decode_sattrguard3(struct xdr_stream * xdr,struct nfsd3_sattrargs * args)296  svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args)
297  {
298  	u32 check;
299  
300  	if (xdr_stream_decode_bool(xdr, &check) < 0)
301  		return false;
302  	if (check) {
303  		if (!svcxdr_decode_nfstime3(xdr, &args->guardtime))
304  			return false;
305  		args->check_guard = 1;
306  	} else
307  		args->check_guard = 0;
308  
309  	return true;
310  }
311  
312  static bool
svcxdr_decode_specdata3(struct xdr_stream * xdr,struct nfsd3_mknodargs * args)313  svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args)
314  {
315  	__be32 *p;
316  
317  	p = xdr_inline_decode(xdr, XDR_UNIT * 2);
318  	if (!p)
319  		return false;
320  	args->major = be32_to_cpup(p++);
321  	args->minor = be32_to_cpup(p);
322  
323  	return true;
324  }
325  
326  static bool
svcxdr_decode_devicedata3(struct svc_rqst * rqstp,struct xdr_stream * xdr,struct nfsd3_mknodargs * args)327  svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
328  			  struct nfsd3_mknodargs *args)
329  {
330  	return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
331  		svcxdr_decode_specdata3(xdr, args);
332  }
333  
334  static bool
svcxdr_encode_fattr3(struct svc_rqst * rqstp,struct xdr_stream * xdr,const struct svc_fh * fhp,const struct kstat * stat)335  svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
336  		     const struct svc_fh *fhp, const struct kstat *stat)
337  {
338  	struct user_namespace *userns = nfsd_user_namespace(rqstp);
339  	__be32 *p;
340  	u64 fsid;
341  
342  	p = xdr_reserve_space(xdr, XDR_UNIT * 21);
343  	if (!p)
344  		return false;
345  
346  	*p++ = cpu_to_be32(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
347  	*p++ = cpu_to_be32((u32)(stat->mode & S_IALLUGO));
348  	*p++ = cpu_to_be32((u32)stat->nlink);
349  	*p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid));
350  	*p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid));
351  	if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN)
352  		p = xdr_encode_hyper(p, (u64)NFS3_MAXPATHLEN);
353  	else
354  		p = xdr_encode_hyper(p, (u64)stat->size);
355  
356  	/* used */
357  	p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
358  
359  	/* rdev */
360  	*p++ = cpu_to_be32((u32)MAJOR(stat->rdev));
361  	*p++ = cpu_to_be32((u32)MINOR(stat->rdev));
362  
363  	switch(fsid_source(fhp)) {
364  	case FSIDSOURCE_FSID:
365  		fsid = (u64)fhp->fh_export->ex_fsid;
366  		break;
367  	case FSIDSOURCE_UUID:
368  		fsid = ((u64 *)fhp->fh_export->ex_uuid)[0];
369  		fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1];
370  		break;
371  	default:
372  		fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev);
373  	}
374  	p = xdr_encode_hyper(p, fsid);
375  
376  	/* fileid */
377  	p = xdr_encode_hyper(p, stat->ino);
378  
379  	p = encode_nfstime3(p, &stat->atime);
380  	p = encode_nfstime3(p, &stat->mtime);
381  	encode_nfstime3(p, &stat->ctime);
382  
383  	return true;
384  }
385  
386  static bool
svcxdr_encode_wcc_attr(struct xdr_stream * xdr,const struct svc_fh * fhp)387  svcxdr_encode_wcc_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
388  {
389  	__be32 *p;
390  
391  	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
392  	if (!p)
393  		return false;
394  	p = xdr_encode_hyper(p, (u64)fhp->fh_pre_size);
395  	p = encode_nfstime3(p, &fhp->fh_pre_mtime);
396  	encode_nfstime3(p, &fhp->fh_pre_ctime);
397  
398  	return true;
399  }
400  
401  static bool
svcxdr_encode_pre_op_attr(struct xdr_stream * xdr,const struct svc_fh * fhp)402  svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
403  {
404  	if (!fhp->fh_pre_saved) {
405  		if (xdr_stream_encode_item_absent(xdr) < 0)
406  			return false;
407  		return true;
408  	}
409  
410  	if (xdr_stream_encode_item_present(xdr) < 0)
411  		return false;
412  	return svcxdr_encode_wcc_attr(xdr, fhp);
413  }
414  
415  /**
416   * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes
417   * @rqstp: Context of a completed RPC transaction
418   * @xdr: XDR stream
419   * @fhp: File handle to encode
420   *
421   * Return values:
422   *   %false: Send buffer space was exhausted
423   *   %true: Success
424   */
425  bool
svcxdr_encode_post_op_attr(struct svc_rqst * rqstp,struct xdr_stream * xdr,const struct svc_fh * fhp)426  svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
427  			   const struct svc_fh *fhp)
428  {
429  	struct dentry *dentry = fhp->fh_dentry;
430  	struct kstat stat;
431  
432  	/*
433  	 * The inode may be NULL if the call failed because of a
434  	 * stale file handle. In this case, no attributes are
435  	 * returned.
436  	 */
437  	if (fhp->fh_no_wcc || !dentry || !d_really_is_positive(dentry))
438  		goto no_post_op_attrs;
439  	if (fh_getattr(fhp, &stat) != nfs_ok)
440  		goto no_post_op_attrs;
441  
442  	if (xdr_stream_encode_item_present(xdr) < 0)
443  		return false;
444  	lease_get_mtime(d_inode(dentry), &stat.mtime);
445  	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &stat))
446  		return false;
447  
448  	return true;
449  
450  no_post_op_attrs:
451  	return xdr_stream_encode_item_absent(xdr) > 0;
452  }
453  
454  /*
455   * Encode weak cache consistency data
456   */
457  static bool
svcxdr_encode_wcc_data(struct svc_rqst * rqstp,struct xdr_stream * xdr,const struct svc_fh * fhp)458  svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr,
459  		       const struct svc_fh *fhp)
460  {
461  	struct dentry *dentry = fhp->fh_dentry;
462  
463  	if (!dentry || !d_really_is_positive(dentry) || !fhp->fh_post_saved)
464  		goto neither;
465  
466  	/* before */
467  	if (!svcxdr_encode_pre_op_attr(xdr, fhp))
468  		return false;
469  
470  	/* after */
471  	if (xdr_stream_encode_item_present(xdr) < 0)
472  		return false;
473  	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &fhp->fh_post_attr))
474  		return false;
475  
476  	return true;
477  
478  neither:
479  	if (xdr_stream_encode_item_absent(xdr) < 0)
480  		return false;
481  	if (!svcxdr_encode_post_op_attr(rqstp, xdr, fhp))
482  		return false;
483  
484  	return true;
485  }
486  
487  /*
488   * XDR decode functions
489   */
490  
491  bool
nfs3svc_decode_fhandleargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)492  nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
493  {
494  	struct nfsd_fhandle *args = rqstp->rq_argp;
495  
496  	return svcxdr_decode_nfs_fh3(xdr, &args->fh);
497  }
498  
499  bool
nfs3svc_decode_sattrargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)500  nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
501  {
502  	struct nfsd3_sattrargs *args = rqstp->rq_argp;
503  
504  	return svcxdr_decode_nfs_fh3(xdr, &args->fh) &&
505  		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
506  		svcxdr_decode_sattrguard3(xdr, args);
507  }
508  
509  bool
nfs3svc_decode_diropargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)510  nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
511  {
512  	struct nfsd3_diropargs *args = rqstp->rq_argp;
513  
514  	return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
515  }
516  
517  bool
nfs3svc_decode_accessargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)518  nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
519  {
520  	struct nfsd3_accessargs *args = rqstp->rq_argp;
521  
522  	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
523  		return false;
524  	if (xdr_stream_decode_u32(xdr, &args->access) < 0)
525  		return false;
526  
527  	return true;
528  }
529  
530  bool
nfs3svc_decode_readargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)531  nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
532  {
533  	struct nfsd3_readargs *args = rqstp->rq_argp;
534  
535  	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
536  		return false;
537  	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
538  		return false;
539  	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
540  		return false;
541  
542  	return true;
543  }
544  
545  bool
nfs3svc_decode_writeargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)546  nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
547  {
548  	struct nfsd3_writeargs *args = rqstp->rq_argp;
549  	u32 max_blocksize = svc_max_payload(rqstp);
550  
551  	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
552  		return false;
553  	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
554  		return false;
555  	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
556  		return false;
557  	if (xdr_stream_decode_u32(xdr, &args->stable) < 0)
558  		return false;
559  
560  	/* opaque data */
561  	if (xdr_stream_decode_u32(xdr, &args->len) < 0)
562  		return false;
563  
564  	/* request sanity */
565  	if (args->count != args->len)
566  		return false;
567  	if (args->count > max_blocksize) {
568  		args->count = max_blocksize;
569  		args->len = max_blocksize;
570  	}
571  
572  	return xdr_stream_subsegment(xdr, &args->payload, args->count);
573  }
574  
575  bool
nfs3svc_decode_createargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)576  nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
577  {
578  	struct nfsd3_createargs *args = rqstp->rq_argp;
579  
580  	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
581  		return false;
582  	if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
583  		return false;
584  	switch (args->createmode) {
585  	case NFS3_CREATE_UNCHECKED:
586  	case NFS3_CREATE_GUARDED:
587  		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
588  	case NFS3_CREATE_EXCLUSIVE:
589  		args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
590  		if (!args->verf)
591  			return false;
592  		break;
593  	default:
594  		return false;
595  	}
596  	return true;
597  }
598  
599  bool
nfs3svc_decode_mkdirargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)600  nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
601  {
602  	struct nfsd3_createargs *args = rqstp->rq_argp;
603  
604  	return svcxdr_decode_diropargs3(xdr, &args->fh,
605  					&args->name, &args->len) &&
606  		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
607  }
608  
609  bool
nfs3svc_decode_symlinkargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)610  nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
611  {
612  	struct nfsd3_symlinkargs *args = rqstp->rq_argp;
613  	struct kvec *head = rqstp->rq_arg.head;
614  
615  	if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
616  		return false;
617  	if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
618  		return false;
619  	if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
620  		return false;
621  
622  	/* symlink_data */
623  	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
624  	args->first.iov_base = xdr_inline_decode(xdr, args->tlen);
625  	return args->first.iov_base != NULL;
626  }
627  
628  bool
nfs3svc_decode_mknodargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)629  nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
630  {
631  	struct nfsd3_mknodargs *args = rqstp->rq_argp;
632  
633  	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
634  		return false;
635  	if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
636  		return false;
637  	switch (args->ftype) {
638  	case NF3CHR:
639  	case NF3BLK:
640  		return svcxdr_decode_devicedata3(rqstp, xdr, args);
641  	case NF3SOCK:
642  	case NF3FIFO:
643  		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
644  	case NF3REG:
645  	case NF3DIR:
646  	case NF3LNK:
647  		/* Valid XDR but illegal file types */
648  		break;
649  	default:
650  		return false;
651  	}
652  
653  	return true;
654  }
655  
656  bool
nfs3svc_decode_renameargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)657  nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
658  {
659  	struct nfsd3_renameargs *args = rqstp->rq_argp;
660  
661  	return svcxdr_decode_diropargs3(xdr, &args->ffh,
662  					&args->fname, &args->flen) &&
663  		svcxdr_decode_diropargs3(xdr, &args->tfh,
664  					 &args->tname, &args->tlen);
665  }
666  
667  bool
nfs3svc_decode_linkargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)668  nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
669  {
670  	struct nfsd3_linkargs *args = rqstp->rq_argp;
671  
672  	return svcxdr_decode_nfs_fh3(xdr, &args->ffh) &&
673  		svcxdr_decode_diropargs3(xdr, &args->tfh,
674  					 &args->tname, &args->tlen);
675  }
676  
677  bool
nfs3svc_decode_readdirargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)678  nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
679  {
680  	struct nfsd3_readdirargs *args = rqstp->rq_argp;
681  
682  	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
683  		return false;
684  	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
685  		return false;
686  	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
687  	if (!args->verf)
688  		return false;
689  	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
690  		return false;
691  
692  	return true;
693  }
694  
695  bool
nfs3svc_decode_readdirplusargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)696  nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
697  {
698  	struct nfsd3_readdirargs *args = rqstp->rq_argp;
699  	u32 dircount;
700  
701  	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
702  		return false;
703  	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
704  		return false;
705  	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
706  	if (!args->verf)
707  		return false;
708  	/* dircount is ignored */
709  	if (xdr_stream_decode_u32(xdr, &dircount) < 0)
710  		return false;
711  	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
712  		return false;
713  
714  	return true;
715  }
716  
717  bool
nfs3svc_decode_commitargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)718  nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
719  {
720  	struct nfsd3_commitargs *args = rqstp->rq_argp;
721  
722  	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
723  		return false;
724  	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
725  		return false;
726  	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
727  		return false;
728  
729  	return true;
730  }
731  
732  /*
733   * XDR encode functions
734   */
735  
736  /* GETATTR */
737  bool
nfs3svc_encode_getattrres(struct svc_rqst * rqstp,struct xdr_stream * xdr)738  nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
739  {
740  	struct nfsd3_attrstat *resp = rqstp->rq_resp;
741  
742  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
743  		return false;
744  	switch (resp->status) {
745  	case nfs_ok:
746  		lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime);
747  		if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat))
748  			return false;
749  		break;
750  	}
751  
752  	return true;
753  }
754  
755  /* SETATTR, REMOVE, RMDIR */
756  bool
nfs3svc_encode_wccstat(struct svc_rqst * rqstp,struct xdr_stream * xdr)757  nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr)
758  {
759  	struct nfsd3_attrstat *resp = rqstp->rq_resp;
760  
761  	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
762  		svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh);
763  }
764  
765  /* LOOKUP */
766  bool
nfs3svc_encode_lookupres(struct svc_rqst * rqstp,struct xdr_stream * xdr)767  nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
768  {
769  	struct nfsd3_diropres *resp = rqstp->rq_resp;
770  
771  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
772  		return false;
773  	switch (resp->status) {
774  	case nfs_ok:
775  		if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh))
776  			return false;
777  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
778  			return false;
779  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
780  			return false;
781  		break;
782  	default:
783  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
784  			return false;
785  	}
786  
787  	return true;
788  }
789  
790  /* ACCESS */
791  bool
nfs3svc_encode_accessres(struct svc_rqst * rqstp,struct xdr_stream * xdr)792  nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
793  {
794  	struct nfsd3_accessres *resp = rqstp->rq_resp;
795  
796  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
797  		return false;
798  	switch (resp->status) {
799  	case nfs_ok:
800  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
801  			return false;
802  		if (xdr_stream_encode_u32(xdr, resp->access) < 0)
803  			return false;
804  		break;
805  	default:
806  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
807  			return false;
808  	}
809  
810  	return true;
811  }
812  
813  /* READLINK */
814  bool
nfs3svc_encode_readlinkres(struct svc_rqst * rqstp,struct xdr_stream * xdr)815  nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
816  {
817  	struct nfsd3_readlinkres *resp = rqstp->rq_resp;
818  	struct kvec *head = rqstp->rq_res.head;
819  
820  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
821  		return false;
822  	switch (resp->status) {
823  	case nfs_ok:
824  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
825  			return false;
826  		if (xdr_stream_encode_u32(xdr, resp->len) < 0)
827  			return false;
828  		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 0,
829  					   resp->len);
830  		if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
831  			return false;
832  		break;
833  	default:
834  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
835  			return false;
836  	}
837  
838  	return true;
839  }
840  
841  /* READ */
842  bool
nfs3svc_encode_readres(struct svc_rqst * rqstp,struct xdr_stream * xdr)843  nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
844  {
845  	struct nfsd3_readres *resp = rqstp->rq_resp;
846  	struct kvec *head = rqstp->rq_res.head;
847  
848  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
849  		return false;
850  	switch (resp->status) {
851  	case nfs_ok:
852  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
853  			return false;
854  		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
855  			return false;
856  		if (xdr_stream_encode_bool(xdr, resp->eof) < 0)
857  			return false;
858  		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
859  			return false;
860  		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages,
861  					   rqstp->rq_res.page_base,
862  					   resp->count);
863  		if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
864  			return false;
865  		break;
866  	default:
867  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
868  			return false;
869  	}
870  
871  	return true;
872  }
873  
874  /* WRITE */
875  bool
nfs3svc_encode_writeres(struct svc_rqst * rqstp,struct xdr_stream * xdr)876  nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
877  {
878  	struct nfsd3_writeres *resp = rqstp->rq_resp;
879  
880  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
881  		return false;
882  	switch (resp->status) {
883  	case nfs_ok:
884  		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
885  			return false;
886  		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
887  			return false;
888  		if (xdr_stream_encode_u32(xdr, resp->committed) < 0)
889  			return false;
890  		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
891  			return false;
892  		break;
893  	default:
894  		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
895  			return false;
896  	}
897  
898  	return true;
899  }
900  
901  /* CREATE, MKDIR, SYMLINK, MKNOD */
902  bool
nfs3svc_encode_createres(struct svc_rqst * rqstp,struct xdr_stream * xdr)903  nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
904  {
905  	struct nfsd3_diropres *resp = rqstp->rq_resp;
906  
907  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
908  		return false;
909  	switch (resp->status) {
910  	case nfs_ok:
911  		if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh))
912  			return false;
913  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
914  			return false;
915  		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
916  			return false;
917  		break;
918  	default:
919  		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
920  			return false;
921  	}
922  
923  	return true;
924  }
925  
926  /* RENAME */
927  bool
nfs3svc_encode_renameres(struct svc_rqst * rqstp,struct xdr_stream * xdr)928  nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
929  {
930  	struct nfsd3_renameres *resp = rqstp->rq_resp;
931  
932  	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
933  		svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) &&
934  		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
935  }
936  
937  /* LINK */
938  bool
nfs3svc_encode_linkres(struct svc_rqst * rqstp,struct xdr_stream * xdr)939  nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
940  {
941  	struct nfsd3_linkres *resp = rqstp->rq_resp;
942  
943  	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
944  		svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) &&
945  		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
946  }
947  
948  /* READDIR */
949  bool
nfs3svc_encode_readdirres(struct svc_rqst * rqstp,struct xdr_stream * xdr)950  nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
951  {
952  	struct nfsd3_readdirres *resp = rqstp->rq_resp;
953  	struct xdr_buf *dirlist = &resp->dirlist;
954  
955  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
956  		return false;
957  	switch (resp->status) {
958  	case nfs_ok:
959  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
960  			return false;
961  		if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
962  			return false;
963  		svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0,
964  					   dirlist->len);
965  		/* no more entries */
966  		if (xdr_stream_encode_item_absent(xdr) < 0)
967  			return false;
968  		if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
969  			return false;
970  		break;
971  	default:
972  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
973  			return false;
974  	}
975  
976  	return true;
977  }
978  
979  static __be32
compose_entry_fh(struct nfsd3_readdirres * cd,struct svc_fh * fhp,const char * name,int namlen,u64 ino)980  compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
981  		 const char *name, int namlen, u64 ino)
982  {
983  	struct svc_export	*exp;
984  	struct dentry		*dparent, *dchild;
985  	__be32 rv = nfserr_noent;
986  
987  	dparent = cd->fh.fh_dentry;
988  	exp  = cd->fh.fh_export;
989  
990  	if (isdotent(name, namlen)) {
991  		if (namlen == 2) {
992  			dchild = dget_parent(dparent);
993  			/*
994  			 * Don't return filehandle for ".." if we're at
995  			 * the filesystem or export root:
996  			 */
997  			if (dchild == dparent)
998  				goto out;
999  			if (dparent == exp->ex_path.dentry)
1000  				goto out;
1001  		} else
1002  			dchild = dget(dparent);
1003  	} else
1004  		dchild = lookup_positive_unlocked(name, dparent, namlen);
1005  	if (IS_ERR(dchild))
1006  		return rv;
1007  	if (d_mountpoint(dchild))
1008  		goto out;
1009  	if (dchild->d_inode->i_ino != ino)
1010  		goto out;
1011  	rv = fh_compose(fhp, exp, dchild, &cd->fh);
1012  out:
1013  	dput(dchild);
1014  	return rv;
1015  }
1016  
1017  /**
1018   * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1019   * @resp: readdir result context
1020   * @offset: offset cookie to encode
1021   *
1022   * The buffer space for the offset cookie has already been reserved
1023   * by svcxdr_encode_entry3_common().
1024   */
nfs3svc_encode_cookie3(struct nfsd3_readdirres * resp,u64 offset)1025  void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset)
1026  {
1027  	__be64 cookie = cpu_to_be64(offset);
1028  
1029  	if (!resp->cookie_offset)
1030  		return;
1031  	write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
1032  			       sizeof(cookie));
1033  	resp->cookie_offset = 0;
1034  }
1035  
1036  static bool
svcxdr_encode_entry3_common(struct nfsd3_readdirres * resp,const char * name,int namlen,loff_t offset,u64 ino)1037  svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name,
1038  			    int namlen, loff_t offset, u64 ino)
1039  {
1040  	struct xdr_buf *dirlist = &resp->dirlist;
1041  	struct xdr_stream *xdr = &resp->xdr;
1042  
1043  	if (xdr_stream_encode_item_present(xdr) < 0)
1044  		return false;
1045  	/* fileid */
1046  	if (xdr_stream_encode_u64(xdr, ino) < 0)
1047  		return false;
1048  	/* name */
1049  	if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0)
1050  		return false;
1051  	/* cookie */
1052  	resp->cookie_offset = dirlist->len;
1053  	if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0)
1054  		return false;
1055  
1056  	return true;
1057  }
1058  
1059  /**
1060   * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1061   * @data: directory context
1062   * @name: name of the object to be encoded
1063   * @namlen: length of that name, in bytes
1064   * @offset: the offset of the previous entry
1065   * @ino: the fileid of this entry
1066   * @d_type: unused
1067   *
1068   * Return values:
1069   *   %0: Entry was successfully encoded.
1070   *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1071   *
1072   * On exit, the following fields are updated:
1073   *   - resp->xdr
1074   *   - resp->common.err
1075   *   - resp->cookie_offset
1076   */
nfs3svc_encode_entry3(void * data,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)1077  int nfs3svc_encode_entry3(void *data, const char *name, int namlen,
1078  			  loff_t offset, u64 ino, unsigned int d_type)
1079  {
1080  	struct readdir_cd *ccd = data;
1081  	struct nfsd3_readdirres *resp = container_of(ccd,
1082  						     struct nfsd3_readdirres,
1083  						     common);
1084  	unsigned int starting_length = resp->dirlist.len;
1085  
1086  	/* The offset cookie for the previous entry */
1087  	nfs3svc_encode_cookie3(resp, offset);
1088  
1089  	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1090  		goto out_toosmall;
1091  
1092  	xdr_commit_encode(&resp->xdr);
1093  	resp->common.err = nfs_ok;
1094  	return 0;
1095  
1096  out_toosmall:
1097  	resp->cookie_offset = 0;
1098  	resp->common.err = nfserr_toosmall;
1099  	resp->dirlist.len = starting_length;
1100  	return -EINVAL;
1101  }
1102  
1103  static bool
svcxdr_encode_entry3_plus(struct nfsd3_readdirres * resp,const char * name,int namlen,u64 ino)1104  svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name,
1105  			  int namlen, u64 ino)
1106  {
1107  	struct xdr_stream *xdr = &resp->xdr;
1108  	struct svc_fh *fhp = &resp->scratch;
1109  	bool result;
1110  
1111  	result = false;
1112  	fh_init(fhp, NFS3_FHSIZE);
1113  	if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok)
1114  		goto out_noattrs;
1115  
1116  	if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp))
1117  		goto out;
1118  	if (!svcxdr_encode_post_op_fh3(xdr, fhp))
1119  		goto out;
1120  	result = true;
1121  
1122  out:
1123  	fh_put(fhp);
1124  	return result;
1125  
1126  out_noattrs:
1127  	if (xdr_stream_encode_item_absent(xdr) < 0)
1128  		return false;
1129  	if (xdr_stream_encode_item_absent(xdr) < 0)
1130  		return false;
1131  	return true;
1132  }
1133  
1134  /**
1135   * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1136   * @data: directory context
1137   * @name: name of the object to be encoded
1138   * @namlen: length of that name, in bytes
1139   * @offset: the offset of the previous entry
1140   * @ino: the fileid of this entry
1141   * @d_type: unused
1142   *
1143   * Return values:
1144   *   %0: Entry was successfully encoded.
1145   *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1146   *
1147   * On exit, the following fields are updated:
1148   *   - resp->xdr
1149   *   - resp->common.err
1150   *   - resp->cookie_offset
1151   */
nfs3svc_encode_entryplus3(void * data,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)1152  int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,
1153  			      loff_t offset, u64 ino, unsigned int d_type)
1154  {
1155  	struct readdir_cd *ccd = data;
1156  	struct nfsd3_readdirres *resp = container_of(ccd,
1157  						     struct nfsd3_readdirres,
1158  						     common);
1159  	unsigned int starting_length = resp->dirlist.len;
1160  
1161  	/* The offset cookie for the previous entry */
1162  	nfs3svc_encode_cookie3(resp, offset);
1163  
1164  	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1165  		goto out_toosmall;
1166  	if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino))
1167  		goto out_toosmall;
1168  
1169  	xdr_commit_encode(&resp->xdr);
1170  	resp->common.err = nfs_ok;
1171  	return 0;
1172  
1173  out_toosmall:
1174  	resp->cookie_offset = 0;
1175  	resp->common.err = nfserr_toosmall;
1176  	resp->dirlist.len = starting_length;
1177  	return -EINVAL;
1178  }
1179  
1180  static bool
svcxdr_encode_fsstat3resok(struct xdr_stream * xdr,const struct nfsd3_fsstatres * resp)1181  svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
1182  			   const struct nfsd3_fsstatres *resp)
1183  {
1184  	const struct kstatfs *s = &resp->stats;
1185  	u64 bs = s->f_bsize;
1186  	__be32 *p;
1187  
1188  	p = xdr_reserve_space(xdr, XDR_UNIT * 13);
1189  	if (!p)
1190  		return false;
1191  	p = xdr_encode_hyper(p, bs * s->f_blocks);	/* total bytes */
1192  	p = xdr_encode_hyper(p, bs * s->f_bfree);	/* free bytes */
1193  	p = xdr_encode_hyper(p, bs * s->f_bavail);	/* user available bytes */
1194  	p = xdr_encode_hyper(p, s->f_files);		/* total inodes */
1195  	p = xdr_encode_hyper(p, s->f_ffree);		/* free inodes */
1196  	p = xdr_encode_hyper(p, s->f_ffree);		/* user available inodes */
1197  	*p = cpu_to_be32(resp->invarsec);		/* mean unchanged time */
1198  
1199  	return true;
1200  }
1201  
1202  /* FSSTAT */
1203  bool
nfs3svc_encode_fsstatres(struct svc_rqst * rqstp,struct xdr_stream * xdr)1204  nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1205  {
1206  	struct nfsd3_fsstatres *resp = rqstp->rq_resp;
1207  
1208  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1209  		return false;
1210  	switch (resp->status) {
1211  	case nfs_ok:
1212  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1213  			return false;
1214  		if (!svcxdr_encode_fsstat3resok(xdr, resp))
1215  			return false;
1216  		break;
1217  	default:
1218  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1219  			return false;
1220  	}
1221  
1222  	return true;
1223  }
1224  
1225  static bool
svcxdr_encode_fsinfo3resok(struct xdr_stream * xdr,const struct nfsd3_fsinfores * resp)1226  svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
1227  			   const struct nfsd3_fsinfores *resp)
1228  {
1229  	__be32 *p;
1230  
1231  	p = xdr_reserve_space(xdr, XDR_UNIT * 12);
1232  	if (!p)
1233  		return false;
1234  	*p++ = cpu_to_be32(resp->f_rtmax);
1235  	*p++ = cpu_to_be32(resp->f_rtpref);
1236  	*p++ = cpu_to_be32(resp->f_rtmult);
1237  	*p++ = cpu_to_be32(resp->f_wtmax);
1238  	*p++ = cpu_to_be32(resp->f_wtpref);
1239  	*p++ = cpu_to_be32(resp->f_wtmult);
1240  	*p++ = cpu_to_be32(resp->f_dtpref);
1241  	p = xdr_encode_hyper(p, resp->f_maxfilesize);
1242  	p = encode_nfstime3(p, &nfs3svc_time_delta);
1243  	*p = cpu_to_be32(resp->f_properties);
1244  
1245  	return true;
1246  }
1247  
1248  /* FSINFO */
1249  bool
nfs3svc_encode_fsinfores(struct svc_rqst * rqstp,struct xdr_stream * xdr)1250  nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1251  {
1252  	struct nfsd3_fsinfores *resp = rqstp->rq_resp;
1253  
1254  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1255  		return false;
1256  	switch (resp->status) {
1257  	case nfs_ok:
1258  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1259  			return false;
1260  		if (!svcxdr_encode_fsinfo3resok(xdr, resp))
1261  			return false;
1262  		break;
1263  	default:
1264  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1265  			return false;
1266  	}
1267  
1268  	return true;
1269  }
1270  
1271  static bool
svcxdr_encode_pathconf3resok(struct xdr_stream * xdr,const struct nfsd3_pathconfres * resp)1272  svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
1273  			     const struct nfsd3_pathconfres *resp)
1274  {
1275  	__be32 *p;
1276  
1277  	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
1278  	if (!p)
1279  		return false;
1280  	*p++ = cpu_to_be32(resp->p_link_max);
1281  	*p++ = cpu_to_be32(resp->p_name_max);
1282  	p = xdr_encode_bool(p, resp->p_no_trunc);
1283  	p = xdr_encode_bool(p, resp->p_chown_restricted);
1284  	p = xdr_encode_bool(p, resp->p_case_insensitive);
1285  	xdr_encode_bool(p, resp->p_case_preserving);
1286  
1287  	return true;
1288  }
1289  
1290  /* PATHCONF */
1291  bool
nfs3svc_encode_pathconfres(struct svc_rqst * rqstp,struct xdr_stream * xdr)1292  nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1293  {
1294  	struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1295  
1296  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1297  		return false;
1298  	switch (resp->status) {
1299  	case nfs_ok:
1300  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1301  			return false;
1302  		if (!svcxdr_encode_pathconf3resok(xdr, resp))
1303  			return false;
1304  		break;
1305  	default:
1306  		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1307  			return false;
1308  	}
1309  
1310  	return true;
1311  }
1312  
1313  /* COMMIT */
1314  bool
nfs3svc_encode_commitres(struct svc_rqst * rqstp,struct xdr_stream * xdr)1315  nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1316  {
1317  	struct nfsd3_commitres *resp = rqstp->rq_resp;
1318  
1319  	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1320  		return false;
1321  	switch (resp->status) {
1322  	case nfs_ok:
1323  		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1324  			return false;
1325  		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
1326  			return false;
1327  		break;
1328  	default:
1329  		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1330  			return false;
1331  	}
1332  
1333  	return true;
1334  }
1335  
1336  /*
1337   * XDR release functions
1338   */
1339  void
nfs3svc_release_fhandle(struct svc_rqst * rqstp)1340  nfs3svc_release_fhandle(struct svc_rqst *rqstp)
1341  {
1342  	struct nfsd3_attrstat *resp = rqstp->rq_resp;
1343  
1344  	fh_put(&resp->fh);
1345  }
1346  
1347  void
nfs3svc_release_fhandle2(struct svc_rqst * rqstp)1348  nfs3svc_release_fhandle2(struct svc_rqst *rqstp)
1349  {
1350  	struct nfsd3_fhandle_pair *resp = rqstp->rq_resp;
1351  
1352  	fh_put(&resp->fh1);
1353  	fh_put(&resp->fh2);
1354  }
1355