From d3abb5271448b54e40be60a527566a669ceb8e99 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Sun, 18 Jun 2000 22:05:57 +0000 Subject: [PATCH] Some additional performance improvements. When freeing an inode check to see if it has been committed to disk. If it has never been written, it can be freed immediately. For short lived files this change allows the same inode to be reused repeatedly. Similarly, when upgrading a fragment to a larger size, if it has never been claimed by an inode on disk, it too can be freed immediately making it available for reuse often in the next slowly growing block of the same file. --- sys/contrib/softupdates/ffs_softdep.c | 26 ++++++++++++++++++-------- 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 870d6acdf714..6773d171a67f 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 870d6acdf714..6773d171a67f 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); } }