From: NeilBrown Date: Sun, 20 Jun 2010 23:41:51 +0000 (+1000) Subject: SegRef fixes. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=a23d2fb19c49d34a92008fade9bcc3bb7b6d5314;p=LaFS.git SegRef fixes. We mustn't hold a SegRef for blocks which aren't going to be accounted in any segment usage counts. This means we should never hold SegRef on the Root block, and if we decide not to account certain block during unmount - as roll-forward will account them - we should drop SegRef promptly. Signed-off-by: NeilBrown --- diff --git a/block.c b/block.c index b4fcf34..6461747 100644 --- a/block.c +++ b/block.c @@ -401,9 +401,12 @@ lafs_reserve_block(struct block *b, int alloc_type) /* Having reserved the block, we need to get a segref, * which will involve reserving those blocks too. + * However we never get a segref for Root. */ - while (err == 0 && !test_bit(B_SegRef, &b->flags)) + while (err == 0 + && !test_bit(B_Root, &b->flags) + && !test_bit(B_SegRef, &b->flags)) err = lafs_seg_ref_block(b, 0); return err; diff --git a/index.c b/index.c index c6cf20a..f8e50a3 100644 --- a/index.c +++ b/index.c @@ -1951,6 +1951,7 @@ int lafs_allocated_block(struct fs *fs, struct block *blk, u64 phys) LAFS_BUG(i == fs->maxsnapshot, blk); blk->physaddr = phys; /* superblock doesn't get counted in summaries */ + LAFS_BUG(test_bit(B_SegRef, &blk->flags), blk); set_bit(B_PhysValid, &blk->flags); fs->ss[i].root_addr = phys; lai = LAFSI(blk->inode); @@ -1975,6 +1976,8 @@ int lafs_allocated_block(struct fs *fs, struct block *blk, u64 phys) * dirty after the checkpoint. * So just return */ + if (test_and_clear_bit(B_SegRef, &blk->flags)) + lafs_seg_deref(fs, blk->physaddr, 0); blk->physaddr = phys; set_bit(B_PhysValid, &blk->flags); return 0; diff --git a/segments.c b/segments.c index a941d69..4f393e9 100644 --- a/segments.c +++ b/segments.c @@ -245,6 +245,8 @@ void lafs_seg_put_all(struct fs *fs) * find the matching segsum block. If it already * has SegRef, we add the reference and retry from the start. * If it doesn't have SegRef, we prealloc and then tail recurse. + * Note: we never set SegRef on B_Root blocks as their usage + * isn't recorded. */ int lafs_seg_ref_block(struct block *b, int ssnum) { @@ -257,6 +259,9 @@ int lafs_seg_ref_block(struct block *b, int ssnum) getref(b, MKREF(segref)); while (!test_bit(B_SegRef, &b->flags)) { + + BUG_ON(test_bit(B_Root, &b->flags)); + if (b->physaddr == 0) { set_bit(B_SegRef, &b->flags); break;