1: /*
   2:  *	SCCS id	@(#)alloc.c	2.1 (Berkeley)	8/5/83
   3:  */
   4: 
   5: #include "param.h"
   6: #include <sys/systm.h>
   7: #include <sys/filsys.h>
   8: #include <sys/mount.h>
   9: #include <sys/fblk.h>
  10: #include <sys/conf.h>
  11: #include <sys/buf.h>
  12: #include <sys/inode.h>
  13: #include <sys/ino.h>
  14: #include <sys/dir.h>
  15: #include <sys/user.h>
  16: #include <sys/quota.h>
  17: 
  18: typedef struct fblk *FBLKP;
  19: 
  20: #ifdef UCB_QUOTAS
  21: /*
  22:  * Bookkeeping for quota system interfaces to alloc() and free():
  23:  * count one block against the quota of the given inode.
  24:  * If the quota has been exceeded, return NULL without allocating block.
  25:  */
  26: struct buf *
  27: qalloc(ip, d)
  28: register struct inode *ip;
  29: dev_t d;
  30: {
  31:     register struct inode *qp, *rp;
  32:     struct buf *ret;
  33: 
  34:     for (qp = ip->i_quot; qp != (struct inode *) NULL; qp = qp->i_quot) {
  35:         if (qp->i_un.i_qused >= qp->i_un.i_qmax) {
  36:             /*
  37: 			 * A quota was exceeded. Undo the counts.
  38: 			 */
  39:             for (rp = ip->i_quot; rp != qp; rp = rp->i_quot)
  40:                 rp->i_un.i_qused -= QCOUNT;
  41:             u.u_error = EQUOT;
  42:             return((struct buf *) NULL);
  43:         }
  44:         qp->i_un.i_qused += QCOUNT;
  45:         qp->i_flag |= IUPD;
  46:     }
  47:     if((ret = alloc(d)) != NULL)
  48:         return(ret);
  49:     /*
  50: 	 * The block could not be allocated.
  51: 	 * Undo the quota count.
  52: 	 */
  53:     for (qp = ip->i_quot; qp != (struct inode *) NULL; qp = qp->i_quot)
  54:         if(qp->i_un.i_qused != 0)
  55:             qp->i_un.i_qused -= QCOUNT;
  56:     return((struct buf *) NULL);
  57: }
  58: #endif
  59: 
  60: /*
  61:  * alloc will obtain the next available
  62:  * free disk block from the free list of
  63:  * the specified device.
  64:  * The super block has up to NICFREE remembered
  65:  * free blocks; the last of these is read to
  66:  * obtain NICFREE more . . .
  67:  *
  68:  * no space on dev x/y -- when
  69:  * the free list is exhausted.
  70:  */
  71: struct buf *
  72: alloc(dev)
  73: dev_t dev;
  74: {
  75:     daddr_t bno;
  76:     register struct filsys *fp;
  77:     register struct buf *bp;
  78:     int i;
  79:     register struct fblk *fbp;
  80:     struct filsys *fps;
  81: 
  82:     if ((fp = getfs(dev)) == NULL)
  83:         goto nofs;
  84:     while(fp->s_flock)
  85:         sleep((caddr_t)&fp->s_flock, PINOD);
  86:     do {
  87:         if(fp->s_nfree <= 0)
  88:             goto nospace;
  89:         if (fp->s_nfree > NICFREE) {
  90:             fserr(fp, "bad free count");
  91:             goto nospace;
  92:         }
  93:         bno = fp->s_free[--fp->s_nfree];
  94:         if(bno == 0)
  95:             goto nospace;
  96:     } while (badblock(fp, bno));
  97:     if(fp->s_nfree <= 0) {
  98:         fp->s_flock++;
  99:         bp = bread(dev, bno);
 100:         if (((bp->b_flags&B_ERROR) == 0) && (bp->b_resid==0)) {
 101:             fbp = (FBLKP) mapin(bp);
 102:             *((FBLKP)&fp->s_nfree) = *fbp;
 103:             mapout(bp);
 104:         }
 105:         brelse(bp);
 106: #ifdef  UCB_FSFIX
 107:         /*
 108: 		 * Write the superblock back, synchronously,
 109: 		 * so that the free list pointer won't point at garbage.
 110: 		 * We can still end up with dups in free if we then
 111: 		 * use some of the blocks in this freeblock, then crash
 112: 		 * without a sync.
 113: 		 */
 114:         bp = getblk(dev, SUPERB);
 115:         fp->s_fmod = 0;
 116:         fp->s_time = time;
 117:         fps = (struct filsys *) mapin(bp);
 118:         *fps = *fp;
 119:         mapout(bp);
 120:         bwrite(bp);
 121: 
 122: #endif
 123:         fp->s_flock = 0;
 124:         wakeup((caddr_t)&fp->s_flock);
 125:         if (fp->s_nfree <=0)
 126:             goto nospace;
 127:     }
 128:     bp = getblk(dev, bno);
 129:     clrbuf(bp);
 130:     fp->s_fmod = 1;
 131:     fp->s_tfree--;
 132:     return(bp);
 133: 
 134: nospace:
 135:     fp->s_nfree = 0;
 136:     fp->s_tfree = 0;
 137:     fserr(fp, "file system full");
 138:     /* THIS IS A KLUDGE... */
 139:     /* SHOULD RATHER SEND A SIGNAL AND SUSPEND THE PROCESS IN A */
 140:     /* STATE FROM WHICH THE SYSTEM CALL WILL RESTART */
 141: #ifdef  UCB_UPRINTF
 142:     uprintf("\n%s: write failed, file system is full\n", fp->s_fsmnt);
 143: #endif
 144:     for (i = 0; i < 5; i++)
 145:         sleep((caddr_t)&lbolt, PRIBIO);
 146: nofs:
 147:     u.u_error = ENOSPC;
 148:     return(NULL);
 149: }
 150: 
 151: #ifdef UCB_QUOTAS
 152: /*
 153:  *	decrement the count for quotas
 154:  */
 155: qfree(ip, b)
 156: register struct inode *ip;
 157: daddr_t b;
 158: {
 159:     register struct inode *qp;
 160: 
 161:     for (qp = ip->i_quot; qp != NULL; qp = qp->i_quot)
 162:         if (qp->i_un.i_qused) {
 163:             qp->i_un.i_qused -= QCOUNT;
 164:             qp->i_flag |= IUPD;
 165:         }
 166:     free(ip->i_dev, b);
 167: }
 168: #endif
 169: 
 170: /*
 171:  * place the specified disk block
 172:  * back on the free list of the
 173:  * specified device.
 174:  */
 175: free(dev, bno)
 176: dev_t dev;
 177: daddr_t bno;
 178: {
 179:     register struct filsys *fp;
 180:     register struct buf *bp;
 181:     register struct fblk *fbp;
 182: 
 183:     if ((fp = getfs(dev)) == NULL)
 184:         return;
 185:     if (badblock(fp, bno))
 186:         return;
 187:     while(fp->s_flock)
 188:         sleep((caddr_t)&fp->s_flock, PINOD);
 189:     if(fp->s_nfree <= 0) {
 190:         fp->s_nfree = 1;
 191:         fp->s_free[0] = 0;
 192:     }
 193:     if(fp->s_nfree >= NICFREE) {
 194:         fp->s_flock++;
 195:         bp = getblk(dev, bno);
 196:         fbp = (FBLKP) mapin(bp);
 197:         *fbp = *((FBLKP) &fp->s_nfree);
 198:         mapout(bp);
 199:         fp->s_nfree = 0;
 200:         bwrite(bp);
 201:         fp->s_flock = 0;
 202:         wakeup((caddr_t)&fp->s_flock);
 203:     }
 204:     fp->s_free[fp->s_nfree++] = bno;
 205:     fp->s_tfree++;
 206:     fp->s_fmod = 1;
 207: }
 208: 
 209: /*
 210:  * Check that a block number is in the
 211:  * range between the I list and the size
 212:  * of the device.
 213:  * This is used mainly to check that a
 214:  * garbage file system has not been mounted.
 215:  *
 216:  * bad block on dev x/y -- not in range
 217:  */
 218: badblock(fp, bn)
 219: register struct filsys *fp;
 220: daddr_t bn;
 221: {
 222: 
 223:     if (bn < fp->s_isize || bn >= fp->s_fsize) {
 224:         fserr(fp, "bad block");
 225:         return(1);
 226:     }
 227:     return(0);
 228: }
 229: 
 230: /*
 231:  * Allocate an unused I node
 232:  * on the specified device.
 233:  * Used with file creation.
 234:  * The algorithm keeps up to
 235:  * NICINOD spare I nodes in the
 236:  * super block. When this runs out,
 237:  * a linear search through the
 238:  * I list is instituted to pick
 239:  * up NICINOD more.
 240:  */
 241: struct inode *
 242: ialloc(dev)
 243: dev_t dev;
 244: {
 245:     register struct filsys *fp;
 246:     register struct buf *bp;
 247:     register struct inode *ip;
 248:     int i;
 249:     struct dinode *dp;
 250:     ino_t ino;
 251:     daddr_t adr;
 252:     ino_t inobas;
 253:     int first;
 254: 
 255:     if ((fp = getfs(dev)) == NULL)
 256:         goto nofs;
 257:     while(fp->s_ilock)
 258:         sleep((caddr_t)&fp->s_ilock, PINOD);
 259: loop:
 260:     if(fp->s_ninode > 0) {
 261:         ino = fp->s_inode[--fp->s_ninode];
 262:         if (ino <= ROOTINO)
 263:             goto loop;
 264:         ip = iget(dev, ino);
 265:         if(ip == NULL)
 266:             return(NULL);
 267:         if(ip->i_mode == 0) {
 268:             for (i=0; i<NADDR; i++)
 269:                 ip->i_un.i_addr[i] = 0;
 270:             fp->s_fmod = 1;
 271:             fp->s_tinode--;
 272:             return(ip);
 273:         }
 274:         /*
 275: 		 * Inode was allocated after all.
 276: 		 * Look some more.
 277: 		 */
 278:         iput(ip);
 279:         goto loop;
 280:     }
 281:     fp->s_ilock++;
 282:     if (fp->s_nbehind < 4 * NICINOD) {
 283:         first = 1;
 284:         ino = fp->s_lasti;
 285: #ifdef  DIAGNOSTIC
 286:         if (itoo(ino))
 287:             panic("ialloc");
 288: #endif
 289:         adr = itod(ino);
 290:     } else {
 291: fromtop:
 292:         first = 0;
 293:         ino = 1;
 294:         adr = SUPERB+1;
 295:         fp->s_nbehind = 0;
 296:     }
 297:     for(; adr < fp->s_isize; adr++) {
 298:         inobas = ino;
 299:         bp = bread(dev, adr);
 300:         if ((bp->b_flags & B_ERROR) || bp->b_resid) {
 301:             brelse(bp);
 302:             ino += INOPB;
 303:             continue;
 304:         }
 305:         dp = (struct dinode *) mapin(bp);
 306:         for(i=0; i<INOPB; i++) {
 307:             if(dp->di_mode != 0)
 308:                 goto cont;
 309: #ifdef  UCB_IHASH
 310:             if(ifind(dev, ino))
 311:                 goto cont;
 312: #else
 313:             for(ip = inode; ip < inodeNINODE; ip++)
 314:                 if(dev==ip->i_dev && ino==ip->i_number)
 315:                     goto cont;
 316: #endif
 317:             fp->s_inode[fp->s_ninode++] = ino;
 318:             if(fp->s_ninode >= NICINOD)
 319:                 break;
 320:         cont:
 321:             ino++;
 322:             dp++;
 323:         }
 324:         mapout(bp);
 325:         brelse(bp);
 326:         if(fp->s_ninode >= NICINOD)
 327:             break;
 328:     }
 329:     if (fp->s_ninode < NICINOD && first) {
 330:         goto fromtop;
 331:     }
 332:     fp->s_lasti = inobas;
 333:     fp->s_ilock = 0;
 334:     wakeup((caddr_t)&fp->s_ilock);
 335:     if(fp->s_ninode > 0)
 336:         goto loop;
 337:     fserr(fp, "out of inodes");
 338: #ifdef  UCB_UPRINTF
 339:     uprintf("\n%s:  create failed, no inodes free\n", fp->s_fsmnt);
 340: #endif
 341: nofs:
 342:     u.u_error = ENOSPC;
 343:     return(NULL);
 344: }
 345: 
 346: /*
 347:  * Free the specified I node
 348:  * on the specified device.
 349:  * The algorithm stores up
 350:  * to NICINOD I nodes in the super
 351:  * block and throws away any more.
 352:  */
 353: ifree(dev, ino)
 354: dev_t dev;
 355: ino_t ino;
 356: {
 357:     register struct filsys *fp;
 358: 
 359:     if ((fp = getfs(dev)) == NULL)
 360:         return;
 361:     fp->s_tinode++;
 362:     if(fp->s_ilock)
 363:         return;
 364:     if(fp->s_ninode >= NICINOD) {
 365:         if (fp->s_lasti > ino)
 366:             fp->s_nbehind++;
 367:         return;
 368:     }
 369:     fp->s_inode[fp->s_ninode++] = ino;
 370:     fp->s_fmod = 1;
 371: }
 372: 
 373: /*
 374:  * getfs maps a device number into
 375:  * a pointer to the incore super
 376:  * block.
 377:  * The algorithm is a linear
 378:  * search through the mount table.
 379:  * A consistency check of the
 380:  * in core free-block and i-node
 381:  * counts.
 382:  *
 383:  * bad count on dev x/y -- the count
 384:  *	check failed. At this point, all
 385:  *	the counts are zeroed which will
 386:  *	almost certainly lead to "no space"
 387:  *	diagnostic
 388:  * The previous ``panic:  no fs'', which occurred
 389:  * when a device was not found in the mount table,
 390:  * has been replaced with a warning message.  This
 391:  * is because a panic would occur if one forgot to
 392:  * mount the pipedev.
 393:  * NULL is now returned instead, and routines which
 394:  * previously thought that they were guaranteed a
 395:  * valid pointer from getfs (alloc, free, ialloc,
 396:  * ifree, access, iupdat) have been modified to
 397:  * detect this.
 398:  */
 399: struct filsys *
 400: getfs(dev)
 401: dev_t dev;
 402: {
 403:     register struct mount *mp;
 404:     register struct filsys *fp;
 405: 
 406:     for(mp = mount; mp < mountNMOUNT; mp++)
 407:     if(mp->m_inodp != NULL && mp->m_dev == dev) {
 408:         fp = &mp->m_filsys;
 409:         if(fp->s_nfree > NICFREE || fp->s_ninode > NICINOD) {
 410:             fserr(fp, "bad count");
 411:             fp->s_nfree = 0;
 412:             fp->s_ninode = 0;
 413:         }
 414:         return(fp);
 415:     }
 416:     printf("no fs on dev %u/%u\n", major(dev), minor(dev));
 417:     return((struct filsys *) NULL);
 418: }
 419: 
 420: /*
 421:  * Update is the internal name of
 422:  * 'sync'. It goes through the disk
 423:  * queues to initiate sandbagged IO;
 424:  * goes through the I nodes to write
 425:  * modified nodes; and it goes through
 426:  * the mount table to initiate modified
 427:  * super blocks.
 428:  */
 429: update()
 430: {
 431:     register struct inode *ip;
 432:     register struct mount *mp;
 433:     register struct buf *bp;
 434:     struct filsys *fp,*fpdst;
 435: 
 436:     if(updlock)
 437:         return;
 438:     updlock++;
 439:     for(mp = mount; mp < mountNMOUNT; mp++)
 440:         if(mp->m_inodp != NULL) {
 441:             fp = &mp->m_filsys;
 442:             if(fp->s_fmod==0 || fp->s_ilock!=0 ||
 443:                fp->s_flock!=0 || fp->s_ronly!=0)
 444:                 continue;
 445:             bp = getblk(mp->m_dev, SUPERB);
 446:             if (bp->b_flags & B_ERROR)
 447:                 continue;
 448:             fp->s_fmod = 0;
 449:             fp->s_time = time;
 450:             fpdst = (struct filsys *) mapin(bp);
 451:             *fpdst = *fp;
 452:             mapout(bp);
 453:             bwrite(bp);
 454:         }
 455:     for(ip = inode; ip < inodeNINODE; ip++)
 456:         if((ip->i_flag&ILOCK)==0 && ip->i_count) {
 457:             ip->i_flag |= ILOCK;
 458:             ip->i_count++;
 459: #ifdef  UCB_FSFIX
 460:             iupdat(ip, &time, &time, 0);
 461: #else
 462:             iupdat(ip, &time, &time);
 463: #endif
 464:             iput(ip);
 465:         }
 466:     updlock = 0;
 467:     bflush(NODEV);
 468: }

Defined functions

alloc defined in line 71; used 2 times
badblock defined in line 218; used 2 times
free defined in line 175; used 2 times
getfs defined in line 399; used 7 times
ialloc defined in line 241; used 4 times
ifree defined in line 353; used 1 times
qalloc defined in line 26; never used
qfree defined in line 155; used 1 times

Defined typedef's

FBLKP defined in line 18; used 4 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1352
Valid CSS Valid XHTML 1.0 Strict