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

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

Version: ~ [ linux-4.20-rc2 ] ~ [ linux-4.19.1 ] ~ [ linux-4.18.18 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.80 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.136 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.163 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.125 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.60 ] ~ [ 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.102 ] ~ [ 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.31.14 ] ~ [ linux-2.6.30.10 ] ~ [ linux-2.6.29.6 ] ~ [ linux-2.6.28.10 ] ~ [ 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         struct timespec ts;
358         __be32 *p;
359 
360         p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
361 
362         if (attr->ia_valid & ATTR_MODE)
363                 *p++ = cpu_to_be32(attr->ia_mode);
364         else
365                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
366         if (attr->ia_valid & ATTR_UID)
367                 *p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
368         else
369                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
370         if (attr->ia_valid & ATTR_GID)
371                 *p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
372         else
373                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
374         if (attr->ia_valid & ATTR_SIZE)
375                 *p++ = cpu_to_be32((u32)attr->ia_size);
376         else
377                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
378 
379         if (attr->ia_valid & ATTR_ATIME_SET) {
380                 ts = timespec64_to_timespec(attr->ia_atime);
381                 p = xdr_encode_time(p, &ts);
382         } else if (attr->ia_valid & ATTR_ATIME) {
383                 ts = timespec64_to_timespec(attr->ia_atime);
384                 p = xdr_encode_current_server_time(p, &ts);
385         } else
386                 p = xdr_time_not_set(p);
387         if (attr->ia_valid & ATTR_MTIME_SET) {
388                 ts = timespec64_to_timespec(attr->ia_atime);
389                 xdr_encode_time(p, &ts);
390         } else if (attr->ia_valid & ATTR_MTIME) {
391                 ts = timespec64_to_timespec(attr->ia_mtime);
392                 xdr_encode_current_server_time(p, &ts);
393         } else
394                 xdr_time_not_set(p);
395 }
396 
397 /*
398  * 2.3.7.  filename
399  *
400  *      typedef string filename<MAXNAMLEN>;
401  */
402 static void encode_filename(struct xdr_stream *xdr,
403                             const char *name, u32 length)
404 {
405         __be32 *p;
406 
407         WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
408         p = xdr_reserve_space(xdr, 4 + length);
409         xdr_encode_opaque(p, name, length);
410 }
411 
412 static int decode_filename_inline(struct xdr_stream *xdr,
413                                   const char **name, u32 *length)
414 {
415         __be32 *p;
416         u32 count;
417 
418         p = xdr_inline_decode(xdr, 4);
419         if (unlikely(p == NULL))
420                 goto out_overflow;
421         count = be32_to_cpup(p);
422         if (count > NFS3_MAXNAMLEN)
423                 goto out_nametoolong;
424         p = xdr_inline_decode(xdr, count);
425         if (unlikely(p == NULL))
426                 goto out_overflow;
427         *name = (const char *)p;
428         *length = count;
429         return 0;
430 out_nametoolong:
431         dprintk("NFS: returned filename too long: %u\n", count);
432         return -ENAMETOOLONG;
433 out_overflow:
434         print_overflow_msg(__func__, xdr);
435         return -EIO;
436 }
437 
438 /*
439  * 2.3.8.  path
440  *
441  *      typedef string path<MAXPATHLEN>;
442  */
443 static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
444 {
445         __be32 *p;
446 
447         p = xdr_reserve_space(xdr, 4);
448         *p = cpu_to_be32(length);
449         xdr_write_pages(xdr, pages, 0, length);
450 }
451 
452 static int decode_path(struct xdr_stream *xdr)
453 {
454         u32 length, recvd;
455         __be32 *p;
456 
457         p = xdr_inline_decode(xdr, 4);
458         if (unlikely(p == NULL))
459                 goto out_overflow;
460         length = be32_to_cpup(p);
461         if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
462                 goto out_size;
463         recvd = xdr_read_pages(xdr, length);
464         if (unlikely(length > recvd))
465                 goto out_cheating;
466         xdr_terminate_string(xdr->buf, length);
467         return 0;
468 out_size:
469         dprintk("NFS: returned pathname too long: %u\n", length);
470         return -ENAMETOOLONG;
471 out_cheating:
472         dprintk("NFS: server cheating in pathname result: "
473                 "length %u > received %u\n", length, recvd);
474         return -EIO;
475 out_overflow:
476         print_overflow_msg(__func__, xdr);
477         return -EIO;
478 }
479 
480 /*
481  * 2.3.9.  attrstat
482  *
483  *      union attrstat switch (stat status) {
484  *      case NFS_OK:
485  *              fattr attributes;
486  *      default:
487  *              void;
488  *      };
489  */
490 static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result,
491                            __u32 *op_status)
492 {
493         enum nfs_stat status;
494         int error;
495 
496         error = decode_stat(xdr, &status);
497         if (unlikely(error))
498                 goto out;
499         if (op_status)
500                 *op_status = status;
501         if (status != NFS_OK)
502                 goto out_default;
503         error = decode_fattr(xdr, result);
504 out:
505         return error;
506 out_default:
507         return nfs_stat_to_errno(status);
508 }
509 
510 /*
511  * 2.3.10.  diropargs
512  *
513  *      struct diropargs {
514  *              fhandle  dir;
515  *              filename name;
516  *      };
517  */
518 static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
519                              const char *name, u32 length)
520 {
521         encode_fhandle(xdr, fh);
522         encode_filename(xdr, name, length);
523 }
524 
525 /*
526  * 2.3.11.  diropres
527  *
528  *      union diropres switch (stat status) {
529  *      case NFS_OK:
530  *              struct {
531  *                      fhandle file;
532  *                      fattr   attributes;
533  *              } diropok;
534  *      default:
535  *              void;
536  *      };
537  */
538 static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result)
539 {
540         int error;
541 
542         error = decode_fhandle(xdr, result->fh);
543         if (unlikely(error))
544                 goto out;
545         error = decode_fattr(xdr, result->fattr);
546 out:
547         return error;
548 }
549 
550 static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result)
551 {
552         enum nfs_stat status;
553         int error;
554 
555         error = decode_stat(xdr, &status);
556         if (unlikely(error))
557                 goto out;
558         if (status != NFS_OK)
559                 goto out_default;
560         error = decode_diropok(xdr, result);
561 out:
562         return error;
563 out_default:
564         return nfs_stat_to_errno(status);
565 }
566 
567 
568 /*
569  * NFSv2 XDR encode functions
570  *
571  * NFSv2 argument types are defined in section 2.2 of RFC 1094:
572  * "NFS: Network File System Protocol Specification".
573  */
574 
575 static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req,
576                                  struct xdr_stream *xdr,
577                                  const void *data)
578 {
579         const struct nfs_fh *fh = data;
580 
581         encode_fhandle(xdr, fh);
582 }
583 
584 /*
585  * 2.2.3.  sattrargs
586  *
587  *      struct sattrargs {
588  *              fhandle file;
589  *              sattr attributes;
590  *      };
591  */
592 static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
593                                    struct xdr_stream *xdr,
594                                    const void *data)
595 {
596         const struct nfs_sattrargs *args = data;
597 
598         encode_fhandle(xdr, args->fh);
599         encode_sattr(xdr, args->sattr);
600 }
601 
602 static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
603                                    struct xdr_stream *xdr,
604                                    const void *data)
605 {
606         const struct nfs_diropargs *args = data;
607 
608         encode_diropargs(xdr, args->fh, args->name, args->len);
609 }
610 
611 static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
612                                       struct xdr_stream *xdr,
613                                       const void *data)
614 {
615         const struct nfs_readlinkargs *args = data;
616 
617         encode_fhandle(xdr, args->fh);
618         prepare_reply_buffer(req, args->pages, args->pgbase,
619                                         args->pglen, NFS_readlinkres_sz);
620 }
621 
622 /*
623  * 2.2.7.  readargs
624  *
625  *      struct readargs {
626  *              fhandle file;
627  *              unsigned offset;
628  *              unsigned count;
629  *              unsigned totalcount;
630  *      };
631  */
632 static void encode_readargs(struct xdr_stream *xdr,
633                             const struct nfs_pgio_args *args)
634 {
635         u32 offset = args->offset;
636         u32 count = args->count;
637         __be32 *p;
638 
639         encode_fhandle(xdr, args->fh);
640 
641         p = xdr_reserve_space(xdr, 4 + 4 + 4);
642         *p++ = cpu_to_be32(offset);
643         *p++ = cpu_to_be32(count);
644         *p = cpu_to_be32(count);
645 }
646 
647 static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
648                                   struct xdr_stream *xdr,
649                                   const void *data)
650 {
651         const struct nfs_pgio_args *args = data;
652 
653         encode_readargs(xdr, args);
654         prepare_reply_buffer(req, args->pages, args->pgbase,
655                                         args->count, NFS_readres_sz);
656         req->rq_rcv_buf.flags |= XDRBUF_READ;
657 }
658 
659 /*
660  * 2.2.9.  writeargs
661  *
662  *      struct writeargs {
663  *              fhandle file;
664  *              unsigned beginoffset;
665  *              unsigned offset;
666  *              unsigned totalcount;
667  *              nfsdata data;
668  *      };
669  */
670 static void encode_writeargs(struct xdr_stream *xdr,
671                              const struct nfs_pgio_args *args)
672 {
673         u32 offset = args->offset;
674         u32 count = args->count;
675         __be32 *p;
676 
677         encode_fhandle(xdr, args->fh);
678 
679         p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
680         *p++ = cpu_to_be32(offset);
681         *p++ = cpu_to_be32(offset);
682         *p++ = cpu_to_be32(count);
683 
684         /* nfsdata */
685         *p = cpu_to_be32(count);
686         xdr_write_pages(xdr, args->pages, args->pgbase, count);
687 }
688 
689 static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
690                                    struct xdr_stream *xdr,
691                                    const void *data)
692 {
693         const struct nfs_pgio_args *args = data;
694 
695         encode_writeargs(xdr, args);
696         xdr->buf->flags |= XDRBUF_WRITE;
697 }
698 
699 /*
700  * 2.2.10.  createargs
701  *
702  *      struct createargs {
703  *              diropargs where;
704  *              sattr attributes;
705  *      };
706  */
707 static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
708                                     struct xdr_stream *xdr,
709                                     const void *data)
710 {
711         const struct nfs_createargs *args = data;
712 
713         encode_diropargs(xdr, args->fh, args->name, args->len);
714         encode_sattr(xdr, args->sattr);
715 }
716 
717 static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
718                                     struct xdr_stream *xdr,
719                                     const void *data)
720 {
721         const struct nfs_removeargs *args = data;
722 
723         encode_diropargs(xdr, args->fh, args->name.name, args->name.len);
724 }
725 
726 /*
727  * 2.2.12.  renameargs
728  *
729  *      struct renameargs {
730  *              diropargs from;
731  *              diropargs to;
732  *      };
733  */
734 static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req,
735                                     struct xdr_stream *xdr,
736                                     const void *data)
737 {
738         const struct nfs_renameargs *args = data;
739         const struct qstr *old = args->old_name;
740         const struct qstr *new = args->new_name;
741 
742         encode_diropargs(xdr, args->old_dir, old->name, old->len);
743         encode_diropargs(xdr, args->new_dir, new->name, new->len);
744 }
745 
746 /*
747  * 2.2.13.  linkargs
748  *
749  *      struct linkargs {
750  *              fhandle from;
751  *              diropargs to;
752  *      };
753  */
754 static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req,
755                                   struct xdr_stream *xdr,
756                                   const void *data)
757 {
758         const struct nfs_linkargs *args = data;
759 
760         encode_fhandle(xdr, args->fromfh);
761         encode_diropargs(xdr, args->tofh, args->toname, args->tolen);
762 }
763 
764 /*
765  * 2.2.14.  symlinkargs
766  *
767  *      struct symlinkargs {
768  *              diropargs from;
769  *              path to;
770  *              sattr attributes;
771  *      };
772  */
773 static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
774                                      struct xdr_stream *xdr,
775                                      const void *data)
776 {
777         const struct nfs_symlinkargs *args = data;
778 
779         encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
780         encode_path(xdr, args->pages, args->pathlen);
781         encode_sattr(xdr, args->sattr);
782 }
783 
784 /*
785  * 2.2.17.  readdirargs
786  *
787  *      struct readdirargs {
788  *              fhandle dir;
789  *              nfscookie cookie;
790  *              unsigned count;
791  *      };
792  */
793 static void encode_readdirargs(struct xdr_stream *xdr,
794                                const struct nfs_readdirargs *args)
795 {
796         __be32 *p;
797 
798         encode_fhandle(xdr, args->fh);
799 
800         p = xdr_reserve_space(xdr, 4 + 4);
801         *p++ = cpu_to_be32(args->cookie);
802         *p = cpu_to_be32(args->count);
803 }
804 
805 static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
806                                      struct xdr_stream *xdr,
807                                      const void *data)
808 {
809         const struct nfs_readdirargs *args = data;
810 
811         encode_readdirargs(xdr, args);
812         prepare_reply_buffer(req, args->pages, 0,
813                                         args->count, NFS_readdirres_sz);
814 }
815 
816 /*
817  * NFSv2 XDR decode functions
818  *
819  * NFSv2 result types are defined in section 2.2 of RFC 1094:
820  * "NFS: Network File System Protocol Specification".
821  */
822 
823 static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
824                              void *__unused)
825 {
826         enum nfs_stat status;
827         int error;
828 
829         error = decode_stat(xdr, &status);
830         if (unlikely(error))
831                 goto out;
832         if (status != NFS_OK)
833                 goto out_default;
834 out:
835         return error;
836 out_default:
837         return nfs_stat_to_errno(status);
838 }
839 
840 static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
841                                  void *result)
842 {
843         return decode_attrstat(xdr, result, NULL);
844 }
845 
846 static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
847                                  void *result)
848 {
849         return decode_diropres(xdr, result);
850 }
851 
852 /*
853  * 2.2.6.  readlinkres
854  *
855  *      union readlinkres switch (stat status) {
856  *      case NFS_OK:
857  *              path data;
858  *      default:
859  *              void;
860  *      };
861  */
862 static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req,
863                                     struct xdr_stream *xdr, void *__unused)
864 {
865         enum nfs_stat status;
866         int error;
867 
868         error = decode_stat(xdr, &status);
869         if (unlikely(error))
870                 goto out;
871         if (status != NFS_OK)
872                 goto out_default;
873         error = decode_path(xdr);
874 out:
875         return error;
876 out_default:
877         return nfs_stat_to_errno(status);
878 }
879 
880 /*
881  * 2.2.7.  readres
882  *
883  *      union readres switch (stat status) {
884  *      case NFS_OK:
885  *              fattr attributes;
886  *              nfsdata data;
887  *      default:
888  *              void;
889  *      };
890  */
891 static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
892                                 void *data)
893 {
894         struct nfs_pgio_res *result = data;
895         enum nfs_stat status;
896         int error;
897 
898         error = decode_stat(xdr, &status);
899         if (unlikely(error))
900                 goto out;
901         result->op_status = status;
902         if (status != NFS_OK)
903                 goto out_default;
904         error = decode_fattr(xdr, result->fattr);
905         if (unlikely(error))
906                 goto out;
907         error = decode_nfsdata(xdr, result);
908 out:
909         return error;
910 out_default:
911         return nfs_stat_to_errno(status);
912 }
913 
914 static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
915                                  void *data)
916 {
917         struct nfs_pgio_res *result = data;
918 
919         /* All NFSv2 writes are "file sync" writes */
920         result->verf->committed = NFS_FILE_SYNC;
921         return decode_attrstat(xdr, result->fattr, &result->op_status);
922 }
923 
924 /**
925  * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
926  *                      the local page cache.
927  * @xdr: XDR stream where entry resides
928  * @entry: buffer to fill in with entry data
929  * @plus: boolean indicating whether this should be a readdirplus entry
930  *
931  * Returns zero if successful, otherwise a negative errno value is
932  * returned.
933  *
934  * This function is not invoked during READDIR reply decoding, but
935  * rather whenever an application invokes the getdents(2) system call
936  * on a directory already in our cache.
937  *
938  * 2.2.17.  entry
939  *
940  *      struct entry {
941  *              unsigned        fileid;
942  *              filename        name;
943  *              nfscookie       cookie;
944  *              entry           *nextentry;
945  *      };
946  */
947 int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
948                        bool plus)
949 {
950         __be32 *p;
951         int error;
952 
953         p = xdr_inline_decode(xdr, 4);
954         if (unlikely(p == NULL))
955                 goto out_overflow;
956         if (*p++ == xdr_zero) {
957                 p = xdr_inline_decode(xdr, 4);
958                 if (unlikely(p == NULL))
959                         goto out_overflow;
960                 if (*p++ == xdr_zero)
961                         return -EAGAIN;
962                 entry->eof = 1;
963                 return -EBADCOOKIE;
964         }
965 
966         p = xdr_inline_decode(xdr, 4);
967         if (unlikely(p == NULL))
968                 goto out_overflow;
969         entry->ino = be32_to_cpup(p);
970 
971         error = decode_filename_inline(xdr, &entry->name, &entry->len);
972         if (unlikely(error))
973                 return error;
974 
975         /*
976          * The type (size and byte order) of nfscookie isn't defined in
977          * RFC 1094.  This implementation assumes that it's an XDR uint32.
978          */
979         entry->prev_cookie = entry->cookie;
980         p = xdr_inline_decode(xdr, 4);
981         if (unlikely(p == NULL))
982                 goto out_overflow;
983         entry->cookie = be32_to_cpup(p);
984 
985         entry->d_type = DT_UNKNOWN;
986 
987         return 0;
988 
989 out_overflow:
990         print_overflow_msg(__func__, xdr);
991         return -EAGAIN;
992 }
993 
994 /*
995  * 2.2.17.  readdirres
996  *
997  *      union readdirres switch (stat status) {
998  *      case NFS_OK:
999  *              struct {
1000  *                      entry *entries;
1001  *                      bool eof;
1002  *              } readdirok;
1003  *      default:
1004  *              void;
1005  *      };
1006  *
1007  * Read the directory contents into the page cache, but don't
1008  * touch them.  The actual decoding is done by nfs2_decode_dirent()
1009  * during subsequent nfs_readdir() calls.
1010  */
1011 static int decode_readdirok(struct xdr_stream *xdr)
1012 {
1013         return xdr_read_pages(xdr, xdr->buf->page_len);
1014 }
1015 
1016 static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
1017                                    struct xdr_stream *xdr, void *__unused)
1018 {
1019         enum nfs_stat status;
1020         int error;
1021 
1022         error = decode_stat(xdr, &status);
1023         if (unlikely(error))
1024                 goto out;
1025         if (status != NFS_OK)
1026                 goto out_default;
1027         error = decode_readdirok(xdr);
1028 out:
1029         return error;
1030 out_default:
1031         return nfs_stat_to_errno(status);
1032 }
1033 
1034 /*
1035  * 2.2.18.  statfsres
1036  *
1037  *      union statfsres (stat status) {
1038  *      case NFS_OK:
1039  *              struct {
1040  *                      unsigned tsize;
1041  *                      unsigned bsize;
1042  *                      unsigned blocks;
1043  *                      unsigned bfree;
1044  *                      unsigned bavail;
1045  *              } info;
1046  *      default:
1047  *              void;
1048  *      };
1049  */
1050 static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1051 {
1052         __be32 *p;
1053 
1054         p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1055         if (unlikely(p == NULL))
1056                 goto out_overflow;
1057         result->tsize  = be32_to_cpup(p++);
1058         result->bsize  = be32_to_cpup(p++);
1059         result->blocks = be32_to_cpup(p++);
1060         result->bfree  = be32_to_cpup(p++);
1061         result->bavail = be32_to_cpup(p);
1062         return 0;
1063 out_overflow:
1064         print_overflow_msg(__func__, xdr);
1065         return -EIO;
1066 }
1067 
1068 static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
1069                                   void *result)
1070 {
1071         enum nfs_stat status;
1072         int error;
1073 
1074         error = decode_stat(xdr, &status);
1075         if (unlikely(error))
1076                 goto out;
1077         if (status != NFS_OK)
1078                 goto out_default;
1079         error = decode_info(xdr, result);
1080 out:
1081         return error;
1082 out_default:
1083         return nfs_stat_to_errno(status);
1084 }
1085 
1086 
1087 /*
1088  * We need to translate between nfs status return values and
1089  * the local errno values which may not be the same.
1090  */
1091 static const struct {
1092         int stat;
1093         int errno;
1094 } nfs_errtbl[] = {
1095         { NFS_OK,               0               },
1096         { NFSERR_PERM,          -EPERM          },
1097         { NFSERR_NOENT,         -ENOENT         },
1098         { NFSERR_IO,            -errno_NFSERR_IO},
1099         { NFSERR_NXIO,          -ENXIO          },
1100 /*      { NFSERR_EAGAIN,        -EAGAIN         }, */
1101         { NFSERR_ACCES,         -EACCES         },
1102         { NFSERR_EXIST,         -EEXIST         },
1103         { NFSERR_XDEV,          -EXDEV          },
1104         { NFSERR_NODEV,         -ENODEV         },
1105         { NFSERR_NOTDIR,        -ENOTDIR        },
1106         { NFSERR_ISDIR,         -EISDIR         },
1107         { NFSERR_INVAL,         -EINVAL         },
1108         { NFSERR_FBIG,          -EFBIG          },
1109         { NFSERR_NOSPC,         -ENOSPC         },
1110         { NFSERR_ROFS,          -EROFS          },
1111         { NFSERR_MLINK,         -EMLINK         },
1112         { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
1113         { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
1114         { NFSERR_DQUOT,         -EDQUOT         },
1115         { NFSERR_STALE,         -ESTALE         },
1116         { NFSERR_REMOTE,        -EREMOTE        },
1117 #ifdef EWFLUSH
1118         { NFSERR_WFLUSH,        -EWFLUSH        },
1119 #endif
1120         { NFSERR_BADHANDLE,     -EBADHANDLE     },
1121         { NFSERR_NOT_SYNC,      -ENOTSYNC       },
1122         { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
1123         { NFSERR_NOTSUPP,       -ENOTSUPP       },
1124         { NFSERR_TOOSMALL,      -ETOOSMALL      },
1125         { NFSERR_SERVERFAULT,   -EREMOTEIO      },
1126         { NFSERR_BADTYPE,       -EBADTYPE       },
1127         { NFSERR_JUKEBOX,       -EJUKEBOX       },
1128         { -1,                   -EIO            }
1129 };
1130 
1131 /**
1132  * nfs_stat_to_errno - convert an NFS status code to a local errno
1133  * @status: NFS status code to convert
1134  *
1135  * Returns a local errno value, or -EIO if the NFS status code is
1136  * not recognized.  This function is used jointly by NFSv2 and NFSv3.
1137  */
1138 static int nfs_stat_to_errno(enum nfs_stat status)
1139 {
1140         int i;
1141 
1142         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1143                 if (nfs_errtbl[i].stat == (int)status)
1144                         return nfs_errtbl[i].errno;
1145         }
1146         dprintk("NFS: Unrecognized nfs status value: %u\n", status);
1147         return nfs_errtbl[i].errno;
1148 }
1149 
1150 #define PROC(proc, argtype, restype, timer)                             \
1151 [NFSPROC_##proc] = {                                                    \
1152         .p_proc     =  NFSPROC_##proc,                                  \
1153         .p_encode   =  nfs2_xdr_enc_##argtype,                          \
1154         .p_decode   =  nfs2_xdr_dec_##restype,                          \
1155         .p_arglen   =  NFS_##argtype##_sz,                              \
1156         .p_replen   =  NFS_##restype##_sz,                              \
1157         .p_timer    =  timer,                                           \
1158         .p_statidx  =  NFSPROC_##proc,                                  \
1159         .p_name     =  #proc,                                           \
1160         }
1161 const struct rpc_procinfo nfs_procedures[] = {
1162         PROC(GETATTR,   fhandle,        attrstat,       1),
1163         PROC(SETATTR,   sattrargs,      attrstat,       0),
1164         PROC(LOOKUP,    diropargs,      diropres,       2),
1165         PROC(READLINK,  readlinkargs,   readlinkres,    3),
1166         PROC(READ,      readargs,       readres,        3),
1167         PROC(WRITE,     writeargs,      writeres,       4),
1168         PROC(CREATE,    createargs,     diropres,       0),
1169         PROC(REMOVE,    removeargs,     stat,           0),
1170         PROC(RENAME,    renameargs,     stat,           0),
1171         PROC(LINK,      linkargs,       stat,           0),
1172         PROC(SYMLINK,   symlinkargs,    stat,           0),
1173         PROC(MKDIR,     createargs,     diropres,       0),
1174         PROC(RMDIR,     diropargs,      stat,           0),
1175         PROC(READDIR,   readdirargs,    readdirres,     3),
1176         PROC(STATFS,    fhandle,        statfsres,      0),
1177 };
1178 
1179 static unsigned int nfs_version2_counts[ARRAY_SIZE(nfs_procedures)];
1180 const struct rpc_version nfs_version2 = {
1181         .number                 = 2,
1182         .nrprocs                = ARRAY_SIZE(nfs_procedures),
1183         .procs                  = nfs_procedures,
1184         .counts                 = nfs_version2_counts,
1185 };
1186 

~ [ 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