xref: /csrg-svn/sys/miscfs/fifofs/fifo_vnops.c (revision 53537)
140292Smckusick /*
240292Smckusick  * Copyright (c) 1990 The Regents of the University of California.
340292Smckusick  * All rights reserved.
440292Smckusick  *
544430Sbostic  * %sccs.include.redist.c%
640292Smckusick  *
7*53537Sheideman  *	@(#)fifo_vnops.c	7.13 (Berkeley) 05/14/92
840292Smckusick  */
940292Smckusick 
1040292Smckusick #include "param.h"
1152512Smckusick #include "proc.h"
1240292Smckusick #include "time.h"
1340292Smckusick #include "namei.h"
1440292Smckusick #include "vnode.h"
1540292Smckusick #include "socket.h"
1640292Smckusick #include "socketvar.h"
1740292Smckusick #include "stat.h"
1847540Skarels #include "systm.h"
1940292Smckusick #include "ioctl.h"
2040292Smckusick #include "file.h"
2148014Smckusick #include "fifo.h"
2240292Smckusick #include "errno.h"
2340292Smckusick #include "malloc.h"
2440292Smckusick 
2540292Smckusick /*
2640292Smckusick  * This structure is associated with the FIFO vnode and stores
2740292Smckusick  * the state associated with the FIFO.
2840292Smckusick  */
2940292Smckusick struct fifoinfo {
3040292Smckusick 	struct socket	*fi_readsock;
3140292Smckusick 	struct socket	*fi_writesock;
3240292Smckusick 	long		fi_readers;
3340292Smckusick 	long		fi_writers;
3440292Smckusick };
3540292Smckusick 
36*53537Sheideman int (**fifo_vnodeop_p)();
37*53537Sheideman struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
38*53537Sheideman 	{ &vop_default_desc, vn_default_error },
39*53537Sheideman 	{ &vop_lookup_desc, fifo_lookup },		/* lookup */
40*53537Sheideman 	{ &vop_create_desc, fifo_create },		/* create */
41*53537Sheideman 	{ &vop_mknod_desc, fifo_mknod },		/* mknod */
42*53537Sheideman 	{ &vop_open_desc, fifo_open },		/* open */
43*53537Sheideman 	{ &vop_close_desc, fifo_close },		/* close */
44*53537Sheideman 	{ &vop_access_desc, fifo_access },		/* access */
45*53537Sheideman 	{ &vop_getattr_desc, fifo_getattr },		/* getattr */
46*53537Sheideman 	{ &vop_setattr_desc, fifo_setattr },		/* setattr */
47*53537Sheideman 	{ &vop_read_desc, fifo_read },		/* read */
48*53537Sheideman 	{ &vop_write_desc, fifo_write },		/* write */
49*53537Sheideman 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
50*53537Sheideman 	{ &vop_select_desc, fifo_select },		/* select */
51*53537Sheideman 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
52*53537Sheideman 	{ &vop_fsync_desc, fifo_fsync },		/* fsync */
53*53537Sheideman 	{ &vop_seek_desc, fifo_seek },		/* seek */
54*53537Sheideman 	{ &vop_remove_desc, fifo_remove },		/* remove */
55*53537Sheideman 	{ &vop_link_desc, fifo_link },		/* link */
56*53537Sheideman 	{ &vop_rename_desc, fifo_rename },		/* rename */
57*53537Sheideman 	{ &vop_mkdir_desc, fifo_mkdir },		/* mkdir */
58*53537Sheideman 	{ &vop_rmdir_desc, fifo_rmdir },		/* rmdir */
59*53537Sheideman 	{ &vop_symlink_desc, fifo_symlink },		/* symlink */
60*53537Sheideman 	{ &vop_readdir_desc, fifo_readdir },		/* readdir */
61*53537Sheideman 	{ &vop_readlink_desc, fifo_readlink },		/* readlink */
62*53537Sheideman 	{ &vop_abortop_desc, fifo_abortop },		/* abortop */
63*53537Sheideman 	{ &vop_inactive_desc, fifo_inactive },		/* inactive */
64*53537Sheideman 	{ &vop_reclaim_desc, fifo_reclaim },		/* reclaim */
65*53537Sheideman 	{ &vop_lock_desc, fifo_lock },		/* lock */
66*53537Sheideman 	{ &vop_unlock_desc, fifo_unlock },		/* unlock */
67*53537Sheideman 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
68*53537Sheideman 	{ &vop_strategy_desc, fifo_strategy },		/* strategy */
69*53537Sheideman 	{ &vop_print_desc, fifo_print },		/* print */
70*53537Sheideman 	{ &vop_islocked_desc, fifo_islocked },		/* islocked */
71*53537Sheideman 	{ &vop_advlock_desc, fifo_advlock },		/* advlock */
72*53537Sheideman 	{ &vop_blkatoff_desc, fifo_blkatoff },		/* blkatoff */
73*53537Sheideman 	{ &vop_vget_desc, fifo_vget },		/* vget */
74*53537Sheideman 	{ &vop_valloc_desc, fifo_valloc },		/* valloc */
75*53537Sheideman 	{ &vop_vfree_desc, fifo_vfree },		/* vfree */
76*53537Sheideman 	{ &vop_truncate_desc, fifo_truncate },		/* truncate */
77*53537Sheideman 	{ &vop_update_desc, fifo_update },		/* update */
78*53537Sheideman 	{ &vop_bwrite_desc, fifo_bwrite },		/* bwrite */
79*53537Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
8040292Smckusick };
81*53537Sheideman struct vnodeopv_desc fifo_vnodeop_opv_desc =
82*53537Sheideman 	{ &fifo_vnodeop_p, fifo_vnodeop_entries };
8340292Smckusick 
8440292Smckusick /*
8540292Smckusick  * Trivial lookup routine that always fails.
8640292Smckusick  */
8748014Smckusick /* ARGSUSED */
88*53537Sheideman fifo_lookup (ap)
89*53537Sheideman 	struct vop_lookup_args *ap;
90*53537Sheideman #define dvp (ap->a_dvp)
91*53537Sheideman #define vpp (ap->a_vpp)
92*53537Sheideman #define cnp (ap->a_cnp)
9340292Smckusick {
9452305Sheideman 
9552305Sheideman 	*vpp = NULL;
9640292Smckusick 	return (ENOTDIR);
9740292Smckusick }
98*53537Sheideman #undef dvp
99*53537Sheideman #undef vpp
100*53537Sheideman #undef cnp
10140292Smckusick 
10240292Smckusick /*
10340292Smckusick  * Open called to set up a new instance of a fifo or
10440292Smckusick  * to find an active instance of a fifo.
10540292Smckusick  */
10640292Smckusick /* ARGSUSED */
107*53537Sheideman fifo_open (ap)
108*53537Sheideman 	struct vop_open_args *ap;
109*53537Sheideman #define vp (ap->a_vp)
110*53537Sheideman #define mode (ap->a_mode)
111*53537Sheideman #define cred (ap->a_cred)
112*53537Sheideman #define p (ap->a_p)
11340292Smckusick {
114*53537Sheideman 	USES_VOP_CLOSE;
115*53537Sheideman 	USES_VOP_LOCK;
116*53537Sheideman 	USES_VOP_UNLOCK;
11740292Smckusick 	register struct fifoinfo *fip;
11840292Smckusick 	struct socket *rso, *wso;
11940292Smckusick 	int error;
12040637Skarels 	static char openstr[] = "fifo";
12140292Smckusick 
12240292Smckusick 	if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
12340292Smckusick 		return (EINVAL);
12440292Smckusick 	if ((fip = vp->v_fifoinfo) == NULL) {
12540292Smckusick 		MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
12640292Smckusick 		vp->v_fifoinfo = fip;
12740655Smckusick 		if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
12840655Smckusick 			free(fip, M_VNODE);
12940655Smckusick 			vp->v_fifoinfo = NULL;
13040292Smckusick 			return (error);
13140655Smckusick 		}
13240292Smckusick 		fip->fi_readsock = rso;
13340292Smckusick 		if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
13440292Smckusick 			(void)soclose(rso);
13540655Smckusick 			free(fip, M_VNODE);
13640655Smckusick 			vp->v_fifoinfo = NULL;
13740292Smckusick 			return (error);
13840292Smckusick 		}
13940292Smckusick 		fip->fi_writesock = wso;
14040292Smckusick 		if (error = unp_connect2(wso, rso)) {
14140292Smckusick 			(void)soclose(wso);
14240292Smckusick 			(void)soclose(rso);
14340655Smckusick 			free(fip, M_VNODE);
14440655Smckusick 			vp->v_fifoinfo = NULL;
14540292Smckusick 			return (error);
14640292Smckusick 		}
14753147Smckusick 		fip->fi_readers = fip->fi_writers = 0;
14840292Smckusick 		wso->so_state |= SS_CANTRCVMORE;
14940292Smckusick 		rso->so_state |= SS_CANTSENDMORE;
15040292Smckusick 	}
15140292Smckusick 	error = 0;
15240292Smckusick 	if (mode & FREAD) {
15340292Smckusick 		fip->fi_readers++;
15440292Smckusick 		if (fip->fi_readers == 1) {
15540292Smckusick 			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
15640292Smckusick 			if (fip->fi_writers > 0)
15740292Smckusick 				wakeup((caddr_t)&fip->fi_writers);
15840292Smckusick 		}
15940292Smckusick 		if (mode & O_NONBLOCK)
16040292Smckusick 			return (0);
16153147Smckusick 		while (fip->fi_writers == 0) {
16253147Smckusick 			VOP_UNLOCK(vp);
16353147Smckusick 			error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
16453147Smckusick 				openstr, 0);
16553147Smckusick 			VOP_LOCK(vp);
16653147Smckusick 			if (error)
16740292Smckusick 				break;
16853147Smckusick 		}
16940292Smckusick 	} else {
17040292Smckusick 		fip->fi_writers++;
17140292Smckusick 		if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
17240292Smckusick 			error = ENXIO;
17340292Smckusick 		} else {
17440292Smckusick 			if (fip->fi_writers == 1) {
17540292Smckusick 				fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
17640292Smckusick 				if (fip->fi_readers > 0)
17740292Smckusick 					wakeup((caddr_t)&fip->fi_readers);
17840292Smckusick 			}
17953147Smckusick 			while (fip->fi_readers == 0) {
18053147Smckusick 				VOP_UNLOCK(vp);
18153147Smckusick 				error = tsleep((caddr_t)&fip->fi_writers,
18253147Smckusick 					PSOCK, openstr, 0);
18353147Smckusick 				VOP_LOCK(vp);
18453147Smckusick 				if (error)
18540292Smckusick 					break;
18653147Smckusick 			}
18740292Smckusick 		}
18840292Smckusick 	}
18940292Smckusick 	if (error)
190*53537Sheideman 		VOP_CLOSE(vp, mode, cred, p);
19140292Smckusick 	return (error);
19240292Smckusick }
193*53537Sheideman #undef vp
194*53537Sheideman #undef mode
195*53537Sheideman #undef cred
196*53537Sheideman #undef p
19740292Smckusick 
19840292Smckusick /*
19940292Smckusick  * Vnode op for read
20040292Smckusick  */
20140292Smckusick /* ARGSUSED */
202*53537Sheideman fifo_read (ap)
203*53537Sheideman 	struct vop_read_args *ap;
204*53537Sheideman #define vp (ap->a_vp)
205*53537Sheideman #define uio (ap->a_uio)
206*53537Sheideman #define ioflag (ap->a_ioflag)
207*53537Sheideman #define cred (ap->a_cred)
20840292Smckusick {
209*53537Sheideman 	USES_VOP_LOCK;
210*53537Sheideman 	USES_VOP_UNLOCK;
21140292Smckusick 	register struct socket *rso = vp->v_fifoinfo->fi_readsock;
21240292Smckusick 	int error, startresid;
21340292Smckusick 
21448014Smckusick #ifdef DIAGNOSTIC
21540292Smckusick 	if (uio->uio_rw != UIO_READ)
21640292Smckusick 		panic("fifo_read mode");
21748014Smckusick #endif
21840292Smckusick 	if (uio->uio_resid == 0)
21940292Smckusick 		return (0);
22040292Smckusick 	if (ioflag & IO_NDELAY)
22140292Smckusick 		rso->so_state |= SS_NBIO;
22240292Smckusick 	startresid = uio->uio_resid;
22340292Smckusick 	VOP_UNLOCK(vp);
22440292Smckusick 	error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
22540292Smckusick 		(struct mbuf **)0, (struct mbuf **)0);
22640292Smckusick 	VOP_LOCK(vp);
22740292Smckusick 	/*
22840292Smckusick 	 * Clear EOF indication after first such return.
22940292Smckusick 	 */
23040292Smckusick 	if (uio->uio_resid == startresid)
23140292Smckusick 		rso->so_state &= ~SS_CANTRCVMORE;
23240292Smckusick 	if (ioflag & IO_NDELAY)
23340292Smckusick 		rso->so_state &= ~SS_NBIO;
23440292Smckusick 	return (error);
23540292Smckusick }
236*53537Sheideman #undef vp
237*53537Sheideman #undef uio
238*53537Sheideman #undef ioflag
239*53537Sheideman #undef cred
24040292Smckusick 
24140292Smckusick /*
24240292Smckusick  * Vnode op for write
24340292Smckusick  */
24440292Smckusick /* ARGSUSED */
245*53537Sheideman fifo_write (ap)
246*53537Sheideman 	struct vop_write_args *ap;
247*53537Sheideman #define vp (ap->a_vp)
248*53537Sheideman #define uio (ap->a_uio)
249*53537Sheideman #define ioflag (ap->a_ioflag)
250*53537Sheideman #define cred (ap->a_cred)
25140292Smckusick {
252*53537Sheideman 	USES_VOP_LOCK;
253*53537Sheideman 	USES_VOP_UNLOCK;
25440292Smckusick 	struct socket *wso = vp->v_fifoinfo->fi_writesock;
25540292Smckusick 	int error;
25640292Smckusick 
25748014Smckusick #ifdef DIAGNOSTIC
25840292Smckusick 	if (uio->uio_rw != UIO_WRITE)
25940292Smckusick 		panic("fifo_write mode");
26048014Smckusick #endif
26140292Smckusick 	if (ioflag & IO_NDELAY)
26240292Smckusick 		wso->so_state |= SS_NBIO;
26340292Smckusick 	VOP_UNLOCK(vp);
26453423Smckusick 	error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0, 0);
26540292Smckusick 	VOP_LOCK(vp);
26640292Smckusick 	if (ioflag & IO_NDELAY)
26740292Smckusick 		wso->so_state &= ~SS_NBIO;
26840292Smckusick 	return (error);
26940292Smckusick }
270*53537Sheideman #undef vp
271*53537Sheideman #undef uio
272*53537Sheideman #undef ioflag
273*53537Sheideman #undef cred
27440292Smckusick 
27540292Smckusick /*
27640292Smckusick  * Device ioctl operation.
27740292Smckusick  */
27840292Smckusick /* ARGSUSED */
279*53537Sheideman fifo_ioctl (ap)
280*53537Sheideman 	struct vop_ioctl_args *ap;
281*53537Sheideman #define vp (ap->a_vp)
282*53537Sheideman #define com (ap->a_command)
283*53537Sheideman #define data (ap->a_data)
284*53537Sheideman #define fflag (ap->a_fflag)
285*53537Sheideman #define cred (ap->a_cred)
286*53537Sheideman #define p (ap->a_p)
28740292Smckusick {
28840292Smckusick 	struct file filetmp;
28940292Smckusick 	int error;
29040292Smckusick 
29140292Smckusick 	if (com == FIONBIO)
29240292Smckusick 		return (0);
29340292Smckusick 	if (fflag & FREAD)
29440292Smckusick 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
29540292Smckusick 	else
29640292Smckusick 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
29748014Smckusick 	return (soo_ioctl(&filetmp, com, data, p));
29840292Smckusick }
299*53537Sheideman #undef vp
300*53537Sheideman #undef com
301*53537Sheideman #undef data
302*53537Sheideman #undef fflag
303*53537Sheideman #undef cred
304*53537Sheideman #undef p
30540292Smckusick 
30640292Smckusick /* ARGSUSED */
307*53537Sheideman fifo_select (ap)
308*53537Sheideman 	struct vop_select_args *ap;
309*53537Sheideman #define vp (ap->a_vp)
310*53537Sheideman #define which (ap->a_which)
311*53537Sheideman #define fflag (ap->a_fflags)
312*53537Sheideman #define cred (ap->a_cred)
313*53537Sheideman #define p (ap->a_p)
31440292Smckusick {
31540292Smckusick 	struct file filetmp;
31640292Smckusick 	int error;
31740292Smckusick 
31840292Smckusick 	if (fflag & FREAD)
31940292Smckusick 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
32040292Smckusick 	else
32140292Smckusick 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
32248014Smckusick 	return (soo_select(&filetmp, which, p));
32340292Smckusick }
324*53537Sheideman #undef vp
325*53537Sheideman #undef which
326*53537Sheideman #undef fflag
327*53537Sheideman #undef cred
328*53537Sheideman #undef p
32940292Smckusick 
33040292Smckusick /*
33140292Smckusick  * This is a noop, simply returning what one has been given.
33240292Smckusick  */
333*53537Sheideman fifo_bmap (ap)
334*53537Sheideman 	struct vop_bmap_args *ap;
335*53537Sheideman #define vp (ap->a_vp)
336*53537Sheideman #define bn (ap->a_bn)
337*53537Sheideman #define vpp (ap->a_vpp)
338*53537Sheideman #define bnp (ap->a_bnp)
33940292Smckusick {
34040292Smckusick 
34140292Smckusick 	if (vpp != NULL)
34240292Smckusick 		*vpp = vp;
34340292Smckusick 	if (bnp != NULL)
34440292Smckusick 		*bnp = bn;
34540292Smckusick 	return (0);
34640292Smckusick }
347*53537Sheideman #undef vp
348*53537Sheideman #undef bn
349*53537Sheideman #undef vpp
350*53537Sheideman #undef bnp
35140292Smckusick 
35240292Smckusick /*
35340292Smckusick  * At the moment we do not do any locking.
35440292Smckusick  */
35540292Smckusick /* ARGSUSED */
356*53537Sheideman fifo_lock (ap)
357*53537Sheideman 	struct vop_lock_args *ap;
358*53537Sheideman #define vp (ap->a_vp)
35940292Smckusick {
36040292Smckusick 
36140292Smckusick 	return (0);
36240292Smckusick }
363*53537Sheideman #undef vp
36440292Smckusick 
36540292Smckusick /* ARGSUSED */
366*53537Sheideman fifo_unlock (ap)
367*53537Sheideman 	struct vop_unlock_args *ap;
368*53537Sheideman #define vp (ap->a_vp)
36940292Smckusick {
37040292Smckusick 
37140292Smckusick 	return (0);
37240292Smckusick }
373*53537Sheideman #undef vp
37440292Smckusick 
37540292Smckusick /*
37640292Smckusick  * Device close routine
37740292Smckusick  */
37840292Smckusick /* ARGSUSED */
379*53537Sheideman fifo_close (ap)
380*53537Sheideman 	struct vop_close_args *ap;
381*53537Sheideman #define vp (ap->a_vp)
382*53537Sheideman #define fflag (ap->a_fflag)
383*53537Sheideman #define cred (ap->a_cred)
384*53537Sheideman #define p (ap->a_p)
38540292Smckusick {
38640292Smckusick 	register struct fifoinfo *fip = vp->v_fifoinfo;
38740292Smckusick 	int error1, error2;
38840292Smckusick 
38940292Smckusick 	if (fflag & FWRITE) {
39040292Smckusick 		fip->fi_writers--;
39140292Smckusick 		if (fip->fi_writers == 0)
39240292Smckusick 			socantrcvmore(fip->fi_readsock);
39340292Smckusick 	} else {
39440292Smckusick 		fip->fi_readers--;
39540292Smckusick 		if (fip->fi_readers == 0)
39640292Smckusick 			socantsendmore(fip->fi_writesock);
39740292Smckusick 	}
39840292Smckusick 	if (vp->v_usecount > 1)
39940292Smckusick 		return (0);
40040292Smckusick 	error1 = soclose(fip->fi_readsock);
40140292Smckusick 	error2 = soclose(fip->fi_writesock);
40240292Smckusick 	FREE(fip, M_VNODE);
40340292Smckusick 	vp->v_fifoinfo = NULL;
40440292Smckusick 	if (error1)
40540292Smckusick 		return (error1);
40640292Smckusick 	return (error2);
40740292Smckusick }
408*53537Sheideman #undef vp
409*53537Sheideman #undef fflag
410*53537Sheideman #undef cred
411*53537Sheideman #undef p
41240292Smckusick 
41340292Smckusick /*
41440292Smckusick  * Print out the contents of a fifo vnode.
41540292Smckusick  */
416*53537Sheideman fifo_print (ap)
417*53537Sheideman 	struct vop_print_args *ap;
418*53537Sheideman #define vp (ap->a_vp)
41940292Smckusick {
42040292Smckusick 
42140292Smckusick 	printf("tag VT_NON");
42240292Smckusick 	fifo_printinfo(vp);
42340292Smckusick 	printf("\n");
42440292Smckusick }
425*53537Sheideman #undef vp
42640292Smckusick 
42740292Smckusick /*
42840292Smckusick  * Print out internal contents of a fifo vnode.
42940292Smckusick  */
43040292Smckusick fifo_printinfo(vp)
43140292Smckusick 	struct vnode *vp;
43240292Smckusick {
43340292Smckusick 	register struct fifoinfo *fip = vp->v_fifoinfo;
43440292Smckusick 
43540292Smckusick 	printf(", fifo with %d readers and %d writers",
43640292Smckusick 		fip->fi_readers, fip->fi_writers);
43740292Smckusick }
43840292Smckusick 
43940292Smckusick /*
44040292Smckusick  * Fifo failed operation
44140292Smckusick  */
44240292Smckusick fifo_ebadf()
44340292Smckusick {
44440292Smckusick 
44540292Smckusick 	return (EBADF);
44640292Smckusick }
44740292Smckusick 
44840292Smckusick /*
44946198Smckusick  * Fifo advisory byte-level locks.
45046198Smckusick  */
45148014Smckusick /* ARGSUSED */
452*53537Sheideman fifo_advlock (ap)
453*53537Sheideman 	struct vop_advlock_args *ap;
454*53537Sheideman #define vp (ap->a_vp)
455*53537Sheideman #define id (ap->a_id)
456*53537Sheideman #define op (ap->a_op)
457*53537Sheideman #define fl (ap->a_fl)
458*53537Sheideman #define flags (ap->a_flags)
45946198Smckusick {
46046198Smckusick 
46146198Smckusick 	return (EOPNOTSUPP);
46246198Smckusick }
463*53537Sheideman #undef vp
464*53537Sheideman #undef id
465*53537Sheideman #undef op
466*53537Sheideman #undef fl
467*53537Sheideman #undef flags
46846198Smckusick 
46946198Smckusick /*
47040292Smckusick  * Fifo bad operation
47140292Smckusick  */
47240292Smckusick fifo_badop()
47340292Smckusick {
47440292Smckusick 
47540292Smckusick 	panic("fifo_badop called");
47640292Smckusick 	/* NOTREACHED */
47740292Smckusick }
478