1 1.91 thorpej /* $NetBSD: fifo_vnops.c,v 1.91 2021/10/11 01:07:36 thorpej Exp $ */ 2 1.64 ad 3 1.64 ad /*- 4 1.64 ad * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 1.64 ad * All rights reserved. 6 1.64 ad * 7 1.64 ad * Redistribution and use in source and binary forms, with or without 8 1.64 ad * modification, are permitted provided that the following conditions 9 1.64 ad * are met: 10 1.64 ad * 1. Redistributions of source code must retain the above copyright 11 1.64 ad * notice, this list of conditions and the following disclaimer. 12 1.64 ad * 2. Redistributions in binary form must reproduce the above copyright 13 1.64 ad * notice, this list of conditions and the following disclaimer in the 14 1.64 ad * documentation and/or other materials provided with the distribution. 15 1.64 ad * 16 1.64 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.64 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.64 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.64 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.64 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.64 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.64 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.64 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.64 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.64 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.64 ad * POSSIBILITY OF SUCH DAMAGE. 27 1.64 ad */ 28 1.9 cgd 29 1.1 cgd /* 30 1.25 fvdl * Copyright (c) 1990, 1993, 1995 31 1.8 mycroft * The Regents of the University of California. All rights reserved. 32 1.1 cgd * 33 1.1 cgd * Redistribution and use in source and binary forms, with or without 34 1.1 cgd * modification, are permitted provided that the following conditions 35 1.1 cgd * are met: 36 1.1 cgd * 1. Redistributions of source code must retain the above copyright 37 1.1 cgd * notice, this list of conditions and the following disclaimer. 38 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 39 1.1 cgd * notice, this list of conditions and the following disclaimer in the 40 1.1 cgd * documentation and/or other materials provided with the distribution. 41 1.42 agc * 3. Neither the name of the University nor the names of its contributors 42 1.1 cgd * may be used to endorse or promote products derived from this software 43 1.1 cgd * without specific prior written permission. 44 1.1 cgd * 45 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 1.1 cgd * SUCH DAMAGE. 56 1.1 cgd * 57 1.25 fvdl * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95 58 1.1 cgd */ 59 1.32 lukem 60 1.32 lukem #include <sys/cdefs.h> 61 1.91 thorpej __KERNEL_RCSID(0, "$NetBSD: fifo_vnops.c,v 1.91 2021/10/11 01:07:36 thorpej Exp $"); 62 1.1 cgd 63 1.6 mycroft #include <sys/param.h> 64 1.25 fvdl #include <sys/systm.h> 65 1.8 mycroft #include <sys/proc.h> 66 1.6 mycroft #include <sys/time.h> 67 1.6 mycroft #include <sys/namei.h> 68 1.6 mycroft #include <sys/vnode.h> 69 1.6 mycroft #include <sys/socket.h> 70 1.45 matt #include <sys/protosw.h> 71 1.6 mycroft #include <sys/socketvar.h> 72 1.6 mycroft #include <sys/stat.h> 73 1.6 mycroft #include <sys/ioctl.h> 74 1.6 mycroft #include <sys/file.h> 75 1.6 mycroft #include <sys/errno.h> 76 1.64 ad #include <sys/kmem.h> 77 1.17 christos #include <sys/un.h> 78 1.20 mycroft #include <sys/poll.h> 79 1.36 jdolecek #include <sys/event.h> 80 1.64 ad #include <sys/condvar.h> 81 1.19 mycroft 82 1.6 mycroft #include <miscfs/fifofs/fifo.h> 83 1.19 mycroft #include <miscfs/genfs/genfs.h> 84 1.1 cgd 85 1.1 cgd /* 86 1.1 cgd * This structure is associated with the FIFO vnode and stores 87 1.1 cgd * the state associated with the FIFO. 88 1.1 cgd */ 89 1.1 cgd struct fifoinfo { 90 1.1 cgd struct socket *fi_readsock; 91 1.1 cgd struct socket *fi_writesock; 92 1.64 ad kcondvar_t fi_rcv; 93 1.64 ad int fi_readers; 94 1.64 ad kcondvar_t fi_wcv; 95 1.64 ad int fi_writers; 96 1.1 cgd }; 97 1.1 cgd 98 1.1 cgd /* 99 1.1 cgd * Trivial lookup routine that always fails. 100 1.1 cgd */ 101 1.1 cgd /* ARGSUSED */ 102 1.68 pooka static int 103 1.30 lukem fifo_lookup(void *v) 104 1.17 christos { 105 1.74 hannken struct vop_lookup_v2_args /* { 106 1.30 lukem struct vnode *a_dvp; 107 1.30 lukem struct vnode **a_vpp; 108 1.30 lukem struct componentname *a_cnp; 109 1.17 christos } */ *ap = v; 110 1.51 perry 111 1.8 mycroft *ap->a_vpp = NULL; 112 1.1 cgd return (ENOTDIR); 113 1.1 cgd } 114 1.1 cgd 115 1.1 cgd /* 116 1.1 cgd * Open called to set up a new instance of a fifo or 117 1.1 cgd * to find an active instance of a fifo. 118 1.1 cgd */ 119 1.68 pooka static int 120 1.30 lukem fifo_open(void *v) 121 1.17 christos { 122 1.8 mycroft struct vop_open_args /* { 123 1.30 lukem struct vnode *a_vp; 124 1.30 lukem int a_mode; 125 1.55 elad kauth_cred_t a_cred; 126 1.17 christos } */ *ap = v; 127 1.58 pooka struct lwp *l = curlwp; 128 1.30 lukem struct vnode *vp; 129 1.30 lukem struct fifoinfo *fip; 130 1.30 lukem struct socket *rso, *wso; 131 1.30 lukem int error; 132 1.1 cgd 133 1.30 lukem vp = ap->a_vp; 134 1.75 rmind KASSERT(VOP_ISLOCKED(vp)); 135 1.30 lukem 136 1.1 cgd if ((fip = vp->v_fifoinfo) == NULL) { 137 1.64 ad fip = kmem_alloc(sizeof(*fip), KM_SLEEP); 138 1.64 ad error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, l, NULL); 139 1.49 jonathan if (error != 0) { 140 1.64 ad kmem_free(fip, sizeof(*fip)); 141 1.64 ad return (error); 142 1.1 cgd } 143 1.1 cgd fip->fi_readsock = rso; 144 1.64 ad error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, l, rso); 145 1.49 jonathan if (error != 0) { 146 1.1 cgd (void)soclose(rso); 147 1.64 ad kmem_free(fip, sizeof(*fip)); 148 1.64 ad return (error); 149 1.1 cgd } 150 1.1 cgd fip->fi_writesock = wso; 151 1.64 ad solock(wso); 152 1.77 rtr if ((error = unp_connect2(wso, rso)) != 0) { 153 1.64 ad sounlock(wso); 154 1.1 cgd (void)soclose(wso); 155 1.1 cgd (void)soclose(rso); 156 1.64 ad kmem_free(fip, sizeof(*fip)); 157 1.64 ad return (error); 158 1.1 cgd } 159 1.88 thorpej 160 1.88 thorpej /* 161 1.88 thorpej * FIFOs must be readable when there is at least 1 162 1.88 thorpej * byte of data available in the receive buffer. 163 1.88 thorpej * 164 1.88 thorpej * FIFOs must be writable when there is space for 165 1.88 thorpej * at least PIPE_BUF bytes in the send buffer. 166 1.88 thorpej * If we're increasing the low water mark for the 167 1.89 thorpej * send buffer, then mimic how soreserve() would 168 1.88 thorpej * have set the high water mark. 169 1.88 thorpej */ 170 1.88 thorpej rso->so_rcv.sb_lowat = 1; 171 1.88 thorpej if (wso->so_snd.sb_lowat < PIPE_BUF) { 172 1.88 thorpej wso->so_snd.sb_hiwat = PIPE_BUF * 2; 173 1.88 thorpej } 174 1.88 thorpej wso->so_snd.sb_lowat = PIPE_BUF; 175 1.88 thorpej 176 1.64 ad fip->fi_readers = 0; 177 1.64 ad fip->fi_writers = 0; 178 1.1 cgd wso->so_state |= SS_CANTRCVMORE; 179 1.1 cgd rso->so_state |= SS_CANTSENDMORE; 180 1.64 ad cv_init(&fip->fi_rcv, "fiford"); 181 1.64 ad cv_init(&fip->fi_wcv, "fifowr"); 182 1.75 rmind vp->v_fifoinfo = fip; 183 1.64 ad } else { 184 1.64 ad wso = fip->fi_writesock; 185 1.64 ad rso = fip->fi_readsock; 186 1.64 ad solock(wso); 187 1.1 cgd } 188 1.64 ad 189 1.8 mycroft if (ap->a_mode & FREAD) { 190 1.16 mycroft if (fip->fi_readers++ == 0) { 191 1.64 ad wso->so_state &= ~SS_CANTSENDMORE; 192 1.64 ad cv_broadcast(&fip->fi_wcv); 193 1.1 cgd } 194 1.16 mycroft } 195 1.16 mycroft if (ap->a_mode & FWRITE) { 196 1.16 mycroft if (fip->fi_writers++ == 0) { 197 1.64 ad rso->so_state &= ~SS_CANTRCVMORE; 198 1.64 ad cv_broadcast(&fip->fi_rcv); 199 1.2 cgd } 200 1.16 mycroft } 201 1.16 mycroft if (ap->a_mode & FREAD) { 202 1.16 mycroft if (ap->a_mode & O_NONBLOCK) { 203 1.1 cgd } else { 204 1.64 ad while (!soreadable(rso) && fip->fi_writers == 0) { 205 1.69 hannken VOP_UNLOCK(vp); 206 1.64 ad error = cv_wait_sig(&fip->fi_rcv, 207 1.64 ad wso->so_lock); 208 1.64 ad sounlock(wso); 209 1.25 fvdl vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 210 1.16 mycroft if (error) 211 1.16 mycroft goto bad; 212 1.64 ad solock(wso); 213 1.1 cgd } 214 1.16 mycroft } 215 1.16 mycroft } 216 1.16 mycroft if (ap->a_mode & FWRITE) { 217 1.16 mycroft if (ap->a_mode & O_NONBLOCK) { 218 1.16 mycroft if (fip->fi_readers == 0) { 219 1.16 mycroft error = ENXIO; 220 1.64 ad sounlock(wso); 221 1.16 mycroft goto bad; 222 1.16 mycroft } 223 1.16 mycroft } else { 224 1.2 cgd while (fip->fi_readers == 0) { 225 1.69 hannken VOP_UNLOCK(vp); 226 1.64 ad error = cv_wait_sig(&fip->fi_wcv, 227 1.64 ad wso->so_lock); 228 1.64 ad sounlock(wso); 229 1.25 fvdl vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 230 1.8 mycroft if (error) 231 1.16 mycroft goto bad; 232 1.64 ad solock(wso); 233 1.2 cgd } 234 1.1 cgd } 235 1.1 cgd } 236 1.64 ad sounlock(wso); 237 1.16 mycroft return (0); 238 1.30 lukem bad: 239 1.58 pooka VOP_CLOSE(vp, ap->a_mode, ap->a_cred); 240 1.1 cgd return (error); 241 1.1 cgd } 242 1.1 cgd 243 1.1 cgd /* 244 1.1 cgd * Vnode op for read 245 1.1 cgd */ 246 1.1 cgd /* ARGSUSED */ 247 1.68 pooka static int 248 1.30 lukem fifo_read(void *v) 249 1.17 christos { 250 1.8 mycroft struct vop_read_args /* { 251 1.30 lukem struct vnode *a_vp; 252 1.30 lukem struct uio *a_uio; 253 1.30 lukem int a_ioflag; 254 1.55 elad kauth_cred_t a_cred; 255 1.17 christos } */ *ap = v; 256 1.30 lukem struct uio *uio; 257 1.30 lukem struct socket *rso; 258 1.71 christos int error, sflags; 259 1.35 thorpej size_t startresid; 260 1.1 cgd 261 1.30 lukem uio = ap->a_uio; 262 1.30 lukem rso = ap->a_vp->v_fifoinfo->fi_readsock; 263 1.1 cgd #ifdef DIAGNOSTIC 264 1.1 cgd if (uio->uio_rw != UIO_READ) 265 1.1 cgd panic("fifo_read mode"); 266 1.1 cgd #endif 267 1.1 cgd if (uio->uio_resid == 0) 268 1.1 cgd return (0); 269 1.1 cgd startresid = uio->uio_resid; 270 1.69 hannken VOP_UNLOCK(ap->a_vp); 271 1.71 christos sflags = (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0; 272 1.71 christos error = (*rso->so_receive)(rso, NULL, uio, NULL, NULL, &sflags); 273 1.1 cgd /* 274 1.1 cgd * Clear EOF indication after first such return. 275 1.1 cgd */ 276 1.72 christos if (error == 0 && uio->uio_resid == startresid) 277 1.1 cgd rso->so_state &= ~SS_CANTRCVMORE; 278 1.23 kleink if (ap->a_ioflag & IO_NDELAY) { 279 1.23 kleink if (error == EWOULDBLOCK && 280 1.23 kleink ap->a_vp->v_fifoinfo->fi_writers == 0) 281 1.23 kleink error = 0; 282 1.23 kleink } 283 1.64 ad vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 284 1.1 cgd return (error); 285 1.1 cgd } 286 1.1 cgd 287 1.1 cgd /* 288 1.1 cgd * Vnode op for write 289 1.1 cgd */ 290 1.1 cgd /* ARGSUSED */ 291 1.68 pooka static int 292 1.30 lukem fifo_write(void *v) 293 1.17 christos { 294 1.8 mycroft struct vop_write_args /* { 295 1.30 lukem struct vnode *a_vp; 296 1.30 lukem struct uio *a_uio; 297 1.30 lukem int a_ioflag; 298 1.55 elad kauth_cred_t a_cred; 299 1.17 christos } */ *ap = v; 300 1.30 lukem struct socket *wso; 301 1.71 christos int error, sflags; 302 1.1 cgd 303 1.30 lukem wso = ap->a_vp->v_fifoinfo->fi_writesock; 304 1.1 cgd #ifdef DIAGNOSTIC 305 1.8 mycroft if (ap->a_uio->uio_rw != UIO_WRITE) 306 1.1 cgd panic("fifo_write mode"); 307 1.1 cgd #endif 308 1.69 hannken VOP_UNLOCK(ap->a_vp); 309 1.71 christos sflags = (ap->a_ioflag & IO_NDELAY) ? MSG_NBIO : 0; 310 1.71 christos error = (*wso->so_send)(wso, NULL, ap->a_uio, 0, NULL, sflags, curlwp); 311 1.64 ad vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY); 312 1.1 cgd return (error); 313 1.1 cgd } 314 1.1 cgd 315 1.1 cgd /* 316 1.1 cgd * Device ioctl operation. 317 1.1 cgd */ 318 1.1 cgd /* ARGSUSED */ 319 1.68 pooka static int 320 1.30 lukem fifo_ioctl(void *v) 321 1.17 christos { 322 1.8 mycroft struct vop_ioctl_args /* { 323 1.30 lukem struct vnode *a_vp; 324 1.30 lukem u_long a_command; 325 1.48 jrf void *a_data; 326 1.30 lukem int a_fflag; 327 1.55 elad kauth_cred_t a_cred; 328 1.54 christos struct lwp *a_l; 329 1.17 christos } */ *ap = v; 330 1.30 lukem struct file filetmp; 331 1.30 lukem int error; 332 1.1 cgd 333 1.8 mycroft if (ap->a_command == FIONBIO) 334 1.1 cgd return (0); 335 1.16 mycroft if (ap->a_fflag & FREAD) { 336 1.48 jrf filetmp.f_data = ap->a_vp->v_fifoinfo->fi_readsock; 337 1.63 ad error = soo_ioctl(&filetmp, ap->a_command, ap->a_data); 338 1.16 mycroft if (error) 339 1.16 mycroft return (error); 340 1.16 mycroft } 341 1.16 mycroft if (ap->a_fflag & FWRITE) { 342 1.48 jrf filetmp.f_data = ap->a_vp->v_fifoinfo->fi_writesock; 343 1.63 ad error = soo_ioctl(&filetmp, ap->a_command, ap->a_data); 344 1.16 mycroft if (error) 345 1.16 mycroft return (error); 346 1.16 mycroft } 347 1.16 mycroft return (0); 348 1.1 cgd } 349 1.1 cgd 350 1.1 cgd /* ARGSUSED */ 351 1.68 pooka static int 352 1.30 lukem fifo_poll(void *v) 353 1.17 christos { 354 1.20 mycroft struct vop_poll_args /* { 355 1.30 lukem struct vnode *a_vp; 356 1.30 lukem int a_events; 357 1.17 christos } */ *ap = v; 358 1.87 thorpej struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; 359 1.87 thorpej struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; 360 1.87 thorpej struct socket *lso = NULL; 361 1.87 thorpej int events; 362 1.87 thorpej 363 1.87 thorpej /* 364 1.87 thorpej * N.B. We're using a slightly different naming convention 365 1.87 thorpej * for these variables that most poll handlers. 366 1.87 thorpej */ 367 1.87 thorpej int revents = 0; 368 1.87 thorpej int wevents = 0; 369 1.87 thorpej 370 1.87 thorpej if (rso != NULL) { 371 1.87 thorpej lso = rso; 372 1.87 thorpej } else if (wso != NULL) { 373 1.87 thorpej lso = wso; 374 1.87 thorpej } 375 1.87 thorpej 376 1.87 thorpej if (lso == NULL) { 377 1.87 thorpej /* No associated sockets -> no events to report. */ 378 1.87 thorpej return 0; 379 1.87 thorpej } 380 1.87 thorpej 381 1.87 thorpej KASSERT(rso == NULL || lso->so_lock == rso->so_lock); 382 1.87 thorpej KASSERT(wso == NULL || lso->so_lock == wso->so_lock); 383 1.87 thorpej 384 1.87 thorpej solock(lso); 385 1.1 cgd 386 1.87 thorpej if (rso != NULL) { 387 1.87 thorpej events = ap->a_events & (POLLIN | POLLRDNORM); 388 1.87 thorpej if (events != 0 && soreadable(rso)) { 389 1.87 thorpej revents |= events; 390 1.87 thorpej } 391 1.87 thorpej if (rso->so_state & SS_CANTRCVMORE) { 392 1.87 thorpej revents |= POLLHUP; 393 1.87 thorpej } 394 1.87 thorpej /* 395 1.87 thorpej * We always selrecord the read side here regardless 396 1.87 thorpej * of the caller's read interest because we need to 397 1.87 thorpej * action POLLHUP. 398 1.87 thorpej */ 399 1.87 thorpej if (revents == 0) { 400 1.87 thorpej selrecord(curlwp, &rso->so_rcv.sb_sel); 401 1.87 thorpej rso->so_rcv.sb_flags |= SB_NOTIFY; 402 1.87 thorpej } 403 1.16 mycroft } 404 1.87 thorpej 405 1.87 thorpej /* POSIX sez: POLLHUP and POLLOUT are mutually-exclusive. */ 406 1.87 thorpej if (wso != NULL && (revents & POLLHUP) == 0) { 407 1.87 thorpej events = ap->a_events & (POLLOUT | POLLWRNORM); 408 1.87 thorpej if (events != 0 && sowritable(wso)) { 409 1.87 thorpej wevents |= events; 410 1.87 thorpej } 411 1.87 thorpej if (wevents == 0 && events != 0) { 412 1.87 thorpej selrecord(curlwp, &wso->so_snd.sb_sel); 413 1.87 thorpej wso->so_snd.sb_flags |= SB_NOTIFY; 414 1.87 thorpej } 415 1.16 mycroft } 416 1.20 mycroft 417 1.87 thorpej sounlock(lso); 418 1.87 thorpej 419 1.87 thorpej return (revents | wevents); 420 1.1 cgd } 421 1.1 cgd 422 1.68 pooka static int 423 1.30 lukem fifo_inactive(void *v) 424 1.25 fvdl { 425 1.78 riastrad struct vop_inactive_v2_args /* { 426 1.30 lukem struct vnode *a_vp; 427 1.54 christos struct lwp *a_l; 428 1.78 riastrad } */ *ap __unused = v; 429 1.25 fvdl 430 1.25 fvdl return (0); 431 1.25 fvdl } 432 1.25 fvdl 433 1.1 cgd /* 434 1.1 cgd * This is a noop, simply returning what one has been given. 435 1.1 cgd */ 436 1.68 pooka static int 437 1.30 lukem fifo_bmap(void *v) 438 1.17 christos { 439 1.8 mycroft struct vop_bmap_args /* { 440 1.30 lukem struct vnode *a_vp; 441 1.30 lukem daddr_t a_bn; 442 1.30 lukem struct vnode **a_vpp; 443 1.30 lukem daddr_t *a_bnp; 444 1.30 lukem int *a_runp; 445 1.17 christos } */ *ap = v; 446 1.1 cgd 447 1.8 mycroft if (ap->a_vpp != NULL) 448 1.8 mycroft *ap->a_vpp = ap->a_vp; 449 1.8 mycroft if (ap->a_bnp != NULL) 450 1.8 mycroft *ap->a_bnp = ap->a_bn; 451 1.25 fvdl if (ap->a_runp != NULL) 452 1.25 fvdl *ap->a_runp = 0; 453 1.1 cgd return (0); 454 1.1 cgd } 455 1.1 cgd 456 1.1 cgd /* 457 1.87 thorpej * This is like socantrcvmore(), but we send the POLL_HUP code. 458 1.87 thorpej */ 459 1.87 thorpej static void 460 1.87 thorpej fifo_socantrcvmore(struct socket *so) 461 1.87 thorpej { 462 1.87 thorpej KASSERT(solocked(so)); 463 1.87 thorpej 464 1.87 thorpej so->so_state |= SS_CANTRCVMORE; 465 1.87 thorpej if (sb_notify(&so->so_rcv)) { 466 1.87 thorpej sowakeup(so, &so->so_rcv, POLL_HUP); 467 1.87 thorpej } 468 1.87 thorpej } 469 1.87 thorpej 470 1.87 thorpej /* 471 1.1 cgd * Device close routine 472 1.1 cgd */ 473 1.1 cgd /* ARGSUSED */ 474 1.68 pooka static int 475 1.30 lukem fifo_close(void *v) 476 1.17 christos { 477 1.8 mycroft struct vop_close_args /* { 478 1.30 lukem struct vnode *a_vp; 479 1.30 lukem int a_fflag; 480 1.55 elad kauth_cred_t a_cred; 481 1.54 christos struct lwp *a_l; 482 1.17 christos } */ *ap = v; 483 1.30 lukem struct vnode *vp; 484 1.30 lukem struct fifoinfo *fip; 485 1.64 ad struct socket *wso, *rso; 486 1.50 mycroft int isrevoke; 487 1.1 cgd 488 1.30 lukem vp = ap->a_vp; 489 1.30 lukem fip = vp->v_fifoinfo; 490 1.50 mycroft isrevoke = (ap->a_fflag & (FREAD | FWRITE | FNONBLOCK)) == FNONBLOCK; 491 1.64 ad wso = fip->fi_writesock; 492 1.64 ad rso = fip->fi_readsock; 493 1.64 ad solock(wso); 494 1.50 mycroft if (isrevoke) { 495 1.50 mycroft if (fip->fi_readers != 0) { 496 1.50 mycroft fip->fi_readers = 0; 497 1.64 ad socantsendmore(wso); 498 1.50 mycroft } 499 1.50 mycroft if (fip->fi_writers != 0) { 500 1.50 mycroft fip->fi_writers = 0; 501 1.87 thorpej fifo_socantrcvmore(rso); 502 1.50 mycroft } 503 1.50 mycroft } else { 504 1.50 mycroft if ((ap->a_fflag & FREAD) && --fip->fi_readers == 0) 505 1.64 ad socantsendmore(wso); 506 1.50 mycroft if ((ap->a_fflag & FWRITE) && --fip->fi_writers == 0) 507 1.87 thorpej fifo_socantrcvmore(rso); 508 1.1 cgd } 509 1.50 mycroft if ((fip->fi_readers + fip->fi_writers) == 0) { 510 1.64 ad sounlock(wso); 511 1.64 ad (void) soclose(rso); 512 1.64 ad (void) soclose(wso); 513 1.64 ad cv_destroy(&fip->fi_rcv); 514 1.64 ad cv_destroy(&fip->fi_wcv); 515 1.64 ad kmem_free(fip, sizeof(*fip)); 516 1.34 chs vp->v_fifoinfo = NULL; 517 1.64 ad } else 518 1.64 ad sounlock(wso); 519 1.34 chs return (0); 520 1.1 cgd } 521 1.1 cgd 522 1.1 cgd /* 523 1.68 pooka * Print out internal contents of a fifo vnode. 524 1.68 pooka */ 525 1.68 pooka static void 526 1.68 pooka fifo_printinfo(struct vnode *vp) 527 1.68 pooka { 528 1.68 pooka struct fifoinfo *fip; 529 1.68 pooka 530 1.68 pooka fip = vp->v_fifoinfo; 531 1.68 pooka printf(", fifo with %d readers and %d writers", 532 1.68 pooka fip->fi_readers, fip->fi_writers); 533 1.68 pooka } 534 1.68 pooka 535 1.68 pooka /* 536 1.1 cgd * Print out the contents of a fifo vnode. 537 1.1 cgd */ 538 1.68 pooka static int 539 1.30 lukem fifo_print(void *v) 540 1.17 christos { 541 1.8 mycroft struct vop_print_args /* { 542 1.30 lukem struct vnode *a_vp; 543 1.17 christos } */ *ap = v; 544 1.1 cgd 545 1.68 pooka /* 546 1.68 pooka * We are most likely being called with the vnode belonging 547 1.68 pooka * to some file system and this is not printed. 548 1.68 pooka */ 549 1.68 pooka if (ap->a_vp->v_tag == VT_NON) 550 1.68 pooka printf("tag VT_NON"); 551 1.68 pooka 552 1.8 mycroft fifo_printinfo(ap->a_vp); 553 1.22 christos printf("\n"); 554 1.17 christos return 0; 555 1.1 cgd } 556 1.1 cgd 557 1.1 cgd /* 558 1.8 mycroft * Return POSIX pathconf information applicable to fifo's. 559 1.8 mycroft */ 560 1.68 pooka static int 561 1.30 lukem fifo_pathconf(void *v) 562 1.17 christos { 563 1.8 mycroft struct vop_pathconf_args /* { 564 1.30 lukem struct vnode *a_vp; 565 1.30 lukem int a_name; 566 1.30 lukem register_t *a_retval; 567 1.17 christos } */ *ap = v; 568 1.8 mycroft 569 1.8 mycroft switch (ap->a_name) { 570 1.8 mycroft case _PC_LINK_MAX: 571 1.8 mycroft *ap->a_retval = LINK_MAX; 572 1.8 mycroft return (0); 573 1.8 mycroft case _PC_PIPE_BUF: 574 1.8 mycroft *ap->a_retval = PIPE_BUF; 575 1.8 mycroft return (0); 576 1.8 mycroft case _PC_CHOWN_RESTRICTED: 577 1.26 kleink *ap->a_retval = 1; 578 1.26 kleink return (0); 579 1.26 kleink case _PC_SYNC_IO: 580 1.8 mycroft *ap->a_retval = 1; 581 1.8 mycroft return (0); 582 1.8 mycroft default: 583 1.81 christos return genfs_pathconf(ap); 584 1.8 mycroft } 585 1.1 cgd /* NOTREACHED */ 586 1.36 jdolecek } 587 1.36 jdolecek 588 1.36 jdolecek static void 589 1.36 jdolecek filt_fifordetach(struct knote *kn) 590 1.36 jdolecek { 591 1.36 jdolecek struct socket *so; 592 1.36 jdolecek 593 1.36 jdolecek so = (struct socket *)kn->kn_hook; 594 1.64 ad solock(so); 595 1.85 thorpej if (selremove_knote(&so->so_rcv.sb_sel, kn)) 596 1.85 thorpej so->so_rcv.sb_flags &= ~SB_KNOTE; 597 1.64 ad sounlock(so); 598 1.36 jdolecek } 599 1.36 jdolecek 600 1.36 jdolecek static int 601 1.57 christos filt_fiforead(struct knote *kn, long hint) 602 1.36 jdolecek { 603 1.36 jdolecek struct socket *so; 604 1.64 ad int rv; 605 1.36 jdolecek 606 1.36 jdolecek so = (struct socket *)kn->kn_hook; 607 1.64 ad if (hint != NOTE_SUBMIT) 608 1.64 ad solock(so); 609 1.36 jdolecek kn->kn_data = so->so_rcv.sb_cc; 610 1.36 jdolecek if (so->so_state & SS_CANTRCVMORE) { 611 1.91 thorpej knote_set_eof(kn, 0); 612 1.65 ad rv = 1; 613 1.65 ad } else { 614 1.91 thorpej knote_clear_eof(kn); 615 1.90 thorpej rv = (kn->kn_data >= so->so_rcv.sb_lowat); 616 1.36 jdolecek } 617 1.64 ad if (hint != NOTE_SUBMIT) 618 1.64 ad sounlock(so); 619 1.64 ad return rv; 620 1.36 jdolecek } 621 1.36 jdolecek 622 1.36 jdolecek static void 623 1.36 jdolecek filt_fifowdetach(struct knote *kn) 624 1.36 jdolecek { 625 1.36 jdolecek struct socket *so; 626 1.36 jdolecek 627 1.36 jdolecek so = (struct socket *)kn->kn_hook; 628 1.64 ad solock(so); 629 1.85 thorpej if (selremove_knote(&so->so_snd.sb_sel, kn)) 630 1.85 thorpej so->so_snd.sb_flags &= ~SB_KNOTE; 631 1.64 ad sounlock(so); 632 1.36 jdolecek } 633 1.36 jdolecek 634 1.36 jdolecek static int 635 1.57 christos filt_fifowrite(struct knote *kn, long hint) 636 1.36 jdolecek { 637 1.36 jdolecek struct socket *so; 638 1.64 ad int rv; 639 1.36 jdolecek 640 1.36 jdolecek so = (struct socket *)kn->kn_hook; 641 1.64 ad if (hint != NOTE_SUBMIT) 642 1.65 ad solock(so); 643 1.36 jdolecek kn->kn_data = sbspace(&so->so_snd); 644 1.36 jdolecek if (so->so_state & SS_CANTSENDMORE) { 645 1.91 thorpej knote_set_eof(kn, 0); 646 1.65 ad rv = 1; 647 1.65 ad } else { 648 1.91 thorpej knote_clear_eof(kn); 649 1.65 ad rv = (kn->kn_data >= so->so_snd.sb_lowat); 650 1.36 jdolecek } 651 1.64 ad if (hint != NOTE_SUBMIT) 652 1.64 ad sounlock(so); 653 1.64 ad return rv; 654 1.36 jdolecek } 655 1.36 jdolecek 656 1.79 maya static const struct filterops fiforead_filtops = { 657 1.86 thorpej .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 658 1.79 maya .f_attach = NULL, 659 1.79 maya .f_detach = filt_fifordetach, 660 1.79 maya .f_event = filt_fiforead, 661 1.79 maya }; 662 1.79 maya 663 1.79 maya static const struct filterops fifowrite_filtops = { 664 1.86 thorpej .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 665 1.79 maya .f_attach = NULL, 666 1.79 maya .f_detach = filt_fifowdetach, 667 1.79 maya .f_event = filt_fifowrite, 668 1.79 maya }; 669 1.36 jdolecek 670 1.36 jdolecek /* ARGSUSED */ 671 1.68 pooka static int 672 1.36 jdolecek fifo_kqfilter(void *v) 673 1.36 jdolecek { 674 1.36 jdolecek struct vop_kqfilter_args /* { 675 1.36 jdolecek struct vnode *a_vp; 676 1.36 jdolecek struct knote *a_kn; 677 1.36 jdolecek } */ *ap = v; 678 1.36 jdolecek struct socket *so; 679 1.36 jdolecek struct sockbuf *sb; 680 1.36 jdolecek 681 1.36 jdolecek switch (ap->a_kn->kn_filter) { 682 1.36 jdolecek case EVFILT_READ: 683 1.90 thorpej so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock; 684 1.36 jdolecek ap->a_kn->kn_fop = &fiforead_filtops; 685 1.36 jdolecek sb = &so->so_rcv; 686 1.36 jdolecek break; 687 1.36 jdolecek case EVFILT_WRITE: 688 1.90 thorpej so = (struct socket *)ap->a_vp->v_fifoinfo->fi_writesock; 689 1.36 jdolecek ap->a_kn->kn_fop = &fifowrite_filtops; 690 1.36 jdolecek sb = &so->so_snd; 691 1.36 jdolecek break; 692 1.36 jdolecek default: 693 1.59 pooka return (EINVAL); 694 1.36 jdolecek } 695 1.36 jdolecek 696 1.36 jdolecek ap->a_kn->kn_hook = so; 697 1.36 jdolecek 698 1.64 ad solock(so); 699 1.82 thorpej selrecord_knote(&sb->sb_sel, ap->a_kn); 700 1.36 jdolecek sb->sb_flags |= SB_KNOTE; 701 1.64 ad sounlock(so); 702 1.64 ad 703 1.36 jdolecek return (0); 704 1.1 cgd } 705 1.68 pooka 706 1.68 pooka int (**fifo_vnodeop_p)(void *); 707 1.68 pooka const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { 708 1.68 pooka { &vop_default_desc, vn_default_error }, 709 1.83 dholland { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */ 710 1.68 pooka { &vop_lookup_desc, fifo_lookup }, /* lookup */ 711 1.68 pooka { &vop_create_desc, genfs_badop }, /* create */ 712 1.68 pooka { &vop_mknod_desc, genfs_badop }, /* mknod */ 713 1.68 pooka { &vop_open_desc, fifo_open }, /* open */ 714 1.68 pooka { &vop_close_desc, fifo_close }, /* close */ 715 1.68 pooka { &vop_access_desc, genfs_ebadf }, /* access */ 716 1.80 christos { &vop_accessx_desc, genfs_accessx }, /* accessx */ 717 1.68 pooka { &vop_getattr_desc, genfs_ebadf }, /* getattr */ 718 1.68 pooka { &vop_setattr_desc, genfs_ebadf }, /* setattr */ 719 1.68 pooka { &vop_read_desc, fifo_read }, /* read */ 720 1.68 pooka { &vop_write_desc, fifo_write }, /* write */ 721 1.76 dholland { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ 722 1.76 dholland { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ 723 1.68 pooka { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 724 1.68 pooka { &vop_poll_desc, fifo_poll }, /* poll */ 725 1.68 pooka { &vop_kqfilter_desc, fifo_kqfilter }, /* kqfilter */ 726 1.68 pooka { &vop_revoke_desc, genfs_revoke }, /* revoke */ 727 1.68 pooka { &vop_mmap_desc, genfs_badop }, /* mmap */ 728 1.68 pooka { &vop_fsync_desc, genfs_nullop }, /* fsync */ 729 1.68 pooka { &vop_seek_desc, genfs_badop }, /* seek */ 730 1.68 pooka { &vop_remove_desc, genfs_badop }, /* remove */ 731 1.68 pooka { &vop_link_desc, genfs_badop }, /* link */ 732 1.68 pooka { &vop_rename_desc, genfs_badop }, /* rename */ 733 1.68 pooka { &vop_mkdir_desc, genfs_badop }, /* mkdir */ 734 1.68 pooka { &vop_rmdir_desc, genfs_badop }, /* rmdir */ 735 1.68 pooka { &vop_symlink_desc, genfs_badop }, /* symlink */ 736 1.68 pooka { &vop_readdir_desc, genfs_badop }, /* readdir */ 737 1.68 pooka { &vop_readlink_desc, genfs_badop }, /* readlink */ 738 1.68 pooka { &vop_abortop_desc, genfs_badop }, /* abortop */ 739 1.68 pooka { &vop_inactive_desc, fifo_inactive }, /* inactive */ 740 1.68 pooka { &vop_reclaim_desc, genfs_nullop }, /* reclaim */ 741 1.68 pooka { &vop_lock_desc, genfs_lock }, /* lock */ 742 1.68 pooka { &vop_unlock_desc, genfs_unlock }, /* unlock */ 743 1.68 pooka { &vop_bmap_desc, fifo_bmap }, /* bmap */ 744 1.68 pooka { &vop_strategy_desc, genfs_badop }, /* strategy */ 745 1.68 pooka { &vop_print_desc, fifo_print }, /* print */ 746 1.68 pooka { &vop_islocked_desc, genfs_islocked }, /* islocked */ 747 1.68 pooka { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 748 1.68 pooka { &vop_advlock_desc, genfs_einval }, /* advlock */ 749 1.68 pooka { &vop_bwrite_desc, genfs_nullop }, /* bwrite */ 750 1.68 pooka { &vop_putpages_desc, genfs_null_putpages }, /* putpages */ 751 1.70 plunky { NULL, NULL } 752 1.68 pooka }; 753 1.68 pooka const struct vnodeopv_desc fifo_vnodeop_opv_desc = 754 1.68 pooka { &fifo_vnodeop_p, fifo_vnodeop_entries }; 755