aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs3xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs3xdr.c')
-rw-r--r--fs/nfs/nfs3xdr.c2811
1 files changed, 2050 insertions, 761 deletions
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index ba91236c6ee7..01c5e8b1941d 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -37,18 +37,16 @@
37#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) 37#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
38#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) 38#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
39#define NFS3_fattr_sz (21) 39#define NFS3_fattr_sz (21)
40#define NFS3_wcc_attr_sz (6) 40#define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2)
41#define NFS3_wcc_attr_sz (6)
41#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz) 42#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
42#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz) 43#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
43#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz) 44#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
44#define NFS3_fsstat_sz
45#define NFS3_fsinfo_sz
46#define NFS3_pathconf_sz
47#define NFS3_entry_sz (NFS3_filename_sz+3)
48
49#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
50#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz) 45#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
51#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz) 46
47#define NFS3_getattrargs_sz (NFS3_fh_sz)
48#define NFS3_setattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
49#define NFS3_lookupargs_sz (NFS3_fh_sz+NFS3_filename_sz)
52#define NFS3_accessargs_sz (NFS3_fh_sz+1) 50#define NFS3_accessargs_sz (NFS3_fh_sz+1)
53#define NFS3_readlinkargs_sz (NFS3_fh_sz) 51#define NFS3_readlinkargs_sz (NFS3_fh_sz)
54#define NFS3_readargs_sz (NFS3_fh_sz+3) 52#define NFS3_readargs_sz (NFS3_fh_sz+3)
@@ -57,14 +55,16 @@
57#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) 55#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
58#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz) 56#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
59#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) 57#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
58#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
60#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) 59#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
61#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) 60#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
62#define NFS3_readdirargs_sz (NFS3_fh_sz+2) 61#define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
62#define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
63#define NFS3_commitargs_sz (NFS3_fh_sz+3) 63#define NFS3_commitargs_sz (NFS3_fh_sz+3)
64 64
65#define NFS3_attrstat_sz (1+NFS3_fattr_sz) 65#define NFS3_getattrres_sz (1+NFS3_fattr_sz)
66#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz) 66#define NFS3_setattrres_sz (1+NFS3_wcc_data_sz)
67#define NFS3_removeres_sz (NFS3_wccstat_sz) 67#define NFS3_removeres_sz (NFS3_setattrres_sz)
68#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) 68#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
69#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) 69#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
70#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) 70#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
@@ -100,1073 +100,2362 @@ static const umode_t nfs_type2fmt[] = {
100 [NF3FIFO] = S_IFIFO, 100 [NF3FIFO] = S_IFIFO,
101}; 101};
102 102
103/*
104 * While encoding arguments, set up the reply buffer in advance to
105 * receive reply data directly into the page cache.
106 */
107static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
108 unsigned int base, unsigned int len,
109 unsigned int bufsize)
110{
111 struct rpc_auth *auth = req->rq_cred->cr_auth;
112 unsigned int replen;
113
114 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
115 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
116}
117
118/*
119 * Handle decode buffer overflows out-of-line.
120 */
103static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 121static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
104{ 122{
105 dprintk("nfs: %s: prematurely hit end of receive buffer. " 123 dprintk("NFS: %s prematurely hit the end of our receive buffer. "
106 "Remaining buffer length is %tu words.\n", 124 "Remaining buffer length is %tu words.\n",
107 func, xdr->end - xdr->p); 125 func, xdr->end - xdr->p);
108} 126}
109 127
128
110/* 129/*
111 * Common NFS XDR functions as inlines 130 * Encode/decode NFSv3 basic data types
131 *
132 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
133 * "NFS Version 3 Protocol Specification".
134 *
135 * Not all basic data types have their own encoding and decoding
136 * functions. For run-time efficiency, some data types are encoded
137 * or decoded inline.
112 */ 138 */
113static inline __be32 * 139
114xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh) 140static void encode_uint32(struct xdr_stream *xdr, u32 value)
115{ 141{
116 return xdr_encode_array(p, fh->data, fh->size); 142 __be32 *p = xdr_reserve_space(xdr, 4);
143 *p = cpu_to_be32(value);
117} 144}
118 145
119static inline __be32 * 146static int decode_uint32(struct xdr_stream *xdr, u32 *value)
120xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
121{ 147{
122 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) { 148 __be32 *p;
123 memcpy(fh->data, p, fh->size); 149
124 return p + XDR_QUADLEN(fh->size); 150 p = xdr_inline_decode(xdr, 4);
125 } 151 if (unlikely(p == NULL))
126 return NULL; 152 goto out_overflow;
153 *value = be32_to_cpup(p);
154 return 0;
155out_overflow:
156 print_overflow_msg(__func__, xdr);
157 return -EIO;
158}
159
160static int decode_uint64(struct xdr_stream *xdr, u64 *value)
161{
162 __be32 *p;
163
164 p = xdr_inline_decode(xdr, 8);
165 if (unlikely(p == NULL))
166 goto out_overflow;
167 xdr_decode_hyper(p, value);
168 return 0;
169out_overflow:
170 print_overflow_msg(__func__, xdr);
171 return -EIO;
172}
173
174/*
175 * fileid3
176 *
177 * typedef uint64 fileid3;
178 */
179static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid)
180{
181 return xdr_decode_hyper(p, fileid);
182}
183
184static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
185{
186 return decode_uint64(xdr, fileid);
187}
188
189/*
190 * filename3
191 *
192 * typedef string filename3<>;
193 */
194static void encode_filename3(struct xdr_stream *xdr,
195 const char *name, u32 length)
196{
197 __be32 *p;
198
199 BUG_ON(length > NFS3_MAXNAMLEN);
200 p = xdr_reserve_space(xdr, 4 + length);
201 xdr_encode_opaque(p, name, length);
127} 202}
128 203
129static inline __be32 * 204static int decode_inline_filename3(struct xdr_stream *xdr,
130xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh) 205 const char **name, u32 *length)
131{ 206{
132 __be32 *p; 207 __be32 *p;
208 u32 count;
209
133 p = xdr_inline_decode(xdr, 4); 210 p = xdr_inline_decode(xdr, 4);
134 if (unlikely(!p)) 211 if (unlikely(p == NULL))
212 goto out_overflow;
213 count = be32_to_cpup(p);
214 if (count > NFS3_MAXNAMLEN)
215 goto out_nametoolong;
216 p = xdr_inline_decode(xdr, count);
217 if (unlikely(p == NULL))
135 goto out_overflow; 218 goto out_overflow;
136 fh->size = ntohl(*p++); 219 *name = (const char *)p;
220 *length = count;
221 return 0;
137 222
138 if (fh->size <= NFS3_FHSIZE) { 223out_nametoolong:
139 p = xdr_inline_decode(xdr, fh->size); 224 dprintk("NFS: returned filename too long: %u\n", count);
140 if (unlikely(!p)) 225 return -ENAMETOOLONG;
141 goto out_overflow; 226out_overflow:
142 memcpy(fh->data, p, fh->size); 227 print_overflow_msg(__func__, xdr);
143 return p + XDR_QUADLEN(fh->size); 228 return -EIO;
144 } 229}
145 return NULL; 230
231/*
232 * nfspath3
233 *
234 * typedef string nfspath3<>;
235 */
236static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
237 const u32 length)
238{
239 BUG_ON(length > NFS3_MAXPATHLEN);
240 encode_uint32(xdr, length);
241 xdr_write_pages(xdr, pages, 0, length);
242}
146 243
244static int decode_nfspath3(struct xdr_stream *xdr)
245{
246 u32 recvd, count;
247 size_t hdrlen;
248 __be32 *p;
249
250 p = xdr_inline_decode(xdr, 4);
251 if (unlikely(p == NULL))
252 goto out_overflow;
253 count = be32_to_cpup(p);
254 if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
255 goto out_nametoolong;
256 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
257 recvd = xdr->buf->len - hdrlen;
258 if (unlikely(count > recvd))
259 goto out_cheating;
260
261 xdr_read_pages(xdr, count);
262 xdr_terminate_string(xdr->buf, count);
263 return 0;
264
265out_nametoolong:
266 dprintk("NFS: returned pathname too long: %u\n", count);
267 return -ENAMETOOLONG;
268out_cheating:
269 dprintk("NFS: server cheating in pathname result: "
270 "count %u > recvd %u\n", count, recvd);
271 return -EIO;
147out_overflow: 272out_overflow:
148 print_overflow_msg(__func__, xdr); 273 print_overflow_msg(__func__, xdr);
149 return ERR_PTR(-EIO); 274 return -EIO;
150} 275}
151 276
152/* 277/*
153 * Encode/decode time. 278 * cookie3
279 *
280 * typedef uint64 cookie3
154 */ 281 */
155static inline __be32 * 282static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
156xdr_encode_time3(__be32 *p, struct timespec *timep)
157{ 283{
158 *p++ = htonl(timep->tv_sec); 284 return xdr_encode_hyper(p, cookie);
159 *p++ = htonl(timep->tv_nsec);
160 return p;
161} 285}
162 286
163static inline __be32 * 287static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
164xdr_decode_time3(__be32 *p, struct timespec *timep)
165{ 288{
166 timep->tv_sec = ntohl(*p++); 289 return decode_uint64(xdr, cookie);
167 timep->tv_nsec = ntohl(*p++); 290}
168 return p; 291
292/*
293 * cookieverf3
294 *
295 * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
296 */
297static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
298{
299 memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
300 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
301}
302
303static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
304{
305 __be32 *p;
306
307 p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
308 if (unlikely(p == NULL))
309 goto out_overflow;
310 memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
311 return 0;
312out_overflow:
313 print_overflow_msg(__func__, xdr);
314 return -EIO;
315}
316
317/*
318 * createverf3
319 *
320 * typedef opaque createverf3[NFS3_CREATEVERFSIZE];
321 */
322static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
323{
324 __be32 *p;
325
326 p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
327 memcpy(p, verifier, NFS3_CREATEVERFSIZE);
328}
329
330static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier)
331{
332 __be32 *p;
333
334 p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
335 if (unlikely(p == NULL))
336 goto out_overflow;
337 memcpy(verifier, p, NFS3_WRITEVERFSIZE);
338 return 0;
339out_overflow:
340 print_overflow_msg(__func__, xdr);
341 return -EIO;
342}
343
344/*
345 * size3
346 *
347 * typedef uint64 size3;
348 */
349static __be32 *xdr_decode_size3(__be32 *p, u64 *size)
350{
351 return xdr_decode_hyper(p, size);
352}
353
354/*
355 * nfsstat3
356 *
357 * enum nfsstat3 {
358 * NFS3_OK = 0,
359 * ...
360 * }
361 */
362#define NFS3_OK NFS_OK
363
364static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
365{
366 __be32 *p;
367
368 p = xdr_inline_decode(xdr, 4);
369 if (unlikely(p == NULL))
370 goto out_overflow;
371 *status = be32_to_cpup(p);
372 return 0;
373out_overflow:
374 print_overflow_msg(__func__, xdr);
375 return -EIO;
376}
377
378/*
379 * ftype3
380 *
381 * enum ftype3 {
382 * NF3REG = 1,
383 * NF3DIR = 2,
384 * NF3BLK = 3,
385 * NF3CHR = 4,
386 * NF3LNK = 5,
387 * NF3SOCK = 6,
388 * NF3FIFO = 7
389 * };
390 */
391static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
392{
393 BUG_ON(type > NF3FIFO);
394 encode_uint32(xdr, type);
169} 395}
170 396
171static __be32 * 397static __be32 *xdr_decode_ftype3(__be32 *p, umode_t *mode)
172xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
173{ 398{
174 unsigned int type, major, minor; 399 u32 type;
175 umode_t fmode;
176 400
177 type = ntohl(*p++); 401 type = be32_to_cpup(p++);
178 if (type > NF3FIFO) 402 if (type > NF3FIFO)
179 type = NF3NON; 403 type = NF3NON;
180 fmode = nfs_type2fmt[type]; 404 *mode = nfs_type2fmt[type];
181 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode; 405 return p;
182 fattr->nlink = ntohl(*p++); 406}
183 fattr->uid = ntohl(*p++);
184 fattr->gid = ntohl(*p++);
185 p = xdr_decode_hyper(p, &fattr->size);
186 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
187
188 /* Turn remote device info into Linux-specific dev_t */
189 major = ntohl(*p++);
190 minor = ntohl(*p++);
191 fattr->rdev = MKDEV(major, minor);
192 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
193 fattr->rdev = 0;
194 407
195 p = xdr_decode_hyper(p, &fattr->fsid.major); 408/*
196 fattr->fsid.minor = 0; 409 * specdata3
197 p = xdr_decode_hyper(p, &fattr->fileid); 410 *
198 p = xdr_decode_time3(p, &fattr->atime); 411 * struct specdata3 {
199 p = xdr_decode_time3(p, &fattr->mtime); 412 * uint32 specdata1;
200 p = xdr_decode_time3(p, &fattr->ctime); 413 * uint32 specdata2;
414 * };
415 */
416static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
417{
418 __be32 *p;
201 419
202 /* Update the mode bits */ 420 p = xdr_reserve_space(xdr, 8);
203 fattr->valid |= NFS_ATTR_FATTR_V3; 421 *p++ = cpu_to_be32(MAJOR(rdev));
422 *p = cpu_to_be32(MINOR(rdev));
423}
424
425static __be32 *xdr_decode_specdata3(__be32 *p, dev_t *rdev)
426{
427 unsigned int major, minor;
428
429 major = be32_to_cpup(p++);
430 minor = be32_to_cpup(p++);
431 *rdev = MKDEV(major, minor);
432 if (MAJOR(*rdev) != major || MINOR(*rdev) != minor)
433 *rdev = 0;
204 return p; 434 return p;
205} 435}
206 436
207static inline __be32 * 437/*
208xdr_encode_sattr(__be32 *p, struct iattr *attr) 438 * nfs_fh3
439 *
440 * struct nfs_fh3 {
441 * opaque data<NFS3_FHSIZE>;
442 * };
443 */
444static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
209{ 445{
446 __be32 *p;
447
448 BUG_ON(fh->size > NFS3_FHSIZE);
449 p = xdr_reserve_space(xdr, 4 + fh->size);
450 xdr_encode_opaque(p, fh->data, fh->size);
451}
452
453static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
454{
455 u32 length;
456 __be32 *p;
457
458 p = xdr_inline_decode(xdr, 4);
459 if (unlikely(p == NULL))
460 goto out_overflow;
461 length = be32_to_cpup(p++);
462 if (unlikely(length > NFS3_FHSIZE))
463 goto out_toobig;
464 p = xdr_inline_decode(xdr, length);
465 if (unlikely(p == NULL))
466 goto out_overflow;
467 fh->size = length;
468 memcpy(fh->data, p, length);
469 return 0;
470out_toobig:
471 dprintk("NFS: file handle size (%u) too big\n", length);
472 return -E2BIG;
473out_overflow:
474 print_overflow_msg(__func__, xdr);
475 return -EIO;
476}
477
478static void zero_nfs_fh3(struct nfs_fh *fh)
479{
480 memset(fh, 0, sizeof(*fh));
481}
482
483/*
484 * nfstime3
485 *
486 * struct nfstime3 {
487 * uint32 seconds;
488 * uint32 nseconds;
489 * };
490 */
491static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep)
492{
493 *p++ = cpu_to_be32(timep->tv_sec);
494 *p++ = cpu_to_be32(timep->tv_nsec);
495 return p;
496}
497
498static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep)
499{
500 timep->tv_sec = be32_to_cpup(p++);
501 timep->tv_nsec = be32_to_cpup(p++);
502 return p;
503}
504
505/*
506 * sattr3
507 *
508 * enum time_how {
509 * DONT_CHANGE = 0,
510 * SET_TO_SERVER_TIME = 1,
511 * SET_TO_CLIENT_TIME = 2
512 * };
513 *
514 * union set_mode3 switch (bool set_it) {
515 * case TRUE:
516 * mode3 mode;
517 * default:
518 * void;
519 * };
520 *
521 * union set_uid3 switch (bool set_it) {
522 * case TRUE:
523 * uid3 uid;
524 * default:
525 * void;
526 * };
527 *
528 * union set_gid3 switch (bool set_it) {
529 * case TRUE:
530 * gid3 gid;
531 * default:
532 * void;
533 * };
534 *
535 * union set_size3 switch (bool set_it) {
536 * case TRUE:
537 * size3 size;
538 * default:
539 * void;
540 * };
541 *
542 * union set_atime switch (time_how set_it) {
543 * case SET_TO_CLIENT_TIME:
544 * nfstime3 atime;
545 * default:
546 * void;
547 * };
548 *
549 * union set_mtime switch (time_how set_it) {
550 * case SET_TO_CLIENT_TIME:
551 * nfstime3 mtime;
552 * default:
553 * void;
554 * };
555 *
556 * struct sattr3 {
557 * set_mode3 mode;
558 * set_uid3 uid;
559 * set_gid3 gid;
560 * set_size3 size;
561 * set_atime atime;
562 * set_mtime mtime;
563 * };
564 */
565static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
566{
567 u32 nbytes;
568 __be32 *p;
569
570 /*
571 * In order to make only a single xdr_reserve_space() call,
572 * pre-compute the total number of bytes to be reserved.
573 * Six boolean values, one for each set_foo field, are always
574 * present in the encoded result, so start there.
575 */
576 nbytes = 6 * 4;
577 if (attr->ia_valid & ATTR_MODE)
578 nbytes += 4;
579 if (attr->ia_valid & ATTR_UID)
580 nbytes += 4;
581 if (attr->ia_valid & ATTR_GID)
582 nbytes += 4;
583 if (attr->ia_valid & ATTR_SIZE)
584 nbytes += 8;
585 if (attr->ia_valid & ATTR_ATIME_SET)
586 nbytes += 8;
587 if (attr->ia_valid & ATTR_MTIME_SET)
588 nbytes += 8;
589 p = xdr_reserve_space(xdr, nbytes);
590
210 if (attr->ia_valid & ATTR_MODE) { 591 if (attr->ia_valid & ATTR_MODE) {
211 *p++ = xdr_one; 592 *p++ = xdr_one;
212 *p++ = htonl(attr->ia_mode & S_IALLUGO); 593 *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO);
213 } else { 594 } else
214 *p++ = xdr_zero; 595 *p++ = xdr_zero;
215 } 596
216 if (attr->ia_valid & ATTR_UID) { 597 if (attr->ia_valid & ATTR_UID) {
217 *p++ = xdr_one; 598 *p++ = xdr_one;
218 *p++ = htonl(attr->ia_uid); 599 *p++ = cpu_to_be32(attr->ia_uid);
219 } else { 600 } else
220 *p++ = xdr_zero; 601 *p++ = xdr_zero;
221 } 602
222 if (attr->ia_valid & ATTR_GID) { 603 if (attr->ia_valid & ATTR_GID) {
223 *p++ = xdr_one; 604 *p++ = xdr_one;
224 *p++ = htonl(attr->ia_gid); 605 *p++ = cpu_to_be32(attr->ia_gid);
225 } else { 606 } else
226 *p++ = xdr_zero; 607 *p++ = xdr_zero;
227 } 608
228 if (attr->ia_valid & ATTR_SIZE) { 609 if (attr->ia_valid & ATTR_SIZE) {
229 *p++ = xdr_one; 610 *p++ = xdr_one;
230 p = xdr_encode_hyper(p, (__u64) attr->ia_size); 611 p = xdr_encode_hyper(p, (u64)attr->ia_size);
231 } else { 612 } else
232 *p++ = xdr_zero; 613 *p++ = xdr_zero;
233 } 614
234 if (attr->ia_valid & ATTR_ATIME_SET) { 615 if (attr->ia_valid & ATTR_ATIME_SET) {
235 *p++ = xdr_two; 616 *p++ = xdr_two;
236 p = xdr_encode_time3(p, &attr->ia_atime); 617 p = xdr_encode_nfstime3(p, &attr->ia_atime);
237 } else if (attr->ia_valid & ATTR_ATIME) { 618 } else if (attr->ia_valid & ATTR_ATIME) {
238 *p++ = xdr_one; 619 *p++ = xdr_one;
239 } else { 620 } else
240 *p++ = xdr_zero; 621 *p++ = xdr_zero;
241 } 622
242 if (attr->ia_valid & ATTR_MTIME_SET) { 623 if (attr->ia_valid & ATTR_MTIME_SET) {
243 *p++ = xdr_two; 624 *p++ = xdr_two;
244 p = xdr_encode_time3(p, &attr->ia_mtime); 625 xdr_encode_nfstime3(p, &attr->ia_mtime);
245 } else if (attr->ia_valid & ATTR_MTIME) { 626 } else if (attr->ia_valid & ATTR_MTIME) {
246 *p++ = xdr_one; 627 *p = xdr_one;
247 } else { 628 } else
248 *p++ = xdr_zero; 629 *p = xdr_zero;
249 }
250 return p;
251} 630}
252 631
253static inline __be32 * 632/*
254xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr) 633 * fattr3
634 *
635 * struct fattr3 {
636 * ftype3 type;
637 * mode3 mode;
638 * uint32 nlink;
639 * uid3 uid;
640 * gid3 gid;
641 * size3 size;
642 * size3 used;
643 * specdata3 rdev;
644 * uint64 fsid;
645 * fileid3 fileid;
646 * nfstime3 atime;
647 * nfstime3 mtime;
648 * nfstime3 ctime;
649 * };
650 */
651static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
255{ 652{
256 p = xdr_decode_hyper(p, &fattr->pre_size); 653 umode_t fmode;
257 p = xdr_decode_time3(p, &fattr->pre_mtime); 654 __be32 *p;
258 p = xdr_decode_time3(p, &fattr->pre_ctime); 655
656 p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
657 if (unlikely(p == NULL))
658 goto out_overflow;
659
660 p = xdr_decode_ftype3(p, &fmode);
661
662 fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
663 fattr->nlink = be32_to_cpup(p++);
664 fattr->uid = be32_to_cpup(p++);
665 fattr->gid = be32_to_cpup(p++);
666
667 p = xdr_decode_size3(p, &fattr->size);
668 p = xdr_decode_size3(p, &fattr->du.nfs3.used);
669 p = xdr_decode_specdata3(p, &fattr->rdev);
670
671 p = xdr_decode_hyper(p, &fattr->fsid.major);
672 fattr->fsid.minor = 0;
673
674 p = xdr_decode_fileid3(p, &fattr->fileid);
675 p = xdr_decode_nfstime3(p, &fattr->atime);
676 p = xdr_decode_nfstime3(p, &fattr->mtime);
677 xdr_decode_nfstime3(p, &fattr->ctime);
678
679 fattr->valid |= NFS_ATTR_FATTR_V3;
680 return 0;
681out_overflow:
682 print_overflow_msg(__func__, xdr);
683 return -EIO;
684}
685
686/*
687 * post_op_attr
688 *
689 * union post_op_attr switch (bool attributes_follow) {
690 * case TRUE:
691 * fattr3 attributes;
692 * case FALSE:
693 * void;
694 * };
695 */
696static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
697{
698 __be32 *p;
699
700 p = xdr_inline_decode(xdr, 4);
701 if (unlikely(p == NULL))
702 goto out_overflow;
703 if (*p != xdr_zero)
704 return decode_fattr3(xdr, fattr);
705 return 0;
706out_overflow:
707 print_overflow_msg(__func__, xdr);
708 return -EIO;
709}
710
711/*
712 * wcc_attr
713 * struct wcc_attr {
714 * size3 size;
715 * nfstime3 mtime;
716 * nfstime3 ctime;
717 * };
718 */
719static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
720{
721 __be32 *p;
722
723 p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
724 if (unlikely(p == NULL))
725 goto out_overflow;
726
259 fattr->valid |= NFS_ATTR_FATTR_PRESIZE 727 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
260 | NFS_ATTR_FATTR_PREMTIME 728 | NFS_ATTR_FATTR_PREMTIME
261 | NFS_ATTR_FATTR_PRECTIME; 729 | NFS_ATTR_FATTR_PRECTIME;
262 return p;
263}
264 730
265static inline __be32 * 731 p = xdr_decode_size3(p, &fattr->pre_size);
266xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr) 732 p = xdr_decode_nfstime3(p, &fattr->pre_mtime);
267{ 733 xdr_decode_nfstime3(p, &fattr->pre_ctime);
268 if (*p++) 734
269 p = xdr_decode_fattr(p, fattr); 735 return 0;
270 return p; 736out_overflow:
737 print_overflow_msg(__func__, xdr);
738 return -EIO;
271} 739}
272 740
273static inline __be32 * 741/*
274xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr) 742 * pre_op_attr
743 * union pre_op_attr switch (bool attributes_follow) {
744 * case TRUE:
745 * wcc_attr attributes;
746 * case FALSE:
747 * void;
748 * };
749 *
750 * wcc_data
751 *
752 * struct wcc_data {
753 * pre_op_attr before;
754 * post_op_attr after;
755 * };
756 */
757static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
275{ 758{
276 __be32 *p; 759 __be32 *p;
277 760
278 p = xdr_inline_decode(xdr, 4); 761 p = xdr_inline_decode(xdr, 4);
279 if (unlikely(!p)) 762 if (unlikely(p == NULL))
280 goto out_overflow; 763 goto out_overflow;
281 if (ntohl(*p++)) { 764 if (*p != xdr_zero)
282 p = xdr_inline_decode(xdr, 84); 765 return decode_wcc_attr(xdr, fattr);
283 if (unlikely(!p)) 766 return 0;
284 goto out_overflow;
285 p = xdr_decode_fattr(p, fattr);
286 }
287 return p;
288out_overflow: 767out_overflow:
289 print_overflow_msg(__func__, xdr); 768 print_overflow_msg(__func__, xdr);
290 return ERR_PTR(-EIO); 769 return -EIO;
291} 770}
292 771
293static inline __be32 * 772static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
294xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
295{ 773{
296 if (*p++) 774 int error;
297 return xdr_decode_wcc_attr(p, fattr); 775
298 return p; 776 error = decode_pre_op_attr(xdr, fattr);
777 if (unlikely(error))
778 goto out;
779 error = decode_post_op_attr(xdr, fattr);
780out:
781 return error;
299} 782}
300 783
784/*
785 * post_op_fh3
786 *
787 * union post_op_fh3 switch (bool handle_follows) {
788 * case TRUE:
789 * nfs_fh3 handle;
790 * case FALSE:
791 * void;
792 * };
793 */
794static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
795{
796 __be32 *p = xdr_inline_decode(xdr, 4);
797 if (unlikely(p == NULL))
798 goto out_overflow;
799 if (*p != xdr_zero)
800 return decode_nfs_fh3(xdr, fh);
801 zero_nfs_fh3(fh);
802 return 0;
803out_overflow:
804 print_overflow_msg(__func__, xdr);
805 return -EIO;
806}
301 807
302static inline __be32 * 808/*
303xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr) 809 * diropargs3
810 *
811 * struct diropargs3 {
812 * nfs_fh3 dir;
813 * filename3 name;
814 * };
815 */
816static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
817 const char *name, u32 length)
304{ 818{
305 p = xdr_decode_pre_op_attr(p, fattr); 819 encode_nfs_fh3(xdr, fh);
306 return xdr_decode_post_op_attr(p, fattr); 820 encode_filename3(xdr, name, length);
307} 821}
308 822
823
309/* 824/*
310 * NFS encode functions 825 * NFSv3 XDR encode functions
826 *
827 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
828 * "NFS Version 3 Protocol Specification".
311 */ 829 */
312 830
313/* 831/*
314 * Encode file handle argument 832 * 3.3.1 GETATTR3args
833 *
834 * struct GETATTR3args {
835 * nfs_fh3 object;
836 * };
315 */ 837 */
316static int 838static void nfs3_xdr_enc_getattr3args(struct rpc_rqst *req,
317nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh) 839 struct xdr_stream *xdr,
840 const struct nfs_fh *fh)
318{ 841{
319 p = xdr_encode_fhandle(p, fh); 842 encode_nfs_fh3(xdr, fh);
320 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
321 return 0;
322} 843}
323 844
324/* 845/*
325 * Encode SETATTR arguments 846 * 3.3.2 SETATTR3args
847 *
848 * union sattrguard3 switch (bool check) {
849 * case TRUE:
850 * nfstime3 obj_ctime;
851 * case FALSE:
852 * void;
853 * };
854 *
855 * struct SETATTR3args {
856 * nfs_fh3 object;
857 * sattr3 new_attributes;
858 * sattrguard3 guard;
859 * };
326 */ 860 */
327static int 861static void encode_sattrguard3(struct xdr_stream *xdr,
328nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args) 862 const struct nfs3_sattrargs *args)
329{ 863{
330 p = xdr_encode_fhandle(p, args->fh); 864 __be32 *p;
331 p = xdr_encode_sattr(p, args->sattr); 865
332 *p++ = htonl(args->guard); 866 if (args->guard) {
333 if (args->guard) 867 p = xdr_reserve_space(xdr, 4 + 8);
334 p = xdr_encode_time3(p, &args->guardtime); 868 *p++ = xdr_one;
335 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 869 xdr_encode_nfstime3(p, &args->guardtime);
336 return 0; 870 } else {
871 p = xdr_reserve_space(xdr, 4);
872 *p = xdr_zero;
873 }
874}
875
876static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req,
877 struct xdr_stream *xdr,
878 const struct nfs3_sattrargs *args)
879{
880 encode_nfs_fh3(xdr, args->fh);
881 encode_sattr3(xdr, args->sattr);
882 encode_sattrguard3(xdr, args);
337} 883}
338 884
339/* 885/*
340 * Encode directory ops argument 886 * 3.3.3 LOOKUP3args
887 *
888 * struct LOOKUP3args {
889 * diropargs3 what;
890 * };
341 */ 891 */
342static int 892static void nfs3_xdr_enc_lookup3args(struct rpc_rqst *req,
343nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args) 893 struct xdr_stream *xdr,
894 const struct nfs3_diropargs *args)
344{ 895{
345 p = xdr_encode_fhandle(p, args->fh); 896 encode_diropargs3(xdr, args->fh, args->name, args->len);
346 p = xdr_encode_array(p, args->name, args->len);
347 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
348 return 0;
349} 897}
350 898
351/* 899/*
352 * Encode REMOVE argument 900 * 3.3.4 ACCESS3args
901 *
902 * struct ACCESS3args {
903 * nfs_fh3 object;
904 * uint32 access;
905 * };
353 */ 906 */
354static int 907static void encode_access3args(struct xdr_stream *xdr,
355nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args) 908 const struct nfs3_accessargs *args)
356{ 909{
357 p = xdr_encode_fhandle(p, args->fh); 910 encode_nfs_fh3(xdr, args->fh);
358 p = xdr_encode_array(p, args->name.name, args->name.len); 911 encode_uint32(xdr, args->access);
359 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 912}
360 return 0; 913
914static void nfs3_xdr_enc_access3args(struct rpc_rqst *req,
915 struct xdr_stream *xdr,
916 const struct nfs3_accessargs *args)
917{
918 encode_access3args(xdr, args);
361} 919}
362 920
363/* 921/*
364 * Encode access() argument 922 * 3.3.5 READLINK3args
923 *
924 * struct READLINK3args {
925 * nfs_fh3 symlink;
926 * };
365 */ 927 */
366static int 928static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
367nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args) 929 struct xdr_stream *xdr,
930 const struct nfs3_readlinkargs *args)
368{ 931{
369 p = xdr_encode_fhandle(p, args->fh); 932 encode_nfs_fh3(xdr, args->fh);
370 *p++ = htonl(args->access); 933 prepare_reply_buffer(req, args->pages, args->pgbase,
371 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 934 args->pglen, NFS3_readlinkres_sz);
372 return 0;
373} 935}
374 936
375/* 937/*
376 * Arguments to a READ call. Since we read data directly into the page 938 * 3.3.6 READ3args
377 * cache, we also set up the reply iovec here so that iov[1] points 939 *
378 * exactly to the page we want to fetch. 940 * struct READ3args {
941 * nfs_fh3 file;
942 * offset3 offset;
943 * count3 count;
944 * };
379 */ 945 */
380static int 946static void encode_read3args(struct xdr_stream *xdr,
381nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) 947 const struct nfs_readargs *args)
382{ 948{
383 struct rpc_auth *auth = req->rq_cred->cr_auth; 949 __be32 *p;
384 unsigned int replen;
385 u32 count = args->count;
386 950
387 p = xdr_encode_fhandle(p, args->fh); 951 encode_nfs_fh3(xdr, args->fh);
952
953 p = xdr_reserve_space(xdr, 8 + 4);
388 p = xdr_encode_hyper(p, args->offset); 954 p = xdr_encode_hyper(p, args->offset);
389 *p++ = htonl(count); 955 *p = cpu_to_be32(args->count);
390 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 956}
391 957
392 /* Inline the page array */ 958static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
393 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2; 959 struct xdr_stream *xdr,
394 xdr_inline_pages(&req->rq_rcv_buf, replen, 960 const struct nfs_readargs *args)
395 args->pages, args->pgbase, count); 961{
962 encode_read3args(xdr, args);
963 prepare_reply_buffer(req, args->pages, args->pgbase,
964 args->count, NFS3_readres_sz);
396 req->rq_rcv_buf.flags |= XDRBUF_READ; 965 req->rq_rcv_buf.flags |= XDRBUF_READ;
397 return 0;
398} 966}
399 967
400/* 968/*
401 * Write arguments. Splice the buffer to be written into the iovec. 969 * 3.3.7 WRITE3args
970 *
971 * enum stable_how {
972 * UNSTABLE = 0,
973 * DATA_SYNC = 1,
974 * FILE_SYNC = 2
975 * };
976 *
977 * struct WRITE3args {
978 * nfs_fh3 file;
979 * offset3 offset;
980 * count3 count;
981 * stable_how stable;
982 * opaque data<>;
983 * };
402 */ 984 */
403static int 985static void encode_write3args(struct xdr_stream *xdr,
404nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 986 const struct nfs_writeargs *args)
405{ 987{
406 struct xdr_buf *sndbuf = &req->rq_snd_buf; 988 __be32 *p;
407 u32 count = args->count;
408 989
409 p = xdr_encode_fhandle(p, args->fh); 990 encode_nfs_fh3(xdr, args->fh);
991
992 p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
410 p = xdr_encode_hyper(p, args->offset); 993 p = xdr_encode_hyper(p, args->offset);
411 *p++ = htonl(count); 994 *p++ = cpu_to_be32(args->count);
412 *p++ = htonl(args->stable); 995 *p++ = cpu_to_be32(args->stable);
413 *p++ = htonl(count); 996 *p = cpu_to_be32(args->count);
414 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 997 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
415 998}
416 /* Copy the page array */ 999
417 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); 1000static void nfs3_xdr_enc_write3args(struct rpc_rqst *req,
418 sndbuf->flags |= XDRBUF_WRITE; 1001 struct xdr_stream *xdr,
419 return 0; 1002 const struct nfs_writeargs *args)
1003{
1004 encode_write3args(xdr, args);
1005 xdr->buf->flags |= XDRBUF_WRITE;
420} 1006}
421 1007
422/* 1008/*
423 * Encode CREATE arguments 1009 * 3.3.8 CREATE3args
1010 *
1011 * enum createmode3 {
1012 * UNCHECKED = 0,
1013 * GUARDED = 1,
1014 * EXCLUSIVE = 2
1015 * };
1016 *
1017 * union createhow3 switch (createmode3 mode) {
1018 * case UNCHECKED:
1019 * case GUARDED:
1020 * sattr3 obj_attributes;
1021 * case EXCLUSIVE:
1022 * createverf3 verf;
1023 * };
1024 *
1025 * struct CREATE3args {
1026 * diropargs3 where;
1027 * createhow3 how;
1028 * };
424 */ 1029 */
425static int 1030static void encode_createhow3(struct xdr_stream *xdr,
426nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args) 1031 const struct nfs3_createargs *args)
427{ 1032{
428 p = xdr_encode_fhandle(p, args->fh); 1033 encode_uint32(xdr, args->createmode);
429 p = xdr_encode_array(p, args->name, args->len); 1034 switch (args->createmode) {
430 1035 case NFS3_CREATE_UNCHECKED:
431 *p++ = htonl(args->createmode); 1036 case NFS3_CREATE_GUARDED:
432 if (args->createmode == NFS3_CREATE_EXCLUSIVE) { 1037 encode_sattr3(xdr, args->sattr);
433 *p++ = args->verifier[0]; 1038 break;
434 *p++ = args->verifier[1]; 1039 case NFS3_CREATE_EXCLUSIVE:
435 } else 1040 encode_createverf3(xdr, args->verifier);
436 p = xdr_encode_sattr(p, args->sattr); 1041 break;
1042 default:
1043 BUG();
1044 }
1045}
437 1046
438 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 1047static void nfs3_xdr_enc_create3args(struct rpc_rqst *req,
439 return 0; 1048 struct xdr_stream *xdr,
1049 const struct nfs3_createargs *args)
1050{
1051 encode_diropargs3(xdr, args->fh, args->name, args->len);
1052 encode_createhow3(xdr, args);
440} 1053}
441 1054
442/* 1055/*
443 * Encode MKDIR arguments 1056 * 3.3.9 MKDIR3args
1057 *
1058 * struct MKDIR3args {
1059 * diropargs3 where;
1060 * sattr3 attributes;
1061 * };
444 */ 1062 */
445static int 1063static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req,
446nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args) 1064 struct xdr_stream *xdr,
1065 const struct nfs3_mkdirargs *args)
447{ 1066{
448 p = xdr_encode_fhandle(p, args->fh); 1067 encode_diropargs3(xdr, args->fh, args->name, args->len);
449 p = xdr_encode_array(p, args->name, args->len); 1068 encode_sattr3(xdr, args->sattr);
450 p = xdr_encode_sattr(p, args->sattr);
451 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
452 return 0;
453} 1069}
454 1070
455/* 1071/*
456 * Encode SYMLINK arguments 1072 * 3.3.10 SYMLINK3args
1073 *
1074 * struct symlinkdata3 {
1075 * sattr3 symlink_attributes;
1076 * nfspath3 symlink_data;
1077 * };
1078 *
1079 * struct SYMLINK3args {
1080 * diropargs3 where;
1081 * symlinkdata3 symlink;
1082 * };
457 */ 1083 */
458static int 1084static void encode_symlinkdata3(struct xdr_stream *xdr,
459nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args) 1085 const struct nfs3_symlinkargs *args)
460{ 1086{
461 p = xdr_encode_fhandle(p, args->fromfh); 1087 encode_sattr3(xdr, args->sattr);
462 p = xdr_encode_array(p, args->fromname, args->fromlen); 1088 encode_nfspath3(xdr, args->pages, args->pathlen);
463 p = xdr_encode_sattr(p, args->sattr); 1089}
464 *p++ = htonl(args->pathlen);
465 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
466 1090
467 /* Copy the page */ 1091static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req,
468 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen); 1092 struct xdr_stream *xdr,
469 return 0; 1093 const struct nfs3_symlinkargs *args)
1094{
1095 encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen);
1096 encode_symlinkdata3(xdr, args);
470} 1097}
471 1098
472/* 1099/*
473 * Encode MKNOD arguments 1100 * 3.3.11 MKNOD3args
1101 *
1102 * struct devicedata3 {
1103 * sattr3 dev_attributes;
1104 * specdata3 spec;
1105 * };
1106 *
1107 * union mknoddata3 switch (ftype3 type) {
1108 * case NF3CHR:
1109 * case NF3BLK:
1110 * devicedata3 device;
1111 * case NF3SOCK:
1112 * case NF3FIFO:
1113 * sattr3 pipe_attributes;
1114 * default:
1115 * void;
1116 * };
1117 *
1118 * struct MKNOD3args {
1119 * diropargs3 where;
1120 * mknoddata3 what;
1121 * };
474 */ 1122 */
475static int 1123static void encode_devicedata3(struct xdr_stream *xdr,
476nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args) 1124 const struct nfs3_mknodargs *args)
477{ 1125{
478 p = xdr_encode_fhandle(p, args->fh); 1126 encode_sattr3(xdr, args->sattr);
479 p = xdr_encode_array(p, args->name, args->len); 1127 encode_specdata3(xdr, args->rdev);
480 *p++ = htonl(args->type); 1128}
481 p = xdr_encode_sattr(p, args->sattr); 1129
482 if (args->type == NF3CHR || args->type == NF3BLK) { 1130static void encode_mknoddata3(struct xdr_stream *xdr,
483 *p++ = htonl(MAJOR(args->rdev)); 1131 const struct nfs3_mknodargs *args)
484 *p++ = htonl(MINOR(args->rdev)); 1132{
1133 encode_ftype3(xdr, args->type);
1134 switch (args->type) {
1135 case NF3CHR:
1136 case NF3BLK:
1137 encode_devicedata3(xdr, args);
1138 break;
1139 case NF3SOCK:
1140 case NF3FIFO:
1141 encode_sattr3(xdr, args->sattr);
1142 break;
1143 case NF3REG:
1144 case NF3DIR:
1145 break;
1146 default:
1147 BUG();
485 } 1148 }
1149}
486 1150
487 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 1151static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req,
488 return 0; 1152 struct xdr_stream *xdr,
1153 const struct nfs3_mknodargs *args)
1154{
1155 encode_diropargs3(xdr, args->fh, args->name, args->len);
1156 encode_mknoddata3(xdr, args);
489} 1157}
490 1158
491/* 1159/*
492 * Encode RENAME arguments 1160 * 3.3.12 REMOVE3args
1161 *
1162 * struct REMOVE3args {
1163 * diropargs3 object;
1164 * };
493 */ 1165 */
494static int 1166static void nfs3_xdr_enc_remove3args(struct rpc_rqst *req,
495nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args) 1167 struct xdr_stream *xdr,
496{ 1168 const struct nfs_removeargs *args)
497 p = xdr_encode_fhandle(p, args->old_dir); 1169{
498 p = xdr_encode_array(p, args->old_name->name, args->old_name->len); 1170 encode_diropargs3(xdr, args->fh, args->name.name, args->name.len);
499 p = xdr_encode_fhandle(p, args->new_dir);
500 p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
501 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
502 return 0;
503} 1171}
504 1172
505/* 1173/*
506 * Encode LINK arguments 1174 * 3.3.14 RENAME3args
1175 *
1176 * struct RENAME3args {
1177 * diropargs3 from;
1178 * diropargs3 to;
1179 * };
507 */ 1180 */
508static int 1181static void nfs3_xdr_enc_rename3args(struct rpc_rqst *req,
509nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args) 1182 struct xdr_stream *xdr,
1183 const struct nfs_renameargs *args)
510{ 1184{
511 p = xdr_encode_fhandle(p, args->fromfh); 1185 const struct qstr *old = args->old_name;
512 p = xdr_encode_fhandle(p, args->tofh); 1186 const struct qstr *new = args->new_name;
513 p = xdr_encode_array(p, args->toname, args->tolen); 1187
514 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 1188 encode_diropargs3(xdr, args->old_dir, old->name, old->len);
515 return 0; 1189 encode_diropargs3(xdr, args->new_dir, new->name, new->len);
516} 1190}
517 1191
518/* 1192/*
519 * Encode arguments to readdir call 1193 * 3.3.15 LINK3args
1194 *
1195 * struct LINK3args {
1196 * nfs_fh3 file;
1197 * diropargs3 link;
1198 * };
520 */ 1199 */
521static int 1200static void nfs3_xdr_enc_link3args(struct rpc_rqst *req,
522nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) 1201 struct xdr_stream *xdr,
1202 const struct nfs3_linkargs *args)
523{ 1203{
524 struct rpc_auth *auth = req->rq_cred->cr_auth; 1204 encode_nfs_fh3(xdr, args->fromfh);
525 unsigned int replen; 1205 encode_diropargs3(xdr, args->tofh, args->toname, args->tolen);
526 u32 count = args->count;
527
528 p = xdr_encode_fhandle(p, args->fh);
529 p = xdr_encode_hyper(p, args->cookie);
530 *p++ = args->verf[0];
531 *p++ = args->verf[1];
532 if (args->plus) {
533 /* readdirplus: need dircount + buffer size.
534 * We just make sure we make dircount big enough */
535 *p++ = htonl(count >> 3);
536 }
537 *p++ = htonl(count);
538 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
539
540 /* Inline the page array */
541 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
542 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
543 return 0;
544} 1206}
545 1207
546/* 1208/*
547 * Decode the result of a readdir call. 1209 * 3.3.16 READDIR3args
548 * We just check for syntactical correctness. 1210 *
1211 * struct READDIR3args {
1212 * nfs_fh3 dir;
1213 * cookie3 cookie;
1214 * cookieverf3 cookieverf;
1215 * count3 count;
1216 * };
549 */ 1217 */
550static int 1218static void encode_readdir3args(struct xdr_stream *xdr,
551nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res) 1219 const struct nfs3_readdirargs *args)
552{ 1220{
553 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 1221 __be32 *p;
554 struct kvec *iov = rcvbuf->head;
555 struct page **page;
556 size_t hdrlen;
557 u32 recvd, pglen;
558 int status;
559
560 status = ntohl(*p++);
561 /* Decode post_op_attrs */
562 p = xdr_decode_post_op_attr(p, res->dir_attr);
563 if (status)
564 return nfs_stat_to_errno(status);
565 /* Decode verifier cookie */
566 if (res->verf) {
567 res->verf[0] = *p++;
568 res->verf[1] = *p++;
569 } else {
570 p += 2;
571 }
572 1222
573 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 1223 encode_nfs_fh3(xdr, args->fh);
574 if (iov->iov_len < hdrlen) {
575 dprintk("NFS: READDIR reply header overflowed:"
576 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
577 return -errno_NFSERR_IO;
578 } else if (iov->iov_len != hdrlen) {
579 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
580 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
581 }
582 1224
583 pglen = rcvbuf->page_len; 1225 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
584 recvd = rcvbuf->len - hdrlen; 1226 p = xdr_encode_cookie3(p, args->cookie);
585 if (pglen > recvd) 1227 p = xdr_encode_cookieverf3(p, args->verf);
586 pglen = recvd; 1228 *p = cpu_to_be32(args->count);
587 page = rcvbuf->pages; 1229}
588 1230
589 return pglen; 1231static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
1232 struct xdr_stream *xdr,
1233 const struct nfs3_readdirargs *args)
1234{
1235 encode_readdir3args(xdr, args);
1236 prepare_reply_buffer(req, args->pages, 0,
1237 args->count, NFS3_readdirres_sz);
590} 1238}
591 1239
592__be32 * 1240/*
593nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus) 1241 * 3.3.17 READDIRPLUS3args
1242 *
1243 * struct READDIRPLUS3args {
1244 * nfs_fh3 dir;
1245 * cookie3 cookie;
1246 * cookieverf3 cookieverf;
1247 * count3 dircount;
1248 * count3 maxcount;
1249 * };
1250 */
1251static void encode_readdirplus3args(struct xdr_stream *xdr,
1252 const struct nfs3_readdirargs *args)
594{ 1253{
595 __be32 *p; 1254 __be32 *p;
596 struct nfs_entry old = *entry;
597
598 p = xdr_inline_decode(xdr, 4);
599 if (unlikely(!p))
600 goto out_overflow;
601 if (!ntohl(*p++)) {
602 p = xdr_inline_decode(xdr, 4);
603 if (unlikely(!p))
604 goto out_overflow;
605 if (!ntohl(*p++))
606 return ERR_PTR(-EAGAIN);
607 entry->eof = 1;
608 return ERR_PTR(-EBADCOOKIE);
609 }
610 1255
611 p = xdr_inline_decode(xdr, 12); 1256 encode_nfs_fh3(xdr, args->fh);
612 if (unlikely(!p))
613 goto out_overflow;
614 p = xdr_decode_hyper(p, &entry->ino);
615 entry->len = ntohl(*p++);
616 1257
617 p = xdr_inline_decode(xdr, entry->len + 8); 1258 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
618 if (unlikely(!p)) 1259 p = xdr_encode_cookie3(p, args->cookie);
619 goto out_overflow; 1260 p = xdr_encode_cookieverf3(p, args->verf);
620 entry->name = (const char *) p;
621 p += XDR_QUADLEN(entry->len);
622 entry->prev_cookie = entry->cookie;
623 p = xdr_decode_hyper(p, &entry->cookie);
624 1261
625 entry->d_type = DT_UNKNOWN; 1262 /*
626 if (plus) { 1263 * readdirplus: need dircount + buffer size.
627 entry->fattr->valid = 0; 1264 * We just make sure we make dircount big enough
628 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr); 1265 */
629 if (IS_ERR(p)) 1266 *p++ = cpu_to_be32(args->count >> 3);
630 goto out_overflow_exit;
631 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
632 /* In fact, a post_op_fh3: */
633 p = xdr_inline_decode(xdr, 4);
634 if (unlikely(!p))
635 goto out_overflow;
636 if (*p++) {
637 p = xdr_decode_fhandle_stream(xdr, entry->fh);
638 if (IS_ERR(p))
639 goto out_overflow_exit;
640 /* Ugh -- server reply was truncated */
641 if (p == NULL) {
642 dprintk("NFS: FH truncated\n");
643 *entry = old;
644 return ERR_PTR(-EAGAIN);
645 }
646 } else
647 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
648 }
649 1267
650 return p; 1268 *p = cpu_to_be32(args->count);
1269}
651 1270
652out_overflow: 1271static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
653 print_overflow_msg(__func__, xdr); 1272 struct xdr_stream *xdr,
654out_overflow_exit: 1273 const struct nfs3_readdirargs *args)
655 return ERR_PTR(-EAGAIN); 1274{
1275 encode_readdirplus3args(xdr, args);
1276 prepare_reply_buffer(req, args->pages, 0,
1277 args->count, NFS3_readdirres_sz);
656} 1278}
657 1279
658/* 1280/*
659 * Encode COMMIT arguments 1281 * 3.3.21 COMMIT3args
1282 *
1283 * struct COMMIT3args {
1284 * nfs_fh3 file;
1285 * offset3 offset;
1286 * count3 count;
1287 * };
660 */ 1288 */
661static int 1289static void encode_commit3args(struct xdr_stream *xdr,
662nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 1290 const struct nfs_writeargs *args)
663{ 1291{
664 p = xdr_encode_fhandle(p, args->fh); 1292 __be32 *p;
1293
1294 encode_nfs_fh3(xdr, args->fh);
1295
1296 p = xdr_reserve_space(xdr, 8 + 4);
665 p = xdr_encode_hyper(p, args->offset); 1297 p = xdr_encode_hyper(p, args->offset);
666 *p++ = htonl(args->count); 1298 *p = cpu_to_be32(args->count);
667 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
668 return 0;
669} 1299}
670 1300
671#ifdef CONFIG_NFS_V3_ACL 1301static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req,
672/* 1302 struct xdr_stream *xdr,
673 * Encode GETACL arguments 1303 const struct nfs_writeargs *args)
674 */
675static int
676nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
677 struct nfs3_getaclargs *args)
678{ 1304{
679 struct rpc_auth *auth = req->rq_cred->cr_auth; 1305 encode_commit3args(xdr, args);
680 unsigned int replen; 1306}
681 1307
682 p = xdr_encode_fhandle(p, args->fh); 1308#ifdef CONFIG_NFS_V3_ACL
683 *p++ = htonl(args->mask);
684 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
685 1309
686 if (args->mask & (NFS_ACL | NFS_DFACL)) { 1310static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
687 /* Inline the page array */ 1311 struct xdr_stream *xdr,
688 replen = (RPC_REPHDRSIZE + auth->au_rslack + 1312 const struct nfs3_getaclargs *args)
689 ACL3_getaclres_sz) << 2; 1313{
690 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, 1314 encode_nfs_fh3(xdr, args->fh);
691 NFSACL_MAXPAGES << PAGE_SHIFT); 1315 encode_uint32(xdr, args->mask);
692 } 1316 if (args->mask & (NFS_ACL | NFS_DFACL))
693 return 0; 1317 prepare_reply_buffer(req, args->pages, 0,
1318 NFSACL_MAXPAGES << PAGE_SHIFT,
1319 ACL3_getaclres_sz);
694} 1320}
695 1321
696/* 1322static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
697 * Encode SETACL arguments 1323 struct xdr_stream *xdr,
698 */ 1324 const struct nfs3_setaclargs *args)
699static int
700nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
701 struct nfs3_setaclargs *args)
702{ 1325{
703 struct xdr_buf *buf = &req->rq_snd_buf;
704 unsigned int base; 1326 unsigned int base;
705 int err; 1327 int error;
706
707 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
708 *p++ = htonl(args->mask);
709 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
710 base = req->rq_slen;
711 1328
1329 encode_nfs_fh3(xdr, NFS_FH(args->inode));
1330 encode_uint32(xdr, args->mask);
712 if (args->npages != 0) 1331 if (args->npages != 0)
713 xdr_encode_pages(buf, args->pages, 0, args->len); 1332 xdr_write_pages(xdr, args->pages, 0, args->len);
714 else
715 req->rq_slen = xdr_adjust_iovec(req->rq_svec,
716 p + XDR_QUADLEN(args->len));
717 1333
718 err = nfsacl_encode(buf, base, args->inode, 1334 base = req->rq_slen;
1335 error = nfsacl_encode(xdr->buf, base, args->inode,
719 (args->mask & NFS_ACL) ? 1336 (args->mask & NFS_ACL) ?
720 args->acl_access : NULL, 1, 0); 1337 args->acl_access : NULL, 1, 0);
721 if (err > 0) 1338 BUG_ON(error < 0);
722 err = nfsacl_encode(buf, base + err, args->inode, 1339 error = nfsacl_encode(xdr->buf, base + error, args->inode,
723 (args->mask & NFS_DFACL) ? 1340 (args->mask & NFS_DFACL) ?
724 args->acl_default : NULL, 1, 1341 args->acl_default : NULL, 1,
725 NFS_ACL_DEFAULT); 1342 NFS_ACL_DEFAULT);
726 return (err > 0) ? 0 : err; 1343 BUG_ON(error < 0);
727} 1344}
1345
728#endif /* CONFIG_NFS_V3_ACL */ 1346#endif /* CONFIG_NFS_V3_ACL */
729 1347
730/* 1348/*
731 * NFS XDR decode functions 1349 * NFSv3 XDR decode functions
1350 *
1351 * NFSv3 result types are defined in section 3.3 of RFC 1813:
1352 * "NFS Version 3 Protocol Specification".
732 */ 1353 */
733 1354
734/* 1355/*
735 * Decode attrstat reply. 1356 * 3.3.1 GETATTR3res
1357 *
1358 * struct GETATTR3resok {
1359 * fattr3 obj_attributes;
1360 * };
1361 *
1362 * union GETATTR3res switch (nfsstat3 status) {
1363 * case NFS3_OK:
1364 * GETATTR3resok resok;
1365 * default:
1366 * void;
1367 * };
736 */ 1368 */
737static int 1369static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req,
738nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 1370 struct xdr_stream *xdr,
1371 struct nfs_fattr *result)
739{ 1372{
740 int status; 1373 enum nfs_stat status;
741 1374 int error;
742 if ((status = ntohl(*p++))) 1375
743 return nfs_stat_to_errno(status); 1376 error = decode_nfsstat3(xdr, &status);
744 xdr_decode_fattr(p, fattr); 1377 if (unlikely(error))
745 return 0; 1378 goto out;
1379 if (status != NFS3_OK)
1380 goto out_default;
1381 error = decode_fattr3(xdr, result);
1382out:
1383 return error;
1384out_default:
1385 return nfs_stat_to_errno(status);
746} 1386}
747 1387
748/* 1388/*
749 * Decode status+wcc_data reply 1389 * 3.3.2 SETATTR3res
750 * SATTR, REMOVE, RMDIR 1390 *
1391 * struct SETATTR3resok {
1392 * wcc_data obj_wcc;
1393 * };
1394 *
1395 * struct SETATTR3resfail {
1396 * wcc_data obj_wcc;
1397 * };
1398 *
1399 * union SETATTR3res switch (nfsstat3 status) {
1400 * case NFS3_OK:
1401 * SETATTR3resok resok;
1402 * default:
1403 * SETATTR3resfail resfail;
1404 * };
751 */ 1405 */
752static int 1406static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req,
753nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 1407 struct xdr_stream *xdr,
1408 struct nfs_fattr *result)
754{ 1409{
755 int status; 1410 enum nfs_stat status;
756 1411 int error;
757 if ((status = ntohl(*p++))) 1412
758 status = nfs_stat_to_errno(status); 1413 error = decode_nfsstat3(xdr, &status);
759 xdr_decode_wcc_data(p, fattr); 1414 if (unlikely(error))
760 return status; 1415 goto out;
1416 error = decode_wcc_data(xdr, result);
1417 if (unlikely(error))
1418 goto out;
1419 if (status != NFS3_OK)
1420 goto out_status;
1421out:
1422 return error;
1423out_status:
1424 return nfs_stat_to_errno(status);
761} 1425}
762 1426
763static int 1427/*
764nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res) 1428 * 3.3.3 LOOKUP3res
1429 *
1430 * struct LOOKUP3resok {
1431 * nfs_fh3 object;
1432 * post_op_attr obj_attributes;
1433 * post_op_attr dir_attributes;
1434 * };
1435 *
1436 * struct LOOKUP3resfail {
1437 * post_op_attr dir_attributes;
1438 * };
1439 *
1440 * union LOOKUP3res switch (nfsstat3 status) {
1441 * case NFS3_OK:
1442 * LOOKUP3resok resok;
1443 * default:
1444 * LOOKUP3resfail resfail;
1445 * };
1446 */
1447static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req,
1448 struct xdr_stream *xdr,
1449 struct nfs3_diropres *result)
765{ 1450{
766 return nfs3_xdr_wccstat(req, p, res->dir_attr); 1451 enum nfs_stat status;
1452 int error;
1453
1454 error = decode_nfsstat3(xdr, &status);
1455 if (unlikely(error))
1456 goto out;
1457 if (status != NFS3_OK)
1458 goto out_default;
1459 error = decode_nfs_fh3(xdr, result->fh);
1460 if (unlikely(error))
1461 goto out;
1462 error = decode_post_op_attr(xdr, result->fattr);
1463 if (unlikely(error))
1464 goto out;
1465 error = decode_post_op_attr(xdr, result->dir_attr);
1466out:
1467 return error;
1468out_default:
1469 error = decode_post_op_attr(xdr, result->dir_attr);
1470 if (unlikely(error))
1471 goto out;
1472 return nfs_stat_to_errno(status);
767} 1473}
768 1474
769/* 1475/*
770 * Decode LOOKUP reply 1476 * 3.3.4 ACCESS3res
1477 *
1478 * struct ACCESS3resok {
1479 * post_op_attr obj_attributes;
1480 * uint32 access;
1481 * };
1482 *
1483 * struct ACCESS3resfail {
1484 * post_op_attr obj_attributes;
1485 * };
1486 *
1487 * union ACCESS3res switch (nfsstat3 status) {
1488 * case NFS3_OK:
1489 * ACCESS3resok resok;
1490 * default:
1491 * ACCESS3resfail resfail;
1492 * };
771 */ 1493 */
772static int 1494static int nfs3_xdr_dec_access3res(struct rpc_rqst *req,
773nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 1495 struct xdr_stream *xdr,
1496 struct nfs3_accessres *result)
774{ 1497{
775 int status; 1498 enum nfs_stat status;
776 1499 int error;
777 if ((status = ntohl(*p++))) { 1500
778 status = nfs_stat_to_errno(status); 1501 error = decode_nfsstat3(xdr, &status);
779 } else { 1502 if (unlikely(error))
780 if (!(p = xdr_decode_fhandle(p, res->fh))) 1503 goto out;
781 return -errno_NFSERR_IO; 1504 error = decode_post_op_attr(xdr, result->fattr);
782 p = xdr_decode_post_op_attr(p, res->fattr); 1505 if (unlikely(error))
783 } 1506 goto out;
784 xdr_decode_post_op_attr(p, res->dir_attr); 1507 if (status != NFS3_OK)
785 return status; 1508 goto out_default;
1509 error = decode_uint32(xdr, &result->access);
1510out:
1511 return error;
1512out_default:
1513 return nfs_stat_to_errno(status);
786} 1514}
787 1515
788/* 1516/*
789 * Decode ACCESS reply 1517 * 3.3.5 READLINK3res
1518 *
1519 * struct READLINK3resok {
1520 * post_op_attr symlink_attributes;
1521 * nfspath3 data;
1522 * };
1523 *
1524 * struct READLINK3resfail {
1525 * post_op_attr symlink_attributes;
1526 * };
1527 *
1528 * union READLINK3res switch (nfsstat3 status) {
1529 * case NFS3_OK:
1530 * READLINK3resok resok;
1531 * default:
1532 * READLINK3resfail resfail;
1533 * };
790 */ 1534 */
791static int 1535static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req,
792nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res) 1536 struct xdr_stream *xdr,
1537 struct nfs_fattr *result)
793{ 1538{
794 int status = ntohl(*p++); 1539 enum nfs_stat status;
795 1540 int error;
796 p = xdr_decode_post_op_attr(p, res->fattr); 1541
797 if (status) 1542 error = decode_nfsstat3(xdr, &status);
798 return nfs_stat_to_errno(status); 1543 if (unlikely(error))
799 res->access = ntohl(*p++); 1544 goto out;
800 return 0; 1545 error = decode_post_op_attr(xdr, result);
1546 if (unlikely(error))
1547 goto out;
1548 if (status != NFS3_OK)
1549 goto out_default;
1550 error = decode_nfspath3(xdr);
1551out:
1552 return error;
1553out_default:
1554 return nfs_stat_to_errno(status);
801} 1555}
802 1556
803static int 1557/*
804nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args) 1558 * 3.3.6 READ3res
1559 *
1560 * struct READ3resok {
1561 * post_op_attr file_attributes;
1562 * count3 count;
1563 * bool eof;
1564 * opaque data<>;
1565 * };
1566 *
1567 * struct READ3resfail {
1568 * post_op_attr file_attributes;
1569 * };
1570 *
1571 * union READ3res switch (nfsstat3 status) {
1572 * case NFS3_OK:
1573 * READ3resok resok;
1574 * default:
1575 * READ3resfail resfail;
1576 * };
1577 */
1578static int decode_read3resok(struct xdr_stream *xdr,
1579 struct nfs_readres *result)
805{ 1580{
806 struct rpc_auth *auth = req->rq_cred->cr_auth; 1581 u32 eof, count, ocount, recvd;
807 unsigned int replen; 1582 size_t hdrlen;
1583 __be32 *p;
808 1584
809 p = xdr_encode_fhandle(p, args->fh); 1585 p = xdr_inline_decode(xdr, 4 + 4 + 4);
810 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 1586 if (unlikely(p == NULL))
1587 goto out_overflow;
1588 count = be32_to_cpup(p++);
1589 eof = be32_to_cpup(p++);
1590 ocount = be32_to_cpup(p++);
1591 if (unlikely(ocount != count))
1592 goto out_mismatch;
1593 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1594 recvd = xdr->buf->len - hdrlen;
1595 if (unlikely(count > recvd))
1596 goto out_cheating;
1597
1598out:
1599 xdr_read_pages(xdr, count);
1600 result->eof = eof;
1601 result->count = count;
1602 return count;
1603out_mismatch:
1604 dprintk("NFS: READ count doesn't match length of opaque: "
1605 "count %u != ocount %u\n", count, ocount);
1606 return -EIO;
1607out_cheating:
1608 dprintk("NFS: server cheating in read result: "
1609 "count %u > recvd %u\n", count, recvd);
1610 count = recvd;
1611 eof = 0;
1612 goto out;
1613out_overflow:
1614 print_overflow_msg(__func__, xdr);
1615 return -EIO;
1616}
811 1617
812 /* Inline the page array */ 1618static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
813 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2; 1619 struct nfs_readres *result)
814 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen); 1620{
815 return 0; 1621 enum nfs_stat status;
1622 int error;
1623
1624 error = decode_nfsstat3(xdr, &status);
1625 if (unlikely(error))
1626 goto out;
1627 error = decode_post_op_attr(xdr, result->fattr);
1628 if (unlikely(error))
1629 goto out;
1630 if (status != NFS3_OK)
1631 goto out_status;
1632 error = decode_read3resok(xdr, result);
1633out:
1634 return error;
1635out_status:
1636 return nfs_stat_to_errno(status);
816} 1637}
817 1638
818/* 1639/*
819 * Decode READLINK reply 1640 * 3.3.7 WRITE3res
1641 *
1642 * enum stable_how {
1643 * UNSTABLE = 0,
1644 * DATA_SYNC = 1,
1645 * FILE_SYNC = 2
1646 * };
1647 *
1648 * struct WRITE3resok {
1649 * wcc_data file_wcc;
1650 * count3 count;
1651 * stable_how committed;
1652 * writeverf3 verf;
1653 * };
1654 *
1655 * struct WRITE3resfail {
1656 * wcc_data file_wcc;
1657 * };
1658 *
1659 * union WRITE3res switch (nfsstat3 status) {
1660 * case NFS3_OK:
1661 * WRITE3resok resok;
1662 * default:
1663 * WRITE3resfail resfail;
1664 * };
820 */ 1665 */
821static int 1666static int decode_write3resok(struct xdr_stream *xdr,
822nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 1667 struct nfs_writeres *result)
823{ 1668{
824 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 1669 __be32 *p;
825 struct kvec *iov = rcvbuf->head;
826 size_t hdrlen;
827 u32 len, recvd;
828 int status;
829
830 status = ntohl(*p++);
831 p = xdr_decode_post_op_attr(p, fattr);
832
833 if (status != 0)
834 return nfs_stat_to_errno(status);
835
836 /* Convert length of symlink */
837 len = ntohl(*p++);
838 if (len >= rcvbuf->page_len) {
839 dprintk("nfs: server returned giant symlink!\n");
840 return -ENAMETOOLONG;
841 }
842 1670
843 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 1671 p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE);
844 if (iov->iov_len < hdrlen) { 1672 if (unlikely(p == NULL))
845 dprintk("NFS: READLINK reply header overflowed:" 1673 goto out_overflow;
846 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 1674 result->count = be32_to_cpup(p++);
847 return -errno_NFSERR_IO; 1675 result->verf->committed = be32_to_cpup(p++);
848 } else if (iov->iov_len != hdrlen) { 1676 if (unlikely(result->verf->committed > NFS_FILE_SYNC))
849 dprintk("NFS: READLINK header is short. " 1677 goto out_badvalue;
850 "iovec will be shifted.\n"); 1678 memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE);
851 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 1679 return result->count;
852 } 1680out_badvalue:
853 recvd = req->rq_rcv_buf.len - hdrlen; 1681 dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
854 if (recvd < len) { 1682 return -EIO;
855 dprintk("NFS: server cheating in readlink reply: " 1683out_overflow:
856 "count %u > recvd %u\n", len, recvd); 1684 print_overflow_msg(__func__, xdr);
857 return -EIO; 1685 return -EIO;
858 } 1686}
859 1687
860 xdr_terminate_string(rcvbuf, len); 1688static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
861 return 0; 1689 struct nfs_writeres *result)
1690{
1691 enum nfs_stat status;
1692 int error;
1693
1694 error = decode_nfsstat3(xdr, &status);
1695 if (unlikely(error))
1696 goto out;
1697 error = decode_wcc_data(xdr, result->fattr);
1698 if (unlikely(error))
1699 goto out;
1700 if (status != NFS3_OK)
1701 goto out_status;
1702 error = decode_write3resok(xdr, result);
1703out:
1704 return error;
1705out_status:
1706 return nfs_stat_to_errno(status);
862} 1707}
863 1708
864/* 1709/*
865 * Decode READ reply 1710 * 3.3.8 CREATE3res
1711 *
1712 * struct CREATE3resok {
1713 * post_op_fh3 obj;
1714 * post_op_attr obj_attributes;
1715 * wcc_data dir_wcc;
1716 * };
1717 *
1718 * struct CREATE3resfail {
1719 * wcc_data dir_wcc;
1720 * };
1721 *
1722 * union CREATE3res switch (nfsstat3 status) {
1723 * case NFS3_OK:
1724 * CREATE3resok resok;
1725 * default:
1726 * CREATE3resfail resfail;
1727 * };
866 */ 1728 */
867static int 1729static int decode_create3resok(struct xdr_stream *xdr,
868nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) 1730 struct nfs3_diropres *result)
869{ 1731{
870 struct kvec *iov = req->rq_rcv_buf.head; 1732 int error;
871 size_t hdrlen; 1733
872 u32 count, ocount, recvd; 1734 error = decode_post_op_fh3(xdr, result->fh);
873 int status; 1735 if (unlikely(error))
1736 goto out;
1737 error = decode_post_op_attr(xdr, result->fattr);
1738 if (unlikely(error))
1739 goto out;
1740 /* The server isn't required to return a file handle.
1741 * If it didn't, force the client to perform a LOOKUP
1742 * to determine the correct file handle and attribute
1743 * values for the new object. */
1744 if (result->fh->size == 0)
1745 result->fattr->valid = 0;
1746 error = decode_wcc_data(xdr, result->dir_attr);
1747out:
1748 return error;
1749}
874 1750
875 status = ntohl(*p++); 1751static int nfs3_xdr_dec_create3res(struct rpc_rqst *req,
876 p = xdr_decode_post_op_attr(p, res->fattr); 1752 struct xdr_stream *xdr,
1753 struct nfs3_diropres *result)
1754{
1755 enum nfs_stat status;
1756 int error;
1757
1758 error = decode_nfsstat3(xdr, &status);
1759 if (unlikely(error))
1760 goto out;
1761 if (status != NFS3_OK)
1762 goto out_default;
1763 error = decode_create3resok(xdr, result);
1764out:
1765 return error;
1766out_default:
1767 error = decode_wcc_data(xdr, result->dir_attr);
1768 if (unlikely(error))
1769 goto out;
1770 return nfs_stat_to_errno(status);
1771}
877 1772
878 if (status != 0) 1773/*
879 return nfs_stat_to_errno(status); 1774 * 3.3.12 REMOVE3res
1775 *
1776 * struct REMOVE3resok {
1777 * wcc_data dir_wcc;
1778 * };
1779 *
1780 * struct REMOVE3resfail {
1781 * wcc_data dir_wcc;
1782 * };
1783 *
1784 * union REMOVE3res switch (nfsstat3 status) {
1785 * case NFS3_OK:
1786 * REMOVE3resok resok;
1787 * default:
1788 * REMOVE3resfail resfail;
1789 * };
1790 */
1791static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req,
1792 struct xdr_stream *xdr,
1793 struct nfs_removeres *result)
1794{
1795 enum nfs_stat status;
1796 int error;
1797
1798 error = decode_nfsstat3(xdr, &status);
1799 if (unlikely(error))
1800 goto out;
1801 error = decode_wcc_data(xdr, result->dir_attr);
1802 if (unlikely(error))
1803 goto out;
1804 if (status != NFS3_OK)
1805 goto out_status;
1806out:
1807 return error;
1808out_status:
1809 return nfs_stat_to_errno(status);
1810}
880 1811
881 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant 1812/*
882 * in that it puts the count both in the res struct and in the 1813 * 3.3.14 RENAME3res
883 * opaque data count. */ 1814 *
884 count = ntohl(*p++); 1815 * struct RENAME3resok {
885 res->eof = ntohl(*p++); 1816 * wcc_data fromdir_wcc;
886 ocount = ntohl(*p++); 1817 * wcc_data todir_wcc;
1818 * };
1819 *
1820 * struct RENAME3resfail {
1821 * wcc_data fromdir_wcc;
1822 * wcc_data todir_wcc;
1823 * };
1824 *
1825 * union RENAME3res switch (nfsstat3 status) {
1826 * case NFS3_OK:
1827 * RENAME3resok resok;
1828 * default:
1829 * RENAME3resfail resfail;
1830 * };
1831 */
1832static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
1833 struct xdr_stream *xdr,
1834 struct nfs_renameres *result)
1835{
1836 enum nfs_stat status;
1837 int error;
1838
1839 error = decode_nfsstat3(xdr, &status);
1840 if (unlikely(error))
1841 goto out;
1842 error = decode_wcc_data(xdr, result->old_fattr);
1843 if (unlikely(error))
1844 goto out;
1845 error = decode_wcc_data(xdr, result->new_fattr);
1846 if (unlikely(error))
1847 goto out;
1848 if (status != NFS3_OK)
1849 goto out_status;
1850out:
1851 return error;
1852out_status:
1853 return nfs_stat_to_errno(status);
1854}
887 1855
888 if (ocount != count) { 1856/*
889 dprintk("NFS: READ count doesn't match RPC opaque count.\n"); 1857 * 3.3.15 LINK3res
890 return -errno_NFSERR_IO; 1858 *
891 } 1859 * struct LINK3resok {
1860 * post_op_attr file_attributes;
1861 * wcc_data linkdir_wcc;
1862 * };
1863 *
1864 * struct LINK3resfail {
1865 * post_op_attr file_attributes;
1866 * wcc_data linkdir_wcc;
1867 * };
1868 *
1869 * union LINK3res switch (nfsstat3 status) {
1870 * case NFS3_OK:
1871 * LINK3resok resok;
1872 * default:
1873 * LINK3resfail resfail;
1874 * };
1875 */
1876static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1877 struct nfs3_linkres *result)
1878{
1879 enum nfs_stat status;
1880 int error;
1881
1882 error = decode_nfsstat3(xdr, &status);
1883 if (unlikely(error))
1884 goto out;
1885 error = decode_post_op_attr(xdr, result->fattr);
1886 if (unlikely(error))
1887 goto out;
1888 error = decode_wcc_data(xdr, result->dir_attr);
1889 if (unlikely(error))
1890 goto out;
1891 if (status != NFS3_OK)
1892 goto out_status;
1893out:
1894 return error;
1895out_status:
1896 return nfs_stat_to_errno(status);
1897}
892 1898
893 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 1899/**
894 if (iov->iov_len < hdrlen) { 1900 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
895 dprintk("NFS: READ reply header overflowed:" 1901 * the local page cache
896 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 1902 * @xdr: XDR stream where entry resides
897 return -errno_NFSERR_IO; 1903 * @entry: buffer to fill in with entry data
898 } else if (iov->iov_len != hdrlen) { 1904 * @plus: boolean indicating whether this should be a readdirplus entry
899 dprintk("NFS: READ header is short. iovec will be shifted.\n"); 1905 *
900 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen); 1906 * Returns zero if successful, otherwise a negative errno value is
901 } 1907 * returned.
1908 *
1909 * This function is not invoked during READDIR reply decoding, but
1910 * rather whenever an application invokes the getdents(2) system call
1911 * on a directory already in our cache.
1912 *
1913 * 3.3.16 entry3
1914 *
1915 * struct entry3 {
1916 * fileid3 fileid;
1917 * filename3 name;
1918 * cookie3 cookie;
1919 * fhandle3 filehandle;
1920 * post_op_attr3 attributes;
1921 * entry3 *nextentry;
1922 * };
1923 *
1924 * 3.3.17 entryplus3
1925 * struct entryplus3 {
1926 * fileid3 fileid;
1927 * filename3 name;
1928 * cookie3 cookie;
1929 * post_op_attr name_attributes;
1930 * post_op_fh3 name_handle;
1931 * entryplus3 *nextentry;
1932 * };
1933 */
1934int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
1935 int plus)
1936{
1937 struct nfs_entry old = *entry;
1938 __be32 *p;
1939 int error;
902 1940
903 recvd = req->rq_rcv_buf.len - hdrlen; 1941 p = xdr_inline_decode(xdr, 4);
904 if (count > recvd) { 1942 if (unlikely(p == NULL))
905 dprintk("NFS: server cheating in read reply: " 1943 goto out_overflow;
906 "count %u > recvd %u\n", count, recvd); 1944 if (*p == xdr_zero) {
907 count = recvd; 1945 p = xdr_inline_decode(xdr, 4);
908 res->eof = 0; 1946 if (unlikely(p == NULL))
1947 goto out_overflow;
1948 if (*p == xdr_zero)
1949 return -EAGAIN;
1950 entry->eof = 1;
1951 return -EBADCOOKIE;
909 } 1952 }
910 1953
911 if (count < res->count) 1954 error = decode_fileid3(xdr, &entry->ino);
912 res->count = count; 1955 if (unlikely(error))
1956 return error;
913 1957
914 return count; 1958 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
915} 1959 if (unlikely(error))
1960 return error;
916 1961
917/* 1962 entry->prev_cookie = entry->cookie;
918 * Decode WRITE response 1963 error = decode_cookie3(xdr, &entry->cookie);
919 */ 1964 if (unlikely(error))
920static int 1965 return error;
921nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
922{
923 int status;
924 1966
925 status = ntohl(*p++); 1967 entry->d_type = DT_UNKNOWN;
926 p = xdr_decode_wcc_data(p, res->fattr);
927 1968
928 if (status != 0) 1969 if (plus) {
929 return nfs_stat_to_errno(status); 1970 entry->fattr->valid = 0;
1971 error = decode_post_op_attr(xdr, entry->fattr);
1972 if (unlikely(error))
1973 return error;
1974 if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
1975 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
930 1976
931 res->count = ntohl(*p++); 1977 /* In fact, a post_op_fh3: */
932 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++); 1978 p = xdr_inline_decode(xdr, 4);
933 res->verf->verifier[0] = *p++; 1979 if (unlikely(p == NULL))
934 res->verf->verifier[1] = *p++; 1980 goto out_overflow;
1981 if (*p != xdr_zero) {
1982 error = decode_nfs_fh3(xdr, entry->fh);
1983 if (unlikely(error)) {
1984 if (error == -E2BIG)
1985 goto out_truncated;
1986 return error;
1987 }
1988 } else
1989 zero_nfs_fh3(entry->fh);
1990 }
935 1991
936 return res->count; 1992 return 0;
937}
938 1993
939/* 1994out_overflow:
940 * Decode a CREATE response 1995 print_overflow_msg(__func__, xdr);
941 */ 1996 return -EAGAIN;
942static int 1997out_truncated:
943nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 1998 dprintk("NFS: directory entry contains invalid file handle\n");
944{ 1999 *entry = old;
945 int status; 2000 return -EAGAIN;
946
947 status = ntohl(*p++);
948 if (status == 0) {
949 if (*p++) {
950 if (!(p = xdr_decode_fhandle(p, res->fh)))
951 return -errno_NFSERR_IO;
952 p = xdr_decode_post_op_attr(p, res->fattr);
953 } else {
954 memset(res->fh, 0, sizeof(*res->fh));
955 /* Do decode post_op_attr but set it to NULL */
956 p = xdr_decode_post_op_attr(p, res->fattr);
957 res->fattr->valid = 0;
958 }
959 } else {
960 status = nfs_stat_to_errno(status);
961 }
962 p = xdr_decode_wcc_data(p, res->dir_attr);
963 return status;
964} 2001}
965 2002
966/* 2003/*
967 * Decode RENAME reply 2004 * 3.3.16 READDIR3res
2005 *
2006 * struct dirlist3 {
2007 * entry3 *entries;
2008 * bool eof;
2009 * };
2010 *
2011 * struct READDIR3resok {
2012 * post_op_attr dir_attributes;
2013 * cookieverf3 cookieverf;
2014 * dirlist3 reply;
2015 * };
2016 *
2017 * struct READDIR3resfail {
2018 * post_op_attr dir_attributes;
2019 * };
2020 *
2021 * union READDIR3res switch (nfsstat3 status) {
2022 * case NFS3_OK:
2023 * READDIR3resok resok;
2024 * default:
2025 * READDIR3resfail resfail;
2026 * };
2027 *
2028 * Read the directory contents into the page cache, but otherwise
2029 * don't touch them. The actual decoding is done by nfs3_decode_entry()
2030 * during subsequent nfs_readdir() calls.
968 */ 2031 */
969static int 2032static int decode_dirlist3(struct xdr_stream *xdr)
970nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
971{ 2033{
972 int status; 2034 u32 recvd, pglen;
2035 size_t hdrlen;
973 2036
974 if ((status = ntohl(*p++)) != 0) 2037 pglen = xdr->buf->page_len;
975 status = nfs_stat_to_errno(status); 2038 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
976 p = xdr_decode_wcc_data(p, res->old_fattr); 2039 recvd = xdr->buf->len - hdrlen;
977 p = xdr_decode_wcc_data(p, res->new_fattr); 2040 if (unlikely(pglen > recvd))
978 return status; 2041 goto out_cheating;
2042out:
2043 xdr_read_pages(xdr, pglen);
2044 return pglen;
2045out_cheating:
2046 dprintk("NFS: server cheating in readdir result: "
2047 "pglen %u > recvd %u\n", pglen, recvd);
2048 pglen = recvd;
2049 goto out;
979} 2050}
980 2051
981/* 2052static int decode_readdir3resok(struct xdr_stream *xdr,
982 * Decode LINK reply 2053 struct nfs3_readdirres *result)
983 */
984static int
985nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
986{ 2054{
987 int status; 2055 int error;
2056
2057 error = decode_post_op_attr(xdr, result->dir_attr);
2058 if (unlikely(error))
2059 goto out;
2060 /* XXX: do we need to check if result->verf != NULL ? */
2061 error = decode_cookieverf3(xdr, result->verf);
2062 if (unlikely(error))
2063 goto out;
2064 error = decode_dirlist3(xdr);
2065out:
2066 return error;
2067}
988 2068
989 if ((status = ntohl(*p++)) != 0) 2069static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req,
990 status = nfs_stat_to_errno(status); 2070 struct xdr_stream *xdr,
991 p = xdr_decode_post_op_attr(p, res->fattr); 2071 struct nfs3_readdirres *result)
992 p = xdr_decode_wcc_data(p, res->dir_attr); 2072{
993 return status; 2073 enum nfs_stat status;
2074 int error;
2075
2076 error = decode_nfsstat3(xdr, &status);
2077 if (unlikely(error))
2078 goto out;
2079 if (status != NFS3_OK)
2080 goto out_default;
2081 error = decode_readdir3resok(xdr, result);
2082out:
2083 return error;
2084out_default:
2085 error = decode_post_op_attr(xdr, result->dir_attr);
2086 if (unlikely(error))
2087 goto out;
2088 return nfs_stat_to_errno(status);
994} 2089}
995 2090
996/* 2091/*
997 * Decode FSSTAT reply 2092 * 3.3.18 FSSTAT3res
2093 *
2094 * struct FSSTAT3resok {
2095 * post_op_attr obj_attributes;
2096 * size3 tbytes;
2097 * size3 fbytes;
2098 * size3 abytes;
2099 * size3 tfiles;
2100 * size3 ffiles;
2101 * size3 afiles;
2102 * uint32 invarsec;
2103 * };
2104 *
2105 * struct FSSTAT3resfail {
2106 * post_op_attr obj_attributes;
2107 * };
2108 *
2109 * union FSSTAT3res switch (nfsstat3 status) {
2110 * case NFS3_OK:
2111 * FSSTAT3resok resok;
2112 * default:
2113 * FSSTAT3resfail resfail;
2114 * };
998 */ 2115 */
999static int 2116static int decode_fsstat3resok(struct xdr_stream *xdr,
1000nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res) 2117 struct nfs_fsstat *result)
1001{ 2118{
1002 int status; 2119 __be32 *p;
1003
1004 status = ntohl(*p++);
1005
1006 p = xdr_decode_post_op_attr(p, res->fattr);
1007 if (status != 0)
1008 return nfs_stat_to_errno(status);
1009
1010 p = xdr_decode_hyper(p, &res->tbytes);
1011 p = xdr_decode_hyper(p, &res->fbytes);
1012 p = xdr_decode_hyper(p, &res->abytes);
1013 p = xdr_decode_hyper(p, &res->tfiles);
1014 p = xdr_decode_hyper(p, &res->ffiles);
1015 p = xdr_decode_hyper(p, &res->afiles);
1016 2120
2121 p = xdr_inline_decode(xdr, 8 * 6 + 4);
2122 if (unlikely(p == NULL))
2123 goto out_overflow;
2124 p = xdr_decode_size3(p, &result->tbytes);
2125 p = xdr_decode_size3(p, &result->fbytes);
2126 p = xdr_decode_size3(p, &result->abytes);
2127 p = xdr_decode_size3(p, &result->tfiles);
2128 p = xdr_decode_size3(p, &result->ffiles);
2129 xdr_decode_size3(p, &result->afiles);
1017 /* ignore invarsec */ 2130 /* ignore invarsec */
1018 return 0; 2131 return 0;
2132out_overflow:
2133 print_overflow_msg(__func__, xdr);
2134 return -EIO;
2135}
2136
2137static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req,
2138 struct xdr_stream *xdr,
2139 struct nfs_fsstat *result)
2140{
2141 enum nfs_stat status;
2142 int error;
2143
2144 error = decode_nfsstat3(xdr, &status);
2145 if (unlikely(error))
2146 goto out;
2147 error = decode_post_op_attr(xdr, result->fattr);
2148 if (unlikely(error))
2149 goto out;
2150 if (status != NFS3_OK)
2151 goto out_status;
2152 error = decode_fsstat3resok(xdr, result);
2153out:
2154 return error;
2155out_status:
2156 return nfs_stat_to_errno(status);
1019} 2157}
1020 2158
1021/* 2159/*
1022 * Decode FSINFO reply 2160 * 3.3.19 FSINFO3res
2161 *
2162 * struct FSINFO3resok {
2163 * post_op_attr obj_attributes;
2164 * uint32 rtmax;
2165 * uint32 rtpref;
2166 * uint32 rtmult;
2167 * uint32 wtmax;
2168 * uint32 wtpref;
2169 * uint32 wtmult;
2170 * uint32 dtpref;
2171 * size3 maxfilesize;
2172 * nfstime3 time_delta;
2173 * uint32 properties;
2174 * };
2175 *
2176 * struct FSINFO3resfail {
2177 * post_op_attr obj_attributes;
2178 * };
2179 *
2180 * union FSINFO3res switch (nfsstat3 status) {
2181 * case NFS3_OK:
2182 * FSINFO3resok resok;
2183 * default:
2184 * FSINFO3resfail resfail;
2185 * };
1023 */ 2186 */
1024static int 2187static int decode_fsinfo3resok(struct xdr_stream *xdr,
1025nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res) 2188 struct nfs_fsinfo *result)
1026{ 2189{
1027 int status; 2190 __be32 *p;
1028
1029 status = ntohl(*p++);
1030
1031 p = xdr_decode_post_op_attr(p, res->fattr);
1032 if (status != 0)
1033 return nfs_stat_to_errno(status);
1034 2191
1035 res->rtmax = ntohl(*p++); 2192 p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
1036 res->rtpref = ntohl(*p++); 2193 if (unlikely(p == NULL))
1037 res->rtmult = ntohl(*p++); 2194 goto out_overflow;
1038 res->wtmax = ntohl(*p++); 2195 result->rtmax = be32_to_cpup(p++);
1039 res->wtpref = ntohl(*p++); 2196 result->rtpref = be32_to_cpup(p++);
1040 res->wtmult = ntohl(*p++); 2197 result->rtmult = be32_to_cpup(p++);
1041 res->dtpref = ntohl(*p++); 2198 result->wtmax = be32_to_cpup(p++);
1042 p = xdr_decode_hyper(p, &res->maxfilesize); 2199 result->wtpref = be32_to_cpup(p++);
1043 p = xdr_decode_time3(p, &res->time_delta); 2200 result->wtmult = be32_to_cpup(p++);
2201 result->dtpref = be32_to_cpup(p++);
2202 p = xdr_decode_size3(p, &result->maxfilesize);
2203 xdr_decode_nfstime3(p, &result->time_delta);
1044 2204
1045 /* ignore properties */ 2205 /* ignore properties */
1046 res->lease_time = 0; 2206 result->lease_time = 0;
1047 return 0; 2207 return 0;
2208out_overflow:
2209 print_overflow_msg(__func__, xdr);
2210 return -EIO;
2211}
2212
2213static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req,
2214 struct xdr_stream *xdr,
2215 struct nfs_fsinfo *result)
2216{
2217 enum nfs_stat status;
2218 int error;
2219
2220 error = decode_nfsstat3(xdr, &status);
2221 if (unlikely(error))
2222 goto out;
2223 error = decode_post_op_attr(xdr, result->fattr);
2224 if (unlikely(error))
2225 goto out;
2226 if (status != NFS3_OK)
2227 goto out_status;
2228 error = decode_fsinfo3resok(xdr, result);
2229out:
2230 return error;
2231out_status:
2232 return nfs_stat_to_errno(status);
1048} 2233}
1049 2234
1050/* 2235/*
1051 * Decode PATHCONF reply 2236 * 3.3.20 PATHCONF3res
2237 *
2238 * struct PATHCONF3resok {
2239 * post_op_attr obj_attributes;
2240 * uint32 linkmax;
2241 * uint32 name_max;
2242 * bool no_trunc;
2243 * bool chown_restricted;
2244 * bool case_insensitive;
2245 * bool case_preserving;
2246 * };
2247 *
2248 * struct PATHCONF3resfail {
2249 * post_op_attr obj_attributes;
2250 * };
2251 *
2252 * union PATHCONF3res switch (nfsstat3 status) {
2253 * case NFS3_OK:
2254 * PATHCONF3resok resok;
2255 * default:
2256 * PATHCONF3resfail resfail;
2257 * };
1052 */ 2258 */
1053static int 2259static int decode_pathconf3resok(struct xdr_stream *xdr,
1054nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res) 2260 struct nfs_pathconf *result)
1055{ 2261{
1056 int status; 2262 __be32 *p;
1057
1058 status = ntohl(*p++);
1059
1060 p = xdr_decode_post_op_attr(p, res->fattr);
1061 if (status != 0)
1062 return nfs_stat_to_errno(status);
1063 res->max_link = ntohl(*p++);
1064 res->max_namelen = ntohl(*p++);
1065 2263
2264 p = xdr_inline_decode(xdr, 4 * 6);
2265 if (unlikely(p == NULL))
2266 goto out_overflow;
2267 result->max_link = be32_to_cpup(p++);
2268 result->max_namelen = be32_to_cpup(p);
1066 /* ignore remaining fields */ 2269 /* ignore remaining fields */
1067 return 0; 2270 return 0;
2271out_overflow:
2272 print_overflow_msg(__func__, xdr);
2273 return -EIO;
2274}
2275
2276static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req,
2277 struct xdr_stream *xdr,
2278 struct nfs_pathconf *result)
2279{
2280 enum nfs_stat status;
2281 int error;
2282
2283 error = decode_nfsstat3(xdr, &status);
2284 if (unlikely(error))
2285 goto out;
2286 error = decode_post_op_attr(xdr, result->fattr);
2287 if (unlikely(error))
2288 goto out;
2289 if (status != NFS3_OK)
2290 goto out_status;
2291 error = decode_pathconf3resok(xdr, result);
2292out:
2293 return error;
2294out_status:
2295 return nfs_stat_to_errno(status);
1068} 2296}
1069 2297
1070/* 2298/*
1071 * Decode COMMIT reply 2299 * 3.3.21 COMMIT3res
2300 *
2301 * struct COMMIT3resok {
2302 * wcc_data file_wcc;
2303 * writeverf3 verf;
2304 * };
2305 *
2306 * struct COMMIT3resfail {
2307 * wcc_data file_wcc;
2308 * };
2309 *
2310 * union COMMIT3res switch (nfsstat3 status) {
2311 * case NFS3_OK:
2312 * COMMIT3resok resok;
2313 * default:
2314 * COMMIT3resfail resfail;
2315 * };
1072 */ 2316 */
1073static int 2317static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
1074nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 2318 struct xdr_stream *xdr,
2319 struct nfs_writeres *result)
1075{ 2320{
1076 int status; 2321 enum nfs_stat status;
1077 2322 int error;
1078 status = ntohl(*p++); 2323
1079 p = xdr_decode_wcc_data(p, res->fattr); 2324 error = decode_nfsstat3(xdr, &status);
1080 if (status != 0) 2325 if (unlikely(error))
1081 return nfs_stat_to_errno(status); 2326 goto out;
1082 2327 error = decode_wcc_data(xdr, result->fattr);
1083 res->verf->verifier[0] = *p++; 2328 if (unlikely(error))
1084 res->verf->verifier[1] = *p++; 2329 goto out;
1085 return 0; 2330 if (status != NFS3_OK)
2331 goto out_status;
2332 error = decode_writeverf3(xdr, result->verf->verifier);
2333out:
2334 return error;
2335out_status:
2336 return nfs_stat_to_errno(status);
1086} 2337}
1087 2338
1088#ifdef CONFIG_NFS_V3_ACL 2339#ifdef CONFIG_NFS_V3_ACL
1089/* 2340
1090 * Decode GETACL reply 2341static inline int decode_getacl3resok(struct xdr_stream *xdr,
1091 */ 2342 struct nfs3_getaclres *result)
1092static int
1093nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1094 struct nfs3_getaclres *res)
1095{ 2343{
1096 struct xdr_buf *buf = &req->rq_rcv_buf;
1097 int status = ntohl(*p++);
1098 struct posix_acl **acl; 2344 struct posix_acl **acl;
1099 unsigned int *aclcnt; 2345 unsigned int *aclcnt;
1100 int err, base; 2346 size_t hdrlen;
1101 2347 int error;
1102 if (status != 0) 2348
1103 return nfs_stat_to_errno(status); 2349 error = decode_post_op_attr(xdr, result->fattr);
1104 p = xdr_decode_post_op_attr(p, res->fattr); 2350 if (unlikely(error))
1105 res->mask = ntohl(*p++); 2351 goto out;
1106 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 2352 error = decode_uint32(xdr, &result->mask);
1107 return -EINVAL; 2353 if (unlikely(error))
1108 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base; 2354 goto out;
1109 2355 error = -EINVAL;
1110 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL; 2356 if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1111 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL; 2357 goto out;
1112 err = nfsacl_decode(buf, base, aclcnt, acl); 2358
1113 2359 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1114 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL; 2360
1115 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL; 2361 acl = NULL;
1116 if (err > 0) 2362 if (result->mask & NFS_ACL)
1117 err = nfsacl_decode(buf, base + err, aclcnt, acl); 2363 acl = &result->acl_access;
1118 return (err > 0) ? 0 : err; 2364 aclcnt = NULL;
2365 if (result->mask & NFS_ACLCNT)
2366 aclcnt = &result->acl_access_count;
2367 error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl);
2368 if (unlikely(error <= 0))
2369 goto out;
2370
2371 acl = NULL;
2372 if (result->mask & NFS_DFACL)
2373 acl = &result->acl_default;
2374 aclcnt = NULL;
2375 if (result->mask & NFS_DFACLCNT)
2376 aclcnt = &result->acl_default_count;
2377 error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl);
2378 if (unlikely(error <= 0))
2379 return error;
2380 error = 0;
2381out:
2382 return error;
1119} 2383}
1120 2384
1121/* 2385static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req,
1122 * Decode setacl reply. 2386 struct xdr_stream *xdr,
1123 */ 2387 struct nfs3_getaclres *result)
1124static int
1125nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1126{ 2388{
1127 int status = ntohl(*p++); 2389 enum nfs_stat status;
2390 int error;
2391
2392 error = decode_nfsstat3(xdr, &status);
2393 if (unlikely(error))
2394 goto out;
2395 if (status != NFS3_OK)
2396 goto out_default;
2397 error = decode_getacl3resok(xdr, result);
2398out:
2399 return error;
2400out_default:
2401 return nfs_stat_to_errno(status);
2402}
1128 2403
1129 if (status) 2404static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req,
1130 return nfs_stat_to_errno(status); 2405 struct xdr_stream *xdr,
1131 xdr_decode_post_op_attr(p, fattr); 2406 struct nfs_fattr *result)
1132 return 0; 2407{
2408 enum nfs_stat status;
2409 int error;
2410
2411 error = decode_nfsstat3(xdr, &status);
2412 if (unlikely(error))
2413 goto out;
2414 if (status != NFS3_OK)
2415 goto out_default;
2416 error = decode_post_op_attr(xdr, result);
2417out:
2418 return error;
2419out_default:
2420 return nfs_stat_to_errno(status);
1133} 2421}
2422
1134#endif /* CONFIG_NFS_V3_ACL */ 2423#endif /* CONFIG_NFS_V3_ACL */
1135 2424
1136#define PROC(proc, argtype, restype, timer) \ 2425#define PROC(proc, argtype, restype, timer) \
1137[NFS3PROC_##proc] = { \ 2426[NFS3PROC_##proc] = { \
1138 .p_proc = NFS3PROC_##proc, \ 2427 .p_proc = NFS3PROC_##proc, \
1139 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \ 2428 .p_encode = (kxdreproc_t)nfs3_xdr_enc_##argtype##3args, \
1140 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \ 2429 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_##restype##3res, \
1141 .p_arglen = NFS3_##argtype##_sz, \ 2430 .p_arglen = NFS3_##argtype##args_sz, \
1142 .p_replen = NFS3_##restype##_sz, \ 2431 .p_replen = NFS3_##restype##res_sz, \
1143 .p_timer = timer, \ 2432 .p_timer = timer, \
1144 .p_statidx = NFS3PROC_##proc, \ 2433 .p_statidx = NFS3PROC_##proc, \
1145 .p_name = #proc, \ 2434 .p_name = #proc, \
1146 } 2435 }
1147 2436
1148struct rpc_procinfo nfs3_procedures[] = { 2437struct rpc_procinfo nfs3_procedures[] = {
1149 PROC(GETATTR, fhandle, attrstat, 1), 2438 PROC(GETATTR, getattr, getattr, 1),
1150 PROC(SETATTR, sattrargs, wccstat, 0), 2439 PROC(SETATTR, setattr, setattr, 0),
1151 PROC(LOOKUP, diropargs, lookupres, 2), 2440 PROC(LOOKUP, lookup, lookup, 2),
1152 PROC(ACCESS, accessargs, accessres, 1), 2441 PROC(ACCESS, access, access, 1),
1153 PROC(READLINK, readlinkargs, readlinkres, 3), 2442 PROC(READLINK, readlink, readlink, 3),
1154 PROC(READ, readargs, readres, 3), 2443 PROC(READ, read, read, 3),
1155 PROC(WRITE, writeargs, writeres, 4), 2444 PROC(WRITE, write, write, 4),
1156 PROC(CREATE, createargs, createres, 0), 2445 PROC(CREATE, create, create, 0),
1157 PROC(MKDIR, mkdirargs, createres, 0), 2446 PROC(MKDIR, mkdir, create, 0),
1158 PROC(SYMLINK, symlinkargs, createres, 0), 2447 PROC(SYMLINK, symlink, create, 0),
1159 PROC(MKNOD, mknodargs, createres, 0), 2448 PROC(MKNOD, mknod, create, 0),
1160 PROC(REMOVE, removeargs, removeres, 0), 2449 PROC(REMOVE, remove, remove, 0),
1161 PROC(RMDIR, diropargs, wccstat, 0), 2450 PROC(RMDIR, lookup, setattr, 0),
1162 PROC(RENAME, renameargs, renameres, 0), 2451 PROC(RENAME, rename, rename, 0),
1163 PROC(LINK, linkargs, linkres, 0), 2452 PROC(LINK, link, link, 0),
1164 PROC(READDIR, readdirargs, readdirres, 3), 2453 PROC(READDIR, readdir, readdir, 3),
1165 PROC(READDIRPLUS, readdirargs, readdirres, 3), 2454 PROC(READDIRPLUS, readdirplus, readdir, 3),
1166 PROC(FSSTAT, fhandle, fsstatres, 0), 2455 PROC(FSSTAT, getattr, fsstat, 0),
1167 PROC(FSINFO, fhandle, fsinfores, 0), 2456 PROC(FSINFO, getattr, fsinfo, 0),
1168 PROC(PATHCONF, fhandle, pathconfres, 0), 2457 PROC(PATHCONF, getattr, pathconf, 0),
1169 PROC(COMMIT, commitargs, commitres, 5), 2458 PROC(COMMIT, commit, commit, 5),
1170}; 2459};
1171 2460
1172struct rpc_version nfs_version3 = { 2461struct rpc_version nfs_version3 = {
@@ -1179,8 +2468,8 @@ struct rpc_version nfs_version3 = {
1179static struct rpc_procinfo nfs3_acl_procedures[] = { 2468static struct rpc_procinfo nfs3_acl_procedures[] = {
1180 [ACLPROC3_GETACL] = { 2469 [ACLPROC3_GETACL] = {
1181 .p_proc = ACLPROC3_GETACL, 2470 .p_proc = ACLPROC3_GETACL,
1182 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs, 2471 .p_encode = (kxdreproc_t)nfs3_xdr_enc_getacl3args,
1183 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres, 2472 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_getacl3res,
1184 .p_arglen = ACL3_getaclargs_sz, 2473 .p_arglen = ACL3_getaclargs_sz,
1185 .p_replen = ACL3_getaclres_sz, 2474 .p_replen = ACL3_getaclres_sz,
1186 .p_timer = 1, 2475 .p_timer = 1,
@@ -1188,8 +2477,8 @@ static struct rpc_procinfo nfs3_acl_procedures[] = {
1188 }, 2477 },
1189 [ACLPROC3_SETACL] = { 2478 [ACLPROC3_SETACL] = {
1190 .p_proc = ACLPROC3_SETACL, 2479 .p_proc = ACLPROC3_SETACL,
1191 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs, 2480 .p_encode = (kxdreproc_t)nfs3_xdr_enc_setacl3args,
1192 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres, 2481 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_setacl3res,
1193 .p_arglen = ACL3_setaclargs_sz, 2482 .p_arglen = ACL3_setaclargs_sz,
1194 .p_replen = ACL3_setaclres_sz, 2483 .p_replen = ACL3_setaclres_sz,
1195 .p_timer = 0, 2484 .p_timer = 0,