]>
git.proxmox.com Git - ceph.git/blob - ceph/src/crimson/os/seastore/journal/circular_journal_space.h
c88b65ad5e6b3ada736574222438a5b48a9c6384
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
2 // vim: ts=8 sw=2 smarttab expandtab
7 #include <seastar/core/circular_buffer.hh>
8 #include <seastar/core/metrics.hh>
9 #include <seastar/core/shared_future.hh>
11 #include "include/buffer.h"
13 #include "crimson/common/errorator.h"
14 #include "crimson/os/seastore/journal.h"
15 #include "crimson/os/seastore/random_block_manager.h"
16 #include "crimson/os/seastore/random_block_manager/rbm_device.h"
17 #include "crimson/os/seastore/journal/record_submitter.h"
18 #include "crimson/os/seastore/async_cleaner.h"
20 namespace crimson::os::seastore
{
21 class SegmentProvider
;
25 namespace crimson::os::seastore::journal
{
27 class CircularBoundedJournal
;
28 class CircularJournalSpace
: public JournalAllocator
{
31 const std::string
& get_name() const final
{
35 extent_len_t
get_block_size() const final
;
37 bool can_write() const final
{
38 return (device
!= nullptr);
41 segment_nonce_t
get_nonce() const final
{
45 bool needs_roll(std::size_t length
) const final
;
47 roll_ertr::future
<> roll() final
;
49 write_ret
write(ceph::bufferlist
&& to_write
) final
;
51 void update_modify_time(record_t
& record
) final
{}
53 close_ertr::future
<> close() final
{
55 ).safe_then([this]() -> close_ertr::future
<> {
57 return close_ertr::now();
59 Journal::open_for_mount_ertr::pass_further
{},
60 crimson::ct_error::assert_all
{
61 "Invalid error write_header"
66 open_ret
open(bool is_mkfs
) final
;
69 CircularJournalSpace(RBMDevice
* device
);
72 using write_ertr
= Journal::submit_record_ertr
;
76 * @param device address to write
77 * @param bufferlist to write
80 write_ertr::future
<> device_write_bl(rbm_abs_addr offset
, ceph::bufferlist
&bl
);
82 using read_ertr
= crimson::errorator
<
83 crimson::ct_error::input_output_error
,
84 crimson::ct_error::invarg
,
85 crimson::ct_error::enoent
,
86 crimson::ct_error::erange
>;
87 using read_header_ertr
= read_ertr
;
88 using read_header_ret
= read_header_ertr::future
<
89 std::optional
<std::pair
<cbj_header_t
, bufferlist
>>
94 * read header block from given absolute address
96 * @param absolute address
99 read_header_ret
read_header();
101 ceph::bufferlist
encode_header();
103 write_ertr::future
<> write_header();
107 * CircularBoundedJournal structure
109 * +-------------------------------------------------------+
110 * | header | record | record | record | record | ... |
111 * +-------------------------------------------------------+
112 * ^-----------block aligned-----------------^
116 struct cbj_header_t
{
117 // start offset of CircularBoundedJournal in the device
118 journal_seq_t dirty_tail
;
119 journal_seq_t alloc_tail
;
120 segment_nonce_t magic
;
122 DENC(cbj_header_t
, v
, p
) {
124 denc(v
.dirty_tail
, p
);
125 denc(v
.alloc_tail
, p
);
133 * Write position for CircularBoundedJournal
135 * | written to rbm | written length to CircularBoundedJournal | new write |
136 * ----------------->------------------------------------------------>
138 * applied_to written_to
142 journal_seq_t
get_written_to() const {
145 rbm_abs_addr
get_rbm_addr(journal_seq_t seq
) const {
146 return convert_paddr_to_abs_addr(seq
.offset
);
148 void set_written_to(journal_seq_t seq
) {
149 rbm_abs_addr addr
= convert_paddr_to_abs_addr(seq
.offset
);
150 assert(addr
>= get_records_start());
151 assert(addr
< get_journal_end());
154 device_id_t
get_device_id() const {
155 return device
->get_device_id();
158 journal_seq_t
get_dirty_tail() const {
159 return header
.dirty_tail
;
161 journal_seq_t
get_alloc_tail() const {
162 return header
.alloc_tail
;
166 Size-related interfaces
167 +---------------------------------------------------------+
168 | header | record | record | record | record | ... |
169 +---------------------------------------------------------+
172 get_journal_start | get_journal_end
174 <-- get_records_total_size + block_size -->
175 <--------------- get_journal_size ------------------------>
178 size_t get_records_used_size() const {
179 auto rbm_written_to
= get_rbm_addr(get_written_to());
180 auto rbm_tail
= get_rbm_addr(get_dirty_tail());
181 return rbm_written_to
>= rbm_tail
?
182 rbm_written_to
- rbm_tail
:
183 rbm_written_to
+ get_records_total_size() + get_block_size()
186 size_t get_records_total_size() const {
188 // a block is for header and a block is reserved to denote the end
189 return device
->get_journal_size() - (2 * get_block_size());
191 rbm_abs_addr
get_records_start() const {
193 return device
->get_shard_journal_start() + get_block_size();
195 size_t get_records_available_size() const {
196 return get_records_total_size() - get_records_used_size();
198 bool is_available_size(uint64_t size
) {
199 auto rbm_written_to
= get_rbm_addr(get_written_to());
200 auto rbm_tail
= get_rbm_addr(get_dirty_tail());
201 if (rbm_written_to
> rbm_tail
&&
202 (get_journal_end() - rbm_written_to
) < size
&&
203 size
> (get_records_used_size() -
204 (get_journal_end() - rbm_written_to
))) {
207 return get_records_available_size() >= size
;
209 rbm_abs_addr
get_journal_end() const {
211 return device
->get_shard_journal_start() + device
->get_journal_size();
214 read_ertr::future
<> read(
218 return device
->read(offset
, bptr
);
221 seastar::future
<> update_journal_tail(
223 journal_seq_t alloc
) {
224 header
.dirty_tail
= dirty
;
225 header
.alloc_tail
= alloc
;
228 crimson::ct_error::assert_all
{
229 "encountered invalid error in update_journal_tail"
233 void set_initialized(bool init
) {
237 void set_cbj_header(cbj_header_t
& head
) {
241 cbj_header_t
get_cbj_header() {
246 std::string print_name
;
249 journal_seq_t written_to
;
250 bool initialized
= false;
253 std::ostream
&operator<<(std::ostream
&out
, const CircularJournalSpace::cbj_header_t
&header
);
257 WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::journal::CircularJournalSpace::cbj_header_t
)
259 #if FMT_VERSION >= 90000
260 template <> struct fmt::formatter
<crimson::os::seastore::journal::CircularJournalSpace::cbj_header_t
> : fmt::ostream_formatter
{};