]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
Hint argument in alloc_blocks + test case changes 10978/head
authorRamesh Chander <Ramesh.Chander@sandisk.com>
Mon, 29 Aug 2016 17:16:11 +0000 (10:16 -0700)
committerRamesh Chander <Ramesh.Chander@sandisk.com>
Wed, 7 Sep 2016 15:05:48 +0000 (08:05 -0700)
Signed-off-by: Ramesh Chander <Ramesh.Chander@sandisk.com>
src/os/bluestore/BitAllocator.cc
src/os/bluestore/BitAllocator.h
src/os/bluestore/BitMapAllocator.cc
src/test/objectstore/Allocator_test.cc
src/test/objectstore/BitAllocator_test.cc

index b22d70b3a5483bf2adecfbac15087ca7f3127306..b47020009ff6f5fcb2ea6ef3b69854df9d2cf035 100644 (file)
@@ -533,17 +533,15 @@ bool BitMapZone::check_locked()
  *
  * Caller must take exclusive lock on Zone.
  */
-int64_t BitMapZone::alloc_blocks(int64_t num_blocks, int64_t *start_block)
+int64_t BitMapZone::alloc_blocks(int64_t num_blocks, int64_t hint, int64_t *start_block)
 {
-  int64_t bmap_idx = 0;
-  int bit_idx = 0;
+  int64_t bmap_idx = hint / BmapEntry::size();
+  int bit_idx = hint % BmapEntry::size();
   BmapEntry *bmap = NULL;
   int64_t allocated = 0;
 
   debug_assert(check_locked());
 
-  bit_idx = 0;
-  bmap_idx = 0;
   BitMapEntityIter <BmapEntry> iter = BitMapEntityIter<BmapEntry>(
           m_bmap_list, bmap_idx);
 
@@ -597,7 +595,7 @@ void BitMapZone::free_blocks(int64_t start_block, int64_t num_blocks)
  * Allocate N blocks, dis-contiguous are fine
  */
 int64_t BitMapZone::alloc_blocks_dis(int64_t num_blocks,
-                                          int64_t hint,
+                               int64_t hint,
                                    int64_t zone_blk_off, 
                                    ExtentList *alloc_blocks)
 {
@@ -620,7 +618,7 @@ int64_t BitMapZone::alloc_blocks_dis(int64_t num_blocks,
     if (allocated == num_blocks) {
       break;
     }
-       bit = 0;
+    bit = 0;
   }
 
   add_used_blocks(allocated);
@@ -870,22 +868,23 @@ bool BitMapAreaIN::is_allocated(int64_t start_block, int64_t num_blocks)
   return true;
 }
 
-int64_t BitMapAreaIN::alloc_blocks_int_work(bool wait, bool wrap,
-                         int64_t num_blocks, int64_t *start_block)
+int64_t BitMapAreaIN::alloc_blocks_int_work(bool wait, bool wrap, int64_t num_blocks,
+                         int64_t hint, int64_t *start_block)
 {
   BitMapArea *child = NULL;
   int64_t allocated = 0;
 
   *start_block = 0;
   BmapEntityListIter iter = BmapEntityListIter(
-                                m_child_list, 0, wrap);
+                                m_child_list, hint / m_child_size_blocks, wrap);
 
   while ((child = (BitMapArea *) iter.next())) {
     if (!child_check_n_lock(child, num_blocks - allocated)) {
+    hint = 0;
       continue;
     }
 
-    allocated = child->alloc_blocks(wait, num_blocks, start_block);
+    allocated = child->alloc_blocks(wait, num_blocks, hint % m_child_size_blocks, start_block);
     child_unlock(child);
     if (allocated == num_blocks) {
       (*start_block) += child->get_index() * m_child_size_blocks;
@@ -893,19 +892,20 @@ int64_t BitMapAreaIN::alloc_blocks_int_work(bool wait, bool wrap,
     }
 
     child->free_blocks(*start_block, allocated);
+  hint = 0;
     *start_block = 0;
     allocated = 0;
   }
   return allocated;
 }
 
-int64_t BitMapAreaIN::alloc_blocks_int(bool wait,
-                         int64_t num_blocks, int64_t *start_block)
+int64_t BitMapAreaIN::alloc_blocks_int(bool wait, int64_t num_blocks,
+                         int64_t hint, int64_t *start_block)
 {
-  return alloc_blocks_int_work(wait, false, num_blocks, start_block);
+  return alloc_blocks_int_work(wait, false, num_blocks, hint, start_block);
 }
 
-int64_t BitMapAreaIN::alloc_blocks(bool wait, int64_t num_blocks,
+int64_t BitMapAreaIN::alloc_blocks(bool wait, int64_t num_blocks, int64_t hint,
                       int64_t *start_block)
 {
   int64_t allocated = 0;
@@ -916,7 +916,7 @@ int64_t BitMapAreaIN::alloc_blocks(bool wait, int64_t num_blocks,
     goto exit;
   }
 
-  allocated = alloc_blocks_int(wait, num_blocks, start_block);
+  allocated = alloc_blocks_int(wait, num_blocks, hint, start_block);
 
   unreserve(num_blocks, allocated);
   debug_assert((get_used_blocks() <= m_total_blocks));
@@ -939,13 +939,14 @@ int64_t BitMapAreaIN::alloc_blocks_dis_int_work(bool wait, bool wrap, int64_t nu
 
   while ((child = (BitMapArea *) iter.next())) {
     if (!child_check_n_lock(child, 1)) {
+    hint = 0;
       continue;
     }
 
     blk_off = child->get_index() * m_child_size_blocks + area_blk_off;
     allocated += child->alloc_blocks_dis(wait, num_blocks - allocated,
                             hint % m_child_size_blocks, blk_off, block_list);
-       hint = 0;
+    hint = 0;
     child_unlock(child);
     if (allocated == num_blocks) {
       break;
@@ -958,9 +959,8 @@ int64_t BitMapAreaIN::alloc_blocks_dis_int_work(bool wait, bool wrap, int64_t nu
 int64_t BitMapAreaIN::alloc_blocks_dis_int(bool wait, int64_t num_blocks,
            int64_t hint, int64_t area_blk_off, ExtentList *block_list)
 {
-  return alloc_blocks_dis_int_work(wait, true, num_blocks, hint,
-                                                                  area_blk_off, block_list);
-
+  return alloc_blocks_dis_int_work(wait, false, num_blocks, hint,
+                     area_blk_off, block_list);
 }
 
 int64_t BitMapAreaIN::alloc_blocks_dis(bool wait, int64_t num_blocks,
@@ -1132,8 +1132,8 @@ void BitMapAreaLeaf::child_unlock(BitMapArea *child)
   child->unlock();
 }
 
-int64_t BitMapAreaLeaf::alloc_blocks_int(bool wait,
-                         int64_t num_blocks, int64_t *start_block)
+int64_t BitMapAreaLeaf::alloc_blocks_int(bool wait, int64_t num_blocks,
+                int64_t hint, int64_t *start_block)
 {
   BitMapArea *child = NULL;
   int64_t allocated = 0;
@@ -1141,15 +1141,16 @@ int64_t BitMapAreaLeaf::alloc_blocks_int(bool wait,
   *start_block = 0;
 
   BmapEntityListIter iter = BmapEntityListIter(
-                                m_child_list, 0, false);
+                                m_child_list, hint / m_child_size_blocks, false);
 
   while ((child = iter.next())) {
     if (!child_check_n_lock(child, num_blocks - allocated, false)) {
+    hint = 0;
       continue;
     }
     debug_assert(child->get_type() == ZONE);
 
-    allocated = child->alloc_blocks(num_blocks, start_block);
+    allocated = child->alloc_blocks(num_blocks, hint % m_child_size_blocks, start_block);
     child_unlock(child);
     if (allocated == num_blocks) {
       (*start_block) += child->get_index() * m_child_size_blocks;
@@ -1157,6 +1158,7 @@ int64_t BitMapAreaLeaf::alloc_blocks_int(bool wait,
     }
 
     child->free_blocks(*start_block, allocated);
+    hint = 0;
     *start_block = 0;
     allocated = 0;
   }
@@ -1175,16 +1177,18 @@ int64_t BitMapAreaLeaf::alloc_blocks_dis_int(bool wait, int64_t num_blocks,
 
   while ((child = (BitMapArea *) iter.next())) {
     if (!child_check_n_lock(child, 1, false)) {
+    hint = 0;
       continue;
     }
 
     blk_off = child->get_index() * m_child_size_blocks + area_blk_off;
-    allocated += child->alloc_blocks_dis(num_blocks - allocated, hint, blk_off, block_list);
-       hint = 0;
+    allocated += child->alloc_blocks_dis(num_blocks - allocated, hint % m_child_size_blocks,
+                                         blk_off, block_list);
     child_unlock(child);
     if (allocated == num_blocks) {
       break;
     }
+  hint = 0;
   }
   return allocated;
 }
@@ -1391,43 +1395,16 @@ bool BitAllocator::check_input(int64_t num_blocks)
   return true;
 }
 
-int64_t BitAllocator::alloc_blocks_int(bool wait,
-                         int64_t num_blocks, int64_t *start_block)
+int64_t BitAllocator::alloc_blocks_int(bool wait, int64_t num_blocks,
+                         int64_t hint, int64_t *start_block)
 {
-
-  return alloc_blocks_int_work(wait, true, num_blocks, start_block);
-#if 0
-  BitMapArea *child = NULL;
-  int64_t allocated = 0;
-
-  *start_block = 0;
-  BmapEntityListIter iter = BmapEntityListIter(
-                                m_child_list, 0, true);
-
-  while ((child = (BitMapArea *) iter.next())) {
-    if (!child_check_n_lock(child, num_blocks - allocated)) {
-      continue;
-    }
-
-    allocated = child->alloc_blocks(wait, num_blocks, start_block);
-    child_unlock(child);
-    if (allocated == num_blocks) {
-      (*start_block) += child->get_index() * m_child_size_blocks;
-      break;
-    }
-
-    child->free_blocks(*start_block, allocated);
-    *start_block = 0;
-    allocated = 0;
-  }
-  return allocated;
-#endif
+  return alloc_blocks_int_work(wait, true, num_blocks, hint, start_block);
 }
 
 /*
  * Interface to allocate blocks after reserve.
  */
-int64_t BitAllocator::alloc_blocks_res(int64_t num_blocks, int64_t *start_block)
+int64_t BitAllocator::alloc_blocks_res(int64_t num_blocks, int64_t hint, int64_t *start_block)
 {
   int scans = 1;
   int64_t allocated = 0;
@@ -1445,7 +1422,7 @@ int64_t BitAllocator::alloc_blocks_res(int64_t num_blocks, int64_t *start_block)
   }
 
   while (scans && !allocated) {
-    allocated = alloc_blocks_int(false, num_blocks, start_block);
+    allocated = alloc_blocks_int(false, num_blocks, hint, start_block);
     scans--;
   }
 
@@ -1458,7 +1435,7 @@ int64_t BitAllocator::alloc_blocks_res(int64_t num_blocks, int64_t *start_block)
     unlock();
     lock_excl();
     serial_lock();
-    allocated = alloc_blocks_int(false, num_blocks, start_block);
+    allocated = alloc_blocks_int(false, num_blocks, hint, start_block);
     if (is_stats_on()) {
       m_stats->add_serial_scans(1);
     }
@@ -1473,7 +1450,7 @@ int64_t BitAllocator::alloc_blocks_res(int64_t num_blocks, int64_t *start_block)
   return allocated;
 }
 
-int64_t BitAllocator::alloc_blocks(int64_t num_blocks, int64_t *start_block)
+int64_t BitAllocator::alloc_blocks(int64_t num_blocks, int64_t hint, int64_t *start_block)
 {
   int scans = 1;
   int64_t allocated = 0;
@@ -1501,7 +1478,7 @@ int64_t BitAllocator::alloc_blocks(int64_t num_blocks, int64_t *start_block)
   }
 
   while (scans && !allocated) {
-    allocated = alloc_blocks_int(false, num_blocks, start_block);
+    allocated = alloc_blocks_int(false, num_blocks, hint, start_block);
     scans--;
   }
 
@@ -1514,9 +1491,9 @@ int64_t BitAllocator::alloc_blocks(int64_t num_blocks, int64_t *start_block)
     unlock();
     lock_excl();
     serial_lock();
-    allocated = alloc_blocks_int(false, num_blocks, start_block);
+    allocated = alloc_blocks_int(false, num_blocks, hint, start_block);
     if (!allocated) {
-      allocated = alloc_blocks_int(false, num_blocks, start_block);
+      allocated = alloc_blocks_int(false, num_blocks, hint, start_block);
       debug_assert(allocated);
     }
     if (is_stats_on()) {
@@ -1578,34 +1555,8 @@ void BitAllocator::set_blocks_used(int64_t start_block, int64_t num_blocks)
 int64_t BitAllocator::alloc_blocks_dis_int(bool wait, int64_t num_blocks,
            int64_t hint, int64_t area_blk_off, ExtentList *block_list)
 {
-  
   return alloc_blocks_dis_int_work(wait, true, num_blocks, hint,
-                                                                  area_blk_off, block_list);
- #if 0
-  BitMapArea *child = NULL;
-  int64_t allocated = 0;
-  int64_t blk_off = 0;
-
-  BmapEntityListIter iter = BmapEntityListIter(
-        m_child_list, hint / m_child_size_blocks, true);
-
-  while ((child = (BitMapArea *) iter.next())) {
-    if (!child_check_n_lock(child, 1)) {
-      continue;
-    }
-
-    blk_off = child->get_index() * m_child_size_blocks + area_blk_off;
-    allocated += child->alloc_blocks_dis(wait, num_blocks - allocated,
-                            hint % m_child_size_blocks, blk_off, block_list);
-       hint = 0;
-    child_unlock(child);
-    if (allocated == num_blocks) {
-      break;
-    }
-  }
-
-  return allocated;
- #endif
+                     area_blk_off, block_list);
 }
 
 int64_t BitAllocator::alloc_blocks_dis(int64_t num_blocks, int64_t hint, ExtentList *block_list)
@@ -1661,7 +1612,8 @@ int64_t BitAllocator::alloc_blocks_dis_work(int64_t num_blocks, int64_t hint, Ex
     unlock();
     lock_excl();
     serial_lock();
-    allocated += alloc_blocks_dis_int(false, num_blocks - allocated, hint + allocated, blk_off, block_list);
+    allocated += alloc_blocks_dis_int(false, num_blocks - allocated, hint + allocated,
+                                      blk_off, block_list);
     if (is_stats_on()) {
       m_stats->add_serial_scans(1);
     }
index 270180d57604083a54ddcfb5477a3b75712843d2..fde28060f6b048f1cba30882697b02929d51e648 100644 (file)
@@ -226,11 +226,12 @@ public:
   virtual int64_t get_used_blocks() = 0;
 
   virtual void shutdown() = 0;
-  virtual int64_t alloc_blocks(bool wait, int64_t num_blocks, int64_t *start_block) {
+  virtual int64_t alloc_blocks(bool wait, int64_t num_blocks,
+                               int64_t hint, int64_t *start_block) {
     debug_assert(0);
     return 0;
   }
-  virtual int64_t alloc_blocks(int64_t num_blocks, int64_t *start_block) {
+  virtual int64_t alloc_blocks(int64_t num_blocks, int64_t hint, int64_t *start_block) {
     debug_assert(0);
     return 0;
   }
@@ -348,7 +349,8 @@ public:
   ~BitMapZone();
   void shutdown();
 
-  virtual int64_t alloc_blocks(bool wait, int64_t num_blocks, int64_t *start_block) {
+  virtual int64_t alloc_blocks(bool wait, int64_t num_blocks,
+                               int64_t hint, int64_t *start_block) {
     debug_assert(0);
     return 0;
   }
@@ -359,7 +361,7 @@ public:
     return 0;
   }
 
-  int64_t alloc_blocks(int64_t num_blocks, int64_t *start_block);
+  int64_t alloc_blocks(int64_t num_blocks, int64_t hint, int64_t *start_block);
   using BitMapArea::alloc_blocks_dis;
   int64_t alloc_blocks_dis(int64_t num_blocks, int64_t hint,
         int64_t blk_off, ExtentList *block_list);  
@@ -406,7 +408,7 @@ protected:
   void init_common(int64_t total_blocks, int64_t zone_size_block, bool def);
 
   int64_t alloc_blocks_int_work(bool wait, bool wrap,
-                         int64_t num_blocks, int64_t *start_block);
+                         int64_t num_blocks, int64_t hint, int64_t *start_block);
   int64_t alloc_blocks_dis_int_work(bool wait, bool wrap, int64_t num_blocks, int64_t hint,
         int64_t blk_off, ExtentList *block_list);  
 
@@ -427,11 +429,11 @@ public:
     return m_total_blocks;
   }
 
-  virtual int64_t alloc_blocks_int(bool wait,
-                     int64_t num_blocks, int64_t *start_block);
+  virtual int64_t alloc_blocks_int(bool wait, int64_t num_blocks,
+                 int64_t hint, int64_t *start_block);
   using BitMapArea::alloc_blocks; //non-wait version
   using BitMapArea::alloc_blocks_dis; //non-wait version
-  virtual int64_t alloc_blocks(bool wait, int64_t num_blocks, int64_t *start_block);
+  virtual int64_t alloc_blocks(bool wait, int64_t num_blocks, int64_t hint, int64_t *start_block);
   virtual int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t hint,
         int64_t blk_off, ExtentList *block_list);  
   virtual int64_t alloc_blocks_dis(bool wait, int64_t num_blocks, int64_t hint,
@@ -464,8 +466,7 @@ public:
   bool child_check_n_lock(BitMapArea *child, int64_t required, bool lock);
   void child_unlock(BitMapArea *child);
 
-  int64_t alloc_blocks_int(bool wait,
-                         int64_t num_blocks, int64_t *start_block);
+  int64_t alloc_blocks_int(bool wait, int64_t num_blocks, int64_t hint, int64_t *start_block);
   int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks, int64_t hint,
         int64_t blk_off, ExtentList *block_list);  
   void free_blocks_int(int64_t start_block, int64_t num_blocks);
@@ -507,6 +508,10 @@ private:
   void init_check(int64_t total_blocks, int64_t zone_size_block,
                  bmap_alloc_mode_t mode, bool def, bool stats_on);
   int64_t alloc_blocks_dis_work(int64_t num_blocks, int64_t hint, ExtentList *block_list, bool reserved);
+  int64_t alloc_blocks_int(bool wait, int64_t num_blocks, int64_t hint, int64_t *start_block);
+
+  int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks,
+           int64_t hint, int64_t area_blk_off, ExtentList *block_list);
 
 public:
 
@@ -519,17 +524,12 @@ public:
   using BitMapAreaIN::alloc_blocks; //Wait version
   using BitMapAreaIN::alloc_blocks_dis; //Wait version
 
-  int64_t alloc_blocks(int64_t num_blocks, int64_t *start_block);
-  int64_t alloc_blocks_res(int64_t num_blocks, int64_t *start_block);
+  int64_t alloc_blocks(int64_t num_blocks, int64_t hint, int64_t *start_block);
+  int64_t alloc_blocks_res(int64_t num_blocks, int64_t hint, int64_t *start_block);
   void free_blocks(int64_t start_block, int64_t num_blocks);
   void set_blocks_used(int64_t start_block, int64_t num_blocks);
   void unreserve_blocks(int64_t blocks);
 
-  int64_t alloc_blocks_int(bool wait,
-                         int64_t num_blocks, int64_t *start_block);
-
-  int64_t alloc_blocks_dis_int(bool wait, int64_t num_blocks,
-           int64_t hint, int64_t area_blk_off, ExtentList *block_list);
   int64_t alloc_blocks_dis(int64_t num_blocks, int64_t hint, ExtentList *block_list);
   int64_t alloc_blocks_dis_res(int64_t num_blocks, int64_t hint, ExtentList *block_list);
 
index b5b0f3b49025ec1d427cfcee7bb2e7ab8f2b0e01..c686ca7ddbcfe739dbb0e9cbd83326fb5e3a47dc 100644 (file)
@@ -133,7 +133,7 @@ int BitMapAllocator::allocate(
   *offset = 0;
   *length = 0;
 
-  count = m_bit_alloc->alloc_blocks_res(nblks, &start_blk);
+  count = m_bit_alloc->alloc_blocks_res(nblks, hint / m_block_size, &start_blk);
   if (count == 0) {
     return -ENOSPC;
   }
@@ -164,9 +164,11 @@ int BitMapAllocator::alloc_extents(
      << dendl;
 
   if (alloc_unit > (uint64_t) m_block_size) {
-    return alloc_extents_cont(want_size, alloc_unit, max_alloc_size, hint, extents, count);     
+    return alloc_extents_cont(want_size, alloc_unit, 
+                              max_alloc_size, hint / m_block_size, extents, count);     
   } else {
-    return alloc_extents_dis(want_size, alloc_unit, max_alloc_size, hint, extents, count); 
+    return alloc_extents_dis(want_size, alloc_unit,
+                             max_alloc_size, hint / m_block_size, extents, count); 
   }
 }
 
@@ -192,7 +194,7 @@ int BitMapAllocator::alloc_extents_cont(
   while (need_blks > 0) {
     int64_t count = 0;
     count = m_bit_alloc->alloc_blocks_res(
-      (max_blks && need_blks > max_blks) ? max_blks : need_blks, &start_blk);
+      (max_blks && need_blks > max_blks) ? max_blks : need_blks, hint, &start_blk);
     if (count == 0) {
       break;
     }
index 16abd35be6027f3654beb992780b9380f2ef2880..a003fdbc74460a550b382f72ec5f63dd11043c2c 100644 (file)
@@ -45,7 +45,7 @@ TEST_P(AllocTest, test_alloc_init)
   alloc->shutdown(); 
   blocks = BitMapZone::get_total_blocks() * 2;
   init_alloc(blocks, 1);
-  ASSERT_EQ(alloc->get_free(), 0);
+  ASSERT_EQ(alloc->get_free(), (uint64_t) 0);
 }
 
 TEST_P(AllocTest, test_alloc_min_alloc)
@@ -187,6 +187,49 @@ TEST_P(AllocTest, test_alloc_failure)
   }
 }
 
+TEST_P(AllocTest, test_alloc_hint_bmap)
+{
+  if (GetParam() == std::string("stupid")) {
+    return;
+  }
+  int64_t blocks = BitMapArea::get_level_factor(2) * 4;
+  int count = 0;
+  int64_t allocated = 0;
+  int64_t zone_size = 1024;
+  g_conf->set_val("bluestore_bitmapallocator_blocks_per_zone", std::to_string(zone_size));
+
+  init_alloc(blocks, 1);
+  alloc->init_add_free(0, blocks);
+
+  auto extents = std::vector<AllocExtent>
+          (zone_size * 4, AllocExtent(-1, -1));
+  alloc->reserve(blocks);
+
+  allocated = alloc->alloc_extents(1, 1, 1, zone_size, &extents, &count);
+  ASSERT_EQ(0, allocated);
+  ASSERT_EQ(1, count);
+  ASSERT_EQ(extents[0].offset, (uint64_t) zone_size);
+
+  allocated = alloc->alloc_extents(1, 1, 1, zone_size * 2 - 1, &extents, &count);
+  EXPECT_EQ(0, allocated);
+  ASSERT_EQ(1, count);
+  EXPECT_EQ((int64_t) extents[0].offset, zone_size * 2 - 1);
+
+  /*
+   * Wrap around with hint
+   */
+  allocated = alloc->alloc_extents(zone_size * 2, 1, 1,  blocks - zone_size * 2, &extents, &count);
+  EXPECT_EQ(0, allocated);
+  EXPECT_EQ(zone_size * 2, count);
+  EXPECT_EQ((int64_t)extents[0].offset, blocks - zone_size * 2);
+
+  allocated = alloc->alloc_extents(zone_size, 1, 1, blocks - zone_size, &extents, &count);
+  EXPECT_EQ(0, allocated);
+  EXPECT_EQ(zone_size, count);
+  EXPECT_EQ(extents[0].offset, (uint64_t) 0);
+}
+
+
 INSTANTIATE_TEST_CASE_P(
   Allocator,
   AllocTest,
index 285dadd660a24d7bcac3acf914af1c6f77ee0fac..68b478eaf71ae50856b38f7a83fa68a2160536e1 100644 (file)
@@ -222,6 +222,8 @@ TEST(BitAllocator, test_bmap_entry)
 
   }
 
+
+
   // Find few bits at end of bitmap and find those
   bmap->clear_bits(0, 4);
   bmap->clear_bits(BmapEntry::size() - 12, 5);
@@ -234,6 +236,29 @@ TEST(BitAllocator, test_bmap_entry)
   bmap_test_assert(bmap->is_allocated(start, 6));
 
   delete bmap;
+
+  {
+
+    bmap = new BmapEntry(false);
+    start = -1;
+    scanned = 0;
+    allocated = 0;
+    allocated = bmap->find_first_set_bits(1, 1, &start, &scanned);
+    bmap_test_assert(allocated == 1);
+    bmap_test_assert(start == 1);
+
+    allocated = bmap->find_first_set_bits(1, BmapEntry::size() - 2, &start, &scanned);
+    bmap_test_assert(allocated == 1);
+    bmap_test_assert(start == BmapEntry::size() - 2);
+
+    bmap->clear_bits(0, BmapEntry::size());
+    bmap->set_bits(0, BmapEntry::size() / 4);
+    allocated = bmap->find_first_set_bits(4, 2, &start, &scanned);
+    bmap_test_assert(allocated == 4);
+    bmap_test_assert(start == BmapEntry::size() / 4);
+    delete bmap;
+  }
+
   bmap = new BmapEntry(false);
   bmap->set_bits(4, BmapEntry::size() - 4);
   bmap_test_assert(bmap->is_allocated(4, BmapEntry::size() - 4));
@@ -241,6 +266,7 @@ TEST(BitAllocator, test_bmap_entry)
   bmap->set_bits(0, 4);
   bmap_test_assert(bmap->is_allocated(0, BmapEntry::size()));
   delete bmap;
+
 }
 
 TEST(BitAllocator, test_zone_alloc)
@@ -258,7 +284,7 @@ TEST(BitAllocator, test_zone_alloc)
   bmap_test_assert(lock);
 
   for (int i = 0; i < total_blocks; i++) {
-    allocated = zone->alloc_blocks(blks, &start_blk);
+    allocated = zone->alloc_blocks(blks, 0, &start_blk);
     bmap_test_assert(last_blk + 1 == start_blk);
     bmap_test_assert(allocated == blks);
     last_blk = start_blk;
@@ -273,7 +299,7 @@ TEST(BitAllocator, test_zone_alloc)
   blks = 2;
   last_blk = -2;
   for (int i = 0; i < total_blocks/2; i++) {
-    allocated = zone->alloc_blocks(blks, &start_blk);
+    allocated = zone->alloc_blocks(blks, 0, &start_blk);
     bmap_test_assert(last_blk + 2 == start_blk);
     last_blk = start_blk;
   }
@@ -284,19 +310,19 @@ TEST(BitAllocator, test_zone_alloc)
   zone->free_blocks(BmapEntry::size() - blks, blks);
   zone->free_blocks(BmapEntry::size(), blks);
 
-  allocated = zone->alloc_blocks(blks * 2, &start_blk);
+  allocated = zone->alloc_blocks(blks * 2, 0, &start_blk);
   bmap_test_assert(BmapEntry::size() - blks == start_blk);
   bmap_test_assert(allocated == blks * 2);
 
   blks = 4;
   zone->free_blocks(BmapEntry::size() * 2 - blks, 2 * blks);
-  allocated = zone->alloc_blocks(2 * blks, &start_blk);
+  allocated = zone->alloc_blocks(2 * blks, 0, &start_blk);
   bmap_test_assert(BmapEntry::size() * 2 - blks == start_blk);
   bmap_test_assert(allocated == blks * 2);
 
   blks = BmapEntry::size() * 2;
   zone->free_blocks(BmapEntry::size() * 6 - blks, blks);
-  allocated = zone->alloc_blocks(blks, &start_blk);
+  allocated = zone->alloc_blocks(blks, 0, &start_blk);
   bmap_test_assert(BmapEntry::size() * 6 - blks == start_blk);
 
   // free blocks at distance 1, 2 up to 63 and allocate all of them
@@ -311,7 +337,7 @@ TEST(BitAllocator, test_zone_alloc)
   num_bits = 1;
   int64_t start_block = 0;
   for (int i = 0; i < zone->size() / BmapEntry::size() -1; i++) {
-    allocated = zone->alloc_blocks(num_bits, &start_block);
+    allocated = zone->alloc_blocks(num_bits, 0, &start_block);
     bmap_test_assert(num_bits == allocated);
     bmap_test_assert(start_block == i * BmapEntry::size());
     num_bits++;
@@ -330,7 +356,7 @@ TEST(BitAllocator, test_zone_alloc)
   lock = zone->lock_excl_try();
   bmap_test_assert(lock);
   for (int i = 0; i < zone->size(); i++) {
-    allocated = zone->alloc_blocks(1, &start_block);
+    allocated = zone->alloc_blocks(1, 0, &start_block);
     bmap_test_assert(allocated == 1);
   }
   for (int i = 0; i < zone->size(); i += 2) {
@@ -342,8 +368,45 @@ TEST(BitAllocator, test_zone_alloc)
         (zone->size() / 2, AllocExtent(-1, -1));
 
   ExtentList *block_list = new ExtentList(&extents, blk_size);
-  allocated = zone->alloc_blocks_dis(zone->size() / 2, 0, block_list);
+  allocated = zone->alloc_blocks_dis(zone->size() / 2, 0, 0, block_list);
   bmap_test_assert(allocated == zone->size() / 2);
+
+  {
+    zone = new BitMapZone(total_blocks, 0);
+    lock = zone->lock_excl_try();
+    bmap_test_assert(lock);
+    for (int i = 0; i < zone->size(); i += 4) {
+    allocated = zone->alloc_blocks(1, i, &start_block);
+    bmap_test_assert(allocated == 1);
+    bmap_test_assert(start_block == i);
+    }
+
+    for (int i = 0; i < zone->size(); i += 4) {
+      zone->free_blocks(i, 1);
+    }
+  }
+
+  {
+    int64_t blk_size = 1024;
+    std::vector<AllocExtent> extents = std::vector<AllocExtent>
+      (zone->size() / 2, AllocExtent(-1, -1));
+
+    ExtentList *block_list = new ExtentList(&extents, blk_size);
+
+    zone = new BitMapZone(total_blocks, 0);
+    lock = zone->lock_excl_try();
+    bmap_test_assert(lock);
+    for (int i = 0; i < zone->size(); i += 4) {
+      block_list->reset();
+      allocated = zone->alloc_blocks_dis(1, i, 0, block_list);
+      bmap_test_assert(allocated == 1);
+      EXPECT_EQ(extents[0].offset, (uint64_t) i * blk_size);
+    }
+
+    for (int i = 0; i < zone->size(); i += 4) {
+      zone->free_blocks(i, 1);
+    }
+  }
 }
 
 TEST(BitAllocator, test_bmap_alloc)
@@ -372,7 +435,8 @@ TEST(BitAllocator, test_bmap_alloc)
 
     for (int64_t iter = 0; iter < max_iter; iter++) {
       for (int64_t i = 0; i < total_blocks; i++) {
-        allocated = alloc->alloc_blocks(1, &start_block);
+        debug_assert(alloc->reserve_blocks(1));
+        allocated = alloc->alloc_blocks_res(1, 0, &start_block);
         bmap_test_assert(allocated == 1);
         bmap_test_assert(start_block == i);
       }
@@ -384,7 +448,8 @@ TEST(BitAllocator, test_bmap_alloc)
 
     for (int64_t iter = 0; iter < max_iter; iter++) {
       for (int64_t i = 0; i < total_blocks / zone_size; i++) {
-        allocated = alloc->alloc_blocks(zone_size, &start_block);
+        debug_assert(alloc->reserve_blocks(zone_size));
+        allocated = alloc->alloc_blocks_res(zone_size, 0, &start_block);
         bmap_test_assert(allocated == zone_size);
         bmap_test_assert(start_block == i * zone_size);
       }
@@ -394,17 +459,17 @@ TEST(BitAllocator, test_bmap_alloc)
       }
     }
 
-    allocated = alloc->alloc_blocks(1, &start_block);
+    allocated = alloc->alloc_blocks(1, 0, &start_block);
     bmap_test_assert(allocated == 1);
 
-    allocated = alloc->alloc_blocks(zone_size - 1, &start_block);
+    allocated = alloc->alloc_blocks(zone_size - 1, 0, &start_block);
     bmap_test_assert(allocated == zone_size - 1);
     bmap_test_assert(start_block == 1);
 
-    allocated = alloc->alloc_blocks(1, &start_block);
+    allocated = alloc->alloc_blocks(1, 0, &start_block);
     bmap_test_assert(allocated == 1);
 
-    allocated = alloc->alloc_blocks(zone_size, &start_block);
+    allocated = alloc->alloc_blocks(zone_size, 0, &start_block);
     bmap_test_assert(allocated == zone_size);
     bmap_test_assert(start_block == zone_size * 2);
 
@@ -413,7 +478,7 @@ TEST(BitAllocator, test_bmap_alloc)
     alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT);
 
     for (int64_t i = 0; i < alloc->size(); i++) {
-      allocated = alloc->alloc_blocks(1, &start_block);
+      allocated = alloc->alloc_blocks(1, 0, &start_block);
       bmap_test_assert(allocated == 1);
     }
     for (int i = 0; i < alloc->size(); i += 2) {
@@ -426,17 +491,17 @@ TEST(BitAllocator, test_bmap_alloc)
 
     ExtentList *block_list = new ExtentList(&extents, blk_size);
 
-    allocated = alloc->alloc_blocks_dis(alloc->size()/2, block_list);
+    allocated = alloc->alloc_blocks_dis(alloc->size()/2, 0, block_list);
     ASSERT_EQ(alloc->size()/2, allocated);
 
     block_list->reset();
-    allocated = alloc->alloc_blocks_dis(1, block_list);
+    allocated = alloc->alloc_blocks_dis(1, 0, block_list);
     bmap_test_assert(allocated == 0);
 
     alloc->free_blocks(alloc->size()/2, 1);
 
     block_list->reset();
-    allocated = alloc->alloc_blocks_dis(1, block_list);
+    allocated = alloc->alloc_blocks_dis(1, 0, block_list);
     bmap_test_assert(allocated == 1);
 
     bmap_test_assert((int64_t) extents[0].offset == alloc->size()/2 * blk_size);
@@ -450,7 +515,7 @@ TEST(BitAllocator, test_bmap_alloc)
 
     for (int64_t iter = 0; iter < max_iter; iter++) {
       for (int64_t i = 0; i < total_blocks; i++) {
-        allocated = alloc->alloc_blocks(1, &start_block);
+        allocated = alloc->alloc_blocks(1, 0, &start_block);
         bmap_test_assert(allocated == 1);
         bmap_test_assert(start_block == i);
       }
@@ -468,7 +533,7 @@ TEST(BitAllocator, test_bmap_alloc)
     alloc = new BitAllocator(total_blocks, zone_size, CONCURRENT, false);
     for (int64_t iter = 0; iter < max_iter; iter++) {
       for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
-        allocated = alloc->alloc_blocks(alloc_size, &start_block);
+        allocated = alloc->alloc_blocks(alloc_size, 0, &start_block);
         bmap_test_assert(allocated == alloc_size);
         bmap_test_assert(start_block == i * alloc_size);
       }
@@ -482,7 +547,7 @@ TEST(BitAllocator, test_bmap_alloc)
     alloc = new BitAllocator(1024, zone_size, CONCURRENT, true);
 
     alloc->free_blocks(1, 1023);
-    allocated = alloc->alloc_blocks(16, &start_block);
+    allocated = alloc->alloc_blocks(16, 0, &start_block);
     bmap_test_assert(allocated == 16);
     bmap_test_assert(start_block == 1);
     delete alloc;
@@ -493,7 +558,7 @@ TEST(BitAllocator, test_bmap_alloc)
     for (int64_t iter = 0; iter < max_iter; iter++) {
       for (int64_t i = 0; i < total_blocks / alloc_size; i++) {
         bmap_test_assert(alloc->reserve_blocks(alloc_size));
-        allocated = alloc->alloc_blocks_res(alloc_size, &start_block);
+        allocated = alloc->alloc_blocks_res(alloc_size, 0, &start_block);
         bmap_test_assert(allocated == alloc_size);
         bmap_test_assert(start_block == i * alloc_size);
       }
@@ -503,7 +568,6 @@ TEST(BitAllocator, test_bmap_alloc)
       }
     }
 
-    delete alloc;
   }
 
   // restore to typical value
@@ -525,7 +589,7 @@ bool alloc_extents_max_block(BitAllocator *alloc,
 
   ExtentList *block_list = new ExtentList(&extents, blk_size, max_alloc);
 
-  allocated = alloc->alloc_blocks_dis(total_alloc, block_list);
+  allocated = alloc->alloc_blocks_dis(total_alloc, 0, block_list);
   EXPECT_EQ(allocated, total_alloc);
 
   max_alloc = total_alloc > max_alloc? max_alloc: total_alloc;
@@ -543,7 +607,7 @@ bool alloc_extents_max_block(BitAllocator *alloc,
   return true;
 }
 
-TEST(BitAllocator2, test_bmap_alloc)
+TEST(BitAllocator, test_bmap_alloc2)
 {
   int64_t total_blocks = 1024 * 4;
   int64_t zone_size = 1024;
@@ -584,7 +648,7 @@ do_work(BitAllocator *alloc)
     printf("Allocating in tid %d.\n", my_tid);
     debug_assert(alloc->reserve_blocks(num_blocks));
     for (int i = 0; i < num_blocks; i++) {
-      alloced = alloc->alloc_blocks_res(1, &start_block);
+      alloced = alloc->alloc_blocks_res(1, 0, &start_block);
       bmap_test_assert(alloced == 1);
       total_alloced++;
       allocated_blocks[i] = start_block;
@@ -613,7 +677,7 @@ do_work_dis(BitAllocator *alloc)
 
   while (num_iters--) {
       debug_assert(alloc->reserve_blocks(num_blocks));
-      alloced = alloc->alloc_blocks_dis_res(num_blocks, block_list);
+      alloced = alloc->alloc_blocks_dis_res(num_blocks, 0, block_list);
       debug_assert(alloced == num_blocks);
 
       debug_assert(alloc->is_allocated_dis(block_list, num_blocks));