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 * mknod: hunt down DE_DELETED, compare name, reinstantiate. 41 * mkdir: want it ? 42 */ 43 44 #include <opt_devfs.h> 45 #include <opt_mac.h> 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/bio.h> 50 #include <sys/buf.h> 51 #include <sys/conf.h> 52 #include <sys/dirent.h> 53 #include <sys/fcntl.h> 54 #include <sys/kernel.h> 55 #include <sys/lock.h> 56 #include <sys/mac.h> 57 #include <sys/malloc.h> 58 #include <sys/mount.h> 59 #include <sys/namei.h> 60 #include <sys/proc.h> 61 #include <sys/stat.h> 62 #include <sys/sx.h> 63 #include <sys/sysctl.h> 64 #include <sys/time.h> 65 #include <sys/unistd.h> 66 #include <sys/vnode.h> 67 68 #include <fs/devfs/devfs.h> 69 70 static int devfs_access(struct vop_access_args *ap); 71 static int devfs_advlock(struct vop_advlock_args *ap); 72 static int devfs_close(struct vop_close_args *ap); 73 static int devfs_fsync(struct vop_fsync_args *ap); 74 static int devfs_getattr(struct vop_getattr_args *ap); 75 static int devfs_ioctl(struct vop_ioctl_args *ap); 76 static int devfs_kqfilter(struct vop_kqfilter_args *ap); 77 static int devfs_lookupx(struct vop_lookup_args *ap); 78 static int devfs_mknod(struct vop_mknod_args *ap); 79 static int devfs_open(struct vop_open_args *ap); 80 static int devfs_pathconf(struct vop_pathconf_args *ap); 81 static int devfs_poll(struct vop_poll_args *ap); 82 static int devfs_print(struct vop_print_args *ap); 83 static int devfs_read(struct vop_read_args *ap); 84 static int devfs_readdir(struct vop_readdir_args *ap); 85 static int devfs_readlink(struct vop_readlink_args *ap); 86 static int devfs_reclaim(struct vop_reclaim_args *ap); 87 static int devfs_remove(struct vop_remove_args *ap); 88 static int devfs_revoke(struct vop_revoke_args *ap); 89 static int devfs_rioctl(struct vop_ioctl_args *ap); 90 static int devfs_rread(struct vop_read_args *ap); 91 static int devfs_setattr(struct vop_setattr_args *ap); 92 #ifdef MAC 93 static int devfs_setlabel(struct vop_setlabel_args *ap); 94 #endif 95 static int devfs_specstrategy(struct vop_specstrategy_args *); 96 static int devfs_symlink(struct vop_symlink_args *ap); 97 static int devfs_write(struct vop_write_args *ap); 98 99 static vop_t **devfs_vnodeop_p; 100 vop_t **devfs_specop_p; 101 102 /* 103 * Construct the fully qualified path name relative to the mountpoint 104 */ 105 static char * 106 devfs_fqpn(char *buf, struct vnode *dvp, struct componentname *cnp) 107 { 108 int i; 109 struct devfs_dirent *de, *dd; 110 struct devfs_mount *dmp; 111 112 dmp = VFSTODEVFS(dvp->v_mount); 113 dd = dvp->v_data; 114 i = SPECNAMELEN; 115 buf[i] = '\0'; 116 i -= cnp->cn_namelen; 117 if (i < 0) 118 return (NULL); 119 bcopy(cnp->cn_nameptr, buf + i, cnp->cn_namelen); 120 de = dd; 121 while (de != dmp->dm_basedir) { 122 i--; 123 if (i < 0) 124 return (NULL); 125 buf[i] = '/'; 126 i -= de->de_dirent->d_namlen; 127 if (i < 0) 128 return (NULL); 129 bcopy(de->de_dirent->d_name, buf + i, 130 de->de_dirent->d_namlen); 131 de = TAILQ_FIRST(&de->de_dlist); /* "." */ 132 de = TAILQ_NEXT(de, de_list); /* ".." */ 133 de = de->de_dir; 134 } 135 return (buf + i); 136 } 137 138 int 139 devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td) 140 { 141 int error; 142 struct vnode *vp; 143 struct cdev *dev; 144 145 KASSERT(td == curthread, ("devfs_allocv: td != curthread")); 146 loop: 147 vp = de->de_vnode; 148 if (vp != NULL) { 149 if (vget(vp, LK_EXCLUSIVE, td)) 150 goto loop; 151 *vpp = vp; 152 return (0); 153 } 154 if (de->de_dirent->d_type == DT_CHR) { 155 dev = *devfs_itod(de->de_inode); 156 if (dev == NULL) 157 return (ENOENT); 158 } else { 159 dev = NULL; 160 } 161 error = getnewvnode("devfs", mp, devfs_vnodeop_p, &vp); 162 if (error != 0) { 163 printf("devfs_allocv: failed to allocate new vnode\n"); 164 return (error); 165 } 166 167 if (de->de_dirent->d_type == DT_CHR) { 168 vp->v_type = VCHR; 169 vp = addaliasu(vp, dev->si_udev); 170 vp->v_op = devfs_specop_p; 171 } else if (de->de_dirent->d_type == DT_DIR) { 172 vp->v_type = VDIR; 173 } else if (de->de_dirent->d_type == DT_LNK) { 174 vp->v_type = VLNK; 175 } else { 176 vp->v_type = VBAD; 177 } 178 vp->v_data = de; 179 de->de_vnode = vp; 180 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 181 #ifdef MAC 182 mac_associate_vnode_devfs(mp, de, vp); 183 #endif 184 *vpp = vp; 185 return (0); 186 } 187 188 static int 189 devfs_access(ap) 190 struct vop_access_args /* { 191 struct vnode *a_vp; 192 int a_mode; 193 struct ucred *a_cred; 194 struct thread *a_td; 195 } */ *ap; 196 { 197 struct vnode *vp = ap->a_vp; 198 struct devfs_dirent *de; 199 int error; 200 201 de = vp->v_data; 202 if (vp->v_type == VDIR) 203 de = de->de_dir; 204 205 error = vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid, 206 ap->a_mode, ap->a_cred, NULL); 207 if (!error) 208 return (error); 209 if (error != EACCES) 210 return (error); 211 /* We do, however, allow access to the controlling terminal */ 212 if (!(ap->a_td->td_proc->p_flag & P_CONTROLT)) 213 return (error); 214 if (ap->a_td->td_proc->p_session->s_ttyvp == de->de_vnode) 215 return (0); 216 return (error); 217 } 218 219 /* 220 * Special device advisory byte-level locks. 221 */ 222 /* ARGSUSED */ 223 static int 224 devfs_advlock(ap) 225 struct vop_advlock_args /* { 226 struct vnode *a_vp; 227 caddr_t a_id; 228 int a_op; 229 struct flock *a_fl; 230 int a_flags; 231 } */ *ap; 232 { 233 234 return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL); 235 } 236 237 /* 238 * Device close routine 239 */ 240 /* ARGSUSED */ 241 static int 242 devfs_close(ap) 243 struct vop_close_args /* { 244 struct vnode *a_vp; 245 int a_fflag; 246 struct ucred *a_cred; 247 struct thread *a_td; 248 } */ *ap; 249 { 250 struct vnode *vp = ap->a_vp, *oldvp; 251 struct thread *td = ap->a_td; 252 struct cdev *dev = vp->v_rdev; 253 struct cdevsw *dsw; 254 int error; 255 256 /* 257 * Hack: a tty device that is a controlling terminal 258 * has a reference from the session structure. 259 * We cannot easily tell that a character device is 260 * a controlling terminal, unless it is the closing 261 * process' controlling terminal. In that case, 262 * if the reference count is 2 (this last descriptor 263 * plus the session), release the reference from the session. 264 */ 265 266 /* 267 * This needs to be rewritten to take the vp interlock into 268 * consideration. 269 */ 270 271 oldvp = NULL; 272 sx_xlock(&proctree_lock); 273 if (td && vp == td->td_proc->p_session->s_ttyvp) { 274 SESS_LOCK(td->td_proc->p_session); 275 VI_LOCK(vp); 276 if (count_dev(dev) == 2 && (vp->v_iflag & VI_XLOCK) == 0) { 277 td->td_proc->p_session->s_ttyvp = NULL; 278 oldvp = vp; 279 } 280 VI_UNLOCK(vp); 281 SESS_UNLOCK(td->td_proc->p_session); 282 } 283 sx_xunlock(&proctree_lock); 284 if (oldvp != NULL) 285 vrele(oldvp); 286 /* 287 * We do not want to really close the device if it 288 * is still in use unless we are trying to close it 289 * forcibly. Since every use (buffer, vnode, swap, cmap) 290 * holds a reference to the vnode, and because we mark 291 * any other vnodes that alias this device, when the 292 * sum of the reference counts on all the aliased 293 * vnodes descends to one, we are on last close. 294 */ 295 dsw = dev_refthread(dev); 296 if (dsw == NULL) 297 return (ENXIO); 298 VI_LOCK(vp); 299 if (vp->v_iflag & VI_XLOCK) { 300 /* Forced close. */ 301 } else if (dsw->d_flags & D_TRACKCLOSE) { 302 /* Keep device updated on status. */ 303 } else if (count_dev(dev) > 1) { 304 VI_UNLOCK(vp); 305 dev_relthread(dev); 306 return (0); 307 } 308 VI_UNLOCK(vp); 309 KASSERT(dev->si_refcount > 0, 310 ("devfs_close() on un-referenced struct cdev *(%s)", devtoname(dev))); 311 if (!(dsw->d_flags & D_NEEDGIANT)) { 312 DROP_GIANT(); 313 error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td); 314 PICKUP_GIANT(); 315 } else 316 error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td); 317 dev_relthread(dev); 318 return (error); 319 } 320 321 /* 322 * Synch buffers associated with a block device 323 */ 324 /* ARGSUSED */ 325 static int 326 devfs_fsync(ap) 327 struct vop_fsync_args /* { 328 struct vnode *a_vp; 329 struct ucred *a_cred; 330 int a_waitfor; 331 struct thread *a_td; 332 } */ *ap; 333 { 334 if (!vn_isdisk(ap->a_vp, NULL)) 335 return (0); 336 337 return (vop_stdfsync(ap)); 338 } 339 340 static int 341 devfs_getattr(ap) 342 struct vop_getattr_args /* { 343 struct vnode *a_vp; 344 struct vattr *a_vap; 345 struct ucred *a_cred; 346 struct thread *a_td; 347 } */ *ap; 348 { 349 struct vnode *vp = ap->a_vp; 350 struct vattr *vap = ap->a_vap; 351 int error = 0; 352 struct devfs_dirent *de; 353 struct cdev *dev; 354 355 de = vp->v_data; 356 if (vp->v_type == VDIR) 357 de = de->de_dir; 358 bzero((caddr_t) vap, sizeof(*vap)); 359 vattr_null(vap); 360 vap->va_uid = de->de_uid; 361 vap->va_gid = de->de_gid; 362 vap->va_mode = de->de_mode; 363 if (vp->v_type == VLNK) 364 vap->va_size = strlen(de->de_symlink); 365 else if (vp->v_type == VDIR) 366 vap->va_size = vap->va_bytes = DEV_BSIZE; 367 else 368 vap->va_size = 0; 369 if (vp->v_type != VDIR) 370 vap->va_bytes = 0; 371 vap->va_blocksize = DEV_BSIZE; 372 vap->va_type = vp->v_type; 373 374 #define fix(aa) \ 375 do { \ 376 if ((aa).tv_sec == 0) { \ 377 (aa).tv_sec = boottime.tv_sec; \ 378 (aa).tv_nsec = boottime.tv_usec * 1000; \ 379 } \ 380 } while (0) 381 382 if (vp->v_type != VCHR) { 383 fix(de->de_atime); 384 vap->va_atime = de->de_atime; 385 fix(de->de_mtime); 386 vap->va_mtime = de->de_mtime; 387 fix(de->de_ctime); 388 vap->va_ctime = de->de_ctime; 389 } else { 390 dev = vp->v_rdev; 391 fix(dev->si_atime); 392 vap->va_atime = dev->si_atime; 393 fix(dev->si_mtime); 394 vap->va_mtime = dev->si_mtime; 395 fix(dev->si_ctime); 396 vap->va_ctime = dev->si_ctime; 397 vap->va_rdev = dev->si_udev; 398 } 399 vap->va_gen = 0; 400 vap->va_flags = 0; 401 vap->va_nlink = de->de_links; 402 vap->va_fileid = de->de_inode; 403 404 return (error); 405 } 406 407 /* 408 * Device ioctl operation. 409 */ 410 /* ARGSUSED */ 411 static int 412 devfs_ioctl(ap) 413 struct vop_ioctl_args /* { 414 struct vnode *a_vp; 415 u_long a_command; 416 caddr_t a_data; 417 int a_fflag; 418 struct ucred *a_cred; 419 struct thread *a_td; 420 } */ *ap; 421 { 422 struct cdev *dev; 423 int error; 424 struct cdevsw *dsw; 425 426 dev = ap->a_vp->v_rdev; 427 dsw = dev_refthread(dev); 428 if (dsw == NULL) 429 return (ENXIO); 430 KASSERT(dev->si_refcount > 0, 431 ("devfs_ioctl() on un-referenced struct cdev *(%s)", devtoname(dev))); 432 if (!(dsw->d_flags & D_NEEDGIANT)) { 433 DROP_GIANT(); 434 error = dsw->d_ioctl(dev, ap->a_command, 435 ap->a_data, ap->a_fflag, ap->a_td); 436 PICKUP_GIANT(); 437 } else 438 error = dsw->d_ioctl(dev, ap->a_command, 439 ap->a_data, ap->a_fflag, ap->a_td); 440 dev_relthread(dev); 441 if (error == ENOIOCTL) 442 error = ENOTTY; 443 return (error); 444 } 445 446 /* ARGSUSED */ 447 static int 448 devfs_kqfilter(ap) 449 struct vop_kqfilter_args /* { 450 struct vnode *a_vp; 451 struct knote *a_kn; 452 } */ *ap; 453 { 454 struct cdev *dev; 455 struct cdevsw *dsw; 456 int error; 457 458 dev = ap->a_vp->v_rdev; 459 dsw = dev_refthread(dev); 460 if (dsw == NULL) 461 return(0); 462 KASSERT(dev->si_refcount > 0, 463 ("devfs_kqfilter() on un-referenced struct cdev *(%s)", devtoname(dev))); 464 if (!(dsw->d_flags & D_NEEDGIANT)) { 465 DROP_GIANT(); 466 error = dsw->d_kqfilter(dev, ap->a_kn); 467 PICKUP_GIANT(); 468 } else 469 error = dsw->d_kqfilter(dev, ap->a_kn); 470 dev_relthread(dev); 471 return (error); 472 } 473 474 static int 475 devfs_lookupx(ap) 476 struct vop_lookup_args /* { 477 struct vnode * a_dvp; 478 struct vnode ** a_vpp; 479 struct componentname * a_cnp; 480 } */ *ap; 481 { 482 struct componentname *cnp; 483 struct vnode *dvp, **vpp; 484 struct thread *td; 485 struct devfs_dirent *de, *dd; 486 struct devfs_dirent **dde; 487 struct devfs_mount *dmp; 488 struct cdev *cdev; 489 int error, flags, nameiop; 490 char specname[SPECNAMELEN + 1], *pname; 491 492 cnp = ap->a_cnp; 493 vpp = ap->a_vpp; 494 dvp = ap->a_dvp; 495 pname = cnp->cn_nameptr; 496 td = cnp->cn_thread; 497 flags = cnp->cn_flags; 498 nameiop = cnp->cn_nameiop; 499 dmp = VFSTODEVFS(dvp->v_mount); 500 dd = dvp->v_data; 501 502 *vpp = NULLVP; 503 cnp->cn_flags &= ~PDIRUNLOCK; 504 505 if ((flags & ISLASTCN) && nameiop == RENAME) 506 return (EOPNOTSUPP); 507 508 if (dvp->v_type != VDIR) 509 return (ENOTDIR); 510 511 if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT)) 512 return (EIO); 513 514 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td); 515 if (error) 516 return (error); 517 518 if (cnp->cn_namelen == 1 && *pname == '.') { 519 if ((flags & ISLASTCN) && nameiop != LOOKUP) 520 return (EINVAL); 521 *vpp = dvp; 522 VREF(dvp); 523 return (0); 524 } 525 526 if (flags & ISDOTDOT) { 527 if ((flags & ISLASTCN) && nameiop != LOOKUP) 528 return (EINVAL); 529 VOP_UNLOCK(dvp, 0, td); 530 cnp->cn_flags |= PDIRUNLOCK; 531 de = TAILQ_FIRST(&dd->de_dlist); /* "." */ 532 de = TAILQ_NEXT(de, de_list); /* ".." */ 533 de = de->de_dir; 534 error = devfs_allocv(de, dvp->v_mount, vpp, td); 535 if (error || ((flags & LOCKPARENT) && (flags & ISLASTCN))) { 536 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); 537 cnp->cn_flags &= ~PDIRUNLOCK; 538 } 539 return (error); 540 } 541 542 devfs_populate(dmp); 543 dd = dvp->v_data; 544 TAILQ_FOREACH(de, &dd->de_dlist, de_list) { 545 if (cnp->cn_namelen != de->de_dirent->d_namlen) 546 continue; 547 if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name, 548 de->de_dirent->d_namlen) != 0) 549 continue; 550 if (de->de_flags & DE_WHITEOUT) 551 goto notfound; 552 goto found; 553 } 554 555 if (nameiop == DELETE) 556 goto notfound; 557 558 /* 559 * OK, we didn't have an entry for the name we were asked for 560 * so we try to see if anybody can create it on demand. 561 */ 562 pname = devfs_fqpn(specname, dvp, cnp); 563 if (pname == NULL) 564 goto notfound; 565 566 cdev = NULL; 567 EVENTHANDLER_INVOKE(dev_clone, pname, strlen(pname), &cdev); 568 if (cdev == NULL) 569 goto notfound; 570 571 devfs_populate(dmp); 572 573 dde = devfs_itode(dmp, cdev->si_inode); 574 575 if (dde == NULL || *dde == NULL || *dde == DE_DELETED) 576 goto notfound; 577 578 if ((*dde)->de_flags & DE_WHITEOUT) 579 goto notfound; 580 581 de = *dde; 582 goto found; 583 584 notfound: 585 586 if ((nameiop == CREATE || nameiop == RENAME) && 587 (flags & (LOCKPARENT | WANTPARENT)) && (flags & ISLASTCN)) { 588 cnp->cn_flags |= SAVENAME; 589 if (!(flags & LOCKPARENT)) { 590 VOP_UNLOCK(dvp, 0, td); 591 cnp->cn_flags |= PDIRUNLOCK; 592 } 593 return (EJUSTRETURN); 594 } 595 return (ENOENT); 596 597 598 found: 599 600 if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) { 601 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); 602 if (error) 603 return (error); 604 if (*vpp == dvp) { 605 VREF(dvp); 606 *vpp = dvp; 607 return (0); 608 } 609 error = devfs_allocv(de, dvp->v_mount, vpp, td); 610 if (error) 611 return (error); 612 if (!(flags & LOCKPARENT)) { 613 VOP_UNLOCK(dvp, 0, td); 614 cnp->cn_flags |= PDIRUNLOCK; 615 } 616 return (0); 617 } 618 error = devfs_allocv(de, dvp->v_mount, vpp, td); 619 if (error) 620 return (error); 621 if (!(flags & LOCKPARENT) || !(flags & ISLASTCN)) { 622 VOP_UNLOCK(dvp, 0, td); 623 cnp->cn_flags |= PDIRUNLOCK; 624 } 625 return (0); 626 } 627 628 static int 629 devfs_lookup(struct vop_lookup_args *ap) 630 { 631 int j; 632 struct devfs_mount *dmp; 633 634 dmp = VFSTODEVFS(ap->a_dvp->v_mount); 635 lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread); 636 j = devfs_lookupx(ap); 637 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 638 return (j); 639 } 640 641 static int 642 devfs_mknod(struct vop_mknod_args *ap) 643 /* 644 struct vop_mknod_args { 645 struct vnodeop_desc *a_desc; 646 struct vnode *a_dvp; 647 struct vnode **a_vpp; 648 struct componentname *a_cnp; 649 struct vattr *a_vap; 650 }; */ 651 { 652 struct componentname *cnp; 653 struct vnode *dvp, **vpp; 654 struct thread *td; 655 struct devfs_dirent *dd, *de; 656 struct devfs_mount *dmp; 657 int error; 658 659 dvp = ap->a_dvp; 660 dmp = VFSTODEVFS(dvp->v_mount); 661 lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread); 662 663 cnp = ap->a_cnp; 664 vpp = ap->a_vpp; 665 td = cnp->cn_thread; 666 dd = dvp->v_data; 667 668 error = ENOENT; 669 TAILQ_FOREACH(de, &dd->de_dlist, de_list) { 670 if (cnp->cn_namelen != de->de_dirent->d_namlen) 671 continue; 672 if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name, 673 de->de_dirent->d_namlen) != 0) 674 continue; 675 if (de->de_flags & DE_WHITEOUT) 676 break; 677 goto notfound; 678 } 679 if (de == NULL) 680 goto notfound; 681 de->de_flags &= ~DE_WHITEOUT; 682 error = devfs_allocv(de, dvp->v_mount, vpp, td); 683 notfound: 684 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 685 return (error); 686 } 687 688 /* 689 * Open a special file. 690 */ 691 /* ARGSUSED */ 692 static int 693 devfs_open(ap) 694 struct vop_open_args /* { 695 struct vnode *a_vp; 696 int a_mode; 697 struct ucred *a_cred; 698 struct thread *a_td; 699 } */ *ap; 700 { 701 struct thread *td = ap->a_td; 702 struct vnode *vp = ap->a_vp; 703 struct cdev *dev = vp->v_rdev; 704 int error; 705 struct cdevsw *dsw; 706 707 if (vp->v_type == VBLK) 708 return (ENXIO); 709 710 /* Don't allow open if fs is mounted -nodev. */ 711 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) 712 return (ENXIO); 713 714 if (dev == NULL) 715 return (ENXIO); 716 717 /* Make this field valid before any I/O in d_open. */ 718 if (dev->si_iosize_max == 0) 719 dev->si_iosize_max = DFLTPHYS; 720 721 /* 722 * XXX: Disks get special billing here, but it is mostly wrong. 723 * XXX: Disk partitions can overlap and the real checks should 724 * XXX: take this into account, and consequently they need to 725 * XXX: live in the disk slice code. Some checks do. 726 */ 727 if (vn_isdisk(vp, NULL) && ap->a_cred != FSCRED && 728 (ap->a_mode & FWRITE)) { 729 /* 730 * Never allow opens for write if the disk is mounted R/W. 731 */ 732 if (vp->v_rdev->si_mountpoint != NULL && 733 !(vp->v_rdev->si_mountpoint->mnt_flag & MNT_RDONLY)) 734 return (EBUSY); 735 736 /* 737 * When running in secure mode, do not allow opens 738 * for writing if the disk is mounted. 739 */ 740 error = securelevel_ge(td->td_ucred, 1); 741 if (error && vfs_mountedon(vp)) 742 return (error); 743 744 /* 745 * When running in very secure mode, do not allow 746 * opens for writing of any disks. 747 */ 748 error = securelevel_ge(td->td_ucred, 2); 749 if (error) 750 return (error); 751 } 752 753 dsw = dev_refthread(dev); 754 if (dsw == NULL) 755 return (ENXIO); 756 757 /* XXX: Special casing of ttys for deadfs. Probably redundant. */ 758 if (dsw->d_flags & D_TTY) 759 vp->v_vflag |= VV_ISTTY; 760 761 VOP_UNLOCK(vp, 0, td); 762 763 if(!(dsw->d_flags & D_NEEDGIANT)) { 764 DROP_GIANT(); 765 if (dsw->d_fdopen != NULL) 766 error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx); 767 else 768 error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td); 769 PICKUP_GIANT(); 770 } else if (dsw->d_fdopen != NULL) 771 error = dsw->d_fdopen(dev, ap->a_mode, td, ap->a_fdidx); 772 else 773 error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td); 774 775 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 776 777 dev_relthread(dev); 778 779 if (error) 780 return (error); 781 782 if (vn_isdisk(vp, NULL)) { 783 if (!dev->si_bsize_phys) 784 dev->si_bsize_phys = DEV_BSIZE; 785 } 786 return (error); 787 } 788 789 790 static int 791 devfs_pathconf(ap) 792 struct vop_pathconf_args /* { 793 struct vnode *a_vp; 794 int a_name; 795 int *a_retval; 796 } */ *ap; 797 { 798 799 switch (ap->a_name) { 800 case _PC_NAME_MAX: 801 *ap->a_retval = NAME_MAX; 802 return (0); 803 case _PC_PATH_MAX: 804 *ap->a_retval = PATH_MAX; 805 return (0); 806 case _PC_MAC_PRESENT: 807 #ifdef MAC 808 /* 809 * If MAC is enabled, devfs automatically supports 810 * trivial non-persistant label storage. 811 */ 812 *ap->a_retval = 1; 813 #else 814 *ap->a_retval = 0; 815 #endif 816 return (0); 817 default: 818 return (vop_stdpathconf(ap)); 819 } 820 /* NOTREACHED */ 821 } 822 823 /* ARGSUSED */ 824 static int 825 devfs_poll(ap) 826 struct vop_poll_args /* { 827 struct vnode *a_vp; 828 int a_events; 829 struct ucred *a_cred; 830 struct thread *a_td; 831 } */ *ap; 832 { 833 struct cdev *dev; 834 struct cdevsw *dsw; 835 int error; 836 837 dev = ap->a_vp->v_rdev; 838 dsw = dev_refthread(dev); 839 if (dsw == NULL) 840 return(0); 841 KASSERT(dev->si_refcount > 0, 842 ("devfs_poll() on un-referenced struct cdev *(%s)", devtoname(dev))); 843 if (!(dsw->d_flags & D_NEEDGIANT)) { 844 /* XXX: not yet DROP_GIANT(); */ 845 error = dsw->d_poll(dev, ap->a_events, ap->a_td); 846 /* XXX: not yet PICKUP_GIANT(); */ 847 } else 848 error = dsw->d_poll(dev, ap->a_events, ap->a_td); 849 dev_relthread(dev); 850 return(error); 851 } 852 853 /* 854 * Print out the contents of a special device vnode. 855 */ 856 static int 857 devfs_print(ap) 858 struct vop_print_args /* { 859 struct vnode *a_vp; 860 } */ *ap; 861 { 862 863 printf("\tdev %s\n", devtoname(ap->a_vp->v_rdev)); 864 return (0); 865 } 866 867 /* 868 * Vnode op for read 869 */ 870 /* ARGSUSED */ 871 static int 872 devfs_read(ap) 873 struct vop_read_args /* { 874 struct vnode *a_vp; 875 struct uio *a_uio; 876 int a_ioflag; 877 struct ucred *a_cred; 878 } */ *ap; 879 { 880 struct vnode *vp; 881 struct thread *td; 882 struct uio *uio; 883 struct cdev *dev; 884 int error, resid; 885 struct cdevsw *dsw; 886 887 vp = ap->a_vp; 888 dev = vp->v_rdev; 889 uio = ap->a_uio; 890 td = uio->uio_td; 891 resid = uio->uio_resid; 892 893 if (resid == 0) 894 return (0); 895 896 KASSERT(dev->si_refcount > 0, 897 ("specread() on un-referenced struct cdev *(%s)", devtoname(dev))); 898 dsw = dev_refthread(dev); 899 if (dsw == NULL) 900 return (ENXIO); 901 VOP_UNLOCK(vp, 0, td); 902 if (!(dsw->d_flags & D_NEEDGIANT)) { 903 DROP_GIANT(); 904 error = dsw->d_read(dev, uio, ap->a_ioflag); 905 PICKUP_GIANT(); 906 } else 907 error = dsw->d_read(dev, uio, ap->a_ioflag); 908 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 909 dev_relthread(dev); 910 if (uio->uio_resid != resid || (error == 0 && resid != 0)) 911 vfs_timestamp(&dev->si_atime); 912 return (error); 913 } 914 915 static int 916 devfs_readdir(ap) 917 struct vop_readdir_args /* { 918 struct vnode *a_vp; 919 struct uio *a_uio; 920 struct ucred *a_cred; 921 int *a_eofflag; 922 int *a_ncookies; 923 u_long **a_cookies; 924 } */ *ap; 925 { 926 int error; 927 struct uio *uio; 928 struct dirent *dp; 929 struct devfs_dirent *dd; 930 struct devfs_dirent *de; 931 struct devfs_mount *dmp; 932 off_t off, oldoff; 933 int ncookies = 0; 934 u_long *cookiebuf, *cookiep; 935 struct dirent *dps, *dpe; 936 937 if (ap->a_vp->v_type != VDIR) 938 return (ENOTDIR); 939 940 uio = ap->a_uio; 941 if (uio->uio_offset < 0) 942 return (EINVAL); 943 944 dmp = VFSTODEVFS(ap->a_vp->v_mount); 945 lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread); 946 devfs_populate(dmp); 947 error = 0; 948 de = ap->a_vp->v_data; 949 off = 0; 950 oldoff = uio->uio_offset; 951 TAILQ_FOREACH(dd, &de->de_dlist, de_list) { 952 if (dd->de_flags & DE_WHITEOUT) 953 continue; 954 if (dd->de_dirent->d_type == DT_DIR) 955 de = dd->de_dir; 956 else 957 de = dd; 958 dp = dd->de_dirent; 959 if (dp->d_reclen > uio->uio_resid) 960 break; 961 dp->d_fileno = de->de_inode; 962 if (off >= uio->uio_offset) { 963 ncookies++; 964 error = uiomove(dp, dp->d_reclen, uio); 965 if (error) 966 break; 967 } 968 off += dp->d_reclen; 969 } 970 if( !error && ap->a_ncookies != NULL && ap->a_cookies != NULL ) { 971 MALLOC(cookiebuf, u_long *, ncookies * sizeof(u_long), 972 M_TEMP, M_WAITOK); 973 cookiep = cookiebuf; 974 dps = (struct dirent *)((char *)uio->uio_iov->iov_base - 975 (uio->uio_offset - oldoff)); 976 dpe = (struct dirent *) uio->uio_iov->iov_base; 977 for( dp = dps; 978 dp < dpe; 979 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) { 980 oldoff += dp->d_reclen; 981 *cookiep++ = (u_long) oldoff; 982 } 983 *ap->a_ncookies = ncookies; 984 *ap->a_cookies = cookiebuf; 985 } 986 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 987 uio->uio_offset = off; 988 return (error); 989 } 990 991 static int 992 devfs_readlink(ap) 993 struct vop_readlink_args /* { 994 struct vnode *a_vp; 995 struct uio *a_uio; 996 struct ucred *a_cead; 997 } */ *ap; 998 { 999 int error; 1000 struct devfs_dirent *de; 1001 1002 de = ap->a_vp->v_data; 1003 error = uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio); 1004 return (error); 1005 } 1006 1007 static int 1008 devfs_reclaim(ap) 1009 struct vop_reclaim_args /* { 1010 struct vnode *a_vp; 1011 } */ *ap; 1012 { 1013 struct vnode *vp = ap->a_vp; 1014 struct devfs_dirent *de; 1015 int i; 1016 1017 de = vp->v_data; 1018 if (de != NULL) 1019 de->de_vnode = NULL; 1020 vp->v_data = NULL; 1021 if (vp->v_rdev != NULL && vp->v_rdev != NULL) { 1022 i = vcount(vp); 1023 if ((vp->v_rdev->si_flags & SI_CHEAPCLONE) && i == 0 && 1024 (vp->v_rdev->si_flags & SI_NAMED)) 1025 destroy_dev(vp->v_rdev); 1026 } 1027 return (0); 1028 } 1029 1030 static int 1031 devfs_remove(ap) 1032 struct vop_remove_args /* { 1033 struct vnode *a_dvp; 1034 struct vnode *a_vp; 1035 struct componentname *a_cnp; 1036 } */ *ap; 1037 { 1038 struct vnode *vp = ap->a_vp; 1039 struct devfs_dirent *dd; 1040 struct devfs_dirent *de; 1041 struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount); 1042 1043 lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread); 1044 dd = ap->a_dvp->v_data; 1045 de = vp->v_data; 1046 if (de->de_dirent->d_type == DT_LNK) { 1047 TAILQ_REMOVE(&dd->de_dlist, de, de_list); 1048 if (de->de_vnode) 1049 de->de_vnode->v_data = NULL; 1050 #ifdef MAC 1051 mac_destroy_devfsdirent(de); 1052 #endif 1053 FREE(de, M_DEVFS); 1054 } else { 1055 de->de_flags |= DE_WHITEOUT; 1056 } 1057 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 1058 return (0); 1059 } 1060 1061 /* 1062 * Revoke is called on a tty when a terminal session ends. The vnode 1063 * is orphaned by setting v_op to deadfs so we need to let go of it 1064 * as well so that we create a new one next time around. 1065 */ 1066 static int 1067 devfs_revoke(ap) 1068 struct vop_revoke_args /* { 1069 struct vnode *a_vp; 1070 int a_flags; 1071 } */ *ap; 1072 { 1073 struct vnode *vp = ap->a_vp; 1074 struct devfs_dirent *de; 1075 1076 de = vp->v_data; 1077 de->de_vnode = NULL; 1078 vop_revoke(ap); 1079 return (0); 1080 } 1081 1082 static int 1083 devfs_rioctl(ap) 1084 struct vop_ioctl_args /* { 1085 struct vnode *a_vp; 1086 u_long a_command; 1087 caddr_t a_data; 1088 int a_fflag; 1089 struct ucred *a_cred; 1090 struct thread *a_td; 1091 } */ *ap; 1092 { 1093 int error; 1094 struct devfs_mount *dmp; 1095 1096 dmp = VFSTODEVFS(ap->a_vp->v_mount); 1097 lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread); 1098 devfs_populate(dmp); 1099 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 1100 error = devfs_rules_ioctl(ap->a_vp->v_mount, ap->a_command, ap->a_data, 1101 ap->a_td); 1102 return (error); 1103 } 1104 1105 static int 1106 devfs_rread(ap) 1107 struct vop_read_args /* { 1108 struct vnode *a_vp; 1109 struct uio *a_uio; 1110 int a_ioflag; 1111 struct ucred *a_cred; 1112 } */ *ap; 1113 { 1114 1115 if (ap->a_vp->v_type != VDIR) 1116 return (EINVAL); 1117 return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL)); 1118 } 1119 1120 static int 1121 devfs_setattr(ap) 1122 struct vop_setattr_args /* { 1123 struct vnode *a_vp; 1124 struct vattr *a_vap; 1125 struct ucred *a_cred; 1126 struct proc *a_p; 1127 } */ *ap; 1128 { 1129 struct devfs_dirent *de; 1130 struct vattr *vap; 1131 struct vnode *vp; 1132 int c, error; 1133 uid_t uid; 1134 gid_t gid; 1135 1136 vap = ap->a_vap; 1137 vp = ap->a_vp; 1138 if ((vap->va_type != VNON) || 1139 (vap->va_nlink != VNOVAL) || 1140 (vap->va_fsid != VNOVAL) || 1141 (vap->va_fileid != VNOVAL) || 1142 (vap->va_blocksize != VNOVAL) || 1143 (vap->va_flags != VNOVAL && vap->va_flags != 0) || 1144 (vap->va_rdev != VNOVAL) || 1145 ((int)vap->va_bytes != VNOVAL) || 1146 (vap->va_gen != VNOVAL)) { 1147 return (EINVAL); 1148 } 1149 1150 de = vp->v_data; 1151 if (vp->v_type == VDIR) 1152 de = de->de_dir; 1153 1154 error = c = 0; 1155 if (vap->va_uid == (uid_t)VNOVAL) 1156 uid = de->de_uid; 1157 else 1158 uid = vap->va_uid; 1159 if (vap->va_gid == (gid_t)VNOVAL) 1160 gid = de->de_gid; 1161 else 1162 gid = vap->va_gid; 1163 if (uid != de->de_uid || gid != de->de_gid) { 1164 if (((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid || 1165 (gid != de->de_gid && !groupmember(gid, ap->a_cred))) && 1166 (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)) != 0) 1167 return (error); 1168 de->de_uid = uid; 1169 de->de_gid = gid; 1170 c = 1; 1171 } 1172 1173 if (vap->va_mode != (mode_t)VNOVAL) { 1174 if ((ap->a_cred->cr_uid != de->de_uid) && 1175 (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL))) 1176 return (error); 1177 de->de_mode = vap->va_mode; 1178 c = 1; 1179 } 1180 1181 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 1182 /* See the comment in ufs_vnops::ufs_setattr(). */ 1183 if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) && 1184 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 1185 (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td)))) 1186 return (error); 1187 if (vap->va_atime.tv_sec != VNOVAL) { 1188 if (vp->v_type == VCHR) 1189 vp->v_rdev->si_atime = vap->va_atime; 1190 else 1191 de->de_atime = vap->va_atime; 1192 } 1193 if (vap->va_mtime.tv_sec != VNOVAL) { 1194 if (vp->v_type == VCHR) 1195 vp->v_rdev->si_mtime = vap->va_mtime; 1196 else 1197 de->de_mtime = vap->va_mtime; 1198 } 1199 c = 1; 1200 } 1201 1202 if (c) { 1203 if (vp->v_type == VCHR) 1204 vfs_timestamp(&vp->v_rdev->si_ctime); 1205 else 1206 vfs_timestamp(&de->de_mtime); 1207 } 1208 return (0); 1209 } 1210 1211 #ifdef MAC 1212 static int 1213 devfs_setlabel(ap) 1214 struct vop_setlabel_args /* { 1215 struct vnode *a_vp; 1216 struct mac *a_label; 1217 struct ucred *a_cred; 1218 struct thread *a_td; 1219 } */ *ap; 1220 { 1221 struct vnode *vp; 1222 struct devfs_dirent *de; 1223 1224 vp = ap->a_vp; 1225 de = vp->v_data; 1226 1227 mac_relabel_vnode(ap->a_cred, vp, ap->a_label); 1228 mac_update_devfsdirent(vp->v_mount, de, vp); 1229 1230 return (0); 1231 } 1232 #endif 1233 1234 static int doslowdown = 0; 1235 SYSCTL_INT(_debug, OID_AUTO, doslowdown, CTLFLAG_RW, &doslowdown, 0, ""); 1236 1237 static int 1238 devfs_specstrategy(ap) 1239 struct vop_specstrategy_args /* { 1240 struct vnode *a_vp; 1241 struct buf *a_bp; 1242 } */ *ap; 1243 { 1244 struct vnode *vp = ap->a_vp; 1245 struct buf *bp = ap->a_bp; 1246 struct mount *mp; 1247 struct thread *td = curthread; 1248 1249 KASSERT(ap->a_vp->v_rdev == ap->a_bp->b_dev, 1250 ("%s, dev %s != %s", __func__, 1251 devtoname(ap->a_vp->v_rdev), 1252 devtoname(ap->a_bp->b_dev))); 1253 KASSERT(bp->b_iocmd == BIO_READ || bp->b_iocmd == BIO_WRITE, 1254 ("Wrong b_iocmd buf=%p cmd=%d", bp, bp->b_iocmd)); 1255 1256 /* 1257 * Slow down disk requests for niced processes. 1258 */ 1259 if (doslowdown && td && td->td_proc->p_nice > 0) { 1260 msleep(td, NULL, PPAUSE | PCATCH, "ioslow", 1261 td->td_proc->p_nice); 1262 } 1263 /* 1264 * Collect statistics on synchronous and asynchronous read 1265 * and write counts for disks that have associated filesystems. 1266 */ 1267 if (vn_isdisk(vp, NULL) && (mp = vp->v_rdev->si_mountpoint) != NULL) { 1268 if (bp->b_iocmd == BIO_WRITE) { 1269 if (bp->b_lock.lk_lockholder == LK_KERNPROC) 1270 mp->mnt_stat.f_asyncwrites++; 1271 else 1272 mp->mnt_stat.f_syncwrites++; 1273 } else { 1274 if (bp->b_lock.lk_lockholder == LK_KERNPROC) 1275 mp->mnt_stat.f_asyncreads++; 1276 else 1277 mp->mnt_stat.f_syncreads++; 1278 } 1279 } 1280 1281 dev_strategy(bp); 1282 1283 return (0); 1284 } 1285 1286 static int 1287 devfs_symlink(ap) 1288 struct vop_symlink_args /* { 1289 struct vnode *a_dvp; 1290 struct vnode **a_vpp; 1291 struct componentname *a_cnp; 1292 struct vattr *a_vap; 1293 char *a_target; 1294 } */ *ap; 1295 { 1296 int i, error; 1297 struct devfs_dirent *dd; 1298 struct devfs_dirent *de; 1299 struct devfs_mount *dmp; 1300 struct thread *td; 1301 1302 td = ap->a_cnp->cn_thread; 1303 KASSERT(td == curthread, ("devfs_symlink: td != curthread")); 1304 error = suser(td); 1305 if (error) 1306 return(error); 1307 dmp = VFSTODEVFS(ap->a_dvp->v_mount); 1308 dd = ap->a_dvp->v_data; 1309 de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen); 1310 de->de_uid = 0; 1311 de->de_gid = 0; 1312 de->de_mode = 0755; 1313 de->de_inode = dmp->dm_inode++; 1314 de->de_dirent->d_type = DT_LNK; 1315 i = strlen(ap->a_target) + 1; 1316 MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK); 1317 bcopy(ap->a_target, de->de_symlink, i); 1318 lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, td); 1319 #ifdef MAC 1320 mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de); 1321 #endif 1322 TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); 1323 devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td); 1324 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, td); 1325 return (0); 1326 } 1327 1328 /* 1329 * Vnode op for write 1330 */ 1331 /* ARGSUSED */ 1332 static int 1333 devfs_write(ap) 1334 struct vop_write_args /* { 1335 struct vnode *a_vp; 1336 struct uio *a_uio; 1337 int a_ioflag; 1338 struct ucred *a_cred; 1339 } */ *ap; 1340 { 1341 struct vnode *vp; 1342 struct thread *td; 1343 struct uio *uio; 1344 struct cdev *dev; 1345 int error, resid; 1346 struct cdevsw *dsw; 1347 1348 vp = ap->a_vp; 1349 dev = vp->v_rdev; 1350 uio = ap->a_uio; 1351 td = uio->uio_td; 1352 resid = uio->uio_resid; 1353 1354 dsw = dev_refthread(dev); 1355 if (dsw == NULL) 1356 return (ENXIO); 1357 VOP_UNLOCK(vp, 0, td); 1358 KASSERT(dev->si_refcount > 0, 1359 ("devfs_write() on un-referenced struct cdev *(%s)", 1360 devtoname(dev))); 1361 if (!(dsw->d_flags & D_NEEDGIANT)) { 1362 DROP_GIANT(); 1363 error = dsw->d_write(dev, uio, ap->a_ioflag); 1364 PICKUP_GIANT(); 1365 } else 1366 error = dsw->d_write(dev, uio, ap->a_ioflag); 1367 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1368 dev_relthread(dev); 1369 if (uio->uio_resid != resid || (error == 0 && resid != 0)) { 1370 vfs_timestamp(&dev->si_ctime); 1371 dev->si_mtime = dev->si_ctime; 1372 } 1373 return (error); 1374 } 1375 1376 1377 static struct vnodeopv_entry_desc devfs_vnodeop_entries[] = { 1378 { &vop_default_desc, (vop_t *) vop_defaultop }, 1379 { &vop_access_desc, (vop_t *) devfs_access }, 1380 { &vop_getattr_desc, (vop_t *) devfs_getattr }, 1381 { &vop_ioctl_desc, (vop_t *) devfs_rioctl }, 1382 { &vop_lookup_desc, (vop_t *) devfs_lookup }, 1383 { &vop_mknod_desc, (vop_t *) devfs_mknod }, 1384 { &vop_pathconf_desc, (vop_t *) devfs_pathconf }, 1385 { &vop_read_desc, (vop_t *) devfs_rread }, 1386 { &vop_readdir_desc, (vop_t *) devfs_readdir }, 1387 { &vop_readlink_desc, (vop_t *) devfs_readlink }, 1388 { &vop_reclaim_desc, (vop_t *) devfs_reclaim }, 1389 { &vop_remove_desc, (vop_t *) devfs_remove }, 1390 { &vop_revoke_desc, (vop_t *) devfs_revoke }, 1391 { &vop_setattr_desc, (vop_t *) devfs_setattr }, 1392 #ifdef MAC 1393 { &vop_setlabel_desc, (vop_t *) devfs_setlabel }, 1394 #endif 1395 { &vop_symlink_desc, (vop_t *) devfs_symlink }, 1396 { NULL, NULL } 1397 }; 1398 1399 static struct vnodeopv_desc devfs_vnodeop_opv_desc = 1400 { &devfs_vnodeop_p, devfs_vnodeop_entries }; 1401 1402 VNODEOP_SET(devfs_vnodeop_opv_desc); 1403 1404 static struct vnodeopv_entry_desc devfs_specop_entries[] = { 1405 { &vop_default_desc, (vop_t *) vop_defaultop }, 1406 { &vop_access_desc, (vop_t *) devfs_access }, 1407 { &vop_advlock_desc, (vop_t *) devfs_advlock }, 1408 { &vop_bmap_desc, (vop_t *) vop_panic }, 1409 { &vop_close_desc, (vop_t *) devfs_close }, 1410 { &vop_create_desc, (vop_t *) vop_panic }, 1411 { &vop_fsync_desc, (vop_t *) devfs_fsync }, 1412 { &vop_getattr_desc, (vop_t *) devfs_getattr }, 1413 { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount }, 1414 { &vop_ioctl_desc, (vop_t *) devfs_ioctl }, 1415 { &vop_kqfilter_desc, (vop_t *) devfs_kqfilter }, 1416 { &vop_lease_desc, (vop_t *) vop_null }, 1417 { &vop_link_desc, (vop_t *) vop_panic }, 1418 { &vop_mkdir_desc, (vop_t *) vop_panic }, 1419 { &vop_mknod_desc, (vop_t *) vop_panic }, 1420 { &vop_open_desc, (vop_t *) devfs_open }, 1421 { &vop_pathconf_desc, (vop_t *) devfs_pathconf }, 1422 { &vop_poll_desc, (vop_t *) devfs_poll }, 1423 { &vop_print_desc, (vop_t *) devfs_print }, 1424 { &vop_read_desc, (vop_t *) devfs_read }, 1425 { &vop_readdir_desc, (vop_t *) vop_panic }, 1426 { &vop_readlink_desc, (vop_t *) vop_panic }, 1427 { &vop_reallocblks_desc, (vop_t *) vop_panic }, 1428 { &vop_reclaim_desc, (vop_t *) devfs_reclaim }, 1429 { &vop_remove_desc, (vop_t *) devfs_remove }, 1430 { &vop_rename_desc, (vop_t *) vop_panic }, 1431 { &vop_revoke_desc, (vop_t *) devfs_revoke }, 1432 { &vop_rmdir_desc, (vop_t *) vop_panic }, 1433 { &vop_setattr_desc, (vop_t *) devfs_setattr }, 1434 #ifdef MAC 1435 { &vop_setlabel_desc, (vop_t *) devfs_setlabel }, 1436 #endif 1437 { &vop_specstrategy_desc, (vop_t *) devfs_specstrategy }, 1438 { &vop_strategy_desc, (vop_t *) vop_panic }, 1439 { &vop_symlink_desc, (vop_t *) vop_panic }, 1440 { &vop_write_desc, (vop_t *) devfs_write }, 1441 { NULL, NULL } 1442 }; 1443 1444 static struct vnodeopv_desc devfs_specop_opv_desc = 1445 { &devfs_specop_p, devfs_specop_entries }; 1446 1447 VNODEOP_SET(devfs_specop_opv_desc); 1448