root/miscfs/fifofs/fifo_vnops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fifo_vnoperate
  2. fifo_lookup
  3. fifo_open
  4. fifo_read
  5. fifo_write
  6. fifo_ioctl
  7. fifo_poll
  8. fifo_inactive
  9. fifo_bmap
  10. fifo_close
  11. fifo_reclaim
  12. fifo_print
  13. fifo_printinfo
  14. fifo_pathconf
  15. fifo_ebadf
  16. fifo_advlock
  17. fifo_badop
  18. fifo_kqfilter
  19. filt_fifordetach
  20. filt_fiforead
  21. filt_fifowdetach
  22. filt_fifowrite

    1 /*      $OpenBSD: fifo_vnops.c,v 1.24 2007/06/18 08:30:07 jasper Exp $  */
    2 /*      $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1990, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)fifo_vnops.c        8.4 (Berkeley) 8/10/94
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/proc.h>
   37 #include <sys/systm.h>
   38 #include <sys/time.h>
   39 #include <sys/namei.h>
   40 #include <sys/vnode.h>
   41 #include <sys/socket.h>
   42 #include <sys/socketvar.h>
   43 #include <sys/stat.h>
   44 #include <sys/ioctl.h>
   45 #include <sys/file.h>
   46 #include <sys/event.h>
   47 #include <sys/errno.h>
   48 #include <sys/malloc.h>
   49 #include <sys/poll.h>
   50 #include <sys/un.h>
   51 #include <miscfs/fifofs/fifo.h>
   52 
   53 /*
   54  * This structure is associated with the FIFO vnode and stores
   55  * the state associated with the FIFO.
   56  */
   57 struct fifoinfo {
   58         struct socket   *fi_readsock;
   59         struct socket   *fi_writesock;
   60         long            fi_readers;
   61         long            fi_writers;
   62 };
   63 
   64 int (**fifo_vnodeop_p)(void *);
   65 struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
   66         { &vop_default_desc, vn_default_error },
   67         { &vop_lookup_desc, fifo_lookup },              /* lookup */
   68         { &vop_create_desc, fifo_create },              /* create */
   69         { &vop_mknod_desc, fifo_mknod },                /* mknod */
   70         { &vop_open_desc, fifo_open },                  /* open */
   71         { &vop_close_desc, fifo_close },                /* close */
   72         { &vop_access_desc, fifo_access },              /* access */
   73         { &vop_getattr_desc, fifo_getattr },            /* getattr */
   74         { &vop_setattr_desc, fifo_setattr },            /* setattr */
   75         { &vop_read_desc, fifo_read },                  /* read */
   76         { &vop_write_desc, fifo_write },                /* write */
   77         { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
   78         { &vop_poll_desc, fifo_poll },                  /* poll */
   79         { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
   80         { &vop_revoke_desc, fifo_revoke },              /* revoke */
   81         { &vop_fsync_desc, fifo_fsync },                /* fsync */
   82         { &vop_remove_desc, fifo_remove },              /* remove */
   83         { &vop_link_desc, fifo_link },                  /* link */
   84         { &vop_rename_desc, fifo_rename },              /* rename */
   85         { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
   86         { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
   87         { &vop_symlink_desc, fifo_symlink },            /* symlink */
   88         { &vop_readdir_desc, fifo_readdir },            /* readdir */
   89         { &vop_readlink_desc, fifo_readlink },          /* readlink */
   90         { &vop_abortop_desc, fifo_abortop },            /* abortop */
   91         { &vop_inactive_desc, fifo_inactive },          /* inactive */
   92         { &vop_reclaim_desc, fifo_reclaim },            /* reclaim */
   93         { &vop_lock_desc, fifo_lock },                  /* lock */
   94         { &vop_unlock_desc, fifo_unlock },              /* unlock */
   95         { &vop_bmap_desc, fifo_bmap },                  /* bmap */
   96         { &vop_strategy_desc, fifo_strategy },          /* strategy */
   97         { &vop_print_desc, fifo_print },                /* print */
   98         { &vop_islocked_desc, fifo_islocked },          /* islocked */
   99         { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
  100         { &vop_advlock_desc, fifo_advlock },            /* advlock */
  101         { &vop_bwrite_desc, fifo_bwrite },              /* bwrite */
  102         { NULL, NULL }
  103 };
  104 
  105 struct vnodeopv_desc fifo_vnodeop_opv_desc =
  106         { &fifo_vnodeop_p, fifo_vnodeop_entries };
  107 
  108 int
  109 fifo_vnoperate(void *v)
  110 {
  111         struct vop_generic_args *ap = v;
  112 
  113         return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
  114 }
  115 
  116 void    filt_fifordetach(struct knote *kn);
  117 int     filt_fiforead(struct knote *kn, long hint);
  118 void    filt_fifowdetach(struct knote *kn);
  119 int     filt_fifowrite(struct knote *kn, long hint);
  120 
  121 struct filterops fiforead_filtops =
  122         { 1, NULL, filt_fifordetach, filt_fiforead };
  123 struct filterops fifowrite_filtops =
  124         { 1, NULL, filt_fifowdetach, filt_fifowrite };
  125 
  126 /*
  127  * Trivial lookup routine that always fails.
  128  */
  129 /* ARGSUSED */
  130 int
  131 fifo_lookup(void *v)
  132 {
  133         struct vop_lookup_args *ap = v;
  134         
  135         *ap->a_vpp = NULL;
  136         return (ENOTDIR);
  137 }
  138 
  139 /*
  140  * Open called to set up a new instance of a fifo or
  141  * to find an active instance of a fifo.
  142  */
  143 /* ARGSUSED */
  144 int
  145 fifo_open(void *v)
  146 {
  147         struct vop_open_args *ap = v;
  148         struct vnode *vp = ap->a_vp;
  149         struct fifoinfo *fip;
  150         struct proc *p = ap->a_p;
  151         struct socket *rso, *wso;
  152         int error;
  153 
  154         if ((fip = vp->v_fifoinfo) == NULL) {
  155                 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
  156                 vp->v_fifoinfo = fip;
  157                 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) {
  158                         free(fip, M_VNODE);
  159                         vp->v_fifoinfo = NULL;
  160                         return (error);
  161                 }
  162                 fip->fi_readsock = rso;
  163                 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) {
  164                         (void)soclose(rso);
  165                         free(fip, M_VNODE);
  166                         vp->v_fifoinfo = NULL;
  167                         return (error);
  168                 }
  169                 fip->fi_writesock = wso;
  170                 if ((error = unp_connect2(wso, rso)) != 0) {
  171                         (void)soclose(wso);
  172                         (void)soclose(rso);
  173                         free(fip, M_VNODE);
  174                         vp->v_fifoinfo = NULL;
  175                         return (error);
  176                 }
  177                 fip->fi_readers = fip->fi_writers = 0;
  178                 wso->so_snd.sb_lowat = PIPE_BUF;
  179                 rso->so_state |= SS_CANTRCVMORE;
  180         }
  181         if (ap->a_mode & FREAD) {
  182                 fip->fi_readers++;
  183                 if (fip->fi_readers == 1) {
  184                         fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
  185                         if (fip->fi_writers > 0)
  186                                 wakeup(&fip->fi_writers);
  187                 }
  188         }
  189         if (ap->a_mode & FWRITE) {
  190                 fip->fi_writers++;
  191                 if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
  192                         error = ENXIO;
  193                         goto bad;
  194                 }
  195                 if (fip->fi_writers == 1) {
  196                         fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
  197                         if (fip->fi_readers > 0)
  198                                 wakeup(&fip->fi_readers);
  199                 }
  200         }
  201         if ((ap->a_mode & O_NONBLOCK) == 0) {
  202                 if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
  203                         VOP_UNLOCK(vp, 0, p);
  204                         error = tsleep(&fip->fi_readers,
  205                             PCATCH | PSOCK, "fifor", 0);
  206                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  207                         if (error)
  208                                 goto bad;
  209                 }
  210                 if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
  211                         VOP_UNLOCK(vp, 0, p);
  212                         error = tsleep(&fip->fi_writers,
  213                             PCATCH | PSOCK, "fifow", 0);
  214                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  215                         if (error)
  216                                 goto bad;
  217                 }
  218         }
  219         return (0);
  220 bad:
  221         VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
  222         return (error);
  223 }
  224 
  225 /*
  226  * Vnode op for read
  227  */
  228 /* ARGSUSED */
  229 int
  230 fifo_read(void *v)
  231 {
  232         struct vop_read_args *ap = v;
  233         struct uio *uio = ap->a_uio;
  234         struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
  235         struct proc *p = uio->uio_procp;
  236         int error;
  237 
  238 #ifdef DIAGNOSTIC
  239         if (uio->uio_rw != UIO_READ)
  240                 panic("fifo_read mode");
  241 #endif
  242         if (uio->uio_resid == 0)
  243                 return (0);
  244         if (ap->a_ioflag & IO_NDELAY)
  245                 rso->so_state |= SS_NBIO;
  246         VOP_UNLOCK(ap->a_vp, 0, p);
  247         error = soreceive(rso, NULL, uio, NULL, NULL, NULL);
  248         vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
  249         if (ap->a_ioflag & IO_NDELAY) {
  250                 rso->so_state &= ~SS_NBIO;
  251                 if (error == EWOULDBLOCK &&
  252                     ap->a_vp->v_fifoinfo->fi_writers == 0)
  253                         error = 0;
  254         }
  255         return (error);
  256 }
  257 
  258 /*
  259  * Vnode op for write
  260  */
  261 /* ARGSUSED */
  262 int
  263 fifo_write(void *v)
  264 {
  265         struct vop_write_args *ap = v;
  266         struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
  267         struct proc *p = ap->a_uio->uio_procp;
  268         int error;
  269 
  270 #ifdef DIAGNOSTIC
  271         if (ap->a_uio->uio_rw != UIO_WRITE)
  272                 panic("fifo_write mode");
  273 #endif
  274         if (ap->a_ioflag & IO_NDELAY)
  275                 wso->so_state |= SS_NBIO;
  276         VOP_UNLOCK(ap->a_vp, 0, p);
  277         error = sosend(wso, NULL, ap->a_uio, NULL, NULL, 0);
  278         vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
  279         if (ap->a_ioflag & IO_NDELAY)
  280                 wso->so_state &= ~SS_NBIO;
  281         return (error);
  282 }
  283 
  284 /*
  285  * Device ioctl operation.
  286  */
  287 /* ARGSUSED */
  288 int
  289 fifo_ioctl(void *v)
  290 {
  291         struct vop_ioctl_args *ap = v;
  292         struct file filetmp;
  293         int error;
  294 
  295         if (ap->a_command == FIONBIO)
  296                 return (0);
  297         if (ap->a_fflag & FREAD) {
  298                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
  299                 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
  300                 if (error)
  301                         return (error);
  302         }
  303         if (ap->a_fflag & FWRITE) {
  304                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
  305                 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
  306                 if (error)
  307                         return (error);
  308         }
  309         return (0);
  310 }
  311 
  312 /* ARGSUSED */
  313 int
  314 fifo_poll(void *v)
  315 {
  316         struct vop_poll_args *ap = v;
  317         struct file filetmp;
  318         short ostate;
  319         int revents = 0;
  320 
  321         if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
  322                 /*
  323                  * Socket and FIFO poll(2) semantics differ wrt EOF on read.
  324                  * Unlike a normal socket, FIFOs don't care whether or not
  325                  * SS_CANTRCVMORE is set.  To get the correct semantics we
  326                  * must clear SS_CANTRCVMORE from so_state temporarily.
  327                  */
  328                 ostate = ap->a_vp->v_fifoinfo->fi_readsock->so_state;
  329                 if (ap->a_events & (POLLIN | POLLRDNORM))
  330                         ap->a_vp->v_fifoinfo->fi_readsock->so_state &=
  331                             ~SS_CANTRCVMORE;
  332                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock;
  333                 if (filetmp.f_data)
  334                         revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
  335                 ap->a_vp->v_fifoinfo->fi_readsock->so_state = ostate;
  336         }
  337         if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
  338                 filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock;
  339                 if (filetmp.f_data)
  340                         revents |= soo_poll(&filetmp, ap->a_events, ap->a_p);
  341         }
  342         return (revents);
  343 }
  344 
  345 int
  346 fifo_inactive(void *v)
  347 {
  348         struct vop_inactive_args *ap = v;
  349 
  350         VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
  351         return (0);
  352 }
  353 
  354 /*
  355  * This is a noop, simply returning what one has been given.
  356  */
  357 int
  358 fifo_bmap(void *v)
  359 {
  360         struct vop_bmap_args *ap = v;
  361 
  362         if (ap->a_vpp != NULL)
  363                 *ap->a_vpp = ap->a_vp;
  364         if (ap->a_bnp != NULL)
  365                 *ap->a_bnp = ap->a_bn;
  366         return (0);
  367 }
  368 
  369 /*
  370  * Device close routine
  371  */
  372 /* ARGSUSED */
  373 int
  374 fifo_close(void *v)
  375 {
  376         struct vop_close_args *ap = v;
  377         struct vnode *vp = ap->a_vp;
  378         struct fifoinfo *fip = vp->v_fifoinfo;
  379         int error1 = 0, error2 = 0;
  380 
  381         if (fip == NULL)
  382                 return (0);
  383 
  384         if (ap->a_fflag & FREAD) {
  385                 if (--fip->fi_readers == 0)
  386                         socantsendmore(fip->fi_writesock);
  387         }
  388         if (ap->a_fflag & FWRITE) {
  389                 if (--fip->fi_writers == 0)
  390                         socantrcvmore(fip->fi_readsock);
  391         }
  392         if (fip->fi_readers == 0 && fip->fi_writers == 0) {
  393                 error1 = soclose(fip->fi_readsock);
  394                 error2 = soclose(fip->fi_writesock);
  395                 FREE(fip, M_VNODE);
  396                 vp->v_fifoinfo = NULL;
  397         }
  398         return (error1 ? error1 : error2);
  399 }
  400 
  401 int
  402 fifo_reclaim(void *v)
  403 {
  404         struct vop_reclaim_args *ap = v;
  405         struct vnode *vp = ap->a_vp;
  406         struct fifoinfo *fip = vp->v_fifoinfo;
  407 
  408         if (fip == NULL)
  409                 return (0);
  410 
  411         soclose(fip->fi_readsock);
  412         soclose(fip->fi_writesock);
  413         FREE(fip, M_VNODE);
  414         vp->v_fifoinfo = NULL;
  415 
  416         return (0);
  417 }
  418 
  419 /*
  420  * Print out the contents of a fifo vnode.
  421  */
  422 int
  423 fifo_print(void *v)
  424 {
  425         struct vop_print_args *ap = v;
  426 
  427         printf("tag VT_NON");
  428         fifo_printinfo(ap->a_vp);
  429         printf("\n");
  430         return 0;
  431 }
  432 
  433 /*
  434  * Print out internal contents of a fifo vnode.
  435  */
  436 void
  437 fifo_printinfo(struct vnode *vp)
  438 {
  439         struct fifoinfo *fip = vp->v_fifoinfo;
  440 
  441         printf(", fifo with %ld readers and %ld writers",
  442                 fip->fi_readers, fip->fi_writers);
  443 }
  444 
  445 /*
  446  * Return POSIX pathconf information applicable to fifo's.
  447  */
  448 int
  449 fifo_pathconf(void *v)
  450 {
  451         struct vop_pathconf_args *ap = v;
  452 
  453         switch (ap->a_name) {
  454         case _PC_LINK_MAX:
  455                 *ap->a_retval = LINK_MAX;
  456                 return (0);
  457         case _PC_PIPE_BUF:
  458                 *ap->a_retval = PIPE_BUF;
  459                 return (0);
  460         case _PC_CHOWN_RESTRICTED:
  461                 *ap->a_retval = 1;
  462                 return (0);
  463         default:
  464                 return (EINVAL);
  465         }
  466         /* NOTREACHED */
  467 }
  468 
  469 /*
  470  * Fifo failed operation
  471  */
  472 /*ARGSUSED*/
  473 int
  474 fifo_ebadf(void *v)
  475 {
  476 
  477         return (EBADF);
  478 }
  479 
  480 /*
  481  * Fifo advisory byte-level locks.
  482  */
  483 /* ARGSUSED */
  484 int
  485 fifo_advlock(void *v)
  486 {
  487         return (EOPNOTSUPP);
  488 }
  489 
  490 /*
  491  * Fifo bad operation
  492  */
  493 /*ARGSUSED*/
  494 int
  495 fifo_badop(void *v)
  496 {
  497 
  498         panic("fifo_badop called");
  499         /* NOTREACHED */
  500         return(0);
  501 }
  502 
  503 
  504 int
  505 fifo_kqfilter(void *v)
  506 {
  507         struct vop_kqfilter_args *ap = v;
  508         struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
  509         struct sockbuf *sb;
  510 
  511         switch (ap->a_kn->kn_filter) {
  512         case EVFILT_READ:
  513                 ap->a_kn->kn_fop = &fiforead_filtops;
  514                 sb = &so->so_rcv;
  515                 break;
  516         case EVFILT_WRITE:
  517                 ap->a_kn->kn_fop = &fifowrite_filtops;
  518                 sb = &so->so_snd;
  519                 break;
  520         default:
  521                 return (1);
  522         }
  523 
  524         ap->a_kn->kn_hook = so;
  525 
  526         SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
  527         sb->sb_flags |= SB_KNOTE;
  528 
  529         return (0);
  530 }
  531 
  532 void
  533 filt_fifordetach(struct knote *kn)
  534 {
  535         struct socket *so = (struct socket *)kn->kn_hook;
  536 
  537         SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
  538         if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
  539                 so->so_rcv.sb_flags &= ~SB_KNOTE;
  540 }
  541 
  542 int
  543 filt_fiforead(struct knote *kn, long hint)
  544 {
  545         struct socket *so = (struct socket *)kn->kn_hook;
  546 
  547         kn->kn_data = so->so_rcv.sb_cc;
  548         if (so->so_state & SS_CANTRCVMORE) {
  549                 kn->kn_flags |= EV_EOF;
  550                 return (1);
  551         }
  552         kn->kn_flags &= ~EV_EOF;
  553         return (kn->kn_data > 0);
  554 }
  555 
  556 void
  557 filt_fifowdetach(struct knote *kn)
  558 {
  559         struct socket *so = (struct socket *)kn->kn_hook;
  560 
  561         SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
  562         if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
  563                 so->so_snd.sb_flags &= ~SB_KNOTE;
  564 }
  565 
  566 int
  567 filt_fifowrite(struct knote *kn, long hint)
  568 {
  569         struct socket *so = (struct socket *)kn->kn_hook;
  570 
  571         kn->kn_data = sbspace(&so->so_snd);
  572         if (so->so_state & SS_CANTSENDMORE) {
  573                 kn->kn_flags |= EV_EOF;
  574                 return (1);
  575         }
  576         kn->kn_flags &= ~EV_EOF;
  577         return (kn->kn_data >= so->so_snd.sb_lowat);
  578 }

/* [<][>][^][v][top][bottom][index][help] */