]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/os/seastore: add write/read_meta methods for seastore
authorXuehan Xu <xxhdx1985126@gmail.com>
Tue, 6 Apr 2021 08:42:04 +0000 (16:42 +0800)
committerXuehan Xu <xxhdx1985126@gmail.com>
Fri, 23 Apr 2021 03:32:57 +0000 (11:32 +0800)
Signed-off-by: Xuehan Xu <xxhdx1985126@gmail.com>
src/crimson/os/seastore/cache.cc
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.h
src/crimson/os/seastore/transaction_manager.h

index 9c6ff428a5c4e2ff4477b2ddbf8aaf75053a5578..ea0fb10b5ddd3a9ef495c30775022ab857bd83a8 100644 (file)
@@ -209,8 +209,9 @@ std::optional<record_t> Cache::try_construct_record(Transaction &t)
 {
   // First, validate read set
   for (auto &i: t.read_set) {
-    if (i->state == CachedExtent::extent_state_t::INVALID)
+    if (i->state == CachedExtent::extent_state_t::INVALID) {
       return std::nullopt;
+    }
   }
 
   record_t record;
index 57d64ad7ca13513085932d861346c1871d005526..fe7bdf993168d7fa0d89a033bf54bb4abe1cef42 100644 (file)
@@ -38,6 +38,8 @@ struct RootBlock : CachedExtent {
 
   root_t root;
 
+  std::map<std::string, std::string> meta;
+
   RootBlock() : CachedExtent(0) {}
 
   RootBlock(const RootBlock &rhs) = default;
@@ -66,6 +68,11 @@ 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);
   }
 
@@ -83,6 +90,7 @@ struct RootBlock : CachedExtent {
   }
 
   root_t &get_root() { return root; }
+
 };
 using RootBlockRef = RootBlock::Ref;
 
index b44a3290b91f386cb13419eee2c24d44f5f39c1c..8a477b591d8d2a16b8e83319568b9f48141a567a 100644 (file)
@@ -911,13 +911,41 @@ boost::intrusive_ptr<SeastoreCollection> SeaStore::_get_collection(const coll_t&
 seastar::future<> SeaStore::write_meta(const std::string& key,
                                        const std::string& value)
 {
-  return seastar::make_ready_future<>();
+  logger().debug("{}, key: {}; value: {}", __func__, 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));
+      });
+    });
+  }).handle_error(
+    crimson::ct_error::assert_all{"Invalid error in Seastar::write_meta"}
+  );
 }
 
 seastar::future<std::tuple<int, std::string>> SeaStore::read_meta(const std::string& key)
 {
-  return seastar::make_ready_future<std::tuple<int, std::string>>(
-    std::make_tuple(0, ""s));
+  logger().debug("{}, key: {}", __func__, 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"}
+  );
 }
 
 uuid_d SeaStore::get_fsid() const
index 59b329c0fcce89989d8647adab192c898de72c34..9b0e43fb801b55436749b07ff3d2c6112be3c53c 100644 (file)
@@ -655,9 +655,14 @@ public:
  * TODO: generalize this to permit more than one lba_manager implementation
  */
 struct __attribute__((packed)) root_t {
+
+  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;
 
   void adjust_addrs_from_base(paddr_t base) {
     lba_root.adjust_addrs_from_base(base);
index d17907a3fa98cb1646823a68f1880d3dee959299..7a46e5c299374efff472e5137dae7e09f8ad25fb 100644 (file)
@@ -15,6 +15,7 @@
 namespace crimson::os::seastore {
 
 struct retired_extent_gate_t;
+class SeaStore;
 
 /**
  * Transaction
@@ -161,6 +162,8 @@ public:
       write_set.erase(*i++);
     }
   }
+
+  friend class crimson::os::seastore::SeaStore;
 };
 using TransactionRef = Transaction::Ref;
 
index a49af8c9e5ca1cece71fe2f2198f185a31cdf606..68736657f09a23b769584e109605f6172a0aeb7a 100644 (file)
@@ -374,6 +374,53 @@ public:
     return segment_manager.release(id);
   }
 
+  /**
+   * get_root
+   *
+   * Get root block's ondisk layout
+   */
+  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);
+  }
+
+  /**
+   * update_root_meta
+   *
+   * modify root block's meta field
+   */
+  using update_root_meta_ertr = base_ertr::extend<
+    crimson::ct_error::value_too_large>;
+  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();
+  }
+
   /**
    * read_onode_root
    *