From 74c46c4407615bb8f4845af67e1bdf5c5b1b4bb3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 13 Jun 2010 17:16:30 +1000 Subject: [PATCH] unhash iblock when it becomes empty. Our handling of empty iblocks was flawed - when they become empty they stayed in the hash table and could be found again - bad. So unhash them. To keep things tidy, always use hlist_del_init to removing things from the hash table, and assert that they are present before removing, and that they aren't before adding. Signed-off-by: NeilBrown --- index.c | 16 ++++++++++++++-- lafs.h | 1 + modify.c | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/index.c b/index.c index d866af5..1eb1ff1 100644 --- a/index.c +++ b/index.c @@ -82,7 +82,7 @@ static int lafs_shrinker(int nr_to_scan, /*gfp_t*/unsigned int gfp_mask) */ LAFS_BUG(test_bit(B_Pinned, &ib->b.flags), &ib->b); if (!hlist_unhashed(&ib->hash)) - hlist_del(&ib->hash); + hlist_del_init(&ib->hash); /* delete from inode->free_index */ list_del_init(&ib->b.siblings); list_move(&ib->b.lru, &togo); @@ -123,7 +123,7 @@ void lafs_release_index(struct list_head *head) list_del_init(&ib->b.siblings); LAFS_BUG(!test_bit(B_OnFree, &ib->b.flags), &ib->b); if (!hlist_unhashed(&ib->hash)) - hlist_del(&ib->hash); + hlist_del_init(&ib->hash); list_move(&ib->b.lru, &togo); freelist.freecnt--; } @@ -305,10 +305,22 @@ void lafs_hash_iblock(struct indexblock *ib) struct hlist_head *head = &hash_table[ihash(ib->b.inode, ib->b.fileaddr, ib->depth)]; spin_lock(&lafs_hash_lock); + LAFS_BUG(!hlist_unhashed(&ib->hash), &ib->b); hlist_add_head(&ib->hash, head); spin_unlock(&lafs_hash_lock); } +void lafs_unhash_iblock(struct indexblock *ib) +{ + /* This block has been emptied and deleted and is no longer + * wanted in the hash tables + */ + spin_lock(&lafs_hash_lock); + LAFS_BUG(hlist_unhashed(&ib->hash), &ib->b); + hlist_del_init(&ib->hash); + spin_unlock(&lafs_hash_lock); +} + /* adopt blk into parent if possible. */ static void diff --git a/lafs.h b/lafs.h index bfd0fa5..580025d 100644 --- a/lafs.h +++ b/lafs.h @@ -527,6 +527,7 @@ struct indexblock *lafs_iblock_alloc(struct fs *fs, int gfp, int with_buffer, REFARG); void lafs_iblock_free(struct indexblock *ib); void lafs_hash_iblock(struct indexblock *ib); +void lafs_unhash_iblock(struct indexblock *ib); void lafs_summary_update(struct fs *fs, struct inode *ino, u64 oldphys, u64 newphys, int is_index, int phase, diff --git a/modify.c b/modify.c index a6ef2e7..a1dd25b 100644 --- a/modify.c +++ b/modify.c @@ -1664,6 +1664,7 @@ static void readdress_index(struct inode *ino, u32 addr, int depth, if (ib) { lafs_iolock_block(&ib->b); ib->b.fileaddr = newaddr; + lafs_unhash_iblock(ib); lafs_hash_iblock(ib); lafs_iounlock_block(&ib->b); putiref(ib, MKREF(readdr)); @@ -1987,6 +1988,7 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib) nxt = NULL; if (ib->b.siblings.next != &ib->b.parent->children) nxt = list_entry(ib->b.siblings.next, struct indexblock, b.siblings); + lafs_unhash_iblock(ib); if (test_and_clear_bit(B_PrimaryRef, &ib->b.flags)) { int cr = 0; /* This was not incorporated yet, revert the uninc status */ -- 2.39.5