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: /* --------------------------- */