[sheepdog] [PATCH] sheep: do not use strbuf for screen_obj_list

Christoph Hellwig hch at infradead.org
Thu May 31 18:09:36 CEST 2012


Any chance to get a review for this one?  The bug fairly reliably
crashes a lot of sheep in recovery operations.

On Thu, May 31, 2012 at 08:50:22AM -0400, Christoph Hellwig wrote:
> "sheep: add a helper function to copy out data from strbuf" added a new
> strbuf_copyout helper that NULL terminates strings copied out of a strbuf.
> 
> For screen_objlist this leads to a off by one in the object list length and
> recovery failures in many test cases.
> 
> Instead of simplify reverting that changes this patch changes screen_obj_list
> to use a more efficienly algorithm for calculating the list of oids to be
> replicated to the local node:
> 
>  - for each candidate OID we do a binary search on rw->oids for the number
>    of elements before this call to screen_obj_list to replace the old call
>    in merge_objlist.
>  - then directly append the new oid to rw->oids and increment rw->count
>  - after we are done processing the object list from one node we do a qsort
>    pass over the oid list to make sure it will be sorted for the next
>    iteration of screen_obj_list.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> 
> diff --git a/sheep/recovery.c b/sheep/recovery.c
> index 433e13b..6b0fda7 100644
> --- a/sheep/recovery.c
> +++ b/sheep/recovery.c
> @@ -15,7 +15,6 @@
>  #include <sys/types.h>
>  
>  #include "sheep_priv.h"
> -#include "strbuf.h"
>  
>  
>  enum rw_state {
> @@ -464,48 +463,30 @@ static int request_obj_list(struct sd_node *e, uint32_t epoch,
>  	return rsp->data_length / sizeof(uint64_t);
>  }
>  
> -int merge_objlist(uint64_t *list1, int nr_list1, uint64_t *list2, int nr_list2)
> +static void screen_obj_list(struct recovery_work *rw,
> +		uint64_t *oids, int nr_oids)
>  {
> -	int i;
> -	int old_nr_list1 = nr_list1;
> -
> -	for (i = 0; i < nr_list2; i++) {
> -		if (bsearch(list2 + i, list1, old_nr_list1, sizeof(*list1), obj_cmp))
> -			continue;
> -
> -		list1[nr_list1++] = list2[i];
> -	}
> -
> -	qsort(list1, nr_list1, sizeof(*list1), obj_cmp);
> -
> -	return nr_list1;
> -}
> -
> -static int screen_obj_list(struct recovery_work *rw,  uint64_t *list, int list_nr)
> -{
> -	int ret, i, j;
> -	struct strbuf buf = STRBUF_INIT;
>  	struct sd_vnode *vnodes[SD_MAX_COPIES];
> +	int old_count = rw->count;
>  	int nr_objs;
> -	size_t len;
> +	int i, j;
>  
>  	nr_objs = get_nr_copies(rw->cur_vnodes);
> -	for (i = 0; i < list_nr; i++) {
> -		oid_to_vnodes(rw->cur_vnodes, list[i], nr_objs, vnodes);
> +	for (i = 0; i < nr_oids; i++) {
> +		oid_to_vnodes(rw->cur_vnodes, oids[i], nr_objs, vnodes);
>  		for (j = 0; j < nr_objs; j++) {
> -			if (vnode_is_local(vnodes[j])) {
> -				strbuf_add(&buf, &list[i], sizeof(uint64_t));
> -				break;
> -			}
> +			if (!vnode_is_local(vnodes[j]))
> +				continue;
> +			if (bsearch(&oids[i], rw->oids, old_count,
> +				    sizeof(uint64_t), obj_cmp))
> +				continue;
> +
> +			rw->oids[rw->count++] = oids[i];
> +			break;
>  		}
>  	}
> -	len = strbuf_copyout(&buf, list, list_nr * sizeof(uint64_t));
>  
> -	ret = len / sizeof(uint64_t);
> -	dprintf("%d\n", ret);
> -	strbuf_release(&buf);
> -
> -	return ret;
> +	qsort(rw->oids, rw->count, sizeof(uint64_t), obj_cmp);
>  }
>  
>  #define MAX_RETRY_CNT  6
> @@ -558,9 +539,7 @@ again:
>  				goto retry;
>  			}
>  		}
> -		buf_nr = screen_obj_list(rw, (uint64_t *)buf, buf_nr);
> -		if (buf_nr)
> -			rw->count = merge_objlist(rw->oids, rw->count, (uint64_t *)buf, buf_nr);
> +		screen_obj_list(rw, (uint64_t *)buf, buf_nr);
>  	}
>  
>  	if (start != 0 && !next_rw) {
> diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
> index f0c26fa..66009ea 100644
> --- a/sheep/sheep_priv.h
> +++ b/sheep/sheep_priv.h
> @@ -302,7 +302,6 @@ int read_object(struct vnode_info *vnodes, uint32_t node_version,
>  		uint64_t offset, int nr);
>  int remove_object(struct vnode_info *vnodes, uint32_t node_version,
>  		  uint64_t oid, int nr);
> -int merge_objlist(uint64_t *list1, int nr_list1, uint64_t *list2, int nr_list2);
>  
>  void del_sheep_fd(int fd);
>  int get_sheep_fd(uint8_t *addr, uint16_t port, int node_idx, uint32_t epoch);
> -- 
> sheepdog mailing list
> sheepdog at lists.wpkg.org
> http://lists.wpkg.org/mailman/listinfo/sheepdog
---end quoted text---



More information about the sheepdog mailing list