axmap: fix bug with max_bs/min_bs ratio being > 64
authorJens Axboe <axboe@kernel.dk>
Fri, 29 Mar 2013 14:56:09 +0000 (08:56 -0600)
committerJens Axboe <axboe@kernel.dk>
Fri, 29 Mar 2013 14:56:09 +0000 (08:56 -0600)
Signed-off-by: Jens Axboe <axboe@kernel.dk>
lib/axmap.c

index eeb32d42a6085e096bdde44fc39f057d9853b8da..4fb59e7a738dd998fcbbeae4c199e4975095336f 100644 (file)
@@ -273,7 +273,8 @@ static void __axmap_set(struct axmap *axmap, uint64_t bit_nr,
                axmap_handler(axmap, bit_nr, axmap_set_fn, data);
                set_bits += data->set_bits;
 
-               if (data->set_bits != (BLOCKS_PER_UNIT - nr_bits))
+               if (!data->set_bits ||
+                   data->set_bits != (BLOCKS_PER_UNIT - nr_bits))
                        break;
 
                nr_bits -= data->set_bits;
@@ -295,10 +296,30 @@ void axmap_set(struct axmap *axmap, uint64_t bit_nr)
 
 unsigned int axmap_set_nr(struct axmap *axmap, uint64_t bit_nr, unsigned int nr_bits)
 {
-       struct axmap_set_data data = { .nr_bits = nr_bits, };
+       unsigned int set_bits = 0;
+
+       do {
+               struct axmap_set_data data = {
+                                               .nr_bits = nr_bits,
+                                               .fail_ok = set_bits != 0,
+                                               };
+               unsigned int max_bits, this_set;
+
+               max_bits = BLOCKS_PER_UNIT - (bit_nr & BLOCKS_PER_UNIT_MASK);
+               if (max_bits < nr_bits)
+                       data.nr_bits = max_bits;
+
+               this_set = data.nr_bits;
+               __axmap_set(axmap, bit_nr, &data);
+               set_bits += data.set_bits;
+               if (data.set_bits != this_set)
+                       break;
 
-       __axmap_set(axmap, bit_nr, &data);
-       return data.set_bits;
+               nr_bits -= data.set_bits;
+               bit_nr += data.set_bits;
+       } while (nr_bits);
+
+       return set_bits;
 }
 
 static int axmap_isset_fn(struct axmap_level *al, unsigned long offset,