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