1 /* $OpenBSD: spec_vnops.c,v 1.108 2022/06/26 05:20:42 visa Exp $ */ 2 /* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)spec_vnops.c 8.8 (Berkeley) 11/21/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/proc.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/conf.h> 40 #include <sys/buf.h> 41 #include <sys/mount.h> 42 #include <sys/namei.h> 43 #include <sys/vnode.h> 44 #include <sys/lock.h> 45 #include <sys/stat.h> 46 #include <sys/errno.h> 47 #include <sys/ioctl.h> 48 #include <sys/fcntl.h> 49 #include <sys/disklabel.h> 50 #include <sys/lockf.h> 51 #include <sys/dkio.h> 52 #include <sys/malloc.h> 53 #include <sys/specdev.h> 54 #include <sys/unistd.h> 55 56 #include <uvm/uvm_extern.h> 57 58 #define v_lastr v_specinfo->si_lastr 59 60 int spec_open_clone(struct vop_open_args *); 61 62 struct vnodechain speclisth[SPECHSZ]; 63 64 const struct vops spec_vops = { 65 .vop_lookup = vop_generic_lookup, 66 .vop_create = vop_generic_badop, 67 .vop_mknod = vop_generic_badop, 68 .vop_open = spec_open, 69 .vop_close = spec_close, 70 .vop_access = spec_access, 71 .vop_getattr = spec_getattr, 72 .vop_setattr = spec_setattr, 73 .vop_read = spec_read, 74 .vop_write = spec_write, 75 .vop_ioctl = spec_ioctl, 76 .vop_kqfilter = spec_kqfilter, 77 .vop_revoke = vop_generic_revoke, 78 .vop_fsync = spec_fsync, 79 .vop_remove = vop_generic_badop, 80 .vop_link = vop_generic_badop, 81 .vop_rename = vop_generic_badop, 82 .vop_mkdir = vop_generic_badop, 83 .vop_rmdir = vop_generic_badop, 84 .vop_symlink = vop_generic_badop, 85 .vop_readdir = vop_generic_badop, 86 .vop_readlink = vop_generic_badop, 87 .vop_abortop = vop_generic_badop, 88 .vop_inactive = spec_inactive, 89 .vop_reclaim = nullop, 90 .vop_lock = nullop, 91 .vop_unlock = nullop, 92 .vop_islocked = nullop, 93 .vop_bmap = vop_generic_bmap, 94 .vop_strategy = spec_strategy, 95 .vop_print = spec_print, 96 .vop_pathconf = spec_pathconf, 97 .vop_advlock = spec_advlock, 98 .vop_bwrite = vop_generic_bwrite, 99 }; 100 101 /* 102 * Open a special file. 103 */ 104 int 105 spec_open(void *v) 106 { 107 struct vop_open_args *ap = v; 108 struct proc *p = ap->a_p; 109 struct vnode *vp = ap->a_vp; 110 struct vnode *bvp; 111 dev_t bdev; 112 dev_t dev = (dev_t)vp->v_rdev; 113 int maj = major(dev); 114 int error; 115 116 /* 117 * Don't allow open if fs is mounted -nodev. 118 */ 119 if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) 120 return (ENXIO); 121 122 switch (vp->v_type) { 123 124 case VCHR: 125 if ((u_int)maj >= nchrdev) 126 return (ENXIO); 127 if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) { 128 /* 129 * When running in very secure mode, do not allow 130 * opens for writing of any disk character devices. 131 */ 132 if (securelevel >= 2 && cdevsw[maj].d_type == D_DISK) 133 return (EPERM); 134 /* 135 * When running in secure mode, do not allow opens 136 * for writing of /dev/mem, /dev/kmem, or character 137 * devices whose corresponding block devices are 138 * currently mounted. 139 */ 140 if (securelevel >= 1) { 141 if ((bdev = chrtoblk(dev)) != NODEV && 142 vfinddev(bdev, VBLK, &bvp) && 143 bvp->v_usecount > 0 && 144 (error = vfs_mountedon(bvp))) 145 return (error); 146 if (iskmemdev(dev)) 147 return (EPERM); 148 } 149 } 150 if (cdevsw[maj].d_type == D_TTY) 151 vp->v_flag |= VISTTY; 152 if (cdevsw[maj].d_flags & D_CLONE) 153 return (spec_open_clone(ap)); 154 VOP_UNLOCK(vp); 155 error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, p); 156 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 157 return (error); 158 159 case VBLK: 160 if ((u_int)maj >= nblkdev) 161 return (ENXIO); 162 /* 163 * When running in very secure mode, do not allow 164 * opens for writing of any disk block devices. 165 */ 166 if (securelevel >= 2 && ap->a_cred != FSCRED && 167 (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK) 168 return (EPERM); 169 /* 170 * Do not allow opens of block devices that are 171 * currently mounted. 172 */ 173 if ((error = vfs_mountedon(vp)) != 0) 174 return (error); 175 return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, p)); 176 case VNON: 177 case VLNK: 178 case VDIR: 179 case VREG: 180 case VBAD: 181 case VFIFO: 182 case VSOCK: 183 break; 184 } 185 return (0); 186 } 187 188 /* 189 * Vnode op for read 190 */ 191 int 192 spec_read(void *v) 193 { 194 struct vop_read_args *ap = v; 195 struct vnode *vp = ap->a_vp; 196 struct uio *uio = ap->a_uio; 197 struct proc *p = uio->uio_procp; 198 struct buf *bp; 199 daddr_t bn, nextbn, bscale; 200 int bsize; 201 struct partinfo dpart; 202 size_t n; 203 int on, majordev; 204 int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *); 205 int error = 0; 206 207 #ifdef DIAGNOSTIC 208 if (uio->uio_rw != UIO_READ) 209 panic("spec_read mode"); 210 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 211 panic("spec_read proc"); 212 #endif 213 if (uio->uio_resid == 0) 214 return (0); 215 216 switch (vp->v_type) { 217 218 case VCHR: 219 VOP_UNLOCK(vp); 220 error = (*cdevsw[major(vp->v_rdev)].d_read) 221 (vp->v_rdev, uio, ap->a_ioflag); 222 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 223 return (error); 224 225 case VBLK: 226 if (uio->uio_offset < 0) 227 return (EINVAL); 228 bsize = BLKDEV_IOSIZE; 229 if ((majordev = major(vp->v_rdev)) < nblkdev && 230 (ioctl = bdevsw[majordev].d_ioctl) != NULL && 231 (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) { 232 u_int32_t frag = 233 DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock); 234 u_int32_t fsize = 235 DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock); 236 if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 && 237 fsize != 0) 238 bsize = frag * fsize; 239 } 240 bscale = btodb(bsize); 241 do { 242 bn = btodb(uio->uio_offset) & ~(bscale - 1); 243 on = uio->uio_offset % bsize; 244 n = ulmin((bsize - on), uio->uio_resid); 245 if (vp->v_lastr + bscale == bn) { 246 nextbn = bn + bscale; 247 error = breadn(vp, bn, bsize, &nextbn, &bsize, 248 1, &bp); 249 } else 250 error = bread(vp, bn, bsize, &bp); 251 vp->v_lastr = bn; 252 n = ulmin(n, bsize - bp->b_resid); 253 if (error) { 254 brelse(bp); 255 return (error); 256 } 257 error = uiomove((char *)bp->b_data + on, n, uio); 258 brelse(bp); 259 } while (error == 0 && uio->uio_resid > 0 && n != 0); 260 return (error); 261 262 default: 263 panic("spec_read type"); 264 } 265 /* NOTREACHED */ 266 } 267 268 int 269 spec_inactive(void *v) 270 { 271 struct vop_inactive_args *ap = v; 272 273 VOP_UNLOCK(ap->a_vp); 274 return (0); 275 } 276 277 /* 278 * Vnode op for write 279 */ 280 int 281 spec_write(void *v) 282 { 283 struct vop_write_args *ap = v; 284 struct vnode *vp = ap->a_vp; 285 struct uio *uio = ap->a_uio; 286 struct proc *p = uio->uio_procp; 287 struct buf *bp; 288 daddr_t bn, bscale; 289 int bsize; 290 struct partinfo dpart; 291 size_t n; 292 int on, majordev; 293 int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *); 294 int error = 0; 295 296 #ifdef DIAGNOSTIC 297 if (uio->uio_rw != UIO_WRITE) 298 panic("spec_write mode"); 299 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 300 panic("spec_write proc"); 301 #endif 302 303 switch (vp->v_type) { 304 305 case VCHR: 306 VOP_UNLOCK(vp); 307 error = (*cdevsw[major(vp->v_rdev)].d_write) 308 (vp->v_rdev, uio, ap->a_ioflag); 309 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 310 return (error); 311 312 case VBLK: 313 if (uio->uio_resid == 0) 314 return (0); 315 if (uio->uio_offset < 0) 316 return (EINVAL); 317 bsize = BLKDEV_IOSIZE; 318 if ((majordev = major(vp->v_rdev)) < nblkdev && 319 (ioctl = bdevsw[majordev].d_ioctl) != NULL && 320 (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) { 321 u_int32_t frag = 322 DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock); 323 u_int32_t fsize = 324 DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock); 325 if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 && 326 fsize != 0) 327 bsize = frag * fsize; 328 } 329 bscale = btodb(bsize); 330 do { 331 bn = btodb(uio->uio_offset) & ~(bscale - 1); 332 on = uio->uio_offset % bsize; 333 n = ulmin((bsize - on), uio->uio_resid); 334 error = bread(vp, bn, bsize, &bp); 335 n = ulmin(n, bsize - bp->b_resid); 336 if (error) { 337 brelse(bp); 338 return (error); 339 } 340 error = uiomove((char *)bp->b_data + on, n, uio); 341 if (n + on == bsize) 342 bawrite(bp); 343 else 344 bdwrite(bp); 345 } while (error == 0 && uio->uio_resid > 0 && n != 0); 346 return (error); 347 348 default: 349 panic("spec_write type"); 350 } 351 /* NOTREACHED */ 352 } 353 354 /* 355 * Device ioctl operation. 356 */ 357 int 358 spec_ioctl(void *v) 359 { 360 struct vop_ioctl_args *ap = v; 361 dev_t dev = ap->a_vp->v_rdev; 362 int maj = major(dev); 363 364 switch (ap->a_vp->v_type) { 365 366 case VCHR: 367 return ((*cdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data, 368 ap->a_fflag, ap->a_p)); 369 370 case VBLK: 371 return ((*bdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data, 372 ap->a_fflag, ap->a_p)); 373 374 default: 375 panic("spec_ioctl"); 376 /* NOTREACHED */ 377 } 378 } 379 380 int 381 spec_kqfilter(void *v) 382 { 383 struct vop_kqfilter_args *ap = v; 384 dev_t dev; 385 386 dev = ap->a_vp->v_rdev; 387 388 switch (ap->a_vp->v_type) { 389 default: 390 if (ap->a_kn->kn_flags & (__EV_POLL | __EV_SELECT)) 391 return seltrue_kqfilter(dev, ap->a_kn); 392 break; 393 case VCHR: 394 if (cdevsw[major(dev)].d_kqfilter) 395 return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn); 396 } 397 return (EOPNOTSUPP); 398 } 399 400 /* 401 * Synch buffers associated with a block device 402 */ 403 int 404 spec_fsync(void *v) 405 { 406 struct vop_fsync_args *ap = v; 407 struct vnode *vp = ap->a_vp; 408 struct buf *bp; 409 struct buf *nbp; 410 int s; 411 412 if (vp->v_type == VCHR) 413 return (0); 414 /* 415 * Flush all dirty buffers associated with a block device. 416 */ 417 loop: 418 s = splbio(); 419 LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) { 420 if ((bp->b_flags & B_BUSY)) 421 continue; 422 if ((bp->b_flags & B_DELWRI) == 0) 423 panic("spec_fsync: not dirty"); 424 bremfree(bp); 425 buf_acquire(bp); 426 splx(s); 427 bawrite(bp); 428 goto loop; 429 } 430 if (ap->a_waitfor == MNT_WAIT) { 431 vwaitforio (vp, 0, "spec_fsync", INFSLP); 432 433 #ifdef DIAGNOSTIC 434 if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { 435 splx(s); 436 vprint("spec_fsync: dirty", vp); 437 goto loop; 438 } 439 #endif 440 } 441 splx(s); 442 return (0); 443 } 444 445 int 446 spec_strategy(void *v) 447 { 448 struct vop_strategy_args *ap = v; 449 struct buf *bp = ap->a_bp; 450 int maj = major(bp->b_dev); 451 452 if (LIST_FIRST(&bp->b_dep) != NULL) 453 buf_start(bp); 454 455 (*bdevsw[maj].d_strategy)(bp); 456 return (0); 457 } 458 459 /* 460 * Device close routine 461 */ 462 int 463 spec_close(void *v) 464 { 465 struct vop_close_args *ap = v; 466 struct proc *p = ap->a_p; 467 struct vnode *vp = ap->a_vp; 468 dev_t dev = vp->v_rdev; 469 int (*devclose)(dev_t, int, int, struct proc *); 470 int mode, relock, xlocked, error; 471 int clone = 0; 472 473 switch (vp->v_type) { 474 475 case VCHR: 476 /* 477 * Hack: a tty device that is a controlling terminal 478 * has a reference from the session structure. 479 * We cannot easily tell that a character device is 480 * a controlling terminal, unless it is the closing 481 * process' controlling terminal. In that case, 482 * if the reference count is 2 (this last descriptor 483 * plus the session), release the reference from the session. 484 */ 485 if (vcount(vp) == 2 && p != NULL && p->p_p->ps_pgrp && 486 vp == p->p_p->ps_pgrp->pg_session->s_ttyvp) { 487 vrele(vp); 488 p->p_p->ps_pgrp->pg_session->s_ttyvp = NULL; 489 } 490 if (cdevsw[major(dev)].d_flags & D_CLONE) { 491 clone = 1; 492 } else { 493 /* 494 * If the vnode is locked, then we are in the midst 495 * of forcibly closing the device, otherwise we only 496 * close on last reference. 497 */ 498 mtx_enter(&vnode_mtx); 499 xlocked = (vp->v_lflag & VXLOCK); 500 mtx_leave(&vnode_mtx); 501 if (vcount(vp) > 1 && !xlocked) 502 return (0); 503 } 504 devclose = cdevsw[major(dev)].d_close; 505 mode = S_IFCHR; 506 break; 507 508 case VBLK: 509 /* 510 * On last close of a block device (that isn't mounted) 511 * we must invalidate any in core blocks, so that 512 * we can, for instance, change floppy disks. In order to do 513 * that, we must lock the vnode. If we are coming from 514 * vclean(), the vnode is already locked. 515 */ 516 mtx_enter(&vnode_mtx); 517 xlocked = (vp->v_lflag & VXLOCK); 518 mtx_leave(&vnode_mtx); 519 if (!xlocked) 520 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 521 error = vinvalbuf(vp, V_SAVE, ap->a_cred, p, 0, INFSLP); 522 if (!xlocked) 523 VOP_UNLOCK(vp); 524 if (error) 525 return (error); 526 /* 527 * We do not want to really close the device if it 528 * is still in use unless we are trying to close it 529 * forcibly. Since every use (buffer, vnode, swap, cmap) 530 * holds a reference to the vnode, and because we mark 531 * any other vnodes that alias this device, when the 532 * sum of the reference counts on all the aliased 533 * vnodes descends to one, we are on last close. 534 */ 535 mtx_enter(&vnode_mtx); 536 xlocked = (vp->v_lflag & VXLOCK); 537 mtx_leave(&vnode_mtx); 538 if (vcount(vp) > 1 && !xlocked) 539 return (0); 540 devclose = bdevsw[major(dev)].d_close; 541 mode = S_IFBLK; 542 break; 543 544 default: 545 panic("spec_close: not special"); 546 } 547 548 /* release lock if held and this isn't coming from vclean() */ 549 mtx_enter(&vnode_mtx); 550 xlocked = (vp->v_lflag & VXLOCK); 551 mtx_leave(&vnode_mtx); 552 relock = VOP_ISLOCKED(vp) && !xlocked; 553 if (relock) 554 VOP_UNLOCK(vp); 555 error = (*devclose)(dev, ap->a_fflag, mode, p); 556 if (relock) 557 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 558 559 if (error == 0 && clone) { 560 struct vnode *pvp; 561 562 pvp = vp->v_specparent; /* get parent device */ 563 clrbit(pvp->v_specbitmap, minor(dev) >> CLONE_SHIFT); 564 vrele(pvp); 565 } 566 567 return (error); 568 } 569 570 int 571 spec_getattr(void *v) 572 { 573 struct vop_getattr_args *ap = v; 574 struct vnode *vp = ap->a_vp; 575 int error; 576 577 if (!(vp->v_flag & VCLONE)) 578 return (EBADF); 579 580 vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY); 581 error = VOP_GETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p); 582 VOP_UNLOCK(vp->v_specparent); 583 584 return (error); 585 } 586 587 int 588 spec_setattr(void *v) 589 { 590 struct vop_getattr_args *ap = v; 591 struct proc *p = ap->a_p; 592 struct vnode *vp = ap->a_vp; 593 int error; 594 595 if (!(vp->v_flag & VCLONE)) 596 return (EBADF); 597 598 vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY); 599 error = VOP_SETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, p); 600 VOP_UNLOCK(vp->v_specparent); 601 602 return (error); 603 } 604 605 int 606 spec_access(void *v) 607 { 608 struct vop_access_args *ap = v; 609 struct vnode *vp = ap->a_vp; 610 int error; 611 612 if (!(vp->v_flag & VCLONE)) 613 return (EBADF); 614 615 vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY); 616 error = VOP_ACCESS(vp->v_specparent, ap->a_mode, ap->a_cred, ap->a_p); 617 VOP_UNLOCK(vp->v_specparent); 618 619 return (error); 620 } 621 622 /* 623 * Print out the contents of a special device vnode. 624 */ 625 int 626 spec_print(void *v) 627 { 628 struct vop_print_args *ap = v; 629 630 printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev), 631 minor(ap->a_vp->v_rdev)); 632 return 0; 633 } 634 635 /* 636 * Return POSIX pathconf information applicable to special devices. 637 */ 638 int 639 spec_pathconf(void *v) 640 { 641 struct vop_pathconf_args *ap = v; 642 int error = 0; 643 644 switch (ap->a_name) { 645 case _PC_LINK_MAX: 646 *ap->a_retval = LINK_MAX; 647 break; 648 case _PC_MAX_CANON: 649 *ap->a_retval = MAX_CANON; 650 break; 651 case _PC_MAX_INPUT: 652 *ap->a_retval = MAX_INPUT; 653 break; 654 case _PC_CHOWN_RESTRICTED: 655 *ap->a_retval = 1; 656 break; 657 case _PC_VDISABLE: 658 *ap->a_retval = _POSIX_VDISABLE; 659 break; 660 case _PC_TIMESTAMP_RESOLUTION: 661 *ap->a_retval = 1; 662 break; 663 default: 664 error = EINVAL; 665 break; 666 } 667 668 return (error); 669 } 670 671 /* 672 * Special device advisory byte-level locks. 673 */ 674 int 675 spec_advlock(void *v) 676 { 677 struct vop_advlock_args *ap = v; 678 struct vnode *vp = ap->a_vp; 679 680 return (lf_advlock(&vp->v_speclockf, (off_t)0, ap->a_id, 681 ap->a_op, ap->a_fl, ap->a_flags)); 682 } 683 684 /* 685 * Copyright (c) 2006 Pedro Martelletto <pedro@ambientworks.net> 686 * Copyright (c) 2006 Thordur Bjornsson <thib@openbsd.org> 687 * 688 * Permission to use, copy, modify, and distribute this software for any 689 * purpose with or without fee is hereby granted, provided that the above 690 * copyright notice and this permission notice appear in all copies. 691 * 692 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 693 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 694 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 695 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 696 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 697 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 698 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 699 */ 700 701 #ifdef CLONE_DEBUG 702 #define DNPRINTF(m...) do { printf(m); } while (0) 703 #else 704 #define DNPRINTF(m...) /* nothing */ 705 #endif 706 707 int 708 spec_open_clone(struct vop_open_args *ap) 709 { 710 struct vnode *cvp, *vp = ap->a_vp; 711 struct cloneinfo *cip; 712 int error, i; 713 714 DNPRINTF("cloning vnode\n"); 715 716 if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT)) 717 return (ENXIO); 718 719 for (i = 1; i < CLONE_MAPSZ * NBBY; i++) 720 if (isclr(vp->v_specbitmap, i)) { 721 setbit(vp->v_specbitmap, i); 722 break; 723 } 724 725 if (i == CLONE_MAPSZ * NBBY) 726 return (EBUSY); /* too many open instances */ 727 728 error = cdevvp(makedev(major(vp->v_rdev), 729 (i << CLONE_SHIFT) | minor(vp->v_rdev)), &cvp); 730 if (error) { 731 clrbit(vp->v_specbitmap, i); 732 return (error); /* out of vnodes */ 733 } 734 735 VOP_UNLOCK(vp); 736 737 error = cdevsw[major(vp->v_rdev)].d_open(cvp->v_rdev, ap->a_mode, 738 S_IFCHR, ap->a_p); 739 740 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 741 742 if (error) { 743 vput(cvp); 744 clrbit(vp->v_specbitmap, i); 745 return (error); /* device open failed */ 746 } 747 748 cvp->v_flag |= VCLONE; 749 750 cip = malloc(sizeof(struct cloneinfo), M_TEMP, M_WAITOK); 751 cip->ci_data = vp->v_data; 752 cip->ci_vp = cvp; 753 754 cvp->v_specparent = vp; 755 vp->v_flag |= VCLONED; 756 vp->v_data = cip; 757 758 DNPRINTF("clone of vnode %p is vnode %p\n", vp, cvp); 759 760 return (0); /* device cloned */ 761 } 762