1: # 2: /* 3: */ 4: 5: #include "../param.h" 6: #include "../systm.h" 7: #include "../filsys.h" 8: #include "../conf.h" 9: #include "../buf.h" 10: #include "../inode.h" 11: #include "../user.h" 12: 13: /* 14: * iinit is called once (from main) 15: * very early in initialization. 16: * It reads the root's super block 17: * and initializes the current date 18: * from the last modified date. 19: * 20: * panic: iinit -- cannot read the super 21: * block. Usually because of an IO error. 22: */ 23: iinit() 24: { 25: register *cp, *bp; 26: 27: (*bdevsw[rootdev.d_major].d_open)(rootdev, 1); 28: bp = bread(rootdev, 1); 29: cp = getblk(NODEV); 30: if(u.u_error) 31: panic("iinit"); 32: bcopy(bp->b_addr, cp->b_addr, 256); 33: brelse(bp); 34: mount[0].m_bufp = cp; 35: mount[0].m_dev = rootdev; 36: cp = cp->b_addr; 37: cp->s_flock = 0; 38: cp->s_ilock = 0; 39: cp->s_ronly = 0; 40: time[0] = cp->s_time[0]; 41: time[1] = cp->s_time[1]; 42: } 43: 44: /* 45: * alloc will obtain the next available 46: * free disk block from the free list of 47: * the specified device. 48: * The super block has up to 100 remembered 49: * free blocks; the last of these is read to 50: * obtain 100 more . . . 51: * 52: * no space on dev x/y -- when 53: * the free list is exhausted. 54: */ 55: alloc(dev) 56: { 57: int bno; 58: register *bp, *ip, *fp; 59: 60: fp = getfs(dev); 61: while(fp->s_flock) 62: sleep(&fp->s_flock, PINOD); 63: do { 64: if(fp->s_nfree <= 0) 65: goto nospace; 66: bno = fp->s_free[--fp->s_nfree]; 67: if(bno == 0) 68: goto nospace; 69: } while (badblock(fp, bno, dev)); 70: if(fp->s_nfree <= 0) { 71: fp->s_flock++; 72: bp = bread(dev, bno); 73: ip = bp->b_addr; 74: fp->s_nfree = *ip++; 75: bcopy(ip, fp->s_free, 100); 76: brelse(bp); 77: fp->s_flock = 0; 78: wakeup(&fp->s_flock); 79: } 80: bp = getblk(dev, bno); 81: clrbuf(bp); 82: fp->s_fmod = 1; 83: return(bp); 84: 85: nospace: 86: fp->s_nfree = 0; 87: prdev("no space", dev); 88: u.u_error = ENOSPC; 89: return(NULL); 90: } 91: 92: /* 93: * place the specified disk block 94: * back on the free list of the 95: * specified device. 96: */ 97: free(dev, bno) 98: { 99: register *fp, *bp, *ip; 100: 101: fp = getfs(dev); 102: fp->s_fmod = 1; 103: while(fp->s_flock) 104: sleep(&fp->s_flock, PINOD); 105: if (badblock(fp, bno, dev)) 106: return; 107: if(fp->s_nfree <= 0) { 108: fp->s_nfree = 1; 109: fp->s_free[0] = 0; 110: } 111: if(fp->s_nfree >= 100) { 112: fp->s_flock++; 113: bp = getblk(dev, bno); 114: ip = bp->b_addr; 115: *ip++ = fp->s_nfree; 116: bcopy(fp->s_free, ip, 100); 117: fp->s_nfree = 0; 118: bwrite(bp); 119: fp->s_flock = 0; 120: wakeup(&fp->s_flock); 121: } 122: fp->s_free[fp->s_nfree++] = bno; 123: fp->s_fmod = 1; 124: } 125: 126: /* 127: * Check that a block number is in the 128: * range between the I list and the size 129: * of the device. 130: * This is used mainly to check that a 131: * garbage file system has not been mounted. 132: * 133: * bad block on dev x/y -- not in range 134: */ 135: badblock(afp, abn, dev) 136: { 137: register struct filsys *fp; 138: register char *bn; 139: 140: fp = afp; 141: bn = abn; 142: if (bn < fp->s_isize+2 || bn >= fp->s_fsize) { 143: prdev("bad block", dev); 144: return(1); 145: } 146: return(0); 147: } 148: 149: /* 150: * Allocate an unused I node 151: * on the specified device. 152: * Used with file creation. 153: * The algorithm keeps up to 154: * 100 spare I nodes in the 155: * super block. When this runs out, 156: * a linear search through the 157: * I list is instituted to pick 158: * up 100 more. 159: */ 160: ialloc(dev) 161: { 162: register *fp, *bp, *ip; 163: int i, j, k, ino; 164: 165: fp = getfs(dev); 166: while(fp->s_ilock) 167: sleep(&fp->s_ilock, PINOD); 168: loop: 169: if(fp->s_ninode > 0) { 170: ino = fp->s_inode[--fp->s_ninode]; 171: ip = iget(dev, ino); 172: if (ip==NULL) 173: return(NULL); 174: if(ip->i_mode == 0) { 175: for(bp = &ip->i_mode; bp < &ip->i_addr[8];) 176: *bp++ = 0; 177: fp->s_fmod = 1; 178: return(ip); 179: } 180: /* 181: * Inode was allocated after all. 182: * Look some more. 183: */ 184: iput(ip); 185: goto loop; 186: } 187: fp->s_ilock++; 188: ino = 0; 189: for(i=0; i<fp->s_isize; i++) { 190: bp = bread(dev, i+2); 191: ip = bp->b_addr; 192: for(j=0; j<256; j=+16) { 193: ino++; 194: if(ip[j] != 0) 195: continue; 196: for(k=0; k<NINODE; k++) 197: if(dev==inode[k].i_dev && ino==inode[k].i_number) 198: goto cont; 199: fp->s_inode[fp->s_ninode++] = ino; 200: if(fp->s_ninode >= 100) 201: break; 202: cont:; 203: } 204: brelse(bp); 205: if(fp->s_ninode >= 100) 206: break; 207: } 208: fp->s_ilock = 0; 209: wakeup(&fp->s_ilock); 210: if (fp->s_ninode > 0) 211: goto loop; 212: prdev("Out of inodes", dev); 213: u.u_error = ENOSPC; 214: return(NULL); 215: } 216: 217: /* 218: * Free the specified I node 219: * on the specified device. 220: * The algorithm stores up 221: * to 100 I nodes in the super 222: * block and throws away any more. 223: */ 224: ifree(dev, ino) 225: { 226: register *fp; 227: 228: fp = getfs(dev); 229: if(fp->s_ilock) 230: return; 231: if(fp->s_ninode >= 100) 232: return; 233: fp->s_inode[fp->s_ninode++] = ino; 234: fp->s_fmod = 1; 235: } 236: 237: /* 238: * getfs maps a device number into 239: * a pointer to the incore super 240: * block. 241: * The algorithm is a linear 242: * search through the mount table. 243: * A consistency check of the 244: * in core free-block and i-node 245: * counts. 246: * 247: * bad count on dev x/y -- the count 248: * check failed. At this point, all 249: * the counts are zeroed which will 250: * almost certainly lead to "no space" 251: * diagnostic 252: * panic: no fs -- the device is not mounted. 253: * this "cannot happen" 254: */ 255: getfs(dev) 256: { 257: register struct mount *p; 258: register char *n1, *n2; 259: 260: for(p = &mount[0]; p < &mount[NMOUNT]; p++) 261: if(p->m_bufp != NULL && p->m_dev == dev) { 262: p = p->m_bufp->b_addr; 263: n1 = p->s_nfree; 264: n2 = p->s_ninode; 265: if(n1 > 100 || n2 > 100) { 266: prdev("bad count", dev); 267: p->s_nfree = 0; 268: p->s_ninode = 0; 269: } 270: return(p); 271: } 272: panic("no fs"); 273: } 274: 275: /* 276: * update is the internal name of 277: * 'sync'. It goes through the disk 278: * queues to initiate sandbagged IO; 279: * goes through the I nodes to write 280: * modified nodes; and it goes through 281: * the mount table to initiate modified 282: * super blocks. 283: */ 284: update() 285: { 286: register struct inode *ip; 287: register struct mount *mp; 288: register *bp; 289: 290: if(updlock) 291: return; 292: updlock++; 293: for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 294: if(mp->m_bufp != NULL) { 295: ip = mp->m_bufp->b_addr; 296: if(ip->s_fmod==0 || ip->s_ilock!=0 || 297: ip->s_flock!=0 || ip->s_ronly!=0) 298: continue; 299: bp = getblk(mp->m_dev, 1); 300: ip->s_fmod = 0; 301: ip->s_time[0] = time[0]; 302: ip->s_time[1] = time[1]; 303: bcopy(ip, bp->b_addr, 256); 304: bwrite(bp); 305: } 306: for(ip = &inode[0]; ip < &inode[NINODE]; ip++) 307: if((ip->i_flag&ILOCK) == 0) { 308: ip->i_flag =| ILOCK; 309: iupdat(ip, time); 310: prele(ip); 311: } 312: updlock = 0; 313: bflush(NODEV); 314: }