]> git.proxmox.com Git - ceph.git/blame - ceph/src/crimson/os/seastore/journal/circular_journal_space.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / crimson / os / seastore / journal / circular_journal_space.cc
CommitLineData
1e59de90
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
2// vim: ts=8 sw=2 smarttab expandtab
3
4#include "circular_journal_space.h"
5
6#include <fmt/format.h>
7#include <fmt/os.h>
8
9#include "crimson/os/seastore/logging.h"
10#include "crimson/os/seastore/async_cleaner.h"
11#include "crimson/os/seastore/journal/circular_bounded_journal.h"
12
13SET_SUBSYS(seastore_journal);
14
15namespace crimson::os::seastore::journal {
16
17std::ostream &operator<<(std::ostream &out,
18 const CircularJournalSpace::cbj_header_t &header)
19{
20 return out << "cbj_header_t("
21 << ", dirty_tail=" << header.dirty_tail
22 << ", alloc_tail=" << header.alloc_tail
23 << ")";
24}
25
26CircularJournalSpace::CircularJournalSpace(RBMDevice * device) : device(device) {}
27
28bool CircularJournalSpace::needs_roll(std::size_t length) const {
29 if (length + get_rbm_addr(get_written_to()) > get_journal_end()) {
30 return true;
31 }
32 return false;
33}
34
35extent_len_t CircularJournalSpace::get_block_size() const {
36 return device->get_block_size();
37}
38
39CircularJournalSpace::roll_ertr::future<> CircularJournalSpace::roll() {
40 paddr_t paddr = convert_abs_addr_to_paddr(
41 get_records_start(),
42 get_device_id());
43 auto seq = get_written_to();
44 set_written_to(
45 journal_seq_t{++seq.segment_seq, paddr});
46 return roll_ertr::now();
47}
48
49CircularJournalSpace::write_ret
50CircularJournalSpace::write(ceph::bufferlist&& to_write) {
51 LOG_PREFIX(CircularJournalSpace::write);
52 assert(get_written_to().segment_seq != NULL_SEG_SEQ);
53 auto encoded_size = to_write.length();
54 if (encoded_size > get_records_available_size()) {
55 ceph_abort("should be impossible with EPM reservation");
56 }
57 assert(encoded_size + get_rbm_addr(get_written_to())
58 < get_journal_end());
59
60 journal_seq_t j_seq = get_written_to();
61 auto target = get_rbm_addr(get_written_to());
62 auto new_written_to = target + encoded_size;
63 assert(new_written_to < get_journal_end());
64 paddr_t paddr = convert_abs_addr_to_paddr(
65 new_written_to,
66 get_device_id());
67 set_written_to(
68 journal_seq_t{get_written_to().segment_seq, paddr});
69 DEBUG("{}, target {}", to_write.length(), target);
70
71 auto write_result = write_result_t{
72 j_seq,
73 encoded_size
74 };
75 return device_write_bl(target, to_write
76 ).safe_then([this, target,
77 length=encoded_size,
78 write_result,
79 FNAME] {
80 DEBUG("commit target {} used_size {} written length {}",
81 target, get_records_used_size(), length);
82 return write_result;
83 }).handle_error(
84 base_ertr::pass_further{},
85 crimson::ct_error::assert_all{ "Invalid error" }
86 );
87}
88
89CircularJournalSpace::open_ret CircularJournalSpace::open(bool is_mkfs) {
90 std::ostringstream oss;
91 oss << device_id_printer_t{get_device_id()};
92 print_name = oss.str();
93
94 if (is_mkfs) {
95 LOG_PREFIX(CircularJournalSpace::open);
96 assert(device);
97 ceph::bufferlist bl;
98 CircularJournalSpace::cbj_header_t head;
99 assert(device->get_journal_size());
100 head.dirty_tail =
101 journal_seq_t{0,
102 convert_abs_addr_to_paddr(
103 get_records_start(),
104 device->get_device_id())};
105 head.alloc_tail = head.dirty_tail;
106 encode(head, bl);
107 header = head;
108 set_written_to(head.dirty_tail);
109 initialized = true;
110 DEBUG(
111 "initialize header block in CircularJournalSpace length {}",
112 bl.length());
113 return write_header(
114 ).safe_then([this]() {
115 return open_ret(
116 open_ertr::ready_future_marker{},
117 get_written_to());
118 }).handle_error(
119 open_ertr::pass_further{},
120 crimson::ct_error::assert_all{
121 "Invalid error write_header"
122 }
123 );
124 }
125 ceph_assert(initialized);
126 if (written_to.segment_seq == NULL_SEG_SEQ) {
127 written_to.segment_seq = 0;
128 }
129 return open_ret(
130 open_ertr::ready_future_marker{},
131 get_written_to());
132}
133
134ceph::bufferlist CircularJournalSpace::encode_header()
135{
136 bufferlist bl;
137 encode(header, bl);
138 auto header_crc_filler = bl.append_hole(sizeof(checksum_t));
139 auto bliter = bl.cbegin();
140 auto header_crc = bliter.crc32c(
141 ceph::encoded_sizeof_bounded<cbj_header_t>(),
142 -1);
143 ceph_le32 header_crc_le;
144 header_crc_le = header_crc;
145 header_crc_filler.copy_in(
146 sizeof(checksum_t),
147 reinterpret_cast<const char *>(&header_crc_le));
148 return bl;
149}
150
151CircularJournalSpace::write_ertr::future<> CircularJournalSpace::device_write_bl(
152 rbm_abs_addr offset, bufferlist &bl)
153{
154 LOG_PREFIX(CircularJournalSpace::device_write_bl);
155 auto length = bl.length();
156 if (offset + length > get_journal_end()) {
157 return crimson::ct_error::erange::make();
158 }
159 DEBUG(
160 "overwrite in CircularJournalSpace, offset {}, length {}",
161 offset,
162 length);
163 return device->writev(offset, bl
164 ).handle_error(
165 write_ertr::pass_further{},
166 crimson::ct_error::assert_all{ "Invalid error device->write" }
167 );
168}
169
170CircularJournalSpace::read_header_ret
171CircularJournalSpace::read_header()
172{
173 LOG_PREFIX(CircularJournalSpace::read_header);
174 assert(device);
175 auto bptr = bufferptr(ceph::buffer::create_page_aligned(
176 device->get_block_size()));
177 DEBUG("reading {}", device->get_journal_start());
178 return device->read(device->get_journal_start(), bptr
179 ).safe_then([bptr, FNAME]() mutable
180 -> read_header_ret {
181 bufferlist bl;
182 bl.append(bptr);
183 auto bp = bl.cbegin();
184 cbj_header_t cbj_header;
185 try {
186 decode(cbj_header, bp);
187 } catch (ceph::buffer::error &e) {
188 ERROR("unable to read header block");
189 return crimson::ct_error::enoent::make();
190 }
191 auto bliter = bl.cbegin();
192 auto test_crc = bliter.crc32c(
193 ceph::encoded_sizeof_bounded<cbj_header_t>(),
194 -1);
195 ceph_le32 recorded_crc_le;
196 decode(recorded_crc_le, bliter);
197 uint32_t recorded_crc = recorded_crc_le;
198 if (test_crc != recorded_crc) {
199 ERROR("error, header crc mismatch.");
200 return read_header_ret(
201 read_header_ertr::ready_future_marker{},
202 std::nullopt);
203 }
204 return read_header_ret(
205 read_header_ertr::ready_future_marker{},
206 std::make_pair(cbj_header, bl)
207 );
208 });
209}
210
211CircularJournalSpace::write_ertr::future<>
212CircularJournalSpace::write_header()
213{
214 LOG_PREFIX(CircularJournalSpace::write_header);
215 ceph::bufferlist bl = encode_header();
216 ceph_assert(bl.length() <= get_block_size());
217 DEBUG(
218 "sync header of CircularJournalSpace, length {}",
219 bl.length());
220 assert(device);
221 auto iter = bl.begin();
222 assert(bl.length() < get_block_size());
223 bufferptr bp = bufferptr(ceph::buffer::create_page_aligned(get_block_size()));
224 iter.copy(bl.length(), bp.c_str());
225 return device->write(device->get_journal_start(), std::move(bp)
226 ).handle_error(
227 write_ertr::pass_further{},
228 crimson::ct_error::assert_all{ "Invalid error device->write" }
229 );
230}
231
232}