diff options
-rw-r--r-- | sys/contrib/softupdates/ffs_softdep.c | 26 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 26 |
2 files changed, 36 insertions, 16 deletions
diff --git a/sys/contrib/softupdates/ffs_softdep.c b/sys/contrib/softupdates/ffs_softdep.c index 870d6ac..6773d17 100644 --- a/sys/contrib/softupdates/ffs_softdep.c +++ b/sys/contrib/softupdates/ffs_softdep.c @@ -52,7 +52,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)ffs_softdep.c 9.56 (McKusick) 1/17/00 + * from: @(#)ffs_softdep.c 9.57 (McKusick) 3/17/00 * $FreeBSD$ */ @@ -1525,19 +1525,22 @@ setup_allocindir_phase2(bp, ip, aip) oldaip; oldaip = LIST_NEXT(oldaip, ai_next)) if (oldaip->ai_offset == aip->ai_offset) break; + freefrag = NULL; if (oldaip != NULL) { if (oldaip->ai_newblkno != aip->ai_oldblkno) panic("setup_allocindir_phase2: blkno"); aip->ai_oldblkno = oldaip->ai_oldblkno; - freefrag = oldaip->ai_freefrag; - oldaip->ai_freefrag = aip->ai_freefrag; - aip->ai_freefrag = freefrag; + freefrag = aip->ai_freefrag; + aip->ai_freefrag = oldaip->ai_freefrag; + oldaip->ai_freefrag = NULL; free_allocindir(oldaip, NULL); } LIST_INSERT_HEAD(&indirdep->ir_deplisthd, aip, ai_next); ((ufs_daddr_t *)indirdep->ir_savebp->b_data) [aip->ai_offset] = aip->ai_oldblkno; FREE_LOCK(&lk); + if (freefrag != NULL) + handle_workitem_freefrag(freefrag); } if (newindirdep) { if (indirdep->ir_savebp != NULL) @@ -1603,7 +1606,7 @@ softdep_setup_freeblocks(ip, length) struct vnode *vp; struct buf *bp; struct fs *fs; - int i, error; + int i, delay, error; fs = ip->i_fs; if (length != 0) @@ -1653,10 +1656,13 @@ softdep_setup_freeblocks(ip, length) * with this inode are obsolete and can simply be de-allocated. * We must first merge the two dependency lists to get rid of * any duplicate freefrag structures, then purge the merged list. + * If we still have a bitmap dependency, then the inode has never + * been written to disk, so we can free any fragments without delay. */ merge_inode_lists(inodedep); + delay = (inodedep->id_state & DEPCOMPLETE); while ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)) != 0) - free_allocdirect(&inodedep->id_inoupdt, adp, 1); + free_allocdirect(&inodedep->id_inoupdt, adp, delay); FREE_LOCK(&lk); bdwrite(bp); /* @@ -3157,7 +3163,7 @@ handle_allocdirect_partdone(adp) { struct allocdirect *listadp; struct inodedep *inodedep; - long bsize; + long bsize, delay; if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE) return; @@ -3207,12 +3213,16 @@ handle_allocdirect_partdone(adp) /* * If we have found the just finished dependency, then free * it along with anything that follows it that is complete. + * If the inode still has a bitmap dependency, then it has + * never been written to disk, hence the on-disk inode cannot + * reference the old fragment so we can free it without delay. */ + delay = (inodedep->id_state & DEPCOMPLETE); for (; adp; adp = listadp) { listadp = TAILQ_NEXT(adp, ad_next); if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE) return; - free_allocdirect(&inodedep->id_inoupdt, adp, 1); + free_allocdirect(&inodedep->id_inoupdt, adp, delay); } } diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 870d6ac..6773d17 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -52,7 +52,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)ffs_softdep.c 9.56 (McKusick) 1/17/00 + * from: @(#)ffs_softdep.c 9.57 (McKusick) 3/17/00 * $FreeBSD$ */ @@ -1525,19 +1525,22 @@ setup_allocindir_phase2(bp, ip, aip) oldaip; oldaip = LIST_NEXT(oldaip, ai_next)) if (oldaip->ai_offset == aip->ai_offset) break; + freefrag = NULL; if (oldaip != NULL) { if (oldaip->ai_newblkno != aip->ai_oldblkno) panic("setup_allocindir_phase2: blkno"); aip->ai_oldblkno = oldaip->ai_oldblkno; - freefrag = oldaip->ai_freefrag; - oldaip->ai_freefrag = aip->ai_freefrag; - aip->ai_freefrag = freefrag; + freefrag = aip->ai_freefrag; + aip->ai_freefrag = oldaip->ai_freefrag; + oldaip->ai_freefrag = NULL; free_allocindir(oldaip, NULL); } LIST_INSERT_HEAD(&indirdep->ir_deplisthd, aip, ai_next); ((ufs_daddr_t *)indirdep->ir_savebp->b_data) [aip->ai_offset] = aip->ai_oldblkno; FREE_LOCK(&lk); + if (freefrag != NULL) + handle_workitem_freefrag(freefrag); } if (newindirdep) { if (indirdep->ir_savebp != NULL) @@ -1603,7 +1606,7 @@ softdep_setup_freeblocks(ip, length) struct vnode *vp; struct buf *bp; struct fs *fs; - int i, error; + int i, delay, error; fs = ip->i_fs; if (length != 0) @@ -1653,10 +1656,13 @@ softdep_setup_freeblocks(ip, length) * with this inode are obsolete and can simply be de-allocated. * We must first merge the two dependency lists to get rid of * any duplicate freefrag structures, then purge the merged list. + * If we still have a bitmap dependency, then the inode has never + * been written to disk, so we can free any fragments without delay. */ merge_inode_lists(inodedep); + delay = (inodedep->id_state & DEPCOMPLETE); while ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)) != 0) - free_allocdirect(&inodedep->id_inoupdt, adp, 1); + free_allocdirect(&inodedep->id_inoupdt, adp, delay); FREE_LOCK(&lk); bdwrite(bp); /* @@ -3157,7 +3163,7 @@ handle_allocdirect_partdone(adp) { struct allocdirect *listadp; struct inodedep *inodedep; - long bsize; + long bsize, delay; if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE) return; @@ -3207,12 +3213,16 @@ handle_allocdirect_partdone(adp) /* * If we have found the just finished dependency, then free * it along with anything that follows it that is complete. + * If the inode still has a bitmap dependency, then it has + * never been written to disk, hence the on-disk inode cannot + * reference the old fragment so we can free it without delay. */ + delay = (inodedep->id_state & DEPCOMPLETE); for (; adp; adp = listadp) { listadp = TAILQ_NEXT(adp, ad_next); if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE) return; - free_allocdirect(&inodedep->id_inoupdt, adp, 1); + free_allocdirect(&inodedep->id_inoupdt, adp, delay); } } |