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