fifo_vnops.c revision 330897
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1990, 1993, 1995
5 *	The Regents of the University of California.
6 * Copyright (c) 2005 Robert N. M. Watson
7 * Copyright (c) 2012 Giovanni Trematerra
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *	@(#)fifo_vnops.c	8.10 (Berkeley) 5/27/95
35 * $FreeBSD: stable/11/sys/fs/fifofs/fifo_vnops.c 330897 2018-03-14 03:19:51Z eadler $
36 */
37
38#include <sys/param.h>
39#include <sys/event.h>
40#include <sys/file.h>
41#include <sys/filedesc.h>
42#include <sys/filio.h>
43#include <sys/fcntl.h>
44#include <sys/kernel.h>
45#include <sys/lock.h>
46#include <sys/mutex.h>
47#include <sys/malloc.h>
48#include <sys/selinfo.h>
49#include <sys/pipe.h>
50#include <sys/proc.h>
51#include <sys/signalvar.h>
52#include <sys/sx.h>
53#include <sys/systm.h>
54#include <sys/un.h>
55#include <sys/unistd.h>
56#include <sys/vnode.h>
57
58/*
59 * This structure is associated with the FIFO vnode and stores
60 * the state associated with the FIFO.
61 * Notes about locking:
62 *   - fi_pipe is invariant since init time.
63 *   - fi_readers and fi_writers are protected by the vnode lock.
64 */
65struct fifoinfo {
66	struct pipe *fi_pipe;
67	long	fi_readers;
68	long	fi_writers;
69	u_int	fi_rgen;
70	u_int	fi_wgen;
71};
72
73static vop_print_t	fifo_print;
74static vop_open_t	fifo_open;
75static vop_close_t	fifo_close;
76static vop_advlock_t	fifo_advlock;
77
78struct vop_vector fifo_specops = {
79	.vop_default =		&default_vnodeops,
80
81	.vop_advlock =		fifo_advlock,
82	.vop_close =		fifo_close,
83	.vop_create =		VOP_PANIC,
84	.vop_getattr =		VOP_EBADF,
85	.vop_ioctl =		VOP_PANIC,
86	.vop_kqfilter =		VOP_PANIC,
87	.vop_link =		VOP_PANIC,
88	.vop_mkdir =		VOP_PANIC,
89	.vop_mknod =		VOP_PANIC,
90	.vop_open =		fifo_open,
91	.vop_pathconf =		VOP_PANIC,
92	.vop_print =		fifo_print,
93	.vop_read =		VOP_PANIC,
94	.vop_readdir =		VOP_PANIC,
95	.vop_readlink =		VOP_PANIC,
96	.vop_reallocblks =	VOP_PANIC,
97	.vop_reclaim =		VOP_NULL,
98	.vop_remove =		VOP_PANIC,
99	.vop_rename =		VOP_PANIC,
100	.vop_rmdir =		VOP_PANIC,
101	.vop_setattr =		VOP_EBADF,
102	.vop_symlink =		VOP_PANIC,
103	.vop_write =		VOP_PANIC,
104};
105
106/*
107 * Dispose of fifo resources.
108 */
109static void
110fifo_cleanup(struct vnode *vp)
111{
112	struct fifoinfo *fip;
113
114	ASSERT_VOP_ELOCKED(vp, "fifo_cleanup");
115	fip = vp->v_fifoinfo;
116	if (fip->fi_readers == 0 && fip->fi_writers == 0) {
117		vp->v_fifoinfo = NULL;
118		pipe_dtor(fip->fi_pipe);
119		free(fip, M_VNODE);
120	}
121}
122
123/*
124 * Open called to set up a new instance of a fifo or
125 * to find an active instance of a fifo.
126 */
127/* ARGSUSED */
128static int
129fifo_open(ap)
130	struct vop_open_args /* {
131		struct vnode *a_vp;
132		int  a_mode;
133		struct ucred *a_cred;
134		struct thread *a_td;
135		struct file *a_fp;
136	} */ *ap;
137{
138	struct vnode *vp;
139	struct file *fp;
140	struct thread *td;
141	struct fifoinfo *fip;
142	struct pipe *fpipe;
143	u_int gen;
144	int error, stops_deferred;
145
146	vp = ap->a_vp;
147	fp = ap->a_fp;
148	td = ap->a_td;
149	ASSERT_VOP_ELOCKED(vp, "fifo_open");
150	if (fp == NULL || (ap->a_mode & FEXEC) != 0)
151		return (EINVAL);
152	if ((fip = vp->v_fifoinfo) == NULL) {
153		pipe_named_ctor(&fpipe, td);
154		fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK);
155		fip->fi_pipe = fpipe;
156		fpipe->pipe_wgen = fip->fi_readers = fip->fi_writers = 0;
157 		KASSERT(vp->v_fifoinfo == NULL, ("fifo_open: v_fifoinfo race"));
158		vp->v_fifoinfo = fip;
159	}
160	fpipe = fip->fi_pipe;
161 	KASSERT(fpipe != NULL, ("fifo_open: pipe is NULL"));
162
163	/*
164	 * Use the pipe mutex here, in addition to the vnode lock,
165	 * in order to allow vnode lock dropping before msleep() calls
166	 * and still avoiding missed wakeups.
167	 */
168	PIPE_LOCK(fpipe);
169	if (ap->a_mode & FREAD) {
170		fip->fi_readers++;
171		fip->fi_rgen++;
172		if (fip->fi_readers == 1) {
173			fpipe->pipe_state &= ~PIPE_EOF;
174			if (fip->fi_writers > 0)
175				wakeup(&fip->fi_writers);
176		}
177		fp->f_seqcount = fpipe->pipe_wgen - fip->fi_writers;
178	}
179	if (ap->a_mode & FWRITE) {
180		if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
181			PIPE_UNLOCK(fpipe);
182			if (fip->fi_writers == 0)
183				fifo_cleanup(vp);
184			return (ENXIO);
185		}
186		fip->fi_writers++;
187		fip->fi_wgen++;
188		if (fip->fi_writers == 1) {
189			fpipe->pipe_state &= ~PIPE_EOF;
190			if (fip->fi_readers > 0)
191				wakeup(&fip->fi_readers);
192		}
193	}
194	if ((ap->a_mode & O_NONBLOCK) == 0) {
195		if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
196			gen = fip->fi_wgen;
197			VOP_UNLOCK(vp, 0);
198			stops_deferred = sigdeferstop(SIGDEFERSTOP_OFF);
199			error = msleep(&fip->fi_readers, PIPE_MTX(fpipe),
200			    PDROP | PCATCH | PSOCK, "fifoor", 0);
201			sigallowstop(stops_deferred);
202			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
203			if (error != 0 && gen == fip->fi_wgen) {
204				fip->fi_readers--;
205				if (fip->fi_readers == 0) {
206					PIPE_LOCK(fpipe);
207					fpipe->pipe_state |= PIPE_EOF;
208					if (fpipe->pipe_state & PIPE_WANTW)
209						wakeup(fpipe);
210					PIPE_UNLOCK(fpipe);
211					fifo_cleanup(vp);
212				}
213				return (error);
214			}
215			PIPE_LOCK(fpipe);
216			/*
217			 * We must have got woken up because we had a writer.
218			 * That (and not still having one) is the condition
219			 * that we must wait for.
220			 */
221		}
222		if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
223			gen = fip->fi_rgen;
224			VOP_UNLOCK(vp, 0);
225			stops_deferred = sigdeferstop(SIGDEFERSTOP_OFF);
226			error = msleep(&fip->fi_writers, PIPE_MTX(fpipe),
227			    PDROP | PCATCH | PSOCK, "fifoow", 0);
228			sigallowstop(stops_deferred);
229			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
230			if (error != 0 && gen == fip->fi_rgen) {
231				fip->fi_writers--;
232				if (fip->fi_writers == 0) {
233					PIPE_LOCK(fpipe);
234					fpipe->pipe_state |= PIPE_EOF;
235					if (fpipe->pipe_state & PIPE_WANTR)
236						wakeup(fpipe);
237					fpipe->pipe_wgen++;
238					PIPE_UNLOCK(fpipe);
239					fifo_cleanup(vp);
240				}
241				return (error);
242			}
243			/*
244			 * We must have got woken up because we had
245			 * a reader.  That (and not still having one)
246			 * is the condition that we must wait for.
247			 */
248			PIPE_LOCK(fpipe);
249		}
250	}
251	PIPE_UNLOCK(fpipe);
252	KASSERT(fp != NULL, ("can't fifo/vnode bypass"));
253	KASSERT(fp->f_ops == &badfileops, ("not badfileops in fifo_open"));
254	finit(fp, fp->f_flag, DTYPE_FIFO, fpipe, &pipeops);
255	return (0);
256}
257
258/*
259 * Device close routine
260 */
261/* ARGSUSED */
262static int
263fifo_close(ap)
264	struct vop_close_args /* {
265		struct vnode *a_vp;
266		int  a_fflag;
267		struct ucred *a_cred;
268		struct thread *a_td;
269	} */ *ap;
270{
271	struct vnode *vp;
272	struct fifoinfo *fip;
273	struct pipe *cpipe;
274
275	vp = ap->a_vp;
276	fip = vp->v_fifoinfo;
277	cpipe = fip->fi_pipe;
278	ASSERT_VOP_ELOCKED(vp, "fifo_close");
279	if (ap->a_fflag & FREAD) {
280		fip->fi_readers--;
281		if (fip->fi_readers == 0) {
282			PIPE_LOCK(cpipe);
283			cpipe->pipe_state |= PIPE_EOF;
284			if ((cpipe->pipe_state & PIPE_WANTW)) {
285				cpipe->pipe_state &= ~PIPE_WANTW;
286				wakeup(cpipe);
287			}
288			pipeselwakeup(cpipe);
289			PIPE_UNLOCK(cpipe);
290		}
291	}
292	if (ap->a_fflag & FWRITE) {
293		fip->fi_writers--;
294		if (fip->fi_writers == 0) {
295			PIPE_LOCK(cpipe);
296			cpipe->pipe_state |= PIPE_EOF;
297			if ((cpipe->pipe_state & PIPE_WANTR)) {
298				cpipe->pipe_state &= ~PIPE_WANTR;
299				wakeup(cpipe);
300			}
301			cpipe->pipe_wgen++;
302			pipeselwakeup(cpipe);
303			PIPE_UNLOCK(cpipe);
304		}
305	}
306	fifo_cleanup(vp);
307	return (0);
308}
309
310/*
311 * Print out internal contents of a fifo vnode.
312 */
313int
314fifo_printinfo(vp)
315	struct vnode *vp;
316{
317	register struct fifoinfo *fip = vp->v_fifoinfo;
318
319	if (fip == NULL){
320		printf(", NULL v_fifoinfo");
321		return (0);
322	}
323	printf(", fifo with %ld readers and %ld writers",
324		fip->fi_readers, fip->fi_writers);
325	return (0);
326}
327
328/*
329 * Print out the contents of a fifo vnode.
330 */
331static int
332fifo_print(ap)
333	struct vop_print_args /* {
334		struct vnode *a_vp;
335	} */ *ap;
336{
337	printf("    ");
338	fifo_printinfo(ap->a_vp);
339	printf("\n");
340	return (0);
341}
342
343/*
344 * Fifo advisory byte-level locks.
345 */
346/* ARGSUSED */
347static int
348fifo_advlock(ap)
349	struct vop_advlock_args /* {
350		struct vnode *a_vp;
351		caddr_t  a_id;
352		int  a_op;
353		struct flock *a_fl;
354		int  a_flags;
355	} */ *ap;
356{
357
358	return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
359}
360
361