1 /*- 2 * Copyright (c) 2000-2004 3 * Poul-Henning Kamp. All rights reserved. 4 * Copyright (c) 1989, 1992-1993, 1995 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software donated to Berkeley by 8 * Jan-Simon Pendry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95 32 * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vnops.c 1.43 33 * 34 * $FreeBSD$ 35 */ 36 37 /* 38 * TODO: 39 * remove empty directories 40 * mkdir: want it ? 41 */ 42 43 #include "opt_mac.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/conf.h> 48 #include <sys/dirent.h> 49 #include <sys/fcntl.h> 50 #include <sys/file.h> 51 #include <sys/filedesc.h> 52 #include <sys/filio.h> 53 #include <sys/kernel.h> 54 #include <sys/lock.h> 55 #include <sys/malloc.h> 56 #include <sys/mount.h> 57 #include <sys/namei.h> 58 #include <sys/priv.h> 59 #include <sys/proc.h> 60 #include <sys/stat.h> 61 #include <sys/sx.h> 62 #include <sys/time.h> 63 #include <sys/ttycom.h> 64 #include <sys/unistd.h> 65 #include <sys/vnode.h> 66 67 static struct vop_vector devfs_vnodeops; 68 static struct vop_vector devfs_specops; 69 static struct fileops devfs_ops_f; 70 71 #include <fs/devfs/devfs.h> 72 #include <fs/devfs/devfs_int.h> 73 74 #include <security/mac/mac_framework.h> 75 76 struct mtx devfs_de_interlock; 77 MTX_SYSINIT(devfs_de_interlock, &devfs_de_interlock, "devfs interlock", MTX_DEF); 78 79 static int 80 devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp) 81 { 82 83 *dswp = devvn_refthread(fp->f_vnode, devp); 84 if (*devp != fp->f_data) { 85 if (*dswp != NULL) 86 dev_relthread(*devp); 87 return (ENXIO); 88 } 89 KASSERT((*devp)->si_refcount > 0, 90 ("devfs: un-referenced struct cdev *(%s)", devtoname(*devp))); 91 if (*dswp == NULL) 92 return (ENXIO); 93 return (0); 94 } 95 96 /* 97 * Construct the fully qualified path name relative to the mountpoint 98 */ 99 static char * 100 devfs_fqpn(char *buf, struct vnode *dvp, struct componentname *cnp) 101 { 102 int i; 103 struct devfs_dirent *de, *dd; 104 struct devfs_mount *dmp; 105 106 dmp = VFSTODEVFS(dvp->v_mount); 107 dd = dvp->v_data; 108 i = SPECNAMELEN; 109 buf[i] = '\0'; 110 i -= cnp->cn_namelen; 111 if (i < 0) 112 return (NULL); 113 bcopy(cnp->cn_nameptr, buf + i, cnp->cn_namelen); 114 de = dd; 115 while (de != dmp->dm_rootdir) { 116 i--; 117 if (i < 0) 118 return (NULL); 119 buf[i] = '/'; 120 i -= de->de_dirent->d_namlen; 121 if (i < 0) 122 return (NULL); 123 bcopy(de->de_dirent->d_name, buf + i, 124 de->de_dirent->d_namlen); 125 de = TAILQ_FIRST(&de->de_dlist); /* "." */ 126 de = TAILQ_NEXT(de, de_list); /* ".." */ 127 de = de->de_dir; 128 } 129 return (buf + i); 130 } 131 132 static int 133 devfs_allocv_drop_refs(int drop_dm_lock, struct devfs_mount *dmp, 134 struct devfs_dirent *de) 135 { 136 int not_found; 137 138 not_found = 0; 139 if (de->de_flags & DE_DOOMED) 140 not_found = 1; 141 if (DEVFS_DE_DROP(de)) { 142 KASSERT(not_found == 1, ("DEVFS de dropped but not doomed")); 143 devfs_dirent_free(de); 144 } 145 if (DEVFS_DMP_DROP(dmp)) { 146 KASSERT(not_found == 1, 147 ("DEVFS mount struct freed before dirent")); 148 not_found = 2; 149 sx_xunlock(&dmp->dm_lock); 150 devfs_unmount_final(dmp); 151 } 152 if (not_found == 1 || (drop_dm_lock && not_found != 2)) 153 sx_unlock(&dmp->dm_lock); 154 return (not_found); 155 } 156 157 /* 158 * devfs_allocv shall be entered with dmp->dm_lock held, and it drops 159 * it on return. 160 */ 161 int 162 devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td) 163 { 164 int error; 165 struct vnode *vp; 166 struct cdev *dev; 167 struct devfs_mount *dmp; 168 169 KASSERT(td == curthread, ("devfs_allocv: td != curthread")); 170 dmp = VFSTODEVFS(mp); 171 if (de->de_flags & DE_DOOMED) { 172 sx_xunlock(&dmp->dm_lock); 173 return (ENOENT); 174 } 175 loop: 176 DEVFS_DE_HOLD(de); 177 DEVFS_DMP_HOLD(dmp); 178 mtx_lock(&devfs_de_interlock); 179 vp = de->de_vnode; 180 if (vp != NULL) { 181 VI_LOCK(vp); 182 mtx_unlock(&devfs_de_interlock); 183 sx_xunlock(&dmp->dm_lock); 184 error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td); 185 sx_xlock(&dmp->dm_lock); 186 if (devfs_allocv_drop_refs(0, dmp, de)) { 187 if (error == 0) 188 vput(vp); 189 return (ENOENT); 190 } 191 else if (error) 192 goto loop; 193 sx_xunlock(&dmp->dm_lock); 194 *vpp = vp; 195 return (0); 196 } 197 mtx_unlock(&devfs_de_interlock); 198 if (de->de_dirent->d_type == DT_CHR) { 199 if (!(de->de_cdp->cdp_flags & CDP_ACTIVE)) { 200 devfs_allocv_drop_refs(1, dmp, de); 201 return (ENOENT); 202 } 203 dev = &de->de_cdp->cdp_c; 204 } else { 205 dev = NULL; 206 } 207 error = getnewvnode("devfs", mp, &devfs_vnodeops, &vp); 208 if (error != 0) { 209 devfs_allocv_drop_refs(1, dmp, de); 210 printf("devfs_allocv: failed to allocate new vnode\n"); 211 return (error); 212 } 213 214 if (de->de_dirent->d_type == DT_CHR) { 215 vp->v_type = VCHR; 216 VI_LOCK(vp); 217 dev_lock(); 218 dev_refl(dev); 219 vp->v_rdev = dev; 220 KASSERT(vp->v_usecount == 1, 221 ("%s %d (%d)\n", __func__, __LINE__, vp->v_usecount)); 222 dev->si_usecount += vp->v_usecount; 223 dev_unlock(); 224 VI_UNLOCK(vp); 225 vp->v_op = &devfs_specops; 226 } else if (de->de_dirent->d_type == DT_DIR) { 227 vp->v_type = VDIR; 228 } else if (de->de_dirent->d_type == DT_LNK) { 229 vp->v_type = VLNK; 230 } else { 231 vp->v_type = VBAD; 232 } 233 mtx_lock(&devfs_de_interlock); 234 vp->v_data = de; 235 de->de_vnode = vp; 236 mtx_unlock(&devfs_de_interlock); 237 sx_xunlock(&dmp->dm_lock); 238 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 239 sx_xlock(&dmp->dm_lock); 240 if (devfs_allocv_drop_refs(0, dmp, de)) { 241 vput(vp); 242 return (ENOENT); 243 } 244 #ifdef MAC 245 mac_associate_vnode_devfs(mp, de, vp); 246 #endif 247 sx_xunlock(&dmp->dm_lock); 248 *vpp = vp; 249 return (0); 250 } 251 252 static int 253 devfs_access(struct vop_access_args *ap) 254 { 255 struct vnode *vp = ap->a_vp; 256 struct devfs_dirent *de; 257 int error; 258 259 de = vp->v_data; 260 if (vp->v_type == VDIR) 261 de = de->de_dir; 262 263 error = vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid, 264 ap->a_mode, ap->a_cred, NULL); 265 if (!error) 266 return (error); 267 if (error != EACCES) 268 return (error); 269 /* We do, however, allow access to the controlling terminal */ 270 if (!(ap->a_td->td_proc->p_flag & P_CONTROLT)) 271 return (error); 272 if (ap->a_td->td_proc->p_session->s_ttyvp == de->de_vnode) 273 return (0); 274 return (error); 275 } 276 277 /* ARGSUSED */ 278 static int 279 devfs_advlock(struct vop_advlock_args *ap) 280 { 281 282 return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL); 283 } 284 285 /* ARGSUSED */ 286 static int 287 devfs_close(struct vop_close_args *ap) 288 { 289 struct vnode *vp = ap->a_vp, *oldvp; 290 struct thread *td = ap->a_td; 291 struct cdev *dev = vp->v_rdev; 292 struct cdevsw *dsw; 293 int vp_locked, error; 294 295 /* 296 * Hack: a tty device that is a controlling terminal 297 * has a reference from the session structure. 298 * We cannot easily tell that a character device is 299 * a controlling terminal, unless it is the closing 300 * process' controlling terminal. In that case, 301 * if the reference count is 2 (this last descriptor 302 * plus the session), release the reference from the session. 303 */ 304 oldvp = NULL; 305 sx_xlock(&proctree_lock); 306 if (td && vp == td->td_proc->p_session->s_ttyvp) { 307 SESS_LOCK(td->td_proc->p_session); 308 VI_LOCK(vp); 309 if (count_dev(dev) == 2 && (vp->v_iflag & VI_DOOMED) == 0) { 310 td->td_proc->p_session->s_ttyvp = NULL; 311 oldvp = vp; 312 } 313 VI_UNLOCK(vp); 314 SESS_UNLOCK(td->td_proc->p_session); 315 } 316 sx_xunlock(&proctree_lock); 317 if (oldvp != NULL) 318 vrele(oldvp); 319 /* 320 * We do not want to really close the device if it 321 * is still in use unless we are trying to close it 322 * forcibly. Since every use (buffer, vnode, swap, cmap) 323 * holds a reference to the vnode, and because we mark 324 * any other vnodes that alias this device, when the 325 * sum of the reference counts on all the aliased 326 * vnodes descends to one, we are on last close. 327 */ 328 dsw = dev_refthread(dev); 329 if (dsw == NULL) 330 return (ENXIO); 331 VI_LOCK(vp); 332 if (vp->v_iflag & VI_DOOMED) { 333 /* Forced close. */ 334 } else if (dsw->d_flags & D_TRACKCLOSE) { 335 /* Keep device updated on status. */ 336 } else if (count_dev(dev) > 1) { 337 VI_UNLOCK(vp); 338 dev_relthread(dev); 339 return (0); 340 } 341 vholdl(vp); 342 VI_UNLOCK(vp); 343 vp_locked = VOP_ISLOCKED(vp, td); 344 VOP_UNLOCK(vp, 0, td); 345 KASSERT(dev->si_refcount > 0, 346 ("devfs_close() on un-referenced struct cdev *(%s)", devtoname(dev))); 347 if (!(dsw->d_flags & D_NEEDGIANT)) { 348 DROP_GIANT(); 349 error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td); 350 PICKUP_GIANT(); 351 } else { 352 error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td); 353 } 354 dev_relthread(dev); 355 vn_lock(vp, vp_locked | LK_RETRY, td); 356 vdrop(vp); 357 return (error); 358 } 359 360 static int 361 devfs_close_f(struct file *fp, struct thread *td) 362 { 363 364 return (vnops.fo_close(fp, td)); 365 } 366 367 /* ARGSUSED */ 368 static int 369 devfs_fsync(struct vop_fsync_args *ap) 370 { 371 if (!vn_isdisk(ap->a_vp, NULL)) 372 return (0); 373 374 return (vop_stdfsync(ap)); 375 } 376 377 static int 378 devfs_getattr(struct vop_getattr_args *ap) 379 { 380 struct vnode *vp = ap->a_vp; 381 struct vattr *vap = ap->a_vap; 382 int error = 0; 383 struct devfs_dirent *de; 384 struct cdev *dev; 385 386 de = vp->v_data; 387 KASSERT(de != NULL, ("Null dirent in devfs_getattr vp=%p", vp)); 388 if (vp->v_type == VDIR) { 389 de = de->de_dir; 390 KASSERT(de != NULL, 391 ("Null dir dirent in devfs_getattr vp=%p", vp)); 392 } 393 bzero((caddr_t) vap, sizeof(*vap)); 394 vattr_null(vap); 395 vap->va_uid = de->de_uid; 396 vap->va_gid = de->de_gid; 397 vap->va_mode = de->de_mode; 398 if (vp->v_type == VLNK) 399 vap->va_size = strlen(de->de_symlink); 400 else if (vp->v_type == VDIR) 401 vap->va_size = vap->va_bytes = DEV_BSIZE; 402 else 403 vap->va_size = 0; 404 if (vp->v_type != VDIR) 405 vap->va_bytes = 0; 406 vap->va_blocksize = DEV_BSIZE; 407 vap->va_type = vp->v_type; 408 409 #define fix(aa) \ 410 do { \ 411 if ((aa).tv_sec == 0) { \ 412 (aa).tv_sec = boottime.tv_sec; \ 413 (aa).tv_nsec = boottime.tv_usec * 1000; \ 414 } \ 415 } while (0) 416 417 if (vp->v_type != VCHR) { 418 fix(de->de_atime); 419 vap->va_atime = de->de_atime; 420 fix(de->de_mtime); 421 vap->va_mtime = de->de_mtime; 422 fix(de->de_ctime); 423 vap->va_ctime = de->de_ctime; 424 } else { 425 dev = vp->v_rdev; 426 fix(dev->si_atime); 427 vap->va_atime = dev->si_atime; 428 fix(dev->si_mtime); 429 vap->va_mtime = dev->si_mtime; 430 fix(dev->si_ctime); 431 vap->va_ctime = dev->si_ctime; 432 433 vap->va_rdev = dev->si_priv->cdp_inode; 434 } 435 vap->va_gen = 0; 436 vap->va_flags = 0; 437 vap->va_nlink = de->de_links; 438 vap->va_fileid = de->de_inode; 439 440 return (error); 441 } 442 443 /* ARGSUSED */ 444 static int 445 devfs_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred, struct thread *td) 446 { 447 struct cdev *dev; 448 struct cdevsw *dsw; 449 struct vnode *vp; 450 struct vnode *vpold; 451 int error, i; 452 const char *p; 453 struct fiodgname_arg *fgn; 454 455 error = devfs_fp_check(fp, &dev, &dsw); 456 if (error) 457 return (error); 458 459 if (com == FIODTYPE) { 460 *(int *)data = dsw->d_flags & D_TYPEMASK; 461 dev_relthread(dev); 462 return (0); 463 } else if (com == FIODGNAME) { 464 fgn = data; 465 p = devtoname(dev); 466 i = strlen(p) + 1; 467 if (i > fgn->len) 468 error = EINVAL; 469 else 470 error = copyout(p, fgn->buf, i); 471 dev_relthread(dev); 472 return (error); 473 } 474 error = dsw->d_ioctl(dev, com, data, fp->f_flag, td); 475 dev_relthread(dev); 476 if (error == ENOIOCTL) 477 error = ENOTTY; 478 if (error == 0 && com == TIOCSCTTY) { 479 vp = fp->f_vnode; 480 481 /* Do nothing if reassigning same control tty */ 482 sx_slock(&proctree_lock); 483 if (td->td_proc->p_session->s_ttyvp == vp) { 484 sx_sunlock(&proctree_lock); 485 return (0); 486 } 487 488 mtx_lock(&Giant); 489 490 vpold = td->td_proc->p_session->s_ttyvp; 491 VREF(vp); 492 SESS_LOCK(td->td_proc->p_session); 493 td->td_proc->p_session->s_ttyvp = vp; 494 SESS_UNLOCK(td->td_proc->p_session); 495 496 sx_sunlock(&proctree_lock); 497 498 /* Get rid of reference to old control tty */ 499 if (vpold) 500 vrele(vpold); 501 mtx_unlock(&Giant); 502 } 503 return (error); 504 } 505 506 /* ARGSUSED */ 507 static int 508 devfs_kqfilter_f(struct file *fp, struct knote *kn) 509 { 510 struct cdev *dev; 511 struct cdevsw *dsw; 512 int error; 513 514 error = devfs_fp_check(fp, &dev, &dsw); 515 if (error) 516 return (error); 517 error = dsw->d_kqfilter(dev, kn); 518 dev_relthread(dev); 519 return (error); 520 } 521 522 static int 523 devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock) 524 { 525 struct componentname *cnp; 526 struct vnode *dvp, **vpp; 527 struct thread *td; 528 struct devfs_dirent *de, *dd; 529 struct devfs_dirent **dde; 530 struct devfs_mount *dmp; 531 struct cdev *cdev; 532 int error, flags, nameiop; 533 char specname[SPECNAMELEN + 1], *pname; 534 535 cnp = ap->a_cnp; 536 vpp = ap->a_vpp; 537 dvp = ap->a_dvp; 538 pname = cnp->cn_nameptr; 539 td = cnp->cn_thread; 540 flags = cnp->cn_flags; 541 nameiop = cnp->cn_nameiop; 542 dmp = VFSTODEVFS(dvp->v_mount); 543 dd = dvp->v_data; 544 *vpp = NULLVP; 545 546 if ((flags & ISLASTCN) && nameiop == RENAME) 547 return (EOPNOTSUPP); 548 549 if (dvp->v_type != VDIR) 550 return (ENOTDIR); 551 552 if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT)) 553 return (EIO); 554 555 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td); 556 if (error) 557 return (error); 558 559 if (cnp->cn_namelen == 1 && *pname == '.') { 560 if ((flags & ISLASTCN) && nameiop != LOOKUP) 561 return (EINVAL); 562 *vpp = dvp; 563 VREF(dvp); 564 return (0); 565 } 566 567 if (flags & ISDOTDOT) { 568 if ((flags & ISLASTCN) && nameiop != LOOKUP) 569 return (EINVAL); 570 VOP_UNLOCK(dvp, 0, td); 571 de = TAILQ_FIRST(&dd->de_dlist); /* "." */ 572 de = TAILQ_NEXT(de, de_list); /* ".." */ 573 de = de->de_dir; 574 error = devfs_allocv(de, dvp->v_mount, vpp, td); 575 *dm_unlock = 0; 576 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); 577 return (error); 578 } 579 580 DEVFS_DMP_HOLD(dmp); 581 devfs_populate(dmp); 582 if (DEVFS_DMP_DROP(dmp)) { 583 *dm_unlock = 0; 584 sx_xunlock(&dmp->dm_lock); 585 devfs_unmount_final(dmp); 586 return (ENOENT); 587 } 588 dd = dvp->v_data; 589 de = devfs_find(dd, cnp->cn_nameptr, cnp->cn_namelen); 590 while (de == NULL) { /* While(...) so we can use break */ 591 592 if (nameiop == DELETE) 593 return (ENOENT); 594 595 /* 596 * OK, we didn't have an entry for the name we were asked for 597 * so we try to see if anybody can create it on demand. 598 */ 599 pname = devfs_fqpn(specname, dvp, cnp); 600 if (pname == NULL) 601 break; 602 603 cdev = NULL; 604 EVENTHANDLER_INVOKE(dev_clone, 605 td->td_ucred, pname, strlen(pname), &cdev); 606 if (cdev == NULL) 607 break; 608 609 DEVFS_DMP_HOLD(dmp); 610 devfs_populate(dmp); 611 if (DEVFS_DMP_DROP(dmp)) { 612 *dm_unlock = 0; 613 sx_xunlock(&dmp->dm_lock); 614 devfs_unmount_final(dmp); 615 return (ENOENT); 616 } 617 618 dev_lock(); 619 dde = &cdev->si_priv->cdp_dirents[dmp->dm_idx]; 620 if (dde != NULL && *dde != NULL) 621 de = *dde; 622 dev_unlock(); 623 dev_rel(cdev); 624 break; 625 } 626 627 if (de == NULL || de->de_flags & DE_WHITEOUT) { 628 if ((nameiop == CREATE || nameiop == RENAME) && 629 (flags & (LOCKPARENT | WANTPARENT)) && (flags & ISLASTCN)) { 630 cnp->cn_flags |= SAVENAME; 631 return (EJUSTRETURN); 632 } 633 return (ENOENT); 634 } 635 636 if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) { 637 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); 638 if (error) 639 return (error); 640 if (*vpp == dvp) { 641 VREF(dvp); 642 *vpp = dvp; 643 return (0); 644 } 645 } 646 error = devfs_allocv(de, dvp->v_mount, vpp, td); 647 *dm_unlock = 0; 648 return (error); 649 } 650 651 static int 652 devfs_lookup(struct vop_lookup_args *ap) 653 { 654 int j; 655 struct devfs_mount *dmp; 656 int dm_unlock; 657 658 dmp = VFSTODEVFS(ap->a_dvp->v_mount); 659 dm_unlock = 1; 660 sx_xlock(&dmp->dm_lock); 661 j = devfs_lookupx(ap, &dm_unlock); 662 if (dm_unlock == 1) 663 sx_xunlock(&dmp->dm_lock); 664 return (j); 665 } 666 667 static int 668 devfs_mknod(struct vop_mknod_args *ap) 669 { 670 struct componentname *cnp; 671 struct vnode *dvp, **vpp; 672 struct thread *td; 673 struct devfs_dirent *dd, *de; 674 struct devfs_mount *dmp; 675 int error; 676 677 /* 678 * The only type of node we should be creating here is a 679 * character device, for anything else return EOPNOTSUPP. 680 */ 681 if (ap->a_vap->va_type != VCHR) 682 return (EOPNOTSUPP); 683 dvp = ap->a_dvp; 684 dmp = VFSTODEVFS(dvp->v_mount); 685 686 cnp = ap->a_cnp; 687 vpp = ap->a_vpp; 688 td = cnp->cn_thread; 689 dd = dvp->v_data; 690 691 error = ENOENT; 692 sx_xlock(&dmp->dm_lock); 693 TAILQ_FOREACH(de, &dd->de_dlist, de_list) { 694 if (cnp->cn_namelen != de->de_dirent->d_namlen) 695 continue; 696 if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name, 697 de->de_dirent->d_namlen) != 0) 698 continue; 699 if (de->de_flags & DE_WHITEOUT) 700 break; 701 goto notfound; 702 } 703 if (de == NULL) 704 goto notfound; 705 de->de_flags &= ~DE_WHITEOUT; 706 error = devfs_allocv(de, dvp->v_mount, vpp, td); 707 return (error); 708 notfound: 709 sx_xunlock(&dmp->dm_lock); 710 return (error); 711 } 712 713 /* ARGSUSED */ 714 static int 715 devfs_open(struct vop_open_args *ap) 716 { 717 struct thread *td = ap->a_td; 718 struct vnode *vp = ap->a_vp; 719 struct cdev *dev = vp->v_rdev; 720 struct file *fp; 721 int error; 722 struct cdevsw *dsw; 723 724 if (vp->v_type == VBLK) 725 return (ENXIO); 726 727 if (dev == NULL) 728 return (ENXIO); 729 730 /* Make this field valid before any I/O in d_open. */ 731 if (dev->si_iosize_max == 0) 732 dev->si_iosize_max = DFLTPHYS; 733 734 dsw = dev_refthread(dev); 735 if (dsw == NULL) 736 return (ENXIO); 737 738 /* XXX: Special casing of ttys for deadfs. Probably redundant. */ 739 if (dsw->d_flags & D_TTY) 740 vp->v_vflag |= VV_ISTTY; 741 742 VOP_UNLOCK(vp, 0, td); 743 744 if(!(dsw->d_flags & D_NEEDGIANT)) { 745 DROP_GIANT(); 746 if (dsw->d_fdopen != NULL) 747 error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx); 748 else 749 error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td); 750 PICKUP_GIANT(); 751 } else { 752 if (dsw->d_fdopen != NULL) 753 error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx); 754 else 755 error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td); 756 } 757 758 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 759 760 dev_relthread(dev); 761 762 if (error) 763 return (error); 764 765 #if 0 /* /dev/console */ 766 KASSERT(ap->a_fdidx >= 0, 767 ("Could not vnode bypass device on fd %d", ap->a_fdidx)); 768 #else 769 if(ap->a_fdidx < 0) 770 return (error); 771 #endif 772 /* 773 * This is a pretty disgustingly long chain, but I am not 774 * sure there is any better way. Passing the fdidx into 775 * VOP_OPEN() offers us more information than just passing 776 * the file *. 777 */ 778 fp = ap->a_td->td_proc->p_fd->fd_ofiles[ap->a_fdidx]; 779 KASSERT(fp->f_ops == &badfileops, 780 ("Could not vnode bypass device on fdops %p", fp->f_ops)); 781 fp->f_ops = &devfs_ops_f; 782 fp->f_data = dev; 783 return (error); 784 } 785 786 static int 787 devfs_pathconf(struct vop_pathconf_args *ap) 788 { 789 790 switch (ap->a_name) { 791 case _PC_MAC_PRESENT: 792 #ifdef MAC 793 /* 794 * If MAC is enabled, devfs automatically supports 795 * trivial non-persistant label storage. 796 */ 797 *ap->a_retval = 1; 798 #else 799 *ap->a_retval = 0; 800 #endif 801 return (0); 802 default: 803 return (vop_stdpathconf(ap)); 804 } 805 /* NOTREACHED */ 806 } 807 808 /* ARGSUSED */ 809 static int 810 devfs_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td) 811 { 812 struct cdev *dev; 813 struct cdevsw *dsw; 814 int error; 815 816 error = devfs_fp_check(fp, &dev, &dsw); 817 if (error) 818 return (error); 819 error = dsw->d_poll(dev, events, td); 820 dev_relthread(dev); 821 return(error); 822 } 823 824 /* 825 * Print out the contents of a special device vnode. 826 */ 827 static int 828 devfs_print(struct vop_print_args *ap) 829 { 830 831 printf("\tdev %s\n", devtoname(ap->a_vp->v_rdev)); 832 return (0); 833 } 834 835 /* ARGSUSED */ 836 static int 837 devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td) 838 { 839 struct cdev *dev; 840 int ioflag, error, resid; 841 struct cdevsw *dsw; 842 843 error = devfs_fp_check(fp, &dev, &dsw); 844 if (error) 845 return (error); 846 resid = uio->uio_resid; 847 ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT); 848 if (ioflag & O_DIRECT) 849 ioflag |= IO_DIRECT; 850 851 if ((flags & FOF_OFFSET) == 0) 852 uio->uio_offset = fp->f_offset; 853 854 error = dsw->d_read(dev, uio, ioflag); 855 if (uio->uio_resid != resid || (error == 0 && resid != 0)) 856 vfs_timestamp(&dev->si_atime); 857 dev_relthread(dev); 858 859 if ((flags & FOF_OFFSET) == 0) 860 fp->f_offset = uio->uio_offset; 861 fp->f_nextoff = uio->uio_offset; 862 return (error); 863 } 864 865 static int 866 devfs_readdir(struct vop_readdir_args *ap) 867 { 868 int error; 869 struct uio *uio; 870 struct dirent *dp; 871 struct devfs_dirent *dd; 872 struct devfs_dirent *de; 873 struct devfs_mount *dmp; 874 off_t off, oldoff; 875 int *tmp_ncookies = NULL; 876 877 if (ap->a_vp->v_type != VDIR) 878 return (ENOTDIR); 879 880 uio = ap->a_uio; 881 if (uio->uio_offset < 0) 882 return (EINVAL); 883 884 /* 885 * XXX: This is a temporary hack to get around this filesystem not 886 * supporting cookies. We store the location of the ncookies pointer 887 * in a temporary variable before calling vfs_subr.c:vfs_read_dirent() 888 * and set the number of cookies to 0. We then set the pointer to 889 * NULL so that vfs_read_dirent doesn't try to call realloc() on 890 * ap->a_cookies. Later in this function, we restore the ap->a_ncookies 891 * pointer to its original location before returning to the caller. 892 */ 893 if (ap->a_ncookies != NULL) { 894 tmp_ncookies = ap->a_ncookies; 895 *ap->a_ncookies = 0; 896 ap->a_ncookies = NULL; 897 } 898 899 dmp = VFSTODEVFS(ap->a_vp->v_mount); 900 sx_xlock(&dmp->dm_lock); 901 DEVFS_DMP_HOLD(dmp); 902 devfs_populate(dmp); 903 if (DEVFS_DMP_DROP(dmp)) { 904 sx_xunlock(&dmp->dm_lock); 905 devfs_unmount_final(dmp); 906 if (tmp_ncookies != NULL) 907 ap->a_ncookies = tmp_ncookies; 908 return (EIO); 909 } 910 error = 0; 911 de = ap->a_vp->v_data; 912 off = 0; 913 oldoff = uio->uio_offset; 914 TAILQ_FOREACH(dd, &de->de_dlist, de_list) { 915 KASSERT(dd->de_cdp != (void *)0xdeadc0de, ("%s %d\n", __func__, __LINE__)); 916 if (dd->de_flags & DE_WHITEOUT) 917 continue; 918 if (dd->de_dirent->d_type == DT_DIR) 919 de = dd->de_dir; 920 else 921 de = dd; 922 dp = dd->de_dirent; 923 if (dp->d_reclen > uio->uio_resid) 924 break; 925 dp->d_fileno = de->de_inode; 926 if (off >= uio->uio_offset) { 927 error = vfs_read_dirent(ap, dp, off); 928 if (error) 929 break; 930 } 931 off += dp->d_reclen; 932 } 933 sx_xunlock(&dmp->dm_lock); 934 uio->uio_offset = off; 935 936 /* 937 * Restore ap->a_ncookies if it wasn't originally NULL in the first 938 * place. 939 */ 940 if (tmp_ncookies != NULL) 941 ap->a_ncookies = tmp_ncookies; 942 943 return (error); 944 } 945 946 static int 947 devfs_readlink(struct vop_readlink_args *ap) 948 { 949 struct devfs_dirent *de; 950 951 de = ap->a_vp->v_data; 952 return (uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio)); 953 } 954 955 static int 956 devfs_reclaim(struct vop_reclaim_args *ap) 957 { 958 struct vnode *vp = ap->a_vp; 959 struct devfs_dirent *de; 960 struct cdev *dev; 961 962 mtx_lock(&devfs_de_interlock); 963 de = vp->v_data; 964 if (de != NULL) { 965 de->de_vnode = NULL; 966 vp->v_data = NULL; 967 } 968 mtx_unlock(&devfs_de_interlock); 969 970 vnode_destroy_vobject(vp); 971 972 dev_lock(); 973 dev = vp->v_rdev; 974 vp->v_rdev = NULL; 975 976 if (dev == NULL) { 977 dev_unlock(); 978 return (0); 979 } 980 981 dev->si_usecount -= vp->v_usecount; 982 dev_unlock(); 983 dev_rel(dev); 984 return (0); 985 } 986 987 static int 988 devfs_remove(struct vop_remove_args *ap) 989 { 990 struct vnode *vp = ap->a_vp; 991 struct devfs_dirent *dd; 992 struct devfs_dirent *de; 993 struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount); 994 995 sx_xlock(&dmp->dm_lock); 996 dd = ap->a_dvp->v_data; 997 de = vp->v_data; 998 if (de->de_cdp == NULL) { 999 TAILQ_REMOVE(&dd->de_dlist, de, de_list); 1000 devfs_delete(dmp, de, 1); 1001 } else { 1002 de->de_flags |= DE_WHITEOUT; 1003 } 1004 sx_xunlock(&dmp->dm_lock); 1005 return (0); 1006 } 1007 1008 /* 1009 * Revoke is called on a tty when a terminal session ends. The vnode 1010 * is orphaned by setting v_op to deadfs so we need to let go of it 1011 * as well so that we create a new one next time around. 1012 * 1013 */ 1014 static int 1015 devfs_revoke(struct vop_revoke_args *ap) 1016 { 1017 struct vnode *vp = ap->a_vp, *vp2; 1018 struct cdev *dev; 1019 struct cdev_priv *cdp; 1020 struct devfs_dirent *de; 1021 int i; 1022 1023 KASSERT((ap->a_flags & REVOKEALL) != 0, ("devfs_revoke !REVOKEALL")); 1024 1025 dev = vp->v_rdev; 1026 cdp = dev->si_priv; 1027 1028 dev_lock(); 1029 cdp->cdp_inuse++; 1030 dev_unlock(); 1031 1032 vhold(vp); 1033 vgone(vp); 1034 vdrop(vp); 1035 1036 VOP_UNLOCK(vp,0,curthread); 1037 loop: 1038 for (;;) { 1039 mtx_lock(&devfs_de_interlock); 1040 dev_lock(); 1041 vp2 = NULL; 1042 for (i = 0; i <= cdp->cdp_maxdirent; i++) { 1043 de = cdp->cdp_dirents[i]; 1044 if (de == NULL) 1045 continue; 1046 1047 vp2 = de->de_vnode; 1048 if (vp2 != NULL) { 1049 dev_unlock(); 1050 VI_LOCK(vp2); 1051 mtx_unlock(&devfs_de_interlock); 1052 if (vget(vp2, LK_EXCLUSIVE | LK_INTERLOCK, 1053 curthread)) 1054 goto loop; 1055 vhold(vp2); 1056 vgone(vp2); 1057 vdrop(vp2); 1058 vput(vp2); 1059 break; 1060 } 1061 } 1062 if (vp2 != NULL) { 1063 continue; 1064 } 1065 dev_unlock(); 1066 mtx_unlock(&devfs_de_interlock); 1067 break; 1068 } 1069 dev_lock(); 1070 cdp->cdp_inuse--; 1071 if (!(cdp->cdp_flags & CDP_ACTIVE) && cdp->cdp_inuse == 0) { 1072 TAILQ_REMOVE(&cdevp_list, cdp, cdp_list); 1073 dev_unlock(); 1074 dev_rel(&cdp->cdp_c); 1075 } else 1076 dev_unlock(); 1077 1078 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); 1079 return (0); 1080 } 1081 1082 static int 1083 devfs_rioctl(struct vop_ioctl_args *ap) 1084 { 1085 int error; 1086 struct devfs_mount *dmp; 1087 1088 dmp = VFSTODEVFS(ap->a_vp->v_mount); 1089 sx_xlock(&dmp->dm_lock); 1090 DEVFS_DMP_HOLD(dmp); 1091 devfs_populate(dmp); 1092 if (DEVFS_DMP_DROP(dmp)) { 1093 sx_xunlock(&dmp->dm_lock); 1094 devfs_unmount_final(dmp); 1095 return (ENOENT); 1096 } 1097 error = devfs_rules_ioctl(dmp, ap->a_command, ap->a_data, ap->a_td); 1098 sx_xunlock(&dmp->dm_lock); 1099 return (error); 1100 } 1101 1102 static int 1103 devfs_rread(struct vop_read_args *ap) 1104 { 1105 1106 if (ap->a_vp->v_type != VDIR) 1107 return (EINVAL); 1108 return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL)); 1109 } 1110 1111 static int 1112 devfs_setattr(struct vop_setattr_args *ap) 1113 { 1114 struct devfs_dirent *de; 1115 struct vattr *vap; 1116 struct vnode *vp; 1117 int c, error; 1118 uid_t uid; 1119 gid_t gid; 1120 1121 vap = ap->a_vap; 1122 vp = ap->a_vp; 1123 if ((vap->va_type != VNON) || 1124 (vap->va_nlink != VNOVAL) || 1125 (vap->va_fsid != VNOVAL) || 1126 (vap->va_fileid != VNOVAL) || 1127 (vap->va_blocksize != VNOVAL) || 1128 (vap->va_flags != VNOVAL && vap->va_flags != 0) || 1129 (vap->va_rdev != VNOVAL) || 1130 ((int)vap->va_bytes != VNOVAL) || 1131 (vap->va_gen != VNOVAL)) { 1132 return (EINVAL); 1133 } 1134 1135 de = vp->v_data; 1136 if (vp->v_type == VDIR) 1137 de = de->de_dir; 1138 1139 error = c = 0; 1140 if (vap->va_uid == (uid_t)VNOVAL) 1141 uid = de->de_uid; 1142 else 1143 uid = vap->va_uid; 1144 if (vap->va_gid == (gid_t)VNOVAL) 1145 gid = de->de_gid; 1146 else 1147 gid = vap->va_gid; 1148 if (uid != de->de_uid || gid != de->de_gid) { 1149 if ((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid || 1150 (gid != de->de_gid && !groupmember(gid, ap->a_cred))) { 1151 error = priv_check_cred(ap->a_td->td_ucred, 1152 PRIV_VFS_CHOWN, SUSER_ALLOWJAIL); 1153 if (error) 1154 return (error); 1155 } 1156 de->de_uid = uid; 1157 de->de_gid = gid; 1158 c = 1; 1159 } 1160 1161 if (vap->va_mode != (mode_t)VNOVAL) { 1162 if (ap->a_cred->cr_uid != de->de_uid) { 1163 error = priv_check_cred(ap->a_td->td_ucred, 1164 PRIV_VFS_ADMIN, SUSER_ALLOWJAIL); 1165 if (error) 1166 return (error); 1167 } 1168 de->de_mode = vap->va_mode; 1169 c = 1; 1170 } 1171 1172 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 1173 /* See the comment in ufs_vnops::ufs_setattr(). */ 1174 if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) && 1175 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 1176 (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td)))) 1177 return (error); 1178 if (vap->va_atime.tv_sec != VNOVAL) { 1179 if (vp->v_type == VCHR) 1180 vp->v_rdev->si_atime = vap->va_atime; 1181 else 1182 de->de_atime = vap->va_atime; 1183 } 1184 if (vap->va_mtime.tv_sec != VNOVAL) { 1185 if (vp->v_type == VCHR) 1186 vp->v_rdev->si_mtime = vap->va_mtime; 1187 else 1188 de->de_mtime = vap->va_mtime; 1189 } 1190 c = 1; 1191 } 1192 1193 if (c) { 1194 if (vp->v_type == VCHR) 1195 vfs_timestamp(&vp->v_rdev->si_ctime); 1196 else 1197 vfs_timestamp(&de->de_mtime); 1198 } 1199 return (0); 1200 } 1201 1202 #ifdef MAC 1203 static int 1204 devfs_setlabel(struct vop_setlabel_args *ap) 1205 { 1206 struct vnode *vp; 1207 struct devfs_dirent *de; 1208 1209 vp = ap->a_vp; 1210 de = vp->v_data; 1211 1212 mac_relabel_vnode(ap->a_cred, vp, ap->a_label); 1213 mac_update_devfsdirent(vp->v_mount, de, vp); 1214 1215 return (0); 1216 } 1217 #endif 1218 1219 static int 1220 devfs_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td) 1221 { 1222 1223 return (vnops.fo_stat(fp, sb, cred, td)); 1224 } 1225 1226 static int 1227 devfs_symlink(struct vop_symlink_args *ap) 1228 { 1229 int i, error; 1230 struct devfs_dirent *dd; 1231 struct devfs_dirent *de; 1232 struct devfs_mount *dmp; 1233 struct thread *td; 1234 1235 td = ap->a_cnp->cn_thread; 1236 KASSERT(td == curthread, ("devfs_symlink: td != curthread")); 1237 1238 error = priv_check(td, PRIV_DEVFS_SYMLINK); 1239 if (error) 1240 return(error); 1241 dmp = VFSTODEVFS(ap->a_dvp->v_mount); 1242 dd = ap->a_dvp->v_data; 1243 de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen); 1244 de->de_uid = 0; 1245 de->de_gid = 0; 1246 de->de_mode = 0755; 1247 de->de_inode = alloc_unr(devfs_inos); 1248 de->de_dirent->d_type = DT_LNK; 1249 i = strlen(ap->a_target) + 1; 1250 de->de_symlink = malloc(i, M_DEVFS, M_WAITOK); 1251 bcopy(ap->a_target, de->de_symlink, i); 1252 sx_xlock(&dmp->dm_lock); 1253 #ifdef MAC 1254 mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de); 1255 #endif 1256 TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); 1257 return (devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td)); 1258 } 1259 1260 /* ARGSUSED */ 1261 static int 1262 devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td) 1263 { 1264 struct cdev *dev; 1265 int error, ioflag, resid; 1266 struct cdevsw *dsw; 1267 1268 error = devfs_fp_check(fp, &dev, &dsw); 1269 if (error) 1270 return (error); 1271 KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td)); 1272 ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT | O_FSYNC); 1273 if (ioflag & O_DIRECT) 1274 ioflag |= IO_DIRECT; 1275 if ((flags & FOF_OFFSET) == 0) 1276 uio->uio_offset = fp->f_offset; 1277 1278 resid = uio->uio_resid; 1279 1280 error = dsw->d_write(dev, uio, ioflag); 1281 if (uio->uio_resid != resid || (error == 0 && resid != 0)) { 1282 vfs_timestamp(&dev->si_ctime); 1283 dev->si_mtime = dev->si_ctime; 1284 } 1285 dev_relthread(dev); 1286 1287 if ((flags & FOF_OFFSET) == 0) 1288 fp->f_offset = uio->uio_offset; 1289 fp->f_nextoff = uio->uio_offset; 1290 return (error); 1291 } 1292 1293 dev_t 1294 dev2udev(struct cdev *x) 1295 { 1296 if (x == NULL) 1297 return (NODEV); 1298 return (x->si_priv->cdp_inode); 1299 } 1300 1301 static struct fileops devfs_ops_f = { 1302 .fo_read = devfs_read_f, 1303 .fo_write = devfs_write_f, 1304 .fo_ioctl = devfs_ioctl_f, 1305 .fo_poll = devfs_poll_f, 1306 .fo_kqfilter = devfs_kqfilter_f, 1307 .fo_stat = devfs_stat_f, 1308 .fo_close = devfs_close_f, 1309 .fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE 1310 }; 1311 1312 static struct vop_vector devfs_vnodeops = { 1313 .vop_default = &default_vnodeops, 1314 1315 .vop_access = devfs_access, 1316 .vop_getattr = devfs_getattr, 1317 .vop_ioctl = devfs_rioctl, 1318 .vop_lookup = devfs_lookup, 1319 .vop_mknod = devfs_mknod, 1320 .vop_pathconf = devfs_pathconf, 1321 .vop_read = devfs_rread, 1322 .vop_readdir = devfs_readdir, 1323 .vop_readlink = devfs_readlink, 1324 .vop_reclaim = devfs_reclaim, 1325 .vop_remove = devfs_remove, 1326 .vop_revoke = devfs_revoke, 1327 .vop_setattr = devfs_setattr, 1328 #ifdef MAC 1329 .vop_setlabel = devfs_setlabel, 1330 #endif 1331 .vop_symlink = devfs_symlink, 1332 }; 1333 1334 static struct vop_vector devfs_specops = { 1335 .vop_default = &default_vnodeops, 1336 1337 .vop_access = devfs_access, 1338 .vop_advlock = devfs_advlock, 1339 .vop_bmap = VOP_PANIC, 1340 .vop_close = devfs_close, 1341 .vop_create = VOP_PANIC, 1342 .vop_fsync = devfs_fsync, 1343 .vop_getattr = devfs_getattr, 1344 .vop_lease = VOP_NULL, 1345 .vop_link = VOP_PANIC, 1346 .vop_mkdir = VOP_PANIC, 1347 .vop_mknod = VOP_PANIC, 1348 .vop_open = devfs_open, 1349 .vop_pathconf = devfs_pathconf, 1350 .vop_print = devfs_print, 1351 .vop_read = VOP_PANIC, 1352 .vop_readdir = VOP_PANIC, 1353 .vop_readlink = VOP_PANIC, 1354 .vop_reallocblks = VOP_PANIC, 1355 .vop_reclaim = devfs_reclaim, 1356 .vop_remove = devfs_remove, 1357 .vop_rename = VOP_PANIC, 1358 .vop_revoke = devfs_revoke, 1359 .vop_rmdir = VOP_PANIC, 1360 .vop_setattr = devfs_setattr, 1361 #ifdef MAC 1362 .vop_setlabel = devfs_setlabel, 1363 #endif 1364 .vop_strategy = VOP_PANIC, 1365 .vop_symlink = VOP_PANIC, 1366 .vop_write = VOP_PANIC, 1367 }; 1368 1369 /* 1370 * Our calling convention to the device drivers used to be that we passed 1371 * vnode.h IO_* flags to read()/write(), but we're moving to fcntl.h O_ 1372 * flags instead since that's what open(), close() and ioctl() takes and 1373 * we don't really want vnode.h in device drivers. 1374 * We solved the source compatibility by redefining some vnode flags to 1375 * be the same as the fcntl ones and by sending down the bitwise OR of 1376 * the respective fcntl/vnode flags. These CTASSERTS make sure nobody 1377 * pulls the rug out under this. 1378 */ 1379 CTASSERT(O_NONBLOCK == IO_NDELAY); 1380 CTASSERT(O_FSYNC == IO_SYNC); 1381