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