Ejemplo n.º 1
0
Archivo: builder.c Proyecto: CzBiX/ceph
int crush_adjust_tree_bucket_item_weight(struct crush_bucket_tree *bucket, int item, int weight)
{
	int diff;
	int node;
	unsigned i, j;
	unsigned depth = calc_depth(bucket->h.size);

	for (i = 0; i < bucket->h.size; i++) {
		if (bucket->h.items[i] == item)
			break;
	}
	if (i == bucket->h.size)
		return 0;
	
	node = crush_calc_tree_node(i);
	diff = weight - bucket->node_weights[node];
	bucket->node_weights[node] = weight;
	bucket->h.weight += diff;

	for (j=1; j<depth; j++) {
		node = parent(node);
		bucket->node_weights[node] += diff;
	}

	return diff;
}
Ejemplo n.º 2
0
Archivo: builder.c Proyecto: CzBiX/ceph
int crush_add_tree_bucket_item(struct crush_bucket_tree *bucket, int item, int weight)
{
	int newsize = bucket->h.size + 1;
	int depth = calc_depth(newsize);;
	int node;
	int j;
	void *_realloc = NULL;

	bucket->num_nodes = 1 << depth;

	if ((_realloc = realloc(bucket->h.items, sizeof(__s32)*newsize)) == NULL) {
		return -ENOMEM;
	} else {
		bucket->h.items = _realloc;
	}
	if ((_realloc = realloc(bucket->h.perm, sizeof(__u32)*newsize)) == NULL) {
		return -ENOMEM;
	} else {
		bucket->h.perm = _realloc;
	}
	if ((_realloc = realloc(bucket->node_weights, sizeof(__u32)*bucket->num_nodes)) == NULL) {
		return -ENOMEM;
	} else {
		bucket->node_weights = _realloc;
	}
	
	node = crush_calc_tree_node(newsize-1);
	bucket->node_weights[node] = weight;

	/* if the depth increase, we need to initialize the new root node's weight before add bucket item */
	int root = bucket->num_nodes/2;
	if (depth >= 2 && (node - 1) == root) {
		/* if the new item is the first node in right sub tree, so
		* the root node initial weight is left sub tree's weight
		*/
		bucket->node_weights[root] = bucket->node_weights[root/2];
	}

	for (j=1; j<depth; j++) {
		node = parent(node);

                if (crush_addition_is_unsafe(bucket->node_weights[node], weight))
                        return -ERANGE;

		bucket->node_weights[node] += weight;
                dprintk(" node %d weight %d\n", node, bucket->node_weights[node]);
	}


	if (crush_addition_is_unsafe(bucket->h.weight, weight))
                return -ERANGE;
	
	bucket->h.items[newsize-1] = item;
        bucket->h.weight += weight;
        bucket->h.size++;

	return 0;
}
Ejemplo n.º 3
0
/**
 * crush_get_bucket_item_weight - Get weight of an item in given bucket
 * @param b bucket pointer
 * @param p item index in bucket
 */
