1 /* $NetBSD: spec_vnops.c,v 1.119 2008/05/16 09:22:00 hannken 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.119 2008/05/16 09:22:00 hannken 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, 0, &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, 605 B_MODIFY, &bp); 606 if (error) { 607 brelse(bp, 0); 608 return (error); 609 } 610 n = min(n, bsize - bp->b_resid); 611 error = uiomove((char *)bp->b_data + on, n, uio); 612 if (error) 613 brelse(bp, 0); 614 else { 615 if (n + on == bsize) 616 bawrite(bp); 617 else 618 bdwrite(bp); 619 error = bp->b_error; 620 } 621 } while (error == 0 && uio->uio_resid > 0 && n != 0); 622 return (error); 623 624 default: 625 panic("spec_write type"); 626 } 627 /* NOTREACHED */ 628 } 629 630 /* 631 * Device ioctl operation. 632 */ 633 /* ARGSUSED */ 634 int 635 spec_ioctl(void *v) 636 { 637 struct vop_ioctl_args /* { 638 struct vnode *a_vp; 639 u_long a_command; 640 void *a_data; 641 int a_fflag; 642 kauth_cred_t a_cred; 643 } */ *ap = v; 644 struct vnode *vp; 645 dev_t dev; 646 647 /* 648 * Extract all the info we need from the vnode, taking care to 649 * avoid a race with VOP_REVOKE(). 650 */ 651 652 vp = ap->a_vp; 653 dev = NODEV; 654 mutex_enter(&vp->v_interlock); 655 if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specnode) { 656 dev = vp->v_rdev; 657 } 658 mutex_exit(&vp->v_interlock); 659 if (dev == NODEV) { 660 return ENXIO; 661 } 662 663 switch (vp->v_type) { 664 665 case VCHR: 666 return cdev_ioctl(dev, ap->a_command, ap->a_data, 667 ap->a_fflag, curlwp); 668 669 case VBLK: 670 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 671 return bdev_ioctl(dev, ap->a_command, ap->a_data, 672 ap->a_fflag, curlwp); 673 674 default: 675 panic("spec_ioctl"); 676 /* NOTREACHED */ 677 } 678 } 679 680 /* ARGSUSED */ 681 int 682 spec_poll(void *v) 683 { 684 struct vop_poll_args /* { 685 struct vnode *a_vp; 686 int a_events; 687 } */ *ap = v; 688 struct vnode *vp; 689 dev_t dev; 690 691 /* 692 * Extract all the info we need from the vnode, taking care to 693 * avoid a race with VOP_REVOKE(). 694 */ 695 696 vp = ap->a_vp; 697 dev = NODEV; 698 mutex_enter(&vp->v_interlock); 699 if ((vp->v_iflag & VI_XLOCK) == 0 && vp->v_specnode) { 700 dev = vp->v_rdev; 701 } 702 mutex_exit(&vp->v_interlock); 703 if (dev == NODEV) { 704 return POLLERR; 705 } 706 707 switch (vp->v_type) { 708 709 case VCHR: 710 return cdev_poll(dev, ap->a_events, curlwp); 711 712 default: 713 return (genfs_poll(v)); 714 } 715 } 716 717 /* ARGSUSED */ 718 int 719 spec_kqfilter(void *v) 720 { 721 struct vop_kqfilter_args /* { 722 struct vnode *a_vp; 723 struct proc *a_kn; 724 } */ *ap = v; 725 dev_t dev; 726 727 switch (ap->a_vp->v_type) { 728 729 case VCHR: 730 dev = ap->a_vp->v_rdev; 731 return cdev_kqfilter(dev, ap->a_kn); 732 default: 733 /* 734 * Block devices don't support kqfilter, and refuse it 735 * for any other files (like those vflush()ed) too. 736 */ 737 return (EOPNOTSUPP); 738 } 739 } 740 741 /* 742 * Allow mapping of only D_DISK. This is called only for VBLK. 743 */ 744 int 745 spec_mmap(void *v) 746 { 747 struct vop_mmap_args /* { 748 struct vnode *a_vp; 749 vm_prot_t a_prot; 750 kauth_cred_t a_cred; 751 } */ *ap = v; 752 struct vnode *vp = ap->a_vp; 753 754 KASSERT(vp->v_type == VBLK); 755 if (bdev_type(vp->v_rdev) != D_DISK) 756 return EINVAL; 757 758 return 0; 759 } 760 761 /* 762 * Synch buffers associated with a block device 763 */ 764 /* ARGSUSED */ 765 int 766 spec_fsync(void *v) 767 { 768 struct vop_fsync_args /* { 769 struct vnode *a_vp; 770 kauth_cred_t a_cred; 771 int a_flags; 772 off_t offlo; 773 off_t offhi; 774 } */ *ap = v; 775 struct vnode *vp = ap->a_vp; 776 struct mount *mp; 777 int error; 778 779 if (vp->v_type == VBLK) { 780 if ((mp = vp->v_specmountpoint) != NULL) { 781 error = VFS_FSYNC(mp, vp, ap->a_flags | FSYNC_VFS); 782 if (error != EOPNOTSUPP) 783 return error; 784 } 785 vflushbuf(vp, (ap->a_flags & FSYNC_WAIT) != 0); 786 } 787 return (0); 788 } 789 790 /* 791 * Just call the device strategy routine 792 */ 793 int 794 spec_strategy(void *v) 795 { 796 struct vop_strategy_args /* { 797 struct vnode *a_vp; 798 struct buf *a_bp; 799 } */ *ap = v; 800 struct vnode *vp = ap->a_vp; 801 struct buf *bp = ap->a_bp; 802 int error; 803 804 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 805 806 error = 0; 807 bp->b_dev = vp->v_rdev; 808 if (!(bp->b_flags & B_READ) && 809 (LIST_FIRST(&bp->b_dep)) != NULL && bioopsp) 810 bioopsp->io_start(bp); 811 812 if (!(bp->b_flags & B_READ)) 813 error = fscow_run(bp, false); 814 815 if (error) { 816 bp->b_error = error; 817 biodone(bp); 818 return (error); 819 } 820 821 bdev_strategy(bp); 822 823 return (0); 824 } 825 826 int 827 spec_inactive(void *v) 828 { 829 struct vop_inactive_args /* { 830 struct vnode *a_vp; 831 struct proc *a_l; 832 } */ *ap = v; 833 834 VOP_UNLOCK(ap->a_vp, 0); 835 return (0); 836 } 837 838 /* 839 * This is a noop, simply returning what one has been given. 840 */ 841 int 842 spec_bmap(void *v) 843 { 844 struct vop_bmap_args /* { 845 struct vnode *a_vp; 846 daddr_t a_bn; 847 struct vnode **a_vpp; 848 daddr_t *a_bnp; 849 int *a_runp; 850 } */ *ap = v; 851 852 if (ap->a_vpp != NULL) 853 *ap->a_vpp = ap->a_vp; 854 if (ap->a_bnp != NULL) 855 *ap->a_bnp = ap->a_bn; 856 if (ap->a_runp != NULL) 857 *ap->a_runp = (MAXBSIZE >> DEV_BSHIFT) - 1; 858 return (0); 859 } 860 861 /* 862 * Device close routine 863 */ 864 /* ARGSUSED */ 865 int 866 spec_close(void *v) 867 { 868 struct vop_close_args /* { 869 struct vnode *a_vp; 870 int a_fflag; 871 kauth_cred_t a_cred; 872 } */ *ap = v; 873 struct vnode *vp = ap->a_vp; 874 struct session *sess; 875 dev_t dev = vp->v_rdev; 876 int mode, error, flags, flags1, count; 877 specnode_t *sn; 878 specdev_t *sd; 879 880 flags = vp->v_iflag; 881 sn = vp->v_specnode; 882 sd = sn->sn_dev; 883 884 switch (vp->v_type) { 885 886 case VCHR: 887 /* 888 * Hack: a tty device that is a controlling terminal 889 * has a reference from the session structure. We 890 * cannot easily tell that a character device is a 891 * controlling terminal, unless it is the closing 892 * process' controlling terminal. In that case, if the 893 * open count is 1 release the reference from the 894 * session. Also, remove the link from the tty back to 895 * the session and pgrp. 896 * 897 * XXX V. fishy. 898 */ 899 mutex_enter(proc_lock); 900 sess = curlwp->l_proc->p_session; 901 if (sn->sn_opencnt == 1 && vp == sess->s_ttyvp) { 902 mutex_spin_enter(&tty_lock); 903 sess->s_ttyvp = NULL; 904 if (sess->s_ttyp->t_session != NULL) { 905 sess->s_ttyp->t_pgrp = NULL; 906 sess->s_ttyp->t_session = NULL; 907 mutex_spin_exit(&tty_lock); 908 SESSRELE(sess); 909 mutex_exit(proc_lock); 910 } else { 911 mutex_spin_exit(&tty_lock); 912 if (sess->s_ttyp->t_pgrp != NULL) 913 panic("spec_close: spurious pgrp ref"); 914 mutex_exit(proc_lock); 915 } 916 vrele(vp); 917 } else 918 mutex_exit(proc_lock); 919 920 /* 921 * If the vnode is locked, then we are in the midst 922 * of forcably closing the device, otherwise we only 923 * close on last reference. 924 */ 925 mode = S_IFCHR; 926 break; 927 928 case VBLK: 929 KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp); 930 /* 931 * On last close of a block device (that isn't mounted) 932 * we must invalidate any in core blocks, so that 933 * we can, for instance, change floppy disks. 934 */ 935 error = vinvalbuf(vp, V_SAVE, ap->a_cred, curlwp, 0, 0); 936 if (error) 937 return (error); 938 /* 939 * We do not want to really close the device if it 940 * is still in use unless we are trying to close it 941 * forcibly. Since every use (buffer, vnode, swap, cmap) 942 * holds a reference to the vnode, and because we mark 943 * any other vnodes that alias this device, when the 944 * sum of the reference counts on all the aliased 945 * vnodes descends to one, we are on last close. 946 */ 947 mode = S_IFBLK; 948 break; 949 950 default: 951 panic("spec_close: not special"); 952 } 953 954 mutex_enter(&specfs_lock); 955 sn->sn_opencnt--; 956 count = --sd->sd_opencnt; 957 if (vp->v_type == VBLK) 958 sd->sd_bdevvp = NULL; 959 mutex_exit(&specfs_lock); 960 961 if (count != 0) 962 return 0; 963 964 flags1 = ap->a_fflag; 965 966 /* 967 * if VI_XLOCK is set, then we're going away soon, so make this 968 * non-blocking. Also ensures that we won't wedge in vn_lock below. 969 */ 970 if (flags & VI_XLOCK) 971 flags1 |= FNONBLOCK; 972 973 /* 974 * If we're able to block, release the vnode lock & reacquire. We 975 * might end up sleeping for someone else who wants our queues. They 976 * won't get them if we hold the vnode locked. Also, if VI_XLOCK is 977 * set, don't release the lock as we won't be able to regain it. 978 */ 979 if (!(flags1 & FNONBLOCK)) 980 VOP_UNLOCK(vp, 0); 981 982 if (vp->v_type == VBLK) 983 error = bdev_close(dev, flags1, mode, curlwp); 984 else 985 error = cdev_close(dev, flags1, mode, curlwp); 986 987 if (!(flags1 & FNONBLOCK)) 988 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 989 990 return (error); 991 } 992 993 /* 994 * Print out the contents of a special device vnode. 995 */ 996 int 997 spec_print(void *v) 998 { 999 struct vop_print_args /* { 1000 struct vnode *a_vp; 1001 } */ *ap = v; 1002 1003 printf("dev %d, %d\n", major(ap->a_vp->v_rdev), 1004 minor(ap->a_vp->v_rdev)); 1005 return 0; 1006 } 1007 1008 /* 1009 * Return POSIX pathconf information applicable to special devices. 1010 */ 1011 int 1012 spec_pathconf(void *v) 1013 { 1014 struct vop_pathconf_args /* { 1015 struct vnode *a_vp; 1016 int a_name; 1017 register_t *a_retval; 1018 } */ *ap = v; 1019 1020 switch (ap->a_name) { 1021 case _PC_LINK_MAX: 1022 *ap->a_retval = LINK_MAX; 1023 return (0); 1024 case _PC_MAX_CANON: 1025 *ap->a_retval = MAX_CANON; 1026 return (0); 1027 case _PC_MAX_INPUT: 1028 *ap->a_retval = MAX_INPUT; 1029 return (0); 1030 case _PC_PIPE_BUF: 1031 *ap->a_retval = PIPE_BUF; 1032 return (0); 1033 case _PC_CHOWN_RESTRICTED: 1034 *ap->a_retval = 1; 1035 return (0); 1036 case _PC_VDISABLE: 1037 *ap->a_retval = _POSIX_VDISABLE; 1038 return (0); 1039 case _PC_SYNC_IO: 1040 *ap->a_retval = 1; 1041 return (0); 1042 default: 1043 return (EINVAL); 1044 } 1045 /* NOTREACHED */ 1046 } 1047 1048 /* 1049 * Advisory record locking support. 1050 */ 1051 int 1052 spec_advlock(void *v) 1053 { 1054 struct vop_advlock_args /* { 1055 struct vnode *a_vp; 1056 void *a_id; 1057 int a_op; 1058 struct flock *a_fl; 1059 int a_flags; 1060 } */ *ap = v; 1061 struct vnode *vp = ap->a_vp; 1062 1063 return lf_advlock(ap, &vp->v_speclockf, (off_t)0); 1064 } 1065