diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2008-01-19 18:12:25 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2008-01-19 18:12:25 +0000 |
| commit | 2044a6a462105dd02820cdfe7bf2ede951017d44 (patch) | |
| tree | 6f553f21b2bfc22edb6c2a748f80627d4b5c0710 | |
| parent | f86934faa805728b12f7d0523f611dc038719c49 (diff) | |
Notes
| -rw-r--r-- | sys/ufs/ffs/ffs_balloc.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 97f4fdae9d1e..1badab653bf6 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -102,6 +102,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, ufs2_daddr_t newb; ufs1_daddr_t *bap, pref; ufs1_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1]; + ufs2_daddr_t *lbns_remfree, lbns[NIADDR + 1]; int unwindidx = -1; ip = VTOI(vp); @@ -231,6 +232,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, nb = dp->di_ib[indirs[0].in_off]; allocib = NULL; allocblk = allociblk; + lbns_remfree = lbns; if (nb == 0) { UFS_LOCK(ump); pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0); @@ -239,6 +241,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, return (error); nb = newb; *allocblk++ = nb; + *lbns_remfree++ = indirs[1].in_lbn; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, 0); bp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(bp); @@ -289,6 +292,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, } nb = newb; *allocblk++ = nb; + *lbns_remfree++ = indirs[i].in_lbn; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(nbp); @@ -342,6 +346,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, } nb = newb; *allocblk++ = nb; + *lbns_remfree++ = lbn; nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); if (flags & BA_CLRBUF) @@ -403,9 +408,18 @@ fail: * have an error to return to the user. */ (void) ffs_syncvnode(vp, MNT_WAIT); - for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { - ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, - ip->i_number); + for (deallocated = 0, blkp = allociblk, lbns_remfree = lbns; + blkp < allocblk; blkp++, lbns_remfree++) { + /* + * We shall not leave the freed blocks on the vnode + * buffer object lists. + */ + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT); + if (bp != NULL) { + bp->b_flags |= (B_INVAL | B_RELBUF); + bp->b_flags &= ~B_ASYNC; + brelse(bp); + } deallocated += fs->fs_bsize; } if (allocib != NULL) { @@ -441,6 +455,14 @@ fail: ip->i_flag |= IN_CHANGE | IN_UPDATE; } (void) ffs_syncvnode(vp, MNT_WAIT); + /* + * After the buffers are invalidated and on-disk pointers are + * cleared, free the blocks. + */ + for (blkp = allociblk; blkp < allocblk; blkp++) { + ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, + ip->i_number); + } return (error); } @@ -464,6 +486,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, struct indir indirs[NIADDR + 2]; ufs2_daddr_t nb, newb, *bap, pref; ufs2_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1]; + ufs2_daddr_t *lbns_remfree, lbns[NIADDR + 1]; int deallocated, osize, nsize, num, i, error; int unwindidx = -1; @@ -703,6 +726,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, nb = dp->di_ib[indirs[0].in_off]; allocib = NULL; allocblk = allociblk; + lbns_remfree = lbns; if (nb == 0) { UFS_LOCK(ump); pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0); @@ -711,6 +735,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, return (error); nb = newb; *allocblk++ = nb; + *lbns_remfree++ = indirs[1].in_lbn; bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, 0); bp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(bp); @@ -761,6 +786,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, } nb = newb; *allocblk++ = nb; + *lbns_remfree++ = indirs[i].in_lbn; nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(nbp); @@ -814,6 +840,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, } nb = newb; *allocblk++ = nb; + *lbns_remfree++ = lbn; nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); if (flags & BA_CLRBUF) @@ -881,9 +908,18 @@ fail: * have an error to return to the user. */ (void) ffs_syncvnode(vp, MNT_WAIT); - for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { - ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, - ip->i_number); + for (deallocated = 0, blkp = allociblk, lbns_remfree = lbns; + blkp < allocblk; blkp++, lbns_remfree++) { + /* + * We shall not leave the freed blocks on the vnode + * buffer object lists. + */ + bp = getblk(vp, *lbns_remfree, fs->fs_bsize, 0, 0, GB_NOCREAT); + if (bp != NULL) { + bp->b_flags |= (B_INVAL | B_RELBUF); + bp->b_flags &= ~B_ASYNC; + brelse(bp); + } deallocated += fs->fs_bsize; } if (allocib != NULL) { @@ -919,5 +955,13 @@ fail: ip->i_flag |= IN_CHANGE | IN_UPDATE; } (void) ffs_syncvnode(vp, MNT_WAIT); + /* + * After the buffers are invalidated and on-disk pointers are + * cleared, free the blocks. + */ + for (blkp = allociblk; blkp < allocblk; blkp++) { + ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, + ip->i_number); + } return (error); } |
