]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: fix inappropriate ENOSPC from avl/hybrid allocator 38438/head
authorIgor Fedotov <ifedotov@suse.com>
Thu, 3 Dec 2020 19:08:43 +0000 (22:08 +0300)
committerIgor Fedotov <ifedotov@suse.com>
Fri, 4 Dec 2020 12:10:49 +0000 (15:10 +0300)
Under high fragmentation circumstances (in best-fit mode) these allocators might fail to
return continuous(longer than a single alloc unit) extents. Occurs when
requested size is longer than the maximum available extents and these
extents are unaligned with alloc unit. The latter results in the actual lengths of these extens are shorter
than the requested length and they do not match to the lookup. Which
finally causes no allocation at all.

Fixes: https://tracker.ceph.com/issues/47883
Signed-off-by: Igor Fedotov <ifedotov@suse.com>
src/os/bluestore/AvlAllocator.cc
src/test/objectstore/Allocator_test.cc

index 3a1f66f7f2bced35cfc4294afa5eeeaaa0ecee94..ba4ec4ee28190004cb0aa47cdbadc9193ef6457b 100644 (file)
@@ -240,7 +240,15 @@ int AvlAllocator::_allocate(
       max_size < range_size_alloc_threshold ||
       free_pct < range_size_alloc_free_pct) {
     *cursor = 0;
-    start = _block_picker(range_size_tree, cursor, size, unit);
+    do {
+      start = _block_picker(range_size_tree, cursor, size, unit);
+      if (start != -1ULL || !force_range_size_alloc) {
+        break;
+      }
+      // try to collect smaller extents as we could fail to retrieve
+      // that large block due to misaligned extents
+      size = p2align(size >> 1, unit);
+    } while (size >= unit);
   } else {
     start = _block_picker(range_tree, cursor, size, unit);
   }
index 21e7318889a6e7eb648ce241ed23f986e6610acb..43f2fbf51ecaf8106c41ebb7581c8125db12e6d3 100644 (file)
@@ -482,6 +482,24 @@ TEST_P(AllocTest, test_alloc_contiguous)
   alloc->shutdown();
 }
 
+TEST_P(AllocTest, test_alloc_47883)
+{
+  uint64_t block = 0x1000;
+  uint64_t size = 1599858540544ul;
+
+  init_alloc(size, block);
+
+  alloc->init_add_free(0x1b970000, 0x26000);
+  alloc->init_add_free(0x1747e9d5000, 0x493000);
+  alloc->init_add_free(0x1747ee6a000, 0x196000);
+
+  PExtentVector extents;
+  auto need = 0x3f980000;
+  auto got = alloc->allocate(need, 0x10000, 0, (int64_t)0, &extents);
+  EXPECT_GT(got, 0);
+  EXPECT_EQ(got, 0x630000);
+}
+
 INSTANTIATE_TEST_SUITE_P(
   Allocator,
   AllocTest,