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/kern/sys_descrip.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 /*      $NetBSD: sys_descrip.c,v 1.40 2022/04/16 07:59:02 hannken Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26  * POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * Copyright (c) 1982, 1986, 1989, 1991, 1993
   31  *      The Regents of the University of California.  All rights reserved.
   32  * (c) UNIX System Laboratories, Inc.
   33  * All or some portions of this file are derived from material licensed
   34  * to the University of California by American Telephone and Telegraph
   35  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   36  * the permission of UNIX System Laboratories, Inc.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. Neither the name of the University nor the names of its contributors
   47  *    may be used to endorse or promote products derived from this software
   48  *    without specific prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   60  * SUCH DAMAGE.
   61  *
   62  *      @(#)kern_descrip.c      8.8 (Berkeley) 2/14/95
   63  */
   64 
   65 /*
   66  * System calls on descriptors.
   67  */
   68 
   69 #include <sys/cdefs.h>
   70 __KERNEL_RCSID(0, "$NetBSD: sys_descrip.c,v 1.40 2022/04/16 07:59:02 hannken Exp $");
   71 
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/filedesc.h>
   75 #include <sys/kernel.h>
   76 #include <sys/vnode.h>
   77 #include <sys/proc.h>
   78 #include <sys/file.h>
   79 #include <sys/namei.h>
   80 #include <sys/socket.h>
   81 #include <sys/socketvar.h>
   82 #include <sys/stat.h>
   83 #include <sys/ioctl.h>
   84 #include <sys/fcntl.h>
   85 #include <sys/kmem.h>
   86 #include <sys/pool.h>
   87 #include <sys/syslog.h>
   88 #include <sys/unistd.h>
   89 #include <sys/resourcevar.h>
   90 #include <sys/conf.h>
   91 #include <sys/event.h>
   92 #include <sys/kauth.h>
   93 #include <sys/atomic.h>
   94 #include <sys/mount.h>
   95 #include <sys/syscallargs.h>
   96 
   97 #include <uvm/uvm_readahead.h>
   98 
   99 /*
  100  * Duplicate a file descriptor.
  101  */
  102 int
  103 sys_dup(struct lwp *l, const struct sys_dup_args *uap, register_t *retval)
  104 {
  105         /* {
  106                 syscallarg(int) fd;
  107         } */
  108         int error, newfd, oldfd;
  109         file_t *fp;
  110 
  111         oldfd = SCARG(uap, fd);
  112 
  113         if ((fp = fd_getfile(oldfd)) == NULL) {
  114                 return EBADF;
  115         }
  116         error = fd_dup(fp, 0, &newfd, false);
  117         fd_putfile(oldfd);
  118         *retval = newfd;
  119         return error;
  120 }
  121 
  122 /*
  123  * Duplicate a file descriptor to a particular value.
  124  */
  125 int
  126 dodup(struct lwp *l, int from, int to, int flags, register_t *retval)
  127 {
  128         int error;
  129         file_t *fp;
  130 
  131         if ((fp = fd_getfile(from)) == NULL)
  132                 return EBADF;
  133         mutex_enter(&fp->f_lock);
  134         fp->f_count++;
  135         mutex_exit(&fp->f_lock);
  136         fd_putfile(from);
  137 
  138         if ((u_int)to >= curproc->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  139             (u_int)to >= maxfiles)
  140                 error = EBADF;
  141         else if (from == to)
  142                 error = 0;
  143         else
  144                 error = fd_dup2(fp, to, flags);
  145         closef(fp);
  146         *retval = to;
  147 
  148         return error;
  149 }
  150 
  151 int
  152 sys_dup3(struct lwp *l, const struct sys_dup3_args *uap, register_t *retval)
  153 {
  154         /* {
  155                 syscallarg(int) from;
  156                 syscallarg(int) to;
  157                 syscallarg(int) flags;
  158         } */
  159         return dodup(l, SCARG(uap, from), SCARG(uap, to), SCARG(uap, flags),
  160             retval);
  161 }
  162 
  163 int
  164 sys_dup2(struct lwp *l, const struct sys_dup2_args *uap, register_t *retval)
  165 {
  166         /* {
  167                 syscallarg(int) from;
  168                 syscallarg(int) to;
  169         } */
  170         return dodup(l, SCARG(uap, from), SCARG(uap, to), 0, retval);
  171 }
  172 
  173 /*
  174  * fcntl call which is being passed to the file's fs.
  175  */
  176 static int
  177 fcntl_forfs(int fd, file_t *fp, int cmd, void *arg)
  178 {
  179         int             error;
  180         u_int           size;
  181         void            *data, *memp;
  182 #define STK_PARAMS      128
  183         char            stkbuf[STK_PARAMS];
  184 
  185         if ((fp->f_flag & (FREAD | FWRITE)) == 0)
  186                 return (EBADF);
  187 
  188         /*
  189          * Interpret high order word to find amount of data to be
  190          * copied to/from the user's address space.
  191          */
  192         size = (size_t)F_PARAM_LEN(cmd);
  193         if (size > F_PARAM_MAX)
  194                 return (EINVAL);
  195         memp = NULL;
  196         if (size > sizeof(stkbuf)) {
  197                 memp = kmem_alloc(size, KM_SLEEP);
  198                 data = memp;
  199         } else
  200                 data = stkbuf;
  201         if (cmd & F_FSIN) {
  202                 if (size) {
  203                         error = copyin(arg, data, size);
  204                         if (error) {
  205                                 if (memp)
  206                                         kmem_free(memp, size);
  207                                 return (error);
  208                         }
  209                 } else
  210                         *(void **)data = arg;
  211         } else if ((cmd & F_FSOUT) != 0 && size != 0) {
  212                 /*
  213                  * Zero the buffer so the user always
  214                  * gets back something deterministic.
  215                  */
  216                 memset(data, 0, size);
  217         } else if (cmd & F_FSVOID)
  218                 *(void **)data = arg;
  219 
  220 
  221         error = (*fp->f_ops->fo_fcntl)(fp, cmd, data);
  222 
  223         /*
  224          * Copy any data to user, size was
  225          * already set and checked above.
  226          */
  227         if (error == 0 && (cmd & F_FSOUT) && size)
  228                 error = copyout(data, arg, size);
  229         if (memp)
  230                 kmem_free(memp, size);
  231         return (error);
  232 }
  233 
  234 int
  235 do_fcntl_lock(int fd, int cmd, struct flock *fl)
  236 {
  237         file_t *fp;
  238         vnode_t *vp;
  239         proc_t *p;
  240         int error, flg;
  241 
  242         if ((error = fd_getvnode(fd, &fp)) != 0)
  243                 return error;
  244 
  245         vp = fp->f_vnode;
  246         if (fl->l_whence == SEEK_CUR) {
  247                 vn_lock(vp, LK_SHARED | LK_RETRY);
  248                 fl->l_start += fp->f_offset;
  249                 VOP_UNLOCK(vp);
  250         }
  251 
  252         flg = F_POSIX;
  253         p = curproc;
  254 
  255         switch (cmd) {
  256         case F_SETLKW:
  257                 flg |= F_WAIT;
  258                 /* Fall into F_SETLK */
  259 
  260                 /* FALLTHROUGH */
  261         case F_SETLK:
  262                 switch (fl->l_type) {
  263                 case F_RDLCK:
  264                         if ((fp->f_flag & FREAD) == 0) {
  265                                 error = EBADF;
  266                                 break;
  267                         }
  268                         if ((p->p_flag & PK_ADVLOCK) == 0) {
  269                                 mutex_enter(p->p_lock);
  270                                 p->p_flag |= PK_ADVLOCK;
  271                                 mutex_exit(p->p_lock);
  272                         }
  273                         error = VOP_ADVLOCK(vp, p, F_SETLK, fl, flg);
  274                         break;
  275 
  276                 case F_WRLCK:
  277                         if ((fp->f_flag & FWRITE) == 0) {
  278                                 error = EBADF;
  279                                 break;
  280                         }
  281                         if ((p->p_flag & PK_ADVLOCK) == 0) {
  282                                 mutex_enter(p->p_lock);
  283                                 p->p_flag |= PK_ADVLOCK;
  284                                 mutex_exit(p->p_lock);
  285                         }
  286                         error = VOP_ADVLOCK(vp, p, F_SETLK, fl, flg);
  287                         break;
  288 
  289                 case F_UNLCK:
  290                         error = VOP_ADVLOCK(vp, p, F_UNLCK, fl, F_POSIX);
  291                         break;
  292 
  293                 default:
  294                         error = EINVAL;
  295                         break;
  296                 }
  297                 break;
  298 
  299         case F_GETLK:
  300                 if (fl->l_type != F_RDLCK &&
  301                     fl->l_type != F_WRLCK &&
  302                     fl->l_type != F_UNLCK) {
  303                         error = EINVAL;
  304                         break;
  305                 }
  306                 error = VOP_ADVLOCK(vp, p, F_GETLK, fl, F_POSIX);
  307                 break;
  308 
  309         default:
  310                 error = EINVAL;
  311                 break;
  312         }
  313 
  314         fd_putfile(fd);
  315         return error;
  316 }
  317 
  318 static int
  319 do_fcntl_getpath(struct lwp *l, file_t *fp, char *upath)
  320 {
  321         char *kpath;
  322         int error;
  323 
  324         if (fp->f_type != DTYPE_VNODE)
  325                 return EOPNOTSUPP;
  326 
  327         kpath = PNBUF_GET();
  328 
  329         error = vnode_to_path(kpath, MAXPATHLEN, fp->f_vnode, l, l->l_proc);
  330         if (!error)
  331                 error = copyoutstr(kpath, upath, MAXPATHLEN, NULL);
  332 
  333         PNBUF_PUT(kpath);
  334 
  335         return error;
  336 }
  337         
  338 /*
  339  * The file control system call.
  340  */
  341 int
  342 sys_fcntl(struct lwp *l, const struct sys_fcntl_args *uap, register_t *retval)
  343 {
  344         /* {
  345                 syscallarg(int)         fd;
  346                 syscallarg(int)         cmd;
  347                 syscallarg(void *)      arg;
  348         } */
  349         int fd, i, tmp, error, cmd, newmin;
  350         filedesc_t *fdp;
  351         fdtab_t *dt;
  352         file_t *fp;
  353         struct flock fl;
  354         bool cloexec = false;
  355 
  356         fd = SCARG(uap, fd);
  357         cmd = SCARG(uap, cmd);
  358         fdp = l->l_fd;
  359         error = 0;
  360 
  361         switch (cmd) {
  362         case F_CLOSEM:
  363                 if (fd < 0)
  364                         return EBADF;
  365                 while ((i = fdp->fd_lastfile) >= fd) {
  366                         if (fd_getfile(i) == NULL) {
  367                                 /* Another thread has updated. */
  368                                 continue;
  369                         }
  370                         fd_close(i);
  371                 }
  372                 return 0;
  373 
  374         case F_MAXFD:
  375                 *retval = fdp->fd_lastfile;
  376                 return 0;
  377 
  378         case F_SETLKW:
  379         case F_SETLK:
  380         case F_GETLK:
  381                 error = copyin(SCARG(uap, arg), &fl, sizeof(fl));
  382                 if (error)
  383                         return error;
  384                 error = do_fcntl_lock(fd, cmd, &fl);
  385                 if (cmd == F_GETLK && error == 0)
  386                         error = copyout(&fl, SCARG(uap, arg), sizeof(fl));
  387                 return error;
  388 
  389         default:
  390                 /* Handled below */
  391                 break;
  392         }
  393 
  394         if ((fp = fd_getfile(fd)) == NULL)
  395                 return EBADF;
  396 
  397         if ((cmd & F_FSCTL)) {
  398                 error = fcntl_forfs(fd, fp, cmd, SCARG(uap, arg));
  399                 fd_putfile(fd);
  400                 return error;
  401         }
  402 
  403         switch (cmd) {
  404         case F_DUPFD_CLOEXEC:
  405                 cloexec = true;
  406                 /*FALLTHROUGH*/
  407         case F_DUPFD:
  408                 newmin = (long)SCARG(uap, arg);
  409                 if ((u_int)newmin >=
  410                     l->l_proc->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  411                     (u_int)newmin >= maxfiles) {
  412                         fd_putfile(fd);
  413                         return EINVAL;
  414                 }
  415                 error = fd_dup(fp, newmin, &i, cloexec);
  416                 *retval = i;
  417                 break;
  418 
  419         case F_GETFD:
  420                 dt = atomic_load_consume(&fdp->fd_dt);
  421                 *retval = dt->dt_ff[fd]->ff_exclose;
  422                 break;
  423 
  424         case F_SETFD:
  425                 fd_set_exclose(l, fd,
  426                     ((long)SCARG(uap, arg) & FD_CLOEXEC) != 0);
  427                 break;
  428 
  429         case F_GETNOSIGPIPE:
  430                 *retval = (fp->f_flag & FNOSIGPIPE) != 0;
  431                 break;
  432 
  433         case F_SETNOSIGPIPE:
  434                 if (SCARG(uap, arg))
  435                         atomic_or_uint(&fp->f_flag, FNOSIGPIPE);
  436                 else
  437                         atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE);
  438                 *retval = 0;
  439                 break;
  440 
  441         case F_GETFL:
  442                 *retval = OFLAGS(fp->f_flag);
  443                 break;
  444 
  445         case F_SETFL:
  446                 /* XXX not guaranteed to be atomic. */
  447                 tmp = FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
  448                 error = (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &tmp);
  449                 if (error)
  450                         break;
  451                 i = tmp ^ fp->f_flag;
  452                 if (i & FNONBLOCK) {
  453                         int flgs = tmp & FNONBLOCK;
  454                         error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, &flgs);
  455                         if (error) {
  456                                 (*fp->f_ops->fo_fcntl)(fp, F_SETFL,
  457                                     &fp->f_flag);
  458                                 break;
  459                         }
  460                 }
  461                 if (i & FASYNC) {
  462                         int flgs = tmp & FASYNC;
  463                         error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, &flgs);
  464                         if (error) {
  465                                 if (i & FNONBLOCK) {
  466                                         tmp = fp->f_flag & FNONBLOCK;
  467                                         (void)(*fp->f_ops->fo_ioctl)(fp,
  468                                                 FIONBIO, &tmp);
  469                                 }
  470                                 (*fp->f_ops->fo_fcntl)(fp, F_SETFL,
  471                                     &fp->f_flag);
  472                                 break;
  473                         }
  474                 }
  475                 fp->f_flag = (fp->f_flag & ~FCNTLFLAGS) | tmp;
  476                 break;
  477 
  478         case F_GETOWN:
  479                 error = (*fp->f_ops->fo_ioctl)(fp, FIOGETOWN, &tmp);
  480                 *retval = tmp;
  481                 break;
  482 
  483         case F_SETOWN:
  484                 tmp = (int)(uintptr_t) SCARG(uap, arg);
  485                 error = (*fp->f_ops->fo_ioctl)(fp, FIOSETOWN, &tmp);
  486                 break;
  487 
  488         case F_GETPATH:
  489                 error = do_fcntl_getpath(l, fp, SCARG(uap, arg));
  490                 break;
  491 
  492         default:
  493                 error = EINVAL;
  494         }
  495 
  496         fd_putfile(fd);
  497         return (error);
  498 }
  499 
  500 /*
  501  * Close a file descriptor.
  502  */
  503 int
  504 sys_close(struct lwp *l, const struct sys_close_args *uap, register_t *retval)
  505 {
  506         /* {
  507                 syscallarg(int) fd;
  508         } */
  509         int error;
  510         int fd = SCARG(uap, fd);
  511 
  512         if (fd_getfile(fd) == NULL) {
  513                 return EBADF;
  514         }
  515 
  516         error = fd_close(fd);
  517         if (error == ERESTART) {
  518 #ifdef DIAGNOSTIC
  519                 printf("%s[%d]: close(%d) returned ERESTART\n",
  520                     l->l_proc->p_comm, (int)l->l_proc->p_pid, fd);
  521 #endif
  522                 error = EINTR;
  523         }
  524 
  525         return error;
  526 }
  527 
  528 /*
  529  * Return status information about a file descriptor.
  530  * Common function for compat code.
  531  */
  532 int
  533 do_sys_fstat(int fd, struct stat *sb)
  534 {
  535         file_t *fp;
  536         int error;
  537 
  538         if ((fp = fd_getfile(fd)) == NULL) {
  539                 return EBADF;
  540         }
  541         error = (*fp->f_ops->fo_stat)(fp, sb);
  542         fd_putfile(fd);
  543 
  544         return error;
  545 }
  546 
  547 /*
  548  * Return status information about a file descriptor.
  549  */
  550 int
  551 sys___fstat50(struct lwp *l, const struct sys___fstat50_args *uap,
  552               register_t *retval)
  553 {
  554         /* {
  555                 syscallarg(int)                 fd;
  556                 syscallarg(struct stat *)       sb;
  557         } */
  558         struct stat sb;
  559         int error;
  560 
  561         error = do_sys_fstat(SCARG(uap, fd), &sb);
  562         if (error == 0) {
  563                 error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
  564         }
  565         return error;
  566 }
  567 
  568 /*
  569  * Return pathconf information about a file descriptor.
  570  */
  571 int
  572 sys_fpathconf(struct lwp *l, const struct sys_fpathconf_args *uap,
  573               register_t *retval)
  574 {
  575         /* {
  576                 syscallarg(int) fd;
  577                 syscallarg(int) name;
  578         } */
  579         int fd, error;
  580         file_t *fp;
  581 
  582         fd = SCARG(uap, fd);
  583         error = 0;
  584 
  585         if ((fp = fd_getfile(fd)) == NULL) {
  586                 return (EBADF);
  587         }
  588         switch (fp->f_type) {
  589         case DTYPE_SOCKET:
  590         case DTYPE_PIPE:
  591                 if (SCARG(uap, name) != _PC_PIPE_BUF)
  592                         error = EINVAL;
  593                 else
  594                         *retval = PIPE_BUF;
  595                 break;
  596 
  597         case DTYPE_VNODE:
  598                 vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
  599                 error = VOP_PATHCONF(fp->f_vnode, SCARG(uap, name), retval);
  600                 VOP_UNLOCK(fp->f_vnode);
  601                 break;
  602 
  603         case DTYPE_KQUEUE:
  604                 error = EINVAL;
  605                 break;
  606 
  607         default:
  608                 error = EOPNOTSUPP;
  609                 break;
  610         }
  611 
  612         fd_putfile(fd);
  613         return (error);
  614 }
  615 
  616 /*
  617  * Apply an advisory lock on a file descriptor.
  618  *
  619  * Just attempt to get a record lock of the requested type on
  620  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
  621  */
  622 /* ARGSUSED */
  623 int
  624 sys_flock(struct lwp *l, const struct sys_flock_args *uap, register_t *retval)
  625 {
  626         /* {
  627                 syscallarg(int) fd;
  628                 syscallarg(int) how;
  629         } */
  630         int fd, how, error;
  631         file_t *fp;
  632         vnode_t *vp;
  633         struct flock lf;
  634 
  635         fd = SCARG(uap, fd);
  636         how = SCARG(uap, how);
  637 
  638         if ((error = fd_getvnode(fd, &fp)) != 0)
  639                 return error == EINVAL ? EOPNOTSUPP : error;
  640 
  641         vp = fp->f_vnode;
  642         lf.l_whence = SEEK_SET;
  643         lf.l_start = 0;
  644         lf.l_len = 0;
  645 
  646         switch (how & ~LOCK_NB) {
  647         case LOCK_UN:
  648                 lf.l_type = F_UNLCK;
  649                 atomic_and_uint(&fp->f_flag, ~FHASLOCK);
  650                 error = VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
  651                 fd_putfile(fd);
  652                 return error;
  653         case LOCK_EX:
  654                 lf.l_type = F_WRLCK;
  655                 break;
  656         case LOCK_SH:
  657                 lf.l_type = F_RDLCK;
  658                 break;
  659         default:
  660                 fd_putfile(fd);
  661                 return EINVAL;
  662         }
  663 
  664         atomic_or_uint(&fp->f_flag, FHASLOCK);
  665         if (how & LOCK_NB) {
  666                 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK);
  667         } else {
  668                 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK|F_WAIT);
  669         }
  670         fd_putfile(fd);
  671         return error;
  672 }
  673 
  674 int
  675 do_posix_fadvise(int fd, off_t offset, off_t len, int advice)
  676 {
  677         const off_t OFF_MAX = __type_max(off_t);
  678         file_t *fp;
  679         vnode_t *vp;
  680         off_t endoffset;
  681         int error;
  682 
  683         CTASSERT(POSIX_FADV_NORMAL == UVM_ADV_NORMAL);
  684         CTASSERT(POSIX_FADV_RANDOM == UVM_ADV_RANDOM);
  685         CTASSERT(POSIX_FADV_SEQUENTIAL == UVM_ADV_SEQUENTIAL);
  686 
  687         if (offset < 0) {
  688                 return EINVAL;
  689         }
  690         if (len == 0) {
  691                 endoffset = OFF_MAX;
  692         } else if (len > 0 && (OFF_MAX - offset) >= len) {
  693                 endoffset = offset + len;
  694         } else {
  695                 return EINVAL;
  696         }
  697         if ((fp = fd_getfile(fd)) == NULL) {
  698                 return EBADF;
  699         }
  700         if (fp->f_type != DTYPE_VNODE) {
  701                 if (fp->f_type == DTYPE_PIPE || fp->f_type == DTYPE_SOCKET) {
  702                         error = ESPIPE;
  703                 } else {
  704                         error = EOPNOTSUPP;
  705                 }
  706                 fd_putfile(fd);
  707                 return error;
  708         }
  709 
  710         switch (advice) {
  711         case POSIX_FADV_WILLNEED:
  712         case POSIX_FADV_DONTNEED:
  713                 vp = fp->f_vnode;
  714                 if (vp->v_type != VREG && vp->v_type != VBLK) {
  715                         fd_putfile(fd);
  716                         return 0;
  717                 }
  718                 break;
  719         }
  720 
  721         switch (advice) {
  722         case POSIX_FADV_NORMAL:
  723         case POSIX_FADV_RANDOM:
  724         case POSIX_FADV_SEQUENTIAL:
  725                 /*
  726                  * We ignore offset and size.  Must lock the file to
  727                  * do this, as f_advice is sub-word sized.
  728                  */
  729                 mutex_enter(&fp->f_lock);
  730                 fp->f_advice = (u_char)advice;
  731                 mutex_exit(&fp->f_lock);
  732                 error = 0;
  733                 break;
  734 
  735         case POSIX_FADV_WILLNEED:
  736                 vp = fp->f_vnode;
  737                 error = uvm_readahead(&vp->v_uobj, offset, endoffset - offset);
  738                 break;
  739 
  740         case POSIX_FADV_DONTNEED:
  741                 vp = fp->f_vnode;
  742                 /*
  743                  * Align the region to page boundaries as VOP_PUTPAGES expects
  744                  * by shrinking it.  We shrink instead of expand because we
  745                  * do not want to deactivate cache outside of the requested
  746                  * region.  It means that if the specified region is smaller
  747                  * than PAGE_SIZE, we do nothing.
  748                  */
  749                 if (offset <= trunc_page(OFF_MAX) &&
  750                     round_page(offset) < trunc_page(endoffset)) {
  751                         rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
  752                         error = VOP_PUTPAGES(vp,
  753                             round_page(offset), trunc_page(endoffset),
  754                             PGO_DEACTIVATE | PGO_CLEANIT);
  755                 } else {
  756                         error = 0;
  757                 }
  758                 break;
  759 
  760         case POSIX_FADV_NOREUSE:
  761                 /* Not implemented yet. */
  762                 error = 0;
  763                 break;
  764         default:
  765                 error = EINVAL;
  766                 break;
  767         }
  768 
  769         fd_putfile(fd);
  770         return error;
  771 }
  772 
  773 int
  774 sys___posix_fadvise50(struct lwp *l,
  775                       const struct sys___posix_fadvise50_args *uap,
  776                       register_t *retval)
  777 {
  778         /* {
  779                 syscallarg(int) fd;
  780                 syscallarg(int) pad;
  781                 syscallarg(off_t) offset;
  782                 syscallarg(off_t) len;
  783                 syscallarg(int) advice;
  784         } */
  785 
  786         *retval = do_posix_fadvise(SCARG(uap, fd), SCARG(uap, offset),
  787             SCARG(uap, len), SCARG(uap, advice));
  788 
  789         return 0;
  790 }
  791 
  792 int
  793 sys_pipe(struct lwp *l, const void *v, register_t *retval)
  794 {
  795         int fd[2], error;
  796 
  797         if ((error = pipe1(l, fd, 0)) != 0)
  798                 return error;
  799 
  800         retval[0] = fd[0];
  801         retval[1] = fd[1];
  802 
  803         return 0;
  804 }
  805 
  806 int
  807 sys_pipe2(struct lwp *l, const struct sys_pipe2_args *uap, register_t *retval)
  808 {
  809         /* {
  810                 syscallarg(int[2]) fildes;
  811                 syscallarg(int) flags;
  812         } */
  813         int fd[2], error;
  814 
  815         if ((error = pipe1(l, fd, SCARG(uap, flags))) != 0)
  816                 return error;
  817 
  818         if ((error = copyout(fd, SCARG(uap, fildes), sizeof(fd))) != 0)
  819                 return error;
  820         retval[0] = 0;
  821         return 0;
  822 }

Cache object: 590b991899fbae53a061d2960678bff9


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