|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)spec_vnops.c 7.37 (Berkeley) 5/30/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "proc.h" ! 38: #include "systm.h" ! 39: #include "kernel.h" ! 40: #include "conf.h" ! 41: #include "buf.h" ! 42: #include "mount.h" ! 43: #include "namei.h" ! 44: #include "vnode.h" ! 45: #include "specdev.h" ! 46: #include "stat.h" ! 47: #include "errno.h" ! 48: #include "ioctl.h" ! 49: #include "file.h" ! 50: #include "disklabel.h" ! 51: ! 52: /* symbolic sleep message strings for devices */ ! 53: char devopn[] = "devopn"; ! 54: char devio[] = "devio"; ! 55: char devwait[] = "devwait"; ! 56: char devin[] = "devin"; ! 57: char devout[] = "devout"; ! 58: char devioc[] = "devioc"; ! 59: char devcls[] = "devcls"; ! 60: ! 61: struct vnodeops spec_vnodeops = { ! 62: spec_lookup, /* lookup */ ! 63: spec_create, /* create */ ! 64: spec_mknod, /* mknod */ ! 65: spec_open, /* open */ ! 66: spec_close, /* close */ ! 67: spec_access, /* access */ ! 68: spec_getattr, /* getattr */ ! 69: spec_setattr, /* setattr */ ! 70: spec_read, /* read */ ! 71: spec_write, /* write */ ! 72: spec_ioctl, /* ioctl */ ! 73: spec_select, /* select */ ! 74: spec_mmap, /* mmap */ ! 75: spec_fsync, /* fsync */ ! 76: spec_seek, /* seek */ ! 77: spec_remove, /* remove */ ! 78: spec_link, /* link */ ! 79: spec_rename, /* rename */ ! 80: spec_mkdir, /* mkdir */ ! 81: spec_rmdir, /* rmdir */ ! 82: spec_symlink, /* symlink */ ! 83: spec_readdir, /* readdir */ ! 84: spec_readlink, /* readlink */ ! 85: spec_abortop, /* abortop */ ! 86: spec_inactive, /* inactive */ ! 87: spec_reclaim, /* reclaim */ ! 88: spec_lock, /* lock */ ! 89: spec_unlock, /* unlock */ ! 90: spec_bmap, /* bmap */ ! 91: spec_strategy, /* strategy */ ! 92: spec_print, /* print */ ! 93: spec_islocked, /* islocked */ ! 94: spec_advlock, /* advlock */ ! 95: }; ! 96: ! 97: /* ! 98: * Trivial lookup routine that always fails. ! 99: */ ! 100: spec_lookup(vp, ndp, p) ! 101: struct vnode *vp; ! 102: struct nameidata *ndp; ! 103: struct proc *p; ! 104: { ! 105: ! 106: ndp->ni_dvp = vp; ! 107: ndp->ni_vp = NULL; ! 108: return (ENOTDIR); ! 109: } ! 110: ! 111: /* ! 112: * Open a special file: Don't allow open if fs is mounted -nodev, ! 113: * and don't allow opens of block devices that are currently mounted. ! 114: * Otherwise, call device driver open function. ! 115: */ ! 116: /* ARGSUSED */ ! 117: spec_open(vp, mode, cred, p) ! 118: register struct vnode *vp; ! 119: int mode; ! 120: struct ucred *cred; ! 121: struct proc *p; ! 122: { ! 123: dev_t dev = (dev_t)vp->v_rdev; ! 124: register int maj = major(dev); ! 125: int error; ! 126: ! 127: if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV)) ! 128: return (ENXIO); ! 129: ! 130: switch (vp->v_type) { ! 131: ! 132: case VCHR: ! 133: if ((u_int)maj >= nchrdev) ! 134: return (ENXIO); ! 135: VOP_UNLOCK(vp); ! 136: error = (*cdevsw[maj].d_open)(dev, mode, S_IFCHR, p); ! 137: VOP_LOCK(vp); ! 138: return (error); ! 139: ! 140: case VBLK: ! 141: if ((u_int)maj >= nblkdev) ! 142: return (ENXIO); ! 143: if (error = mountedon(vp)) ! 144: return (error); ! 145: return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK, p)); ! 146: } ! 147: return (0); ! 148: } ! 149: ! 150: /* ! 151: * Vnode op for read ! 152: */ ! 153: /* ARGSUSED */ ! 154: spec_read(vp, uio, ioflag, cred) ! 155: register struct vnode *vp; ! 156: register struct uio *uio; ! 157: int ioflag; ! 158: struct ucred *cred; ! 159: { ! 160: struct proc *p = uio->uio_procp; ! 161: struct buf *bp; ! 162: daddr_t bn; ! 163: long bsize, bscale; ! 164: struct partinfo dpart; ! 165: register int n, on; ! 166: int error = 0; ! 167: extern int mem_no; ! 168: ! 169: #ifdef DIAGNOSTIC ! 170: if (uio->uio_rw != UIO_READ) ! 171: panic("spec_read mode"); ! 172: if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) ! 173: panic("spec_read proc"); ! 174: #endif ! 175: if (uio->uio_resid == 0) ! 176: return (0); ! 177: ! 178: switch (vp->v_type) { ! 179: ! 180: case VCHR: ! 181: /* ! 182: * Negative offsets allowed only for /dev/kmem ! 183: */ ! 184: if (uio->uio_offset < 0 && major(vp->v_rdev) != mem_no) ! 185: return (EINVAL); ! 186: VOP_UNLOCK(vp); ! 187: error = (*cdevsw[major(vp->v_rdev)].d_read) ! 188: (vp->v_rdev, uio, ioflag); ! 189: VOP_LOCK(vp); ! 190: return (error); ! 191: ! 192: case VBLK: ! 193: if (uio->uio_offset < 0) ! 194: return (EINVAL); ! 195: bsize = BLKDEV_IOSIZE; ! 196: if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, ! 197: (caddr_t)&dpart, FREAD, p) == 0) { ! 198: if (dpart.part->p_fstype == FS_BSDFFS && ! 199: dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) ! 200: bsize = dpart.part->p_frag * ! 201: dpart.part->p_fsize; ! 202: } ! 203: bscale = bsize / DEV_BSIZE; ! 204: do { ! 205: bn = (uio->uio_offset / DEV_BSIZE) &~ (bscale - 1); ! 206: on = uio->uio_offset % bsize; ! 207: n = MIN((unsigned)(bsize - on), uio->uio_resid); ! 208: if (vp->v_lastr + bscale == bn) ! 209: error = breada(vp, bn, (int)bsize, bn + bscale, ! 210: (int)bsize, NOCRED, &bp); ! 211: else ! 212: error = bread(vp, bn, (int)bsize, NOCRED, &bp); ! 213: vp->v_lastr = bn; ! 214: n = MIN(n, bsize - bp->b_resid); ! 215: if (error) { ! 216: brelse(bp); ! 217: return (error); ! 218: } ! 219: error = uiomove(bp->b_un.b_addr + on, n, uio); ! 220: if (n + on == bsize) ! 221: bp->b_flags |= B_AGE; ! 222: brelse(bp); ! 223: } while (error == 0 && uio->uio_resid > 0 && n != 0); ! 224: return (error); ! 225: ! 226: default: ! 227: panic("spec_read type"); ! 228: } ! 229: /* NOTREACHED */ ! 230: } ! 231: ! 232: /* ! 233: * Vnode op for write ! 234: */ ! 235: /* ARGSUSED */ ! 236: spec_write(vp, uio, ioflag, cred) ! 237: register struct vnode *vp; ! 238: register struct uio *uio; ! 239: int ioflag; ! 240: struct ucred *cred; ! 241: { ! 242: struct proc *p = uio->uio_procp; ! 243: struct buf *bp; ! 244: daddr_t bn; ! 245: int bsize, blkmask; ! 246: struct partinfo dpart; ! 247: register int n, on; ! 248: int error = 0; ! 249: extern int mem_no; ! 250: ! 251: #ifdef DIAGNOSTIC ! 252: if (uio->uio_rw != UIO_WRITE) ! 253: panic("spec_write mode"); ! 254: if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) ! 255: panic("spec_write proc"); ! 256: #endif ! 257: ! 258: switch (vp->v_type) { ! 259: ! 260: case VCHR: ! 261: /* ! 262: * Negative offsets allowed only for /dev/kmem ! 263: */ ! 264: if (uio->uio_offset < 0 && major(vp->v_rdev) != mem_no) ! 265: return (EINVAL); ! 266: VOP_UNLOCK(vp); ! 267: error = (*cdevsw[major(vp->v_rdev)].d_write) ! 268: (vp->v_rdev, uio, ioflag); ! 269: VOP_LOCK(vp); ! 270: return (error); ! 271: ! 272: case VBLK: ! 273: if (uio->uio_resid == 0) ! 274: return (0); ! 275: if (uio->uio_offset < 0) ! 276: return (EINVAL); ! 277: bsize = BLKDEV_IOSIZE; ! 278: if ((*bdevsw[major(vp->v_rdev)].d_ioctl)(vp->v_rdev, DIOCGPART, ! 279: (caddr_t)&dpart, FREAD, p) == 0) { ! 280: if (dpart.part->p_fstype == FS_BSDFFS && ! 281: dpart.part->p_frag != 0 && dpart.part->p_fsize != 0) ! 282: bsize = dpart.part->p_frag * ! 283: dpart.part->p_fsize; ! 284: } ! 285: blkmask = (bsize / DEV_BSIZE) - 1; ! 286: do { ! 287: bn = (uio->uio_offset / DEV_BSIZE) &~ blkmask; ! 288: on = uio->uio_offset % bsize; ! 289: n = MIN((unsigned)(bsize - on), uio->uio_resid); ! 290: if (n == bsize) ! 291: bp = getblk(vp, bn, bsize); ! 292: else ! 293: error = bread(vp, bn, bsize, NOCRED, &bp); ! 294: n = MIN(n, bsize - bp->b_resid); ! 295: if (error) { ! 296: brelse(bp); ! 297: return (error); ! 298: } ! 299: error = uiomove(bp->b_un.b_addr + on, n, uio); ! 300: if (n + on == bsize) { ! 301: bp->b_flags |= B_AGE; ! 302: bawrite(bp); ! 303: } else ! 304: bdwrite(bp); ! 305: } while (error == 0 && uio->uio_resid > 0 && n != 0); ! 306: return (error); ! 307: ! 308: default: ! 309: panic("spec_write type"); ! 310: } ! 311: /* NOTREACHED */ ! 312: } ! 313: ! 314: /* ! 315: * Device ioctl operation. ! 316: */ ! 317: /* ARGSUSED */ ! 318: spec_ioctl(vp, com, data, fflag, cred, p) ! 319: struct vnode *vp; ! 320: int com; ! 321: caddr_t data; ! 322: int fflag; ! 323: struct ucred *cred; ! 324: struct proc *p; ! 325: { ! 326: dev_t dev = vp->v_rdev; ! 327: ! 328: switch (vp->v_type) { ! 329: ! 330: case VCHR: ! 331: return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data, ! 332: fflag, p)); ! 333: ! 334: case VBLK: ! 335: if (com == 0 && (int)data == B_TAPE) ! 336: if (bdevsw[major(dev)].d_flags & B_TAPE) ! 337: return (0); ! 338: else ! 339: return (1); ! 340: return ((*bdevsw[major(dev)].d_ioctl)(dev, com, data, ! 341: fflag, p)); ! 342: ! 343: default: ! 344: panic("spec_ioctl"); ! 345: /* NOTREACHED */ ! 346: } ! 347: } ! 348: ! 349: /* ARGSUSED */ ! 350: spec_select(vp, which, fflags, cred, p) ! 351: struct vnode *vp; ! 352: int which, fflags; ! 353: struct ucred *cred; ! 354: struct proc *p; ! 355: { ! 356: register dev_t dev; ! 357: ! 358: switch (vp->v_type) { ! 359: ! 360: default: ! 361: return (1); /* XXX */ ! 362: ! 363: case VCHR: ! 364: dev = vp->v_rdev; ! 365: return (*cdevsw[major(dev)].d_select)(dev, which, p); ! 366: } ! 367: } ! 368: ! 369: /* ! 370: * Just call the device strategy routine ! 371: */ ! 372: spec_strategy(bp) ! 373: register struct buf *bp; ! 374: { ! 375: ! 376: (*bdevsw[major(bp->b_dev)].d_strategy)(bp); ! 377: return (0); ! 378: } ! 379: ! 380: /* ! 381: * This is a noop, simply returning what one has been given. ! 382: */ ! 383: spec_bmap(vp, bn, vpp, bnp) ! 384: struct vnode *vp; ! 385: daddr_t bn; ! 386: struct vnode **vpp; ! 387: daddr_t *bnp; ! 388: { ! 389: ! 390: if (vpp != NULL) ! 391: *vpp = vp; ! 392: if (bnp != NULL) ! 393: *bnp = bn; ! 394: return (0); ! 395: } ! 396: ! 397: /* ! 398: * At the moment we do not do any locking. ! 399: */ ! 400: /* ARGSUSED */ ! 401: spec_lock(vp) ! 402: struct vnode *vp; ! 403: { ! 404: ! 405: return (0); ! 406: } ! 407: ! 408: /* ARGSUSED */ ! 409: spec_unlock(vp) ! 410: struct vnode *vp; ! 411: { ! 412: ! 413: return (0); ! 414: } ! 415: ! 416: /* ! 417: * Device close routine ! 418: */ ! 419: /* ARGSUSED */ ! 420: spec_close(vp, flag, cred, p) ! 421: register struct vnode *vp; ! 422: int flag; ! 423: struct ucred *cred; ! 424: struct proc *p; ! 425: { ! 426: dev_t dev = vp->v_rdev; ! 427: int (*devclose) __P((dev_t, int, int, struct proc *)); ! 428: int mode; ! 429: ! 430: switch (vp->v_type) { ! 431: ! 432: case VCHR: ! 433: /* ! 434: * If the vnode is locked, then we are in the midst ! 435: * of forcably closing the device, otherwise we only ! 436: * close on last reference. ! 437: */ ! 438: if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) ! 439: return (0); ! 440: devclose = cdevsw[major(dev)].d_close; ! 441: mode = S_IFCHR; ! 442: break; ! 443: ! 444: case VBLK: ! 445: /* ! 446: * On last close of a block device (that isn't mounted) ! 447: * we must invalidate any in core blocks, so that ! 448: * we can, for instance, change floppy disks. ! 449: */ ! 450: vflushbuf(vp, 0); ! 451: if (vinvalbuf(vp, 1)) ! 452: return (0); ! 453: /* ! 454: * We do not want to really close the device if it ! 455: * is still in use unless we are trying to close it ! 456: * forcibly. Since every use (buffer, vnode, swap, cmap) ! 457: * holds a reference to the vnode, and because we mark ! 458: * any other vnodes that alias this device, when the ! 459: * sum of the reference counts on all the aliased ! 460: * vnodes descends to one, we are on last close. ! 461: */ ! 462: if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) ! 463: return (0); ! 464: devclose = bdevsw[major(dev)].d_close; ! 465: mode = S_IFBLK; ! 466: break; ! 467: ! 468: default: ! 469: panic("spec_close: not special"); ! 470: } ! 471: ! 472: return ((*devclose)(dev, flag, mode, p)); ! 473: } ! 474: ! 475: /* ! 476: * Print out the contents of a special device vnode. ! 477: */ ! 478: spec_print(vp) ! 479: struct vnode *vp; ! 480: { ! 481: ! 482: printf("tag VT_NON, dev %d, %d\n", major(vp->v_rdev), ! 483: minor(vp->v_rdev)); ! 484: } ! 485: ! 486: /* ! 487: * Special device advisory byte-level locks. ! 488: */ ! 489: /* ARGSUSED */ ! 490: spec_advlock(vp, id, op, fl, flags) ! 491: struct vnode *vp; ! 492: caddr_t id; ! 493: int op; ! 494: struct flock *fl; ! 495: int flags; ! 496: { ! 497: ! 498: return (EOPNOTSUPP); ! 499: } ! 500: ! 501: /* ! 502: * Special device failed operation ! 503: */ ! 504: spec_ebadf() ! 505: { ! 506: ! 507: return (EBADF); ! 508: } ! 509: ! 510: /* ! 511: * Special device bad operation ! 512: */ ! 513: spec_badop() ! 514: { ! 515: ! 516: panic("spec_badop called"); ! 517: /* NOTREACHED */ ! 518: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.