|
|
1.1 ! root 1: /* $Header: /src386/kernel/coh.386/RCS/fs2.c,v 1.10 93/06/14 13:34:40 bin Exp Locker: bin $ */ ! 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 (disk inodes). ! 18: * ! 19: * $Log: fs2.c,v $ ! 20: * Revision 1.10 93/06/14 13:34:40 bin ! 21: * Hal: kernel 78 update ! 22: * ! 23: * Revision 1.5 93/04/14 10:06:31 root ! 24: * r75 ! 25: * ! 26: * Revision 1.2 92/01/06 11:59:27 hal ! 27: * Compile with cc.mwc. ! 28: * ! 29: * Revision 1.1 88/03/24 16:13:51 src ! 30: * Initial revision ! 31: * ! 32: * 87/04/29 Allan Cornish /usr/src/sys/coh/fs2.c ! 33: * Fsminit panic messages now specify the root major and minor device. ! 34: * ! 35: * 86/11/19 Allan Cornish /usr/src/sys/coh/fs2.c ! 36: * setacct() initializes the (new) (IO).io_flag field to 0. ! 37: * ! 38: * 85/08/08 Allan Cornish ! 39: * ialloc() erroneously did a brelease(NULL) if bclaim() returned NULL. ! 40: * also, sbp->s_fmod was set BEFORE the in-core inode table was updated. ! 41: * This created a critical race with msync() (called by sync system call). ! 42: * ! 43: * 85/04/17 Allan Cornish ! 44: * eliminated test for rootdev in msync() ! 45: */ ! 46: #include <sys/coherent.h> ! 47: #include <sys/acct.h> ! 48: #include <sys/buf.h> ! 49: #include <canon.h> ! 50: #include <sys/con.h> ! 51: #include <errno.h> ! 52: #include <sys/filsys.h> ! 53: #include <sys/ino.h> ! 54: #include <sys/inode.h> ! 55: #include <sys/io.h> ! 56: #include <sys/mount.h> ! 57: #include <sys/proc.h> ! 58: #include <sys/stat.h> ! 59: ! 60: #define _INODE_BUSY_DUMP 1 ! 61: ! 62: /* ! 63: * Initialise filesystem. ! 64: */ ! 65: fsminit() ! 66: { ! 67: register MOUNT *mp; ! 68: ! 69: /* ! 70: * Mount the root file system. ! 71: */ ! 72: if ( (mp = fsmount(rootdev, ronflag)) == NULL ) ! 73: panic( "fsminit: no rootdev(%d,%d)", ! 74: major(rootdev), minor(rootdev) ); ! 75: ! 76: /* ! 77: * Set system time from the super block. ! 78: */ ! 79: timer.t_time = mp->m_super.s_time; ! 80: ! 81: /* ! 82: * Access the root directory. ! 83: */ ! 84: if ( (u.u_rdir = iattach(rootdev, ROOTIN)) == NULL ) ! 85: panic( "fsminit: no / on rootdev(%d,%d)", ! 86: major(rootdev), minor(rootdev) ); ! 87: ! 88: /* ! 89: * Record current directory. ! 90: */ ! 91: u.u_cdir = u.u_rdir; ! 92: u.u_cdir->i_refc++; ! 93: iunlock(u.u_rdir); ! 94: } ! 95: ! 96: /* ! 97: * Mount the given device. ! 98: */ ! 99: MOUNT * ! 100: fsmount(dev, f) ! 101: register dev_t dev; ! 102: { ! 103: register MOUNT *mp; ! 104: register BUF *bp; ! 105: ! 106: if ((mp=kalloc(sizeof(MOUNT))) == NULL) { ! 107: printf("fsmount(%x,%x): kalloc failed ", dev, f); ! 108: return NULL; ! 109: } ! 110: dopen(dev, (f?IPR:IPR|IPW), DFBLK); ! 111: if (u.u_error) { ! 112: printf("fsmount(%x,%x): dopen failed ", dev, f); ! 113: kfree(mp); ! 114: return NULL; ! 115: } ! 116: if ((bp=bread(dev, (daddr_t)SUPERI, 1)) == NULL) { ! 117: dclose(dev, (f?IPR:IPR|IPW), DFBLK); /* NIGEL */ ! 118: kfree(mp); ! 119: return NULL; ! 120: } ! 121: kkcopy(bp->b_vaddr, &mp->m_super, sizeof(struct filsys)); ! 122: brelease(bp); ! 123: cansuper(&mp->m_super); ! 124: mp->m_ip = NULL; ! 125: mp->m_dev = dev; ! 126: mp->m_flag = f; ! 127: mp->m_super.s_fmod = 0; ! 128: mp->m_next = mountp; ! 129: mountp = mp; ! 130: return (mp); ! 131: } ! 132: ! 133: /* ! 134: * Canonize a super block. ! 135: */ ! 136: cansuper(fsp) ! 137: register struct filsys *fsp; ! 138: { ! 139: register int i; ! 140: ! 141: canint(fsp->s_isize); ! 142: candaddr(fsp->s_fsize); ! 143: canshort(fsp->s_nfree); ! 144: for (i=0; i<NICFREE; i++) ! 145: candaddr(fsp->s_free[i]); ! 146: canshort(fsp->s_ninode); ! 147: for (i=0; i<NICINOD; i++) ! 148: canino(fsp->s_inode[i]); ! 149: cantime(fsp->s_time); ! 150: candaddr(fsp->s_tfree); ! 151: canino(fsp->s_tinode); ! 152: canshort(fsp->s_m); ! 153: canshort(fsp->s_n); ! 154: canlong(fsp->s_unique); ! 155: } ! 156: ! 157: /* ! 158: * Given a pointer to a mount entry, write out all inodes on that device. ! 159: */ ! 160: msync(mp) ! 161: register MOUNT *mp; ! 162: { ! 163: register struct filsys *sbp; ! 164: register BUF *bp; ! 165: ! 166: if ((mp->m_flag&MFRON) != 0) ! 167: return; ! 168: isync(mp->m_dev); ! 169: sbp = &mp->m_super; ! 170: if (sbp->s_fmod==0) ! 171: return; ! 172: bp = bclaim(mp->m_dev, (daddr_t)SUPERI); ! 173: sbp->s_time = timer.t_time; ! 174: sbp->s_fmod = 0; ! 175: kkcopy(sbp, bp->b_vaddr, sizeof(*sbp)); ! 176: cansuper(bp->b_vaddr); ! 177: bwrite(bp, 1); ! 178: brelease(bp); ! 179: } ! 180: ! 181: /* ! 182: * Return the mount entry for the given device. If `f' is not set ! 183: * and the device is read only, don't set the error status. ! 184: */ ! 185: MOUNT * ! 186: getment(dev, f) ! 187: register dev_t dev; ! 188: { ! 189: register MOUNT *mp; ! 190: ! 191: for (mp=mountp; mp!=NULL; mp=mp->m_next) { ! 192: if (mp->m_dev != dev) ! 193: continue; ! 194: if ((mp->m_flag&MFRON) != 0) { ! 195: if (f != 0) ! 196: u.u_error = EROFS; ! 197: return NULL; ! 198: } ! 199: return (mp); ! 200: } ! 201: panic("getment: dev=0x%x", dev); ! 202: } ! 203: ! 204: /* ! 205: * Allocate a new inode with the given mode. The returned inode is locked. ! 206: */ ! 207: INODE * ! 208: ialloc(dev, mode) ! 209: dev_t dev; ! 210: unsigned mode; ! 211: { ! 212: register struct dinode *dip; ! 213: register struct filsys *sbp; ! 214: register ino_t *inop; ! 215: register ino_t ino; ! 216: register BUF *bp; ! 217: register daddr_t b; ! 218: register struct dinode *dipe; ! 219: register ino_t *inope; ! 220: register MOUNT *mp; ! 221: register INODE *ip; ! 222: #if _INODE_BUSY_DUMP ! 223: int eninode, etinode; ! 224: int lninode, ltinode; ! 225: int xninode, xtinode; ! 226: #endif ! 227: ! 228: if ((mp=getment(dev, 1)) == NULL) ! 229: return NULL; ! 230: sbp = &mp->m_super; ! 231: ! 232: #if _INODE_BUSY_DUMP ! 233: eninode = sbp->s_ninode; ! 234: etinode = sbp->s_tinode; ! 235: #endif ! 236: ! 237: for (;;) { ! 238: lock(mp->m_ilock); ! 239: ! 240: #if _INODE_BUSY_DUMP ! 241: lninode = sbp->s_ninode; ! 242: ltinode = sbp->s_tinode; ! 243: #endif ! 244: ! 245: if (sbp->s_ninode == 0) { ! 246: isync(dev); ! 247: ino = 1; ! 248: inop = sbp->s_inode; ! 249: inope = &sbp->s_inode[NICINOD]; ! 250: for (b=INODEI; b<sbp->s_isize; b++) { ! 251: if (bad(dev, b)) { ! 252: ino += INOPB; ! 253: continue; ! 254: } ! 255: if ((bp=bread(dev, b, 1)) == NULL) { ! 256: ino += INOPB; ! 257: continue; ! 258: } ! 259: dip = bp->b_vaddr; ! 260: dipe = &dip[INOPB]; ! 261: for (; dip<dipe; dip++, ino++) { ! 262: if (dip->di_mode != 0) ! 263: continue; ! 264: if (inop >= inope) ! 265: break; ! 266: *inop++ = ino; ! 267: } ! 268: brelease(bp); ! 269: if (inop >= inope) ! 270: break; ! 271: } ! 272: sbp->s_ninode = inop - sbp->s_inode; ! 273: if (sbp->s_ninode == 0) { ! 274: sbp->s_tinode = 0; ! 275: unlock(mp->m_ilock); ! 276: devmsg(dev, "Out of inodes"); ! 277: u.u_error = ENOSPC; ! 278: return NULL; ! 279: } ! 280: } ! 281: ! 282: #if _INODE_BUSY_DUMP ! 283: xninode = sbp->s_ninode; ! 284: xtinode = sbp->s_tinode; ! 285: #endif ! 286: ! 287: ino = sbp->s_inode[--sbp->s_ninode]; ! 288: --sbp->s_tinode; ! 289: sbp->s_fmod = 1; ! 290: unlock(mp->m_ilock); ! 291: if ((ip=iattach(dev, ino)) != NULL) { ! 292: if (ip->i_mode != 0) { ! 293: devmsg(dev, "Inode %u busy", ino); ! 294: ! 295: #if _INODE_BUSY_DUMP ! 296: printf("%x %x rf=%x fl=%x md=%x nl=%x en=%x et=%x ln=%x lt=%x xn=%x xt=%x n=%x t=%x\n", ! 297: mode, ino, ip->i_refc, ip->i_flag, ip->i_mode, ip->i_nlink, ! 298: eninode, etinode, lninode, ltinode, xninode, xtinode, ! 299: sbp->s_ninode, sbp->s_tinode); ! 300: #endif ! 301: ! 302: idetach(ip); ! 303: lock(mp->m_ilock); ! 304: ++sbp->s_tinode; ! 305: sbp->s_fmod = 1; ! 306: unlock(mp->m_ilock); ! 307: continue; ! 308: } ! 309: ip->i_flag = 0; ! 310: ip->i_mode = mode; ! 311: ip->i_nlink = 0; ! 312: ip->i_uid = u.u_uid; ! 313: ip->i_gid = u.u_gid; ! 314: } ! 315: return (ip); ! 316: } ! 317: } ! 318: ! 319: /* ! 320: * Free the inode `ino' on device `dev'. ! 321: */ ! 322: ifree(dev, ino) ! 323: dev_t dev; ! 324: ino_t ino; ! 325: { ! 326: register struct filsys *sbp; ! 327: register MOUNT *mp; ! 328: ! 329: if ((mp=getment(dev, 1)) == NULL) ! 330: return; ! 331: lock(mp->m_ilock); ! 332: sbp = &mp->m_super; ! 333: sbp->s_fmod = 1; ! 334: if (sbp->s_ninode < NICINOD) ! 335: sbp->s_inode[sbp->s_ninode++] = ino; ! 336: sbp->s_tinode++; ! 337: unlock(mp->m_ilock); ! 338: } ! 339: ! 340: /* ! 341: * Free all blocks in the indirect block `b' on the device `dev'. ! 342: * `l' is the level of indirection. ! 343: */ ! 344: indfree(dev, b, l) ! 345: dev_t dev; ! 346: daddr_t b; ! 347: register unsigned l; ! 348: { ! 349: register int i; ! 350: register BUF *bp; ! 351: daddr_t * dp; ! 352: daddr_t b1; ! 353: ! 354: if (b == 0) ! 355: return; ! 356: if (l-->0 && (bp=bread(dev, b, 1))!=NULL) { ! 357: i = NBN; ! 358: while (i-- > 0) { ! 359: dp = bp->b_vaddr; ! 360: if ((b1 = dp[i]) == 0) ! 361: continue; ! 362: candaddr(b1); ! 363: if (l == 0) ! 364: bfree(dev, b1); ! 365: else ! 366: indfree(dev, b1, l); ! 367: } ! 368: brelease(bp); ! 369: } ! 370: bfree(dev, b); ! 371: } ! 372: ! 373: /* ! 374: * Allocate a block from the filesystem mounted of device `dev'. ! 375: */ ! 376: daddr_t ! 377: balloc(dev) ! 378: dev_t dev; ! 379: { ! 380: register struct filsys *sbp; ! 381: register struct fblk *fbp; ! 382: register daddr_t b; ! 383: register BUF *bp; ! 384: register MOUNT *mp; ! 385: ! 386: if ((mp=getment(dev, 1)) == NULL) ! 387: return (0); ! 388: lock(mp->m_flock); ! 389: sbp = &mp->m_super; ! 390: if (sbp->s_nfree == 0) { ! 391: enospc: ! 392: sbp->s_nfree = 0; ! 393: devmsg(dev, "Out of space"); ! 394: u.u_error = ENOSPC; ! 395: b = 0; ! 396: } else { ! 397: sbp->s_fmod = 1; ! 398: if ((b=sbp->s_free[--sbp->s_nfree]) == 0) ! 399: goto enospc; ! 400: if (sbp->s_nfree == 0) { ! 401: if (b >= sbp->s_fsize ! 402: || b < sbp->s_isize ! 403: || (bp = bread(dev, b, 1)) == NULL) { ! 404: ebadflist: ! 405: devmsg(dev, "Bad free list"); ! 406: goto enospc; ! 407: } ! 408: fbp = bp->b_vaddr; ! 409: sbp->s_nfree = fbp->df_nfree; ! 410: canshort(sbp->s_nfree); ! 411: if ((unsigned)sbp->s_nfree > NICFREE) ! 412: goto ebadflist; ! 413: kkcopy(fbp->df_free, sbp->s_free, sizeof(sbp->s_free)); ! 414: canndaddr(sbp->s_free, sbp->s_nfree); ! 415: brelease(bp); ! 416: } ! 417: --sbp->s_tfree; ! 418: if (b >= sbp->s_fsize || b < sbp->s_isize) ! 419: goto ebadflist; ! 420: } ! 421: unlock(mp->m_flock); ! 422: return (b); ! 423: } ! 424: ! 425: /* ! 426: * Free the block `b' on the device `dev'. ! 427: */ ! 428: bfree(dev, b) ! 429: dev_t dev; ! 430: daddr_t b; ! 431: { ! 432: register struct filsys *sbp; ! 433: register struct fblk *fbp; ! 434: register BUF *bp; ! 435: register MOUNT *mp; ! 436: ! 437: if ((mp=getment(dev, 1)) == NULL) ! 438: return; ! 439: sbp = &mp->m_super; ! 440: if (b>=sbp->s_fsize || b<sbp->s_isize) { ! 441: devmsg(dev, "Bad block %u (free)", (unsigned)b); ! 442: return; ! 443: } ! 444: lock(mp->m_flock); ! 445: if (sbp->s_nfree == 0 || sbp->s_nfree == NICFREE) { ! 446: bp = bclaim(dev, b); ! 447: kclear(bp->b_vaddr, BSIZE); ! 448: fbp = bp->b_vaddr; ! 449: fbp->df_nfree = sbp->s_nfree; ! 450: canshort(fbp->df_nfree); ! 451: kkcopy(sbp->s_free, fbp->df_free, sizeof(fbp->df_free)); ! 452: canndaddr(fbp->df_free, sbp->s_nfree); ! 453: bp->b_flag |= BFMOD; ! 454: brelease(bp); ! 455: sbp->s_nfree = 0; ! 456: } ! 457: sbp->s_free[sbp->s_nfree++] = b; ! 458: sbp->s_tfree++; ! 459: sbp->s_fmod = 1; ! 460: unlock(mp->m_flock); ! 461: } ! 462: ! 463: /* ! 464: * Determine if the given block is bad. ! 465: */ ! 466: bad(dev, b) ! 467: dev_t dev; ! 468: daddr_t b; ! 469: { ! 470: register INODE *ip; ! 471: register BUF *bp; ! 472: register int i; ! 473: register int m; ! 474: register int n; ! 475: daddr_t l; ! 476: ! 477: if ((ip=iattach(dev, 1)) == NULL) ! 478: panic("bad()"); ! 479: n = blockn(ip->i_size); ! 480: if ((m=n) > ND) ! 481: m = ND; ! 482: for (i=0; i<m; i++) { ! 483: --n; ! 484: if (b == ip->i_a.i_addr[i]) { ! 485: idetach(ip); ! 486: return (1); ! 487: } ! 488: } ! 489: l = ip->i_a.i_addr[ND]; ! 490: idetach(ip); ! 491: if (n == 0) ! 492: return (0); ! 493: if ((bp=bread(dev, l, 1)) == NULL) ! 494: return (0); ! 495: if ((m=n) > NBN) ! 496: m = NBN; ! 497: for (i=0; i<m; i++) { ! 498: l = ((daddr_t *)bp)[i]; ! 499: candaddr(l); ! 500: if (b == l) { ! 501: brelease(bp); ! 502: return (1); ! 503: } ! 504: } ! 505: brelease(bp); ! 506: return (0); ! 507: } ! 508: ! 509: /* ! 510: * Canonize `n' disk addresses. ! 511: */ ! 512: canndaddr(dp, n) ! 513: register daddr_t *dp; ! 514: register int n; ! 515: { ! 516: while (n--) { ! 517: candaddr(*dp); ! 518: dp++; ! 519: } ! 520: } ! 521: ! 522: /* ! 523: * Convert long to comp_t style number. ! 524: * A comp_t contains 3 bits of base-8 exponent ! 525: * and a 13-bit mantissa. Only unsigned ! 526: * numbers can be comp_t numbers. ! 527: */ ! 528: ! 529: #define MAXMANT 017777 /* 2^13-1 = largest mantissa */ ! 530: ! 531: static comp_t ! 532: ltoc(l) ! 533: long l; ! 534: { ! 535: register int exp; ! 536: ! 537: if (l < 0) ! 538: return (0); ! 539: for (exp = 0; l > MAXMANT; exp++) ! 540: l >>= 3; ! 541: return ((exp<<13) | l); ! 542: } ! 543: ! 544: /* ! 545: * Write out an accounting record. ! 546: */ ! 547: setacct() ! 548: { ! 549: register PROC *pp; ! 550: struct acct acct; ! 551: IO acctio; ! 552: ! 553: if (acctip == NULL) ! 554: return; ! 555: pp = SELF; ! 556: kkcopy(u.u_comm, acct.ac_comm, 10); ! 557: acct.ac_utime = ltoc(pp->p_utime); ! 558: acct.ac_stime = ltoc(pp->p_stime); ! 559: acct.ac_etime = ltoc(timer.t_time - u.u_btime); ! 560: acct.ac_btime = u.u_btime; ! 561: acct.ac_uid = u.u_uid; ! 562: acct.ac_gid = u.u_gid; ! 563: acct.ac_mem = 0; ! 564: acct.ac_io = ltoc(u.u_block); ! 565: acct.ac_tty = pp->p_ttdev; ! 566: acct.ac_flag = u.u_flag; ! 567: ilock(acctip); ! 568: acctio.io_seek = acctip->i_size; ! 569: acctio.io_ioc = sizeof (acct); ! 570: acctio.io.vbase = &acct; ! 571: acctio.io_seg = IOSYS; ! 572: acctio.io_flag = 0; ! 573: iwrite(acctip, &acctio); ! 574: iunlock(acctip); ! 575: u.u_error = 0; ! 576: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.