st_blocks is a quad
[unix-history] / usr / src / sys / miscfs / fifofs / fifo_vnops.c
CommitLineData
cc6b488e
KM
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
dbf0c423 5 * %sccs.include.redist.c%
cc6b488e 6 *
e1b76915 7 * @(#)fifo_vnops.c 7.14 (Berkeley) %G%
cc6b488e
KM
8 */
9
10#include "param.h"
063b2136 11#include "proc.h"
cc6b488e
KM
12#include "time.h"
13#include "namei.h"
14#include "vnode.h"
15#include "socket.h"
16#include "socketvar.h"
17#include "stat.h"
8429d022 18#include "systm.h"
cc6b488e
KM
19#include "ioctl.h"
20#include "file.h"
81b4c293 21#include "fifo.h"
cc6b488e
KM
22#include "errno.h"
23#include "malloc.h"
24
25/*
26 * This structure is associated with the FIFO vnode and stores
27 * the state associated with the FIFO.
28 */
29struct fifoinfo {
30 struct socket *fi_readsock;
31 struct socket *fi_writesock;
32 long fi_readers;
33 long fi_writers;
34};
35
9342689a
JH
36int (**fifo_vnodeop_p)();
37struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
38 { &vop_default_desc, vn_default_error },
39 { &vop_lookup_desc, fifo_lookup }, /* lookup */
40 { &vop_create_desc, fifo_create }, /* create */
41 { &vop_mknod_desc, fifo_mknod }, /* mknod */
42 { &vop_open_desc, fifo_open }, /* open */
43 { &vop_close_desc, fifo_close }, /* close */
44 { &vop_access_desc, fifo_access }, /* access */
45 { &vop_getattr_desc, fifo_getattr }, /* getattr */
46 { &vop_setattr_desc, fifo_setattr }, /* setattr */
47 { &vop_read_desc, fifo_read }, /* read */
48 { &vop_write_desc, fifo_write }, /* write */
49 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */
50 { &vop_select_desc, fifo_select }, /* select */
51 { &vop_mmap_desc, fifo_mmap }, /* mmap */
52 { &vop_fsync_desc, fifo_fsync }, /* fsync */
53 { &vop_seek_desc, fifo_seek }, /* seek */
54 { &vop_remove_desc, fifo_remove }, /* remove */
55 { &vop_link_desc, fifo_link }, /* link */
56 { &vop_rename_desc, fifo_rename }, /* rename */
57 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */
58 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */
59 { &vop_symlink_desc, fifo_symlink }, /* symlink */
60 { &vop_readdir_desc, fifo_readdir }, /* readdir */
61 { &vop_readlink_desc, fifo_readlink }, /* readlink */
62 { &vop_abortop_desc, fifo_abortop }, /* abortop */
63 { &vop_inactive_desc, fifo_inactive }, /* inactive */
64 { &vop_reclaim_desc, fifo_reclaim }, /* reclaim */
65 { &vop_lock_desc, fifo_lock }, /* lock */
66 { &vop_unlock_desc, fifo_unlock }, /* unlock */
67 { &vop_bmap_desc, fifo_bmap }, /* bmap */
68 { &vop_strategy_desc, fifo_strategy }, /* strategy */
69 { &vop_print_desc, fifo_print }, /* print */
70 { &vop_islocked_desc, fifo_islocked }, /* islocked */
71 { &vop_advlock_desc, fifo_advlock }, /* advlock */
72 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */
73 { &vop_vget_desc, fifo_vget }, /* vget */
74 { &vop_valloc_desc, fifo_valloc }, /* valloc */
75 { &vop_vfree_desc, fifo_vfree }, /* vfree */
76 { &vop_truncate_desc, fifo_truncate }, /* truncate */
77 { &vop_update_desc, fifo_update }, /* update */
78 { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */
79 { (struct vnodeop_desc*)NULL, (int(*)())NULL }
cc6b488e 80};
9342689a
JH
81struct vnodeopv_desc fifo_vnodeop_opv_desc =
82 { &fifo_vnodeop_p, fifo_vnodeop_entries };
cc6b488e
KM
83
84/*
85 * Trivial lookup routine that always fails.
86 */
81b4c293 87/* ARGSUSED */
9342689a
JH
88fifo_lookup (ap)
89 struct vop_lookup_args *ap;
cc6b488e 90{
085e9ab7 91
e1b76915 92 *ap->a_vpp = NULL;
cc6b488e
KM
93 return (ENOTDIR);
94}
95
96/*
97 * Open called to set up a new instance of a fifo or
98 * to find an active instance of a fifo.
99 */
100/* ARGSUSED */
9342689a
JH
101fifo_open (ap)
102 struct vop_open_args *ap;
cc6b488e 103{
9342689a
JH
104 USES_VOP_CLOSE;
105 USES_VOP_LOCK;
106 USES_VOP_UNLOCK;
cc6b488e
KM
107 register struct fifoinfo *fip;
108 struct socket *rso, *wso;
109 int error;
bcc829cc 110 static char openstr[] = "fifo";
cc6b488e 111
e1b76915 112 if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE))
cc6b488e 113 return (EINVAL);
e1b76915 114 if ((fip = ap->a_vp->v_fifoinfo) == NULL) {
cc6b488e 115 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
e1b76915 116 ap->a_vp->v_fifoinfo = fip;
ed89f575
KM
117 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) {
118 free(fip, M_VNODE);
e1b76915 119 ap->a_vp->v_fifoinfo = NULL;
cc6b488e 120 return (error);
ed89f575 121 }
cc6b488e
KM
122 fip->fi_readsock = rso;
123 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) {
124 (void)soclose(rso);
ed89f575 125 free(fip, M_VNODE);
e1b76915 126 ap->a_vp->v_fifoinfo = NULL;
cc6b488e
KM
127 return (error);
128 }
129 fip->fi_writesock = wso;
130 if (error = unp_connect2(wso, rso)) {
131 (void)soclose(wso);
132 (void)soclose(rso);
ed89f575 133 free(fip, M_VNODE);
e1b76915 134 ap->a_vp->v_fifoinfo = NULL;
cc6b488e
KM
135 return (error);
136 }
80c4c463 137 fip->fi_readers = fip->fi_writers = 0;
cc6b488e
KM
138 wso->so_state |= SS_CANTRCVMORE;
139 rso->so_state |= SS_CANTSENDMORE;
140 }
141 error = 0;
e1b76915 142 if (ap->a_mode & FREAD) {
cc6b488e
KM
143 fip->fi_readers++;
144 if (fip->fi_readers == 1) {
145 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
146 if (fip->fi_writers > 0)
147 wakeup((caddr_t)&fip->fi_writers);
148 }
e1b76915 149 if (ap->a_mode & O_NONBLOCK)
cc6b488e 150 return (0);
80c4c463 151 while (fip->fi_writers == 0) {
e1b76915 152 VOP_UNLOCK(ap->a_vp);
80c4c463
KM
153 error = tsleep((caddr_t)&fip->fi_readers, PSOCK,
154 openstr, 0);
e1b76915 155 VOP_LOCK(ap->a_vp);
80c4c463 156 if (error)
cc6b488e 157 break;
80c4c463 158 }
cc6b488e
KM
159 } else {
160 fip->fi_writers++;
e1b76915 161 if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) {
cc6b488e
KM
162 error = ENXIO;
163 } else {
164 if (fip->fi_writers == 1) {
165 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
166 if (fip->fi_readers > 0)
167 wakeup((caddr_t)&fip->fi_readers);
168 }
80c4c463 169 while (fip->fi_readers == 0) {
e1b76915 170 VOP_UNLOCK(ap->a_vp);
80c4c463
KM
171 error = tsleep((caddr_t)&fip->fi_writers,
172 PSOCK, openstr, 0);
e1b76915 173 VOP_LOCK(ap->a_vp);
80c4c463 174 if (error)
cc6b488e 175 break;
80c4c463 176 }
cc6b488e
KM
177 }
178 }
179 if (error)
e1b76915 180 VOP_CLOSE(ap->a_vp, ap->a_mode, ap->a_cred, ap->a_p);
cc6b488e
KM
181 return (error);
182}
183
184/*
185 * Vnode op for read
186 */
187/* ARGSUSED */
9342689a
JH
188fifo_read (ap)
189 struct vop_read_args *ap;
cc6b488e 190{
9342689a
JH
191 USES_VOP_LOCK;
192 USES_VOP_UNLOCK;
e1b76915 193 register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
cc6b488e
KM
194 int error, startresid;
195
81b4c293 196#ifdef DIAGNOSTIC
e1b76915 197 if (ap->a_uio->uio_rw != UIO_READ)
cc6b488e 198 panic("fifo_read mode");
81b4c293 199#endif
e1b76915 200 if (ap->a_uio->uio_resid == 0)
cc6b488e 201 return (0);
e1b76915 202 if (ap->a_ioflag & IO_NDELAY)
cc6b488e 203 rso->so_state |= SS_NBIO;
e1b76915
JH
204 startresid = ap->a_uio->uio_resid;
205 VOP_UNLOCK(ap->a_vp);
206 error = soreceive(rso, (struct mbuf **)0, ap->a_uio, (int *)0,
cc6b488e 207 (struct mbuf **)0, (struct mbuf **)0);
e1b76915 208 VOP_LOCK(ap->a_vp);
cc6b488e
KM
209 /*
210 * Clear EOF indication after first such return.
211 */
e1b76915 212 if (ap->a_uio->uio_resid == startresid)
cc6b488e 213 rso->so_state &= ~SS_CANTRCVMORE;
e1b76915 214 if (ap->a_ioflag & IO_NDELAY)
cc6b488e
KM
215 rso->so_state &= ~SS_NBIO;
216 return (error);
217}
218
219/*
220 * Vnode op for write
221 */
222/* ARGSUSED */
9342689a
JH
223fifo_write (ap)
224 struct vop_write_args *ap;
cc6b488e 225{
9342689a
JH
226 USES_VOP_LOCK;
227 USES_VOP_UNLOCK;
e1b76915 228 struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
cc6b488e
KM
229 int error;
230
81b4c293 231#ifdef DIAGNOSTIC
e1b76915 232 if (ap->a_uio->uio_rw != UIO_WRITE)
cc6b488e 233 panic("fifo_write mode");
81b4c293 234#endif
e1b76915 235 if (ap->a_ioflag & IO_NDELAY)
cc6b488e 236 wso->so_state |= SS_NBIO;
e1b76915
JH
237 VOP_UNLOCK(ap->a_vp);
238 error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0);
239 VOP_LOCK(ap->a_vp);
240 if (ap->a_ioflag & IO_NDELAY)
cc6b488e
KM
241 wso->so_state &= ~SS_NBIO;
242 return (error);
243}
244
245/*
246 * Device ioctl operation.
247 */
248/* ARGSUSED */
9342689a
JH
249fifo_ioctl (ap)
250 struct vop_ioctl_args *ap;
cc6b488e
KM
251{
252 struct file filetmp;
253 int error;
254
e1b76915 255 if (ap->a_command == FIONBIO)
cc6b488e 256 return (0);
e1b76915
JH
257 if (ap->a_fflag & FREAD)
258 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
cc6b488e 259 else
e1b76915
JH
260 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
261 return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p));
cc6b488e
KM
262}
263
264/* ARGSUSED */
9342689a
JH
265fifo_select (ap)
266 struct vop_select_args *ap;
cc6b488e
KM
267{
268 struct file filetmp;
269 int error;
270
e1b76915
JH
271 if (ap->a_fflags & FREAD)
272 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
cc6b488e 273 else
e1b76915
JH
274 filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
275 return (soo_select(&filetmp, ap->a_which, ap->a_p));
cc6b488e
KM
276}
277
278/*
279 * This is a noop, simply returning what one has been given.
280 */
9342689a
JH
281fifo_bmap (ap)
282 struct vop_bmap_args *ap;
cc6b488e
KM
283{
284
e1b76915
JH
285 if (ap->a_vpp != NULL)
286 *ap->a_vpp = ap->a_vp;
287 if (ap->a_bnp != NULL)
288 *ap->a_bnp = ap->a_bn;
cc6b488e
KM
289 return (0);
290}
291
292/*
293 * At the moment we do not do any locking.
294 */
295/* ARGSUSED */
9342689a
JH
296fifo_lock (ap)
297 struct vop_lock_args *ap;
cc6b488e
KM
298{
299
300 return (0);
301}
302
303/* ARGSUSED */
9342689a
JH
304fifo_unlock (ap)
305 struct vop_unlock_args *ap;
cc6b488e
KM
306{
307
308 return (0);
309}
310
311/*
312 * Device close routine
313 */
314/* ARGSUSED */
9342689a
JH
315fifo_close (ap)
316 struct vop_close_args *ap;
cc6b488e 317{
e1b76915 318 register struct fifoinfo *fip = ap->a_vp->v_fifoinfo;
cc6b488e
KM
319 int error1, error2;
320
e1b76915 321 if (ap->a_fflag & FWRITE) {
cc6b488e
KM
322 fip->fi_writers--;
323 if (fip->fi_writers == 0)
324 socantrcvmore(fip->fi_readsock);
325 } else {
326 fip->fi_readers--;
327 if (fip->fi_readers == 0)
328 socantsendmore(fip->fi_writesock);
329 }
e1b76915 330 if (ap->a_vp->v_usecount > 1)
cc6b488e
KM
331 return (0);
332 error1 = soclose(fip->fi_readsock);
333 error2 = soclose(fip->fi_writesock);
334 FREE(fip, M_VNODE);
e1b76915 335 ap->a_vp->v_fifoinfo = NULL;
cc6b488e
KM
336 if (error1)
337 return (error1);
338 return (error2);
339}
340
341/*
342 * Print out the contents of a fifo vnode.
343 */
9342689a
JH
344fifo_print (ap)
345 struct vop_print_args *ap;
cc6b488e
KM
346{
347
348 printf("tag VT_NON");
e1b76915 349 fifo_printinfo(ap->a_vp);
cc6b488e
KM
350 printf("\n");
351}
352
353/*
354 * Print out internal contents of a fifo vnode.
355 */
356fifo_printinfo(vp)
357 struct vnode *vp;
358{
359 register struct fifoinfo *fip = vp->v_fifoinfo;
360
361 printf(", fifo with %d readers and %d writers",
362 fip->fi_readers, fip->fi_writers);
363}
364
365/*
366 * Fifo failed operation
367 */
368fifo_ebadf()
369{
370
371 return (EBADF);
372}
373
a4128336
KM
374/*
375 * Fifo advisory byte-level locks.
376 */
81b4c293 377/* ARGSUSED */
9342689a
JH
378fifo_advlock (ap)
379 struct vop_advlock_args *ap;
a4128336
KM
380{
381
382 return (EOPNOTSUPP);
383}
384
cc6b488e
KM
385/*
386 * Fifo bad operation
387 */
388fifo_badop()
389{
390
391 panic("fifo_badop called");
392 /* NOTREACHED */
393}