]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: force reshard if new extent spans shard boundary 11451/head
authorSage Weil <sage@redhat.com>
Thu, 13 Oct 2016 13:42:17 +0000 (09:42 -0400)
committerSage Weil <sage@redhat.com>
Thu, 13 Oct 2016 13:42:17 +0000 (09:42 -0400)
A new write may create a new lextent that spans an
existing shard boundary.  If that happens, set a flag
so that we force a reshard when the onode is written.

Signed-off-by: Sage Weil <sage@redhat.com>
src/os/bluestore/BlueStore.cc
src/os/bluestore/BlueStore.h

index 57c6fbbd3a42a12c7501137175f4de131d55fe7d..6d0cf5b67a09898f25b57ec401241ed062759ca2 100644 (file)
@@ -1485,6 +1485,7 @@ BlueStore::ExtentMap::ExtentMap(Onode *o)
 bool BlueStore::ExtentMap::update(Onode *o, KeyValueDB::Transaction t,
                                  bool force)
 {
+  assert(!needs_reshard);
   if (o->onode.extent_map_shards.empty()) {
     if (inline_bl.length() == 0) {
       unsigned n;
@@ -1539,6 +1540,8 @@ bool BlueStore::ExtentMap::update(Onode *o, KeyValueDB::Transaction t,
 
 void BlueStore::ExtentMap::reshard(Onode *o, uint64_t min_alloc_size)
 {
+  needs_reshard = false;
+
   // un-span all blobs
   auto p = spanning_blob_map.begin();
   while (p != spanning_blob_map.end()) {
@@ -2088,6 +2091,9 @@ BlueStore::Extent *BlueStore::ExtentMap::set_lextent(
   b->ref_map.get(offset, length);
   Extent *le = new Extent(logical_offset, offset, length, blob_depth, b);
   extent_map.insert(*le);
+  if (!needs_reshard && spans_shard(offset, length)) {
+    needs_reshard = true;
+  }
   return le;
 }
 
@@ -6128,7 +6134,10 @@ void BlueStore::_txc_write_nodes(TransContext *txc, KeyValueDB::Transaction t)
   // finalize onodes
   for (auto o : txc->onodes) {
     // finalize extent_map shards
-    bool reshard = o->extent_map.update(o.get(), t, false);
+    bool reshard = o->extent_map.needs_reshard;
+    if (!reshard) {
+      reshard = o->extent_map.update(o.get(), t, false);
+    }
     if (reshard) {
       dout(20) << __func__ << "  resharding extents for " << o->oid << dendl;
       for (auto &s : o->extent_map.shards) {
@@ -7261,7 +7270,8 @@ void BlueStore::_do_write_small(
       b->dirty_blob().calc_csum(b_off, padded);
       dout(20) << __func__ << "  lex old " << *ep << dendl;
       Extent *le = o->extent_map.set_lextent(offset, b_off + head_pad, length,
-                                            wctx->blob_depth, b, &wctx->old_extents);
+                                            wctx->blob_depth, b,
+                                            &wctx->old_extents);
       b->dirty_blob().mark_used(le->blob_offset, le->length);
       txc->statfs_delta.stored() += le->length;
       dout(20) << __func__ << "  lex " << *le << dendl;
index 16aaaea85fe096f0b431f060ea12e08c252428f7..689b37939a38620a23857bc6e814e2b507b48d79 100644 (file)
@@ -579,6 +579,8 @@ public:
 
     bufferlist inline_bl;    ///< cached encoded map, if unsharded; empty=>dirty
 
+    bool needs_reshard = false;   ///< true if we must reshard
+
     ExtentMap(Onode *o);
     ~ExtentMap() {
       extent_map.clear_and_dispose([&](Extent *e) { delete e; });
@@ -627,6 +629,22 @@ public:
       return -1; // not found
     }
 
+    /// check if a range spans a shard
+    bool spans_shard(uint32_t offset, uint32_t length) {
+      if (shards.empty()) {
+       return false;
+      }
+      int s = seek_shard(offset);
+      assert(s >= 0);
+      if (s == shards.size() - 1) {
+       return false; // last shard
+      }
+      if (offset + length <= shards[s+1].offset) {
+       return false;
+      }
+      return true;
+    }
+
     /// ensure that a range of the map is loaded
     void fault_range(KeyValueDB *db,
                     uint32_t offset, uint32_t length);