]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
os/bluestore: do garbage collection if blob count is too high.
authorIgor Fedotov <ifedotov@suse.com>
Thu, 23 May 2019 14:11:28 +0000 (17:11 +0300)
committerIgor Fedotov <ifedotov@suse.com>
Fri, 24 May 2019 09:55:46 +0000 (12:55 +0300)
Signed-off-by: Igor Fedotov <ifedotov@suse.com>
src/os/bluestore/BlueStore.cc
src/test/objectstore/store_test.cc

index 6c7985375c7a98bfca9cfdeef645b7ab31d1e363..fad23ce6271a0a8878372175827b071ece115035 100644 (file)
@@ -18,6 +18,8 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include <boost/container/flat_set.hpp>
+
 #include "include/cpp-btree/btree_set.h"
 
 #include "BlueStore.h"
@@ -11517,12 +11519,27 @@ void BlueStore::_do_write_small(
     prev_ep = end; // to avoid this extent check as it's a duplicate
   }
 
+  boost::container::flat_set<const bluestore_blob_t*> inspected_blobs;
+  // We don't want to have more blobs than min alloc units fit
+  // into 2 max blobs
+  size_t blob_threshold = max_blob_size / min_alloc_size * 2 + 1;
+  bool above_blob_threshold = false;
+
+  inspected_blobs.reserve(blob_threshold);
+
+  uint64_t max_off = 0;
+  auto start_ep = ep;
+  auto end_ep = ep; // exclusively
   do {
     any_change = false;
 
     if (ep != end && ep->logical_offset < offset + max_bsize) {
       BlobRef b = ep->blob;
-
+      if (!above_blob_threshold) {
+       inspected_blobs.insert(&b->get_blob());
+       above_blob_threshold = inspected_blobs.size() >= blob_threshold;
+      }
+      max_off = ep->logical_end();
       auto bstart = ep->blob_start();
 
       dout(20) << __func__ << " considering " << *b
@@ -11723,13 +11740,18 @@ void BlueStore::_do_write_small(
        }
       }
       ++ep;
+      end_ep = ep;
       any_change = true;
     } // if (ep != end && ep->logical_offset < offset + max_bsize)
 
     // check extent for reuse in reverse order
     if (prev_ep != end && prev_ep->logical_offset >= min_off) {
       BlobRef b = prev_ep->blob;
-
+      if (!above_blob_threshold) {
+       inspected_blobs.insert(&b->get_blob());
+       above_blob_threshold = inspected_blobs.size() >= blob_threshold;
+      }
+      start_ep = prev_ep;
       auto bstart = prev_ep->blob_start();
       dout(20) << __func__ << " considering " << *b
               << " bstart 0x" << std::hex << bstart << std::dec << dendl;
@@ -11776,6 +11798,24 @@ void BlueStore::_do_write_small(
     } // if (prev_ep != end && prev_ep->logical_offset >= min_off) 
   } while (any_change);
 
+  if (above_blob_threshold) {
+    dout(10) << __func__ << " request GC, blobs >= " << inspected_blobs.size()
+            << " " << std::hex << min_off << "~" << max_off << std::dec
+           << dendl;
+    ceph_assert(start_ep != end_ep);
+    for (auto ep = start_ep; ep != end_ep; ++ep) {
+      dout(20) << __func__ << " inserting for GC "
+              << std::hex << ep->logical_offset << "~" << ep->length
+             << std::dec << dendl;
+
+      wctx->extents_to_gc.union_insert(ep->logical_offset, ep->length);
+    }
+    // insert newly written extent to GC
+    wctx->extents_to_gc.union_insert(offset, length);
+      dout(20) << __func__ << " inserting (last) for GC "
+              << std::hex << offset << "~" << length
+             << std::dec << dendl;
+  }
   // new blob.
   BlobRef b = c->new_blob();
   uint64_t b_off = p2phase<uint64_t>(offset, alloc_len);
@@ -12409,7 +12449,9 @@ int BlueStore::_do_gc(
     bufferlist bl;
     auto offset = (*it).first;
     auto length = (*it).second;
-
+    dout(20) << __func__ << " processing " << std::hex
+            << offset << "~" << length << std::dec
+           << dendl;
     int r = _do_read(c.get(), o, offset, length, bl, 0);
     ceph_assert(r == (int)length);
 
@@ -12470,7 +12512,7 @@ int BlueStore::_do_write(
   uint64_t end = offset + length;
 
   GarbageCollector gc(c->store->cct);
-  int64_t benefit;
+  int64_t benefit = 0;
   auto dirty_start = offset;
   auto dirty_end = end;
 
@@ -12486,8 +12528,8 @@ int BlueStore::_do_write(
   }
 
   if (wctx.extents_to_gc.empty() ||
-      !(wctx.extents_to_gc.range_start() <= offset &&
-        wctx.extents_to_gc.range_end() >= offset + length)) {
+      wctx.extents_to_gc.range_start() > offset ||
+      wctx.extents_to_gc.range_end() < offset + length) {
     benefit = gc.estimate(offset,
                          length,
                          o->extent_map,
@@ -12512,6 +12554,7 @@ int BlueStore::_do_write(
   }
   if (!wctx.extents_to_gc.empty()) {
     dout(20) << __func__ << " perform garbage collection" << dendl;
+
     r = _do_gc(txc, c, o,
       wctx,
       &dirty_start, &dirty_end);
index 0224a91051be66996600071b5282e5edb459501f..7ace015352f6311fb9d24b8322d057e1d5fe2315 100644 (file)
@@ -1318,6 +1318,7 @@ TEST_P(StoreTestSpecificAUSize, BluestoreStatFSTest) {
     return;
   StartDeferred(65536);
   SetVal(g_conf(), "bluestore_compression_mode", "force");
+  SetVal(g_conf(), "bluestore_max_blob_size", "524288");
   // just a big number to disble gc
   SetVal(g_conf(), "bluestore_gc_enable_total_threshold", "100000");
   SetVal(g_conf(), "bluestore_fsck_on_umount", "true");