/* * alloc will obtain the next available * free disk block from the free list of * the specified device. * The super block has up to NICFREE remembered * free blocks; the last of these is read to * obtain NICFREE more . . . * * no space on dev x/y -- when * the free list is exhausted. */ struct buf *alloc(dev_t dev) { daddr_t bno; struct filsys *fp; struct buf *bp; if (debugAlloc) { printf("----- alloc dev = 0x%08X -----\n", dev); } fp = getfs(dev); while(fp->s_flock) sleep((caddr_t)&fp->s_flock, PINOD); do { if(fp->s_nfree <= 0) goto nospace; if (fp->s_nfree > NICFREE) { prdev("bad free count", dev); goto nospace; } bno = fp->s_free[--fp->s_nfree]; if(bno == 0) goto nospace; } while (badblock(fp, bno, dev)); if(fp->s_nfree <= 0) { fp->s_flock++; bp = bread(dev, bno); if ((bp->b_flags&B_ERROR) == 0) { fp->s_nfree = ((FBLKP)(bp->b_un.b_addr))->df_nfree; bcopy((caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free, (caddr_t)fp->s_free, sizeof(fp->s_free)); } brelse(bp); fp->s_flock = 0; wakeup((caddr_t)&fp->s_flock); if (fp->s_nfree <=0) goto nospace; } bp = getblk(dev, bno); clrbuf(bp); fp->s_fmod = 1; if (debugAlloc) { printf(" alloc = 0x%08X\n", bp->b_blkno); } return(bp); nospace: fp->s_nfree = 0; prdev("no space", dev); u.u_error = ENOSPC; return(NULL); }
/* * Check that a block number is in the * range between the I list and the size * of the device. * This is used mainly to check that a * garbage file system has not been mounted. * * bad block on dev x/y -- not in range */ int badblock(struct filsys *fp, daddr_t bn, dev_t dev) { if (bn < SUPERB + 1 + fp->s_isize || bn >= fp->s_fsize) { prdev("bad block", dev); return(1); } return(0); }
/* * Check that a block number is in the * range between the I list and the size * of the device. * This is used mainly to check that a * garbage file system has not been mounted. * * bad block on dev x/y -- not in range */ badblock(afp, abn, dev) { register struct filsys *fp; register char *bn; fp = afp; bn = abn; if (bn < fp->s_isize+2 || bn >= fp->s_fsize) { prdev("bad block", dev); return(1); } return(0); }
/* * getfs maps a device number into * a pointer to the incore super * block. * The algorithm is a linear * search through the mount table. * A consistency check of the * in core free-block and i-node * counts. * * bad count on dev x/y -- the count * check failed. At this point, all * the counts are zeroed which will * almost certainly lead to "no space" * diagnostic * panic: no fs -- the device is not mounted. * this "cannot happen" */ struct filsys *getfs(dev_t dev) { struct mount *mp; struct filsys *fp; for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if(mp->m_bufp != NULL && mp->m_dev == dev) { fp = mp->m_bufp->b_un.b_filsys; if(fp->s_nfree > NICFREE || fp->s_ninode > NICINOD) { prdev("bad count", dev); fp->s_nfree = 0; fp->s_ninode = 0; } return(fp); } panic("no fs"); return(NULL); }
/* * Allocate an unused I node * on the specified device. * Used with file creation. * The algorithm keeps up to * NICINOD spare I nodes in the * super block. When this runs out, * a linear search through the * I list is instituted to pick * up NICINOD more. */ struct inode *ialloc(dev_t dev) { struct filsys *fp; struct buf *bp; struct inode *ip; int i; struct dinode *dp; ino_t ino; int index; daddr_t adr; if (debugIalloc) { printf("----- ialloc dev = 0x%08X -----\n", dev); } fp = getfs(dev); while(fp->s_ilock) sleep((caddr_t)&fp->s_ilock, PINOD); loop: if(fp->s_ninode > 0) { ino = fp->s_inode[--fp->s_ninode]; if (ino < ROOTINO) goto loop; ip = iget(dev, ino); if(ip == NULL) return(NULL); if(ip->i_mode == 0) { for (i=0; i<NADDR; i++) ip->i_un.i_s1.i_addr[i] = 0; fp->s_fmod = 1; if (debugIalloc) { printf(" ialloc = 0x%08X\n", ip->i_number); } return(ip); } /* * Inode was allocated after all. * Look some more. */ iput(ip); goto loop; } fp->s_ilock++; ino = 0; /* HG: we start numbering inodes with 0 */ index = NICINOD; /* HG: start filling at upper end */ for(adr = SUPERB + 1; adr < SUPERB + 1 + fp->s_isize; adr++) { bp = bread(dev, adr); if (bp->b_flags & B_ERROR) { brelse(bp); ino += INOPB; continue; } dp = bp->b_un.b_dino; for(i=0; i<INOPB; i++) { if(dp->di_mode != 0) goto cont; for(ip = &inode[0]; ip < &inode[NINODE]; ip++) if(dev==ip->i_dev && ino==ip->i_number) goto cont; fp->s_inode[--index] = ino; fp->s_ninode++; if(fp->s_ninode >= NICINOD) break; cont: ino++; dp++; } brelse(bp); if(fp->s_ninode >= NICINOD) break; } /* HG: if the list is not completely filled, shift entries down */ if (index > 0) { for (i = 0; i < fp->s_ninode; i++) { fp->s_inode[i] = fp->s_inode[index++]; } } fp->s_ilock = 0; wakeup((caddr_t)&fp->s_ilock); if(fp->s_ninode > 0) goto loop; prdev("out of inodes", dev); u.u_error = ENOSPC; return(NULL); }