xref: /dragonfly/sys/vfs/fifofs/fifo_vnops.c (revision 22db36083bc98aa8a7876ca8e7811e6a33362f59)
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