1: /*
   2:  * Copyright (c) 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)ufs_alloc.c	1.3 (2.11BSD GTE) 1996/9/19
   7:  */
   8: 
   9: #include "param.h"
  10: #include "../machine/seg.h"
  11: 
  12: #include "fs.h"
  13: #include "dir.h"
  14: #include "inode.h"
  15: #include "buf.h"
  16: #include "user.h"
  17: #include "kernel.h"
  18: #include "mount.h"
  19: #ifdef QUOTA
  20: #include "quota.h"
  21: #endif
  22: 
  23: typedef struct fblk *FBLKP;
  24: 
  25: /*
  26:  * Allocate a block in the file system.
  27:  *
  28:  * alloc will obtain the next available free disk block from the
  29:  * free list of the specified device.  The super block has up to
  30:  * NICFREE remembered free blocks; the last of these is read to
  31:  * obtain NICFREE more...
  32:  */
  33: struct buf *
  34: balloc(ip, flags)
  35:     struct inode *ip;
  36:     int flags;
  37: {
  38:     register struct fs *fs;
  39:     register struct buf *bp;
  40:     int async;
  41:     daddr_t bno;
  42: 
  43:     fs = ip->i_fs;
  44:     async = fs->fs_flags & MNT_ASYNC;
  45: 
  46:     while (fs->fs_flock)
  47:         sleep((caddr_t)&fs->fs_flock, PINOD);
  48:     do {
  49:         if (fs->fs_nfree <= 0)
  50:             goto nospace;
  51:         if (fs->fs_nfree > NICFREE) {
  52:             fserr(fs, "bad free count");
  53:             goto nospace;
  54:         }
  55:         bno = fs->fs_free[--fs->fs_nfree];
  56:         if (bno == 0)
  57:             goto nospace;
  58:     } while (badblock(fs, bno));
  59:     if (fs->fs_nfree <= 0) {
  60:         fs->fs_flock++;
  61:         bp = bread(ip->i_dev, bno);
  62:         if (((bp->b_flags&B_ERROR) == 0) && (bp->b_resid==0)) {
  63:             register struct fblk *fbp;
  64: 
  65:             fbp = (FBLKP) mapin(bp);
  66:             *((FBLKP)&fs->fs_nfree) = *fbp;
  67:             mapout(bp);
  68:         }
  69:         brelse(bp);
  70:         /*
  71: 		 * Write the superblock back, synchronously if requested,
  72: 		 * so that the free list pointer won't point at garbage.
  73: 		 * We can still end up with dups in free if we then
  74: 		 * use some of the blocks in this freeblock, then crash
  75: 		 * without a sync.
  76: 		 */
  77:         bp = getblk(ip->i_dev, SUPERB);
  78:         fs->fs_fmod = 0;
  79:         fs->fs_time = time.tv_sec;
  80:         {
  81:             register struct fs *fps;
  82: 
  83:             fps = (struct fs *)mapin(bp);
  84:             *fps = *fs;
  85:         }
  86:         mapout(bp);
  87:         if (!async)
  88:             bwrite(bp);
  89:         else
  90:             bdwrite(bp);
  91:         fs->fs_flock = 0;
  92:         wakeup((caddr_t)&fs->fs_flock);
  93:         if (fs->fs_nfree <=0)
  94:             goto nospace;
  95:     }
  96:     bp = getblk(ip->i_dev, bno);
  97:     bp->b_resid = 0;
  98:     if (flags & B_CLRBUF)
  99:         clrbuf(bp);
 100:     fs->fs_fmod = 1;
 101:     fs->fs_tfree--;
 102:     return(bp);
 103: 
 104: nospace:
 105:     fs->fs_nfree = 0;
 106:     fs->fs_tfree = 0;
 107:     fserr(fs, "file system full");
 108:     /*
 109: 	 * THIS IS A KLUDGE...
 110: 	 * SHOULD RATHER SEND A SIGNAL AND SUSPEND THE PROCESS IN A
 111: 	 * STATE FROM WHICH THE SYSTEM CALL WILL RESTART
 112: 	 */
 113:     uprintf("\n%s: write failed, file system full\n", fs->fs_fsmnt);
 114:     {
 115:         register int i;
 116: 
 117:         for (i = 0; i < 5; i++)
 118:             sleep((caddr_t)&lbolt, PRIBIO);
 119:     }
 120:     u.u_error = ENOSPC;
 121:     return(NULL);
 122: }
 123: 
 124: /*
 125:  * Allocate an inode in the file system.
 126:  *
 127:  * Allocate an unused I node on the specified device.  Used with file
 128:  * creation.  The algorithm keeps up to NICINOD spare I nodes in the
 129:  * super block.  When this runs out, a linear search through the I list
 130:  * is instituted to pick up NICINOD more.
 131:  */
 132: struct inode *
 133: ialloc(pip)
 134:     struct inode *pip;
 135: {
 136:     register struct fs *fs;
 137:     register struct buf *bp;
 138:     register struct inode *ip;
 139:     int i;
 140:     struct dinode *dp;
 141:     ino_t ino;
 142:     daddr_t adr;
 143:     ino_t inobas;
 144:     int first;
 145:     struct inode *ifind();
 146:     char    *emsg = "no inodes free";
 147: 
 148:     fs = pip->i_fs;
 149:     while (fs->fs_ilock)
 150:         sleep((caddr_t)&fs->fs_ilock, PINOD);
 151: #ifdef QUOTA
 152:     QUOTAMAP();
 153:     u.u_error = chkiq(pip->i_dev, NULL, u.u_uid, 0);
 154:     QUOTAUNMAP();
 155:     if (u.u_error)
 156:         return(NULL);
 157: #endif
 158: loop:
 159:     if (fs->fs_ninode > 0) {
 160:         ino = fs->fs_inode[--fs->fs_ninode];
 161:         if (ino <= ROOTINO)
 162:             goto loop;
 163:         ip = iget(pip->i_dev, fs, ino);
 164:         if (ip == NULL)
 165:             return(NULL);
 166:         if (ip->i_mode == 0) {
 167:             bzero((caddr_t)ip->i_addr,sizeof(ip->i_addr));
 168:             ip->i_flags = 0;
 169:             fs->fs_fmod = 1;
 170:             fs->fs_tinode--;
 171:             return(ip);
 172:         }
 173:         /*
 174: 		 * Inode was allocated after all.
 175: 		 * Look some more.
 176: 		 */
 177:         iput(ip);
 178:         goto loop;
 179:     }
 180:     fs->fs_ilock++;
 181:     if (fs->fs_nbehind < 4 * NICINOD) {
 182:         first = 1;
 183:         ino = fs->fs_lasti;
 184: #ifdef DIAGNOSTIC
 185:         if (itoo(ino))
 186:             panic("ialloc");
 187: #endif DIAGNOSTIC
 188:         adr = itod(ino);
 189:     } else {
 190: fromtop:
 191:         first = 0;
 192:         ino = 1;
 193:         adr = SUPERB+1;
 194:         fs->fs_nbehind = 0;
 195:     }
 196:     for (;adr < fs->fs_isize;adr++) {
 197:         inobas = ino;
 198:         bp = bread(pip->i_dev, adr);
 199:         if ((bp->b_flags & B_ERROR) || bp->b_resid) {
 200:             brelse(bp);
 201:             ino += INOPB;
 202:             continue;
 203:         }
 204:         dp = (struct dinode *)mapin(bp);
 205:         for (i = 0;i < INOPB;i++) {
 206:             if (dp->di_mode != 0)
 207:                 goto cont;
 208:             if (ifind(pip->i_dev, ino))
 209:                 goto cont;
 210:             fs->fs_inode[fs->fs_ninode++] = ino;
 211:             if (fs->fs_ninode >= NICINOD)
 212:                 break;
 213:         cont:
 214:             ino++;
 215:             dp++;
 216:         }
 217:         mapout(bp);
 218:         brelse(bp);
 219:         if (fs->fs_ninode >= NICINOD)
 220:             break;
 221:     }
 222:     if (fs->fs_ninode < NICINOD && first)
 223:         goto fromtop;
 224:     fs->fs_lasti = inobas;
 225:     fs->fs_ilock = 0;
 226:     wakeup((caddr_t)&fs->fs_ilock);
 227:     if (fs->fs_ninode > 0)
 228:         goto loop;
 229:     fserr(fs, emsg);
 230:     uprintf("\n%s: %s\n", fs->fs_fsmnt, emsg);
 231:     u.u_error = ENOSPC;
 232:     return(NULL);
 233: }
 234: 
 235: /*
 236:  * Free a block or fragment.
 237:  *
 238:  * Place the specified disk block back on the free list of the
 239:  * specified device.
 240:  */
 241: free(ip, bno)
 242:     struct inode *ip;
 243:     daddr_t bno;
 244: {
 245:     register struct fs *fs;
 246:     register struct buf *bp;
 247:     struct fblk *fbp;
 248: 
 249:     fs = ip->i_fs;
 250:     if (badblock(fs, bno)) {
 251:         printf("bad block %D, ino %d\n", bno, ip->i_number);
 252:         return;
 253:     }
 254:     while (fs->fs_flock)
 255:         sleep((caddr_t)&fs->fs_flock, PINOD);
 256:     if (fs->fs_nfree <= 0) {
 257:         fs->fs_nfree = 1;
 258:         fs->fs_free[0] = 0;
 259:     }
 260:     if (fs->fs_nfree >= NICFREE) {
 261:         fs->fs_flock++;
 262:         bp = getblk(ip->i_dev, bno);
 263:         fbp = (FBLKP)mapin(bp);
 264:         *fbp = *((FBLKP)&fs->fs_nfree);
 265:         mapout(bp);
 266:         fs->fs_nfree = 0;
 267:         if (fs->fs_flags & MNT_ASYNC)
 268:             bdwrite(bp);
 269:         else
 270:             bwrite(bp);
 271:         fs->fs_flock = 0;
 272:         wakeup((caddr_t)&fs->fs_flock);
 273:     }
 274:     fs->fs_free[fs->fs_nfree++] = bno;
 275:     fs->fs_tfree++;
 276:     fs->fs_fmod = 1;
 277: }
 278: 
 279: /*
 280:  * Free an inode.
 281:  *
 282:  * Free the specified I node on the specified device.  The algorithm
 283:  * stores up to NICINOD I nodes in the super block and throws away any more.
 284:  */
 285: ifree(ip, ino)
 286:     struct inode *ip;
 287:     ino_t ino;
 288: {
 289:     register struct fs *fs;
 290: 
 291:     fs = ip->i_fs;
 292:     fs->fs_tinode++;
 293:     if (fs->fs_ilock)
 294:         return;
 295:     if (fs->fs_ninode >= NICINOD) {
 296:         if (fs->fs_lasti > ino)
 297:             fs->fs_nbehind++;
 298:         return;
 299:     }
 300:     fs->fs_inode[fs->fs_ninode++] = ino;
 301:     fs->fs_fmod = 1;
 302: }
 303: 
 304: /*
 305:  * Fserr prints the name of a file system with an error diagnostic.
 306:  *
 307:  * The form of the error message is:
 308:  *	fs: error message
 309:  */
 310: fserr(fp, cp)
 311:     struct fs *fp;
 312:     char *cp;
 313: {
 314:     printf("%s: %s\n", fp->fs_fsmnt, cp);
 315: }

Defined functions

balloc defined in line 33; used 4 times
free defined in line 241; used 4 times
fserr defined in line 310; used 5 times
ifree defined in line 285; used 1 times

Defined typedef's

FBLKP defined in line 23; used 4 times
Last modified: 1996-09-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3741
Valid CSS Valid XHTML 1.0 Strict