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: }