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/nfsd/nfsproc.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  * nfsproc2.c   Process version 2 NFS requests.
    3  * linux/fs/nfsd/nfs2proc.c
    4  * 
    5  * Process version 2 NFS requests.
    6  *
    7  * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
    8  */
    9 
   10 #include <linux/linkage.h>
   11 #include <linux/sched.h>
   12 #include <linux/errno.h>
   13 #include <linux/locks.h>
   14 #include <linux/fs.h>
   15 #include <linux/stat.h>
   16 #include <linux/fcntl.h>
   17 #include <linux/net.h>
   18 #include <linux/in.h>
   19 #include <linux/version.h>
   20 #include <linux/unistd.h>
   21 #include <linux/slab.h>
   22 
   23 #include <linux/sunrpc/svc.h>
   24 #include <linux/nfsd/nfsd.h>
   25 #include <linux/nfsd/cache.h>
   26 #include <linux/nfsd/xdr.h>
   27 
   28 typedef struct svc_rqst svc_rqst;
   29 typedef struct svc_buf  svc_buf;
   30 
   31 #define NFSDDBG_FACILITY                NFSDDBG_PROC
   32 
   33 
   34 static void
   35 svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
   36 {
   37         *ptr = buf->buf + nr;
   38         *len = buf->buflen - buf->len - nr;
   39 }
   40 
   41 static int
   42 nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
   43 {
   44         return nfs_ok;
   45 }
   46 
   47 /*
   48  * Get a file's attributes
   49  * N.B. After this call resp->fh needs an fh_put
   50  */
   51 static int
   52 nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
   53                                           struct nfsd_attrstat *resp)
   54 {
   55         dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
   56 
   57         fh_copy(&resp->fh, &argp->fh);
   58         return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
   59 }
   60 
   61 /*
   62  * Set a file's attributes
   63  * N.B. After this call resp->fh needs an fh_put
   64  */
   65 static int
   66 nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
   67                                           struct nfsd_attrstat  *resp)
   68 {
   69         dprintk("nfsd: SETATTR  %s, valid=%x, size=%ld\n",
   70                 SVCFH_fmt(&argp->fh),
   71                 argp->attrs.ia_valid, (long) argp->attrs.ia_size);
   72 
   73         fh_copy(&resp->fh, &argp->fh);
   74         return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
   75 }
   76 
   77 /*
   78  * Look up a path name component
   79  * Note: the dentry in the resp->fh may be negative if the file
   80  * doesn't exist yet.
   81  * N.B. After this call resp->fh needs an fh_put
   82  */
   83 static int
   84 nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
   85                                          struct nfsd_diropres  *resp)
   86 {
   87         int     nfserr;
   88 
   89         dprintk("nfsd: LOOKUP   %s %.*s\n",
   90                 SVCFH_fmt(&argp->fh), argp->len, argp->name);
   91 
   92         fh_init(&resp->fh, NFS_FHSIZE);
   93         nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
   94                                  &resp->fh);
   95 
   96         fh_put(&argp->fh);
   97         return nfserr;
   98 }
   99 
  100 /*
  101  * Read a symlink.
  102  */
  103 static int
  104 nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle     *argp,
  105                                            struct nfsd_readlinkres *resp)
  106 {
  107         u32             *path;
  108         int             dummy, nfserr;
  109 
  110         dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
  111 
  112         /* Reserve room for status and path length */
  113         svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy, 2);
  114 
  115         /* Read the symlink. */
  116         resp->len = NFS_MAXPATHLEN;
  117         nfserr = nfsd_readlink(rqstp, &argp->fh, (char *) path, &resp->len);
  118 
  119         fh_put(&argp->fh);
  120         return nfserr;
  121 }
  122 
  123 /*
  124  * Read a portion of a file.
  125  * N.B. After this call resp->fh needs an fh_put
  126  */
  127 static int
  128 nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
  129                                        struct nfsd_readres  *resp)
  130 {
  131         u32 *   buffer;
  132         int     nfserr, avail;
  133 
  134         dprintk("nfsd: READ    %s %d bytes at %d\n",
  135                 SVCFH_fmt(&argp->fh),
  136                 argp->count, argp->offset);
  137 
  138         /* Obtain buffer pointer for payload. 19 is 1 word for
  139          * status, 17 words for fattr, and 1 word for the byte count.
  140          */
  141         svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &avail, 19);
  142 
  143         if ((avail << 2) < argp->count) {
  144                 printk(KERN_NOTICE
  145                         "oversized read request from %08x:%d (%d bytes)\n",
  146                                 ntohl(rqstp->rq_addr.sin_addr.s_addr),
  147                                 ntohs(rqstp->rq_addr.sin_port),
  148                                 argp->count);
  149                 argp->count = avail << 2;
  150         }
  151         svc_reserve(rqstp, (19<<2) + argp->count + 4);
  152 
  153         resp->count = argp->count;
  154         nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
  155                                   argp->offset,
  156                                   (char *) buffer,
  157                                   &resp->count);
  158 
  159         return nfserr;
  160 }
  161 
  162 /*
  163  * Write data to a file
  164  * N.B. After this call resp->fh needs an fh_put
  165  */
  166 static int
  167 nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
  168                                         struct nfsd_attrstat  *resp)
  169 {
  170         int     nfserr;
  171         int     stable = 1;
  172 
  173         dprintk("nfsd: WRITE    %s %d bytes at %d\n",
  174                 SVCFH_fmt(&argp->fh),
  175                 argp->len, argp->offset);
  176 
  177         nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
  178                                    argp->offset,
  179                                    argp->data,
  180                                    argp->len,
  181                                    &stable);
  182         return nfserr;
  183 }
  184 
  185 /*
  186  * CREATE processing is complicated. The keyword here is `overloaded.'
  187  * The parent directory is kept locked between the check for existence
  188  * and the actual create() call in compliance with VFS protocols.
  189  * N.B. After this call _both_ argp->fh and resp->fh need an fh_put
  190  */
  191 static int
  192 nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
  193                                          struct nfsd_diropres   *resp)
  194 {
  195         svc_fh          *dirfhp = &argp->fh;
  196         svc_fh          *newfhp = &resp->fh;
  197         struct iattr    *attr = &argp->attrs;
  198         struct inode    *inode;
  199         struct dentry   *dchild;
  200         int             nfserr, type, mode;
  201         dev_t           rdev = NODEV;
  202 
  203         dprintk("nfsd: CREATE   %s %.*s\n",
  204                 SVCFH_fmt(dirfhp), argp->len, argp->name);
  205 
  206         /* First verify the parent file handle */
  207         nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
  208         if (nfserr)
  209                 goto done; /* must fh_put dirfhp even on error */
  210 
  211         /* Check for MAY_WRITE in nfsd_create if necessary */
  212 
  213         nfserr = nfserr_acces;
  214         if (!argp->len)
  215                 goto done;
  216         nfserr = nfserr_exist;
  217         if (isdotent(argp->name, argp->len))
  218                 goto done;
  219         fh_lock(dirfhp);
  220         dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
  221         if (IS_ERR(dchild)) {
  222                 nfserr = nfserrno(PTR_ERR(dchild));
  223                 goto out_unlock;
  224         }
  225         fh_init(newfhp, NFS_FHSIZE);
  226         nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
  227         if (!nfserr && !dchild->d_inode)
  228                 nfserr = nfserr_noent;
  229         if (nfserr) {
  230                 if (nfserr != nfserr_noent)
  231                         goto out_unlock;
  232                 /*
  233                  * If the new file handle wasn't verified, we can't tell
  234                  * whether the file exists or not. Time to bail ...
  235                  */
  236                 nfserr = nfserr_acces;
  237                 if (!newfhp->fh_dentry) {
  238                         printk(KERN_WARNING 
  239                                 "nfsd_proc_create: file handle not verified\n");
  240                         goto out_unlock;
  241                 }
  242         }
  243 
  244         inode = newfhp->fh_dentry->d_inode;
  245 
  246         /* Unfudge the mode bits */
  247         if (attr->ia_valid & ATTR_MODE) { 
  248                 type = attr->ia_mode & S_IFMT;
  249                 mode = attr->ia_mode & ~S_IFMT;
  250                 if (!type) {
  251                         /* no type, so if target exists, assume same as that,
  252                          * else assume a file */
  253                         if (inode) {
  254                                 type = inode->i_mode & S_IFMT;
  255                                 switch(type) {
  256                                 case S_IFCHR:
  257                                 case S_IFBLK:
  258                                         /* reserve rdev for later checking */
  259                                         attr->ia_size = inode->i_rdev;
  260                                         attr->ia_valid |= ATTR_SIZE;
  261 
  262                                         /* FALLTHROUGH */
  263                                 case S_IFIFO:
  264                                         /* this is probably a permission check..
  265                                          * at least IRIX implements perm checking on
  266                                          *   echo thing > device-special-file-or-pipe
  267                                          * by doing a CREATE with type==0
  268                                          */
  269                                         nfserr = nfsd_permission(newfhp->fh_export,
  270                                                                  newfhp->fh_dentry,
  271                                                                  MAY_WRITE|_NFSD_IRIX_BOGOSITY);
  272                                         if (nfserr && nfserr != nfserr_rofs)
  273                                                 goto out_unlock;
  274                                 }
  275                         } else
  276                                 type = S_IFREG;
  277                 }
  278         } else if (inode) {
  279                 type = inode->i_mode & S_IFMT;
  280                 mode = inode->i_mode & ~S_IFMT;
  281         } else {
  282                 type = S_IFREG;
  283                 mode = 0;       /* ??? */
  284         }
  285 
  286         attr->ia_valid |= ATTR_MODE;
  287         attr->ia_mode = mode;
  288 
  289         /* Special treatment for non-regular files according to the
  290          * gospel of sun micro
  291          */
  292         if (type != S_IFREG) {
  293                 int     is_borc = 0;
  294                 u32     size = attr->ia_size;
  295 
  296                 rdev = (dev_t) size;
  297                 if (type != S_IFBLK && type != S_IFCHR) {
  298                         rdev = 0;
  299                 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
  300                         /* If you think you've seen the worst, grok this. */
  301                         type = S_IFIFO;
  302                 } else if (size != rdev) {
  303                         /* dev got truncated because of 16bit Linux dev_t */
  304                         nfserr = nfserr_inval;
  305                         goto out_unlock;
  306                 } else {
  307                         /* Okay, char or block special */
  308                         is_borc = 1;
  309                 }
  310 
  311                 /* we've used the SIZE information, so discard it */
  312                 attr->ia_valid &= ~ATTR_SIZE;
  313 
  314                 /* Make sure the type and device matches */
  315                 nfserr = nfserr_exist;
  316                 if (inode && (type != (inode->i_mode & S_IFMT) || 
  317                     (is_borc && inode->i_rdev != rdev)))
  318                         goto out_unlock;
  319         }
  320         
  321         nfserr = 0;
  322         if (!inode) {
  323                 /* File doesn't exist. Create it and set attrs */
  324                 nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
  325                                         attr, type, rdev, newfhp);
  326         } else if (type == S_IFREG) {
  327                 dprintk("nfsd:   existing %s, valid=%x, size=%ld\n",
  328                         argp->name, attr->ia_valid, (long) attr->ia_size);
  329                 /* File already exists. We ignore all attributes except
  330                  * size, so that creat() behaves exactly like
  331                  * open(..., O_CREAT|O_TRUNC|O_WRONLY).
  332                  */
  333                 attr->ia_valid &= ATTR_SIZE;
  334                 if (attr->ia_valid)
  335                         nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0);
  336         }
  337 
  338 out_unlock:
  339         /* We don't really need to unlock, as fh_put does it. */
  340         fh_unlock(dirfhp);
  341 
  342 done:
  343         fh_put(dirfhp);
  344         return nfserr;
  345 }
  346 
  347 static int
  348 nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
  349                                          void                  *resp)
  350 {
  351         int     nfserr;
  352 
  353         dprintk("nfsd: REMOVE   %s %.*s\n", SVCFH_fmt(&argp->fh),
  354                 argp->len, argp->name);
  355 
  356         /* Unlink. -SIFDIR means file must not be a directory */
  357         nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
  358         fh_put(&argp->fh);
  359         return nfserr;
  360 }
  361 
  362 static int
  363 nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp,
  364                                          void                   *resp)
  365 {
  366         int     nfserr;
  367 
  368         dprintk("nfsd: RENAME   %s %.*s -> \n",
  369                 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
  370         dprintk("nfsd:        ->  %s %.*s\n",
  371                 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
  372 
  373         nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
  374                                     &argp->tfh, argp->tname, argp->tlen);
  375         fh_put(&argp->ffh);
  376         fh_put(&argp->tfh);
  377         return nfserr;
  378 }
  379 
  380 static int
  381 nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp,
  382                                 void                        *resp)
  383 {
  384         int     nfserr;
  385 
  386         dprintk("nfsd: LINK     %s ->\n",
  387                 SVCFH_fmt(&argp->ffh));
  388         dprintk("nfsd:    %s %.*s\n",
  389                 SVCFH_fmt(&argp->tfh),
  390                 argp->tlen,
  391                 argp->tname);
  392 
  393         nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
  394                                   &argp->ffh);
  395         fh_put(&argp->ffh);
  396         fh_put(&argp->tfh);
  397         return nfserr;
  398 }
  399 
  400 static int
  401 nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
  402                                           void                    *resp)
  403 {
  404         struct svc_fh   newfh;
  405         int             nfserr;
  406 
  407         dprintk("nfsd: SYMLINK  %s %.*s -> %.*s\n",
  408                 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
  409                 argp->tlen, argp->tname);
  410 
  411         fh_init(&newfh, NFS_FHSIZE);
  412         /*
  413          * Create the link, look up new file and set attrs.
  414          */
  415         nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
  416                                                  argp->tname, argp->tlen,
  417                                                  &newfh, &argp->attrs);
  418 
  419 
  420         fh_put(&argp->ffh);
  421         fh_put(&newfh);
  422         return nfserr;
  423 }
  424 
  425 /*
  426  * Make directory. This operation is not idempotent.
  427  * N.B. After this call resp->fh needs an fh_put
  428  */
  429 static int
  430 nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
  431                                         struct nfsd_diropres   *resp)
  432 {
  433         int     nfserr;
  434 
  435         dprintk("nfsd: MKDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
  436 
  437         if (resp->fh.fh_dentry) {
  438                 printk(KERN_WARNING
  439                         "nfsd_proc_mkdir: response already verified??\n");
  440         }
  441 
  442         argp->attrs.ia_valid &= ~ATTR_SIZE;
  443         fh_init(&resp->fh, NFS_FHSIZE);
  444         nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
  445                                     &argp->attrs, S_IFDIR, 0, &resp->fh);
  446         fh_put(&argp->fh);
  447         return nfserr;
  448 }
  449 
  450 /*
  451  * Remove a directory
  452  */
  453 static int
  454 nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
  455                                         void                  *resp)
  456 {
  457         int     nfserr;
  458 
  459         dprintk("nfsd: RMDIR    %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
  460 
  461         nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
  462         fh_put(&argp->fh);
  463         return nfserr;
  464 }
  465 
  466 /*
  467  * Read a portion of a directory.
  468  */
  469 static int
  470 nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
  471                                           struct nfsd_readdirres  *resp)
  472 {
  473         u32 *           buffer;
  474         int             nfserr, count;
  475 
  476         dprintk("nfsd: READDIR  %s %d bytes at %d\n",
  477                 SVCFH_fmt(&argp->fh),           
  478                 argp->count, argp->cookie);
  479 
  480         /* Reserve buffer space for status */
  481         svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count, 1);
  482 
  483         /* Shrink to the client read size */
  484         if (count > (argp->count >> 2))
  485                 count = argp->count >> 2;
  486 
  487         /* Make sure we've room for the NULL ptr & eof flag */
  488         count -= 2;
  489         if (count < 0)
  490                 count = 0;
  491 
  492         /* Read directory and encode entries on the fly */
  493         nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie, 
  494                               nfssvc_encode_entry,
  495                               buffer, &count, NULL);
  496         resp->count = count;
  497 
  498         fh_put(&argp->fh);
  499         return nfserr;
  500 }
  501 
  502 /*
  503  * Get file system info
  504  */
  505 static int
  506 nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle   *argp,
  507                                           struct nfsd_statfsres *resp)
  508 {
  509         int     nfserr;
  510 
  511         dprintk("nfsd: STATFS   %s\n", SVCFH_fmt(&argp->fh));
  512 
  513         nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
  514         fh_put(&argp->fh);
  515         return nfserr;
  516 }
  517 
  518 /*
  519  * NFSv2 Server procedures.
  520  * Only the results of non-idempotent operations are cached.
  521  */
  522 #define nfsd_proc_none          NULL
  523 #define nfssvc_release_none     NULL
  524 struct nfsd_void { int dummy; };
  525 
  526 #define PROC(name, argt, rest, relt, cache, respsize)   \
  527  { (svc_procfunc) nfsd_proc_##name,             \
  528    (kxdrproc_t) nfssvc_decode_##argt,           \
  529    (kxdrproc_t) nfssvc_encode_##rest,           \
  530    (kxdrproc_t) nfssvc_release_##relt,          \
  531    sizeof(struct nfsd_##argt),                  \
  532    sizeof(struct nfsd_##rest),                  \
  533    0,                                           \
  534    cache,                                       \
  535    respsize,                                    \
  536  }
  537 
  538 #define ST 1            /* status */
  539 #define FH 8            /* filehandle */
  540 #define AT 18           /* attributes */
  541 
  542 struct svc_procedure            nfsd_procedures2[18] = {
  543   PROC(null,     void,          void,           none,           RC_NOCACHE, ST),
  544   PROC(getattr,  fhandle,       attrstat,       fhandle,        RC_NOCACHE, ST+AT),
  545   PROC(setattr,  sattrargs,     attrstat,       fhandle,        RC_REPLBUFF, ST+AT),
  546   PROC(none,     void,          void,           none,           RC_NOCACHE, ST),
  547   PROC(lookup,   diropargs,     diropres,       fhandle,        RC_NOCACHE, ST+FH+AT),
  548   PROC(readlink, fhandle,       readlinkres,    none,           RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4),
  549   PROC(read,     readargs,      readres,        fhandle,        RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
  550   PROC(none,     void,          void,           none,           RC_NOCACHE, ST),
  551   PROC(write,    writeargs,     attrstat,       fhandle,        RC_REPLBUFF, ST+AT),
  552   PROC(create,   createargs,    diropres,       fhandle,        RC_REPLBUFF, ST+FH+AT),
  553   PROC(remove,   diropargs,     void,           none,           RC_REPLSTAT, ST),
  554   PROC(rename,   renameargs,    void,           none,           RC_REPLSTAT, ST),
  555   PROC(link,     linkargs,      void,           none,           RC_REPLSTAT, ST),
  556   PROC(symlink,  symlinkargs,   void,           none,           RC_REPLSTAT, ST),
  557   PROC(mkdir,    createargs,    diropres,       fhandle,        RC_REPLBUFF, ST+FH+AT),
  558   PROC(rmdir,    diropargs,     void,           none,           RC_REPLSTAT, ST),
  559   PROC(readdir,  readdirargs,   readdirres,     none,           RC_REPLBUFF, 0),
  560   PROC(statfs,   fhandle,       statfsres,      none,           RC_NOCACHE, ST+5),
  561 };
  562 
  563 
  564 /*
  565  * Map errnos to NFS errnos.
  566  */
  567 int
  568 nfserrno (int errno)
  569 {
  570         static struct {
  571                 int     nfserr;
  572                 int     syserr;
  573         } nfs_errtbl[] = {
  574                 { nfs_ok, 0 },
  575                 { nfserr_perm, -EPERM },
  576                 { nfserr_noent, -ENOENT },
  577                 { nfserr_io, -EIO },
  578                 { nfserr_nxio, -ENXIO },
  579                 { nfserr_acces, -EACCES },
  580                 { nfserr_exist, -EEXIST },
  581                 { nfserr_xdev, -EXDEV },
  582                 { nfserr_mlink, -EMLINK },
  583                 { nfserr_nodev, -ENODEV },
  584                 { nfserr_notdir, -ENOTDIR },
  585                 { nfserr_isdir, -EISDIR },
  586                 { nfserr_inval, -EINVAL },
  587                 { nfserr_fbig, -EFBIG },
  588                 { nfserr_nospc, -ENOSPC },
  589                 { nfserr_rofs, -EROFS },
  590                 { nfserr_mlink, -EMLINK },
  591                 { nfserr_nametoolong, -ENAMETOOLONG },
  592                 { nfserr_notempty, -ENOTEMPTY },
  593 #ifdef EDQUOT
  594                 { nfserr_dquot, -EDQUOT },
  595 #endif
  596                 { nfserr_stale, -ESTALE },
  597                 { nfserr_dropit, -ENOMEM },
  598                 { -1, -EIO }
  599         };
  600         int     i;
  601 
  602         for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
  603                 if (nfs_errtbl[i].syserr == errno)
  604                         return nfs_errtbl[i].nfserr;
  605         }
  606         printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
  607         return nfserr_io;
  608 }
  609 

Cache object: 14272f799a0f6786b4c869a91c018c6d


[ 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.