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

TOMOYO Linux Cross Reference
Linux/fs/nfs/nfs2xdr.c

Version: ~ [ linux-4.17-rc2 ] ~ [ linux-4.16.4 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.36 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.96 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.129 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.51 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.106 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.56 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.101 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.27.62 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp