[sheepdog] [PATCH 2/6] object cache: fix add_to_object_cache()
Liu Yuan
namei.unix at gmail.com
Wed Aug 1 12:03:46 CEST 2012
From: Liu Yuan <tailai.ly at taobao.com>
add_to_object_cache() and add_to_dirty_tree_and_list() should be operating
atomically, otherwise following race will happen:
thread 1 thread 2
create A on object cache
add_to_object_cache(A)
do_reclaim_object(A)
remove_cache_object(A)
add_to_dirty_tree_and_list(A) <--- panic!
Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
sheep/object_cache.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/sheep/object_cache.c b/sheep/object_cache.c
index 1ebe896..e986bed 100644
--- a/sheep/object_cache.c
+++ b/sheep/object_cache.c
@@ -495,7 +495,7 @@ dirty_tree_and_list_insert(struct object_cache *oc, uint32_t idx,
entry = object_tree_search(&oc->object_tree, idx);
if (!entry)
- return NULL;
+ panic("Can not find object entry %" PRIx32 "\n", idx);
entry->bmap |= bmap;
if (create)
@@ -566,8 +566,6 @@ add_to_dirty_tree_and_list(struct object_cache *oc, uint32_t idx,
{
struct object_cache_entry *entry;
entry = dirty_tree_and_list_insert(oc, idx, bmap, create);
- if (!entry)
- panic("Can not find object entry %" PRIx32 "\n", idx);
if (cache_in_reclaim(0))
return;
@@ -606,7 +604,8 @@ void object_cache_try_to_reclaim(void)
queue_work(sys->reclaim_wqueue, work);
}
-static void add_to_object_cache(struct object_cache *oc, uint32_t idx)
+static void add_to_object_cache(struct object_cache *oc, uint32_t idx,
+ int create)
{
struct object_cache_entry *entry, *old;
uint32_t data_length;
@@ -633,6 +632,10 @@ static void add_to_object_cache(struct object_cache *oc, uint32_t idx)
free(entry);
entry = old;
}
+ if (create) {
+ uint64_t all = UINT64_MAX;
+ add_to_dirty_tree_and_list(oc, idx, all, create);
+ }
pthread_rwlock_unlock(&oc->lock);
object_cache_try_to_reclaim();
@@ -673,15 +676,8 @@ static int object_cache_lookup(struct object_cache *oc, uint32_t idx,
ret = prealloc(fd, data_length);
if (ret != SD_RES_SUCCESS)
ret = SD_RES_EIO;
- else {
- uint64_t bmap = UINT64_MAX;
-
- add_to_object_cache(oc, idx);
-
- pthread_rwlock_wrlock(&oc->lock);
- add_to_dirty_tree_and_list(oc, idx, bmap, 1);
- pthread_rwlock_unlock(&oc->lock);
- }
+ else
+ add_to_object_cache(oc, idx, 1);
close(fd);
out:
strbuf_release(&buf);
@@ -769,7 +765,7 @@ static int object_cache_pull(struct object_cache *oc, uint32_t idx)
dprintf("oid %"PRIx64" pulled successfully\n", oid);
ret = create_cache_object(oc, idx, buf, data_length);
if (ret == SD_RES_SUCCESS)
- add_to_object_cache(oc, idx);
+ add_to_object_cache(oc, idx, 0);
}
free(buf);
out:
@@ -798,7 +794,7 @@ static int object_cache_push(struct object_cache *oc)
del_from_dirty_tree_and_list(entry, &oc->dirty_tree);
}
push_failed:
- pthread_rwlock_wrlock(&oc->lock);
+ pthread_rwlock_unlock(&oc->lock);
return ret;
}
@@ -1139,7 +1135,7 @@ static int load_existing_cache_object(struct object_cache *cache)
if (idx == ULLONG_MAX)
continue;
- add_to_object_cache(cache, idx);
+ add_to_object_cache(cache, idx, 0);
dprintf("load cache %06" PRIx32 "/%08" PRIx32 "\n",
cache->vid, idx);
}
--
1.7.10.2
More information about the sheepdog
mailing list