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