diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1997-10-06 15:27:41 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1997-10-06 15:27:41 +0000 |
commit | 62c64950f8e658fa60106b4d32e70ae3b6156d0d (patch) | |
tree | 744cdeb111ee67810449481a1420174c49e0ef8d /sys/ufs/ffs/ffs_alloc.c | |
parent | cc87020169150a242c9019d00234c378942f5e88 (diff) |
VFS Lite2 Changes
Diffstat (limited to 'sys/ufs/ffs/ffs_alloc.c')
-rw-r--r-- | sys/ufs/ffs/ffs_alloc.c | 210 |
1 files changed, 175 insertions, 35 deletions
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index e25073d6715..e4bf9e3d285 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_alloc.c,v 1.7 1997/07/22 10:31:50 deraadt Exp $ */ +/* $OpenBSD: ffs_alloc.c,v 1.8 1997/10/06 15:26:28 csapuntz Exp $ */ /* $NetBSD: ffs_alloc.c,v 1.11 1996/05/11 18:27:09 mycroft Exp $ */ /* @@ -59,7 +59,7 @@ extern u_long nextgennumber; static daddr_t ffs_alloccg __P((struct inode *, int, daddr_t, int)); -static daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, daddr_t)); +static daddr_t ffs_alloccgblk __P((struct inode *, struct buf *, daddr_t)); static daddr_t ffs_clusteralloc __P((struct inode *, int, daddr_t, int)); static ino_t ffs_dirpref __P((struct fs *)); static daddr_t ffs_fragextend __P((struct inode *, int, long, int, int)); @@ -70,6 +70,11 @@ static u_long ffs_hashalloc __P((struct inode *, int, long, int, static daddr_t ffs_nodealloccg __P((struct inode *, int, daddr_t, int)); static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int)); +#ifdef DIAGNOSTIC +static int ffs_checkblk __P((struct inode *, daddr_t, long)); +#endif +int ffs_freefile __P((struct vop_vfree_args *)); + /* * Allocate a block in the file system. * @@ -272,7 +277,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp) if (bno > 0) { bp->b_blkno = fsbtodb(fs, bno); (void) vnode_pager_uncache(ITOV(ip)); - ffs_blkfree(ip, bprev, (long)osize); + if (!DOINGSOFTDEP(ITOV(ip))) + ffs_blkfree(ip, bprev, (long)osize); if (nsize < request) ffs_blkfree(ip, bno + numfrags(fs, nsize), (long)(request - nsize)); @@ -314,15 +320,10 @@ nospace: * Note that the error return is not reflected back to the user. Rather * the previous block allocation will be used. */ -#ifdef DEBUG -#include <sys/sysctl.h> + int doasyncfree = 1; -struct ctldebug debug14 = { "doasyncfree", &doasyncfree }; +int doreallocblks = 1; int prtrealloc = 0; -struct ctldebug debug15 = { "prtrealloc", &prtrealloc }; -#else -#define doasyncfree 1 -#endif int ffs_reallocblks(v) @@ -343,6 +344,9 @@ ffs_reallocblks(v) int i, len, start_lvl, end_lvl, pref, ssize; struct timespec ts; + if (doreallocblks == 0) + return (ENOSPC); + vp = ap->a_vp; ip = VTOI(vp); fs = ip->i_fs; @@ -352,10 +356,22 @@ ffs_reallocblks(v) len = buflist->bs_nchildren; start_lbn = buflist->bs_children[0]->b_lblkno; end_lbn = start_lbn + len - 1; + #ifdef DIAGNOSTIC + for (i = 0; i < len; i++) + if (!ffs_checkblk(ip, + dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize)) + panic("ffs_reallocblks: unallocated block 1"); + for (i = 1; i < len; i++) if (buflist->bs_children[i]->b_lblkno != start_lbn + i) - panic("ffs_reallocblks: non-cluster"); + panic("ffs_reallocblks: non-logical cluster"); + + blkno = buflist->bs_children[0]->b_blkno; + ssize = fsbtodb(fs, fs->fs_frag); + for (i = 1; i < len - 1; i++) + if (buflist->bs_children[i]->b_blkno != blkno + (i * ssize)) + panic("ffs_reallocblks: non-physical cluster %d", i); #endif /* * If the latest allocation is in a new cylinder group, assume that @@ -422,9 +438,14 @@ ffs_reallocblks(v) #endif blkno = newblk; for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) { - if (i == ssize) + if (i == ssize) { bap = ebap; + soff = -i; + } #ifdef DIAGNOSTIC + if (!ffs_checkblk(ip, + dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize)) + panic("ffs_reallocblks: unallocated block 2"); if (dbtofsb(fs, buflist->bs_children[i]->b_blkno) != *bap) panic("ffs_reallocblks: alloc mismatch"); #endif @@ -432,6 +453,17 @@ ffs_reallocblks(v) if (prtrealloc) printf(" %d,", *bap); #endif + if (DOINGSOFTDEP(vp)) { + if (sbap == &ip->i_ffs_db[0] && i < ssize) + softdep_setup_allocdirect(ip, start_lbn + i, + blkno, *bap, fs->fs_bsize, fs->fs_bsize, + buflist->bs_children[i]); + else + softdep_setup_allocindir_page(ip, start_lbn + i, + i < ssize ? sbp : ebp, soff + i, blkno, + *bap, buflist->bs_children[i]); + } + *bap++ = blkno; } /* @@ -473,10 +505,15 @@ ffs_reallocblks(v) printf("\n\tnew:"); #endif for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) { - ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), - fs->fs_bsize); + if (!DOINGSOFTDEP(vp)) + ffs_blkfree(ip, + dbtofsb(fs, buflist->bs_children[i]->b_blkno), + fs->fs_bsize); buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); #ifdef DEBUG + if (!ffs_checkblk(ip, + dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize)) + panic("ffs_reallocblks: unallocated block 3"); if (prtrealloc) printf(" %d,", blkno); #endif @@ -815,6 +852,9 @@ ffs_fragextend(ip, cg, bprev, osize, nsize) fs->fs_cs(fs, cg).cs_nffree--; } fs->fs_fmod = 1; + if (DOINGSOFTDEP(ITOV(ip))) + softdep_setup_blkmapdep(bp, fs, bprev); + bdwrite(bp); return (bprev); } @@ -835,8 +875,8 @@ ffs_alloccg(ip, cg, bpref, size) register struct fs *fs; register struct cg *cgp; struct buf *bp; - register int i; - int error, bno, frags, allocsiz; + daddr_t bno, blkno; + int error, i, frags, allocsiz; fs = ip->i_fs; if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) @@ -855,7 +895,7 @@ ffs_alloccg(ip, cg, bpref, size) } cgp->cg_time = time.tv_sec; if (size == fs->fs_bsize) { - bno = ffs_alloccgblk(fs, cgp, bpref); + bno = ffs_alloccgblk(ip, bp, bpref); bdwrite(bp); return (bno); } @@ -877,7 +917,7 @@ ffs_alloccg(ip, cg, bpref, size) brelse(bp); return (NULL); } - bno = ffs_alloccgblk(fs, cgp, bpref); + bno = ffs_alloccgblk(ip, bp, bpref); bpref = dtogd(fs, bno); for (i = frags; i < fs->fs_frag; i++) setbit(cg_blksfree(cgp), bpref + i); @@ -904,8 +944,12 @@ ffs_alloccg(ip, cg, bpref, size) cgp->cg_frsum[allocsiz]--; if (frags != allocsiz) cgp->cg_frsum[allocsiz - frags]++; - bdwrite(bp); - return (cg * fs->fs_fpg + bno); + + blkno = cg * fs->fs_fpg + bno; + if (DOINGSOFTDEP(ITOV(ip))) + softdep_setup_blkmapdep(bp, fs, blkno); + bdwrite(bp); + return ((u_long)blkno); } /* @@ -920,16 +964,20 @@ ffs_alloccg(ip, cg, bpref, size) * blocks may be fragmented by the routine that allocates them. */ static daddr_t -ffs_alloccgblk(fs, cgp, bpref) - register struct fs *fs; - register struct cg *cgp; +ffs_alloccgblk(ip, bp, bpref) + struct inode *ip; + struct buf *bp; daddr_t bpref; { + struct fs *fs; + struct cg *cgp; daddr_t bno, blkno; int cylno, pos, delta; short *cylbp; register int i; + fs = ip->i_fs; + cgp = (struct cg *)bp->b_data; if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) { bpref = cgp->cg_rotor; goto norot; @@ -1020,7 +1068,10 @@ gotit: cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--; cg_blktot(cgp)[cylno]--; fs->fs_fmod = 1; - return (cgp->cg_cgx * fs->fs_fpg + bno); + blkno = cgp->cg_cgx * fs->fs_fpg + bno; + if (DOINGSOFTDEP(ITOV(ip))) + softdep_setup_blkmapdep(bp, fs, blkno); + return (blkno); } /* @@ -1040,7 +1091,7 @@ ffs_clusteralloc(ip, cg, bpref, len) register struct fs *fs; register struct cg *cgp; struct buf *bp; - int i, run, bno, bit, map; + int i, got, run, bno, bit, map; u_char *mapp; int32_t *lp; @@ -1094,7 +1145,7 @@ ffs_clusteralloc(ip, cg, bpref, len) mapp = &cg_clustersfree(cgp)[bpref / NBBY]; map = *mapp++; bit = 1 << (bpref % NBBY); - for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) { + for (run = 0, got = bpref; got < cgp->cg_nclusterblks; got++) { if ((map & bit) == 0) { run = 0; } else { @@ -1102,22 +1153,32 @@ ffs_clusteralloc(ip, cg, bpref, len) if (run == len) break; } - if ((i & (NBBY - 1)) != (NBBY - 1)) { + if ((got & (NBBY - 1)) != (NBBY - 1)) { bit <<= 1; } else { map = *mapp++; bit = 1; } } - if (i >= cgp->cg_nclusterblks) + if (got >= cgp->cg_nclusterblks) goto fail; /* * Allocate the cluster that we have found. */ - bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1); +#ifdef DIAGNOSTIC + for (i = 1; i <= len; i++) + if (!ffs_isblock(fs, cg_blksfree(cgp), got - run + i)) + panic("ffs_clusteralloc: map mismatch"); +#endif + bno = cg * fs->fs_fpg + blkstofrags(fs, got - run + 1); +#ifdef DIAGNOSTIC + if (dtog(fs, bno) != cg) + panic("ffs_clusteralloc: allocated out of group"); +#endif + len = blkstofrags(fs, len); for (i = 0; i < len; i += fs->fs_frag) - if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i) + if (ffs_alloccgblk(ip, bp, bno + i) != bno + i) panic("ffs_clusteralloc: lost block"); bdwrite(bp); return (bno); @@ -1195,6 +1256,9 @@ ffs_nodealloccg(ip, cg, ipref, mode) panic("ffs_nodealloccg: block not in map"); /* NOTREACHED */ gotit: + if (DOINGSOFTDEP(ITOV(ip))) + softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref); + setbit(cg_inosused(cgp), ipref); cgp->cg_cs.cs_nifree--; fs->fs_cstotal.cs_nifree--; @@ -1229,7 +1293,8 @@ ffs_blkfree(ip, bno, size) int i, error, cg, blk, frags, bbase; fs = ip->i_fs; - if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) { + if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 || + fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) { printf("dev = 0x%x, bsize = %d, size = %ld, fs = %s\n", ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt); panic("blkfree: bad size"); @@ -1255,7 +1320,7 @@ ffs_blkfree(ip, bno, size) bno = dtogd(fs, bno); if (size == fs->fs_bsize) { blkno = fragstoblks(fs, bno); - if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) { + if (!ffs_isfreeblock(fs, cg_blksfree(cgp), blkno)) { printf("dev = 0x%x, block = %d, fs = %s\n", ip->i_dev, bno, fs->fs_fsmnt); panic("blkfree: freeing free block"); @@ -1318,8 +1383,6 @@ ffs_blkfree(ip, bno, size) /* * Free an inode. - * - * The specified inode is placed back in the free map. */ int ffs_vfree(v) @@ -1330,6 +1393,28 @@ ffs_vfree(v) ino_t a_ino; int a_mode; } */ *ap = v; + + + if (DOINGSOFTDEP(ap->a_pvp)) { + softdep_freefile(ap); + return (0); + } + + return (ffs_freefile(ap)); +} + +/* + * Do the actual free operation. + * The specified inode is placed back in the free map. + */ +int +ffs_freefile(ap) + struct vop_vfree_args /* { + struct vnode *a_pvp; + ino_t a_ino; + int a_mode; + } */ *ap; +{ register struct fs *fs; register struct cg *cgp; register struct inode *pip; @@ -1347,7 +1432,7 @@ ffs_vfree(v) (int)fs->fs_cgsize, NOCRED, &bp); if (error) { brelse(bp); - return (0); + return (error); } cgp = (struct cg *)bp->b_data; if (!cg_chkmagic(cgp)) { @@ -1378,6 +1463,60 @@ ffs_vfree(v) return (0); } +#ifdef DIAGNOSTIC +/* + * Verify allocation of a block or fragment. Returns true if block or + * fragment is allocated, false if it is free. + */ +int +ffs_checkblk(ip, bno, size) + struct inode *ip; + daddr_t bno; + long size; +{ + struct fs *fs; + struct cg *cgp; + struct buf *bp; + int i, error, frags, free; + + fs = ip->i_fs; + if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) { + printf("bsize = %d, size = %d, fs = %s\n", + fs->fs_bsize, size, fs->fs_fsmnt); + panic("checkblk: bad size"); + } + if ((u_int)bno >= fs->fs_size) + panic("checkblk: bad block %d", bno); + error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, dtog(fs, bno))), + (int)fs->fs_cgsize, NOCRED, &bp); + if (error) { + /* XXX -probably should pannic here */ + brelse(bp); + return (-1); + } + cgp = (struct cg *)bp->b_data; + if (!cg_chkmagic(cgp)) { + /* XXX -probably should pannic here */ + brelse(bp); + return (-1); + } + bno = dtogd(fs, bno); + if (size == fs->fs_bsize) { + free = ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno)); + } else { + frags = numfrags(fs, size); + for (free = 0, i = 0; i < frags; i++) + if (isset(cg_blksfree(cgp), bno + i)) + free++; + if (free != 0 && free != frags) + panic("checkblk: partially free fragment"); + } + brelse(bp); + return (!free); +} +#endif /* DIAGNOSTIC */ + + /* * Find a block of the specified size in the specified cylinder group. * @@ -1550,3 +1689,4 @@ ffs_fserr(fs, uid, cp) log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); } + |