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