Home | History | Annotate | Line # | Download | only in fifofs
fifo_vnops.c revision 1.3
      1 /*
      2  * Copyright (c) 1990 The Regents of the University of California.
      3  * 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  *	from: @(#)fifo_vnops.c	7.7 (Berkeley) 4/15/91
     34  *	$Id: fifo_vnops.c,v 1.3 1993/05/20 02:54:13 cgd Exp $
     35  */
     36 
     37 #include "param.h"
     38 #include "time.h"
     39 #include "namei.h"
     40 #include "vnode.h"
     41 #include "socket.h"
     42 #include "socketvar.h"
     43 #include "stat.h"
     44 #include "systm.h"
     45 #include "ioctl.h"
     46 #include "file.h"
     47 #include "fifo.h"
     48 #include "errno.h"
     49 #include "malloc.h"
     50 
     51 /*
     52  * This structure is associated with the FIFO vnode and stores
     53  * the state associated with the FIFO.
     54  */
     55 struct fifoinfo {
     56 	struct socket	*fi_readsock;
     57 	struct socket	*fi_writesock;
     58 	long		fi_readers;
     59 	long		fi_writers;
     60 };
     61 
     62 struct vnodeops fifo_vnodeops = {
     63 	fifo_lookup,		/* lookup */
     64 	fifo_create,		/* create */
     65 	fifo_mknod,		/* mknod */
     66 	fifo_open,		/* open */
     67 	fifo_close,		/* close */
     68 	fifo_access,		/* access */
     69 	fifo_getattr,		/* getattr */
     70 	fifo_setattr,		/* setattr */
     71 	fifo_read,		/* read */
     72 	fifo_write,		/* write */
     73 	fifo_ioctl,		/* ioctl */
     74 	fifo_select,		/* select */
     75 	fifo_mmap,		/* mmap */
     76 	fifo_fsync,		/* fsync */
     77 	fifo_seek,		/* seek */
     78 	fifo_remove,		/* remove */
     79 	fifo_link,		/* link */
     80 	fifo_rename,		/* rename */
     81 	fifo_mkdir,		/* mkdir */
     82 	fifo_rmdir,		/* rmdir */
     83 	fifo_symlink,		/* symlink */
     84 	fifo_readdir,		/* readdir */
     85 	fifo_readlink,		/* readlink */
     86 	fifo_abortop,		/* abortop */
     87 	fifo_inactive,		/* inactive */
     88 	fifo_reclaim,		/* reclaim */
     89 	fifo_lock,		/* lock */
     90 	fifo_unlock,		/* unlock */
     91 	fifo_bmap,		/* bmap */
     92 	fifo_strategy,		/* strategy */
     93 	fifo_print,		/* print */
     94 	fifo_islocked,		/* islocked */
     95 	fifo_advlock,		/* advlock */
     96 };
     97 
     98 /*
     99  * Trivial lookup routine that always fails.
    100  */
    101 /* ARGSUSED */
    102 fifo_lookup(vp, ndp, p)
    103 	struct vnode *vp;
    104 	struct nameidata *ndp;
    105 	struct proc *p;
    106 {
    107 
    108 	ndp->ni_dvp = vp;
    109 	ndp->ni_vp = NULL;
    110 	return (ENOTDIR);
    111 }
    112 
    113 /*
    114  * Open called to set up a new instance of a fifo or
    115  * to find an active instance of a fifo.
    116  */
    117 /* ARGSUSED */
    118 fifo_open(vp, mode, cred, p)
    119 	register struct vnode *vp;
    120 	int mode;
    121 	struct ucred *cred;
    122 	struct proc *p;
    123 {
    124 	register struct fifoinfo *fip;
    125 	struct socket *rso, *wso;
    126 	int error;
    127 	static char openstr[] = "fifo";
    128 
    129 	if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
    130 		return (EINVAL);
    131 	if ((fip = vp->v_fifoinfo) == NULL) {
    132 		MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
    133 		vp->v_fifoinfo = fip;
    134 		fip->fi_readers=0;
    135 		fip->fi_writers=0;
    136 		if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
    137 			free(fip, M_VNODE);
    138 			vp->v_fifoinfo = NULL;
    139 			return (error);
    140 		}
    141 		fip->fi_readsock = rso;
    142 		if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
    143 			(void)soclose(rso);
    144 			free(fip, M_VNODE);
    145 			vp->v_fifoinfo = NULL;
    146 			return (error);
    147 		}
    148 		fip->fi_writesock = wso;
    149 		if (error = unp_connect2(wso, rso)) {
    150 			(void)soclose(wso);
    151 			(void)soclose(rso);
    152 			free(fip, M_VNODE);
    153 			vp->v_fifoinfo = NULL;
    154 			return (error);
    155 		}
    156 		wso->so_state |= SS_CANTRCVMORE;
    157 		rso->so_state |= SS_CANTSENDMORE;
    158 	}
    159 	error = 0;
    160 	if (mode & FREAD) {
    161 		fip->fi_readers++;
    162 		if (fip->fi_readers == 1) {
    163 			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
    164 			if (fip->fi_writers > 0)
    165 				wakeup((caddr_t)&fip->fi_writers);
    166 		}
    167 		if (mode & O_NONBLOCK)
    168 			return (0);
    169 		while (fip->fi_writers == 0) {
    170 			VOP_UNLOCK(vp);
    171 			error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
    172 			    openstr, 0);
    173 			VOP_LOCK(vp);
    174 			if(error)
    175 				break;
    176 		}
    177 	} else {
    178 		fip->fi_writers++;
    179 		if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
    180 			error = ENXIO;
    181 		} else {
    182 			if (fip->fi_writers == 1) {
    183 				fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
    184 				if (fip->fi_readers > 0)
    185 					wakeup((caddr_t)&fip->fi_readers);
    186 			}
    187 			while (fip->fi_readers == 0) {
    188 				VOP_UNLOCK(vp);
    189 				error = tsleep((caddr_t)&fip->fi_writers,
    190 				    PSOCK, openstr, 0);
    191 				VOP_LOCK(vp);
    192 				if(error)
    193 					break;
    194 			}
    195 		}
    196 	}
    197 	if (error)
    198 		fifo_close(vp, mode, cred, p);
    199 	return (error);
    200 }
    201 
    202 /*
    203  * Vnode op for read
    204  */
    205 /* ARGSUSED */
    206 fifo_read(vp, uio, ioflag, cred)
    207 	struct vnode *vp;
    208 	register struct uio *uio;
    209 	int ioflag;
    210 	struct ucred *cred;
    211 {
    212 	register struct socket *rso = vp->v_fifoinfo->fi_readsock;
    213 	int error, startresid;
    214 
    215 #ifdef DIAGNOSTIC
    216 	if (uio->uio_rw != UIO_READ)
    217 		panic("fifo_read mode");
    218 #endif
    219 	if (uio->uio_resid == 0)
    220 		return (0);
    221 	if (ioflag & IO_NDELAY)
    222 		rso->so_state |= SS_NBIO;
    223 	startresid = uio->uio_resid;
    224 	VOP_UNLOCK(vp);
    225 	error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
    226 		(struct mbuf **)0, (struct mbuf **)0);
    227 	VOP_LOCK(vp);
    228 	/*
    229 	 * Clear EOF indication after first such return.
    230 	 */
    231 	if (uio->uio_resid == startresid)
    232 		rso->so_state &= ~SS_CANTRCVMORE;
    233 	if (ioflag & IO_NDELAY)
    234 		rso->so_state &= ~SS_NBIO;
    235 	return (error);
    236 }
    237 
    238 /*
    239  * Vnode op for write
    240  */
    241 /* ARGSUSED */
    242 fifo_write(vp, uio, ioflag, cred)
    243 	struct vnode *vp;
    244 	register struct uio *uio;
    245 	int ioflag;
    246 	struct ucred *cred;
    247 {
    248 	struct socket *wso = vp->v_fifoinfo->fi_writesock;
    249 	int error;
    250 
    251 #ifdef DIAGNOSTIC
    252 	if (uio->uio_rw != UIO_WRITE)
    253 		panic("fifo_write mode");
    254 #endif
    255 	if (ioflag & IO_NDELAY)
    256 		wso->so_state |= SS_NBIO;
    257 	VOP_UNLOCK(vp);
    258 	error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0);
    259 	VOP_LOCK(vp);
    260 	if (ioflag & IO_NDELAY)
    261 		wso->so_state &= ~SS_NBIO;
    262 	return (error);
    263 }
    264 
    265 /*
    266  * Device ioctl operation.
    267  */
    268 /* ARGSUSED */
    269 fifo_ioctl(vp, com, data, fflag, cred, p)
    270 	struct vnode *vp;
    271 	int com;
    272 	caddr_t data;
    273 	int fflag;
    274 	struct ucred *cred;
    275 	struct proc *p;
    276 {
    277 	struct file filetmp;
    278 	int error;
    279 
    280 	if (com == FIONBIO)
    281 		return (0);
    282 	if (fflag & FREAD)
    283 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
    284 	else
    285 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
    286 	return (soo_ioctl(&filetmp, com, data, p));
    287 }
    288 
    289 /* ARGSUSED */
    290 fifo_select(vp, which, fflag, cred, p)
    291 	struct vnode *vp;
    292 	int which, fflag;
    293 	struct ucred *cred;
    294 	struct proc *p;
    295 {
    296 	struct file filetmp;
    297 	int error;
    298 
    299 	if (fflag & FREAD)
    300 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
    301 	else
    302 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
    303 	return (soo_select(&filetmp, which, p));
    304 }
    305 
    306 /*
    307  * This is a noop, simply returning what one has been given.
    308  */
    309 fifo_bmap(vp, bn, vpp, bnp)
    310 	struct vnode *vp;
    311 	daddr_t bn;
    312 	struct vnode **vpp;
    313 	daddr_t *bnp;
    314 {
    315 
    316 	if (vpp != NULL)
    317 		*vpp = vp;
    318 	if (bnp != NULL)
    319 		*bnp = bn;
    320 	return (0);
    321 }
    322 
    323 /*
    324  * At the moment we do not do any locking.
    325  */
    326 /* ARGSUSED */
    327 fifo_lock(vp)
    328 	struct vnode *vp;
    329 {
    330 
    331 	return (0);
    332 }
    333 
    334 /* ARGSUSED */
    335 fifo_unlock(vp)
    336 	struct vnode *vp;
    337 {
    338 
    339 	return (0);
    340 }
    341 
    342 /*
    343  * Device close routine
    344  */
    345 /* ARGSUSED */
    346 fifo_close(vp, fflag, cred, p)
    347 	register struct vnode *vp;
    348 	int fflag;
    349 	struct ucred *cred;
    350 	struct proc *p;
    351 {
    352 	register struct fifoinfo *fip = vp->v_fifoinfo;
    353 	int error1, error2;
    354 
    355 	if (fflag & FWRITE) {
    356 		fip->fi_writers--;
    357 		if (fip->fi_writers == 0)
    358 			socantrcvmore(fip->fi_readsock);
    359 	} else {
    360 		fip->fi_readers--;
    361 		if (fip->fi_readers == 0)
    362 			socantsendmore(fip->fi_writesock);
    363 	}
    364 	if (vp->v_usecount > 1)
    365 		return (0);
    366 	error1 = soclose(fip->fi_readsock);
    367 	error2 = soclose(fip->fi_writesock);
    368 	FREE(fip, M_VNODE);
    369 	vp->v_fifoinfo = NULL;
    370 	if (error1)
    371 		return (error1);
    372 	return (error2);
    373 }
    374 
    375 /*
    376  * Print out the contents of a fifo vnode.
    377  */
    378 fifo_print(vp)
    379 	struct vnode *vp;
    380 {
    381 
    382 	printf("tag VT_NON");
    383 	fifo_printinfo(vp);
    384 	printf("\n");
    385 }
    386 
    387 /*
    388  * Print out internal contents of a fifo vnode.
    389  */
    390 fifo_printinfo(vp)
    391 	struct vnode *vp;
    392 {
    393 	register struct fifoinfo *fip = vp->v_fifoinfo;
    394 
    395 	printf(", fifo with %d readers and %d writers",
    396 		fip->fi_readers, fip->fi_writers);
    397 }
    398 
    399 /*
    400  * Fifo failed operation
    401  */
    402 fifo_ebadf()
    403 {
    404 
    405 	return (EBADF);
    406 }
    407 
    408 /*
    409  * Fifo advisory byte-level locks.
    410  */
    411 /* ARGSUSED */
    412 fifo_advlock(vp, id, op, fl, flags)
    413 	struct vnode *vp;
    414 	caddr_t id;
    415 	int op;
    416 	struct flock *fl;
    417 	int flags;
    418 {
    419 
    420 	return (EOPNOTSUPP);
    421 }
    422 
    423 /*
    424  * Fifo bad operation
    425  */
    426 fifo_badop()
    427 {
    428 
    429 	panic("fifo_badop called");
    430 	/* NOTREACHED */
    431 }
    432