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 * 3. 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: releng/12.0/sys/fs/fifofs/fifo_vnops.c 327004 2017-12-19 22:39:05Z jhb $
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 */
65 struct 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
73 static vop_print_t fifo_print;
74 static vop_open_t fifo_open;
75 static vop_close_t fifo_close;
76 static vop_advlock_t fifo_advlock;
77
78 struct 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 */
109 static void
110 fifo_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 */
128 static int
129 fifo_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 */
262 static int
263 fifo_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 */
313 int
314 fifo_printinfo(vp)
315 struct vnode *vp;
316 {
317 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 */
331 static int
332 fifo_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 */
347 static int
348 fifo_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
Cache object: 57ab974f9bf03a9441a4fbe4c119482e
|