From: Sage Weil Date: Sat, 22 Nov 2014 01:47:56 +0000 (-0800) Subject: crush/builder: prevent bucket weight underflow on item removal X-Git-Tag: v0.80.8~7^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cee51af9c1dbde550177c95caf6c93f612442300;p=ceph.git crush/builder: prevent bucket weight underflow on item removal It is possible to set a bucket weight that is not the sum of the item weights if you manually modify/build the CRUSH map. Protect against any underflow on the bucket weight when removing items. Signed-off-by: Sage Weil (cherry picked from commit 8c87e9502142d5b4a282b94f929ae776a49be1dc) --- diff --git a/src/crush/builder.c b/src/crush/builder.c index ab0f08626ef..f6c2dad0899 100644 --- a/src/crush/builder.c +++ b/src/crush/builder.c @@ -746,7 +746,10 @@ int crush_remove_uniform_bucket_item(struct crush_bucket_uniform *bucket, int it for (j = i; j < bucket->h.size; j++) bucket->h.items[j] = bucket->h.items[j+1]; newsize = --bucket->h.size; - bucket->h.weight -= bucket->item_weight; + if (bucket->item_weight < bucket->h.weight) + bucket->h.weight -= bucket->item_weight; + else + bucket->h.weight = 0; if ((_realloc = realloc(bucket->h.items, sizeof(__s32)*newsize)) == NULL) { return -ENOMEM; @@ -779,7 +782,10 @@ int crush_remove_list_bucket_item(struct crush_bucket_list *bucket, int item) bucket->item_weights[j] = bucket->item_weights[j+1]; bucket->sum_weights[j] = bucket->sum_weights[j+1] - weight; } - bucket->h.weight -= weight; + if (weight < bucket->h.weight) + bucket->h.weight -= weight; + else + bucket->h.weight = 0; newsize = --bucket->h.size; void *_realloc = NULL; @@ -830,7 +836,10 @@ int crush_remove_tree_bucket_item(struct crush_bucket_tree *bucket, int item) bucket->node_weights[node] -= weight; printf(" node %d weight %d\n", node, bucket->node_weights[node]); } - bucket->h.weight -= weight; + if (weight < bucket->h.weight) + bucket->h.weight -= weight; + else + bucket->h.weight = 0; break; } if (i == bucket->h.size) @@ -885,7 +894,10 @@ int crush_remove_straw_bucket_item(struct crush_bucket_straw *bucket, int item) for (i = 0; i < bucket->h.size; i++) { if (bucket->h.items[i] == item) { bucket->h.size--; - bucket->h.weight -= bucket->item_weights[i]; + 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];