aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs2xdr.c406
1 files changed, 403 insertions, 3 deletions
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 5914a1911c95..869e2151a2b1 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -61,6 +61,23 @@
61#define NFS_readdirres_sz (1) 61#define NFS_readdirres_sz (1)
62#define NFS_statfsres_sz (1+NFS_info_sz) 62#define NFS_statfsres_sz (1+NFS_info_sz)
63 63
64
65/*
66 * While encoding arguments, set up the reply buffer in advance to
67 * receive reply data directly into the page cache.
68 */
69static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
70 unsigned int base, unsigned int len,
71 unsigned int bufsize)
72{
73 struct rpc_auth *auth = req->rq_cred->cr_auth;
74 unsigned int replen;
75
76 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
77 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
78}
79
80
64/* 81/*
65 * Common NFS XDR functions as inlines 82 * Common NFS XDR functions as inlines
66 */ 83 */
@@ -81,7 +98,7 @@ xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle)
81} 98}
82 99
83static inline __be32* 100static inline __be32*
84xdr_encode_time(__be32 *p, struct timespec *timep) 101xdr_encode_time(__be32 *p, const struct timespec *timep)
85{ 102{
86 *p++ = htonl(timep->tv_sec); 103 *p++ = htonl(timep->tv_sec);
87 /* Convert nanoseconds into microseconds */ 104 /* Convert nanoseconds into microseconds */
@@ -90,7 +107,7 @@ xdr_encode_time(__be32 *p, struct timespec *timep)
90} 107}
91 108
92static inline __be32* 109static inline __be32*
93xdr_encode_current_server_time(__be32 *p, struct timespec *timep) 110xdr_encode_current_server_time(__be32 *p, const struct timespec *timep)
94{ 111{
95 /* 112 /*
96 * Passing the invalid value useconds=1000000 is a 113 * Passing the invalid value useconds=1000000 is a
@@ -174,6 +191,136 @@ xdr_encode_sattr(__be32 *p, struct iattr *attr)
174} 191}
175 192
176/* 193/*
194 * Encode/decode NFSv2 basic data types
195 *
196 * Basic NFSv2 data types are defined in section 2.3 of RFC 1094:
197 * "NFS: Network File System Protocol Specification".
198 *
199 * Not all basic data types have their own encoding and decoding
200 * functions. For run-time efficiency, some data types are encoded
201 * or decoded inline.
202 */
203
204/*
205 * 2.3.3. fhandle
206 *
207 * typedef opaque fhandle[FHSIZE];
208 */
209static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
210{
211 __be32 *p;
212
213 BUG_ON(fh->size != NFS2_FHSIZE);
214 p = xdr_reserve_space(xdr, NFS2_FHSIZE);
215 memcpy(p, fh->data, NFS2_FHSIZE);
216}
217
218/*
219 * 2.3.6. sattr
220 *
221 * struct sattr {
222 * unsigned int mode;
223 * unsigned int uid;
224 * unsigned int gid;
225 * unsigned int size;
226 * timeval atime;
227 * timeval mtime;
228 * };
229 */
230
231#define NFS2_SATTR_NOT_SET (0xffffffff)
232
233static __be32 *xdr_time_not_set(__be32 *p)
234{
235 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
236 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
237 return p;
238}
239
240static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
241{
242 __be32 *p;
243
244 p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
245
246 if (attr->ia_valid & ATTR_MODE)
247 *p++ = cpu_to_be32(attr->ia_mode);
248 else
249 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
250 if (attr->ia_valid & ATTR_UID)
251 *p++ = cpu_to_be32(attr->ia_uid);
252 else
253 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
254 if (attr->ia_valid & ATTR_GID)
255 *p++ = cpu_to_be32(attr->ia_gid);
256 else
257 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
258 if (attr->ia_valid & ATTR_SIZE)
259 *p++ = cpu_to_be32((u32)attr->ia_size);
260 else
261 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
262
263 if (attr->ia_valid & ATTR_ATIME_SET)
264 p = xdr_encode_time(p, &attr->ia_atime);
265 else if (attr->ia_valid & ATTR_ATIME)
266 p = xdr_encode_current_server_time(p, &attr->ia_atime);
267 else
268 p = xdr_time_not_set(p);
269 if (attr->ia_valid & ATTR_MTIME_SET)
270 xdr_encode_time(p, &attr->ia_mtime);
271 else if (attr->ia_valid & ATTR_MTIME)
272 xdr_encode_current_server_time(p, &attr->ia_mtime);
273 else
274 xdr_time_not_set(p);
275}
276
277/*
278 * 2.3.7. filename
279 *
280 * typedef string filename<MAXNAMLEN>;
281 */
282static void encode_filename(struct xdr_stream *xdr,
283 const char *name, u32 length)
284{
285 __be32 *p;
286
287 BUG_ON(length > NFS2_MAXNAMLEN);
288 p = xdr_reserve_space(xdr, 4 + length);
289 xdr_encode_opaque(p, name, length);
290}
291
292/*
293 * 2.3.8. path
294 *
295 * typedef string path<MAXPATHLEN>;
296 */
297static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
298{
299 __be32 *p;
300
301 BUG_ON(length > NFS2_MAXPATHLEN);
302 p = xdr_reserve_space(xdr, 4);
303 *p = cpu_to_be32(length);
304 xdr_write_pages(xdr, pages, 0, length);
305}
306
307/*
308 * 2.3.10. diropargs
309 *
310 * struct diropargs {
311 * fhandle dir;
312 * filename name;
313 * };
314 */
315static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
316 const char *name, u32 length)
317{
318 encode_fhandle(xdr, fh);
319 encode_filename(xdr, name, length);
320}
321
322
323/*
177 * NFS encode functions 324 * NFS encode functions
178 */ 325 */
179/* 326/*
@@ -188,6 +335,16 @@ nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
188 return 0; 335 return 0;
189} 336}
190 337
338static int nfs2_xdr_enc_fhandle(struct rpc_rqst *req, __be32 *p,
339 const struct nfs_fh *fh)
340{
341 struct xdr_stream xdr;
342
343 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
344 encode_fhandle(&xdr, fh);
345 return 0;
346}
347
191/* 348/*
192 * Encode SETATTR arguments 349 * Encode SETATTR arguments
193 */ 350 */
@@ -201,6 +358,25 @@ nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
201} 358}
202 359
203/* 360/*
361 * 2.2.3. sattrargs
362 *
363 * struct sattrargs {
364 * fhandle file;
365 * sattr attributes;
366 * };
367 */
368static int nfs2_xdr_enc_sattrargs(struct rpc_rqst *req, __be32 *p,
369 const struct nfs_sattrargs *args)
370{
371 struct xdr_stream xdr;
372
373 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
374 encode_fhandle(&xdr, args->fh);
375 encode_sattr(&xdr, args->sattr);
376 return 0;
377}
378
379/*
204 * Encode directory ops argument 380 * Encode directory ops argument
205 * LOOKUP, RMDIR 381 * LOOKUP, RMDIR
206 */ 382 */
@@ -213,6 +389,16 @@ nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
213 return 0; 389 return 0;
214} 390}
215 391
392static int nfs2_xdr_enc_diropargs(struct rpc_rqst *req, __be32 *p,
393 const struct nfs_diropargs *args)
394{
395 struct xdr_stream xdr;
396
397 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
398 encode_diropargs(&xdr, args->fh, args->name, args->len);
399 return 0;
400}
401
216/* 402/*
217 * Encode REMOVE argument 403 * Encode REMOVE argument
218 */ 404 */
@@ -225,6 +411,18 @@ nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs
225 return 0; 411 return 0;
226} 412}
227 413
414static int nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req, __be32 *p,
415 const struct nfs_readlinkargs *args)
416{
417 struct xdr_stream xdr;
418
419 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
420 encode_fhandle(&xdr, args->fh);
421 prepare_reply_buffer(req, args->pages, args->pgbase,
422 args->pglen, NFS_readlinkres_sz);
423 return 0;
424}
425
228/* 426/*
229 * Arguments to a READ call. Since we read data directly into the page 427 * Arguments to a READ call. Since we read data directly into the page
230 * cache, we also set up the reply iovec here so that iov[1] points 428 * cache, we also set up the reply iovec here so that iov[1] points
@@ -253,6 +451,44 @@ nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
253} 451}
254 452
255/* 453/*
454 * 2.2.7. readargs
455 *
456 * struct readargs {
457 * fhandle file;
458 * unsigned offset;
459 * unsigned count;
460 * unsigned totalcount;
461 * };
462 */
463static void encode_readargs(struct xdr_stream *xdr,
464 const struct nfs_readargs *args)
465{
466 u32 offset = args->offset;
467 u32 count = args->count;
468 __be32 *p;
469
470 encode_fhandle(xdr, args->fh);
471
472 p = xdr_reserve_space(xdr, 4 + 4 + 4);
473 *p++ = cpu_to_be32(offset);
474 *p++ = cpu_to_be32(count);
475 *p = cpu_to_be32(count);
476}
477
478static int nfs2_xdr_enc_readargs(struct rpc_rqst *req, __be32 *p,
479 const struct nfs_readargs *args)
480{
481 struct xdr_stream xdr;
482
483 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
484 encode_readargs(&xdr, args);
485 prepare_reply_buffer(req, args->pages, args->pgbase,
486 args->count, NFS_readres_sz);
487 req->rq_rcv_buf.flags |= XDRBUF_READ;
488 return 0;
489}
490
491/*
256 * Decode READ reply 492 * Decode READ reply
257 */ 493 */
258static int 494static int
@@ -318,6 +554,47 @@ nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
318} 554}
319 555
320/* 556/*
557 * 2.2.9. writeargs
558 *
559 * struct writeargs {
560 * fhandle file;
561 * unsigned beginoffset;
562 * unsigned offset;
563 * unsigned totalcount;
564 * nfsdata data;
565 * };
566 */
567static void encode_writeargs(struct xdr_stream *xdr,
568 const struct nfs_writeargs *args)
569{
570 u32 offset = args->offset;
571 u32 count = args->count;
572 __be32 *p;
573
574 encode_fhandle(xdr, args->fh);
575
576 p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
577 *p++ = cpu_to_be32(offset);
578 *p++ = cpu_to_be32(offset);
579 *p++ = cpu_to_be32(count);
580
581 /* nfsdata */
582 *p = cpu_to_be32(count);
583 xdr_write_pages(xdr, args->pages, args->pgbase, count);
584}
585
586static int nfs2_xdr_enc_writeargs(struct rpc_rqst *req, __be32 *p,
587 const struct nfs_writeargs *args)
588{
589 struct xdr_stream xdr;
590
591 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
592 encode_writeargs(&xdr, args);
593 xdr.buf->flags |= XDRBUF_WRITE;
594 return 0;
595}
596
597/*
321 * Encode create arguments 598 * Encode create arguments
322 * CREATE, MKDIR 599 * CREATE, MKDIR
323 */ 600 */
@@ -332,6 +609,35 @@ nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
332} 609}
333 610
334/* 611/*
612 * 2.2.10. createargs
613 *
614 * struct createargs {
615 * diropargs where;
616 * sattr attributes;
617 * };
618 */
619static int nfs2_xdr_enc_createargs(struct rpc_rqst *req, __be32 *p,
620 const struct nfs_createargs *args)
621{
622 struct xdr_stream xdr;
623
624 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
625 encode_diropargs(&xdr, args->fh, args->name, args->len);
626 encode_sattr(&xdr, args->sattr);
627 return 0;
628}
629
630static int nfs2_xdr_enc_removeargs(struct rpc_rqst *req, __be32 *p,
631 const struct nfs_removeargs *args)
632{
633 struct xdr_stream xdr;
634
635 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
636 encode_diropargs(&xdr, args->fh, args->name.name, args->name.len);
637 return 0;
638}
639
640/*
335 * Encode RENAME arguments 641 * Encode RENAME arguments
336 */ 642 */
337static int 643static int
@@ -346,6 +652,27 @@ nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
346} 652}
347 653
348/* 654/*
655 * 2.2.12. renameargs
656 *
657 * struct renameargs {
658 * diropargs from;
659 * diropargs to;
660 * };
661 */
662static int nfs2_xdr_enc_renameargs(struct rpc_rqst *req, __be32 *p,
663 const struct nfs_renameargs *args)
664{
665 const struct qstr *old = args->old_name;
666 const struct qstr *new = args->new_name;
667 struct xdr_stream xdr;
668
669 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
670 encode_diropargs(&xdr, args->old_dir, old->name, old->len);
671 encode_diropargs(&xdr, args->new_dir, new->name, new->len);
672 return 0;
673}
674
675/*
349 * Encode LINK arguments 676 * Encode LINK arguments
350 */ 677 */
351static int 678static int
@@ -359,6 +686,25 @@ nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args)
359} 686}
360 687
361/* 688/*
689 * 2.2.13. linkargs
690 *
691 * struct linkargs {
692 * fhandle from;
693 * diropargs to;
694 * };
695 */
696static int nfs2_xdr_enc_linkargs(struct rpc_rqst *req, __be32 *p,
697 const struct nfs_linkargs *args)
698{
699 struct xdr_stream xdr;
700
701 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
702 encode_fhandle(&xdr, args->fromfh);
703 encode_diropargs(&xdr, args->tofh, args->toname, args->tolen);
704 return 0;
705}
706
707/*
362 * Encode SYMLINK arguments 708 * Encode SYMLINK arguments
363 */ 709 */
364static int 710static int
@@ -388,6 +734,27 @@ nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *arg
388} 734}
389 735
390/* 736/*
737 * 2.2.14. symlinkargs
738 *
739 * struct symlinkargs {
740 * diropargs from;
741 * path to;
742 * sattr attributes;
743 * };
744 */
745static int nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req, __be32 *p,
746 const struct nfs_symlinkargs *args)
747{
748 struct xdr_stream xdr;
749
750 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
751 encode_diropargs(&xdr, args->fromfh, args->fromname, args->fromlen);
752 encode_path(&xdr, args->pages, args->pathlen);
753 encode_sattr(&xdr, args->sattr);
754 return 0;
755}
756
757/*
391 * Encode arguments to readdir call 758 * Encode arguments to readdir call
392 */ 759 */
393static int 760static int
@@ -409,6 +776,39 @@ nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *arg
409} 776}
410 777
411/* 778/*
779 * 2.2.17. readdirargs
780 *
781 * struct readdirargs {
782 * fhandle dir;
783 * nfscookie cookie;
784 * unsigned count;
785 * };
786 */
787static void encode_readdirargs(struct xdr_stream *xdr,
788 const struct nfs_readdirargs *args)
789{
790 __be32 *p;
791
792 encode_fhandle(xdr, args->fh);
793
794 p = xdr_reserve_space(xdr, 4 + 4);
795 *p++ = cpu_to_be32(args->cookie);
796 *p = cpu_to_be32(args->count);
797}
798
799static int nfs2_xdr_enc_readdirargs(struct rpc_rqst *req, __be32 *p,
800 const struct nfs_readdirargs *args)
801{
802 struct xdr_stream xdr;
803
804 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
805 encode_readdirargs(&xdr, args);
806 prepare_reply_buffer(req, args->pages, 0,
807 args->count, NFS_readdirres_sz);
808 return 0;
809}
810
811/*
412 * Decode the result of a readdir call. 812 * Decode the result of a readdir call.
413 * We're not really decoding anymore, we just leave the buffer untouched 813 * We're not really decoding anymore, we just leave the buffer untouched
414 * and only check that it is syntactically correct. 814 * and only check that it is syntactically correct.
@@ -698,7 +1098,7 @@ nfs_stat_to_errno(int stat)
698#define PROC(proc, argtype, restype, timer) \ 1098#define PROC(proc, argtype, restype, timer) \
699[NFSPROC_##proc] = { \ 1099[NFSPROC_##proc] = { \
700 .p_proc = NFSPROC_##proc, \ 1100 .p_proc = NFSPROC_##proc, \
701 .p_encode = (kxdrproc_t) nfs_xdr_##argtype, \ 1101 .p_encode = (kxdrproc_t)nfs2_xdr_enc_##argtype, \
702 .p_decode = (kxdrproc_t) nfs_xdr_##restype, \ 1102 .p_decode = (kxdrproc_t) nfs_xdr_##restype, \
703 .p_arglen = NFS_##argtype##_sz, \ 1103 .p_arglen = NFS_##argtype##_sz, \
704 .p_replen = NFS_##restype##_sz, \ 1104 .p_replen = NFS_##restype##_sz, \