|
|
1.1 ! root 1: /* $Header: /y/coh.386/RCS/fs3.c,v 1.5 93/04/14 10:06:33 root Exp $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Coherent. ! 17: * Filesystem (I/O). ! 18: * ! 19: * $Log: fs3.c,v $ ! 20: * Revision 1.5 93/04/14 10:06:33 root ! 21: * r75 ! 22: * ! 23: * Revision 1.2 92/01/06 11:59:34 hal ! 24: * Compile with cc.mwc. ! 25: * ! 26: * Revision 1.1 88/03/24 16:13:54 src ! 27: * Initial revision ! 28: * ! 29: * 87/11/25 Allan Cornish /usr/src/sys/coh/fs3.c ! 30: * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr. ! 31: * ! 32: * 86/02/01 Allan Cornish ! 33: * Added code to fwrite() to avoid needless writing of pipe blocks. ! 34: * Throughput on 6 Mhz AT rose from 30 Kbytes/sec to 79 Kbytes/sec. ! 35: */ ! 36: #include <sys/coherent.h> ! 37: #include <sys/buf.h> ! 38: #include <canon.h> ! 39: #include <sys/con.h> ! 40: #include <errno.h> ! 41: #include <sys/filsys.h> ! 42: #include <sys/mount.h> ! 43: #include <sys/io.h> ! 44: #include <sys/ino.h> ! 45: #include <sys/inode.h> ! 46: #include <sys/stat.h> ! 47: ! 48: /* ! 49: * Given an inode, open it. ! 50: */ ! 51: iopen(ip, mode) ! 52: register INODE *ip; ! 53: { ! 54: register int type; ! 55: ! 56: type = ip->i_mode & IFMT; ! 57: switch (type) { ! 58: case IFCHR: ! 59: case IFBLK: ! 60: iunlock(ip); ! 61: dopen(ip->i_a.i_rdev, mode, type==IFCHR ? DFCHR : DFBLK); ! 62: ilock(ip); ! 63: break; ! 64: case IFDIR: ! 65: if (mode & IPW) { ! 66: ! 67: /* Return (EISDIR) if not superuser. */ ! 68: if (super() == 0) { ! 69: /* Override EPERM set when super() failed. */ ! 70: u.u_error = EISDIR; ! 71: return; ! 72: } ! 73: ! 74: /* ! 75: * Opening a directory O_WRONLY is insane, even ! 76: * if you are superuser! ! 77: */ ! 78: if (mode == IPW) { ! 79: u.u_error = EISDIR; ! 80: return; ! 81: } ! 82: } ! 83: break; ! 84: case IFPIPE: ! 85: popen(ip, mode); ! 86: break; ! 87: } ! 88: } ! 89: ! 90: /* ! 91: * Given an inode, close it. ! 92: * ! 93: * NIGEL: Modified for new dclose (). ! 94: */ ! 95: iclose(ip, mode) ! 96: register INODE *ip; ! 97: { ! 98: register int type; ! 99: ! 100: ilock(ip); ! 101: switch (type = ip->i_mode&IFMT) { ! 102: case IFBLK: ! 103: bflush(ip->i_a.i_rdev); ! 104: /* FALL THROUGH */ ! 105: case IFCHR: ! 106: iunlock(ip); ! 107: dclose(ip->i_a.i_rdev, mode, type==IFCHR ? DFCHR : DFBLK); ! 108: ilock(ip); ! 109: break; ! 110: ! 111: case IFPIPE: ! 112: pclose(ip, mode); ! 113: break; ! 114: } ! 115: idetach(ip); ! 116: } ! 117: ! 118: /* ! 119: * Read from a file described by an inode and an io strucuture. ! 120: */ ! 121: iread(ip, iop) ! 122: register INODE *ip; ! 123: register IO *iop; ! 124: { ! 125: if (iop->io_ioc == 0) ! 126: return; ! 127: switch (ip->i_mode&IFMT) { ! 128: case IFCHR: ! 129: dread(ip->i_a.i_rdev, iop); ! 130: break; ! 131: case IFBLK: ! 132: case IFREG: ! 133: case IFDIR: ! 134: fread(ip, iop); ! 135: break; ! 136: case IFPIPE: ! 137: pread(ip, iop); ! 138: break; ! 139: default: ! 140: u.u_error = ENXIO; ! 141: break; ! 142: } ! 143: } ! 144: ! 145: /* ! 146: * Write to a file described by an inode and io structure. ! 147: */ ! 148: iwrite(ip, iop) ! 149: register INODE *ip; ! 150: register IO *iop; ! 151: { ! 152: imod(ip); /* write - mtime */ ! 153: icrt(ip); /* write - ctime */ ! 154: if (iop->io_ioc == 0) ! 155: return; ! 156: switch (ip->i_mode&IFMT) { ! 157: case IFCHR: ! 158: dwrite(ip->i_a.i_rdev, iop); ! 159: break; ! 160: case IFBLK: ! 161: fwrite(ip, iop); ! 162: break; ! 163: case IFREG: ! 164: case IFDIR: ! 165: if (getment(ip->i_dev, 1) == NULL) ! 166: return; ! 167: fwrite(ip, iop); ! 168: break; ! 169: case IFPIPE: ! 170: pwrite(ip, iop); ! 171: break; ! 172: default: ! 173: u.u_error = ENXIO; ! 174: break; ! 175: } ! 176: } ! 177: ! 178: /* ! 179: * Read from a regular or block special file. ! 180: */ ! 181: fread(ip, iop) ! 182: INODE *ip; ! 183: register IO *iop; ! 184: { ! 185: register unsigned n; ! 186: register unsigned i; ! 187: register off_t res; ! 188: register unsigned off; ! 189: register dev_t dev; ! 190: register daddr_t lbn; ! 191: register daddr_t pbn; ! 192: register daddr_t abn; ! 193: register daddr_t zbn; ! 194: register BUF *bp; ! 195: register int blk; ! 196: daddr_t list[NEXREAD]; ! 197: ! 198: if ((ip->i_mode&IFMT) == IFBLK) { ! 199: blk = 1; ! 200: dev = ip->i_a.i_rdev; ! 201: } else { ! 202: blk = 0; ! 203: dev = ip->i_dev; ! 204: } ! 205: abn = 0; ! 206: zbn = 0; ! 207: lbn = blockn(iop->io_seek); ! 208: off = blocko(iop->io_seek); ! 209: res = ip->i_size - iop->io_seek; ! 210: if ( (blk!=0) || ((res>0) && (res>iop->io_ioc)) ) /* unsigned prob */ ! 211: res = iop->io_ioc; /* with io_ioc */ ! 212: if (res <= 0) ! 213: return; ! 214: if (res+off <= BSIZE) { ! 215: bp = blk ? bread(dev, lbn, 1) : vread(ip, lbn); ! 216: if (bp == NULL) ! 217: return; ! 218: iowrite(iop, bp->b_vaddr+off, (unsigned)res); ! 219: brelease(bp); ! 220: return; ! 221: } ! 222: while (res > 0) { ! 223: if (lbn >= zbn) { ! 224: if ((n=blockn(res+BSIZE-1)) > NEXREAD) ! 225: n = NEXREAD; ! 226: if (n <= 0) ! 227: n = 1; ! 228: abn = lbn; ! 229: for (i=0, zbn=lbn; i<n; i++, zbn++) { ! 230: if (blk != 0) ! 231: pbn = zbn; ! 232: else { ! 233: if ((pbn=vmap(ip, zbn)) < 0) ! 234: return; ! 235: if (pbn == 0) { ! 236: list[i] = -1; ! 237: continue; ! 238: } ! 239: } ! 240: list[i] = pbn; ! 241: bread(dev, pbn, 0); ! 242: } ! 243: } ! 244: if ((pbn=list[lbn-abn]) < 0) { ! 245: bp = bclaim(NODEV, (daddr_t)0); ! 246: kclear(bp->b_vaddr, BSIZE); ! 247: } else { ! 248: if ((bp=bread(dev, pbn, 1)) == NULL) ! 249: return; ! 250: } ! 251: n = BSIZE - off; ! 252: n = res>n ? n : res; ! 253: iowrite(iop, bp->b_vaddr+off, n); ! 254: brelease(bp); ! 255: if (u.u_error) ! 256: return; ! 257: lbn++; ! 258: off = 0; ! 259: res -= n; ! 260: } ! 261: } ! 262: ! 263: /* ! 264: * Write to a regular or block special file. ! 265: */ ! 266: fwrite(ip, iop) ! 267: INODE *ip; ! 268: register IO *iop; ! 269: { ! 270: register unsigned n; ! 271: register unsigned off; ! 272: register daddr_t lbn; ! 273: register BUF *bp; ! 274: register int blk; ! 275: register int com; ! 276: ! 277: lbn = blockn(iop->io_seek); ! 278: off = blocko(iop->io_seek); ! 279: blk = (ip->i_mode&IFMT) == IFBLK; ! 280: while (iop->io_ioc > 0) { ! 281: n = BSIZE - off; ! 282: n = iop->io_ioc>n ? n : iop->io_ioc; ! 283: com = off==0 && n==BSIZE; ! 284: if (blk == 0) ! 285: bp = aread(ip, lbn, com); ! 286: else { ! 287: if (com) ! 288: bp = bclaim(ip->i_a.i_rdev, lbn); ! 289: else ! 290: bp = bread(ip->i_a.i_rdev, lbn, 1); ! 291: } ! 292: if (bp == NULL) ! 293: return; ! 294: ioread(iop, bp->b_vaddr+off, n); ! 295: bp->b_flag |= BFMOD; ! 296: if (com && ((ip->i_mode&IFMT) != IFPIPE) ) ! 297: bwrite(bp, 0); ! 298: else ! 299: brelease(bp); ! 300: if (u.u_error) ! 301: return; ! 302: lbn++; ! 303: off = 0; ! 304: if ((iop->io_seek+=n) > ip->i_size) ! 305: if (blk == 0) ! 306: ip->i_size = iop->io_seek; ! 307: } ! 308: } ! 309: ! 310: /* ! 311: * Given an inode pointer, read the requested virtual block and return ! 312: * a buffer with the data. ! 313: */ ! 314: BUF * ! 315: vread(ip, lb) ! 316: register INODE *ip; ! 317: daddr_t lb; ! 318: { ! 319: register daddr_t pb; ! 320: register BUF *bp; ! 321: ! 322: if ((pb=vmap(ip, lb)) < 0) ! 323: return (NULL); ! 324: if (pb != 0) ! 325: return (bread(ip->i_dev, pb, 1)); ! 326: bp = bclaim(NODEV, (daddr_t)0); ! 327: kclear(bp->b_vaddr, BSIZE); ! 328: return (bp); ! 329: } ! 330: ! 331: /* ! 332: * Convert the given virtual block to a physical block for the given inode. ! 333: * If the block does not map onto a physical block because the file is sparse ! 334: * but it does exist, 0 is returned. If an error is encountered, -1 is ! 335: * returned. ! 336: */ ! 337: daddr_t ! 338: vmap(ip, lb) ! 339: register INODE *ip; ! 340: daddr_t lb; ! 341: { ! 342: register BUF *bp; ! 343: register int *lp; ! 344: daddr_t * dp; ! 345: daddr_t pb; ! 346: int list[1+NI]; ! 347: ! 348: if ((lp=lmap(lb, list)) == NULL) ! 349: return (-1); ! 350: pb = ip->i_a.i_addr[*--lp]; ! 351: for (;;) { ! 352: if (pb==0 || lp==list) ! 353: return (pb); ! 354: if ((bp=bread(ip->i_dev, pb, 1)) == NULL) ! 355: return (0); ! 356: dp = bp->b_vaddr; ! 357: pb = dp[*--lp]; ! 358: brelease(bp); ! 359: candaddr(pb); ! 360: } ! 361: } ! 362: ! 363: /* ! 364: * Given an inode pointer, read the requested virtual block and return a ! 365: * buffer with the data. In sparse files, the necessary blocks are allocated. ! 366: * If the flag, `fflag' is set, the final buffer is just claimed rather than ! 367: * read as we are going to change it's contents completely. ! 368: */ ! 369: BUF * ! 370: aread(ip, lb, fflag) ! 371: register INODE *ip; ! 372: daddr_t lb; ! 373: { ! 374: register BUF *bp; ! 375: register int *lp; ! 376: register dev_t dev; ! 377: register int l; ! 378: register int aflag; ! 379: register int lflag; ! 380: daddr_t * dp; ! 381: daddr_t pb; ! 382: int list[1+NI]; ! 383: ! 384: if ((lp=lmap(lb, list)) == NULL) ! 385: return (NULL); ! 386: aflag = 0; ! 387: dev = ip->i_dev; ! 388: pb = ip->i_a.i_addr[l=*--lp]; ! 389: if (pb == 0) { ! 390: aflag = 1; ! 391: if ((pb=balloc(dev)) == 0) ! 392: return (NULL); ! 393: ip->i_a.i_addr[l] = pb; ! 394: } ! 395: for (;;) { ! 396: lflag = lp==list; ! 397: if (aflag==0 && (fflag==0 || lflag==0)) { ! 398: if ((bp=bread(dev, pb, 1)) == NULL) ! 399: return (NULL); ! 400: } else { ! 401: bp = bclaim(dev, pb); ! 402: kclear(bp->b_vaddr, BSIZE); ! 403: bp->b_flag |= BFMOD; ! 404: } ! 405: if (lflag) ! 406: return (bp); ! 407: ! 408: aflag = 0; ! 409: dp = bp->b_vaddr; ! 410: pb = dp[l=*--lp]; ! 411: candaddr(pb); ! 412: if (pb == 0) { ! 413: aflag = 1; ! 414: if ((pb=balloc(dev)) == 0) { ! 415: brelease(bp); ! 416: return (NULL); ! 417: } ! 418: dp[l] = pb; ! 419: candaddr( dp[l] ); ! 420: bp->b_flag |= BFMOD; ! 421: } ! 422: brelease(bp); ! 423: } ! 424: } ! 425: ! 426: /* ! 427: * Given a block number, `b', store the offsets for the indirect blocks ! 428: * backwards in the array, `lp', and return a pointer just after the ! 429: * position where the first offset is stored. ! 430: */ ! 431: int * ! 432: lmap(b, lp) ! 433: register daddr_t b; ! 434: register int *lp; ! 435: { ! 436: register int n; ! 437: ! 438: if (b < ND) { ! 439: *lp++ = b; ! 440: return (lp); ! 441: } ! 442: b -= ND; ! 443: n = NI; ! 444: do { ! 445: if (n-- == 0) { ! 446: u.u_error = EFBIG; ! 447: return (NULL); ! 448: } ! 449: *lp = nbnrem(b); ! 450: ++lp; ! 451: b = nbndiv(b); ! 452: } while (b--); ! 453: *lp++ = ND+NI-1-n; ! 454: return (lp); ! 455: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.