From: NeilBrown Date: Sat, 26 Jun 2010 03:26:37 +0000 (+1000) Subject: Pin SegmentMap block when they might need to be dirtied. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=81618ee992e9ca11f91428afb4b0c029e2e9b3f2;p=LaFS.git Pin SegmentMap block when they might need to be dirtied. This is more in-keeping with other practices and not that SegmentMap blocks are handles carefully by the cleaner and checkpoint, it is safe to do this. They stay pinned until they are no-longer referenced. This may keep some Credits unavailable but that is not a big cost. When we pin these we don't hold or need a phase lock, so don't require it. Now that we alway pin segments when first used (free_get) we don't need to prealloc in lafs_seg_move. Signed-off-by: NeilBrown --- diff --git a/block.c b/block.c index 7ea8f3a..22a6613 100644 --- a/block.c +++ b/block.c @@ -462,9 +462,15 @@ lafs_pin_dblock(struct datablock *b, int alloc_type) } else blk = getref(&b->b, MKREF(pindb)); - LAFS_BUG(!test_phase_locked(fs), &b->b); - lafs_phase_wait(blk); + if (LAFSI(b->b.inode)->type != TypeSegmentMap) { + /* FIXME test is a hack until we get a better + * phase wait. TypeSegmentMap does it's own + * dirty management so doesn't need this. + */ + LAFS_BUG(!test_phase_locked(fs), &b->b); + lafs_phase_wait(blk); + } set_bit(B_PinPending, &b->b.flags); err = lafs_reserve_block(blk, alloc_type); diff --git a/index.c b/index.c index 5884e79..283291e 100644 --- a/index.c +++ b/index.c @@ -399,7 +399,8 @@ void lafs_pin_block_ph(struct block *b, int ph) struct inode *ino; LAFS_BUG(b->parent == NULL && !test_bit(B_Root, &b->flags), b); - if (!test_bit(B_Realloc, &b->flags)) + if (!test_bit(B_Realloc, &b->flags) && + LAFSI(b->inode)->type != TypeSegmentMap) LAFS_BUG(!test_phase_locked(fs), b); ino = b->inode; @@ -818,6 +819,12 @@ void lafs_refile(struct block *b, int dec) */ onlru = 1; + /* PinPending disappears with the last non-lru reference, + * (or possibly at other times). + */ + if (atomic_read(&b->refcnt) == dec + onlru) + clear_bit(B_PinPending, &b->flags); + ph = !!test_bit(B_Phase1, &b->flags); /* See if we still need to be pinned */ /* FIXME need some locking here ... */ diff --git a/segments.c b/segments.c index 66d9faa..c8f2194 100644 --- a/segments.c +++ b/segments.c @@ -313,7 +313,7 @@ int lafs_seg_ref_block(struct block *b, int ssnum) continue; } - err = lafs_prealloc(&ss->ssblk->b, AccountSpace); + err = lafs_pin_dblock(ss->ssblk, AccountSpace); if (err) { ss_put(ss, fs); putref(b, MKREF(segref)); @@ -376,10 +376,6 @@ void lafs_seg_move(struct fs *fs, u64 oldaddr, u64 newaddr, ss = segsum_byaddr(fs, newaddr, ssnum); seg_inc(fs, ss, 1, fs->qphase == phase); - /* FIXME this doesn't belong here, does it ?*/ - lafs_checkpoint_lock(fs); - (void)lafs_reserve_block(&ss->ssblk->b, AccountSpace); - lafs_checkpoint_unlock(fs); if (!moveref) ss_put(ss, fs); } @@ -1108,9 +1104,9 @@ again: * to the two blocks !! */ LAFS_BUG(1, &db->b); lafs_checkpoint_lock(fs); - (void)lafs_reserve_block(&ssum->ssblk->b, AccountSpace); + (void)lafs_pin_dblock(ssum->ssblk, AccountSpace); if (ssnum == 0) - (void)lafs_reserve_block(&ssum->youthblk->b, AccountSpace); + (void)lafs_pin_dblock(ssum->youthblk, AccountSpace); lafs_checkpoint_unlock(fs); /* These aren't in the table any more - the segsum holds * the necessary reference */ @@ -1133,8 +1129,10 @@ again: - 1), NULL, GFP_KERNEL, MKREF(youth)); - // FIXME we need to hold a ref on all youth blocks for - // known free segments.... + /* As we hold a ref on youth block for anything in the + * table, and that block was loaded at the time, it must + * still be valid. + */ BUG_ON(!test_bit(B_Valid, &db->b.flags)); goto again; }