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