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