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

Cache object: 4b4297abb28d02dccde124842c54f910


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