sys/alloc.c

08100 #include "../h/param.h" 08101 #include "../h/systm.h" 08102 #include "../h/mount.h" 08103 #include "../h/filsys.h" 08104 #include "../h/fblk.h" 08105 #include "../h/conf.h" 08106 #include "../h/buf.h" 08107 #include "../h/inode.h" 08108 #include "../h/ino.h" 08109 #include "../h/dir.h" 08110 #include "../h/user.h" 08111 typedef struct fblk *FBLKP; 08112 08113 /* 08114 * alloc will obtain the next available 08115 * free disk block from the free list of 08116 * the specified device. 08117 * The super block has up to NICFREE remembered 08118 * free blocks; the last of these is read to 08119 * obtain NICFREE more . . . 08120 * 08121 * no space on dev x/y -- when 08122 * the free list is exhausted. 08123 */ 08124 struct buf * 08125 alloc(dev) 08126 dev_t dev; 08127 { 08128 daddr_t bno; 08129 register struct filsys *fp; 08130 register struct buf *bp; 08131 08132 fp = getfs(dev); 08133 while(fp->s_flock) 08134 sleep((caddr_t)&fp->s_flock, PINOD); 08135 do { 08136 if(fp->s_nfree <= 0) 08137 goto nospace; 08138 if (fp->s_nfree > NICFREE) { 08139 prdev("Bad free count", dev); 08140 goto nospace; 08141 } 08142 bno = fp->s_free[--fp->s_nfree]; 08143 if(bno == 0) 08144 goto nospace; 08145 } while (badblock(fp, bno, dev)); 08146 if(fp->s_nfree <= 0) { 08147 fp->s_flock++; 08148 bp = bread(dev, bno); 08149 if ((bp->b_flags&B_ERROR) == 0) { 08150 fp->s_nfree = ((FBLKP)(bp->b_un.b_addr))->df_nfree; 08151 bcopy((caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free, 08152 (caddr_t)fp->s_free, sizeof(fp->s_free)); 08153 } 08154 brelse(bp); 08155 fp->s_flock = 0; 08156 wakeup((caddr_t)&fp->s_flock); 08157 if (fp->s_nfree <=0) 08158 goto nospace; 08159 } 08160 bp = getblk(dev, bno); 08161 clrbuf(bp); 08162 fp->s_fmod = 1; 08163 return(bp); 08164 08165 nospace: 08166 fp->s_nfree = 0; 08167 prdev("no space", dev); 08168 u.u_error = ENOSPC; 08169 return(NULL); 08170 } 08171 08172 /* 08173 * place the specified disk block 08174 * back on the free list of the 08175 * specified device. 08176 */ 08177 free(dev, bno) 08178 dev_t dev; 08179 daddr_t bno; 08180 { 08181 register struct filsys *fp; 08182 register struct buf *bp; 08183 08184 fp = getfs(dev); 08185 fp->s_fmod = 1; 08186 while(fp->s_flock) 08187 sleep((caddr_t)&fp->s_flock, PINOD); 08188 if (badblock(fp, bno, dev)) 08189 return; 08190 if(fp->s_nfree <= 0) { 08191 fp->s_nfree = 1; 08192 fp->s_free[0] = 0; 08193 } 08194 if(fp->s_nfree >= NICFREE) { 08195 fp->s_flock++; 08196 bp = getblk(dev, bno); 08197 ((FBLKP)(bp->b_un.b_addr))->df_nfree = fp->s_nfree; 08198 bcopy((caddr_t)fp->s_free, 08199 (caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free, 08200 sizeof(fp->s_free)); 08201 fp->s_nfree = 0; 08202 bwrite(bp); 08203 fp->s_flock = 0; 08204 wakeup((caddr_t)&fp->s_flock); 08205 } 08206 fp->s_free[fp->s_nfree++] = bno; 08207 fp->s_fmod = 1; 08208 } 08209 08210 /* 08211 * Check that a block number is in the 08212 * range between the I list and the size 08213 * of the device. 08214 * This is used mainly to check that a 08215 * garbage file system has not been mounted. 08216 * 08217 * bad block on dev x/y -- not in range 08218 */ 08219 badblock(fp, bn, dev) 08220 register struct filsys *fp; 08221 daddr_t bn; 08222 dev_t dev; 08223 { 08224 08225 if (bn < fp->s_isize || bn >= fp->s_fsize) { 08226 prdev("bad block", dev); 08227 return(1); 08228 } 08229 return(0); 08230 } 08231 08232 /* 08233 * Allocate an unused I node 08234 * on the specified device. 08235 * Used with file creation. 08236 * The algorithm keeps up to 08237 * NICINOD spare I nodes in the 08238 * super block. When this runs out, 08239 * a linear search through the 08240 * I list is instituted to pick 08241 * up NICINOD more. 08242 */ 08243 struct inode */ 08244 ialloc(dev) 08245 dev_t dev; 08246 { 08247 register struct filsys *fp; 08248 register struct buf *bp; 08249 register struct inode *ip; 08250 int i; 08251 struct dinode *dp; 08252 ino_t ino; 08253 daddr_t adr; 08254 08255 fp = getfs(dev); 08256 while(fp->s_ilock) 08257 sleep((caddr_t)&fp->s_ilock, PINOD); 08258 loop: 08259 if(fp->s_ninode > 0) { 08260 ino = fp->s_inode[--fp->s_ninode]; 08261 if (ino < ROOTINO) 08262 goto loop; 08263 ip = iget(dev, ino); 08264 if(ip == NULL) 08265 return(NULL); 08266 if(ip->i_mode == 0) { 08267 for (i=0; i08268 ip->i_un.i_addr[i] = 0; 08269 fp->s_fmod = 1; 08270 return(ip); 08271 } 08272 /* 08273 * Inode was allocated after all. 08274 * Look some more. 08275 */ 08276 iput(ip); 08277 goto loop; 08278 } 08279 fp->s_ilock++; 08280 ino = 1; 08281 for(adr = SUPERB+1; adr < fp->s_isize; adr++) { 08282 bp = bread(dev, adr); 08283 if (bp->b_flags & B_ERROR) { 08284 brelse(bp); 08285 ino += INOPB; 08286 continue; 08287 } 08288 dp = bp->b_un.b_dino; 08289 for(i=0; i08290 if(dp->di_mode != 0) 08291 goto cont; 08292 for(ip = &inode[0]; ip < &inode[NINODE]; ip++) 08293 if(dev==ip->i_dev && ino==ip->i_number) 08294 goto cont; 08295 fp->s_inode[fp->s_ninode++] = ino; 08296 if(fp->s_ninode >= NICINOD) 08297 break; 08298 cont: 08299 ino++; 08300 dp++; 08301 } 08302 brelse(bp); 08303 if(fp->s_ninode >= NICINOD) 08304 break; 08305 } 08306 fp->s_ilock = 0; 08307 wakeup((caddr_t)&fp->s_ilock); 08308 if(fp->s_ninode > 0) 08309 goto loop; 08310 prdev("Out of inodes", dev); 08311 u.u_error = ENOSPC; 08312 return(NULL); 08313 } 08314 08315 /* 08316 * Free the specified I node 08317 * on the specified device. 08318 * The algorithm stores up 08319 * to NICINOD I nodes in the super 08320 * block and throws away any more. 08321 */ 08322 ifree(dev, ino) 08323 dev_t dev; 08324 ino_t ino; 08325 { 08326 register struct filsys *fp; 08327 08328 fp = getfs(dev); 08329 if(fp->s_ilock) 08330 return; 08331 if(fp->s_ninode >= NICINOD) 08332 return; 08333 fp->s_inode[fp->s_ninode++] = ino; 08334 fp->s_fmod = 1; 08335 } 08336 08337 /* 08338 * getfs maps a device number into 08339 * a pointer to the incore super 08340 * block. 08341 * The algorithm is a linear 08342 * search through the mount table. 08343 * A consistency check of the 08344 * in core free-block and i-node 08345 * counts. 08346 * 08347 * bad count on dev x/y -- the count 08348 * check failed. At this point, all 08349 * the counts are zeroed which will 08350 * almost certainly lead to "no space" 08351 * diagnostic 08352 * panic: no fs -- the device is not mounted. 08353 * this "cannot happen" 08354 */ 08355 struct filsys */ 08356 getfs(dev) 08357 dev_t dev; 08358 { 08359 register struct mount *mp; 08360 register struct filsys *fp; 08361 08362 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 08363 if(mp->m_bufp != NULL && mp->m_dev == dev) { 08364 fp = mp->m_bufp->b_un.b_filsys; 08365 if(fp->s_nfree > NICFREE || fp->s_ninode > NICINOD) { 08366 prdev("bad count", dev); 08367 fp->s_nfree = 0; 08368 fp->s_ninode = 0; 08369 } 08370 return(fp); 08371 } 08372 panic("no fs"); 08373 return(NULL); 08374 } 08375 08376 /* 08377 * update is the internal name of 08378 * 'sync'. It goes through the disk 08379 * queues to initiate sandbagged IO; 08380 * goes through the I nodes to write 08381 * modified nodes; and it goes through 08382 * the mount table to initiate modified 08383 * super blocks. 08384 */ 08385 update() 08386 { 08387 register struct inode *ip; 08388 register struct mount *mp; 08389 register struct buf *bp; 08390 struct filsys *fp; 08391 08392 if(updlock) 08393 return; 08394 updlock++; 08395 for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 08396 if(mp->m_bufp != NULL) { 08397 fp = mp->m_bufp->b_un.b_filsys; 08398 if(fp->s_fmod==0 || fp->s_ilock!=0 || 08399 fp->s_flock!=0 || fp->s_ronly!=0) 08400 continue; 08401 bp = getblk(mp->m_dev, SUPERB); 08402 if (bp->b_flags & B_ERROR) 08403 continue; 08404 fp->s_fmod = 0; 08405 fp->s_time = time; 08406 bcopy((caddr_t)fp, bp->b_un.b_addr, BSIZE); 08407 bwrite(bp); 08408 } 08409 for(ip = &inode[0]; ip < &inode[NINODE]; ip++) 08410 if((ip->i_flag&ILOCK)==0 && ip->i_count) { 08411 ip->i_flag |= ILOCK; 08412 ip->i_count++; 08413 iupdat(ip, &time, &time); 08414 iput(ip); 08415 } 08416 updlock = 0; 08417 bflush(NODEV); 08418 } 08419 08420 08421 08422 08423 08424 08425 08426 08427 08428 08429 08430 08431 08432 08433 08434 08435 08436 08437 08438 08439 08440 08441 08442 08443 08444 08445 08446 08447 08448 08449