int crush_get_bucket_item_weight(const struct crush_bucket *b, int p)
{
	if ((__u32)p >= b->size)
		return 0;

	switch (b->alg) {
	case CRUSH_BUCKET_UNIFORM:
		return ((struct crush_bucket_uniform *)b)->item_weight;
	case CRUSH_BUCKET_LIST:
		return ((struct crush_bucket_list *)b)->item_weights[p];
	case CRUSH_BUCKET_TREE:
		return ((struct crush_bucket_tree *)b)->node_weights[crush_calc_tree_node(p)];
	case CRUSH_BUCKET_STRAW:
		return ((struct crush_bucket_straw *)b)->item_weights[p];
	}
	return 0;
}
Ejemplo n.º 4
0
Archivo: builder.c Proyecto: CzBiX/ceph
static int crush_reweight_tree_bucket(struct crush_map *crush, struct crush_bucket_tree *bucket)
{
	unsigned i;

	bucket->h.weight = 0;
	for (i = 0; i < bucket->h.size; i++) {
		int node = crush_calc_tree_node(i);
		int id = bucket->h.items[i];
		if (id < 0) {
			struct crush_bucket *c = crush->buckets[-1-id];
			crush_reweight_bucket(crush, c);
			bucket->node_weights[node] = c->weight;
		}

		if (crush_addition_is_unsafe(bucket->h.weight, bucket->node_weights[node]))
                        return -ERANGE;

		bucket->h.weight += bucket->node_weights[node];


	}

	return 0;
}
Ejemplo n.º 5
0
Archivo: builder.c Proyecto: CzBiX/ceph
int crush_remove_tree_bucket_item(struct crush_bucket_tree *bucket, int item)
{
	unsigned i;
	unsigned newsize;

	for (i = 0; i < bucket->h.size; i++) {
		int node;
		int weight;
		int j;
		int depth = calc_depth(bucket->h.size);

		if (bucket->h.items[i] != item)
			continue;
		
		node = crush_calc_tree_node(i);
		weight = bucket->node_weights[node];
		bucket->node_weights[node] = 0;

		for (j = 1; j < depth; j++) {
			node = parent(node);
			bucket->node_weights[node] -= weight;
			dprintk(" node %d weight %d\n", node, bucket->node_weights[node]);
		}
		bucket->h.weight -= weight;
		break;
	}
	if (i == bucket->h.size)
		return -ENOENT;

	newsize = bucket->h.size;
	while (newsize > 0) {
		int node = crush_calc_tree_node(newsize - 1);
		if (bucket->node_weights[node])
			break;
		--newsize;
	}

	if (newsize != bucket->h.size) {
		int olddepth, newdepth;

		void *_realloc = NULL;

		if ((_realloc = realloc(bucket->h.items, sizeof(__s32)*newsize)) == NULL) {
			return -ENOMEM;
		} else {
			bucket->h.items = _realloc;
		}
		if ((_realloc = realloc(bucket->h.perm, sizeof(__u32)*newsize)) == NULL) {
			return -ENOMEM;
		} else {
			bucket->h.perm = _realloc;
		}

		olddepth = calc_depth(bucket->h.size);
		newdepth = calc_depth(newsize);
		if (olddepth != newdepth) {
			bucket->num_nodes = 1 << newdepth;
			if ((_realloc = realloc(bucket->node_weights, 
						sizeof(__u32)*bucket->num_nodes)) == NULL) {
				return -ENOMEM;
			} else {
				bucket->node_weights = _realloc;
			}
		}

		bucket->h.size = newsize;
	}
	return 0;
}
Ejemplo n.º 6
0
Archivo: builder.c Proyecto: CzBiX/ceph
struct crush_bucket_tree*
crush_make_tree_bucket(int hash, int type, int size,
		       int *items,    /* in leaf order */
		       int *weights)
{
	struct crush_bucket_tree *bucket;
	int depth;
	int node;
	int i, j;

	bucket = malloc(sizeof(*bucket));
        if (!bucket)
                return NULL;
	memset(bucket, 0, sizeof(*bucket));
	bucket->h.alg = CRUSH_BUCKET_TREE;
	bucket->h.hash = hash;
	bucket->h.type = type;
	bucket->h.size = size;

	if (size == 0) {
		bucket->h.items = NULL;
		bucket->h.perm = NULL;
		bucket->h.weight = 0;
		bucket->node_weights = NULL;
		bucket->num_nodes = 0;
		/* printf("size 0 depth 0 nodes 0\n"); */
		return bucket;
	}

	bucket->h.items = malloc(sizeof(__s32)*size);
        if (!bucket->h.items)
                goto err;
	bucket->h.perm = malloc(sizeof(__u32)*size);
        if (!bucket->h.perm)
                goto err;

	/* calc tree depth */
	depth = calc_depth(size);
	bucket->num_nodes = 1 << depth;
	dprintk("size %d depth %d nodes %d\n", size, depth, bucket->num_nodes);

        bucket->node_weights = malloc(sizeof(__u32)*bucket->num_nodes);
        if (!bucket->node_weights)
                goto err;

	memset(bucket->h.items, 0, sizeof(__s32)*bucket->h.size);
	memset(bucket->node_weights, 0, sizeof(__u32)*bucket->num_nodes);

	for (i=0; i<size; i++) {
		bucket->h.items[i] = items[i];
		node = crush_calc_tree_node(i);
		dprintk("item %d node %d weight %d\n", i, node, weights[i]);
		bucket->node_weights[node] = weights[i];

		if (crush_addition_is_unsafe(bucket->h.weight, weights[i]))
                        goto err;

		bucket->h.weight += weights[i];
		for (j=1; j<depth; j++) {
			node = parent(node);

                        if (crush_addition_is_unsafe(bucket->node_weights[node], weights[i]))
                                goto err;

			bucket->node_weights[node] += weights[i];
			dprintk(" node %d weight %d\n", node, bucket->node_weights[node]);
		}
	}
	BUG_ON(bucket->node_weights[bucket->num_nodes/2] != bucket->h.weight);

	return bucket;
err:
        free(bucket->node_weights);
        free(bucket->h.perm);
        free(bucket->h.items);
        free(bucket);
        return NULL;
}