xref: /csrg-svn/sys/miscfs/fifofs/fifo_vnops.c (revision 53537)
1 /*
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)fifo_vnops.c	7.13 (Berkeley) 05/14/92
8  */
9 
10 #include "param.h"
11 #include "proc.h"
12 #include "time.h"
13 #include "namei.h"
14 #include "vnode.h"
15 #include "socket.h"
16 #include "socketvar.h"
17 #include "stat.h"
18 #include "systm.h"
19 #include "ioctl.h"
20 #include "file.h"
21 #include "fifo.h"
22 #include "errno.h"
23 #include "malloc.h"
24 
25 /*
26  * This structure is associated with the FIFO vnode and stores
27  * the state associated with the FIFO.
28  */
29 struct fifoinfo {
30 	struct socket	*fi_readsock;
31 	struct socket	*fi_writesock;
32 	long		fi_readers;
33 	long		fi_writers;
34 };
35 
36 int (**fifo_vnodeop_p)();
37 struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
38 	{ &vop_default_desc, vn_default_error },
39 	{ &vop_lookup_desc, fifo_lookup },		/* lookup */
40 	{ &vop_create_desc, fifo_create },		/* create */
41 	{ &vop_mknod_desc, fifo_mknod },		/* mknod */
42 	{ &vop_open_desc, fifo_open },		/* open */
43 	{ &vop_close_desc, fifo_close },		/* close */
44 	{ &vop_access_desc, fifo_access },		/* access */
45 	{ &vop_getattr_desc, fifo_getattr },		/* getattr */
46 	{ &vop_setattr_desc, fifo_setattr },		/* setattr */
47 	{ &vop_read_desc, fifo_read },		/* read */
48 	{ &vop_write_desc, fifo_write },		/* write */
49 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
50 	{ &vop_select_desc, fifo_select },		/* select */
51 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
52 	{ &vop_fsync_desc, fifo_fsync },		/* fsync */
53 	{ &vop_seek_desc, fifo_seek },		/* seek */
54 	{ &vop_remove_desc, fifo_remove },		/* remove */
55 	{ &vop_link_desc, fifo_link },		/* link */
56 	{ &vop_rename_desc, fifo_rename },		/* rename */
57 	{ &vop_mkdir_desc, fifo_mkdir },		/* mkdir */
58 	{ &vop_rmdir_desc, fifo_rmdir },		/* rmdir */
59 	{ &vop_symlink_desc, fifo_symlink },		/* symlink */
60 	{ &vop_readdir_desc, fifo_readdir },		/* readdir */
61 	{ &vop_readlink_desc, fifo_readlink },		/* readlink */
62 	{ &vop_abortop_desc, fifo_abortop },		/* abortop */
63 	{ &vop_inactive_desc, fifo_inactive },		/* inactive */
64 	{ &vop_reclaim_desc, fifo_reclaim },		/* reclaim */
65 	{ &vop_lock_desc, fifo_lock },		/* lock */
66 	{ &vop_unlock_desc, fifo_unlock },		/* unlock */
67 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
68 	{ &vop_strategy_desc, fifo_strategy },		/* strategy */
69 	{ &vop_print_desc, fifo_print },		/* print */
70 	{ &vop_islocked_desc, fifo_islocked },		/* islocked */
71 	{ &vop_advlock_desc, fifo_advlock },		/* advlock */
72 	{ &vop_blkatoff_desc, fifo_blkatoff },		/* blkatoff */
73 	{ &vop_vget_desc, fifo_vget },		/* vget */
74 	{ &vop_valloc_desc, fifo_valloc },		/* valloc */
75 	{ &vop_vfree_desc, fifo_vfree },		/* vfree */
76 	{ &vop_truncate_desc, fifo_truncate },		/* truncate */
77 	{ &vop_update_desc, fifo_update },		/* update */
78 	{ &vop_bwrite_desc, fifo_bwrite },		/* bwrite */
79 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
80 };
81 struct vnodeopv_desc fifo_vnodeop_opv_desc =
82 	{ &fifo_vnodeop_p, fifo_vnodeop_entries };
83 
84 /*
85  * Trivial lookup routine that always fails.
86  */
87 /* ARGSUSED */
88 fifo_lookup (ap)
89 	struct vop_lookup_args *ap;
90 #define dvp (ap->a_dvp)
91 #define vpp (ap->a_vpp)
92 #define cnp (ap->a_cnp)
93 {
94 
95 	*vpp = NULL;
96 	return (ENOTDIR);
97 }
98 #undef dvp
99 #undef vpp
100 #undef cnp
101 
102 /*
103  * Open called to set up a new instance of a fifo or
104  * to find an active instance of a fifo.
105  */
106 /* ARGSUSED */
107 fifo_open (ap)
108 	struct vop_open_args *ap;
109 #define vp (ap->a_vp)
110 #define mode (ap->a_mode)
111 #define cred (ap->a_cred)
112 #define p (ap->a_p)
113 {
114 	USES_VOP_CLOSE;
115 	USES_VOP_LOCK;
116 	USES_VOP_UNLOCK;
117 	register struct fifoinfo *fip;
118 	struct socket *rso, *wso;
119 	int error;
120 	static char openstr[] = "fifo";
121 
122 	if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
123 		return (EINVAL);
124 	if ((fip = vp->v_fifoinfo) == NULL) {
125 		MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
126 		vp->v_fifoinfo = fip;
127 		if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
128 			free(fip, M_VNODE);
129 			vp->v_fifoinfo = NULL;
130 			return (error);
131 		}
132 		fip->fi_readsock = rso;
133 		if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
134 			(void)soclose(rso);
135 			free(fip, M_VNODE);
136 			vp->v_fifoinfo = NULL;
137 			return (error);
138 		}
139 		fip->fi_writesock = wso;
140 		if (error = unp_connect2(wso, rso)) {
141 			(void)soclose(wso);
142 			(void)soclose(rso);
143 			free(fip, M_VNODE);
144 			vp->v_fifoinfo = NULL;
145 			return (error);
146 		}
147 		fip->fi_readers = fip->fi_writers = 0;
148 		wso->so_state |= SS_CANTRCVMORE;
149 		rso->so_state |= SS_CANTSENDMORE;
150 	}
151 	error = 0;
152 	if (mode & FREAD) {
153 		fip->fi_readers++;
154 		if (fip->fi_readers == 1) {
155 			fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
156 			if (fip->fi_writers > 0)
157 				wakeup((caddr_t)&fip->fi_writers);
158 		}
159 		if (mode & O_NONBLOCK)
160 			return (0);
161 		while (fip->fi_writers == 0) {
162 			VOP_UNLOCK(vp);
163 			error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
164 				openstr, 0);
165 			VOP_LOCK(vp);
166 			if (error)
167 				break;
168 		}
169 	} else {
170 		fip->fi_writers++;
171 		if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) {
172 			error = ENXIO;
173 		} else {
174 			if (fip->fi_writers == 1) {
175 				fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
176 				if (fip->fi_readers > 0)
177 					wakeup((caddr_t)&fip->fi_readers);
178 			}
179 			while (fip->fi_readers == 0) {
180 				VOP_UNLOCK(vp);
181 				error = tsleep((caddr_t)&fip->fi_writers,
182 					PSOCK, openstr, 0);
183 				VOP_LOCK(vp);
184 				if (error)
185 					break;
186 			}
187 		}
188 	}
189 	if (error)
190 		VOP_CLOSE(vp, mode, cred, p);
191 	return (error);
192 }
193 #undef vp
194 #undef mode
195 #undef cred
196 #undef p
197 
198 /*
199  * Vnode op for read
200  */
201 /* ARGSUSED */
202 fifo_read (ap)
203 	struct vop_read_args *ap;
204 #define vp (ap->a_vp)
205 #define uio (ap->a_uio)
206 #define ioflag (ap->a_ioflag)
207 #define cred (ap->a_cred)
208 {
209 	USES_VOP_LOCK;
210 	USES_VOP_UNLOCK;
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 #undef vp
237 #undef uio
238 #undef ioflag
239 #undef cred
240 
241 /*
242  * Vnode op for write
243  */
244 /* ARGSUSED */
245 fifo_write (ap)
246 	struct vop_write_args *ap;
247 #define vp (ap->a_vp)
248 #define uio (ap->a_uio)
249 #define ioflag (ap->a_ioflag)
250 #define cred (ap->a_cred)
251 {
252 	USES_VOP_LOCK;
253 	USES_VOP_UNLOCK;
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 #undef vp
271 #undef uio
272 #undef ioflag
273 #undef cred
274 
275 /*
276  * Device ioctl operation.
277  */
278 /* ARGSUSED */
279 fifo_ioctl (ap)
280 	struct vop_ioctl_args *ap;
281 #define vp (ap->a_vp)
282 #define com (ap->a_command)
283 #define data (ap->a_data)
284 #define fflag (ap->a_fflag)
285 #define cred (ap->a_cred)
286 #define p (ap->a_p)
287 {
288 	struct file filetmp;
289 	int error;
290 
291 	if (com == FIONBIO)
292 		return (0);
293 	if (fflag & FREAD)
294 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
295 	else
296 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
297 	return (soo_ioctl(&filetmp, com, data, p));
298 }
299 #undef vp
300 #undef com
301 #undef data
302 #undef fflag
303 #undef cred
304 #undef p
305 
306 /* ARGSUSED */
307 fifo_select (ap)
308 	struct vop_select_args *ap;
309 #define vp (ap->a_vp)
310 #define which (ap->a_which)
311 #define fflag (ap->a_fflags)
312 #define cred (ap->a_cred)
313 #define p (ap->a_p)
314 {
315 	struct file filetmp;
316 	int error;
317 
318 	if (fflag & FREAD)
319 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock;
320 	else
321 		filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock;
322 	return (soo_select(&filetmp, which, p));
323 }
324 #undef vp
325 #undef which
326 #undef fflag
327 #undef cred
328 #undef p
329 
330 /*
331  * This is a noop, simply returning what one has been given.
332  */
333 fifo_bmap (ap)
334 	struct vop_bmap_args *ap;
335 #define vp (ap->a_vp)
336 #define bn (ap->a_bn)
337 #define vpp (ap->a_vpp)
338 #define bnp (ap->a_bnp)
339 {
340 
341 	if (vpp != NULL)
342 		*vpp = vp;
343 	if (bnp != NULL)
344 		*bnp = bn;
345 	return (0);
346 }
347 #undef vp
348 #undef bn
349 #undef vpp
350 #undef bnp
351 
352 /*
353  * At the moment we do not do any locking.
354  */
355 /* ARGSUSED */
356 fifo_lock (ap)
357 	struct vop_lock_args *ap;
358 #define vp (ap->a_vp)
359 {
360 
361 	return (0);
362 }
363 #undef vp
364 
365 /* ARGSUSED */
366 fifo_unlock (ap)
367 	struct vop_unlock_args *ap;
368 #define vp (ap->a_vp)
369 {
370 
371 	return (0);
372 }
373 #undef vp
374 
375 /*
376  * Device close routine
377  */
378 /* ARGSUSED */
379 fifo_close (ap)
380 	struct vop_close_args *ap;
381 #define vp (ap->a_vp)
382 #define fflag (ap->a_fflag)
383 #define cred (ap->a_cred)
384 #define p (ap->a_p)
385 {
386 	register struct fifoinfo *fip = vp->v_fifoinfo;
387 	int error1, error2;
388 
389 	if (fflag & FWRITE) {
390 		fip->fi_writers--;
391 		if (fip->fi_writers == 0)
392 			socantrcvmore(fip->fi_readsock);
393 	} else {
394 		fip->fi_readers--;
395 		if (fip->fi_readers == 0)
396 			socantsendmore(fip->fi_writesock);
397 	}
398 	if (vp->v_usecount > 1)
399 		return (0);
400 	error1 = soclose(fip->fi_readsock);
401 	error2 = soclose(fip->fi_writesock);
402 	FREE(fip, M_VNODE);
403 	vp->v_fifoinfo = NULL;
404 	if (error1)
405 		return (error1);
406 	return (error2);
407 }
408 #undef vp
409 #undef fflag
410 #undef cred
411 #undef p
412 
413 /*
414  * Print out the contents of a fifo vnode.
415  */
416 fifo_print (ap)
417 	struct vop_print_args *ap;
418 #define vp (ap->a_vp)
419 {
420 
421 	printf("tag VT_NON");
422 	fifo_printinfo(vp);
423 	printf("\n");
424 }
425 #undef vp
426 
427 /*
428  * Print out internal contents of a fifo vnode.
429  */
430 fifo_printinfo(vp)
431 	struct vnode *vp;
432 {
433 	register struct fifoinfo *fip = vp->v_fifoinfo;
434 
435 	printf(", fifo with %d readers and %d writers",
436 		fip->fi_readers, fip->fi_writers);
437 }
438 
439 /*
440  * Fifo failed operation
441  */
442 fifo_ebadf()
443 {
444 
445 	return (EBADF);
446 }
447 
448 /*
449  * Fifo advisory byte-level locks.
450  */
451 /* ARGSUSED */
452 fifo_advlock (ap)
453 	struct vop_advlock_args *ap;
454 #define vp (ap->a_vp)
455 #define id (ap->a_id)
456 #define op (ap->a_op)
457 #define fl (ap->a_fl)
458 #define flags (ap->a_flags)
459 {
460 
461 	return (EOPNOTSUPP);
462 }
463 #undef vp
464 #undef id
465 #undef op
466 #undef fl
467 #undef flags
468 
469 /*
470  * Fifo bad operation
471  */
472 fifo_badop()
473 {
474 
475 	panic("fifo_badop called");
476 	/* NOTREACHED */
477 }
478