namespace crimson::os::seastore {
-size_t Onode::size() const
-{
- return ceph::encoded_sizeof(*this);
-}
-
-void Onode::encode(void* buffer, size_t len)
-{
- struct [[gnu::packed]] encoded_t {
- uint8_t struct_v;
- uint8_t struct_compat;
- uint32_t struct_len;
- uint32_t len;
- char data[];
- };
- auto p = reinterpret_cast<encoded_t*>(buffer);
- assert(std::numeric_limits<uint16_t>::max() >= size());
- assert(len >= size());
- p->struct_v = 1;
- p->struct_compat = 1;
- p->struct_len = sizeof(encoded_t) + payload.size();
- p->len = payload.size();
- std::memcpy(p->data, payload.data(), payload.size());
-}
-
-bool operator==(const Onode& lhs, const Onode& rhs)
-{
- return lhs.get() == rhs.get();
-}
-
std::ostream& operator<<(std::ostream &out, const Onode &rhs)
{
- return out << rhs.get();
+ auto &layout = rhs.get_layout();
+ return out << "Onode("
+ << "size=" << static_cast<uint32_t>(layout.size)
+ << ")";
}
}
#include "include/buffer.h"
#include "include/denc.h"
+#include "crimson/os/seastore/transaction.h"
+
namespace crimson::os::seastore {
-// in-memory onode, in addition to the stuff that should be persisted to disk,
-// it may contain intrusive hooks for LRU, rw locks etc
+struct __attribute__((packed)) onode_layout_t {
+ ceph_le32 size = init_le32(0);
+ omap_root_le_t omap_root;
+} __attribute__((packed));
+
+/**
+ * Onode
+ *
+ * Interface manipulated by seastore. OnodeManager implementations should
+ * return objects derived from this interface with layout referencing
+ * internal representation of onode_layout_t.
+ */
class Onode : public boost::intrusive_ref_counter<
Onode,
boost::thread_unsafe_counter>
{
public:
- Onode(std::string_view s)
- : payload{s}
- {}
- size_t size() const;
- const std::string& get() const {
- return payload;
- }
- void encode(void* buffer, size_t len);
- DENC(Onode, v, p) {
- DENC_START(1, 1, p);
- denc(v.payload, p);
- DENC_FINISH(p);
- }
-
-private:
- // dummy payload
- std::string payload;
+
+ virtual const onode_layout_t &get_layout() const = 0;
+ virtual onode_layout_t &get_mutable_layout(Transaction &t) = 0;
+ virtual ~Onode() = default;
};
-bool operator==(const Onode& lhs, const Onode& rhs);
+
std::ostream& operator<<(std::ostream &out, const Onode &rhs);
using OnodeRef = boost::intrusive_ptr<Onode>;
}
-
-WRITE_CLASS_DENC(crimson::os::seastore::Onode)
namespace crimson::os::seastore {
class OnodeManager {
+ using base_ertr = TransactionManager::base_ertr;
public:
- using open_ertr = crimson::errorator<
- crimson::ct_error::input_output_error>;
- virtual open_ertr::future<OnodeRef> get_or_create_onode(
+ using mkfs_ertr = TransactionManager::mkfs_ertr;
+ using mkfs_ret = mkfs_ertr::future<>;
+ virtual mkfs_ret mkfs(Transaction &t) = 0;
+
+ using get_onode_ertr = base_ertr::extend<
+ crimson::ct_error::enoent>;
+ using get_onode_ret = get_onode_ertr::future<
+ OnodeRef>;
+ virtual get_onode_ret get_onode(
+ Transaction &trans,
+ const ghobject_t &hoid) {
+ return seastar::make_ready_future<OnodeRef>();
+ }
+
+ using get_or_create_onode_ertr = base_ertr;
+ using get_or_create_onode_ret = get_or_create_onode_ertr::future<
+ OnodeRef>;
+ virtual get_or_create_onode_ret get_or_create_onode(
Transaction &trans,
const ghobject_t &hoid) {
- return open_ertr::make_ready_future<OnodeRef>();
+ return seastar::make_ready_future<OnodeRef>();
}
- virtual open_ertr::future<std::vector<OnodeRef>> get_or_create_onodes(
+
+ using get_or_create_onodes_ertr = base_ertr;
+ using get_or_create_onodes_ret = get_or_create_onodes_ertr::future<
+ std::vector<OnodeRef>>;
+ virtual get_or_create_onodes_ret get_or_create_onodes(
Transaction &trans,
const std::vector<ghobject_t> &hoids) {
- return open_ertr::make_ready_future<std::vector<OnodeRef>>();
+ return seastar::make_ready_future<std::vector<OnodeRef>>();
}
- using write_ertr= crimson::errorator<
- crimson::ct_error::input_output_error>;
- virtual write_ertr::future<> write_dirty(
+ using write_dirty_ertr = base_ertr;
+ using write_dirty_ret = write_dirty_ertr::future<>;
+ virtual write_dirty_ret write_dirty(
Transaction &trans,
const std::vector<OnodeRef> &onodes) {
- return write_ertr::now();
+ return seastar::now();
}
virtual ~OnodeManager() {}
};
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "crimson/os/seastore/onode_manager/staged-fltree/fltree_onode_manager.h"
+
+namespace {
+[[maybe_unused]] seastar::logger& logger() {
+ return crimson::get_logger(ceph_subsys_test);
+}
+}
+
+namespace crimson::os::seastore::onode {
+
+FLTreeOnodeManager::get_onode_ret FLTreeOnodeManager::get_onode(
+ Transaction &trans,
+ const ghobject_t &hoid) {
+ return tree.find(
+ trans, hoid
+ ).safe_then([this, &trans, &hoid](auto cursor)
+ -> get_onode_ret {
+ if (cursor == tree.end()) {
+ logger().debug(
+ "FLTreeOnodeManager::{}: no entry for {}",
+ __func__,
+ hoid);
+ return crimson::ct_error::enoent::make();
+ }
+ auto val = OnodeRef(new FLTreeOnode(cursor.value()));
+ return seastar::make_ready_future<OnodeRef>(
+ val
+ );
+ }).handle_error(
+ get_onode_ertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in FLTreeOnodeManager::get_onode"
+ }
+ );
+}
+
+FLTreeOnodeManager::get_or_create_onode_ret
+FLTreeOnodeManager::get_or_create_onode(
+ Transaction &trans,
+ const ghobject_t &hoid) {
+ return tree.insert(
+ trans, hoid,
+ OnodeTree::tree_value_config_t{sizeof(onode_layout_t)}
+ ).safe_then([this, &trans, &hoid](auto p)
+ -> get_or_create_onode_ret {
+ auto [cursor, created] = std::move(p);
+ auto val = OnodeRef(new FLTreeOnode(cursor.value()));
+ if (created) {
+ logger().debug(
+ "FLTreeOnodeManager::{}: created onode for entry for {}",
+ __func__,
+ hoid);
+ val->get_mutable_layout(trans) = onode_layout_t{};
+ }
+ return seastar::make_ready_future<OnodeRef>(
+ val
+ );
+ }).handle_error(
+ get_or_create_onode_ertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in FLTreeOnodeManager::get_or_create_onode"
+ }
+ );
+}
+
+FLTreeOnodeManager::get_or_create_onodes_ret
+FLTreeOnodeManager::get_or_create_onodes(
+ Transaction &trans,
+ const std::vector<ghobject_t> &hoids) {
+ return seastar::do_with(
+ std::vector<OnodeRef>(),
+ [this, &hoids, &trans](auto &ret) {
+ ret.reserve(hoids.size());
+ return crimson::do_for_each(
+ hoids,
+ [this, &trans, &ret](auto &hoid) {
+ return get_or_create_onode(trans, hoid
+ ).safe_then([this, &ret](auto &&onoderef) {
+ ret.push_back(std::move(onoderef));
+ });
+ }).safe_then([&ret] {
+ return std::move(ret);
+ });
+ });
+}
+
+FLTreeOnodeManager::write_dirty_ret FLTreeOnodeManager::write_dirty(
+ Transaction &trans,
+ const std::vector<OnodeRef> &onodes) {
+ return crimson::do_for_each(
+ onodes,
+ [this, &trans](auto &onode) -> OnodeTree::btree_future<> {
+ auto &flonode = static_cast<FLTreeOnode&>(*onode);
+ switch (flonode.status) {
+ case FLTreeOnode::status_t::MUTATED: {
+ flonode.populate_recorder(trans);
+ return seastar::now();
+ }
+ case FLTreeOnode::status_t::DELETED: {
+ return tree.erase(trans, flonode).safe_then([](auto) {});
+ }
+ case FLTreeOnode::status_t::STABLE: {
+ return seastar::now();
+ }
+ default:
+ __builtin_unreachable();
+ }
+ }).handle_error(
+ write_dirty_ertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in FLTreeOnodeManager::write_dirty"
+ }
+ );
+}
+
+FLTreeOnodeManager::~FLTreeOnodeManager() {}
+
+}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include "crimson/os/seastore/onode_manager.h"
+#include "crimson/os/seastore/onode_manager/staged-fltree/node_extent_manager/seastore.h"
+#include "crimson/os/seastore/onode_manager/staged-fltree/value.h"
+#include "crimson/os/seastore/onode_manager/staged-fltree/tree.h"
+
+namespace crimson::os::seastore::onode {
+
+struct FLTreeOnode : Onode, Value {
+ static constexpr value_magic_t HEADER_MAGIC = value_magic_t::ONODE;
+
+ enum class status_t {
+ STABLE,
+ MUTATED,
+ DELETED
+ } status = status_t::STABLE;
+
+ FLTreeOnode(FLTreeOnode&&) = default;
+ FLTreeOnode& operator=(FLTreeOnode&&) = delete;
+
+ FLTreeOnode(const FLTreeOnode&) = default;
+ FLTreeOnode& operator=(const FLTreeOnode&) = delete;
+
+ template <typename... T>
+ FLTreeOnode(T&&... args) : Value(std::forward<T>(args)...) {}
+
+ struct Recorder : public ValueDeltaRecorder {
+ Recorder(bufferlist &bl) : ValueDeltaRecorder(bl) {}
+
+ value_magic_t get_header_magic() const final {
+ return value_magic_t::ONODE;
+ }
+
+ void apply_value_delta(
+ ceph::bufferlist::const_iterator&,
+ NodeExtentMutable&,
+ laddr_t) final {
+ // TODO
+ }
+ };
+
+ const onode_layout_t &get_layout() const final {
+ return *read_payload<onode_layout_t>();
+ }
+
+ onode_layout_t &get_mutable_layout(Transaction &t) final {
+ auto p = prepare_mutate_payload<
+ onode_layout_t,
+ Recorder>(t);
+ status = status_t::MUTATED;
+ return *reinterpret_cast<onode_layout_t*>(p.first.get_write());
+ };
+
+ void populate_recorder(Transaction &t) {
+ auto p = prepare_mutate_payload<
+ onode_layout_t,
+ Recorder>(t);
+ status = status_t::STABLE;
+ // TODO: fill in recorder
+ }
+
+ ~FLTreeOnode() final {}
+};
+
+using OnodeTree = Btree<FLTreeOnode>;
+
+class FLTreeOnodeManager : public crimson::os::seastore::OnodeManager {
+ OnodeTree tree;
+
+public:
+ FLTreeOnodeManager(TransactionManager &tm) :
+ tree(std::make_unique<SeastoreNodeExtentManager>(
+ tm, laddr_t{})) {}
+
+ mkfs_ret mkfs(Transaction &t) {
+ return tree.mkfs(t
+ ).handle_error(
+ mkfs_ertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in FLTreeOnodeManager::mkfs"
+ }
+ );
+ }
+
+ get_onode_ret get_onode(
+ Transaction &trans,
+ const ghobject_t &hoid) final;
+
+ get_or_create_onode_ret get_or_create_onode(
+ Transaction &trans,
+ const ghobject_t &hoid) final;
+
+ get_or_create_onodes_ret get_or_create_onodes(
+ Transaction &trans,
+ const std::vector<ghobject_t> &hoids) final;
+
+ write_dirty_ret write_dirty(
+ Transaction &trans,
+ const std::vector<OnodeRef> &onodes) final;
+
+ ~FLTreeOnodeManager();
+};
+
+}
return btree_ertr::make_ready_future<size_t>(0u);
}
- btree_future<Cursor> erase(Cursor& pos) {
+ btree_future<Cursor> erase(Transaction &t, Cursor& pos) {
// TODO
return btree_ertr::make_ready_future<Cursor>(
Cursor::make_end(this));
}
- btree_future<Cursor> erase(Cursor& first, Cursor& last) {
+ btree_future<Cursor> erase(Transaction &t, Cursor& first, Cursor& last) {
+ // TODO
+ return btree_ertr::make_ready_future<Cursor>(
+ Cursor::make_end(this));
+ }
+
+ btree_future<Cursor> erase(Transaction &t, Value &value) {
// TODO
return btree_ertr::make_ready_future<Cursor>(
Cursor::make_end(this));