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/miscfs/fifofs/fifo_vnops.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: fifo_vnops.c,v 1.66 2008/04/28 20:24:08 martin Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2008 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) 1990, 1993, 1995
   31  *      The Regents of the University of California.  All rights reserved.
   32  *
   33  * Redistribution and use in source and binary forms, with or without
   34  * modification, are permitted provided that the following conditions
   35  * are met:
   36  * 1. Redistributions of source code must retain the above copyright
   37  *    notice, this list of conditions and the following disclaimer.
   38  * 2. Redistributions in binary form must reproduce the above copyright
   39  *    notice, this list of conditions and the following disclaimer in the
   40  *    documentation and/or other materials provided with the distribution.
   41  * 3. Neither the name of the University nor the names of its contributors
   42  *    may be used to endorse or promote products derived from this software
   43  *    without specific prior written permission.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   55  * SUCH DAMAGE.
   56  *
   57  *      @(#)fifo_vnops.c        8.10 (Berkeley) 5/27/95
   58  */
   59 
   60 #include <sys/cdefs.h>
   61 __KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.66 2008/04/28 20:24:08 martin Exp $");
   62 
   63 #include <sys/param.h>
   64 #include <sys/systm.h>
   65 #include <sys/proc.h>
   66 #include <sys/time.h>
   67 #include <sys/namei.h>
   68 #include <sys/vnode.h>
   69 #include <sys/socket.h>
   70 #include <sys/protosw.h>
   71 #include <sys/socketvar.h>
   72 #include <sys/stat.h>
   73 #include <sys/ioctl.h>
   74 #include <sys/file.h>
   75 #include <sys/errno.h>
   76 #include <sys/kmem.h>
   77 #include <sys/un.h>
   78 #include <sys/poll.h>
   79 #include <sys/event.h>
   80 #include <sys/condvar.h>
   81 
   82 #include <miscfs/fifofs/fifo.h>
   83 #include <miscfs/genfs/genfs.h>
   84 
   85 /*
   86  * This structure is associated with the FIFO vnode and stores
   87  * the state associated with the FIFO.
   88  */
   89 struct fifoinfo {
   90         struct socket   *fi_readsock;
   91         struct socket   *fi_writesock;
   92         kcondvar_t      fi_rcv;
   93         int             fi_readers;
   94         kcondvar_t      fi_wcv;
   95         int             fi_writers;
   96 };
   97 
   98 int (**fifo_vnodeop_p)(void *);
   99 const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
  100         { &vop_default_desc, vn_default_error },
  101         { &vop_lookup_desc, fifo_lookup },              /* lookup */
  102         { &vop_create_desc, fifo_create },              /* create */
  103         { &vop_mknod_desc, fifo_mknod },                /* mknod */
  104         { &vop_open_desc, fifo_open },                  /* open */
  105         { &vop_close_desc, fifo_close },                /* close */
  106         { &vop_access_desc, fifo_access },              /* access */
  107         { &vop_getattr_desc, fifo_getattr },            /* getattr */
  108         { &vop_setattr_desc, fifo_setattr },            /* setattr */
  109         { &vop_read_desc, fifo_read },                  /* read */
  110         { &vop_write_desc, fifo_write },                /* write */
  111         { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
  112         { &vop_poll_desc, fifo_poll },                  /* poll */
  113         { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
  114         { &vop_revoke_desc, fifo_revoke },              /* revoke */
  115         { &vop_mmap_desc, fifo_mmap },                  /* mmap */
  116         { &vop_fsync_desc, fifo_fsync },                /* fsync */
  117         { &vop_seek_desc, fifo_seek },                  /* seek */
  118         { &vop_remove_desc, fifo_remove },              /* remove */
  119         { &vop_link_desc, fifo_link },                  /* link */
  120         { &vop_rename_desc, fifo_rename },              /* rename */
  121         { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
  122         { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
  123         { &vop_symlink_desc, fifo_symlink },            /* symlink */
  124         { &vop_readdir_desc, fifo_readdir },            /* readdir */
  125         { &vop_readlink_desc, fifo_readlink },          /* readlink */
  126         { &vop_abortop_desc, fifo_abortop },            /* abortop */
  127         { &vop_inactive_desc, fifo_inactive },          /* inactive */
  128         { &vop_reclaim_desc, fifo_reclaim },            /* reclaim */
  129         { &vop_lock_desc, fifo_lock },                  /* lock */
  130         { &vop_unlock_desc, fifo_unlock },              /* unlock */
  131         { &vop_bmap_desc, fifo_bmap },                  /* bmap */
  132         { &vop_strategy_desc, fifo_strategy },          /* strategy */
  133         { &vop_print_desc, fifo_print },                /* print */
  134         { &vop_islocked_desc, fifo_islocked },          /* islocked */
  135         { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
  136         { &vop_advlock_desc, fifo_advlock },            /* advlock */
  137         { &vop_bwrite_desc, fifo_bwrite },              /* bwrite */
  138         { &vop_putpages_desc, fifo_putpages },          /* putpages */
  139         { (struct vnodeop_desc*)NULL, (int(*)(void *))NULL }
  140 };
  141 const struct vnodeopv_desc fifo_vnodeop_opv_desc =
  142         { &fifo_vnodeop_p, fifo_vnodeop_entries };
  143 
  144 /*
  145  * Trivial lookup routine that always fails.
  146  */
  147 /* ARGSUSED */
  148 int
  149 fifo_lookup(void *v)
  150 {
  151         struct vop_lookup_args /* {
  152                 struct vnode            *a_dvp;
  153                 struct vnode            **a_vpp;
  154                 struct componentname    *a_cnp;
  155         } */ *ap = v;
  156 
  157         *ap->a_vpp = NULL;
  158         return (ENOTDIR);
  159 }
  160 
  161 /*
  162  * Open called to set up a new instance of a fifo or
  163  * to find an active instance of a fifo.
  164  */
  165 /* ARGSUSED */
  166 int
  167 fifo_open(void *v)
  168 {
  169         struct vop_open_args /* {
  170                 struct vnode    *a_vp;
  171                 int             a_mode;
  172                 kauth_cred_t    a_cred;
  173         } */ *ap = v;
  174         struct lwp      *l = curlwp;
  175         struct vnode    *vp;
  176         struct fifoinfo *fip;
  177         struct proc     *p;
  178         struct socket   *rso, *wso;
  179         int             error;
  180 
  181         vp = ap->a_vp;
  182         p = l->l_proc;
  183 
  184         if ((fip = vp->v_fifoinfo) == NULL) {
  185                 fip = kmem_alloc(sizeof(*fip), KM_SLEEP);
  186                 vp->v_fifoinfo = fip;
  187                 error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL);
  188                 if (error != 0) {
  189                         kmem_free(fip, sizeof(*fip));
  190                         vp->v_fifoinfo = NULL;
  191                         return (error);
  192                 }
  193                 fip->fi_readsock = rso;
  194                 error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso);
  195                 if (error != 0) {
  196                         (void)soclose(rso);
  197                         kmem_free(fip, sizeof(*fip));
  198                         vp->v_fifoinfo = NULL;
  199                         return (error);
  200                 }
  201                 fip->fi_writesock = wso;
  202                 solock(wso);
  203                 if ((error = unp_connect2(wso, rso, PRU_CONNECT2)) != 0) {
  204                         sounlock(wso);
  205                         (void)soclose(wso);
  206                         (void)soclose(rso);
  207                         kmem_free(fip, sizeof(*fip));
  208                         vp->v_fifoinfo = NULL;
  209                         return (error);
  210                 }
  211                 fip->fi_readers = 0;
  212                 fip->fi_writers = 0;
  213                 wso->so_state |= SS_CANTRCVMORE;
  214                 rso->so_state |= SS_CANTSENDMORE;
  215                 cv_init(&fip->fi_rcv, "fiford");
  216                 cv_init(&fip->fi_wcv, "fifowr");
  217         } else {
  218                 wso = fip->fi_writesock;
  219                 rso = fip->fi_readsock;
  220                 solock(wso);
  221         }
  222 
  223         if (ap->a_mode & FREAD) {
  224                 if (fip->fi_readers++ == 0) {
  225                         wso->so_state &= ~SS_CANTSENDMORE;
  226                         cv_broadcast(&fip->fi_wcv);
  227                 }
  228         }
  229         if (ap->a_mode & FWRITE) {
  230                 if (fip->fi_writers++ == 0) {
  231                         rso->so_state &= ~SS_CANTRCVMORE;
  232                         cv_broadcast(&fip->fi_rcv);
  233                 }
  234         }
  235         if (ap->a_mode & FREAD) {
  236                 if (ap->a_mode & O_NONBLOCK) {
  237                 } else {
  238                         while (!soreadable(rso) && fip->fi_writers == 0) {
  239                                 VOP_UNLOCK(vp, 0);
  240                                 error = cv_wait_sig(&fip->fi_rcv,
  241                                     wso->so_lock);
  242                                 sounlock(wso);
  243                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  244                                 if (error)
  245                                         goto bad;
  246                                 solock(wso);
  247                         }
  248                 }
  249         }
  250         if (ap->a_mode & FWRITE) {
  251                 if (ap->a_mode & O_NONBLOCK) {
  252                         if (fip->fi_readers == 0) {
  253                                 error = ENXIO;
  254                                 sounlock(wso);
  255                                 goto bad;
  256                         }
  257                 } else {
  258                         while (fip->fi_readers == 0) {
  259                                 VOP_UNLOCK(vp, 0);
  260                                 error = cv_wait_sig(&fip->fi_wcv,
  261                                     wso->so_lock);
  262                                 sounlock(wso);
  263                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  264                                 if (error)
  265                                         goto bad;
  266                                 solock(wso);
  267                         }
  268                 }
  269         }
  270         sounlock(wso);
  271         return (0);
  272  bad:
  273         VOP_CLOSE(vp, ap->a_mode, ap->a_cred);
  274         return (error);
  275 }
  276 
  277 /*
  278  * Vnode op for read
  279  */
  280 /* ARGSUSED */
  281 int
  282 fifo_read(void *v)
  283 {
  284         struct vop_read_args /* {
  285                 struct vnode    *a_vp;
  286                 struct uio      *a_uio;
  287                 int             a_ioflag;
  288                 kauth_cred_t    a_cred;
  289         } */ *ap = v;
  290         struct uio      *uio;
  291         struct socket   *rso;
  292         int             error;
  293         size_t          startresid;
  294 
  295         uio = ap->a_uio;
  296         rso = ap->a_vp->v_fifoinfo->fi_readsock;
  297 #ifdef DIAGNOSTIC
  298         if (uio->uio_rw != UIO_READ)
  299                 panic("fifo_read mode");
  300 #endif
  301         if (uio->uio_resid == 0)
  302                 return (0);
  303         startresid = uio->uio_resid;
  304         VOP_UNLOCK(ap->a_vp, 0);
  305         if (ap->a_ioflag & IO_NDELAY) {
  306                 /* XXX Bogus, affects other threads. */
  307                 rso->so_nbio = 1;
  308         }
  309         error = (*rso->so_receive)(rso, NULL, uio, NULL, NULL, NULL);
  310         /*
  311          * Clear EOF indication after first such return.
  312          */
  313         if (uio->uio_resid == startresid)
  314                 rso->so_state &= ~SS_CANTRCVMORE;
  315         if (ap->a_ioflag & IO_NDELAY) {
  316                 rso->so_nbio = 0;
  317                 if (error == EWOULDBLOCK &&
  318                     ap->a_vp->v_fifoinfo->fi_writers == 0)
  319                         error = 0;
  320         }
  321         vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
  322         return (error);
  323 }
  324 
  325 /*
  326  * Vnode op for write
  327  */
  328 /* ARGSUSED */
  329 int
  330 fifo_write(void *v)
  331 {
  332         struct vop_write_args /* {
  333                 struct vnode    *a_vp;
  334                 struct uio      *a_uio;
  335                 int             a_ioflag;
  336                 kauth_cred_t    a_cred;
  337         } */ *ap = v;
  338         struct socket   *wso;
  339         int             error;
  340 
  341         wso = ap->a_vp->v_fifoinfo->fi_writesock;
  342 #ifdef DIAGNOSTIC
  343         if (ap->a_uio->uio_rw != UIO_WRITE)
  344                 panic("fifo_write mode");
  345 #endif
  346         VOP_UNLOCK(ap->a_vp, 0);
  347         if (ap->a_ioflag & IO_NDELAY) {
  348                 /* XXX Bogus, affects other threads. */
  349                 wso->so_nbio = 1;
  350         }
  351         error = (*wso->so_send)(wso, NULL, ap->a_uio, 0, NULL, 0, curlwp);
  352         if (ap->a_ioflag & IO_NDELAY)
  353                 wso->so_nbio = 0;
  354         vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
  355         return (error);
  356 }
  357 
  358 /*
  359  * Device ioctl operation.
  360  */
  361 /* ARGSUSED */
  362 int
  363 fifo_ioctl(void *v)
  364 {
  365         struct vop_ioctl_args /* {
  366                 struct vnode    *a_vp;
  367                 u_long          a_command;
  368                 void            *a_data;
  369                 int             a_fflag;
  370                 kauth_cred_t    a_cred;
  371                 struct lwp      *a_l;
  372         } */ *ap = v;
  373         struct file     filetmp;
  374         int             error;
  375 
  376         if (ap->a_command == FIONBIO)
  377                 return (0);
  378         if (ap->a_fflag & FREAD) {
  379                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
  380                 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data);
  381                 if (error)
  382                         return (error);
  383         }
  384         if (ap->a_fflag & FWRITE) {
  385                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
  386                 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data);
  387                 if (error)
  388                         return (error);
  389         }
  390         return (0);
  391 }
  392 
  393 /* ARGSUSED */
  394 int
  395 fifo_poll(void *v)
  396 {
  397         struct vop_poll_args /* {
  398                 struct vnode    *a_vp;
  399                 int             a_events;
  400                 struct lwp      *a_l;
  401         } */ *ap = v;
  402         struct socket   *so;
  403         int             revents;
  404 
  405         revents = 0;
  406         if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
  407                 so = ap->a_vp->v_fifoinfo->fi_readsock;
  408                 if (so)
  409                         revents |= sopoll(so, ap->a_events);
  410         }
  411         if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
  412                 so = ap->a_vp->v_fifoinfo->fi_writesock;
  413                 if (so)
  414                         revents |= sopoll(so, ap->a_events);
  415         }
  416 
  417         return (revents);
  418 }
  419 
  420 int
  421 fifo_inactive(void *v)
  422 {
  423         struct vop_inactive_args /* {
  424                 struct vnode    *a_vp;
  425                 struct lwp      *a_l;
  426         } */ *ap = v;
  427 
  428         VOP_UNLOCK(ap->a_vp, 0);
  429         return (0);
  430 }
  431 
  432 /*
  433  * This is a noop, simply returning what one has been given.
  434  */
  435 int
  436 fifo_bmap(void *v)
  437 {
  438         struct vop_bmap_args /* {
  439                 struct vnode    *a_vp;
  440                 daddr_t         a_bn;
  441                 struct vnode    **a_vpp;
  442                 daddr_t         *a_bnp;
  443                 int             *a_runp;
  444         } */ *ap = v;
  445 
  446         if (ap->a_vpp != NULL)
  447                 *ap->a_vpp = ap->a_vp;
  448         if (ap->a_bnp != NULL)
  449                 *ap->a_bnp = ap->a_bn;
  450         if (ap->a_runp != NULL)
  451                 *ap->a_runp = 0;
  452         return (0);
  453 }
  454 
  455 /*
  456  * Device close routine
  457  */
  458 /* ARGSUSED */
  459 int
  460 fifo_close(void *v)
  461 {
  462         struct vop_close_args /* {
  463                 struct vnode    *a_vp;
  464                 int             a_fflag;
  465                 kauth_cred_t    a_cred;
  466                 struct lwp      *a_l;
  467         } */ *ap = v;
  468         struct vnode    *vp;
  469         struct fifoinfo *fip;
  470         struct socket *wso, *rso;
  471         int isrevoke;
  472 
  473         vp = ap->a_vp;
  474         fip = vp->v_fifoinfo;
  475         isrevoke = (ap->a_fflag & (FREAD | FWRITE | FNONBLOCK)) == FNONBLOCK;
  476         wso = fip->fi_writesock;
  477         rso = fip->fi_readsock;
  478         solock(wso);
  479         if (isrevoke) {
  480                 if (fip->fi_readers != 0) {
  481                         fip->fi_readers = 0;
  482                         socantsendmore(wso);
  483                 }
  484                 if (fip->fi_writers != 0) {
  485                         fip->fi_writers = 0;
  486                         socantrcvmore(rso);
  487                 }
  488         } else {
  489                 if ((ap->a_fflag & FREAD) && --fip->fi_readers == 0)
  490                         socantsendmore(wso);
  491                 if ((ap->a_fflag & FWRITE) && --fip->fi_writers == 0)
  492                         socantrcvmore(rso);
  493         }
  494         if ((fip->fi_readers + fip->fi_writers) == 0) {
  495                 sounlock(wso);
  496                 (void) soclose(rso);
  497                 (void) soclose(wso);
  498                 cv_destroy(&fip->fi_rcv);
  499                 cv_destroy(&fip->fi_wcv);
  500                 kmem_free(fip, sizeof(*fip));
  501                 vp->v_fifoinfo = NULL;
  502         } else
  503                 sounlock(wso);
  504         return (0);
  505 }
  506 
  507 /*
  508  * Print out the contents of a fifo vnode.
  509  */
  510 int
  511 fifo_print(void *v)
  512 {
  513         struct vop_print_args /* {
  514                 struct vnode    *a_vp;
  515         } */ *ap = v;
  516 
  517         printf("tag VT_NON");
  518         fifo_printinfo(ap->a_vp);
  519         printf("\n");
  520         return 0;
  521 }
  522 
  523 /*
  524  * Print out internal contents of a fifo vnode.
  525  */
  526 void
  527 fifo_printinfo(struct vnode *vp)
  528 {
  529         struct fifoinfo *fip;
  530 
  531         fip = vp->v_fifoinfo;
  532         printf(", fifo with %d readers and %d writers",
  533             fip->fi_readers, fip->fi_writers);
  534 }
  535 
  536 /*
  537  * Return POSIX pathconf information applicable to fifo's.
  538  */
  539 int
  540 fifo_pathconf(void *v)
  541 {
  542         struct vop_pathconf_args /* {
  543                 struct vnode    *a_vp;
  544                 int             a_name;
  545                 register_t      *a_retval;
  546         } */ *ap = v;
  547 
  548         switch (ap->a_name) {
  549         case _PC_LINK_MAX:
  550                 *ap->a_retval = LINK_MAX;
  551                 return (0);
  552         case _PC_PIPE_BUF:
  553                 *ap->a_retval = PIPE_BUF;
  554                 return (0);
  555         case _PC_CHOWN_RESTRICTED:
  556                 *ap->a_retval = 1;
  557                 return (0);
  558         case _PC_SYNC_IO:
  559                 *ap->a_retval = 1;
  560                 return (0);
  561         default:
  562                 return (EINVAL);
  563         }
  564         /* NOTREACHED */
  565 }
  566 
  567 static void
  568 filt_fifordetach(struct knote *kn)
  569 {
  570         struct socket *so;
  571 
  572         so = (struct socket *)kn->kn_hook;
  573         solock(so);
  574         SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext);
  575         if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist))
  576                 so->so_rcv.sb_flags &= ~SB_KNOTE;
  577         sounlock(so);
  578 }
  579 
  580 static int
  581 filt_fiforead(struct knote *kn, long hint)
  582 {
  583         struct socket *so;
  584         int rv;
  585 
  586         so = (struct socket *)kn->kn_hook;
  587         if (hint != NOTE_SUBMIT)
  588                 solock(so);
  589         kn->kn_data = so->so_rcv.sb_cc;
  590         if (so->so_state & SS_CANTRCVMORE) {
  591                 kn->kn_flags |= EV_EOF;
  592                 rv = 1;
  593         } else {
  594                 kn->kn_flags &= ~EV_EOF;
  595                 rv = (kn->kn_data > 0);
  596         }
  597         if (hint != NOTE_SUBMIT)
  598                 sounlock(so);
  599         return rv;
  600 }
  601 
  602 static void
  603 filt_fifowdetach(struct knote *kn)
  604 {
  605         struct socket *so;
  606 
  607         so = (struct socket *)kn->kn_hook;
  608         solock(so);
  609         SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext);
  610         if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist))
  611                 so->so_snd.sb_flags &= ~SB_KNOTE;
  612         sounlock(so);
  613 }
  614 
  615 static int
  616 filt_fifowrite(struct knote *kn, long hint)
  617 {
  618         struct socket *so;
  619         int rv;
  620 
  621         so = (struct socket *)kn->kn_hook;
  622         if (hint != NOTE_SUBMIT)
  623                 solock(so);
  624         kn->kn_data = sbspace(&so->so_snd);
  625         if (so->so_state & SS_CANTSENDMORE) {
  626                 kn->kn_flags |= EV_EOF;
  627                 rv = 1;
  628         } else {
  629                 kn->kn_flags &= ~EV_EOF;
  630                 rv = (kn->kn_data >= so->so_snd.sb_lowat);
  631         }
  632         if (hint != NOTE_SUBMIT)
  633                 sounlock(so);
  634         return rv;
  635 }
  636 
  637 static const struct filterops fiforead_filtops =
  638         { 1, NULL, filt_fifordetach, filt_fiforead };
  639 static const struct filterops fifowrite_filtops =
  640         { 1, NULL, filt_fifowdetach, filt_fifowrite };
  641 
  642 /* ARGSUSED */
  643 int
  644 fifo_kqfilter(void *v)
  645 {
  646         struct vop_kqfilter_args /* {
  647                 struct vnode *a_vp;
  648                 struct knote *a_kn;
  649         } */ *ap = v;
  650         struct socket   *so;
  651         struct sockbuf  *sb;
  652 
  653         so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
  654         switch (ap->a_kn->kn_filter) {
  655         case EVFILT_READ:
  656                 ap->a_kn->kn_fop = &fiforead_filtops;
  657                 sb = &so->so_rcv;
  658                 break;
  659         case EVFILT_WRITE:
  660                 ap->a_kn->kn_fop = &fifowrite_filtops;
  661                 sb = &so->so_snd;
  662                 break;
  663         default:
  664                 return (EINVAL);
  665         }
  666 
  667         ap->a_kn->kn_hook = so;
  668 
  669         solock(so);
  670         SLIST_INSERT_HEAD(&sb->sb_sel.sel_klist, ap->a_kn, kn_selnext);
  671         sb->sb_flags |= SB_KNOTE;
  672         sounlock(so);
  673 
  674         return (0);
  675 }

Cache object: fb08b04c83bd875bdaad848e0963ecb6


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