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