]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crush/builder: prevent bucket weight underflow on item removal
authorSage Weil <sage@redhat.com>
Sat, 22 Nov 2014 01:47:56 +0000 (17:47 -0800)
committerLoic Dachary <ldachary@redhat.com>
Mon, 15 Dec 2014 09:26:42 +0000 (10:26 +0100)
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 <sage@redhat.com>
(cherry picked from commit 8c87e9502142d5b4a282b94f929ae776a49be1dc)

src/crush/builder.c

index ab0f08626efa403eb2e9bd05c64691b96285ad28..f6c2dad08990981286f064986050f253027b72b3 100644 (file)
@@ -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];