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