summaryrefslogtreecommitdiffstats
path: root/src/crimson/os/seastore/root_block.h
diff options
context:
space:
mode:
authorSamuel Just <sjust@redhat.com>2020-06-17 20:46:26 +0200
committerSamuel Just <sjust@redhat.com>2020-06-19 21:59:26 +0200
commit4252b87c1e163382424e14c7406bc08527f271df (patch)
treeff420a817812546be864055f15e95ff356bef8c5 /src/crimson/os/seastore/root_block.h
parentcrimson/os/seastore/lba_manager/btree: move duplicate_for_write (diff)
downloadceph-4252b87c1e163382424e14c7406bc08527f271df.tar.xz
ceph-4252b87c1e163382424e14c7406bc08527f271df.zip
crimson/os/seastore: embed the root pointers directly in the root delta
Previously, I set it up so that there was a "magic" ROOT_LOCATION delta associated with no block type which would point at the root block. As long as replaying the journal yielded at least one of those, we'd therefore be able to find the most recent root block. However, in practice, the entire root block is unlikely to ever weigh in at more than 100 bytes or so. Thus, this patch does a few things: - ROOT_LOCATION deltas are removed - ROOT deltas contain an encoding of the entire root block - ROOT blocks are never actually written down except in these deltas - ROOT blocks do not have a physical address - ROOT blocks never show up in the transaction fresh or mutated lists nor do they show up in the cache extent set or dirty list This adds a little bit of special handling, but the root was already special due to a need for cache interface users to discover it without knowing the physical address. Signed-off-by: Samuel Just <sjust@redhat.com>
Diffstat (limited to 'src/crimson/os/seastore/root_block.h')
-rw-r--r--src/crimson/os/seastore/root_block.h98
1 files changed, 48 insertions, 50 deletions
diff --git a/src/crimson/os/seastore/root_block.h b/src/crimson/os/seastore/root_block.h
index 5a74f10d0f8..acc31eefe95 100644
--- a/src/crimson/os/seastore/root_block.h
+++ b/src/crimson/os/seastore/root_block.h
@@ -9,32 +9,22 @@ namespace crimson::os::seastore {
using depth_t = uint32_t;
-/* Belongs in lba_manager/btree, TODO: generalize this to
- * permit more than one lba_manager implementation
+/**
+ * root_t
+ *
+ * Contains information required to find metadata roots.
+ * TODO: generalize this to permit more than one lba_manager implementation
*/
-struct btree_lba_root_t {
+struct __attribute__((aligned(8), packed)) root_t {
depth_t lba_depth = 0;
depth_t segment_depth = 0;
paddr_t lba_root_addr;
paddr_t segment_root;
- DENC(btree_lba_root_t, v, p) {
- DENC_START(1, 1, p);
- denc(v.lba_depth, p);
- denc(v.segment_depth, p);
- denc(v.lba_root_addr, p);
- denc(v.segment_root, p);
- DENC_FINISH(p);
- }
-};
-
-struct root_block_t {
- btree_lba_root_t lba_root;
-
- DENC(root_block_t, v, p) {
- DENC_START(1, 1, p);
- denc(v.lba_root, p);
- DENC_FINISH(p);
+ void adjust_addrs_from_base(paddr_t base) {
+ if (lba_root_addr.is_relative()) {
+ lba_root_addr = base.add_record_relative(lba_root_addr);
+ }
}
};
@@ -45,26 +35,31 @@ struct root_block_t {
* In-memory values may be
* - absolute: reference to block which predates the current transaction
* - record_relative: reference to block updated in this transaction
- * if !is_initial_pending()
- * - block_relative: reference to block updated in this transaction
- * if is_initial_pending()
+ * if !pending()
*
- * Upon initial commit, on_initial_write checks physical references and updates
- * based on newly discovered address (relative ones must be block_relative).
+ * Journal replay only considers deltas and must always discover the most
+ * recent value for the RootBlock. Because the contents of root_t above are
+ * very small, it's simplest to stash the entire root_t value into the delta
+ * and never actually write the RootBlock to a physical location (safe since
+ * nothing references the location of the RootBlock).
*
- * complete_load also updates addresses in memory post load based on block addr.
+ * As a result, Cache treats the root differently in a few ways including:
+ * - state will only ever be DIRTY or MUTATION_PENDING
+ * - RootBlock's never show up in the transaction fresh or dirty lists --
+ * there's a special Transaction::root member for when the root needs to
+ * be mutated.
*
- * Upon delta commit, on_delta_write uses record addr to update in-memory values.
- * apply_delta will do the same once implemented (TODO).
+ * TODO: Journal trimming will need to be aware of the most recent RootBlock
+ * delta location, or, even easier, just always write one out with the
+ * mutation which changes the journal trim bound.
*/
struct RootBlock : CachedExtent {
constexpr static segment_off_t SIZE = 4<<10;
using Ref = TCachedExtentRef<RootBlock>;
- root_block_t root;
+ root_t root;
- template <typename... T>
- RootBlock(T&&... t) : CachedExtent(std::forward<T>(t)...) {}
+ RootBlock() : CachedExtent(0) {}
RootBlock(const RootBlock &rhs) = default;
@@ -72,41 +67,44 @@ struct RootBlock : CachedExtent {
return CachedExtentRef(new RootBlock(*this));
};
- /**
- * prepare_write
- *
- * For RootBlock, serializes RootBlock::root into the bptr.
- */
- void prepare_write() final;
-
static constexpr extent_types_t TYPE = extent_types_t::ROOT;
extent_types_t get_type() const final {
return extent_types_t::ROOT;
}
+ /// dumps root as delta
ceph::bufferlist get_delta() final {
- return ceph::bufferlist();
+ ceph::bufferlist bl;
+ ceph::buffer::ptr bptr(sizeof(root_t));
+ *reinterpret_cast<root_t*>(bptr.c_str()) = root;
+ bl.append(bptr);
+ return bl;
}
+ /// overwrites root
void apply_delta_and_adjust_crc(paddr_t base, const ceph::bufferlist &_bl) final {
- ceph_assert(0 == "TODO");
+ assert(_bl.length() == sizeof(root_t));
+ ceph::bufferlist bl = _bl;
+ bl.rebuild();
+ root = *reinterpret_cast<const root_t*>(bl.front().c_str());
+ root.adjust_addrs_from_base(base);
}
- /// Patches relative addrs in memory based on actual address
- complete_load_ertr::future<> complete_load() final;
-
/// Patches relative addrs in memory based on record commit addr
- void on_delta_write(paddr_t record_block_offset) final;
+ void on_delta_write(paddr_t record_block_offset) final {
+ root.adjust_addrs_from_base(record_block_offset);
+ }
- /// Patches relative addrs in memory based on record addr
- void on_initial_write() final;
+ complete_load_ertr::future<> complete_load() final {
+ assert(0 == "Root is only written via deltas");
+ }
- btree_lba_root_t &get_lba_root();
+ void on_initial_write() final {
+ assert(0 == "Root is only written via deltas");
+ }
+ root_t &get_lba_root() { return root; }
};
using RootBlockRef = RootBlock::Ref;
}
-
-WRITE_CLASS_DENC(crimson::os::seastore::btree_lba_root_t)
-WRITE_CLASS_DENC(crimson::os::seastore::root_block_t)