1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)fifo_vnops.c 7.3 (Berkeley) 03/27/90 18 */ 19 20 #include "param.h" 21 #include "time.h" 22 #include "namei.h" 23 #include "vnode.h" 24 #include "socket.h" 25 #include "socketvar.h" 26 #include "stat.h" 27 #include "ioctl.h" 28 #include "file.h" 29 #include "errno.h" 30 #include "malloc.h" 31 32 /* 33 * This structure is associated with the FIFO vnode and stores 34 * the state associated with the FIFO. 35 */ 36 struct fifoinfo { 37 struct socket *fi_readsock; 38 struct socket *fi_writesock; 39 long fi_readers; 40 long fi_writers; 41 }; 42 43 int fifo_lookup(), 44 fifo_open(), 45 fifo_read(), 46 fifo_write(), 47 fifo_strategy(), 48 fifo_bmap(), 49 fifo_ioctl(), 50 fifo_select(), 51 fifo_lock(), 52 fifo_unlock(), 53 fifo_close(), 54 fifo_print(), 55 fifo_ebadf(), 56 fifo_badop(), 57 fifo_nullop(); 58 59 struct vnodeops fifo_vnodeops = { 60 fifo_lookup, /* lookup */ 61 fifo_badop, /* create */ 62 fifo_badop, /* mknod */ 63 fifo_open, /* open */ 64 fifo_close, /* close */ 65 fifo_ebadf, /* access */ 66 fifo_ebadf, /* getattr */ 67 fifo_ebadf, /* setattr */ 68 fifo_read, /* read */ 69 fifo_write, /* write */ 70 fifo_ioctl, /* ioctl */ 71 fifo_select, /* select */ 72 fifo_badop, /* mmap */ 73 fifo_nullop, /* fsync */ 74 fifo_badop, /* seek */ 75 fifo_badop, /* remove */ 76 fifo_badop, /* link */ 77 fifo_badop, /* rename */ 78 fifo_badop, /* mkdir */ 79 fifo_badop, /* rmdir */ 80 fifo_badop, /* symlink */ 81 fifo_badop, /* readdir */ 82 fifo_badop, /* readlink */ 83 fifo_badop, /* abortop */ 84 fifo_nullop, /* inactive */ 85 fifo_nullop, /* reclaim */ 86 fifo_lock, /* lock */ 87 fifo_unlock, /* unlock */ 88 fifo_bmap, /* bmap */ 89 fifo_badop, /* strategy */ 90 fifo_print, /* print */ 91 fifo_nullop, /* islocked */ 92 }; 93 94 /* 95 * Trivial lookup routine that always fails. 96 */ 97 fifo_lookup(vp, ndp) 98 struct vnode *vp; 99 struct nameidata *ndp; 100 { 101 102 ndp->ni_dvp = vp; 103 ndp->ni_vp = NULL; 104 return (ENOTDIR); 105 } 106 107 /* 108 * Open called to set up a new instance of a fifo or 109 * to find an active instance of a fifo. 110 */ 111 /* ARGSUSED */ 112 fifo_open(vp, mode, cred) 113 register struct vnode *vp; 114 int mode; 115 struct ucred *cred; 116 { 117 register struct fifoinfo *fip; 118 struct socket *rso, *wso; 119 int error; 120 static char openstr[] = "fifo"; 121 122 if ((mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) 123 return (EINVAL); 124 if ((fip = vp->v_fifoinfo) == NULL) { 125 MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK); 126 vp->v_fifoinfo = fip; 127 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) { 128 free(fip, M_VNODE); 129 vp->v_fifoinfo = NULL; 130 return (error); 131 } 132 fip->fi_readsock = rso; 133 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) { 134 (void)soclose(rso); 135 free(fip, M_VNODE); 136 vp->v_fifoinfo = NULL; 137 return (error); 138 } 139 fip->fi_writesock = wso; 140 if (error = unp_connect2(wso, rso)) { 141 (void)soclose(wso); 142 (void)soclose(rso); 143 free(fip, M_VNODE); 144 vp->v_fifoinfo = NULL; 145 return (error); 146 } 147 wso->so_state |= SS_CANTRCVMORE; 148 rso->so_state |= SS_CANTSENDMORE; 149 } 150 error = 0; 151 if (mode & FREAD) { 152 fip->fi_readers++; 153 if (fip->fi_readers == 1) { 154 fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; 155 if (fip->fi_writers > 0) 156 wakeup((caddr_t)&fip->fi_writers); 157 } 158 if (mode & O_NONBLOCK) 159 return (0); 160 while (fip->fi_writers == 0) 161 if (error = tsleep((caddr_t)&fip->fi_readers, PSOCK, 162 openstr, 0)) 163 break; 164 } else { 165 fip->fi_writers++; 166 if (fip->fi_readers == 0 && (mode & O_NONBLOCK)) { 167 error = ENXIO; 168 } else { 169 if (fip->fi_writers == 1) { 170 fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; 171 if (fip->fi_readers > 0) 172 wakeup((caddr_t)&fip->fi_readers); 173 } 174 while (fip->fi_readers == 0) 175 if (error = tsleep((caddr_t)&fip->fi_writers, 176 PSOCK, openstr, 0)) 177 break; 178 } 179 } 180 if (error) 181 fifo_close(vp, mode, cred); 182 return (error); 183 } 184 185 /* 186 * Vnode op for read 187 */ 188 /* ARGSUSED */ 189 fifo_read(vp, uio, ioflag, cred) 190 struct vnode *vp; 191 register struct uio *uio; 192 int ioflag; 193 struct ucred *cred; 194 { 195 register struct socket *rso = vp->v_fifoinfo->fi_readsock; 196 int error, startresid; 197 198 if (uio->uio_rw != UIO_READ) 199 panic("fifo_read mode"); 200 if (uio->uio_resid == 0) 201 return (0); 202 if (ioflag & IO_NDELAY) 203 rso->so_state |= SS_NBIO; 204 startresid = uio->uio_resid; 205 VOP_UNLOCK(vp); 206 error = soreceive(rso, (struct mbuf **)0, uio, (int *)0, 207 (struct mbuf **)0, (struct mbuf **)0); 208 VOP_LOCK(vp); 209 /* 210 * Clear EOF indication after first such return. 211 */ 212 if (uio->uio_resid == startresid) 213 rso->so_state &= ~SS_CANTRCVMORE; 214 if (ioflag & IO_NDELAY) 215 rso->so_state &= ~SS_NBIO; 216 return (error); 217 } 218 219 /* 220 * Vnode op for write 221 */ 222 /* ARGSUSED */ 223 fifo_write(vp, uio, ioflag, cred) 224 struct vnode *vp; 225 register struct uio *uio; 226 int ioflag; 227 struct ucred *cred; 228 { 229 struct socket *wso = vp->v_fifoinfo->fi_writesock; 230 int error; 231 232 if (uio->uio_rw != UIO_WRITE) 233 panic("fifo_write mode"); 234 if (ioflag & IO_NDELAY) 235 wso->so_state |= SS_NBIO; 236 VOP_UNLOCK(vp); 237 error = sosend(wso, (struct mbuf *)0, uio, 0, (struct mbuf *)0); 238 VOP_LOCK(vp); 239 if (ioflag & IO_NDELAY) 240 wso->so_state &= ~SS_NBIO; 241 return (error); 242 } 243 244 /* 245 * Device ioctl operation. 246 */ 247 /* ARGSUSED */ 248 fifo_ioctl(vp, com, data, fflag, cred) 249 struct vnode *vp; 250 int com; 251 caddr_t data; 252 int fflag; 253 struct ucred *cred; 254 { 255 struct file filetmp; 256 int error; 257 258 if (com == FIONBIO) 259 return (0); 260 if (fflag & FREAD) 261 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 262 else 263 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 264 return (soo_ioctl(&filetmp, com, data)); 265 } 266 267 /* ARGSUSED */ 268 fifo_select(vp, which, fflag, cred) 269 struct vnode *vp; 270 int which, fflag; 271 struct ucred *cred; 272 { 273 struct file filetmp; 274 int error; 275 276 if (fflag & FREAD) 277 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_readsock; 278 else 279 filetmp.f_data = (caddr_t)vp->v_fifoinfo->fi_writesock; 280 return (soo_select(&filetmp, which)); 281 } 282 283 /* 284 * This is a noop, simply returning what one has been given. 285 */ 286 fifo_bmap(vp, bn, vpp, bnp) 287 struct vnode *vp; 288 daddr_t bn; 289 struct vnode **vpp; 290 daddr_t *bnp; 291 { 292 293 if (vpp != NULL) 294 *vpp = vp; 295 if (bnp != NULL) 296 *bnp = bn; 297 return (0); 298 } 299 300 /* 301 * At the moment we do not do any locking. 302 */ 303 /* ARGSUSED */ 304 fifo_lock(vp) 305 struct vnode *vp; 306 { 307 308 return (0); 309 } 310 311 /* ARGSUSED */ 312 fifo_unlock(vp) 313 struct vnode *vp; 314 { 315 316 return (0); 317 } 318 319 /* 320 * Device close routine 321 */ 322 /* ARGSUSED */ 323 fifo_close(vp, fflag, cred) 324 register struct vnode *vp; 325 int fflag; 326 struct ucred *cred; 327 { 328 register struct fifoinfo *fip = vp->v_fifoinfo; 329 int error1, error2; 330 331 if (fflag & FWRITE) { 332 fip->fi_writers--; 333 if (fip->fi_writers == 0) 334 socantrcvmore(fip->fi_readsock); 335 } else { 336 fip->fi_readers--; 337 if (fip->fi_readers == 0) 338 socantsendmore(fip->fi_writesock); 339 } 340 if (vp->v_usecount > 1) 341 return (0); 342 error1 = soclose(fip->fi_readsock); 343 error2 = soclose(fip->fi_writesock); 344 FREE(fip, M_VNODE); 345 vp->v_fifoinfo = NULL; 346 if (error1) 347 return (error1); 348 return (error2); 349 } 350 351 /* 352 * Print out the contents of a fifo vnode. 353 */ 354 fifo_print(vp) 355 struct vnode *vp; 356 { 357 358 printf("tag VT_NON"); 359 fifo_printinfo(vp); 360 printf("\n"); 361 } 362 363 /* 364 * Print out internal contents of a fifo vnode. 365 */ 366 fifo_printinfo(vp) 367 struct vnode *vp; 368 { 369 register struct fifoinfo *fip = vp->v_fifoinfo; 370 371 printf(", fifo with %d readers and %d writers", 372 fip->fi_readers, fip->fi_writers); 373 } 374 375 /* 376 * Fifo failed operation 377 */ 378 fifo_ebadf() 379 { 380 381 return (EBADF); 382 } 383 384 /* 385 * Fifo bad operation 386 */ 387 fifo_badop() 388 { 389 390 panic("fifo_badop called"); 391 /* NOTREACHED */ 392 } 393 394 /* 395 * Fifo null operation 396 */ 397 fifo_nullop() 398 { 399 400 return (0); 401 } 402