- int start, len, loc, map, i;
-
- fs = ip->i_fs;
- if (fs->fs_cs(fs, cg).cs_nifree == 0)
- return (NULL);
-#ifdef SECSIZE
- bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
- fs->fs_dbsize);
-#else SECSIZE
- bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize);
-#endif SECSIZE
- cgp = bp->b_un.b_cg;
- if (bp->b_flags & B_ERROR || !cg_chkmagic(cgp) ||
- cgp->cg_cs.cs_nifree == 0) {
- brelse(bp);
- return (NULL);
- }
- cgp->cg_time = time.tv_sec;
- if (ipref) {
- ipref %= fs->fs_ipg;
- if (isclr(cg_inosused(cgp), ipref))
- goto gotit;
- }
- start = cgp->cg_irotor / NBBY;
- len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY);
- loc = skpc(0xff, len, &cg_inosused(cgp)[start]);
- if (loc == 0) {
- len = start + 1;
- start = 0;
- loc = skpc(0xff, len, &cg_inosused(cgp)[0]);
- if (loc == 0) {
- printf("cg = %s, irotor = %d, fs = %s\n",
- cg, cgp->cg_irotor, fs->fs_fsmnt);
- panic("ialloccg: map corrupted");
- /* NOTREACHED */
- }
- }
- i = start + len - loc;
- map = cg_inosused(cgp)[i];
- ipref = i * NBBY;
- for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
- if ((map & i) == 0) {
- cgp->cg_irotor = ipref;
- goto gotit;
- }
- }
- printf("fs = %s\n", fs->fs_fsmnt);
- panic("ialloccg: block not in map");
- /* NOTREACHED */
-gotit:
- setbit(cg_inosused(cgp), ipref);
- cgp->cg_cs.cs_nifree--;
- fs->fs_cstotal.cs_nifree--;
- fs->fs_cs(fs, cg).cs_nifree--;
- fs->fs_fmod++;
- if ((mode & IFMT) == IFDIR) {
- cgp->cg_cs.cs_ndir++;
- fs->fs_cstotal.cs_ndir++;
- fs->fs_cs(fs, cg).cs_ndir++;
- }
- bdwrite(bp);
- return (cg * fs->fs_ipg + ipref);
-}
-
-/*
- * Free a block or fragment.
- *
- * The specified block or fragment is placed back in the
- * free map. If a fragment is deallocated, a possible
- * block reassembly is checked.
- */
-blkfree(ip, bno, size)
- register struct inode *ip;
- daddr_t bno;
- off_t size;
-{
- register struct fs *fs;
- register struct cg *cgp;
- register struct buf *bp;
- int cg, blk, frags, bbase;
- register int i;
-
- fs = ip->i_fs;
- if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) {
- printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n",
- ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
- panic("blkfree: bad size");
- }
- cg = dtog(fs, bno);
- if (badblock(fs, bno)) {
- printf("bad block %d, ino %d\n", bno, ip->i_number);
- return;
- }
-#ifdef SECSIZE
- bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
- fs->fs_dbsize);
-#else SECSIZE
- bp = bread(ip->i_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize);
-#endif SECSIZE
- cgp = bp->b_un.b_cg;
- if (bp->b_flags & B_ERROR || !cg_chkmagic(cgp)) {
- brelse(bp);
- return;
- }
- cgp->cg_time = time.tv_sec;
- bno = dtogd(fs, bno);
- if (size == fs->fs_bsize) {
- if (isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno))) {
- printf("dev = 0x%x, block = %d, fs = %s\n",
- ip->i_dev, bno, fs->fs_fsmnt);
- panic("blkfree: freeing free block");
- }
- setblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno));
- cgp->cg_cs.cs_nbfree++;
- fs->fs_cstotal.cs_nbfree++;
- fs->fs_cs(fs, cg).cs_nbfree++;
- i = cbtocylno(fs, bno);
- cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++;
- cg_blktot(cgp)[i]++;
- } else {
- bbase = bno - fragnum(fs, bno);
- /*
- * decrement the counts associated with the old frags
- */
- blk = blkmap(fs, cg_blksfree(cgp), bbase);
- fragacct(fs, blk, cgp->cg_frsum, -1);
- /*
- * deallocate the fragment
- */
- frags = numfrags(fs, size);
- for (i = 0; i < frags; i++) {
- if (isset(cg_blksfree(cgp), bno + i)) {
- printf("dev = 0x%x, block = %d, fs = %s\n",
- ip->i_dev, bno + i, fs->fs_fsmnt);
- panic("blkfree: freeing free frag");
- }
- setbit(cg_blksfree(cgp), bno + i);
- }
- cgp->cg_cs.cs_nffree += i;
- fs->fs_cstotal.cs_nffree += i;
- fs->fs_cs(fs, cg).cs_nffree += i;
- /*
- * add back in counts associated with the new frags
- */
- blk = blkmap(fs, cg_blksfree(cgp), bbase);
- fragacct(fs, blk, cgp->cg_frsum, 1);
- /*
- * if a complete block has been reassembled, account for it
- */
- if (isblock(fs, cg_blksfree(cgp),
- (daddr_t)fragstoblks(fs, bbase))) {
- cgp->cg_cs.cs_nffree -= fs->fs_frag;
- fs->fs_cstotal.cs_nffree -= fs->fs_frag;
- fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
- cgp->cg_cs.cs_nbfree++;
- fs->fs_cstotal.cs_nbfree++;
- fs->fs_cs(fs, cg).cs_nbfree++;
- i = cbtocylno(fs, bbase);
- cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++;
- cg_blktot(cgp)[i]++;
- }
- }
- fs->fs_fmod++;
- bdwrite(bp);
-}
-
-/*
- * Free an inode.
- *
- * The specified inode is placed back in the free map.
- */
-ifree(ip, ino, mode)