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

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

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/fs/nfs/nfs2xdr.c
  3  *
  4  * XDR functions to encode/decode NFS RPC arguments and results.
  5  *
  6  * Copyright (C) 1992, 1993, 1994  Rick Sladkey
  7  * Copyright (C) 1996 Olaf Kirch
  8  * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>
  9  *              FIFO's need special handling in NFSv2
 10  */
 11 
 12 #include <linux/param.h>
 13 #include <linux/sched.h>
 14 #include <linux/mm.h>
 15 #include <linux/malloc.h>
 16 #include <linux/utsname.h>
 17 #include <linux/errno.h>
 18 #include <linux/string.h>
 19 #include <linux/in.h>
 20 #include <linux/pagemap.h>
 21 #include <linux/proc_fs.h>
 22 #include <linux/sunrpc/clnt.h>
 23 #include <linux/nfs.h>
 24 #include <linux/nfs2.h>
 25 #include <linux/nfs_fs.h>
 26 
 27 /* Uncomment this to support servers requiring longword lengths */
 28 #define NFS_PAD_WRITES 1
 29 
 30 #define NFSDBG_FACILITY         NFSDBG_XDR
 31 /* #define NFS_PARANOIA 1 */
 32 
 33 extern int                      nfs_stat_to_errno(int stat);
 34 
 35 /* Mapping from NFS error code to "errno" error code. */
 36 #define errno_NFSERR_IO         EIO
 37 
 38 /*
 39  * Declare the space requirements for NFS arguments and replies as
 40  * number of 32bit-words
 41  */
 42 #define NFS_fhandle_sz          8
 43 #define NFS_sattr_sz            8
 44 #define NFS_filename_sz         1+(NFS2_MAXNAMLEN>>2)
 45 #define NFS_path_sz             1+(NFS2_MAXPATHLEN>>2)
 46 #define NFS_fattr_sz            17
 47 #define NFS_info_sz             5
 48 #define NFS_entry_sz            NFS_filename_sz+3
 49 
 50 #define NFS_enc_void_sz         0
 51 #define NFS_diropargs_sz        NFS_fhandle_sz+NFS_filename_sz
 52 #define NFS_sattrargs_sz        NFS_fhandle_sz+NFS_sattr_sz
 53 #define NFS_readlinkargs_sz     NFS_fhandle_sz
 54 #define NFS_readargs_sz         NFS_fhandle_sz+3
 55 #define NFS_writeargs_sz        NFS_fhandle_sz+4
 56 #define NFS_createargs_sz       NFS_diropargs_sz+NFS_sattr_sz
 57 #define NFS_renameargs_sz       NFS_diropargs_sz+NFS_diropargs_sz
 58 #define NFS_linkargs_sz         NFS_fhandle_sz+NFS_diropargs_sz
 59 #define NFS_symlinkargs_sz      NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz
 60 #define NFS_readdirargs_sz      NFS_fhandle_sz+2
 61 
 62 #define NFS_dec_void_sz         0
 63 #define NFS_attrstat_sz         1+NFS_fattr_sz
 64 #define NFS_diropres_sz         1+NFS_fhandle_sz+NFS_fattr_sz
 65 #define NFS_readlinkres_sz      1
 66 #define NFS_readres_sz          1+NFS_fattr_sz+1
 67 #define NFS_writeres_sz         NFS_attrstat_sz
 68 #define NFS_stat_sz             1
 69 #define NFS_readdirres_sz       1
 70 #define NFS_statfsres_sz        1+NFS_info_sz
 71 
 72 /*
 73  * Common NFS XDR functions as inlines
 74  */
 75 static inline u32 *
 76 xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
 77 {
 78         memcpy(p, fhandle->data, NFS2_FHSIZE);
 79         return p + XDR_QUADLEN(NFS2_FHSIZE);
 80 }
 81 
 82 static inline u32 *
 83 xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
 84 {
 85         /* Zero handle first to allow comparisons */
 86         memset(fhandle, 0, sizeof(*fhandle));
 87         /* NFSv2 handles have a fixed length */
 88         fhandle->size = NFS2_FHSIZE;
 89         memcpy(fhandle->data, p, NFS2_FHSIZE);
 90         return p + XDR_QUADLEN(NFS2_FHSIZE);
 91 }
 92 
 93 static inline u32 *
 94 xdr_decode_string2(u32 *p, char **string, unsigned int *len,
 95                         unsigned int maxlen)
 96 {
 97         *len = ntohl(*p++);
 98         if (*len > maxlen)
 99                 return NULL;
100         *string = (char *) p;
101         return p + XDR_QUADLEN(*len);
102 }
103 
104 static inline u32*
105 xdr_decode_time(u32 *p, u64 *timep)
106 {
107         u64 tmp = (u64)ntohl(*p++) << 32;
108         *timep = tmp + (u64)ntohl(*p++);
109         return p;
110 }
111 
112 static inline u32 *
113 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
114 {
115         fattr->type = (enum nfs_ftype) ntohl(*p++);
116         fattr->mode = ntohl(*p++);
117         fattr->nlink = ntohl(*p++);
118         fattr->uid = ntohl(*p++);
119         fattr->gid = ntohl(*p++);
120         fattr->size = ntohl(*p++);
121         fattr->du.nfs2.blocksize = ntohl(*p++);
122         fattr->rdev = ntohl(*p++);
123         fattr->du.nfs2.blocks = ntohl(*p++);
124         fattr->fsid = ntohl(*p++);
125         fattr->fileid = ntohl(*p++);
126         p = xdr_decode_time(p, &fattr->atime);
127         p = xdr_decode_time(p, &fattr->mtime);
128         p = xdr_decode_time(p, &fattr->ctime);
129         fattr->valid |= NFS_ATTR_FATTR;
130         if (fattr->type == NFCHR && fattr->rdev == NFS2_FIFO_DEV) {
131                 fattr->type = NFFIFO;
132                 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
133                 fattr->rdev = 0;
134         }
135         return p;
136 }
137 
138 #define SATTR(p, attr, flag, field) \
139         *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0
140 static inline u32 *
141 xdr_encode_sattr(u32 *p, struct iattr *attr)
142 {
143         SATTR(p, attr, ATTR_MODE, ia_mode);
144         SATTR(p, attr, ATTR_UID, ia_uid);
145         SATTR(p, attr, ATTR_GID, ia_gid);
146         SATTR(p, attr, ATTR_SIZE, ia_size);
147 
148         if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) {
149                 *p++ = htonl(attr->ia_atime);
150                 *p++ = 0;
151         } else {
152                 *p++ = ~(u32) 0;
153                 *p++ = ~(u32) 0;
154         }
155 
156         if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) {
157                 *p++ = htonl(attr->ia_mtime);
158                 *p++ = 0;
159         } else {
160                 *p++ = ~(u32) 0;        
161                 *p++ = ~(u32) 0;
162         }
163         return p;
164 }
165 #undef SATTR
166 
167 /*
168  * NFS encode functions
169  */
170 /*
171  * Encode void argument
172  */
173 static int
174 nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
175 {
176         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
177         return 0;
178 }
179 
180 /*
181  * Encode file handle argument
182  * GETATTR, READLINK, STATFS
183  */
184 static int
185 nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
186 {
187         p = xdr_encode_fhandle(p, fh);
188         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
189         return 0;
190 }
191 
192 /*
193  * Encode SETATTR arguments
194  */
195 static int
196 nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args)
197 {
198         p = xdr_encode_fhandle(p, args->fh);
199         p = xdr_encode_sattr(p, args->sattr);
200         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
201         return 0;
202 }
203 
204 /*
205  * Encode directory ops argument
206  * LOOKUP, REMOVE, RMDIR
207  */
208 static int
209 nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args)
210 {
211         p = xdr_encode_fhandle(p, args->fh);
212         p = xdr_encode_array(p, args->name, args->len);
213         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
214         return 0;
215 }
216 
217 /*
218  * Arguments to a READ call. Since we read data directly into the page
219  * cache, we also set up the reply iovec here so that iov[1] points
220  * exactly to the page we want to fetch.
221  */
222 static int
223 nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
224 {
225         struct rpc_auth *auth = req->rq_task->tk_auth;
226         int             buflen, replen;
227         unsigned int    nr;
228 
229         p = xdr_encode_fhandle(p, args->fh);
230         *p++ = htonl(args->offset);
231         *p++ = htonl(args->count);
232         *p++ = htonl(args->count);
233         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
234 
235         /* Get the number of buffers in the receive iovec */
236         nr = args->nriov;
237 
238         if (nr+2 > MAX_IOVEC) {
239                 printk(KERN_ERR "NFS: Bad number of iov's in xdr_readargs\n");
240                 return -EINVAL;
241         }
242 
243         /* set up reply iovec */
244         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
245         buflen = req->rq_rvec[0].iov_len;
246         req->rq_rvec[0].iov_len  = replen;
247         /* Copy the iovec */
248         memcpy(req->rq_rvec + 1, args->iov, nr * sizeof(struct iovec));
249 
250         req->rq_rvec[nr+1].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen;
251         req->rq_rvec[nr+1].iov_len  = buflen - replen;
252         req->rq_rlen = args->count + buflen;
253         req->rq_rnr += nr+1;
254 
255         return 0;
256 }
257 
258 /*
259  * Decode READ reply
260  */
261 static int
262 nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
263 {
264         struct iovec *iov = req->rq_rvec;
265         int     status, count, recvd, hdrlen;
266 
267         if ((status = ntohl(*p++)))
268                 return -nfs_stat_to_errno(status);
269         p = xdr_decode_fattr(p, res->fattr);
270 
271         count = ntohl(*p++);
272         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
273         recvd = req->rq_rlen - hdrlen;
274         if (p != iov[req->rq_rnr-1].iov_base) {
275                 /* Unexpected reply header size. Punt.
276                  * XXX: Move iovec contents to align data on page
277                  * boundary and adjust RPC header size guess */
278                 printk(KERN_WARNING "NFS: Odd RPC header size in read reply: %d\n", hdrlen);
279                 return -errno_NFSERR_IO;
280         }
281         if (count > recvd) {
282                 printk(KERN_WARNING "NFS: server cheating in read reply: "
283                         "count %d > recvd %d\n", count, recvd);
284                 count = recvd;
285         }
286 
287         dprintk("RPC:      readres OK count %d\n", count);
288         if (count < res->count) {
289                 xdr_zero_iovec(iov+1, req->rq_rnr-2, res->count - count);
290                 res->count = count;
291                 res->eof = 1;  /* Silly NFSv3ism which can't be helped */
292         } else
293                 res->eof = 0;
294 
295         return count;
296 }
297 
298 
299 /*
300  * Write arguments. Splice the buffer to be written into the iovec.
301  */
302 static int
303 nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
304 {
305         unsigned int nr;
306         u32 count = args->count;
307 
308         p = xdr_encode_fhandle(p, args->fh);
309         *p++ = htonl(args->offset);
310         *p++ = htonl(args->offset);
311         *p++ = htonl(count);
312         *p++ = htonl(count);
313         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
314 
315         /* Get the number of buffers in the send iovec */
316         nr = args->nriov;
317 
318         if (nr+2 > MAX_IOVEC) {
319                 printk(KERN_ERR "NFS: Bad number of iov's in xdr_writeargs "
320                         "(nr %d max %d)\n", nr, MAX_IOVEC);
321                 return -EINVAL;
322         }
323 
324         /* Copy the iovec */
325         memcpy(req->rq_svec + 1, args->iov, nr * sizeof(struct iovec));
326 
327 #ifdef NFS_PAD_WRITES
328         /*
329          * Some old servers require that the message length
330          * be a multiple of 4, so we pad it here if needed.
331          */
332         if (count & 3) {
333                 struct iovec    *iov = req->rq_svec + nr + 1;
334                 int             pad = 4 - (count & 3);
335 
336                 iov->iov_base = (void *) "\0\0\0";
337                 iov->iov_len  = pad;
338                 count += pad;
339                 nr++;
340         }
341 #endif
342         req->rq_slen += count;
343         req->rq_snr += nr;
344 
345         return 0;
346 }
347 
348 /*
349  * Encode create arguments
350  * CREATE, MKDIR
351  */
352 static int
353 nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args)
354 {
355         p = xdr_encode_fhandle(p, args->fh);
356         p = xdr_encode_array(p, args->name, args->len);
357         p = xdr_encode_sattr(p, args->sattr);
358         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
359         return 0;
360 }
361 
362 /*
363  * Encode RENAME arguments
364  */
365 static int
366 nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args)
367 {
368         p = xdr_encode_fhandle(p, args->fromfh);
369         p = xdr_encode_array(p, args->fromname, args->fromlen);
370         p = xdr_encode_fhandle(p, args->tofh);
371         p = xdr_encode_array(p, args->toname, args->tolen);
372         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
373         return 0;
374 }
375 
376 /*
377  * Encode LINK arguments
378  */
379 static int
380 nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
381 {
382         p = xdr_encode_fhandle(p, args->fromfh);
383         p = xdr_encode_fhandle(p, args->tofh);
384         p = xdr_encode_array(p, args->toname, args->tolen);
385         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
386         return 0;
387 }
388 
389 /*
390  * Encode SYMLINK arguments
391  */
392 static int
393 nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
394 {
395         p = xdr_encode_fhandle(p, args->fromfh);
396         p = xdr_encode_array(p, args->fromname, args->fromlen);
397         p = xdr_encode_array(p, args->topath, args->tolen);
398         p = xdr_encode_sattr(p, args->sattr);
399         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
400         return 0;
401 }
402 
403 /*
404  * Encode arguments to readdir call
405  */
406 static int
407 nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args)
408 {
409         struct rpc_task *task = req->rq_task;
410         struct rpc_auth *auth = task->tk_auth;
411         u32             bufsiz = args->bufsiz;
412         int             buflen, replen;
413 
414         /*
415          * Some servers (e.g. HP OS 9.5) seem to expect the buffer size
416          * to be in longwords ... check whether to convert the size.
417          */
418         if (task->tk_client->cl_flags & NFS_CLNTF_BUFSIZE)
419                 bufsiz = bufsiz >> 2;
420 
421         p = xdr_encode_fhandle(p, args->fh);
422         *p++ = htonl(args->cookie);
423         *p++ = htonl(bufsiz); /* see above */
424         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
425 
426         /* set up reply iovec */
427         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
428         buflen = req->rq_rvec[0].iov_len;
429         req->rq_rvec[0].iov_len  = replen;
430         req->rq_rvec[1].iov_base = args->buffer;
431         req->rq_rvec[1].iov_len  = args->bufsiz;
432         req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen;
433         req->rq_rvec[2].iov_len  = buflen - replen;
434         req->rq_rlen = buflen + args->bufsiz;
435         req->rq_rnr += 2;
436 
437         return 0;
438 }
439 
440 /*
441  * Decode the result of a readdir call.
442  * We're not really decoding anymore, we just leave the buffer untouched
443  * and only check that it is syntactically correct.
444  * The real decoding happens in nfs_decode_entry below, called directly
445  * from nfs_readdir for each entry.
446  */
447 static int
448 nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs_readdirres *res)
449 {
450         struct iovec            *iov = req->rq_rvec;
451         int                      status, nr;
452         u32                     *end, *entry, len;
453 
454         if ((status = ntohl(*p++)))
455                 return -nfs_stat_to_errno(status);
456         if ((void *) p != ((u8 *) iov->iov_base+iov->iov_len)) {
457                 /* Unexpected reply header size. Punt. */
458                 printk(KERN_WARNING "NFS: Odd RPC header size in readdirres reply\n");
459                 return -errno_NFSERR_IO;
460         }
461 
462         /* Get start and end address of XDR data */
463         p   = (u32 *) iov[1].iov_base;
464         end = (u32 *) ((u8 *) p + iov[1].iov_len);
465 
466         /* Get start and end of dirent buffer */
467         if (res->buffer != p) {
468                 printk(KERN_ERR "NFS: Bad result buffer in readdir\n");
469                 return -errno_NFSERR_IO;
470         }
471 
472         for (nr = 0; *p++; nr++) {
473                 entry = p - 1;
474                 p++; /* fileid */
475                 len = ntohl(*p++);
476                 p += XDR_QUADLEN(len) + 1;      /* name plus cookie */
477                 if (len > NFS2_MAXNAMLEN) {
478                         printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n",
479                                                 len);
480                         return -errno_NFSERR_IO;
481                 }
482                 if (p + 2 > end) {
483                         printk(KERN_NOTICE
484                                 "NFS: short packet in readdir reply!\n");
485                         entry[0] = entry[1] = 0;
486                         break;
487                 }
488         }
489         return nr;
490 }
491 
492 u32 *
493 nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
494 {
495         if (!*p++) {
496                 if (!*p)
497                         return ERR_PTR(-EAGAIN);
498                 entry->eof = 1;
499                 return ERR_PTR(-EBADCOOKIE);
500         }
501 
502         entry->ino        = ntohl(*p++);
503         entry->len        = ntohl(*p++);
504         entry->name       = (const char *) p;
505         p                += XDR_QUADLEN(entry->len);
506         entry->prev_cookie        = entry->cookie;
507         entry->cookie     = ntohl(*p++);
508         entry->eof        = !p[0] && p[1];
509 
510         return p;
511 }
512 
513 /*
514  * NFS XDR decode functions
515  */
516 /*
517  * Decode void reply
518  */
519 static int
520 nfs_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
521 {
522         return 0;
523 }
524 
525 /*
526  * Decode simple status reply
527  */
528 static int
529 nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy)
530 {
531         int     status;
532 
533         if ((status = ntohl(*p++)) != 0)
534                 status = -nfs_stat_to_errno(status);
535         return status;
536 }
537 
538 /*
539  * Decode attrstat reply
540  * GETATTR, SETATTR, WRITE
541  */
542 static int
543 nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
544 {
545         int     status;
546 
547         if ((status = ntohl(*p++)))
548                 return -nfs_stat_to_errno(status);
549         xdr_decode_fattr(p, fattr);
550         return 0;
551 }
552 
553 /*
554  * Decode diropres reply
555  * LOOKUP, CREATE, MKDIR
556  */
557 static int
558 nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res)
559 {
560         int     status;
561 
562         if ((status = ntohl(*p++)))
563                 return -nfs_stat_to_errno(status);
564         p = xdr_decode_fhandle(p, res->fh);
565         xdr_decode_fattr(p, res->fattr);
566         return 0;
567 }
568 
569 /*
570  * Encode READLINK args
571  */
572 static int
573 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
574 {
575         struct rpc_task *task = req->rq_task;
576         struct rpc_auth *auth = task->tk_auth;
577         int             buflen, replen;
578 
579         p = xdr_encode_fhandle(p, args->fh);
580         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
581         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
582         buflen = req->rq_rvec[0].iov_len;
583         req->rq_rvec[0].iov_len  = replen;
584         req->rq_rvec[1].iov_base = args->buffer;
585         req->rq_rvec[1].iov_len  = args->bufsiz;
586         req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen;
587         req->rq_rvec[2].iov_len  = buflen - replen;
588         req->rq_rlen = buflen + args->bufsiz;
589         req->rq_rnr += 2;
590         return 0;
591 }
592 
593 /*
594  * Decode READLINK reply
595  */
596 static int
597 nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_readlinkres *res)
598 {
599         u32     *strlen;
600         char    *string;
601         int     status;
602         unsigned int len;
603 
604         if ((status = ntohl(*p++)))
605                 return -nfs_stat_to_errno(status);
606         strlen = (u32*)res->buffer;
607         /* Convert length of symlink */
608         len = ntohl(*strlen);
609         if (len > res->bufsiz - 5)
610                 len = res->bufsiz - 5;
611         *strlen = len;
612         /* NULL terminate the string we got */
613         string = (char *)(strlen + 1);
614         string[len] = 0;
615         return 0;
616 }
617 
618 /*
619  * Decode WRITE reply
620  */
621 static int
622 nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
623 {
624         res->verf->committed = NFS_FILE_SYNC;
625         return nfs_xdr_attrstat(req, p, res->fattr);
626 }
627 
628 /*
629  * Decode STATFS reply
630  */
631 static int
632 nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
633 {
634         int     status;
635         u32     xfer_size;
636 
637         if ((status = ntohl(*p++)))
638                 return -nfs_stat_to_errno(status);
639 
640         /* For NFSv2, we more or less have to guess the preferred
641          * read/write/readdir sizes from the single 'transfer size'
642          * value.
643          */
644         xfer_size = ntohl(*p++);        /* tsize */
645         res->rtmax  = 8 * 1024;
646         res->rtpref = xfer_size;
647         res->rtmult = xfer_size;
648         res->wtmax  = 8 * 1024;
649         res->wtpref = xfer_size;
650         res->wtmult = xfer_size;
651         res->dtpref = PAGE_CACHE_SIZE;
652         res->maxfilesize = 0x7FFFFFFF;  /* just a guess */
653         res->bsize  = ntohl(*p++);
654 
655         res->tbytes = ntohl(*p++) * res->bsize;
656         res->fbytes = ntohl(*p++) * res->bsize;
657         res->abytes = ntohl(*p++) * res->bsize;
658         res->tfiles = 0;
659         res->ffiles = 0;
660         res->afiles = 0;
661         res->namelen = 0;
662 
663         return 0;
664 }
665 
666 /*
667  * We need to translate between nfs status return values and
668  * the local errno values which may not be the same.
669  */
670 static struct {
671         int stat;
672         int errno;
673 } nfs_errtbl[] = {
674         { NFS_OK,               0               },
675         { NFSERR_PERM,          EPERM           },
676         { NFSERR_NOENT,         ENOENT          },
677         { NFSERR_IO,            errno_NFSERR_IO },
678         { NFSERR_NXIO,          ENXIO           },
679 /*      { NFSERR_EAGAIN,        EAGAIN          }, */
680         { NFSERR_ACCES,         EACCES          },
681         { NFSERR_EXIST,         EEXIST          },
682         { NFSERR_XDEV,          EXDEV           },
683         { NFSERR_NODEV,         ENODEV          },
684         { NFSERR_NOTDIR,        ENOTDIR         },
685         { NFSERR_ISDIR,         EISDIR          },
686         { NFSERR_INVAL,         EINVAL          },
687         { NFSERR_FBIG,          EFBIG           },
688         { NFSERR_NOSPC,         ENOSPC          },
689         { NFSERR_ROFS,          EROFS           },
690         { NFSERR_MLINK,         EMLINK          },
691         { NFSERR_NAMETOOLONG,   ENAMETOOLONG    },
692         { NFSERR_NOTEMPTY,      ENOTEMPTY       },
693         { NFSERR_DQUOT,         EDQUOT          },
694         { NFSERR_STALE,         ESTALE          },
695         { NFSERR_REMOTE,        EREMOTE         },
696 #ifdef EWFLUSH
697         { NFSERR_WFLUSH,        EWFLUSH         },
698 #endif
699         { NFSERR_BADHANDLE,     EBADHANDLE      },
700         { NFSERR_NOT_SYNC,      ENOTSYNC        },
701         { NFSERR_BAD_COOKIE,    EBADCOOKIE      },
702         { NFSERR_NOTSUPP,       ENOTSUPP        },
703         { NFSERR_TOOSMALL,      ETOOSMALL       },
704         { NFSERR_SERVERFAULT,   ESERVERFAULT    },
705         { NFSERR_BADTYPE,       EBADTYPE        },
706         { NFSERR_JUKEBOX,       EJUKEBOX        },
707         { -1,                   EIO             }
708 };
709 
710 /*
711  * Convert an NFS error code to a local one.
712  * This one is used jointly by NFSv2 and NFSv3.
713  */
714 int
715 nfs_stat_to_errno(int stat)
716 {
717         int i;
718 
719         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
720                 if (nfs_errtbl[i].stat == stat)
721                         return nfs_errtbl[i].errno;
722         }
723         printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
724         return nfs_errtbl[i].errno;
725 }
726 
727 #ifndef MAX
728 # define MAX(a, b)      (((a) > (b))? (a) : (b))
729 #endif
730 
731 #define PROC(proc, argtype, restype)    \
732     { "nfs_" #proc,                                     \
733       (kxdrproc_t) nfs_xdr_##argtype,                   \
734       (kxdrproc_t) nfs_xdr_##restype,                   \
735       MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2,  \
736       0                                                 \
737     }
738 
739 static struct rpc_procinfo      nfs_procedures[18] = {
740     PROC(null,          enc_void,       dec_void),
741     PROC(getattr,       fhandle,        attrstat),
742     PROC(setattr,       sattrargs,      attrstat),
743     PROC(root,          enc_void,       dec_void),
744     PROC(lookup,        diropargs,      diropres),
745     PROC(readlink,      readlinkargs,   readlinkres),
746     PROC(read,          readargs,       readres),
747     PROC(writecache,    enc_void,       dec_void),
748     PROC(write,         writeargs,      writeres),
749     PROC(create,        createargs,     diropres),
750     PROC(remove,        diropargs,      stat),
751     PROC(rename,        renameargs,     stat),
752     PROC(link,          linkargs,       stat),
753     PROC(symlink,       symlinkargs,    stat),
754     PROC(mkdir,         createargs,     diropres),
755     PROC(rmdir,         diropargs,      stat),
756     PROC(readdir,       readdirargs,    readdirres),
757     PROC(statfs,        fhandle,        statfsres),
758 };
759 
760 struct rpc_version              nfs_version2 = {
761         2,
762         sizeof(nfs_procedures)/sizeof(nfs_procedures[0]),
763         nfs_procedures
764 };
765 

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

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.