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.91 2021/10/11 01:07:36 thorpej 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.91 2021/10/11 01:07:36 thorpej 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 /*
   99  * Trivial lookup routine that always fails.
  100  */
  101 /* ARGSUSED */
  102 static int
  103 fifo_lookup(void *v)
  104 {
  105         struct vop_lookup_v2_args /* {
  106                 struct vnode            *a_dvp;
  107                 struct vnode            **a_vpp;
  108                 struct componentname    *a_cnp;
  109         } */ *ap = v;
  110 
  111         *ap->a_vpp = NULL;
  112         return (ENOTDIR);
  113 }
  114 
  115 /*
  116  * Open called to set up a new instance of a fifo or
  117  * to find an active instance of a fifo.
  118  */
  119 static int
  120 fifo_open(void *v)
  121 {
  122         struct vop_open_args /* {
  123                 struct vnode    *a_vp;
  124                 int             a_mode;
  125                 kauth_cred_t    a_cred;
  126         } */ *ap = v;
  127         struct lwp      *l = curlwp;
  128         struct vnode    *vp;
  129         struct fifoinfo *fip;
  130         struct socket   *rso, *wso;
  131         int             error;
  132 
  133         vp = ap->a_vp;
  134         KASSERT(VOP_ISLOCKED(vp));
  135 
  136         if ((fip = vp->v_fifoinfo) == NULL) {
  137                 fip = kmem_alloc(sizeof(*fip), KM_SLEEP);
  138                 error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL);
  139                 if (error != 0) {
  140                         kmem_free(fip, sizeof(*fip));
  141                         return (error);
  142                 }
  143                 fip->fi_readsock = rso;
  144                 error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso);
  145                 if (error != 0) {
  146                         (void)soclose(rso);
  147                         kmem_free(fip, sizeof(*fip));
  148                         return (error);
  149                 }
  150                 fip->fi_writesock = wso;
  151                 solock(wso);
  152                 if ((error = unp_connect2(wso, rso)) != 0) {
  153                         sounlock(wso);
  154                         (void)soclose(wso);
  155                         (void)soclose(rso);
  156                         kmem_free(fip, sizeof(*fip));
  157                         return (error);
  158                 }
  159 
  160                 /*
  161                  * FIFOs must be readable when there is at least 1
  162                  * byte of data available in the receive buffer.
  163                  *
  164                  * FIFOs must be writable when there is space for
  165                  * at least PIPE_BUF bytes in the send buffer.
  166                  * If we're increasing the low water mark for the
  167                  * send buffer, then mimic how soreserve() would
  168                  * have set the high water mark.
  169                  */
  170                 rso->so_rcv.sb_lowat = 1;
  171                 if (wso->so_snd.sb_lowat < PIPE_BUF) {
  172                         wso->so_snd.sb_hiwat = PIPE_BUF * 2;
  173                 }
  174                 wso->so_snd.sb_lowat = PIPE_BUF;
  175 
  176                 fip->fi_readers = 0;
  177                 fip->fi_writers = 0;
  178                 wso->so_state |= SS_CANTRCVMORE;
  179                 rso->so_state |= SS_CANTSENDMORE;
  180                 cv_init(&fip->fi_rcv, "fiford");
  181                 cv_init(&fip->fi_wcv, "fifowr");
  182                 vp->v_fifoinfo = fip;
  183         } else {
  184                 wso = fip->fi_writesock;
  185                 rso = fip->fi_readsock;
  186                 solock(wso);
  187         }
  188 
  189         if (ap->a_mode & FREAD) {
  190                 if (fip->fi_readers++ == 0) {
  191                         wso->so_state &= ~SS_CANTSENDMORE;
  192                         cv_broadcast(&fip->fi_wcv);
  193                 }
  194         }
  195         if (ap->a_mode & FWRITE) {
  196                 if (fip->fi_writers++ == 0) {
  197                         rso->so_state &= ~SS_CANTRCVMORE;
  198                         cv_broadcast(&fip->fi_rcv);
  199                 }
  200         }
  201         if (ap->a_mode & FREAD) {
  202                 if (ap->a_mode & O_NONBLOCK) {
  203                 } else {
  204                         while (!soreadable(rso) && fip->fi_writers == 0) {
  205                                 VOP_UNLOCK(vp);
  206                                 error = cv_wait_sig(&fip->fi_rcv,
  207                                     wso->so_lock);
  208                                 sounlock(wso);
  209                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  210                                 if (error)
  211                                         goto bad;
  212                                 solock(wso);
  213                         }
  214                 }
  215         }
  216         if (ap->a_mode & FWRITE) {
  217                 if (ap->a_mode & O_NONBLOCK) {
  218                         if (fip->fi_readers == 0) {
  219                                 error = ENXIO;
  220                                 sounlock(wso);
  221                                 goto bad;
  222                         }
  223                 } else {
  224                         while (fip->fi_readers == 0) {
  225                                 VOP_UNLOCK(vp);
  226                                 error = cv_wait_sig(&fip->fi_wcv,
  227                                     wso->so_lock);
  228                                 sounlock(wso);
  229                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
  230                                 if (error)
  231                                         goto bad;
  232                                 solock(wso);
  233                         }
  234                 }
  235         }
  236         sounlock(wso);
  237         return (0);
  238  bad:
  239         VOP_CLOSE(vp, ap->a_mode, ap->a_cred);
  240         return (error);
  241 }
  242 
  243 /*
  244  * Vnode op for read
  245  */
  246 /* ARGSUSED */
  247 static int
  248 fifo_read(void *v)
  249 {
  250         struct vop_read_args /* {
  251                 struct vnode    *a_vp;
  252                 struct uio      *a_uio;
  253                 int             a_ioflag;
  254                 kauth_cred_t    a_cred;
  255         } */ *ap = v;
  256         struct uio      *uio;
  257         struct socket   *rso;
  258         int             error, sflags;
  259         size_t          startresid;
  260 
  261         uio = ap->a_uio;
  262         rso = ap->a_vp->v_fifoinfo->fi_readsock;
  263 #ifdef DIAGNOSTIC
  264         if (uio->uio_rw != UIO_READ)
  265                 panic("fifo_read mode");
  266 #endif
  267         if (uio->uio_resid == 0)
  268                 return (0);
  269         startresid = uio->uio_resid;
  270         VOP_UNLOCK(ap->a_vp);
  271         sflags = (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0;
  272         error = (*rso->so_receive)(rso, NULL, uio, NULL, NULL, &sflags);
  273         /*
  274          * Clear EOF indication after first such return.
  275          */
  276         if (error == 0 && uio->uio_resid == startresid)
  277                 rso->so_state &= ~SS_CANTRCVMORE;
  278         if (ap->a_ioflag & IO_NDELAY) {
  279                 if (error == EWOULDBLOCK &&
  280                     ap->a_vp->v_fifoinfo->fi_writers == 0)
  281                         error = 0;
  282         }
  283         vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
  284         return (error);
  285 }
  286 
  287 /*
  288  * Vnode op for write
  289  */
  290 /* ARGSUSED */
  291 static int
  292 fifo_write(void *v)
  293 {
  294         struct vop_write_args /* {
  295                 struct vnode    *a_vp;
  296                 struct uio      *a_uio;
  297                 int             a_ioflag;
  298                 kauth_cred_t    a_cred;
  299         } */ *ap = v;
  300         struct socket   *wso;
  301         int             error, sflags;
  302 
  303         wso = ap->a_vp->v_fifoinfo->fi_writesock;
  304 #ifdef DIAGNOSTIC
  305         if (ap->a_uio->uio_rw != UIO_WRITE)
  306                 panic("fifo_write mode");
  307 #endif
  308         VOP_UNLOCK(ap->a_vp);
  309         sflags = (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0;
  310         error = (*wso->so_send)(wso, NULL, ap->a_uio, 0, NULL, sflags, curlwp);
  311         vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
  312         return (error);
  313 }
  314 
  315 /*
  316  * Device ioctl operation.
  317  */
  318 /* ARGSUSED */
  319 static int
  320 fifo_ioctl(void *v)
  321 {
  322         struct vop_ioctl_args /* {
  323                 struct vnode    *a_vp;
  324                 u_long          a_command;
  325                 void            *a_data;
  326                 int             a_fflag;
  327                 kauth_cred_t    a_cred;
  328                 struct lwp      *a_l;
  329         } */ *ap = v;
  330         struct file     filetmp;
  331         int             error;
  332 
  333         if (ap->a_command == FIONBIO)
  334                 return (0);
  335         if (ap->a_fflag & FREAD) {
  336                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
  337                 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data);
  338                 if (error)
  339                         return (error);
  340         }
  341         if (ap->a_fflag & FWRITE) {
  342                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
  343                 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data);
  344                 if (error)
  345                         return (error);
  346         }
  347         return (0);
  348 }
  349 
  350 /* ARGSUSED */
  351 static int
  352 fifo_poll(void *v)
  353 {
  354         struct vop_poll_args /* {
  355                 struct vnode    *a_vp;
  356                 int             a_events;
  357         } */ *ap = v;
  358         struct socket   *rso = ap->a_vp->v_fifoinfo->fi_readsock;
  359         struct socket   *wso = ap->a_vp->v_fifoinfo->fi_writesock;
  360         struct socket   *lso = NULL;
  361         int             events;
  362 
  363         /*
  364          * N.B. We're using a slightly different naming convention
  365          * for these variables that most poll handlers.
  366          */
  367         int             revents = 0;
  368         int             wevents = 0;
  369 
  370         if (rso != NULL) {
  371                 lso = rso;
  372         } else if (wso != NULL) {
  373                 lso = wso;
  374         }
  375 
  376         if (lso == NULL) {
  377                 /* No associated sockets -> no events to report. */
  378                 return 0;
  379         }
  380 
  381         KASSERT(rso == NULL || lso->so_lock == rso->so_lock);
  382         KASSERT(wso == NULL || lso->so_lock == wso->so_lock);
  383 
  384         solock(lso);
  385 
  386         if (rso != NULL) {
  387                 events = ap->a_events & (POLLIN | POLLRDNORM);
  388                 if (events != 0 && soreadable(rso)) {
  389                         revents |= events;
  390                 }
  391                 if (rso->so_state & SS_CANTRCVMORE) {
  392                         revents |= POLLHUP;
  393                 }
  394                 /*
  395                  * We always selrecord the read side here regardless
  396                  * of the caller's read interest because we need to
  397                  * action POLLHUP.
  398                  */
  399                 if (revents == 0) {
  400                         selrecord(curlwp, &rso->so_rcv.sb_sel);
  401                         rso->so_rcv.sb_flags |= SB_NOTIFY;
  402                 }
  403         }
  404 
  405         /* POSIX sez: POLLHUP and POLLOUT are mutually-exclusive. */
  406         if (wso != NULL && (revents & POLLHUP) == 0) {
  407                 events = ap->a_events & (POLLOUT | POLLWRNORM);
  408                 if (events != 0 && sowritable(wso)) {
  409                         wevents |= events;
  410                 }
  411                 if (wevents == 0 && events != 0) {
  412                         selrecord(curlwp, &wso->so_snd.sb_sel);
  413                         wso->so_snd.sb_flags |= SB_NOTIFY;
  414                 }
  415         }
  416 
  417         sounlock(lso);
  418 
  419         return (revents | wevents);
  420 }
  421 
  422 static int
  423 fifo_inactive(void *v)
  424 {
  425         struct vop_inactive_v2_args /* {
  426                 struct vnode    *a_vp;
  427                 struct lwp      *a_l;
  428         } */ *ap __unused = v;
  429 
  430         return (0);
  431 }
  432 
  433 /*
  434  * This is a noop, simply returning what one has been given.
  435  */
  436 static int
  437 fifo_bmap(void *v)
  438 {
  439         struct vop_bmap_args /* {
  440                 struct vnode    *a_vp;
  441                 daddr_t         a_bn;
  442                 struct vnode    **a_vpp;
  443                 daddr_t         *a_bnp;
  444                 int             *a_runp;
  445         } */ *ap = v;
  446 
  447         if (ap->a_vpp != NULL)
  448                 *ap->a_vpp = ap->a_vp;
  449         if (ap->a_bnp != NULL)
  450                 *ap->a_bnp = ap->a_bn;
  451         if (ap->a_runp != NULL)
  452                 *ap->a_runp = 0;
  453         return (0);
  454 }
  455 
  456 /*
  457  * This is like socantrcvmore(), but we send the POLL_HUP code.
  458  */
  459 static void
  460 fifo_socantrcvmore(struct socket *so)
  461 {
  462         KASSERT(solocked(so));
  463 
  464         so->so_state |= SS_CANTRCVMORE;
  465         if (sb_notify(&so->so_rcv)) {
  466                 sowakeup(so, &so->so_rcv, POLL_HUP);
  467         }
  468 }
  469 
  470 /*
  471  * Device close routine
  472  */
  473 /* ARGSUSED */
  474 static int
  475 fifo_close(void *v)
  476 {
  477         struct vop_close_args /* {
  478                 struct vnode    *a_vp;
  479                 int             a_fflag;
  480                 kauth_cred_t    a_cred;
  481                 struct lwp      *a_l;
  482         } */ *ap = v;
  483         struct vnode    *vp;
  484         struct fifoinfo *fip;
  485         struct socket *wso, *rso;
  486         int isrevoke;
  487 
  488         vp = ap->a_vp;
  489         fip = vp->v_fifoinfo;
  490         isrevoke = (ap->a_fflag & (FREAD | FWRITE | FNONBLOCK)) == FNONBLOCK;
  491         wso = fip->fi_writesock;
  492         rso = fip->fi_readsock;
  493         solock(wso);
  494         if (isrevoke) {
  495                 if (fip->fi_readers != 0) {
  496                         fip->fi_readers = 0;
  497                         socantsendmore(wso);
  498                 }
  499                 if (fip->fi_writers != 0) {
  500                         fip->fi_writers = 0;
  501                         fifo_socantrcvmore(rso);
  502                 }
  503         } else {
  504                 if ((ap->a_fflag & FREAD) && --fip->fi_readers == 0)
  505                         socantsendmore(wso);
  506                 if ((ap->a_fflag & FWRITE) && --fip->fi_writers == 0)
  507                         fifo_socantrcvmore(rso);
  508         }
  509         if ((fip->fi_readers + fip->fi_writers) == 0) {
  510                 sounlock(wso);
  511                 (void) soclose(rso);
  512                 (void) soclose(wso);
  513                 cv_destroy(&fip->fi_rcv);
  514                 cv_destroy(&fip->fi_wcv);
  515                 kmem_free(fip, sizeof(*fip));
  516                 vp->v_fifoinfo = NULL;
  517         } else
  518                 sounlock(wso);
  519         return (0);
  520 }
  521 
  522 /*
  523  * Print out internal contents of a fifo vnode.
  524  */
  525 static void
  526 fifo_printinfo(struct vnode *vp)
  527 {
  528         struct fifoinfo *fip;
  529 
  530         fip = vp->v_fifoinfo;
  531         printf(", fifo with %d readers and %d writers",
  532             fip->fi_readers, fip->fi_writers);
  533 }
  534 
  535 /*
  536  * Print out the contents of a fifo vnode.
  537  */
  538 static int
  539 fifo_print(void *v)
  540 {
  541         struct vop_print_args /* {
  542                 struct vnode    *a_vp;
  543         } */ *ap = v;
  544 
  545         /*
  546          * We are most likely being called with the vnode belonging
  547          * to some file system and this is not printed.
  548          */
  549         if (ap->a_vp->v_tag == VT_NON)
  550                 printf("tag VT_NON");
  551 
  552         fifo_printinfo(ap->a_vp);
  553         printf("\n");
  554         return 0;
  555 }
  556 
  557 /*
  558  * Return POSIX pathconf information applicable to fifo's.
  559  */
  560 static int
  561 fifo_pathconf(void *v)
  562 {
  563         struct vop_pathconf_args /* {
  564                 struct vnode    *a_vp;
  565                 int             a_name;
  566                 register_t      *a_retval;
  567         } */ *ap = v;
  568 
  569         switch (ap->a_name) {
  570         case _PC_LINK_MAX:
  571                 *ap->a_retval = LINK_MAX;
  572                 return (0);
  573         case _PC_PIPE_BUF:
  574                 *ap->a_retval = PIPE_BUF;
  575                 return (0);
  576         case _PC_CHOWN_RESTRICTED:
  577                 *ap->a_retval = 1;
  578                 return (0);
  579         case _PC_SYNC_IO:
  580                 *ap->a_retval = 1;
  581                 return (0);
  582         default:
  583                 return genfs_pathconf(ap);
  584         }
  585         /* NOTREACHED */
  586 }
  587 
  588 static void
  589 filt_fifordetach(struct knote *kn)
  590 {
  591         struct socket *so;
  592 
  593         so = (struct socket *)kn->kn_hook;
  594         solock(so);
  595         if (selremove_knote(&so->so_rcv.sb_sel, kn))
  596                 so->so_rcv.sb_flags &= ~SB_KNOTE;
  597         sounlock(so);
  598 }
  599 
  600 static int
  601 filt_fiforead(struct knote *kn, long hint)
  602 {
  603         struct socket *so;
  604         int rv;
  605 
  606         so = (struct socket *)kn->kn_hook;
  607         if (hint != NOTE_SUBMIT)
  608                 solock(so);
  609         kn->kn_data = so->so_rcv.sb_cc;
  610         if (so->so_state & SS_CANTRCVMORE) {
  611                 knote_set_eof(kn, 0);
  612                 rv = 1;
  613         } else {
  614                 knote_clear_eof(kn);
  615                 rv = (kn->kn_data >= so->so_rcv.sb_lowat);
  616         }
  617         if (hint != NOTE_SUBMIT)
  618                 sounlock(so);
  619         return rv;
  620 }
  621 
  622 static void
  623 filt_fifowdetach(struct knote *kn)
  624 {
  625         struct socket *so;
  626 
  627         so = (struct socket *)kn->kn_hook;
  628         solock(so);
  629         if (selremove_knote(&so->so_snd.sb_sel, kn))
  630                 so->so_snd.sb_flags &= ~SB_KNOTE;
  631         sounlock(so);
  632 }
  633 
  634 static int
  635 filt_fifowrite(struct knote *kn, long hint)
  636 {
  637         struct socket *so;
  638         int rv;
  639 
  640         so = (struct socket *)kn->kn_hook;
  641         if (hint != NOTE_SUBMIT)
  642                 solock(so);
  643         kn->kn_data = sbspace(&so->so_snd);
  644         if (so->so_state & SS_CANTSENDMORE) {
  645                 knote_set_eof(kn, 0);
  646                 rv = 1;
  647         } else {
  648                 knote_clear_eof(kn);
  649                 rv = (kn->kn_data >= so->so_snd.sb_lowat);
  650         }
  651         if (hint != NOTE_SUBMIT)
  652                 sounlock(so);
  653         return rv;
  654 }
  655 
  656 static const struct filterops fiforead_filtops = {
  657         .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE,
  658         .f_attach = NULL,
  659         .f_detach = filt_fifordetach,
  660         .f_event = filt_fiforead,
  661 };
  662 
  663 static const struct filterops fifowrite_filtops = {
  664         .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE,
  665         .f_attach = NULL,
  666         .f_detach = filt_fifowdetach,
  667         .f_event = filt_fifowrite,
  668 };
  669 
  670 /* ARGSUSED */
  671 static int
  672 fifo_kqfilter(void *v)
  673 {
  674         struct vop_kqfilter_args /* {
  675                 struct vnode *a_vp;
  676                 struct knote *a_kn;
  677         } */ *ap = v;
  678         struct socket   *so;
  679         struct sockbuf  *sb;
  680 
  681         switch (ap->a_kn->kn_filter) {
  682         case EVFILT_READ:
  683                 so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
  684                 ap->a_kn->kn_fop = &fiforead_filtops;
  685                 sb = &so->so_rcv;
  686                 break;
  687         case EVFILT_WRITE:
  688                 so = (struct socket *)ap->a_vp->v_fifoinfo->fi_writesock;
  689                 ap->a_kn->kn_fop = &fifowrite_filtops;
  690                 sb = &so->so_snd;
  691                 break;
  692         default:
  693                 return (EINVAL);
  694         }
  695 
  696         ap->a_kn->kn_hook = so;
  697 
  698         solock(so);
  699         selrecord_knote(&sb->sb_sel, ap->a_kn);
  700         sb->sb_flags |= SB_KNOTE;
  701         sounlock(so);
  702 
  703         return (0);
  704 }
  705 
  706 int (**fifo_vnodeop_p)(void *);
  707 const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
  708         { &vop_default_desc, vn_default_error },
  709         { &vop_parsepath_desc, genfs_parsepath },       /* parsepath */
  710         { &vop_lookup_desc, fifo_lookup },              /* lookup */
  711         { &vop_create_desc, genfs_badop },              /* create */
  712         { &vop_mknod_desc, genfs_badop },               /* mknod */
  713         { &vop_open_desc, fifo_open },                  /* open */
  714         { &vop_close_desc, fifo_close },                /* close */
  715         { &vop_access_desc, genfs_ebadf },              /* access */
  716         { &vop_accessx_desc, genfs_accessx },           /* accessx */
  717         { &vop_getattr_desc, genfs_ebadf },             /* getattr */
  718         { &vop_setattr_desc, genfs_ebadf },             /* setattr */
  719         { &vop_read_desc, fifo_read },                  /* read */
  720         { &vop_write_desc, fifo_write },                /* write */
  721         { &vop_fallocate_desc, genfs_eopnotsupp },      /* fallocate */
  722         { &vop_fdiscard_desc, genfs_eopnotsupp },       /* fdiscard */
  723         { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
  724         { &vop_poll_desc, fifo_poll },                  /* poll */
  725         { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
  726         { &vop_revoke_desc, genfs_revoke },             /* revoke */
  727         { &vop_mmap_desc, genfs_badop },                /* mmap */
  728         { &vop_fsync_desc, genfs_nullop },              /* fsync */
  729         { &vop_seek_desc, genfs_badop },                /* seek */
  730         { &vop_remove_desc, genfs_badop },              /* remove */
  731         { &vop_link_desc, genfs_badop },                /* link */
  732         { &vop_rename_desc, genfs_badop },              /* rename */
  733         { &vop_mkdir_desc, genfs_badop },               /* mkdir */
  734         { &vop_rmdir_desc, genfs_badop },               /* rmdir */
  735         { &vop_symlink_desc, genfs_badop },             /* symlink */
  736         { &vop_readdir_desc, genfs_badop },             /* readdir */
  737         { &vop_readlink_desc, genfs_badop },            /* readlink */
  738         { &vop_abortop_desc, genfs_badop },             /* abortop */
  739         { &vop_inactive_desc, fifo_inactive },          /* inactive */
  740         { &vop_reclaim_desc, genfs_nullop },            /* reclaim */
  741         { &vop_lock_desc, genfs_lock },                 /* lock */
  742         { &vop_unlock_desc, genfs_unlock },             /* unlock */
  743         { &vop_bmap_desc, fifo_bmap },                  /* bmap */
  744         { &vop_strategy_desc, genfs_badop },            /* strategy */
  745         { &vop_print_desc, fifo_print },                /* print */
  746         { &vop_islocked_desc, genfs_islocked },         /* islocked */
  747         { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
  748         { &vop_advlock_desc, genfs_einval },            /* advlock */
  749         { &vop_bwrite_desc, genfs_nullop },             /* bwrite */
  750         { &vop_putpages_desc, genfs_null_putpages },    /* putpages */
  751         { NULL, NULL }
  752 };
  753 const struct vnodeopv_desc fifo_vnodeop_opv_desc =
  754         { &fifo_vnodeop_p, fifo_vnodeop_entries };

Cache object: 940ea6795aaf9814d6f8f206fe8795af


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