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

Ing. Luca Lazzeroni - Trend Servizi Srl luca at gvnet.it
Fri Jul 26 15:41:28 CEST 2013


Il 24/07/2013 12:46, Hitoshi Mitake ha scritto:
> 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:

Hi Hitoshi,
I've tried to apply the patch as you suggested, but it isn't applyable 
to sheepdog-stable since:

object_cache.c:888:1: error: ‘struct object_cache’ has no member named 
‘dirty_count’

Maybe code needs some refactor for succesfuly back-port it to 0.6-stable..

Thank you,


> 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;




More information about the sheepdog mailing list