]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
6 | #include "crimson/os/seastore/cached_extent.h" | |
7 | ||
8 | namespace crimson::os::seastore { | |
9 | ||
f67539c2 TL |
10 | /** |
11 | * RootBlock | |
12 | * | |
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 | |
17 | * if !pending() | |
18 | * | |
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). | |
24 | * | |
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 | |
29 | * be mutated. | |
30 | * | |
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. | |
34 | */ | |
35 | struct RootBlock : CachedExtent { | |
36 | constexpr static segment_off_t SIZE = 4<<10; | |
37 | using Ref = TCachedExtentRef<RootBlock>; | |
38 | ||
39 | root_t root; | |
40 | ||
41 | RootBlock() : CachedExtent(0) {} | |
42 | ||
43 | RootBlock(const RootBlock &rhs) = default; | |
44 | ||
45 | CachedExtentRef duplicate_for_write() final { | |
46 | return CachedExtentRef(new RootBlock(*this)); | |
47 | }; | |
48 | ||
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; | |
52 | } | |
53 | ||
54 | /// dumps root as delta | |
55 | ceph::bufferlist get_delta() final { | |
56 | ceph::bufferlist bl; | |
57 | ceph::buffer::ptr bptr(sizeof(root_t)); | |
58 | *reinterpret_cast<root_t*>(bptr.c_str()) = root; | |
59 | bl.append(bptr); | |
60 | return bl; | |
61 | } | |
62 | ||
63 | /// overwrites 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; | |
67 | bl.rebuild(); | |
68 | root = *reinterpret_cast<const root_t*>(bl.front().c_str()); | |
69 | root.adjust_addrs_from_base(base); | |
70 | } | |
71 | ||
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); | |
75 | } | |
76 | ||
77 | complete_load_ertr::future<> complete_load() final { | |
78 | ceph_abort_msg("Root is only written via deltas"); | |
79 | } | |
80 | ||
81 | void on_initial_write() final { | |
82 | ceph_abort_msg("Root is only written via deltas"); | |
83 | } | |
84 | ||
85 | root_t &get_root() { return root; } | |
20effc67 | 86 | |
f67539c2 TL |
87 | }; |
88 | using RootBlockRef = RootBlock::Ref; | |
89 | ||
90 | } |