The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfs/nfs2xdr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 46a0c002e0f108fba8856752e362535f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.