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