From: NeilBrown Date: Mon, 9 Aug 2010 10:24:20 +0000 (+1000) Subject: Unpin data blocks from previous phase before allowing them to be dirty. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=c0b5878edf59956cb3995436d860da4d365c525e;p=LaFS.git Unpin data blocks from previous phase before allowing them to be dirty. While checkpointing will unpin PinPending blocks, it might not manage to do it before the block gets Dirtied again. So before we Pin the block - which is a required precursor to dirtying them, unpin the block. Signed-off-by: NeilBrown --- diff --git a/block.c b/block.c index d64f25f..2070499 100644 --- a/block.c +++ b/block.c @@ -465,6 +465,18 @@ lafs_pin_dblock(struct datablock *b, int alloc_type) if (LAFSI(b->b.inode)->type != TypeSegmentMap) { LAFS_BUG(!test_phase_locked(fs), &b->b); lafs_iolock_written(&b->b); + /* If this block is already pinned in the previous + * phase, now it a good time to flip it - we know it has + * been written and we want to flip it before it + * can be dirtied. + */ + if (blk == &b->b && + test_bit(B_Pinned, &b->b.flags) && + !!test_bit(B_Phase1, &b->b.flags) != fs->phase) { + clear_bit(B_PinPending, &b->b.flags); + lafs_refile(&b->b, 0); + set_bit(B_PinPending, &b->b.flags); + } lafs_iounlock_block(&b->b); } diff --git a/checkpoint.c b/checkpoint.c index 4ab6b2c..36072bd 100644 --- a/checkpoint.c +++ b/checkpoint.c @@ -383,9 +383,9 @@ again: * de-async them. */ - LAFS_BUG(!!test_bit(B_Phase1, &b->flags) != oldphase, b); - - if (test_bit(B_PinPending, &b->flags) && + if (!!test_bit(B_Phase1, &b->flags) != oldphase) + /* lafs_pin_dblock flipped phase for us */; + else if (test_bit(B_PinPending, &b->flags) && !test_bit(B_Index, &b->flags) && (LAFSI(b->inode)->type == TypeSegmentMap || LAFSI(b->inode)->type == TypeQuota)) {