~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/nfsd/nfs3xdr.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 *
 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
 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
 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  */
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
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  */
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
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  */
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
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
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
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
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
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
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
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
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
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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php