]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: fix incomplete faulty range marking when doing compression 22873/head
authorIgor Fedotov <ifedotov@suse.com>
Thu, 5 Jul 2018 11:27:12 +0000 (14:27 +0300)
committerIgor Fedotov <ifedotov@suse.com>
Thu, 5 Jul 2018 14:47:37 +0000 (17:47 +0300)
GC.

Under some scenarios GC might process an extent range where some inner extents are left untouched by GC (as there is no need for that). Hence GC doesn't invaliate these inner extents with fault_range call. If untouched extents are mapped to unloaded shards it results in subsequent assertion on o->extent_map.dirty_range() call.
The solution is to invalidate the whole extent range when doing GC.

Fixes: https://tracker.ceph.com/issues/23540
Signed-off-by: Igor Fedotov <ifedotov@suse.com>
src/os/bluestore/BlueStore.cc

index c73749ded22d6b6b97c74e9a0cd5736d7ecba841..3bb30477823eea9a06d383a164b4015a67377c53 100644 (file)
@@ -11018,6 +11018,7 @@ int BlueStore::_do_gc(
 {
   auto& extents_to_collect = gc.get_extents_to_collect();
 
+  bool dirty_range_updated = false;
   WriteContext wctx_gc;
   wctx_gc.fork(wctx); // make a clone for garbage collection
 
@@ -11034,12 +11035,17 @@ int BlueStore::_do_gc(
 
     if (*dirty_start > it->offset) {
       *dirty_start = it->offset;
+      dirty_range_updated = true;
     }
 
     if (*dirty_end < it->offset + it->length) {
       *dirty_end = it->offset + it->length;
+      dirty_range_updated = true;
     }
   }
+  if (dirty_range_updated) {
+    o->extent_map.fault_range(db, *dirty_start, *dirty_end);
+  }
 
   dout(30) << __func__ << " alloc write" << dendl;
   int r = _do_alloc_write(txc, c, o, &wctx_gc);
@@ -11121,9 +11127,10 @@ int BlueStore::_do_write(
              << dendl;
         goto out;
       }
+      dout(20)<<__func__<<" gc range is " << std::hex << dirty_start
+             << "~" << dirty_end - dirty_start << std::dec << dendl;
     }
   }
-
   o->extent_map.compress_extent_map(dirty_start, dirty_end - dirty_start);
   o->extent_map.dirty_range(dirty_start, dirty_end - dirty_start);