]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crush/mapper: fix divide-by-0 in straw2
authorSage Weil <sage@redhat.com>
Thu, 9 Apr 2015 21:42:34 +0000 (14:42 -0700)
committerSage Weil <sage@redhat.com>
Fri, 10 Apr 2015 00:30:20 +0000 (17:30 -0700)
If the item weight is 0 we don't want to divide; instead draw a minimal
value.

Fixes: #11357
Reported-by: Yann Dupont <yd@objoo.org>
Tested-by: Yann Dupont <yd@objoo.org>
Signed-off-by: Sage Weil <sage@redhat.com>
(cherry picked from commit 64d1e900ec4f5831972ec80e8d0129604669f5bb)

src/crush/mapper.c

index b2e0bfd9266fedfea3297d9a4bd77860b0186037..251ab4af1f8a3e17f85d1751e20faf2477d90a27 100644 (file)
@@ -307,28 +307,38 @@ static int bucket_straw2_choose(struct crush_bucket_straw2 *bucket,
 {
        unsigned i, high = 0;
        unsigned u;
+       unsigned w;
        __s64 ln, draw, high_draw = 0;
 
        for (i = 0; i < bucket->h.size; i++) {
-               u = crush_hash32_3(bucket->h.hash, x, bucket->h.items[i], r);
-               u &= 0xffff;
-
-               /*
-                * for some reason slightly less than 0x10000 produces
-                * a slightly more accurate distribution... probably a
-                * rounding effect.
-                *
-                * the natural log lookup table maps [0,0xffff]
-                * (corresponding to real numbers [1/0x10000, 1] to
-                * [0, 0xffffffffffff] (corresponding to real numbers
-                * [-11.090355,0]).
-                */
-               ln = crush_ln(u) - 0x1000000000000ll;
-
-               /*
-                * divide by 16.16 fixed-point weight
-                */
-               draw = ln / bucket->item_weights[i];
+               w = bucket->item_weights[i];
+               if (w) {
+                       u = crush_hash32_3(bucket->h.hash, x,
+                                          bucket->h.items[i], r);
+                       u &= 0xffff;
+
+                       /*
+                        * for some reason slightly less than 0x10000 produces
+                        * a slightly more accurate distribution... probably a
+                        * rounding effect.
+                        *
+                        * the natural log lookup table maps [0,0xffff]
+                        * (corresponding to real numbers [1/0x10000, 1] to
+                        * [0, 0xffffffffffff] (corresponding to real numbers
+                        * [-11.090355,0]).
+                        */
+                       ln = crush_ln(u) - 0x1000000000000ll;
+
+                       /*
+                        * divide by 16.16 fixed-point weight.  note
+                        * that the ln value is negative, so a larger
+                        * weight means a larger (less negative) value
+                        * for draw.
+                        */
+                       draw = ln / w;
+               } else {
+                       draw = INT64_MIN;
+               }
 
                if (i == 0 || draw > high_draw) {
                        high = i;