axmap: return early of an overlap results in 0 settable bits
[fio.git] / lib / axmap.c
index 4a907fec22d2f8a2723121d8236d7a56be6db01c..03e712f53be7a7623f90b12a3eecf57d73fc6f62 100644 (file)
@@ -83,14 +83,6 @@ struct axmap {
        uint64_t nr_bits;
 };
 
-static inline unsigned long ulog64(unsigned long val, unsigned int log)
-{
-       while (log-- && val)
-               val >>= UNIT_SHIFT;
-
-       return val;
-}
-
 /* Remove all elements from the @axmap set */
 void axmap_reset(struct axmap *axmap)
 {
@@ -136,6 +128,8 @@ struct axmap *axmap_new(unsigned long nr_bits)
 
        axmap->nr_levels = levels;
        axmap->levels = calloc(axmap->nr_levels, sizeof(struct axmap_level));
+       if (!axmap->levels)
+               goto free_axmap;
        axmap->nr_bits = nr_bits;
 
        for (i = 0; i < axmap->nr_levels; i++) {
@@ -145,19 +139,21 @@ struct axmap *axmap_new(unsigned long nr_bits)
                al->map_size = (nr_bits + BLOCKS_PER_UNIT - 1) >> UNIT_SHIFT;
                al->map = malloc(al->map_size * sizeof(unsigned long));
                if (!al->map)
-                       goto err;
+                       goto free_levels;
 
                nr_bits = (nr_bits + BLOCKS_PER_UNIT - 1) >> UNIT_SHIFT;
        }
 
        axmap_reset(axmap);
        return axmap;
-err:
+
+free_levels:
        for (i = 0; i < axmap->nr_levels; i++)
-               if (axmap->levels[i].map)
-                       free(axmap->levels[i].map);
+               free(axmap->levels[i].map);
 
        free(axmap->levels);
+
+free_axmap:
        free(axmap);
        return NULL;
 }
@@ -202,7 +198,7 @@ static bool axmap_handler_topdown(struct axmap *axmap, uint64_t bit_nr,
        int i;
 
        for (i = axmap->nr_levels - 1; i >= 0; i--) {
-               unsigned long index = ulog64(bit_nr, i);
+               unsigned long index = bit_nr >> (UNIT_SHIFT * i);
                unsigned long offset = index >> UNIT_SHIFT;
                unsigned int bit = index & BLOCKS_PER_UNIT_MASK;
 
@@ -239,18 +235,14 @@ static bool axmap_set_fn(struct axmap_level *al, unsigned long offset,
         */
        overlap = al->map[offset] & mask;
        if (overlap == mask) {
-done:
                data->set_bits = 0;
                return true;
        }
 
        if (overlap) {
-               const int __bit = ffz(~overlap);
-
-               nr_bits = __bit - bit;
+               nr_bits = ffz(~overlap) - bit;
                if (!nr_bits)
-                       goto done;
-
+                       return true;
                mask = bit_masks[nr_bits] << bit;
        }
 
@@ -278,29 +270,16 @@ done:
 static void __axmap_set(struct axmap *axmap, uint64_t bit_nr,
                         struct axmap_set_data *data)
 {
-       unsigned int set_bits, nr_bits = data->nr_bits;
+       unsigned int nr_bits = data->nr_bits;
 
        if (bit_nr > axmap->nr_bits)
                return;
        else if (bit_nr + nr_bits > axmap->nr_bits)
                nr_bits = axmap->nr_bits - bit_nr;
 
-       set_bits = 0;
-       while (nr_bits) {
-               axmap_handler(axmap, bit_nr, axmap_set_fn, data);
-               set_bits += data->set_bits;
-
-               if (!data->set_bits ||
-                   data->set_bits != (BLOCKS_PER_UNIT - nr_bits))
-                       break;
-
-               nr_bits -= data->set_bits;
-               bit_nr += data->set_bits;
-
-               data->nr_bits = nr_bits;
-       }
+       assert(nr_bits <= BLOCKS_PER_UNIT);
 
-       data->set_bits = set_bits;
+       axmap_handler(axmap, bit_nr, axmap_set_fn, data);
 }
 
 void axmap_set(struct axmap *axmap, uint64_t bit_nr)