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.
This commit is contained in:
Kirk McKusick 2000-06-18 22:05:57 +00:00
parent ce5163041d
commit d3abb52714
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=61812
2 changed files with 36 additions and 16 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}