int crush_add_straw_bucket_item(struct crush_map *map, struct crush_bucket_straw *bucket, int item, int weight) { int newsize = bucket->h.size + 1; void *_realloc = NULL; if ((_realloc = realloc(bucket->h.items, sizeof(__s32)*newsize)) == NULL) { return -ENOMEM; } else { bucket->h.items = _realloc; } if ((_realloc = realloc(bucket->item_weights, sizeof(__u32)*newsize)) == NULL) { return -ENOMEM; } else { bucket->item_weights = _realloc; } if ((_realloc = realloc(bucket->straws, sizeof(__u32)*newsize)) == NULL) { return -ENOMEM; } else { bucket->straws = _realloc; } bucket->h.items[newsize-1] = item; bucket->item_weights[newsize-1] = weight; if (crush_addition_is_unsafe(bucket->h.weight, weight)) return -ERANGE; bucket->h.weight += weight; bucket->h.size++; return crush_calc_straw(map, bucket); }
struct crush_bucket_straw * crush_make_straw_bucket(struct crush_map *map, int hash, int type, int size, int *items, int *weights) { struct crush_bucket_straw *bucket; int i; bucket = malloc(sizeof(*bucket)); if (!bucket) return NULL; memset(bucket, 0, sizeof(*bucket)); bucket->h.alg = CRUSH_BUCKET_STRAW; bucket->h.hash = hash; bucket->h.type = type; bucket->h.size = size; 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; bucket->item_weights = malloc(sizeof(__u32)*size); if (!bucket->item_weights) goto err; bucket->straws = malloc(sizeof(__u32)*size); if (!bucket->straws) goto err; bucket->h.weight = 0; for (i=0; i<size; i++) { bucket->h.items[i] = items[i]; bucket->h.weight += weights[i]; bucket->item_weights[i] = weights[i]; } if (crush_calc_straw(map, bucket) < 0) goto err; return bucket; err: free(bucket->straws); free(bucket->item_weights); free(bucket->h.perm); free(bucket->h.items); free(bucket); return NULL; }
int crush_remove_straw_bucket_item(struct crush_map *map, struct crush_bucket_straw *bucket, int item) { int newsize = bucket->h.size - 1; unsigned i, j; for (i = 0; i < bucket->h.size; i++) { if (bucket->h.items[i] == item) { bucket->h.size--; if (bucket->item_weights[i] < bucket->h.weight) bucket->h.weight -= bucket->item_weights[i]; else bucket->h.weight = 0; for (j = i; j < bucket->h.size; j++) { bucket->h.items[j] = bucket->h.items[j+1]; bucket->item_weights[j] = bucket->item_weights[j+1]; } break; } } if (i == bucket->h.size) return -ENOENT; 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; } if ((_realloc = realloc(bucket->item_weights, sizeof(__u32)*newsize)) == NULL) { return -ENOMEM; } else { bucket->item_weights = _realloc; } if ((_realloc = realloc(bucket->straws, sizeof(__u32)*newsize)) == NULL) { return -ENOMEM; } else { bucket->straws = _realloc; } return crush_calc_straw(map, bucket); }
int crush_adjust_straw_bucket_item_weight(struct crush_bucket_straw *bucket, int item, int weight) { unsigned idx; int diff; int r; for (idx = 0; idx < bucket->h.size; idx++) if (bucket->h.items[idx] == item) break; if (idx == bucket->h.size) return 0; diff = weight - bucket->item_weights[idx]; bucket->item_weights[idx] = weight; bucket->h.weight += diff; r = crush_calc_straw(bucket); if (r < 0) return r; return diff; }
static int crush_reweight_straw_bucket(struct crush_map *crush, struct crush_bucket_straw *bucket) { unsigned i; bucket->h.weight = 0; for (i = 0; i < bucket->h.size; i++) { int id = bucket->h.items[i]; if (id < 0) { struct crush_bucket *c = crush->buckets[-1-id]; crush_reweight_bucket(crush, c); bucket->item_weights[i] = c->weight; } if (crush_addition_is_unsafe(bucket->h.weight, bucket->item_weights[i])) return -ERANGE; bucket->h.weight += bucket->item_weights[i]; } crush_calc_straw(crush, bucket); return 0; }