Line data Source code
1 : /* $OpenBSD: sys_pipe.c,v 1.85 2018/08/20 16:00:22 mpi Exp $ */
2 :
3 : /*
4 : * Copyright (c) 1996 John S. Dyson
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice immediately at the beginning of the file, without modification,
12 : * this list of conditions, and the following disclaimer.
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : * 3. Absolutely no warranty of function or purpose is made by the author
17 : * John S. Dyson.
18 : * 4. Modifications may be freely made to this file if the above conditions
19 : * are met.
20 : */
21 :
22 : /*
23 : * This file contains a high-performance replacement for the socket-based
24 : * pipes scheme originally used in FreeBSD/4.4Lite. It does not support
25 : * all features of sockets, but does do everything that pipes normally
26 : * do.
27 : */
28 :
29 : #include <sys/param.h>
30 : #include <sys/systm.h>
31 : #include <sys/proc.h>
32 : #include <sys/fcntl.h>
33 : #include <sys/file.h>
34 : #include <sys/filedesc.h>
35 : #include <sys/pool.h>
36 : #include <sys/ioctl.h>
37 : #include <sys/stat.h>
38 : #include <sys/signalvar.h>
39 : #include <sys/mount.h>
40 : #include <sys/syscallargs.h>
41 : #include <sys/event.h>
42 : #include <sys/lock.h>
43 : #include <sys/poll.h>
44 : #ifdef KTRACE
45 : #include <sys/ktrace.h>
46 : #endif
47 :
48 : #include <uvm/uvm_extern.h>
49 :
50 : #include <sys/pipe.h>
51 :
52 : /*
53 : * interfaces to the outside world
54 : */
55 : int pipe_read(struct file *, struct uio *, int);
56 : int pipe_write(struct file *, struct uio *, int);
57 : int pipe_close(struct file *, struct proc *);
58 : int pipe_poll(struct file *, int events, struct proc *);
59 : int pipe_kqfilter(struct file *fp, struct knote *kn);
60 : int pipe_ioctl(struct file *, u_long, caddr_t, struct proc *);
61 : int pipe_stat(struct file *fp, struct stat *ub, struct proc *p);
62 :
63 : static struct fileops pipeops = {
64 : .fo_read = pipe_read,
65 : .fo_write = pipe_write,
66 : .fo_ioctl = pipe_ioctl,
67 : .fo_poll = pipe_poll,
68 : .fo_kqfilter = pipe_kqfilter,
69 : .fo_stat = pipe_stat,
70 : .fo_close = pipe_close
71 : };
72 :
73 : void filt_pipedetach(struct knote *kn);
74 : int filt_piperead(struct knote *kn, long hint);
75 : int filt_pipewrite(struct knote *kn, long hint);
76 :
77 : struct filterops pipe_rfiltops =
78 : { 1, NULL, filt_pipedetach, filt_piperead };
79 : struct filterops pipe_wfiltops =
80 : { 1, NULL, filt_pipedetach, filt_pipewrite };
81 :
82 : /*
83 : * Default pipe buffer size(s), this can be kind-of large now because pipe
84 : * space is pageable. The pipe code will try to maintain locality of
85 : * reference for performance reasons, so small amounts of outstanding I/O
86 : * will not wipe the cache.
87 : */
88 : #define MINPIPESIZE (PIPE_SIZE/3)
89 :
90 : /*
91 : * Limit the number of "big" pipes
92 : */
93 : #define LIMITBIGPIPES 32
94 : unsigned int nbigpipe;
95 : static unsigned int amountpipekva;
96 :
97 : struct pool pipe_pool;
98 :
99 : int dopipe(struct proc *, int *, int);
100 : void pipeclose(struct pipe *);
101 : void pipe_free_kmem(struct pipe *);
102 : int pipe_create(struct pipe *);
103 : int pipelock(struct pipe *);
104 : void pipeunlock(struct pipe *);
105 : void pipeselwakeup(struct pipe *);
106 : int pipespace(struct pipe *, u_int);
107 :
108 : /*
109 : * The pipe system call for the DTYPE_PIPE type of pipes
110 : */
111 :
112 : int
113 0 : sys_pipe(struct proc *p, void *v, register_t *retval)
114 : {
115 : struct sys_pipe_args /* {
116 : syscallarg(int *) fdp;
117 0 : } */ *uap = v;
118 :
119 0 : return (dopipe(p, SCARG(uap, fdp), 0));
120 : }
121 :
122 : int
123 0 : sys_pipe2(struct proc *p, void *v, register_t *retval)
124 : {
125 : struct sys_pipe2_args /* {
126 : syscallarg(int *) fdp;
127 : syscallarg(int) flags;
128 0 : } */ *uap = v;
129 :
130 0 : if (SCARG(uap, flags) & ~(O_CLOEXEC | FNONBLOCK))
131 0 : return (EINVAL);
132 :
133 0 : return (dopipe(p, SCARG(uap, fdp), SCARG(uap, flags)));
134 0 : }
135 :
136 : int
137 0 : dopipe(struct proc *p, int *ufds, int flags)
138 : {
139 0 : struct filedesc *fdp = p->p_fd;
140 0 : struct file *rf, *wf;
141 : struct pipe *rpipe, *wpipe = NULL;
142 0 : int fds[2], cloexec, error;
143 :
144 0 : cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
145 :
146 0 : rpipe = pool_get(&pipe_pool, PR_WAITOK);
147 0 : error = pipe_create(rpipe);
148 0 : if (error != 0)
149 : goto free1;
150 0 : wpipe = pool_get(&pipe_pool, PR_WAITOK);
151 0 : error = pipe_create(wpipe);
152 0 : if (error != 0)
153 : goto free1;
154 :
155 0 : fdplock(fdp);
156 :
157 0 : error = falloc(p, &rf, &fds[0]);
158 0 : if (error != 0)
159 : goto free2;
160 0 : rf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK);
161 0 : rf->f_type = DTYPE_PIPE;
162 0 : rf->f_data = rpipe;
163 0 : rf->f_ops = &pipeops;
164 :
165 0 : error = falloc(p, &wf, &fds[1]);
166 0 : if (error != 0)
167 : goto free3;
168 0 : wf->f_flag = FREAD | FWRITE | (flags & FNONBLOCK);
169 0 : wf->f_type = DTYPE_PIPE;
170 0 : wf->f_data = wpipe;
171 0 : wf->f_ops = &pipeops;
172 :
173 0 : rpipe->pipe_peer = wpipe;
174 0 : wpipe->pipe_peer = rpipe;
175 :
176 0 : fdinsert(fdp, fds[0], cloexec, rf);
177 0 : fdinsert(fdp, fds[1], cloexec, wf);
178 :
179 0 : error = copyout(fds, ufds, sizeof(fds));
180 0 : if (error != 0) {
181 0 : fdrelease(p, fds[0]);
182 0 : fdrelease(p, fds[1]);
183 0 : }
184 : #ifdef KTRACE
185 0 : else if (KTRPOINT(p, KTR_STRUCT))
186 0 : ktrfds(p, fds, 2);
187 : #endif
188 0 : fdpunlock(fdp);
189 :
190 0 : FRELE(rf, p);
191 0 : FRELE(wf, p);
192 0 : return (error);
193 :
194 : free3:
195 0 : fdremove(fdp, fds[0]);
196 0 : closef(rf, p);
197 0 : rpipe = NULL;
198 : free2:
199 0 : fdpunlock(fdp);
200 : free1:
201 0 : pipeclose(wpipe);
202 0 : pipeclose(rpipe);
203 0 : return (error);
204 0 : }
205 :
206 : /*
207 : * Allocate kva for pipe circular buffer, the space is pageable.
208 : * This routine will 'realloc' the size of a pipe safely, if it fails
209 : * it will retain the old buffer.
210 : * If it fails it will return ENOMEM.
211 : */
212 : int
213 0 : pipespace(struct pipe *cpipe, u_int size)
214 : {
215 : caddr_t buffer;
216 :
217 0 : KERNEL_LOCK();
218 0 : buffer = km_alloc(size, &kv_any, &kp_pageable, &kd_waitok);
219 0 : KERNEL_UNLOCK();
220 0 : if (buffer == NULL) {
221 0 : return (ENOMEM);
222 : }
223 :
224 : /* free old resources if we are resizing */
225 0 : pipe_free_kmem(cpipe);
226 0 : cpipe->pipe_buffer.buffer = buffer;
227 0 : cpipe->pipe_buffer.size = size;
228 0 : cpipe->pipe_buffer.in = 0;
229 0 : cpipe->pipe_buffer.out = 0;
230 0 : cpipe->pipe_buffer.cnt = 0;
231 :
232 0 : atomic_add_int(&amountpipekva, cpipe->pipe_buffer.size);
233 :
234 0 : return (0);
235 0 : }
236 :
237 : /*
238 : * initialize and allocate VM and memory for pipe
239 : */
240 : int
241 0 : pipe_create(struct pipe *cpipe)
242 : {
243 : int error;
244 :
245 : /* so pipe_free_kmem() doesn't follow junk pointer */
246 0 : cpipe->pipe_buffer.buffer = NULL;
247 : /*
248 : * protect so pipeclose() doesn't follow a junk pointer
249 : * if pipespace() fails.
250 : */
251 0 : memset(&cpipe->pipe_sel, 0, sizeof(cpipe->pipe_sel));
252 0 : cpipe->pipe_state = 0;
253 0 : cpipe->pipe_peer = NULL;
254 0 : cpipe->pipe_busy = 0;
255 :
256 0 : error = pipespace(cpipe, PIPE_SIZE);
257 0 : if (error != 0)
258 0 : return (error);
259 :
260 0 : getnanotime(&cpipe->pipe_ctime);
261 0 : cpipe->pipe_atime = cpipe->pipe_ctime;
262 0 : cpipe->pipe_mtime = cpipe->pipe_ctime;
263 0 : cpipe->pipe_pgid = NO_PID;
264 :
265 0 : return (0);
266 0 : }
267 :
268 :
269 : /*
270 : * lock a pipe for I/O, blocking other access
271 : */
272 : int
273 0 : pipelock(struct pipe *cpipe)
274 : {
275 : int error;
276 0 : while (cpipe->pipe_state & PIPE_LOCK) {
277 0 : cpipe->pipe_state |= PIPE_LWANT;
278 0 : if ((error = tsleep(cpipe, PRIBIO|PCATCH, "pipelk", 0)))
279 0 : return error;
280 : }
281 0 : cpipe->pipe_state |= PIPE_LOCK;
282 0 : return 0;
283 0 : }
284 :
285 : /*
286 : * unlock a pipe I/O lock
287 : */
288 : void
289 0 : pipeunlock(struct pipe *cpipe)
290 : {
291 0 : cpipe->pipe_state &= ~PIPE_LOCK;
292 0 : if (cpipe->pipe_state & PIPE_LWANT) {
293 0 : cpipe->pipe_state &= ~PIPE_LWANT;
294 0 : wakeup(cpipe);
295 0 : }
296 0 : }
297 :
298 : void
299 0 : pipeselwakeup(struct pipe *cpipe)
300 : {
301 0 : if (cpipe->pipe_state & PIPE_SEL) {
302 0 : cpipe->pipe_state &= ~PIPE_SEL;
303 0 : selwakeup(&cpipe->pipe_sel);
304 0 : } else
305 0 : KNOTE(&cpipe->pipe_sel.si_note, 0);
306 0 : if ((cpipe->pipe_state & PIPE_ASYNC) && cpipe->pipe_pgid != NO_PID)
307 0 : gsignal(cpipe->pipe_pgid, SIGIO);
308 0 : }
309 :
310 : int
311 0 : pipe_read(struct file *fp, struct uio *uio, int fflags)
312 : {
313 0 : struct pipe *rpipe = fp->f_data;
314 : int error;
315 : size_t size, nread = 0;
316 :
317 0 : error = pipelock(rpipe);
318 0 : if (error)
319 0 : return (error);
320 :
321 0 : ++rpipe->pipe_busy;
322 :
323 0 : while (uio->uio_resid) {
324 : /*
325 : * normal pipe buffer receive
326 : */
327 0 : if (rpipe->pipe_buffer.cnt > 0) {
328 0 : size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out;
329 0 : if (size > rpipe->pipe_buffer.cnt)
330 0 : size = rpipe->pipe_buffer.cnt;
331 0 : if (size > uio->uio_resid)
332 0 : size = uio->uio_resid;
333 0 : error = uiomove(&rpipe->pipe_buffer.buffer[rpipe->pipe_buffer.out],
334 : size, uio);
335 0 : if (error) {
336 : break;
337 : }
338 0 : rpipe->pipe_buffer.out += size;
339 0 : if (rpipe->pipe_buffer.out >= rpipe->pipe_buffer.size)
340 0 : rpipe->pipe_buffer.out = 0;
341 :
342 0 : rpipe->pipe_buffer.cnt -= size;
343 : /*
344 : * If there is no more to read in the pipe, reset
345 : * its pointers to the beginning. This improves
346 : * cache hit stats.
347 : */
348 0 : if (rpipe->pipe_buffer.cnt == 0) {
349 0 : rpipe->pipe_buffer.in = 0;
350 0 : rpipe->pipe_buffer.out = 0;
351 0 : }
352 0 : nread += size;
353 0 : } else {
354 : /*
355 : * detect EOF condition
356 : * read returns 0 on EOF, no need to set error
357 : */
358 0 : if (rpipe->pipe_state & PIPE_EOF)
359 : break;
360 :
361 : /*
362 : * If the "write-side" has been blocked, wake it up now.
363 : */
364 0 : if (rpipe->pipe_state & PIPE_WANTW) {
365 0 : rpipe->pipe_state &= ~PIPE_WANTW;
366 0 : wakeup(rpipe);
367 0 : }
368 :
369 : /*
370 : * Break if some data was read.
371 : */
372 0 : if (nread > 0)
373 : break;
374 :
375 : /*
376 : * Unlock the pipe buffer for our remaining processing.
377 : * We will either break out with an error or we will
378 : * sleep and relock to loop.
379 : */
380 0 : pipeunlock(rpipe);
381 :
382 : /*
383 : * Handle non-blocking mode operation or
384 : * wait for more data.
385 : */
386 0 : if (fp->f_flag & FNONBLOCK) {
387 : error = EAGAIN;
388 0 : } else {
389 0 : rpipe->pipe_state |= PIPE_WANTR;
390 0 : if ((error = tsleep(rpipe, PRIBIO|PCATCH, "piperd", 0)) == 0)
391 0 : error = pipelock(rpipe);
392 : }
393 0 : if (error)
394 : goto unlocked_error;
395 : }
396 : }
397 0 : pipeunlock(rpipe);
398 :
399 0 : if (error == 0)
400 0 : getnanotime(&rpipe->pipe_atime);
401 : unlocked_error:
402 0 : --rpipe->pipe_busy;
403 :
404 : /*
405 : * PIPE_WANT processing only makes sense if pipe_busy is 0.
406 : */
407 0 : if ((rpipe->pipe_busy == 0) && (rpipe->pipe_state & PIPE_WANT)) {
408 0 : rpipe->pipe_state &= ~(PIPE_WANT|PIPE_WANTW);
409 0 : wakeup(rpipe);
410 0 : } else if (rpipe->pipe_buffer.cnt < MINPIPESIZE) {
411 : /*
412 : * Handle write blocking hysteresis.
413 : */
414 0 : if (rpipe->pipe_state & PIPE_WANTW) {
415 0 : rpipe->pipe_state &= ~PIPE_WANTW;
416 0 : wakeup(rpipe);
417 0 : }
418 : }
419 :
420 0 : if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF)
421 0 : pipeselwakeup(rpipe);
422 :
423 0 : return (error);
424 0 : }
425 :
426 : int
427 0 : pipe_write(struct file *fp, struct uio *uio, int fflags)
428 : {
429 : int error = 0;
430 : size_t orig_resid;
431 : struct pipe *wpipe, *rpipe;
432 :
433 0 : rpipe = fp->f_data;
434 0 : wpipe = rpipe->pipe_peer;
435 :
436 : /*
437 : * detect loss of pipe read side, issue SIGPIPE if lost.
438 : */
439 0 : if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
440 0 : return (EPIPE);
441 : }
442 0 : ++wpipe->pipe_busy;
443 :
444 : /*
445 : * If it is advantageous to resize the pipe buffer, do
446 : * so.
447 : */
448 0 : if ((uio->uio_resid > PIPE_SIZE) &&
449 0 : (wpipe->pipe_buffer.size <= PIPE_SIZE) &&
450 0 : (wpipe->pipe_buffer.cnt == 0)) {
451 : unsigned int npipe;
452 :
453 0 : npipe = atomic_inc_int_nv(&nbigpipe);
454 0 : if ((npipe <= LIMITBIGPIPES) &&
455 0 : (error = pipelock(wpipe)) == 0) {
456 0 : if (pipespace(wpipe, BIG_PIPE_SIZE) != 0)
457 0 : atomic_dec_int(&nbigpipe);
458 0 : pipeunlock(wpipe);
459 0 : } else
460 0 : atomic_dec_int(&nbigpipe);
461 0 : }
462 :
463 : /*
464 : * If an early error occurred unbusy and return, waking up any pending
465 : * readers.
466 : */
467 0 : if (error) {
468 0 : --wpipe->pipe_busy;
469 0 : if ((wpipe->pipe_busy == 0) &&
470 0 : (wpipe->pipe_state & PIPE_WANT)) {
471 0 : wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
472 0 : wakeup(wpipe);
473 0 : }
474 0 : return (error);
475 : }
476 :
477 0 : orig_resid = uio->uio_resid;
478 :
479 0 : while (uio->uio_resid) {
480 0 : size_t space;
481 :
482 : retrywrite:
483 0 : if (wpipe->pipe_state & PIPE_EOF) {
484 : error = EPIPE;
485 0 : break;
486 : }
487 :
488 0 : space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
489 :
490 : /* Writes of size <= PIPE_BUF must be atomic. */
491 0 : if ((space < uio->uio_resid) && (orig_resid <= PIPE_BUF))
492 0 : space = 0;
493 :
494 0 : if (space > 0) {
495 0 : if ((error = pipelock(wpipe)) == 0) {
496 : size_t size; /* Transfer size */
497 : size_t segsize; /* first segment to transfer */
498 :
499 : /*
500 : * If a process blocked in uiomove, our
501 : * value for space might be bad.
502 : *
503 : * XXX will we be ok if the reader has gone
504 : * away here?
505 : */
506 0 : if (space > wpipe->pipe_buffer.size -
507 0 : wpipe->pipe_buffer.cnt) {
508 0 : pipeunlock(wpipe);
509 0 : goto retrywrite;
510 : }
511 :
512 : /*
513 : * Transfer size is minimum of uio transfer
514 : * and free space in pipe buffer.
515 : */
516 0 : if (space > uio->uio_resid)
517 0 : size = uio->uio_resid;
518 : else
519 : size = space;
520 : /*
521 : * First segment to transfer is minimum of
522 : * transfer size and contiguous space in
523 : * pipe buffer. If first segment to transfer
524 : * is less than the transfer size, we've got
525 : * a wraparound in the buffer.
526 : */
527 0 : segsize = wpipe->pipe_buffer.size -
528 0 : wpipe->pipe_buffer.in;
529 0 : if (segsize > size)
530 0 : segsize = size;
531 :
532 : /* Transfer first segment */
533 :
534 0 : error = uiomove(&wpipe->pipe_buffer.buffer[wpipe->pipe_buffer.in],
535 : segsize, uio);
536 :
537 0 : if (error == 0 && segsize < size) {
538 : /*
539 : * Transfer remaining part now, to
540 : * support atomic writes. Wraparound
541 : * happened.
542 : */
543 : #ifdef DIAGNOSTIC
544 0 : if (wpipe->pipe_buffer.in + segsize !=
545 0 : wpipe->pipe_buffer.size)
546 0 : panic("Expected pipe buffer wraparound disappeared");
547 : #endif
548 :
549 0 : error = uiomove(&wpipe->pipe_buffer.buffer[0],
550 0 : size - segsize, uio);
551 0 : }
552 0 : if (error == 0) {
553 0 : wpipe->pipe_buffer.in += size;
554 0 : if (wpipe->pipe_buffer.in >=
555 0 : wpipe->pipe_buffer.size) {
556 : #ifdef DIAGNOSTIC
557 0 : if (wpipe->pipe_buffer.in != size - segsize + wpipe->pipe_buffer.size)
558 0 : panic("Expected wraparound bad");
559 : #endif
560 0 : wpipe->pipe_buffer.in = size - segsize;
561 0 : }
562 :
563 0 : wpipe->pipe_buffer.cnt += size;
564 : #ifdef DIAGNOSTIC
565 0 : if (wpipe->pipe_buffer.cnt > wpipe->pipe_buffer.size)
566 0 : panic("Pipe buffer overflow");
567 : #endif
568 : }
569 0 : pipeunlock(wpipe);
570 0 : }
571 0 : if (error)
572 0 : break;
573 : } else {
574 : /*
575 : * If the "read-side" has been blocked, wake it up now.
576 : */
577 0 : if (wpipe->pipe_state & PIPE_WANTR) {
578 0 : wpipe->pipe_state &= ~PIPE_WANTR;
579 0 : wakeup(wpipe);
580 0 : }
581 :
582 : /*
583 : * don't block on non-blocking I/O
584 : */
585 0 : if (fp->f_flag & FNONBLOCK) {
586 : error = EAGAIN;
587 0 : break;
588 : }
589 :
590 : /*
591 : * We have no more space and have something to offer,
592 : * wake up select/poll.
593 : */
594 0 : pipeselwakeup(wpipe);
595 :
596 0 : wpipe->pipe_state |= PIPE_WANTW;
597 0 : error = tsleep(wpipe, (PRIBIO + 1)|PCATCH,
598 : "pipewr", 0);
599 0 : if (error)
600 0 : break;
601 : /*
602 : * If read side wants to go away, we just issue a
603 : * signal to ourselves.
604 : */
605 0 : if (wpipe->pipe_state & PIPE_EOF) {
606 : error = EPIPE;
607 0 : break;
608 : }
609 : }
610 0 : }
611 :
612 0 : --wpipe->pipe_busy;
613 :
614 0 : if ((wpipe->pipe_busy == 0) && (wpipe->pipe_state & PIPE_WANT)) {
615 0 : wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
616 0 : wakeup(wpipe);
617 0 : } else if (wpipe->pipe_buffer.cnt > 0) {
618 : /*
619 : * If we have put any characters in the buffer, we wake up
620 : * the reader.
621 : */
622 0 : if (wpipe->pipe_state & PIPE_WANTR) {
623 0 : wpipe->pipe_state &= ~PIPE_WANTR;
624 0 : wakeup(wpipe);
625 0 : }
626 : }
627 :
628 : /*
629 : * Don't return EPIPE if I/O was successful
630 : */
631 0 : if ((wpipe->pipe_buffer.cnt == 0) &&
632 0 : (uio->uio_resid == 0) &&
633 0 : (error == EPIPE)) {
634 : error = 0;
635 0 : }
636 :
637 0 : if (error == 0)
638 0 : getnanotime(&wpipe->pipe_mtime);
639 : /*
640 : * We have something to offer, wake up select/poll.
641 : */
642 0 : if (wpipe->pipe_buffer.cnt)
643 0 : pipeselwakeup(wpipe);
644 :
645 0 : return (error);
646 0 : }
647 :
648 : /*
649 : * we implement a very minimal set of ioctls for compatibility with sockets.
650 : */
651 : int
652 0 : pipe_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
653 : {
654 0 : struct pipe *mpipe = fp->f_data;
655 :
656 0 : switch (cmd) {
657 :
658 : case FIONBIO:
659 0 : return (0);
660 :
661 : case FIOASYNC:
662 0 : if (*(int *)data) {
663 0 : mpipe->pipe_state |= PIPE_ASYNC;
664 0 : } else {
665 0 : mpipe->pipe_state &= ~PIPE_ASYNC;
666 : }
667 0 : return (0);
668 :
669 : case FIONREAD:
670 0 : *(int *)data = mpipe->pipe_buffer.cnt;
671 0 : return (0);
672 :
673 : case TIOCSPGRP:
674 : /* FALLTHROUGH */
675 : case SIOCSPGRP:
676 0 : mpipe->pipe_pgid = *(int *)data;
677 0 : return (0);
678 :
679 : case SIOCGPGRP:
680 0 : *(int *)data = mpipe->pipe_pgid;
681 0 : return (0);
682 :
683 : case TIOCGPGRP:
684 0 : *(int *)data = -mpipe->pipe_pgid;
685 0 : break;
686 :
687 : }
688 0 : return (ENOTTY);
689 0 : }
690 :
691 : int
692 0 : pipe_poll(struct file *fp, int events, struct proc *p)
693 : {
694 0 : struct pipe *rpipe = fp->f_data;
695 : struct pipe *wpipe;
696 : int revents = 0;
697 :
698 0 : wpipe = rpipe->pipe_peer;
699 0 : if (events & (POLLIN | POLLRDNORM)) {
700 0 : if ((rpipe->pipe_buffer.cnt > 0) ||
701 0 : (rpipe->pipe_state & PIPE_EOF))
702 0 : revents |= events & (POLLIN | POLLRDNORM);
703 : }
704 :
705 : /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */
706 0 : if ((rpipe->pipe_state & PIPE_EOF) ||
707 0 : (wpipe == NULL) ||
708 0 : (wpipe->pipe_state & PIPE_EOF))
709 0 : revents |= POLLHUP;
710 0 : else if (events & (POLLOUT | POLLWRNORM)) {
711 0 : if ((wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)
712 0 : revents |= events & (POLLOUT | POLLWRNORM);
713 : }
714 :
715 0 : if (revents == 0) {
716 0 : if (events & (POLLIN | POLLRDNORM)) {
717 0 : selrecord(p, &rpipe->pipe_sel);
718 0 : rpipe->pipe_state |= PIPE_SEL;
719 0 : }
720 0 : if (events & (POLLOUT | POLLWRNORM)) {
721 0 : selrecord(p, &wpipe->pipe_sel);
722 0 : wpipe->pipe_state |= PIPE_SEL;
723 0 : }
724 : }
725 0 : return (revents);
726 : }
727 :
728 : int
729 0 : pipe_stat(struct file *fp, struct stat *ub, struct proc *p)
730 : {
731 0 : struct pipe *pipe = fp->f_data;
732 :
733 0 : memset(ub, 0, sizeof(*ub));
734 0 : ub->st_mode = S_IFIFO;
735 0 : ub->st_blksize = pipe->pipe_buffer.size;
736 0 : ub->st_size = pipe->pipe_buffer.cnt;
737 0 : ub->st_blocks = (ub->st_size + ub->st_blksize - 1) / ub->st_blksize;
738 0 : ub->st_atim.tv_sec = pipe->pipe_atime.tv_sec;
739 0 : ub->st_atim.tv_nsec = pipe->pipe_atime.tv_nsec;
740 0 : ub->st_mtim.tv_sec = pipe->pipe_mtime.tv_sec;
741 0 : ub->st_mtim.tv_nsec = pipe->pipe_mtime.tv_nsec;
742 0 : ub->st_ctim.tv_sec = pipe->pipe_ctime.tv_sec;
743 0 : ub->st_ctim.tv_nsec = pipe->pipe_ctime.tv_nsec;
744 0 : ub->st_uid = fp->f_cred->cr_uid;
745 0 : ub->st_gid = fp->f_cred->cr_gid;
746 : /*
747 : * Left as 0: st_dev, st_ino, st_nlink, st_rdev, st_flags, st_gen.
748 : * XXX (st_dev, st_ino) should be unique.
749 : */
750 0 : return (0);
751 : }
752 :
753 : int
754 0 : pipe_close(struct file *fp, struct proc *p)
755 : {
756 0 : struct pipe *cpipe = fp->f_data;
757 :
758 0 : fp->f_ops = NULL;
759 0 : fp->f_data = NULL;
760 0 : KERNEL_LOCK();
761 0 : pipeclose(cpipe);
762 0 : KERNEL_UNLOCK();
763 0 : return (0);
764 : }
765 :
766 : void
767 0 : pipe_free_kmem(struct pipe *cpipe)
768 : {
769 0 : u_int size = cpipe->pipe_buffer.size;
770 :
771 0 : if (cpipe->pipe_buffer.buffer != NULL) {
772 0 : KERNEL_LOCK();
773 0 : km_free(cpipe->pipe_buffer.buffer, size, &kv_any, &kp_pageable);
774 0 : KERNEL_UNLOCK();
775 0 : atomic_sub_int(&amountpipekva, size);
776 0 : cpipe->pipe_buffer.buffer = NULL;
777 0 : if (size > PIPE_SIZE)
778 0 : atomic_dec_int(&nbigpipe);
779 : }
780 0 : }
781 :
782 : /*
783 : * shutdown the pipe
784 : */
785 : void
786 0 : pipeclose(struct pipe *cpipe)
787 : {
788 : struct pipe *ppipe;
789 0 : if (cpipe) {
790 0 : pipeselwakeup(cpipe);
791 :
792 : /*
793 : * If the other side is blocked, wake it up saying that
794 : * we want to close it down.
795 : */
796 0 : cpipe->pipe_state |= PIPE_EOF;
797 0 : while (cpipe->pipe_busy) {
798 0 : wakeup(cpipe);
799 0 : cpipe->pipe_state |= PIPE_WANT;
800 0 : tsleep(cpipe, PRIBIO, "pipecl", 0);
801 : }
802 :
803 : /*
804 : * Disconnect from peer
805 : */
806 0 : if ((ppipe = cpipe->pipe_peer) != NULL) {
807 0 : pipeselwakeup(ppipe);
808 :
809 0 : ppipe->pipe_state |= PIPE_EOF;
810 0 : wakeup(ppipe);
811 0 : ppipe->pipe_peer = NULL;
812 0 : }
813 :
814 : /*
815 : * free resources
816 : */
817 0 : pipe_free_kmem(cpipe);
818 0 : pool_put(&pipe_pool, cpipe);
819 0 : }
820 0 : }
821 :
822 : int
823 0 : pipe_kqfilter(struct file *fp, struct knote *kn)
824 : {
825 0 : struct pipe *rpipe = kn->kn_fp->f_data;
826 0 : struct pipe *wpipe = rpipe->pipe_peer;
827 :
828 0 : switch (kn->kn_filter) {
829 : case EVFILT_READ:
830 0 : kn->kn_fop = &pipe_rfiltops;
831 0 : SLIST_INSERT_HEAD(&rpipe->pipe_sel.si_note, kn, kn_selnext);
832 0 : break;
833 : case EVFILT_WRITE:
834 0 : if (wpipe == NULL) {
835 : /* other end of pipe has been closed */
836 0 : return (EPIPE);
837 : }
838 0 : kn->kn_fop = &pipe_wfiltops;
839 0 : SLIST_INSERT_HEAD(&wpipe->pipe_sel.si_note, kn, kn_selnext);
840 0 : break;
841 : default:
842 0 : return (EINVAL);
843 : }
844 :
845 0 : return (0);
846 0 : }
847 :
848 : void
849 0 : filt_pipedetach(struct knote *kn)
850 : {
851 0 : struct pipe *rpipe = kn->kn_fp->f_data;
852 0 : struct pipe *wpipe = rpipe->pipe_peer;
853 :
854 0 : switch (kn->kn_filter) {
855 : case EVFILT_READ:
856 0 : SLIST_REMOVE(&rpipe->pipe_sel.si_note, kn, knote, kn_selnext);
857 0 : break;
858 : case EVFILT_WRITE:
859 0 : if (wpipe == NULL)
860 0 : return;
861 0 : SLIST_REMOVE(&wpipe->pipe_sel.si_note, kn, knote, kn_selnext);
862 0 : break;
863 : }
864 0 : }
865 :
866 : int
867 0 : filt_piperead(struct knote *kn, long hint)
868 : {
869 0 : struct pipe *rpipe = kn->kn_fp->f_data;
870 0 : struct pipe *wpipe = rpipe->pipe_peer;
871 :
872 0 : kn->kn_data = rpipe->pipe_buffer.cnt;
873 :
874 0 : if ((rpipe->pipe_state & PIPE_EOF) ||
875 0 : (wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
876 0 : kn->kn_flags |= EV_EOF;
877 0 : return (1);
878 : }
879 0 : return (kn->kn_data > 0);
880 0 : }
881 :
882 : int
883 0 : filt_pipewrite(struct knote *kn, long hint)
884 : {
885 0 : struct pipe *rpipe = kn->kn_fp->f_data;
886 0 : struct pipe *wpipe = rpipe->pipe_peer;
887 :
888 0 : if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
889 0 : kn->kn_data = 0;
890 0 : kn->kn_flags |= EV_EOF;
891 0 : return (1);
892 : }
893 0 : kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
894 :
895 0 : return (kn->kn_data >= PIPE_BUF);
896 0 : }
897 :
898 : void
899 0 : pipe_init(void)
900 : {
901 0 : pool_init(&pipe_pool, sizeof(struct pipe), 0, IPL_MPFLOOR, PR_WAITOK,
902 : "pipepl", NULL);
903 0 : }
904 :
|