1 /*
2 * Copyright (c) 1990, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29 /*
30 * Filesystem FIFO type ops. All entry points are MPSAFE.
31 */
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/unistd.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/malloc.h>
38 #include <sys/vnode.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/filio.h>
42 #include <sys/fcntl.h>
43 #include <sys/file.h>
44 #include <sys/event.h>
45 #include <sys/un.h>
46
47 #include <sys/socketvar2.h>
48
49 #include "fifo.h"
50
51 /*
52 * This structure is associated with the FIFO vnode and stores
53 * the state associated with the FIFO.
54 */
55 struct fifoinfo {
56 struct socket *fi_readsock;
57 struct socket *fi_writesock;
58 long fi_readers;
59 long fi_writers;
60 };
61
62 #define FIFO_LOCK_POOL 128
63 #define FIFO_LOCK_MASK (FIFO_LOCK_POOL - 1)
64
65 static int fifo_badop (void);
66 static int fifo_print (struct vop_print_args *);
67 static int fifo_lookup (struct vop_old_lookup_args *);
68 static int fifo_open (struct vop_open_args *);
69 static int fifo_close (struct vop_close_args *);
70 static int fifo_read (struct vop_read_args *);
71 static int fifo_write (struct vop_write_args *);
72 static int fifo_ioctl (struct vop_ioctl_args *);
73 static int fifo_kqfilter (struct vop_kqfilter_args *);
74 static int fifo_inactive (struct vop_inactive_args *);
75 static int fifo_bmap (struct vop_bmap_args *);
76 static int fifo_pathconf (struct vop_pathconf_args *);
77 static int fifo_advlock (struct vop_advlock_args *);
78
79 static void filt_fifordetach(struct knote *kn);
80 static int filt_fiforead(struct knote *kn, long hint);
81 static void filt_fifowdetach(struct knote *kn);
82 static int filt_fifowrite(struct knote *kn, long hint);
83
84 static struct filterops fiforead_filtops =
85 { FILTEROP_ISFD, NULL, filt_fifordetach, filt_fiforead };
86 static struct filterops fifowrite_filtops =
87 { FILTEROP_ISFD, NULL, filt_fifowdetach, filt_fifowrite };
88
89 struct vop_ops fifo_vnode_vops = {
90 .vop_default = vop_defaultop,
91 .vop_access = (void *)vop_ebadf,
92 .vop_advlock = fifo_advlock,
93 .vop_bmap = fifo_bmap,
94 .vop_close = fifo_close,
95 .vop_old_create = (void *)fifo_badop,
96 .vop_getattr = (void *)vop_ebadf,
97 .vop_inactive = fifo_inactive,
98 .vop_ioctl = fifo_ioctl,
99 .vop_kqfilter = fifo_kqfilter,
100 .vop_old_link = (void *)fifo_badop,
101 .vop_old_lookup = fifo_lookup,
102 .vop_old_mkdir = (void *)fifo_badop,
103 .vop_old_mknod = (void *)fifo_badop,
104 .vop_open = fifo_open,
105 .vop_pathconf = fifo_pathconf,
106 .vop_print = fifo_print,
107 .vop_read = fifo_read,
108 .vop_readdir = (void *)fifo_badop,
109 .vop_readlink = (void *)fifo_badop,
110 .vop_reallocblks = (void *)fifo_badop,
111 .vop_reclaim = (void *)vop_null,
112 .vop_old_remove = (void *)fifo_badop,
113 .vop_old_rename = (void *)fifo_badop,
114 .vop_old_rmdir = (void *)fifo_badop,
115 .vop_setattr = (void *)vop_ebadf,
116 .vop_old_symlink = (void *)fifo_badop,
117 .vop_write = fifo_write
118 };
119
120 VNODEOP_SET(fifo_vnode_vops);
121
122 static MALLOC_DEFINE(M_FIFOINFO, "Fifo info", "Fifo info entries");
123
124 /*
125 * The vnode might be using a shared lock, we need an exclusive lock
126 * for open/close sequencing. Create a little pool of locks.
127 */
128 static struct lock fifo_locks[FIFO_LOCK_POOL];
129
130 static __inline
131 void
fifo_lock(struct vnode * vp)132 fifo_lock(struct vnode *vp)
133 {
134 int hv;
135
136 hv = ((intptr_t)vp / sizeof(*vp)) & FIFO_LOCK_MASK;
137 lockmgr(&fifo_locks[hv], LK_EXCLUSIVE);
138 }
139
140 static __inline
141 void
fifo_unlock(struct vnode * vp)142 fifo_unlock(struct vnode *vp)
143 {
144 int hv;
145
146 hv = ((intptr_t)vp / sizeof(*vp)) & FIFO_LOCK_MASK;
147 lockmgr(&fifo_locks[hv], LK_RELEASE);
148 }
149
150 static void
fifo_init(void)151 fifo_init(void)
152 {
153 int i;
154
155 for (i = 0; i < FIFO_LOCK_POOL; ++i)
156 lockinit(&fifo_locks[i], "fifolk", 0, 0);
157 }
158 SYSINIT(fifoinit, SI_SUB_PSEUDO, SI_ORDER_ANY, fifo_init, NULL);
159
160 /*
161 * fifo_vnoperate()
162 */
163 int
fifo_vnoperate(struct vop_generic_args * ap)164 fifo_vnoperate(struct vop_generic_args *ap)
165 {
166 return (VOCALL(&fifo_vnode_vops, ap));
167 }
168
169 /*
170 * Trivial lookup routine that always fails.
171 *
172 * fifo_lookup(struct vnode *a_dvp, struct vnode **a_vpp,
173 * struct componentname *a_cnp)
174 */
175 /* ARGSUSED */
176 static int
fifo_lookup(struct vop_old_lookup_args * ap)177 fifo_lookup(struct vop_old_lookup_args *ap)
178 {
179 *ap->a_vpp = NULL;
180 return (ENOTDIR);
181 }
182
183 /*
184 * Create/destroy the socket pairs for the fifo
185 */
186 static
187 struct fifoinfo *
fifo_fip_create(int * errorp)188 fifo_fip_create(int *errorp)
189 {
190 struct thread *td = curthread;
191 struct fifoinfo *fip;
192 struct socket *rso, *wso;
193
194 fip = kmalloc(sizeof(*fip), M_FIFOINFO, M_WAITOK);
195 *errorp = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, td);
196 if (*errorp) {
197 kfree(fip, M_FIFOINFO);
198 return NULL;
199 }
200 rso->so_options &= ~SO_LINGER;
201 fip->fi_readsock = rso;
202 *errorp = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, td);
203 if (*errorp) {
204 soclose(rso, FNONBLOCK);
205 kfree(fip, M_FIFOINFO);
206 return NULL;
207 }
208 wso->so_options &= ~SO_LINGER;
209 fip->fi_writesock = wso;
210 *errorp = unp_connect2(wso, rso, td->td_ucred);
211 if (*errorp) {
212 soclose(wso, FNONBLOCK);
213 soclose(rso, FNONBLOCK);
214 kfree(fip, M_FIFOINFO);
215 return NULL;
216 }
217 fip->fi_readers = fip->fi_writers = 0;
218 wso->so_snd.ssb_lowat = PIPE_BUF;
219 sosetstate(rso, SS_CANTRCVMORE);
220
221 return fip;
222 }
223
224 static int
fifo_fip_destroy(struct fifoinfo * fip)225 fifo_fip_destroy(struct fifoinfo *fip)
226 {
227 int error1, error;
228
229 error1 = soclose(fip->fi_readsock, FNONBLOCK);
230 error = soclose(fip->fi_writesock, FNONBLOCK);
231 kfree(fip, M_FIFOINFO);
232 if (error1)
233 error = error1;
234 return error;
235 }
236
237 /*
238 * Open called to set up a new instance of a fifo or
239 * to find an active instance of a fifo.
240 *
241 * fifo_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
242 * struct file *a_fp)
243 */
244 /* ARGSUSED */
245 static int
fifo_open(struct vop_open_args * ap)246 fifo_open(struct vop_open_args *ap)
247 {
248 struct vnode *vp = ap->a_vp;
249 struct fifoinfo *fip;
250 int error;
251
252 error = 0;
253
254 /*
255 * Create the fip if necessary
256 */
257 fifo_lock(vp);
258 if ((fip = vp->v_fifoinfo) == NULL) {
259 fip = fifo_fip_create(&error);
260 if (fip == NULL) {
261 fifo_unlock(vp);
262 return error;
263 }
264 vp->v_fifoinfo = fip;
265 }
266
267 /*
268 * Adjust fi_readers and fi_writers interlocked and issue wakeups
269 * as appropriate.
270 */
271 if (ap->a_mode & FREAD) {
272 fip->fi_readers++;
273 if (fip->fi_readers == 1) {
274 soisreconnected(fip->fi_writesock);
275 if (fip->fi_writers > 0) {
276 wakeup((caddr_t)&fip->fi_writers);
277 sowwakeup(fip->fi_writesock);
278 }
279 }
280 }
281 if (ap->a_mode & FWRITE) {
282 fip->fi_writers++;
283 if (fip->fi_writers == 1) {
284 soisreconnected(fip->fi_readsock);
285 if (fip->fi_readers > 0) {
286 wakeup((caddr_t)&fip->fi_readers);
287 sorwakeup(fip->fi_writesock);
288 }
289 }
290 }
291
292 /*
293 * Handle blocking as appropriate
294 */
295 if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
296 if (fip->fi_writers == 0) {
297 fifo_unlock(vp);
298 vn_unlock(vp);
299 error = tsleep((caddr_t)&fip->fi_readers,
300 PCATCH, "fifoor", 0);
301 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
302 fifo_lock(vp);
303 if (error)
304 goto bad;
305 /*
306 * We must have got woken up because we had a writer.
307 * That (and not still having one) is the condition
308 * that we must wait for.
309 */
310 }
311 }
312 if (ap->a_mode & FWRITE) {
313 if (ap->a_mode & O_NONBLOCK) {
314 if (fip->fi_readers == 0) {
315 error = ENXIO;
316 goto bad;
317 }
318 } else {
319 if (fip->fi_readers == 0) {
320 fifo_unlock(vp);
321 vn_unlock(vp);
322 error = tsleep((caddr_t)&fip->fi_writers,
323 PCATCH, "fifoow", 0);
324 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
325 fifo_lock(vp);
326 if (error)
327 goto bad;
328 /*
329 * We must have got woken up because we had
330 * a reader. That (and not still having one)
331 * is the condition that we must wait for.
332 */
333 }
334 }
335 }
336 vsetflags(vp, VNOTSEEKABLE);
337 error = vop_stdopen(ap);
338 fifo_unlock(vp);
339
340 return (error);
341
342 bad:
343 if (ap->a_mode & FREAD) {
344 fip->fi_readers--;
345 if (fip->fi_readers == 0)
346 soisdisconnected(fip->fi_writesock);
347 }
348 if (ap->a_mode & FWRITE) {
349 fip->fi_writers--;
350 if (fip->fi_writers == 0)
351 soisdisconnected(fip->fi_readsock);
352 }
353 if (fip->fi_readers == 0 && fip->fi_writers == 0) {
354 vp->v_fifoinfo = NULL;
355 (void)fifo_fip_destroy(fip);
356 }
357 fifo_unlock(vp);
358
359 return (error);
360 }
361
362 /*
363 * Vnode op for read
364 *
365 * fifo_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
366 * struct ucred *a_cred)
367 */
368 /* ARGSUSED */
369 static int
fifo_read(struct vop_read_args * ap)370 fifo_read(struct vop_read_args *ap)
371 {
372 struct uio *uio = ap->a_uio;
373 struct vnode *vp = ap->a_vp;
374 struct socket *rso = vp->v_fifoinfo->fi_readsock;
375 int error;
376 int flags;
377
378 #ifdef DIAGNOSTIC
379 if (uio->uio_rw != UIO_READ)
380 panic("fifo_read mode");
381 #endif
382 if (uio->uio_resid == 0)
383 return (0);
384 if (ap->a_ioflag & IO_NDELAY)
385 flags = MSG_FNONBLOCKING;
386 else
387 flags = 0;
388 vn_unlock(vp);
389 lwkt_gettoken(&vp->v_token);
390 error = soreceive(rso, NULL, uio, NULL, NULL, &flags);
391 lwkt_reltoken(&vp->v_token);
392 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
393 return (error);
394 }
395
396 /*
397 * Vnode op for write
398 *
399 * fifo_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
400 * struct ucred *a_cred)
401 */
402 /* ARGSUSED */
403 static int
fifo_write(struct vop_write_args * ap)404 fifo_write(struct vop_write_args *ap)
405 {
406 struct thread *td = ap->a_uio->uio_td;
407 struct vnode *vp = ap->a_vp;
408 struct socket *wso = vp->v_fifoinfo->fi_writesock;
409 int error;
410 int flags;
411
412 #ifdef DIAGNOSTIC
413 if (ap->a_uio->uio_rw != UIO_WRITE)
414 panic("fifo_write mode");
415 #endif
416 if (ap->a_ioflag & IO_NDELAY)
417 flags = MSG_FNONBLOCKING;
418 else
419 flags = 0;
420 vn_unlock(vp);
421 lwkt_gettoken(&vp->v_token);
422 error = sosend(wso, NULL, ap->a_uio, 0, NULL, flags, td);
423 lwkt_reltoken(&vp->v_token);
424 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
425 return (error);
426 }
427
428 /*
429 * Device ioctl operation.
430 *
431 * fifo_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data, int a_fflag,
432 * struct ucred *a_cred, struct sysmsg *a_sysmsg)
433 */
434 /* ARGSUSED */
435 static int
fifo_ioctl(struct vop_ioctl_args * ap)436 fifo_ioctl(struct vop_ioctl_args *ap)
437 {
438 struct file filetmp; /* Local */
439 struct vnode *vp = ap->a_vp;
440 int error;
441
442 if (ap->a_fflag & FREAD) {
443 filetmp.f_data = vp->v_fifoinfo->fi_readsock;
444 lwkt_gettoken(&vp->v_token);
445 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data,
446 ap->a_cred, ap->a_sysmsg);
447 lwkt_reltoken(&vp->v_token);
448 if (error)
449 return (error);
450 }
451 if (ap->a_fflag & FWRITE) {
452 filetmp.f_data = vp->v_fifoinfo->fi_writesock;
453 lwkt_gettoken(&vp->v_token);
454 error = soo_ioctl(&filetmp, ap->a_command, ap->a_data,
455 ap->a_cred, ap->a_sysmsg);
456 lwkt_reltoken(&vp->v_token);
457 if (error)
458 return (error);
459 }
460 return (0);
461 }
462
463 /*
464 * fifo_kqfilter(struct vnode *a_vp, struct knote *a_kn)
465 */
466 /* ARGSUSED */
467 static int
fifo_kqfilter(struct vop_kqfilter_args * ap)468 fifo_kqfilter(struct vop_kqfilter_args *ap)
469 {
470 struct vnode *vp = ap->a_vp;
471 struct fifoinfo *fi = vp->v_fifoinfo;
472 struct socket *so;
473 struct signalsockbuf *ssb;
474
475 lwkt_gettoken(&vp->v_token);
476
477 switch (ap->a_kn->kn_filter) {
478 case EVFILT_READ:
479 ap->a_kn->kn_fop = &fiforead_filtops;
480 so = fi->fi_readsock;
481 ssb = &so->so_rcv;
482 break;
483 case EVFILT_WRITE:
484 ap->a_kn->kn_fop = &fifowrite_filtops;
485 so = fi->fi_writesock;
486 ssb = &so->so_snd;
487 break;
488 default:
489 lwkt_reltoken(&vp->v_token);
490 return (EOPNOTSUPP);
491 }
492
493 ap->a_kn->kn_hook = (caddr_t)vp;
494 ssb_insert_knote(ssb, ap->a_kn);
495
496 lwkt_reltoken(&vp->v_token);
497 return (0);
498 }
499
500 static void
filt_fifordetach(struct knote * kn)501 filt_fifordetach(struct knote *kn)
502 {
503 struct vnode *vp = (void *)kn->kn_hook;
504 struct socket *so = vp->v_fifoinfo->fi_readsock;
505
506 lwkt_gettoken(&vp->v_token);
507 ssb_remove_knote(&so->so_rcv, kn);
508 lwkt_reltoken(&vp->v_token);
509 }
510
511 static int
filt_fiforead(struct knote * kn,long hint)512 filt_fiforead(struct knote *kn, long hint)
513 {
514 struct vnode *vp = (void *)kn->kn_hook;
515 struct socket *so = vp->v_fifoinfo->fi_readsock;
516
517 lwkt_gettoken(&vp->v_token);
518 kn->kn_data = so->so_rcv.ssb_cc;
519 if ((kn->kn_sfflags & NOTE_OLDAPI) == 0 &&
520 so->so_state & SS_ISDISCONNECTED) {
521 if (kn->kn_data == 0)
522 kn->kn_flags |= EV_NODATA;
523 kn->kn_flags |= EV_EOF | EV_HUP;
524 lwkt_reltoken(&vp->v_token);
525 return (1);
526 }
527 kn->kn_flags &= ~(EV_EOF | EV_HUP | EV_NODATA);
528 lwkt_reltoken(&vp->v_token);
529 if ((kn->kn_sfflags & NOTE_HUPONLY) == 0)
530 return (kn->kn_data > 0);
531 return 0;
532 }
533
534 static void
filt_fifowdetach(struct knote * kn)535 filt_fifowdetach(struct knote *kn)
536 {
537 struct vnode *vp = (void *)kn->kn_hook;
538 struct socket *so = vp->v_fifoinfo->fi_writesock;
539
540 lwkt_gettoken(&vp->v_token);
541 ssb_remove_knote(&so->so_snd, kn);
542 lwkt_reltoken(&vp->v_token);
543 }
544
545 static int
filt_fifowrite(struct knote * kn,long hint)546 filt_fifowrite(struct knote *kn, long hint)
547 {
548 struct vnode *vp = (void *)kn->kn_hook;
549 struct socket *so = vp->v_fifoinfo->fi_writesock;
550
551 lwkt_gettoken(&vp->v_token);
552 kn->kn_data = ssb_space(&so->so_snd);
553 if (so->so_state & SS_ISDISCONNECTED) {
554 kn->kn_flags |= EV_EOF | EV_HUP | EV_NODATA;
555 lwkt_reltoken(&vp->v_token);
556 return (1);
557 }
558 kn->kn_flags &= ~(EV_EOF | EV_HUP | EV_NODATA);
559 lwkt_reltoken(&vp->v_token);
560 return (kn->kn_data >= so->so_snd.ssb_lowat);
561 }
562
563 /*
564 * fifo_inactive(struct vnode *a_vp)
565 */
566 static int
fifo_inactive(struct vop_inactive_args * ap)567 fifo_inactive(struct vop_inactive_args *ap)
568 {
569 return (0);
570 }
571
572 /*
573 * This is a noop, simply returning what one has been given.
574 *
575 * fifo_bmap(struct vnode *a_vp, off_t a_loffset,
576 * off_t *a_doffsetp, int *a_runp, int *a_runb)
577 */
578 static int
fifo_bmap(struct vop_bmap_args * ap)579 fifo_bmap(struct vop_bmap_args *ap)
580 {
581 if (ap->a_doffsetp != NULL)
582 *ap->a_doffsetp = ap->a_loffset;
583 if (ap->a_runp != NULL)
584 *ap->a_runp = 0;
585 if (ap->a_runb != NULL)
586 *ap->a_runb = 0;
587 return (0);
588 }
589
590 /*
591 * Device close routine
592 *
593 * fifo_close(struct vnode *a_vp, int a_fflag)
594 */
595 /* ARGSUSED */
596 static int
fifo_close(struct vop_close_args * ap)597 fifo_close(struct vop_close_args *ap)
598 {
599 struct vnode *vp = ap->a_vp;
600 struct fifoinfo *fip;
601 int error;
602
603 fifo_lock(vp);
604 fip = vp->v_fifoinfo;
605 if (fip == NULL) {
606 vop_stdclose(ap);
607 fifo_unlock(vp);
608 return 0;
609 }
610 if (ap->a_fflag & FREAD) {
611 fip->fi_readers--;
612 if (fip->fi_readers == 0)
613 soisdisconnected(fip->fi_writesock);
614 }
615 if (ap->a_fflag & FWRITE) {
616 fip->fi_writers--;
617 if (fip->fi_writers == 0)
618 soisdisconnected(fip->fi_readsock);
619 }
620 if (fip->fi_readers == 0 && fip->fi_writers == 0) {
621 vp->v_fifoinfo = NULL;
622 error = fifo_fip_destroy(fip);
623 } else {
624 error = 0;
625 }
626 vop_stdclose(ap);
627 fifo_unlock(vp);
628
629 return error;
630 }
631
632 /*
633 * Print out internal contents of a fifo vnode.
634 */
635 int
fifo_printinfo(struct vnode * vp)636 fifo_printinfo(struct vnode *vp)
637 {
638 struct fifoinfo *fip = vp->v_fifoinfo;
639
640 kprintf(", fifo with %ld readers and %ld writers",
641 fip->fi_readers, fip->fi_writers);
642 return (0);
643 }
644
645 /*
646 * Print out the contents of a fifo vnode.
647 *
648 * fifo_print(struct vnode *a_vp)
649 */
650 static int
fifo_print(struct vop_print_args * ap)651 fifo_print(struct vop_print_args *ap)
652 {
653 kprintf("tag VT_NON");
654 fifo_printinfo(ap->a_vp);
655 kprintf("\n");
656 return (0);
657 }
658
659 /*
660 * Return POSIX pathconf information applicable to fifo's.
661 *
662 * fifo_pathconf(struct vnode *a_vp, int a_name, int *a_retval)
663 */
664 int
fifo_pathconf(struct vop_pathconf_args * ap)665 fifo_pathconf(struct vop_pathconf_args *ap)
666 {
667 switch (ap->a_name) {
668 case _PC_LINK_MAX:
669 *ap->a_retval = LINK_MAX;
670 return (0);
671 case _PC_PIPE_BUF:
672 *ap->a_retval = PIPE_BUF;
673 return (0);
674 case _PC_CHOWN_RESTRICTED:
675 *ap->a_retval = 1;
676 return (0);
677 default:
678 return (EINVAL);
679 }
680 /* NOTREACHED */
681 }
682
683 /*
684 * Fifo advisory byte-level locks.
685 *
686 * fifo_advlock(struct vnode *a_vp, caddr_t a_id, int a_op, struct flock *a_fl,
687 * int a_flags)
688 */
689 /* ARGSUSED */
690 static int
fifo_advlock(struct vop_advlock_args * ap)691 fifo_advlock(struct vop_advlock_args *ap)
692 {
693 return ((ap->a_flags & F_POSIX) ? EINVAL : EOPNOTSUPP);
694 }
695
696 /*
697 * Fifo bad operation
698 */
699 static int
fifo_badop(void)700 fifo_badop(void)
701 {
702 panic("fifo_badop called");
703 /* NOTREACHED */
704 }
705