From e08aa27380bab6dd3f22b2b36dcf728366794d43 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 15 Sep 2010 14:57:02 +1000 Subject: [PATCH] lafs_refile: factor out check for unpinnable data blocks. Data blocks can be unpinned while refcounts are still present. Factor that case out into a stand-alone test. We still test for datablocks being unpinnable in the 'refcnt==0' case as PinPending might have only just been cleared. This leaves a large bulk of tests all of which depend on refcnt reaching zero which can be improved in a subsequent patch. Signed-off-by: NeilBrown --- index.c | 34 ++++++++++++++++++++++++++++++++-- lafs.h | 1 + 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/index.c b/index.c index ec8fa9d..ebef167 100644 --- a/index.c +++ b/index.c @@ -876,6 +876,7 @@ void lafs_refile(struct block *b, int dec) if (!b) return; + fs = fs_from_inode(b->inode); check_consistency(b); /* To (mostly) avoid recursion, we have a loop which may @@ -892,6 +893,36 @@ void lafs_refile(struct block *b, int dec) set_lru(b); + if (test_bit(B_Pinned, &b->flags) && + !test_bit(B_Index, &b->flags) && + !test_bit(B_PinPending, &b->flags) && + !test_bit(B_Dirty, &b->flags) && + !test_bit(B_Realloc, &b->flags) + ) { + /* Don't need to be Pinned any more */ + /* FIXME do I need to lock access to ->parent */ + lafs_checkpoint_lock(fs); + ph = !!test_bit(B_Phase1, &b->flags); + if (test_and_clear_bit(B_Pinned, &b->flags)) { + if (test_bit(B_Dirty, &b->flags) || + test_bit(B_Realloc, &b->flags) || + test_bit(B_PinPending, &b->flags)) + /* lost a race */ + set_phase(b, ph); + else if (!test_bit(B_Root, &b->flags)) { + struct block *nb; + atomic_dec(&b->parent->pincnt[ph]); + nb = &b->parent->b; + if (next_parent != nb) { + LAFS_BUG(next_parent, b); + next_parent = nb; + atomic_inc(&nb->refcnt); + } + } + } + lafs_checkpoint_unlock(fs); + } + spin_lock(&lafs_hash_lock); /* PinPending disappears with the last non-lru reference, @@ -901,18 +932,17 @@ void lafs_refile(struct block *b, int dec) clear_bit(B_PinPending, &b->flags); ph = !!test_bit(B_Phase1, &b->flags); - fs = fs_from_inode(b->inode); /* See if we still need to be pinned */ /* FIXME need some locking here ... */ if (test_bit(B_Pinned, &b->flags) && !test_bit(B_PinPending, &b->flags) && !test_bit(B_Dirty, &b->flags) && !test_bit(B_Realloc, &b->flags) && + atomic_read(&b->refcnt) == dec && (!test_bit(B_Index, &b->flags) || (iblk(b)->uninc_table.pending_cnt == 0 && iblk(b)->uninc == NULL && iblk(b)->uninc_next == NULL && - atomic_read(&b->refcnt) == dec && atomic_read(&iblk(b)->pincnt[0]) == 0 && atomic_read(&iblk(b)->pincnt[1]) == 0)) ) { diff --git a/lafs.h b/lafs.h index 082d67b..c1a0e9a 100644 --- a/lafs.h +++ b/lafs.h @@ -365,6 +365,7 @@ static inline int set_phase(struct block *b, int ph) else clear_bit(B_Phase1, &b->flags); + /* FIXME do I need to lock access to ->parent */ if (!test_and_set_bit(B_Pinned, &b->flags) && b->parent) { atomic_inc(&b->parent->pincnt[ph]); -- 2.39.5