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