From c3290771a07ca743d28ac0935aac79eaa2b7e377 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 7 Apr 2021 14:34:05 -0700 Subject: [PATCH] Block cache use rht _lookup_ insert for EEXIST The sneaky rhashtable_insert_fast() can't return -EEXIST despite the last line of the function *REALLY* making it look like it can. It just inserts new objects at the head of the bucket lists without comparing the insertion with existing objects. The block cache was relying on insertion to resolve duplicate racing allocated blocks. Because it couldn't return -EEXIST we could get duplicate cached blocks present in the hash table. rhashtable_lookup_insert_fast() fixes this by actually comparing the inserted objects key with the objects found in the insertion bucket. A racing allocator trying to insert a duplicate cached block will get an error, drop their allocated block, and retry their lookup. Signed-off-by: Zach Brown --- kmod/src/block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmod/src/block.c b/kmod/src/block.c index ef6a1cb3..bb581173 100644 --- a/kmod/src/block.c +++ b/kmod/src/block.c @@ -288,7 +288,7 @@ static int block_insert(struct super_block *sb, struct block_private *bp) retry: atomic_add(BLOCK_REF_INSERTED, &bp->refcount); - ret = rhashtable_insert_fast(&binf->ht, &bp->ht_head, block_ht_params); + ret = rhashtable_lookup_insert_fast(&binf->ht, &bp->ht_head, block_ht_params); if (ret < 0) { atomic_sub(BLOCK_REF_INSERTED, &bp->refcount); if (ret == -EBUSY) {