-/*
- * Determine whether a block can be allocated.
- *
- * Check to see if a block of the apprpriate size is available,
- * and if it is, allocate it.
- */
-daddr_t
-alloccg(ip, cg, bpref, size)
- struct inode *ip;
- int cg;
- daddr_t bpref;
- int size;
-{
- register struct fs *fs;
- register struct buf *bp;
- register struct cg *cgp;
- int bno, frags;
- int allocsiz;
- register int i;
-
- fs = ip->i_fs;
- if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
- return (NULL);
- bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_bsize);
- cgp = bp->b_un.b_cg;
- if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) {
- brelse(bp);
- return (NULL);
- }
- cgp->cg_time = time.tv_sec;
- if (size == fs->fs_bsize) {
- bno = alloccgblk(fs, cgp, bpref);
- bdwrite(bp);
- return (bno);
- }
- /*
- * check to see if any fragments are already available
- * allocsiz is the size which will be allocated, hacking
- * it down to a smaller size if necessary
- */
- frags = numfrags(fs, size);
- for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++)
- if (cgp->cg_frsum[allocsiz] != 0)
- break;
- if (allocsiz == fs->fs_frag) {
- /*
- * no fragments were available, so a block will be
- * allocated, and hacked up
- */
- if (cgp->cg_cs.cs_nbfree == 0) {
- brelse(bp);
- return (NULL);
- }
- bno = alloccgblk(fs, cgp, bpref);
- bpref = dtogd(fs, bno);
- for (i = frags; i < fs->fs_frag; i++)
- setbit(cgp->cg_free, bpref + i);
- i = fs->fs_frag - frags;
- cgp->cg_cs.cs_nffree += i;
- fs->fs_cstotal.cs_nffree += i;
- fs->fs_cs(fs, cg).cs_nffree += i;
- cgp->cg_frsum[i]++;
- bdwrite(bp);
- return (bno);
- }
- bno = mapsearch(fs, cgp, bpref, allocsiz);
- if (bno < 0)
- return (NULL);
- for (i = 0; i < frags; i++)
- clrbit(cgp->cg_free, bno + i);
- cgp->cg_cs.cs_nffree -= frags;
- fs->fs_cstotal.cs_nffree -= frags;
- fs->fs_cs(fs, cg).cs_nffree -= frags;
- cgp->cg_frsum[allocsiz]--;
- if (frags != allocsiz)
- cgp->cg_frsum[allocsiz - frags]++;
- bdwrite(bp);
- return (cg * fs->fs_fpg + bno);
-}
-
-/*
- * Allocate a block in a cylinder group.
- *
- * This algorithm implements the following policy:
- * 1) allocate the requested block.
- * 2) allocate a rotationally optimal block in the same cylinder.
- * 3) allocate the next available block on the block rotor for the
- * specified cylinder group.
- * Note that this routine only allocates fs_bsize blocks; these
- * blocks may be fragmented by the routine that allocates them.
- */
-daddr_t
-alloccgblk(fs, cgp, bpref)
- register struct fs *fs;
- register struct cg *cgp;
- daddr_t bpref;
-{
- daddr_t bno;
- int cylno, pos, delta;
- short *cylbp;
- register int i;
-
- if (bpref == 0) {
- bpref = cgp->cg_rotor;
- goto norot;
- }
- bpref &= ~(fs->fs_frag - 1);
- bpref = dtogd(fs, bpref);
- /*
- * if the requested block is available, use it
- */
- if (isblock(fs, cgp->cg_free, bpref/fs->fs_frag)) {
- bno = bpref;
- goto gotit;
- }
- /*
- * check for a block available on the same cylinder
- */
- cylno = cbtocylno(fs, bpref);
- if (cgp->cg_btot[cylno] == 0)
- goto norot;
- if (fs->fs_cpc == 0) {
- /*
- * block layout info is not available, so just have
- * to take any block in this cylinder.
- */
- bpref = howmany(fs->fs_spc * cylno, NSPF(fs));
- goto norot;
- }
- /*
- * check the summary information to see if a block is
- * available in the requested cylinder starting at the
- * requested rotational position and proceeding around.
- */
- cylbp = cgp->cg_b[cylno];
- pos = cbtorpos(fs, bpref);
- for (i = pos; i < NRPOS; i++)
- if (cylbp[i] > 0)
- break;
- if (i == NRPOS)
- for (i = 0; i < pos; i++)
- if (cylbp[i] > 0)
- break;
- if (cylbp[i] > 0) {
- /*
- * found a rotational position, now find the actual
- * block. A panic if none is actually there.
- */
- pos = cylno % fs->fs_cpc;
- bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
- if (fs->fs_postbl[pos][i] == -1) {
- printf("pos = %d, i = %d, fs = %s\n",
- pos, i, fs->fs_fsmnt);
- panic("alloccgblk: cyl groups corrupted");
- }
- for (i = fs->fs_postbl[pos][i];; ) {
- if (isblock(fs, cgp->cg_free, bno + i)) {
- bno = (bno + i) * fs->fs_frag;
- goto gotit;
- }
- delta = fs->fs_rotbl[i];
- if (delta <= 0 || delta > MAXBPC - i)
- break;
- i += delta;
- }
- printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt);
- panic("alloccgblk: can't find blk in cyl");
- }
-norot:
- /*
- * no blocks in the requested cylinder, so take next
- * available one in this cylinder group.
- */
- bno = mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
- if (bno < 0)
- return (NULL);
- cgp->cg_rotor = bno;
-gotit:
- clrblock(fs, cgp->cg_free, (long)(bno/fs->fs_frag));
- cgp->cg_cs.cs_nbfree--;
- fs->fs_cstotal.cs_nbfree--;
- fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
- cylno = cbtocylno(fs, bno);
- cgp->cg_b[cylno][cbtorpos(fs, bno)]--;
- cgp->cg_btot[cylno]--;
- fs->fs_fmod++;
- return (cgp->cg_cgx * fs->fs_fpg + bno);
-}
-
-/*
- * Determine whether an inode can be allocated.
- *
- * Check to see if an inode is available, and if it is,
- * allocate it using the following policy:
- * 1) allocate the requested inode.
- * 2) allocate the next available inode after the requested
- * inode in the specified cylinder group.
- */
-ino_t
-ialloccg(ip, cg, ipref, mode)
- struct inode *ip;
- int cg;
- daddr_t ipref;
- int mode;