From: NeilBrown Date: Mon, 28 Sep 2009 00:16:13 +0000 (+1000) Subject: Handle index blocks becoming empty better. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=ec1227ccfc17b853dfe758694147e453a662640b;p=LaFS.git Handle index blocks becoming empty better. MORE TEXT HERE --- diff --git a/index.c b/index.c index 5104687..7d9ec0d 100644 --- a/index.c +++ b/index.c @@ -1305,6 +1305,7 @@ lafs_leaf_find(struct inode *inode, u32 addr, int adopt, u32 *next, BUG_ON(li->dblock == NULL); BUG_ON(atomic_read(&li->dblock->b.refcnt) == 0); + retry: if (next) *next = 0xFFFFFFFF; @@ -1354,6 +1355,19 @@ lafs_leaf_find(struct inode *inode, u32 addr, int adopt, u32 *next, dprintk("WARN %llu != %llu\n", ib2->b.physaddr, iphys); } + + if (test_bit(B_PhysValid, &ib2->b.flags) && + ib2->b.physaddr == 0) { + /* this block has been invalidated, we must be + * racing with some sort of truncate. + * try again from the top. + * FIXME should wait for something here. + */ + putiref(ib2, REF); + lafs_iounlock_block(&ib->b); + putiref(ib, REF); + goto retry; + } #ifdef FIXME if (!(ib2->b.flags & B_Linked)) { struct block *b2 = peer_find(fs, inode->filesys, diff --git a/modify.c b/modify.c index c4ccdae..2796c25 100644 --- a/modify.c +++ b/modify.c @@ -1790,18 +1790,22 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib) temp_credits = 0; lafs_space_return(fs, uit.credits); - /* If this index block is now empty, we clear - * B_Valid so that it doesn't get written out, - * but rather gets allocated as '0'. + /* If this internal index block is now empty, we either + * invalidate it or merge it with the first dependent block. + * If it is the first index block in it's parent we need to + * adjust the start of parent and possibly other ancestors, + * and incorporate them immediately. */ if (test_bit(B_Valid, &ib->b.flags) && - list_empty(&ib->children)) { - if (ib->depth == 1 && - lafs_leaf_next(ib, ib->b.fileaddr) == 0xFFFFFFFF) - clear_bit(B_Valid, &ib->b.flags); - if (ib->depth > 1 && - lafs_index_empty(ib)) - clear_bit(B_Valid, &ib->b.flags); + list_empty(&ib->children) && + ib->depth > 1 && + lafs_index_empty(ib)) { + struct block *nxt = list_entry(ib->b.siblings.next, + struct block, siblings); + if (ib->b.siblings.next != &ib->b.parent->children && + test_bit(B_PrimaryRef, &nxt->flags)) { + /* */ + } } }