6900: #
6901: /*
6902: */
6903:
6904: #include "../param.h"
6905: #include "../systm.h"
6906: #include "../filsys.h"
6907: #include "../conf.h"
6908: #include "../buf.h"
6909: #include "../inode.h"
6910: #include "../user.h"
6911:
6912: /*
6913: * iinit is called once (from main)
6914: * very early in initialization.
6915: * It reads the root's super block
6916: * and initializes the current date
6917: * from the last modified date.
6918: *
6919: * panic: iinit -- cannot read the super
6920: * block. Usually because of an IO error.
6921: */
6922: iinit()
6923: {
6924: register *cp, *bp;
6925:
6926: (*bdevsw[rootdev.d_major].d_open)(rootdev, 1);
6927: bp = bread(rootdev, 1);
6928: cp = getblk(NODEV);
6929: if(u.u_error)
6930: panic("iinit");
6931: bcopy(bp->b_addr, cp->b_addr, 256);
6932: brelse(bp);
6933: mount[0].m_bufp = cp;
6934: mount[0].m_dev = rootdev;
6935: cp = cp->b_addr;
6936: cp->s_flock = 0;
6937: cp->s_ilock = 0;
6938: cp->s_ronly = 0;
6939: time[0] = cp->s_time[0];
6940: time[1] = cp->s_time[1];
6941: }
6942: /* --------------------------- */
6943: /* --------------------------- */
6944:
6945: /*
6946: * alloc will obtain the next available
6947: * free disk block from the free list of
6948: * the specified device.
6949: * The super block has up to 100 remembered
6950: * free blocks; the last of these is read to
6951: * obtain 100 more . . .
6952: *
6953: * no space on dev x/y -- when
6954: * the free list is exhausted.
6955: */
6956: alloc(dev)
6957: {
6958: int bno;
6959: register *bp, *ip, *fp;
6960:
6961: fp = getfs(dev);
6962: while(fp->s_flock)
6963: sleep(&fp->s_flock, PINOD);
6964: do {
6965: if(fp->s_nfree <= 0)
6966: goto nospace;
6967: bno = fp->s_free[--fp->s_nfree];
6968: if(bno == 0)
6969: goto nospace;
6970: } while (badblock(fp, bno, dev));
6971: if(fp->s_nfree <= 0) {
6972: fp->s_flock++;
6973: bp = bread(dev, bno);
6974: ip = bp->b_addr;
6975: fp->s_nfree = *ip++;
6976: bcopy(ip, fp->s_free, 100);
6977: brelse(bp);
6978: fp->s_flock = 0;
6979: wakeup(&fp->s_flock);
6980: }
6981: bp = getblk(dev, bno);
6982: clrbuf(bp);
6983: fp->s_fmod = 1;
6984: return(bp);
6985:
6986: nospace:
6987: fp->s_nfree = 0;
6988: prdev("no space", dev);
6989: u.u_error = ENOSPC;
6990: return(NULL);
6991: }
6992: /* --------------------------- */
6993: /* --------------------------- */
6994:
6995: /*
6996: * place the specified disk block
6997: * back on the free list of the
6998: * specified device.
6999: */
7000: free(dev, bno)
7001: {
7002: register *fp, *bp, *ip;
7003:
7004: fp = getfs(dev);
7005: fp->s_fmod = 1;
7006: while(fp->s_flock)
7007: sleep(&fp->s_flock, PINOD);
7008: if (badblock(fp, bno, dev))
7009: return;
7010: if(fp->s_nfree <= 0) {
7011: fp->s_nfree = 1;
7012: fp->s_free[0] = 0;
7013: }
7014: if(fp->s_nfree >= 100) {
7015: fp->s_flock++;
7016: bp = getblk(dev, bno);
7017: ip = bp->b_addr;
7018: *ip++ = fp->s_nfree;
7019: bcopy(fp->s_free, ip, 100);
7020: fp->s_nfree = 0;
7021: bwrite(bp);
7022: fp->s_flock = 0;
7023: wakeup(&fp->s_flock);
7024: }
7025: fp->s_free[fp->s_nfree++] = bno;
7026: fp->s_fmod = 1;
7027: }
7028: /* --------------------------- */
7029: /* --------------------------- */
7030:
7031: /*
7032: * Check that a block number is in the
7033: * range between the I list and the size
7034: * of the device.
7035: * This is used mainly to check that a
7036: * garbage file system has not been mounted.
7037: *
7038: * bad block on dev x/y -- not in range
7039: */
7040: badblock(afp, abn, dev)
7041: {
7042: register struct filsys *fp;
7043: register char *bn;
7044:
7045: fp = afp;
7046: bn = abn;
7047: if (bn < fp->s_isize+2 || bn >= fp->s_fsize) {
7048: prdev("bad block", dev);
7049: return(1);
7050: }
7051: return(0);
7052: }
7053: /* --------------------------- */
7054: /* --------------------------- */
7055:
7056: /*
7057: * Allocate an unused I node
7058: * on the specified device.
7059: * Used with file creation.
7060: * The algorithm keeps up to
7061: * 100 spare I nodes in the
7062: * super block. When this runs out,
7063: * a linear search through the
7064: * I list is instituted to pick
7065: * up 100 more.
7066: */
7067: ialloc(dev)
7068: {
7069: register *fp, *bp, *ip;
7070: int i, j, k, ino;
7071:
7072: fp = getfs(dev);
7073: while(fp->s_ilock)
7074: sleep(&fp->s_ilock, PINOD);
7075: loop:
7076: if(fp->s_ninode > 0) {
7077: ino = fp->s_inode[--fp->s_ninode];
7078: ip = iget(dev, ino);
7079: if (ip==NULL)
7080: return(NULL);
7081: if(ip->i_mode == 0) {
7082: for(bp = &ip->i_mode; bp < &ip->i_addr[8];)
7083: *bp++ = 0;
7084: fp->s_fmod = 1;
7085: return(ip);
7086: }
7087: /*
7088: * Inode was allocated after all.
7089: * Look some more.
7090: */
7091: iput(ip);
7092: goto loop;
7093: }
7094: fp->s_ilock++;
7095: ino = 0;
7096: for(i=0; i<fp->s_isize; i++) {
7097: bp = bread(dev, i+2);
7098: ip = bp->b_addr;
7099: for(j=0; j<256; j=+16) {
7100: ino++;
7101: if(ip[j] != 0)
7102: continue;
7103: for(k=0; k<NINODE; k++)
7104:
7105: if(dev==inode[k].i_dev && ino==inode[k].i_number)
7106: goto cont;
7107: fp->s_inode[fp->s_ninode++] = ino;
7108: if(fp->s_ninode >= 100)
7109: break;
7110: cont:;
7111: }
7112: brelse(bp);
7113: if(fp->s_ninode >= 100)
7114: break;
7115: }
7116: fp->s_ilock = 0;
7117: wakeup(&fp->s_ilock);
7118: if (fp->s_ninode > 0)
7119: goto loop;
7120: prdev("Out of inodes", dev);
7121: u.u_error = ENOSPC;
7122: return(NULL);
7123: }
7124: /* --------------------------- */
7125: /* --------------------------- */
7126:
7127: /*
7128: * Free the specified I node
7129: * on the specified device.
7130: * The algorithm stores up
7131: * to 100 I nodes in the super
7132: * block and throws away any more.
7133: */
7134: ifree(dev, ino)
7135: {
7136: register *fp;
7137:
7138: fp = getfs(dev);
7139: if(fp->s_ilock)
7140: return;
7141: if(fp->s_ninode >= 100)
7142: return;
7143: fp->s_inode[fp->s_ninode++] = ino;
7144: fp->s_fmod = 1;
7145: }
7146: /* --------------------------- */
7147: /* --------------------------- */
7148:
7149: /*
7150: * getfs maps a device number into
7151: * a pointer to the incore super
7152: * block.
7153: * The algorithm is a linear
7154: * search through the mount table.
7155: * A consistency check of the
7156: * in core free-block and i-node
7157: * counts.
7158: *
7159: * bad count on dev x/y -- the count
7160: * check failed. At this point, all
7161: * the counts are zeroed which will
7162: * almost certainly lead to "no space"
7163: * diagnostic
7164: * panic: no fs -- the device is not mounted.
7165: * this "cannot happen"
7166: */
7167: getfs(dev)
7168: {
7169: register struct mount *p;
7170: register char *n1, *n2;
7171:
7172: for(p = &mount[0]; p < &mount[NMOUNT]; p++)
7173: if(p->m_bufp != NULL && p->m_dev == dev) {
7174: p = p->m_bufp->b_addr;
7175: n1 = p->s_nfree;
7176: n2 = p->s_ninode;
7177: if(n1 > 100 || n2 > 100) {
7178: prdev("bad count", dev);
7179: p->s_nfree = 0;
7180: p->s_ninode = 0;
7181: }
7182: return(p);
7183: }
7184: panic("no fs");
7185: }
7186: /* --------------------------- */
7187: /* --------------------------- */
7188:
7189: /*
7190: * update is the internal name of
7191: * 'sync'. It goes through the disk
7192: * queues to initiate sandbagged IO;
7193: * goes through the I nodes to write
7194: * modified nodes; and it goes through
7195: * the mount table to initiate modified
7196: * super blocks.
7197: */
7198:
7199:
7200:
7201: update()
7202: {
7203: register struct inode *ip;
7204: register struct mount *mp;
7205: register *bp;
7206:
7207: if(updlock)
7208: return;
7209: updlock++;
7210: for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
7211: if(mp->m_bufp != NULL) {
7212: ip = mp->m_bufp->b_addr;
7213: if(ip->s_fmod==0 || ip->s_ilock!=0 ||
7214: ip->s_flock!=0 || ip->s_ronly!=0)
7215: continue;
7216: bp = getblk(mp->m_dev, 1);
7217: ip->s_fmod = 0;
7218: ip->s_time[0] = time[0];
7219: ip->s_time[1] = time[1];
7220: bcopy(ip, bp->b_addr, 256);
7221: bwrite(bp);
7222: }
7223: for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
7224: if((ip->i_flag&ILOCK) == 0) {
7225: ip->i_flag =| ILOCK;
7226: iupdat(ip, time);
7227: prele(ip);
7228: }
7229: updlock = 0;
7230: bflush(NODEV);
7231: }
7232: /* --------------------------- */
7233: /* --------------------------- */