]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore: clean up meta implementation
authorSamuel Just <sjust@redhat.com>
Wed, 28 Apr 2021 07:24:00 +0000 (00:24 -0700)
committerSamuel Just <sjust@redhat.com>
Fri, 7 May 2021 07:36:40 +0000 (00:36 -0700)
There's really no reason to cache the decoded representation here since
the meta keys are only accessed during startup, mkfs.  This approach is
much simpler.

Signed-off-by: Samuel Just <sjust@redhat.com>
src/crimson/os/seastore/root_block.h
src/crimson/os/seastore/seastore.cc
src/crimson/os/seastore/seastore_types.h
src/crimson/os/seastore/transaction_manager.h

index fe7bdf993168d7fa0d89a033bf54bb4abe1cef42..3144edb82512183f3048bbd9864006f6fb4175ed 100644 (file)
@@ -38,8 +38,6 @@ struct RootBlock : CachedExtent {
 
   root_t root;
 
-  std::map<std::string, std::string> meta;
-
   RootBlock() : CachedExtent(0) {}
 
   RootBlock(const RootBlock &rhs) = default;
@@ -68,11 +66,6 @@ struct RootBlock : CachedExtent {
     ceph::bufferlist bl = _bl;
     bl.rebuild();
     root = *reinterpret_cast<const root_t*>(bl.front().c_str());
-    if (root.have_meta) {
-      ceph::bufferlist meta_bl;
-      meta_bl.rebuild(ceph::buffer::ptr_node::create(&root.meta[0], root_t::MAX_META_LENGTH));
-      decode(meta, meta_bl);
-    }
     root.adjust_addrs_from_base(base);
   }
 
index 814bde35eff77df5ee8ddad43f8e880ad5bdf4ea..8455a94e033e41ef869216635c982cfc64898644 100644 (file)
@@ -997,41 +997,51 @@ seastar::future<> SeaStore::write_meta(const std::string& key,
 {
   LOG_PREFIX(SeaStore::write_meta);
   DEBUG("key: {}; value: {}", key, value);
-  return seastar::do_with(key, value,
-    [this](auto& key, auto& value) {
-    return repeat_eagain([this, &key, &value] {
-      auto t = transaction_manager->create_transaction();
-      return transaction_manager->get_root(*t).safe_then(
-        [this, t=std::move(t), &key, &value](auto root) mutable {
-        transaction_manager->update_root_meta(*t, key, value);
-        return transaction_manager->submit_transaction(std::move(t));
+  return seastar::do_with(
+    TransactionRef(),
+    key,
+    value,
+    [this, FNAME](auto &t, auto& key, auto& value) {
+      return repeat_eagain([this, FNAME, &t, &key, &value] {
+       t = transaction_manager->create_transaction();
+       DEBUGT("Have transaction, key: {}; value: {}", *t, key, value);
+        return transaction_manager->update_root_meta(
+         *t, key, value
+       ).safe_then([this, &t] {
+         return transaction_manager->submit_transaction(std::move(t));
+       });
       });
-    });
-  }).handle_error(
-    crimson::ct_error::assert_all{"Invalid error in Seastar::write_meta"}
-  );
+    }).handle_error(
+      crimson::ct_error::assert_all{"Invalid error in SeaStore::write_meta"}
+    );
 }
 
 seastar::future<std::tuple<int, std::string>> SeaStore::read_meta(const std::string& key)
 {
   LOG_PREFIX(SeaStore::read_meta);
   DEBUG("key: {}", key);
-  return seastar::do_with(transaction_manager->create_transaction(), key,
-    [this](auto& t, auto& key) {
-    return transaction_manager->get_root(*t).safe_then(
-      [this, &key](auto root) {
-      auto& meta = root->meta;
-      auto it = meta.find(key);
-      if (it != meta.end()) {
-        return seastar::make_ready_future<std::tuple<int, std::string>>(
-          std::make_tuple(0, it->second));
-      }
-      return seastar::make_ready_future<std::tuple<int, std::string>>(
-        std::make_tuple(-1, std::string("")));
-    });
-  }).handle_error(
-    crimson::ct_error::assert_all{"Invalid error in Seastar::write_meta"}
-  );
+  return seastar::do_with(
+    std::tuple<int, std::string>(),
+    TransactionRef(),
+    key,
+    [this](auto &ret, auto &t, auto& key) {
+      return repeat_eagain([this, &ret, &t, &key] {
+       t = transaction_manager->create_transaction();
+       return transaction_manager->read_root_meta(
+         *t, key
+       ).safe_then([&ret](auto v) {
+         if (v) {
+           ret = std::make_tuple(0, std::move(*v));
+         } else {
+           ret = std::make_tuple(-1, std::string(""));
+         }
+       });
+      }).safe_then([&ret] {
+       return std::move(ret);
+      });
+    }).handle_error(
+      crimson::ct_error::assert_all{"Invalid error in SeaStore::read_meta"}
+    );
 }
 
 uuid_d SeaStore::get_fsid() const
index 9b0e43fb801b55436749b07ff3d2c6112be3c53c..c2bd7d3cbef8fe209b3c9be638b10db8fb9f1473 100644 (file)
@@ -655,18 +655,42 @@ public:
  * TODO: generalize this to permit more than one lba_manager implementation
  */
 struct __attribute__((packed)) root_t {
+  using meta_t = std::map<std::string, std::string>;
 
   static constexpr int MAX_META_LENGTH = 1024;
 
   lba_root_t lba_root;
   laddr_le_t onode_root;
   coll_root_le_t collection_root;
+
   char meta[MAX_META_LENGTH];
-  bool have_meta = false;
+
+  root_t() {
+    set_meta(meta_t{});
+  }
 
   void adjust_addrs_from_base(paddr_t base) {
     lba_root.adjust_addrs_from_base(base);
   }
+
+  meta_t get_meta() {
+    bufferlist bl;
+    bl.append(ceph::buffer::create_static(MAX_META_LENGTH, meta));
+    meta_t ret;
+    auto iter = bl.cbegin();
+    decode(ret, iter);
+    return ret;
+  }
+
+  void set_meta(const meta_t &m) {
+    ceph::bufferlist bl;
+    encode(m, bl);
+    ceph_assert(bl.length() < MAX_META_LENGTH);
+    bl.rebuild();
+    auto &bptr = bl.front();
+    ::memset(meta, 0, MAX_META_LENGTH);
+    ::memcpy(meta, bptr.c_str(), bl.length());
+  }
 };
 
 }
index 07125396d0b024858f09f1b7cd5874ba6f27f768..75f0ed6537ead4fd15d0490ef3354c0eedfa2188 100644 (file)
@@ -373,50 +373,52 @@ public:
   }
 
   /**
-   * get_root
+   * read_root_meta
    *
-   * Get root block's ondisk layout
+   * Read root block meta entry for key.
    */
-  using get_root_ertr = base_ertr;
-  using get_root_ret = get_root_ertr::future<RootBlockRef>;
-  get_root_ret get_root(Transaction &t) {
-    return cache->get_root(t);
+  using read_root_meta_ertr = base_ertr;
+  using read_root_meta_bare = std::optional<std::string>;
+  using read_root_meta_ret = read_root_meta_ertr::future<
+    read_root_meta_bare>;
+  read_root_meta_ret read_root_meta(
+    Transaction &t,
+    const std::string &key) {
+    return cache->get_root(
+      t
+    ).safe_then([&key](auto root) {
+      auto meta = root->root.get_meta();
+      auto iter = meta.find(key);
+      if (iter == meta.end()) {
+       return seastar::make_ready_future<read_root_meta_bare>(std::nullopt);
+      } else {
+       return seastar::make_ready_future<read_root_meta_bare>(iter->second);
+      }
+    });
   }
 
   /**
    * update_root_meta
    *
-   * modify root block's meta field
+   * Update root block meta entry for key to value.
    */
-  using update_root_meta_ertr = base_ertr::extend<
-    crimson::ct_error::value_too_large>;
+  using update_root_meta_ertr = base_ertr;
   using update_root_meta_ret = update_root_meta_ertr::future<>;
-  update_root_meta_ret update_root_meta(Transaction& t,
-                                        const std::string& key,
-                                        const std::string& value) {
-    auto root = cache->get_root_fast(t);
-    root = cache->duplicate_for_write(t, root)->cast<RootBlock>();
-    root->meta[key] = value;
-
-    // calculate meta size
-    // TODO: we probably need a uniformal interface for calcuting
-    // the encoded size of data structures
-    uint32_t meta_size = 4; // initial 4 bytes for std::map size
-    for (auto& [key, val] : root->meta) {
-      // sizes of length fields for key and val + sizes of key and val
-      meta_size += 8 + key.length() + val.length();
-    }
-
-    if (meta_size > root_t::MAX_META_LENGTH) {
-      return crimson::ct_error::value_too_large::make();
-    }
-
-    ceph::bufferlist bl(1);
-    bl.rebuild(ceph::buffer::ptr_node::create(
-      &root->get_root().meta[0], root_t::MAX_META_LENGTH));
-    encode(root->meta, bl);
-    root->get_root().have_meta = true;
-    return update_root_meta_ertr::now();
+  update_root_meta_ret update_root_meta(
+    Transaction& t,
+    const std::string& key,
+    const std::string& value) {
+    return cache->get_root(
+      t
+    ).safe_then([this, &t, &key, &value](RootBlockRef root) {
+      root = cache->duplicate_for_write(t, root)->cast<RootBlock>();
+
+      auto meta = root->root.get_meta();
+      meta[key] = value;
+
+      root->root.set_meta(meta);
+      return seastar::now();
+    });
   }
 
   /**