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