crimson/seastore: fix potential non-repeatable-read from RootBlock 37271/head
authorYingxin Cheng <yingxin.cheng@intel.com>
Fri, 18 Sep 2020 08:55:03 +0000 (16:55 +0800)
committerYingxin Cheng <yingxin.cheng@intel.com>
Mon, 21 Sep 2020 02:18:55 +0000 (10:18 +0800)
Load root block into the transaction when read it.

Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.com>
src/crimson/os/seastore/cache.cc
src/crimson/os/seastore/transaction.h

index ba49f532fffd6ce37fe7040f0d47aa9da943ad00..e5b98c337efa8964ac049f0716d3c894ebf76d50 100644 (file)
@@ -99,6 +99,8 @@ CachedExtentRef Cache::duplicate_for_write(
 
   auto ret = i->duplicate_for_write();
   if (ret->get_type() == extent_types_t::ROOT) {
+    // root must be loaded before mutate
+    assert(t.root == i);
     t.root = ret->cast<RootBlock>();
   } else {
     ret->last_committed_crc = i->last_committed_crc;
@@ -246,8 +248,10 @@ void Cache::init() {
 
 Cache::mkfs_ertr::future<> Cache::mkfs(Transaction &t)
 {
-  duplicate_for_write(t, root);
-  return mkfs_ertr::now();
+  return get_root(t).safe_then([this, &t](auto croot) {
+    duplicate_for_write(t, croot);
+    return mkfs_ertr::now();
+  });
 }
 
 Cache::close_ertr::future<> Cache::close()
@@ -299,7 +303,8 @@ Cache::get_root_ret Cache::get_root(Transaction &t)
       t.root);
   } else {
     auto ret = root;
-    return ret->wait_io().then([ret] {
+    return ret->wait_io().then([ret, &t] {
+      t.root = ret;
       return get_root_ret(
        get_root_ertr::ready_future_marker{},
        ret);
index 8a01c99b7dee1888b0d20c212c748c5f362a684b..60d295820ebbc54f2023e717a1831f7183d94d84 100644 (file)
@@ -19,7 +19,7 @@ namespace crimson::os::seastore {
 class Transaction {
   friend class Cache;
 
-  RootBlockRef root;        ///< ref to root if mutated by transaction
+  RootBlockRef root;        ///< ref to root if read or written by transaction
 
   segment_off_t offset = 0; ///< relative offset of next block