1 /* $NetBSD: spec_vnops.c,v 1.117 2008/04/28 20:24:08 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Copyright (c) 1989, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. Neither the name of the University nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 * 57 * @(#)spec_vnops.c 8.15 (Berkeley) 7/14/95 58 */ 59 60 #include <sys/cdefs.h> 61 __KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.117 2008/04/28 20:24:08 martin Exp $"); 62 63 #include <sys/param.h> 64 #include <sys/proc.h> 65 #include <sys/systm.h> 66 #include <sys/kernel.h> 67 #include <sys/conf.h> 68 #include <sys/buf.h> 69 #include <sys/mount.h> 70 #include <sys/namei.h> 71 #include <sys/vnode.h> 72 #include <sys/stat.h> 73 #include <sys/errno.h> 74 #include <sys/ioctl.h> 75 #include <sys/poll.h> 76 #include <sys/file.h> 77 #include <sys/disklabel.h> 78 #include <sys/lockf.h> 79 #include <sys/tty.h> 80 #include <sys/kauth.h> 81 #include <sys/fstrans.h> 82 83 #include <miscfs/genfs/genfs.h> 84 #include <miscfs/specfs/specdev.h> 85 86 /* symbolic sleep message strings for devices */ 87 const char devopn[] = "devopn"; 88 const char devio[] = "devio"; 89 const char devwait[] = "devwait"; 90 const char devin[] = "devin"; 91 const char devout[] = "devout"; 92 const char devioc[] = "devioc"; 93 const char devcls[] = "devcls"; 94 95 vnode_t *specfs_hash[SPECHSZ]; 96 kmutex_t specfs_lock; 97 98 /* 99 * This vnode operations vector is used for special device nodes 100 * created from whole cloth by the kernel. For the ops vector for 101 * vnodes built from special devices found in a filesystem, see (e.g) 102 * ffs_specop_entries[] in ffs_vnops.c or the equivalent for other 103 * filesystems. 104 */ 105 106 int (**spec_vnodeop_p)(void *); 107 const struct vnodeopv_entry_desc spec_vnodeop_entries[] = { 108 { &vop_default_desc, vn_default_error }, 109 { &vop_lookup_desc, spec_lookup }, /* lookup */ 110 { &vop_create_desc, spec_create }, /* create */ 111 { &vop_mknod_desc, spec_mknod }, /* mknod */ 112 { &vop_open_desc, spec_open }, /* open */ 113 { &vop_close_desc, spec_close }, /* close */ 114 { &vop_access_desc, spec_access }, /* access */ 115 { &vop_getattr_desc, spec_getattr }, /* getattr */ 116 { &vop_setattr_desc, spec_setattr }, /* setattr */ 117 { &vop_read_desc, spec_read }, /* read */ 118 { &vop_write_desc, spec_write }, /* write */ 119 { &vop_fcntl_desc, spec_fcntl }, /* fcntl */ 120 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 121 { &vop_poll_desc, spec_poll }, /* poll */ 122 { &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */ 123 { &vop_revoke_desc, spec_revoke }, /* revoke */ 124 { &vop_mmap_desc, spec_mmap }, /* mmap */ 125 { &vop_fsync_desc, spec_fsync }, /* fsync */ 126 { &vop_seek_desc, spec_seek }, /* seek */ 127 { &vop_remove_desc, spec_remove }, /* remove */ 128 { &vop_link_desc, spec_link }, /* link */ 129 { &vop_rename_desc, spec_rename }, /* rename */ 130 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 131 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 132 { &vop_symlink_desc, spec_symlink }, /* symlink */ 133 { &vop_readdir_desc, spec_readdir }, /* readdir */ 134 { &vop_readlink_desc, spec_readlink }, /* readlink */ 135 { &vop_abortop_desc, spec_abortop }, /* abortop */ 136 { &vop_inactive_desc, spec_inactive }, /* inactive */ 137 { &vop_reclaim_desc, spec_reclaim }, /* reclaim */ 138 { &vop_lock_desc, spec_lock }, /* lock */ 139 { &vop_unlock_desc, spec_unlock }, /* unlock */ 140 { &vop_bmap_desc, spec_bmap }, /* bmap */ 141 { &vop_strategy_desc, spec_strategy }, /* strategy */ 142 { &vop_print_desc, spec_print }, /* print */ 143 { &vop_islocked_desc, spec_islocked }, /* islocked */ 144 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 145 { &vop_advlock_desc, spec_advlock }, /* advlock */ 146 { &vop_bwrite_desc, spec_bwrite }, /* bwrite */ 147 { &vop_getpages_desc, spec_getpages }, /* getpages */ 148 { &vop_putpages_desc, spec_putpages }, /* putpages */ 149 { NULL, NULL } 150 }; 151 const struct vnodeopv_desc spec_vnodeop_opv_desc = 152 { &spec_vnodeop_p, spec_vnodeop_entries }; 153 154 /* 155 * Returns true if dev is /dev/mem or /dev/kmem. 156 */ 157 int 158 iskmemdev(dev_t dev) 159 { 160 /* mem_no is emitted by config(8) to generated devsw.c */ 161 extern const int mem_no; 162 163 /* minor 14 is /dev/io on i386 with COMPAT_10 */ 164 return (major(dev) == mem_no && (minor(dev) < 2 || minor(dev) == 14)); 165 } 166 167 /* 168 * Initialize a vnode that represents a device. 169 */ 170 void 171 spec_node_init(vnode_t *vp, dev_t rdev) 172 { 173 specnode_t *sn; 174 specdev_t *sd; 175 vnode_t *vp2; 176 vnode_t **vpp; 177 178 KASSERT(vp->v_type == VBLK || vp->v_type == VCHR); 179 KASSERT(vp->v_specnode == NULL); 180 181 /* 182 * Search the hash table for this device. If known, add a 183 * reference to the device structure. If not known, create 184 * a new entry to represent the device. In all cases add 185 * the vnode to the hash table. 186 */ 187 sn = kmem_alloc(sizeof(*sn), KM_SLEEP); 188 if (sn == NULL) { 189 /* XXX */ 190 panic("spec_node_init: unable to allocate memory"); 191 } 192 sd = kmem_alloc(sizeof(*sd), KM_SLEEP); 193 if (sd == NULL) { 194 /* XXX */ 195 panic("spec_node_init: unable to allocate memory"); 196 } 197 mutex_enter(&specfs_lock); 198 vpp = &specfs_hash[SPECHASH(rdev)]; 199 for (vp2 = *vpp; vp2 != NULL; vp2 = vp2->v_specnext) { 200 KASSERT(vp2->v_specnode != NULL); 201 if (rdev == vp2->v_rdev && vp->v_type == vp2->v_type) { 202 break; 203 } 204 } 205 if (vp2 == NULL) { 206 /* No existing record, create a new one. */ 207 sd->sd_rdev = rdev; 208 sd->sd_mountpoint = NULL; 209 sd->sd_lockf = NULL; 210 sd->sd_refcnt = 1; 211 sd->sd_opencnt = 0; 212 sd->sd_bdevvp = NULL; 213 sn->sn_dev = sd; 214 sd = NULL; 215 } else { 216 /* Use the existing record. */ 217 sn->sn_dev = vp2->v_specnode->sn_dev; 218 sn->sn_dev->sd_refcnt++; 219 } 220 /* Insert vnode into the hash chain. */ 221 sn->sn_opencnt = 0; 222 sn->sn_rdev = rdev; 223 sn->sn_gone = false; 224 vp->v_specnode = sn; 225 vp->v_specnext = *vpp; 226 *vpp = vp; 227 mutex_exit(&specfs_lock); 228 229 /* Free the record we allocated if unused. */ 230 if (sd != NULL) { 231 kmem_free(sd, sizeof(*sd)); 232 } 233 } 234 235 /* 236 * A vnode representing a special device is going away. Close 237 * the device if the vnode holds it open. 238 */ 239 void 240 spec_node_revoke(vnode_t *vp) 241 { 242 specnode_t *sn; 243 specdev_t *sd; 244 245 sn = vp->v_specnode; 246 sd = sn->sn_dev; 247 248 KASSERT(vp->v_type == VBLK || vp->v_type == VCHR); 249 KASSERT(vp->v_specnode != NULL); 250 KASSERT((vp->v_iflag & VI_XLOCK) != 0); 251 KASSERT(sn->sn_gone == false); 252 253 mutex_enter(&specfs_lock); 254 KASSERT(sn->sn_opencnt <= sd->sd_opencnt); 255 if (sn->sn_opencnt != 0) { 256 sd->sd_opencnt -= (sn->sn_opencnt - 1); 257 sn->sn_opencnt = 1; 258 sn->sn_gone = true; 259 mutex_exit(&specfs_lock); 260 261 VOP_CLOSE(vp, FNONBLOCK, NOCRED); 262 263 mutex_enter(&specfs_lock); 264 KASSERT(sn->sn_opencnt == 0); 265 } 266 mutex_exit(&specfs_lock); 267 } 268 269 /* 270 * A vnode representing a special device is being recycled. 271 * Destroy the specfs component. 272 */ 273 void 274 spec_node_destroy(vnode_t *vp) 275 { 276 specnode_t *sn; 277 specdev_t *sd; 278 vnode_t **vpp, *vp2; 279 int refcnt; 280 281 sn = vp->v_specnode; 282 sd = sn->sn_dev; 283 284 KASSERT(vp->v_type == VBLK || vp->v_type == VCHR); 285 KASSERT(vp->v_specnode != NULL); 286 KASSERT(sn->sn_opencnt == 0); 287 288 mutex_enter(&specfs_lock); 289 /* Remove from the hash and destroy the node. */ 290 vpp = &specfs_hash[SPECHASH(vp->v_rdev)]; 291 for (vp2 = *vpp;; vp2 = vp2->v_specnext) { 292 if (vp2 == NULL) { 293 panic("spec_node_destroy: corrupt hash"); 294 } 295 if (vp2 == vp) { 296 KASSERT(vp == *vpp); 297 *vpp = vp->v_specnext; 298 break; 299 } 300 if (vp2->v_specnext == vp) { 301 vp2->v_specnext = vp->v_specnext; 302 break; 303 } 304 } 305 sn = vp->v_specnode; 306 vp->v_specnode = NULL; 307 refcnt = sd->sd_refcnt--; 308 KASSERT(refcnt > 0); 309 mutex_exit(&specfs_lock); 310 311 /* If the device is no longer in use, destroy our record. */ 312 if (refcnt == 1) { 313 KASSERT(sd->sd_opencnt == 0); 314 KASSERT(sd->sd_bdevvp == NULL); 315 kmem_free(sd, sizeof(*sd)); 316 } 317 kmem_free(sn, sizeof(*sn)); 318 } 319 320 /* 321 * Trivial lookup routine that always fails. 322 */ 323 int 324 spec_lookup(void *v) 325 { 326 struct vop_lookup_args /* { 327 struct vnode *a_dvp; 328 struct vnode **a_vpp; 329 struct componentname *a_cnp; 330 } */ *ap = v; 331 332 *ap->a_vpp = NULL; 333 return (ENOTDIR); 334 } 335 336 /* 337 * Open a special file. 338 */ 339 /* ARGSUSED */ 340 int 341 spec_open(void *v) 342 { 343 struct vop_open_args /* { 344 struct vnode *a_vp; 345 int a_mode; 346 kauth_cred_t a_cred; 347 } */ *ap = v; 348 struct lwp *l; 349 struct vnode *vp; 350 dev_t dev; 351 int error; 352 struct partinfo pi; 353 enum kauth_device_req req; 354 specnode_t *sn; 355 specdev_t *sd; 356 357 l = curlwp; 358 vp = ap->a_vp; 359 dev = vp->v_rdev; 360 sn = vp->v_specnode; 361 sd = sn->sn_dev; 362 363 /* 364 * Don't allow open if fs is mounted -nodev. 365 */ 366 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) 367 return (ENXIO); 368 369 switch (ap->a_mode & (FREAD | FWRITE)) { 370 case FREAD | FWRITE: 371 req = KAUTH_REQ_DEVICE_RAWIO_SPEC_RW; 372 break; 373 case FWRITE: 374 req = KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE; 375 break; 376 default: 377 req = KAUTH_REQ_DEVICE_RAWIO_SPEC_READ; 378 break; 379 } 380 381 switch (vp->v_type) { 382 case VCHR: 383 error = kauth_authorize_device_spec(ap->a_cred, req, vp); 384 if (error != 0) 385 return (error); 386 387 /* 388 * Character devices can accept opens from multiple 389 * vnodes. 390 */ 391 mutex_enter(&specfs_lock); 392 if (sn->sn_gone) { 393 mutex_exit(&specfs_lock); 394 return (EBADF); 395 } 396 sd->sd_opencnt++; 397 sn->sn_opencnt++; 398 mutex_exit(&specfs_lock); 399 if (cdev_type(dev) == D_TTY) 400 vp->v_vflag |= VV_ISTTY; 401 VOP_UNLOCK(vp, 0); 402 error = cdev_open(dev, ap->a_mode, S_IFCHR, l); 403 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 404 break; 405 406 case VBLK: 407 error = kauth_authorize_device_spec(ap->a_cred, req, vp); 408 if (error != 0) 409 return (error); 410 411 /* 412 * For block devices, permit only one open. The buffer 413 * cache cannot remain self-consistent with multiple 414 * vnodes holding a block device open. 415 */ 416 mutex_enter(&specfs_lock); 417 if (sn->sn_gone) { 418 mutex_exit(&specfs_lock); 419 return (EBADF); 420 } 421 if (sd->sd_opencnt != 0) { 422 mutex_exit(&specfs_lock); 423 return EBUSY; 424 } 425 sn->sn_opencnt = 1; 426 sd->sd_opencnt = 1; 427 sd->sd_bdevvp = vp; 428 mutex_exit(&specfs_lock); 429 430 error = bdev_open(dev, ap->a_mode, S_IFBLK, l); 431 break; 432 433 case VNON: 434 case VLNK: 435 case VDIR: 436 case VREG: 437 case VBAD: 438 case VFIFO: 439 case VSOCK: 440 default: 441 return 0; 442 } 443 444 mutex_enter(&specfs_lock); 445 if (sn->sn_gone) { 446 if (error == 0) 447 error = EBADF; 448 } else if (error != 0) { 449 sd->sd_opencnt--; 450 sn->sn_opencnt--; 451 if (vp->v_type == VBLK) 452 sd->sd_bdevvp = NULL; 453 454 } 455 mutex_exit(&specfs_lock); 456 457 if (cdev_type(dev) != D_DISK || error != 0) 458 return error; 459 460 if (vp->v_type == VCHR) 461 error = cdev_ioctl(vp->v_rdev, DIOCGPART, &pi, FREAD, curlwp); 462 else 463 error = bdev_ioctl(vp->v_rdev, DIOCGPART, &pi, FREAD, curlwp); 464 if (error == 0) 465 uvm_vnp_setsize(vp, 466 (voff_t)pi.disklab->d_secsize * pi.part->p_size); 467 return 0; 468 } 469 470 /* 471 * Vnode op for read 472 */ 473 /* ARGSUSED */ 474 int 475 spec_read(void *v) 476 { 477 struct vop_read_args /* { 478 struct vnode *a_vp; 479 struct uio *a_uio; 480 int a_ioflag; 481 kauth_cred_t a_cred; 482 } */ *ap = v; 483 struct vnode *vp = ap->a_vp; 484 struct uio *uio = ap->a_uio; 485 struct lwp *l = curlwp; 486 struct buf *bp; 487 daddr_t bn; 488 int bsize, bscale; 489 struct partinfo dpart; 490 int n, on; 491 int error = 0; 492 493 #ifdef DIAGNOSTIC 494 if (uio->uio_rw != UIO_READ) 495 panic("spec_read mode"); 496 if (&uio->uio_vmspace->vm_map != kernel_map && 497 uio->uio_vmspace != curproc->p_vmspace) 498 panic("spec_read proc"); 499 #endif 500 if (uio->uio_resid == 0) 501 return (0); 502 503 switch (vp->v_type) { 504 505 case VCHR: 506 VOP_UNLOCK(vp, 0); 507 error = cdev_read(vp->v_rdev, uio, ap->a_ioflag); 508 vn_lock(vp, LK_SHARED | LK_RETRY); 509 return (error); 510 511 case VBLK: 512 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 513 if (uio->uio_offset < 0) 514 return (EINVAL); 515 bsize = BLKDEV_IOSIZE; 516 if (bdev_ioctl(vp->v_rdev, DIOCGPART, &dpart, FREAD, l) == 0) { 517 if (dpart.part->p_fstype == FS_BSDFFS && 518 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 519 bsize = dpart.part->p_frag * 520 dpart.part->p_fsize; 521 } 522 bscale = bsize >> DEV_BSHIFT; 523 do { 524 bn = (uio->uio_offset >> DEV_BSHIFT) &~ (bscale - 1); 525 on = uio->uio_offset % bsize; 526 n = min((unsigned)(bsize - on), uio->uio_resid); 527 error = bread(vp, bn, bsize, NOCRED, &bp); 528 n = min(n, bsize - bp->b_resid); 529 if (error) { 530 brelse(bp, 0); 531 return (error); 532 } 533 error = uiomove((char *)bp->b_data + on, n, uio); 534 brelse(bp, 0); 535 } while (error == 0 && uio->uio_resid > 0 && n != 0); 536 return (error); 537 538 default: 539 panic("spec_read type"); 540 } 541 /* NOTREACHED */ 542 } 543 544 /* 545 * Vnode op for write 546 */ 547 /* ARGSUSED */ 548 int 549 spec_write(void *v) 550 { 551 struct vop_write_args /* { 552 struct vnode *a_vp; 553 struct uio *a_uio; 554 int a_ioflag; 555 kauth_cred_t a_cred; 556 } */ *ap = v; 557 struct vnode *vp = ap->a_vp; 558 struct uio *uio = ap->a_uio; 559 struct lwp *l = curlwp; 560 struct buf *bp; 561 daddr_t bn; 562 int bsize, bscale; 563 struct partinfo dpart; 564 int n, on; 565 int error = 0; 566 567 #ifdef DIAGNOSTIC 568 if (uio->uio_rw != UIO_WRITE) 569 panic("spec_write mode"); 570 if (&uio->uio_vmspace->vm_map != kernel_map && 571 uio->uio_vmspace != curproc->p_vmspace) 572 panic("spec_write proc"); 573 #endif 574 575 switch (vp->v_type) { 576 577 case VCHR: 578 VOP_UNLOCK(vp, 0); 579 error = cdev_write(vp->v_rdev, uio, ap->a_ioflag); 580 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 581 return (error); 582 583 case VBLK: 584 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 585 if (uio->uio_resid == 0) 586 return (0); 587 if (uio->uio_offset < 0) 588 return (EINVAL); 589 bsize = BLKDEV_IOSIZE; 590 if (bdev_ioctl(vp->v_rdev, DIOCGPART, &dpart, FREAD, l) == 0) { 591 if (dpart.part->p_fstype == FS_BSDFFS && 592 dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) 593 bsize = dpart.part->p_frag * 594 dpart.part->p_fsize; 595 } 596 bscale = bsize >> DEV_BSHIFT; 597 do { 598 bn = (uio->uio_offset >> DEV_BSHIFT) &~ (bscale - 1); 599 on = uio->uio_offset % bsize; 600 n = min((unsigned)(bsize - on), uio->uio_resid); 601 if (n == bsize) 602 bp = getblk(vp, bn, bsize, 0, 0); 603 else 604 error = bread(vp, bn, bsize, NOCRED, &bp); 605 if (error) { 606 brelse(bp, 0); 607 return (error); 608 } 609 n = min(n, bsize - bp->b_resid); 610 error = uiomove((char *)bp->b_data + on, n, uio); 611 if (error) 612 brelse(bp, 0); 613 else { 614 if (n + on == bsize) 615 bawrite(bp); 616 else 617 bdwrite(bp); 618 error = bp->b_error; 619 } 620 } while (error == 0 && uio->uio_resid > 0 && n != 0); 621 return (error); 622 623 default: 624 panic("spec_write type"); 625 } 626 /* NOTREACHED */ 627 } 628 629 /* 630 * Device ioctl operation. 631 */ 632 /* ARGSUSED */ 633 int 634 spec_ioctl(void *v) 635 { 636 struct vop_ioctl_args /* { 637 struct vnode *a_vp; 638 u_long a_command; 639 void *a_data; 640 int a_fflag; 641 kauth_cred_t a_cred; 642 } */ *ap = v; 643 struct vnode *vp; 644 dev_t dev; 645 646 /* 647 * Extract all the info we need from the vnode, taking care to 648 * avoid a race with VOP_REVOKE(). 649 */ 650 651 vp = ap->a_vp; 652 dev = NODEV; 653 mutex_enter(&vp->v_interlock); 654 if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specnode) { 655 dev = vp->v_rdev; 656 } 657 mutex_exit(&vp->v_interlock); 658 if (dev == NODEV) { 659 return ENXIO; 660 } 661 662 switch (vp->v_type) { 663 664 case VCHR: 665 return cdev_ioctl(dev, ap->a_command, ap->a_data, 666 ap->a_fflag, curlwp); 667 668 case VBLK: 669 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 670 return bdev_ioctl(dev, ap->a_command, ap->a_data, 671 ap->a_fflag, curlwp); 672 673 default: 674 panic("spec_ioctl"); 675 /* NOTREACHED */ 676 } 677 } 678 679 /* ARGSUSED */ 680 int 681 spec_poll(void *v) 682 { 683 struct vop_poll_args /* { 684 struct vnode *a_vp; 685 int a_events; 686 } */ *ap = v; 687 struct vnode *vp; 688 dev_t dev; 689 690 /* 691 * Extract all the info we need from the vnode, taking care to 692 * avoid a race with VOP_REVOKE(). 693 */ 694 695 vp = ap->a_vp; 696 dev = NODEV; 697 mutex_enter(&vp->v_interlock); 698 if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specnode) { 699 dev = vp->v_rdev; 700 } 701 mutex_exit(&vp->v_interlock); 702 if (dev == NODEV) { 703 return POLLERR; 704 } 705 706 switch (vp->v_type) { 707 708 case VCHR: 709 return cdev_poll(dev, ap->a_events, curlwp); 710 711 default: 712 return (genfs_poll(v)); 713 } 714 } 715 716 /* ARGSUSED */ 717 int 718 spec_kqfilter(void *v) 719 { 720 struct vop_kqfilter_args /* { 721 struct vnode *a_vp; 722 struct proc *a_kn; 723 } */ *ap = v; 724 dev_t dev; 725 726 switch (ap->a_vp->v_type) { 727 728 case VCHR: 729 dev = ap->a_vp->v_rdev; 730 return cdev_kqfilter(dev, ap->a_kn); 731 default: 732 /* 733 * Block devices don't support kqfilter, and refuse it 734 * for any other files (like those vflush()ed) too. 735 */ 736 return (EOPNOTSUPP); 737 } 738 } 739 740 /* 741 * Allow mapping of only D_DISK. This is called only for VBLK. 742 */ 743 int 744 spec_mmap(void *v) 745 { 746 struct vop_mmap_args /* { 747 struct vnode *a_vp; 748 vm_prot_t a_prot; 749 kauth_cred_t a_cred; 750 } */ *ap = v; 751 struct vnode *vp = ap->a_vp; 752 753 KASSERT(vp->v_type == VBLK); 754 if (bdev_type(vp->v_rdev) != D_DISK) 755 return EINVAL; 756 757 return 0; 758 } 759 760 /* 761 * Synch buffers associated with a block device 762 */ 763 /* ARGSUSED */ 764 int 765 spec_fsync(void *v) 766 { 767 struct vop_fsync_args /* { 768 struct vnode *a_vp; 769 kauth_cred_t a_cred; 770 int a_flags; 771 off_t offlo; 772 off_t offhi; 773 } */ *ap = v; 774 struct vnode *vp = ap->a_vp; 775 776 if (vp->v_type == VBLK) { 777 vflushbuf(vp, (ap->a_flags & FSYNC_WAIT) != 0); 778 } 779 return (0); 780 } 781 782 /* 783 * Just call the device strategy routine 784 */ 785 int 786 spec_strategy(void *v) 787 { 788 struct vop_strategy_args /* { 789 struct vnode *a_vp; 790 struct buf *a_bp; 791 } */ *ap = v; 792 struct vnode *vp = ap->a_vp; 793 struct buf *bp = ap->a_bp; 794 int error; 795 796 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 797 798 error = 0; 799 bp->b_dev = vp->v_rdev; 800 if (!(bp->b_flags & B_READ) && 801 (LIST_FIRST(&bp->b_dep)) != NULL && bioopsp) 802 bioopsp->io_start(bp); 803 804 if (!(bp->b_flags & B_READ)) 805 error = fscow_run(bp, false); 806 807 if (error) { 808 bp->b_error = error; 809 biodone(bp); 810 return (error); 811 } 812 813 bdev_strategy(bp); 814 815 return (0); 816 } 817 818 int 819 spec_inactive(void *v) 820 { 821 struct vop_inactive_args /* { 822 struct vnode *a_vp; 823 struct proc *a_l; 824 } */ *ap = v; 825 826 VOP_UNLOCK(ap->a_vp, 0); 827 return (0); 828 } 829 830 /* 831 * This is a noop, simply returning what one has been given. 832 */ 833 int 834 spec_bmap(void *v) 835 { 836 struct vop_bmap_args /* { 837 struct vnode *a_vp; 838 daddr_t a_bn; 839 struct vnode **a_vpp; 840 daddr_t *a_bnp; 841 int *a_runp; 842 } */ *ap = v; 843 844 if (ap->a_vpp != NULL) 845 *ap->a_vpp = ap->a_vp; 846 if (ap->a_bnp != NULL) 847 *ap->a_bnp = ap->a_bn; 848 if (ap->a_runp != NULL) 849 *ap->a_runp = (MAXBSIZE >> DEV_BSHIFT) - 1; 850 return (0); 851 } 852 853 /* 854 * Device close routine 855 */ 856 /* ARGSUSED */ 857 int 858 spec_close(void *v) 859 { 860 struct vop_close_args /* { 861 struct vnode *a_vp; 862 int a_fflag; 863 kauth_cred_t a_cred; 864 } */ *ap = v; 865 struct vnode *vp = ap->a_vp; 866 struct session *sess; 867 dev_t dev = vp->v_rdev; 868 int mode, error, flags, flags1, count; 869 specnode_t *sn; 870 specdev_t *sd; 871 872 flags = vp->v_iflag; 873 sn = vp->v_specnode; 874 sd = sn->sn_dev; 875 876 switch (vp->v_type) { 877 878 case VCHR: 879 /* 880 * Hack: a tty device that is a controlling terminal 881 * has a reference from the session structure. We 882 * cannot easily tell that a character device is a 883 * controlling terminal, unless it is the closing 884 * process' controlling terminal. In that case, if the 885 * open count is 1 release the reference from the 886 * session. Also, remove the link from the tty back to 887 * the session and pgrp. 888 * 889 * XXX V. fishy. 890 */ 891 mutex_enter(proc_lock); 892 sess = curlwp->l_proc->p_session; 893 if (sn->sn_opencnt == 1 && vp == sess->s_ttyvp) { 894 mutex_spin_enter(&tty_lock); 895 sess->s_ttyvp = NULL; 896 if (sess->s_ttyp->t_session != NULL) { 897 sess->s_ttyp->t_pgrp = NULL; 898 sess->s_ttyp->t_session = NULL; 899 mutex_spin_exit(&tty_lock); 900 SESSRELE(sess); 901 mutex_exit(proc_lock); 902 } else { 903 mutex_spin_exit(&tty_lock); 904 if (sess->s_ttyp->t_pgrp != NULL) 905 panic("spec_close: spurious pgrp ref"); 906 mutex_exit(proc_lock); 907 } 908 vrele(vp); 909 } else 910 mutex_exit(proc_lock); 911 912 /* 913 * If the vnode is locked, then we are in the midst 914 * of forcably closing the device, otherwise we only 915 * close on last reference. 916 */ 917 mode = S_IFCHR; 918 break; 919 920 case VBLK: 921 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 922 /* 923 * On last close of a block device (that isn't mounted) 924 * we must invalidate any in core blocks, so that 925 * we can, for instance, change floppy disks. 926 */ 927 error = vinvalbuf(vp, V_SAVE, ap->a_cred, curlwp, 0, 0); 928 if (error) 929 return (error); 930 /* 931 * We do not want to really close the device if it 932 * is still in use unless we are trying to close it 933 * forcibly. Since every use (buffer, vnode, swap, cmap) 934 * holds a reference to the vnode, and because we mark 935 * any other vnodes that alias this device, when the 936 * sum of the reference counts on all the aliased 937 * vnodes descends to one, we are on last close. 938 */ 939 mode = S_IFBLK; 940 break; 941 942 default: 943 panic("spec_close: not special"); 944 } 945 946 mutex_enter(&specfs_lock); 947 sn->sn_opencnt--; 948 count = --sd->sd_opencnt; 949 if (vp->v_type == VBLK) 950 sd->sd_bdevvp = NULL; 951 mutex_exit(&specfs_lock); 952 953 if (count != 0) 954 return 0; 955 956 flags1 = ap->a_fflag; 957 958 /* 959 * if VI_XLOCK is set, then we're going away soon, so make this 960 * non-blocking. Also ensures that we won't wedge in vn_lock below. 961 */ 962 if (flags & VI_XLOCK) 963 flags1 |= FNONBLOCK; 964 965 /* 966 * If we're able to block, release the vnode lock & reacquire. We 967 * might end up sleeping for someone else who wants our queues. They 968 * won't get them if we hold the vnode locked. Also, if VI_XLOCK is 969 * set, don't release the lock as we won't be able to regain it. 970 */ 971 if (!(flags1 & FNONBLOCK)) 972 VOP_UNLOCK(vp, 0); 973 974 if (vp->v_type == VBLK) 975 error = bdev_close(dev, flags1, mode, curlwp); 976 else 977 error = cdev_close(dev, flags1, mode, curlwp); 978 979 if (!(flags1 & FNONBLOCK)) 980 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 981 982 return (error); 983 } 984 985 /* 986 * Print out the contents of a special device vnode. 987 */ 988 int 989 spec_print(void *v) 990 { 991 struct vop_print_args /* { 992 struct vnode *a_vp; 993 } */ *ap = v; 994 995 printf("dev %d, %d\n", major(ap->a_vp->v_rdev), 996 minor(ap->a_vp->v_rdev)); 997 return 0; 998 } 999 1000 /* 1001 * Return POSIX pathconf information applicable to special devices. 1002 */ 1003 int 1004 spec_pathconf(void *v) 1005 { 1006 struct vop_pathconf_args /* { 1007 struct vnode *a_vp; 1008 int a_name; 1009 register_t *a_retval; 1010 } */ *ap = v; 1011 1012 switch (ap->a_name) { 1013 case _PC_LINK_MAX: 1014 *ap->a_retval = LINK_MAX; 1015 return (0); 1016 case _PC_MAX_CANON: 1017 *ap->a_retval = MAX_CANON; 1018 return (0); 1019 case _PC_MAX_INPUT: 1020 *ap->a_retval = MAX_INPUT; 1021 return (0); 1022 case _PC_PIPE_BUF: 1023 *ap->a_retval = PIPE_BUF; 1024 return (0); 1025 case _PC_CHOWN_RESTRICTED: 1026 *ap->a_retval = 1; 1027 return (0); 1028 case _PC_VDISABLE: 1029 *ap->a_retval = _POSIX_VDISABLE; 1030 return (0); 1031 case _PC_SYNC_IO: 1032 *ap->a_retval = 1; 1033 return (0); 1034 default: 1035 return (EINVAL); 1036 } 1037 /* NOTREACHED */ 1038 } 1039 1040 /* 1041 * Advisory record locking support. 1042 */ 1043 int 1044 spec_advlock(void *v) 1045 { 1046 struct vop_advlock_args /* { 1047 struct vnode *a_vp; 1048 void *a_id; 1049 int a_op; 1050 struct flock *a_fl; 1051 int a_flags; 1052 } */ *ap = v; 1053 struct vnode *vp = ap->a_vp; 1054 1055 return lf_advlock(ap, &vp->v_speclockf, (off_t)0); 1056 } 1057