summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/contrib/softupdates/ffs_softdep.c26
-rw-r--r--sys/ufs/ffs/ffs_softdep.c26
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);
}
}
OpenPOWER on IntegriCloud