1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
6 #include "crimson/os/seastore/cached_extent.h"
8 namespace crimson::os::seastore
{
13 * Holds the physical addresses of all metadata roots.
14 * In-memory values may be
15 * - absolute: reference to block which predates the current transaction
16 * - record_relative: reference to block updated in this transaction
19 * Journal replay only considers deltas and must always discover the most
20 * recent value for the RootBlock. Because the contents of root_t above are
21 * very small, it's simplest to stash the entire root_t value into the delta
22 * and never actually write the RootBlock to a physical location (safe since
23 * nothing references the location of the RootBlock).
25 * As a result, Cache treats the root differently in a few ways including:
26 * - state will only ever be DIRTY or MUTATION_PENDING
27 * - RootBlock's never show up in the transaction fresh or dirty lists --
28 * there's a special Transaction::root member for when the root needs to
31 * TODO: Journal trimming will need to be aware of the most recent RootBlock
32 * delta location, or, even easier, just always write one out with the
33 * mutation which changes the journal trim bound.
35 struct RootBlock
: CachedExtent
{
36 constexpr static segment_off_t SIZE
= 4<<10;
37 using Ref
= TCachedExtentRef
<RootBlock
>;
41 RootBlock() : CachedExtent(0) {}
43 RootBlock(const RootBlock
&rhs
) = default;
45 CachedExtentRef
duplicate_for_write() final
{
46 return CachedExtentRef(new RootBlock(*this));
49 static constexpr extent_types_t TYPE
= extent_types_t::ROOT
;
50 extent_types_t
get_type() const final
{
51 return extent_types_t::ROOT
;
54 /// dumps root as delta
55 ceph::bufferlist
get_delta() final
{
57 ceph::buffer::ptr
bptr(sizeof(root_t
));
58 *reinterpret_cast<root_t
*>(bptr
.c_str()) = root
;
64 void apply_delta_and_adjust_crc(paddr_t base
, const ceph::bufferlist
&_bl
) final
{
65 assert(_bl
.length() == sizeof(root_t
));
66 ceph::bufferlist bl
= _bl
;
68 root
= *reinterpret_cast<const root_t
*>(bl
.front().c_str());
69 root
.adjust_addrs_from_base(base
);
72 /// Patches relative addrs in memory based on record commit addr
73 void on_delta_write(paddr_t record_block_offset
) final
{
74 root
.adjust_addrs_from_base(record_block_offset
);
77 complete_load_ertr::future
<> complete_load() final
{
78 ceph_abort_msg("Root is only written via deltas");
81 void on_initial_write() final
{
82 ceph_abort_msg("Root is only written via deltas");
85 root_t
&get_root() { return root
; }
88 using RootBlockRef
= RootBlock::Ref
;