📄 ufs_alloc.c
字号:
goto norot; } bpref = blknum(fs, bpref); bpref = dtogd(fs, bpref); /* * if the requested block is available, use it */ if (isblock(fs, cgp->cg_free, fragstoblks(fs, bpref))) { 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 = blkstofrags(fs, (bno + i)); 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)fragstoblks(fs, bno)); cgp->cg_cs.cs_nbfree--; cylno = cbtocylno(fs, bno); cgp->cg_b[cylno][cbtorpos(fs, bno)]--; cgp->cg_btot[cylno]--; fs_lock(mp); fs->fs_cstotal.cs_nbfree--; fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; mp->m_flags |= M_MOD; fs_unlock(mp); return (cgp->cg_cgx * fs->fs_fpg + bno);} /* * Determine whether an gnode can be allocated. * * Check to see if an gnode is available, and if it is, * allocate it using the following policy: * 1) allocate the requested gnode. * 2) allocate the next available gnode after the requested * gnode in the specified cylinder group. */gno_tialloccg(gp, cg, gpref, mode) register struct gnode *gp; int cg; register daddr_t gpref; int mode;{ register struct fs *fs; register struct cg *cgp; struct buf *bp; int start, len, loc; register int map, i; fs = FS(gp); if (fs->fs_cs(fs, cg).cs_nifree == 0) return (NULL); bp = bread(gp->g_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, (struct gnode *) NULL); cgp = bp->b_un.b_cg; if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC || cgp->cg_cs.cs_nifree == 0) { brelse(bp); return (NULL); } cgp->cg_time = timepick->tv_sec; if (gpref) { gpref %= fs->fs_ipg; if (isclr(cgp->cg_iused, gpref)) goto gotit; } start = cgp->cg_irotor / NBBY; len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY); loc = skpc(0xff, len, &cgp->cg_iused[start]); if (loc == 0) { len = start + 1; start = 0; loc = skpc(0xff, len, &cgp->cg_iused[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 = cgp->cg_iused[i]; gpref = i * NBBY; for (i = 1; i < (1 << NBBY); i <<= 1, gpref++) { if ((map & i) == 0) { cgp->cg_irotor = gpref; goto gotit; } } printf("fs = %s\n", fs->fs_fsmnt); panic("ialloccg: block not in map"); /* NOTREACHED */gotit: setbit(cgp->cg_iused, gpref); cgp->cg_cs.cs_nifree--; fs_lock(gp->g_mp); fs->fs_cstotal.cs_nifree--; fs->fs_cs(fs, cg).cs_nifree--; gp->g_mp->m_flags |= M_MOD; if ((mode & GFMT) == GFDIR) { cgp->cg_cs.cs_ndir++; fs->fs_cstotal.cs_ndir++; fs->fs_cs(fs, cg).cs_ndir++; } fs_unlock(gp->g_mp); if (gp->g_mp->m_flags & M_SYNC) bwrite(bp); else bdwrite(bp); return (cg * fs->fs_ipg + gpref);}/* * 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. */free(gp, bno, size) register struct gnode *gp; register 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 = FS(gp); if ((unsigned)size > fs->fs_bsize || fragoff(fs, size) != 0) { printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n", gp->g_dev, fs->fs_bsize, size, fs->fs_fsmnt); panic("free: bad size"); } cg = dtog(fs, bno); if (badblock(fs, bno)) { printf("bad block %d, gno %d\n", bno, gp->g_number); return; } bp = bread(gp->g_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, (struct gnode *) NULL); cgp = bp->b_un.b_cg; if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { brelse(bp); return; } cgp->cg_time = timepick->tv_sec; bno = dtogd(fs, bno); if (size == fs->fs_bsize) { if (isblock(fs, cgp->cg_free, fragstoblks(fs, bno))) { printf("dev = 0x%x, block = %d, fs = %s\n", gp->g_dev, bno, fs->fs_fsmnt); panic("free: freeing free block"); } setblock(fs, cgp->cg_free, fragstoblks(fs, bno)); cgp->cg_cs.cs_nbfree++; i = cbtocylno(fs, bno); cgp->cg_b[i][cbtorpos(fs, bno)]++; cgp->cg_btot[i]++; fs_lock(gp->g_mp); fs->fs_cstotal.cs_nbfree++; fs->fs_cs(fs, cg).cs_nbfree++; gp->g_mp->m_flags |= M_MOD; fs_unlock(gp->g_mp); } else { bbase = bno - fragnum(fs, bno); /* * decrement the counts associated with the old frags */ blk = blkmap(fs, cgp->cg_free, bbase); fragacct(fs, blk, cgp->cg_frsum, -1); /* * deallocate the fragment */ frags = numfrags(fs, size); for (i = 0; i < frags; i++) { if (isset(cgp->cg_free, bno + i)) { printf("dev = 0x%x, block = %d, fs = %s\n", gp->g_dev, bno + i, fs->fs_fsmnt); panic("free: freeing free frag"); } setbit(cgp->cg_free, bno + i); } cgp->cg_cs.cs_nffree += i; /* * add back in counts associated with the new frags */ blk = blkmap(fs, cgp->cg_free, bbase); fragacct(fs, blk, cgp->cg_frsum, 1); /* * Update superblock information. If a complete block * has been reassembled, account for it */ fs_lock(gp->g_mp); fs->fs_cstotal.cs_nffree += i; fs->fs_cs(fs, cg).cs_nffree += i; if (isblock(fs, cgp->cg_free, 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); cgp->cg_b[i][cbtorpos(fs, bbase)]++; cgp->cg_btot[i]++; } gp->g_mp->m_flags |= M_MOD; fs_unlock(gp->g_mp); } if (gp->g_mp->m_flags & M_SYNC) bwrite(bp); else bdwrite(bp);}/* * Free a gnode. * * The specified gnode is placed back in the free map. */ufs_gfree(gp, gno, mode) register struct gnode *gp; register gno_t gno; int mode;{ register struct fs *fs; register struct cg *cgp; register struct buf *bp; register int cg; fs = FS(gp); if ((unsigned)gno >= fs->fs_ipg*fs->fs_ncg) { printf("dev = 0x%x, gno = %d, fs = %s\n", gp->g_dev, gno, fs->fs_fsmnt); panic("ufs_gfree: range"); } cg = itog(fs, gno); bp = bread(gp->g_dev, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, (struct gnode *) NULL); cgp = bp->b_un.b_cg; if (bp->b_flags & B_ERROR || cgp->cg_magic != CG_MAGIC) { brelse(bp); return; } cgp->cg_time = timepick->tv_sec; gno %= fs->fs_ipg; if (isclr(cgp->cg_iused, gno)) { printf("dev = 0x%x, gno = %d, fs = %s block %d\n", gp->g_dev, gno, fs->fs_fsmnt, fsbtodb(fs, cgtod(fs, cg))); panic("ufs_gfree: freeing free gnode"); } clrbit(cgp->cg_iused, gno); if (gno < cgp->cg_irotor) cgp->cg_irotor = gno; cgp->cg_cs.cs_nifree++; fs_lock(gp->g_mp); fs->fs_cstotal.cs_nifree++; fs->fs_cs(fs, cg).cs_nifree++; if ((mode & GFMT) == GFDIR) { cgp->cg_cs.cs_ndir--; fs->fs_cstotal.cs_ndir--; fs->fs_cs(fs, cg).cs_ndir--; } gp->g_mp->m_flags |= M_MOD; fs_unlock(gp->g_mp); if (gp->g_mp->m_flags & M_SYNC) bwrite(bp); else bdwrite(bp);}/* * Find a block of the specified size in the specified cylinder group. * * It is a panic if a request is made to find a block if none are * available. */daddr_tmapsearch(fs, cgp, bpref, allocsiz) register struct fs *fs; register struct cg *cgp; daddr_t bpref; int allocsiz;{ register daddr_t bno; register int i; register int field, subfield; int start, len, loc; int blk, pos; /* * find the fragment by searching through the free block * map for an appropriate bit pattern */ if (bpref) start = dtogd(fs, bpref) / NBBY; else start = cgp->cg_frotor / NBBY; len = howmany(fs->fs_fpg, NBBY) - start; loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[start], (caddr_t)fragtbl[fs->fs_frag], (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) { len = start + 1; start = 0; loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[0], (caddr_t)fragtbl[fs->fs_frag], (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) { printf("start = %d, len = %d, fs = %s\n", start, len, fs->fs_fsmnt); panic("alloccg: map corrupted"); /* NOTREACHED */ } } bno = (start + len - loc) * NBBY; cgp->cg_frotor = bno; /* * found the byte in the map * sift through the bits to find the selected frag */ for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { blk = blkmap(fs, cgp->cg_free, bno); blk <<= 1; field = around[allocsiz]; subfield = inside[allocsiz]; for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { if ((blk & field) == subfield) return (bno + pos); field <<= 1; subfield <<= 1; } } printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt); panic("alloccg: block not in map"); return (-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -