[sheepdog] [PATCH] sheep: implement a correct detection of object cache pushing completion

Hitoshi Mitake mitake.hitoshi at lab.ntt.co.jp
Wed Jul 24 12:46:33 CEST 2013


Current implementation for pushing object cache would have a bug. In
object_cache_push(), the variable oc->push_count is incremented in the
loop of queuing work. This can produce a non deterministic bug when
a sequence of scheduling like below happens:

1. object_cache_push() creates a work and queue it to
   sys->oc_push_wqueue (oc->push_count == 1)
2. Before queuing next work, a worker thread of oc_push_wqueue wakes
   up and pushes the object
3. After completion of pushing, the worker thread decrements
   oc->push_count atomically. The thread calls eventfd_write() because
   oc->push_count is 0.
4. The thread which calls object_cache_push() detects an invalid
   completion after its queuing iteration.

This sequence can produce an invalid early finish of flush request
from VMs, especially when a number of cached object is large.

Cc: Luca Lazzeroni <luca at gvnet.it>
Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
 sheep/object_cache.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sheep/object_cache.c b/sheep/object_cache.c
index 1bd2a59..27d544d 100644
--- a/sheep/object_cache.c
+++ b/sheep/object_cache.c
@@ -932,11 +932,12 @@ static int object_cache_push(struct object_cache *oc)
 		unlock_cache(oc);
 		return SD_RES_SUCCESS;
 	}
+
+	uatomic_set(&oc->push_count, uatomic_read(&oc->dirty_count));
 	list_for_each_entry_safe(entry, t, &oc->dirty_head, dirty_list) {
 		struct push_work *pw;
 
 		get_cache_entry(entry);
-		uatomic_inc(&oc->push_count);
 		pw = xzalloc(sizeof(struct push_work));
 		pw->work.fn = do_push_object;
 		pw->work.done = push_object_done;
-- 
1.7.10.4




More information about the sheepdog mailing list