1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "include/denc.h"
5 #include "include/intarith.h"
7 #include "crimson/common/log.h"
9 #include "crimson/os/seastore/transaction_manager.h"
10 #include "crimson/os/seastore/segment_manager.h"
11 #include "crimson/os/seastore/journal.h"
14 seastar::logger
& logger() {
15 return crimson::get_logger(ceph_subsys_filestore
);
19 namespace crimson::os::seastore
{
21 TransactionManager::TransactionManager(
22 SegmentManager
&segment_manager
,
23 SegmentCleaner
&segment_cleaner
,
26 LBAManager
&lba_manager
)
27 : segment_manager(segment_manager
),
28 segment_cleaner(segment_cleaner
),
30 lba_manager(lba_manager
),
34 TransactionManager::mkfs_ertr::future
<> TransactionManager::mkfs()
36 return journal
.open_for_write().safe_then([this](auto addr
) {
37 logger().debug("TransactionManager::mkfs: about to do_with");
38 segment_cleaner
.set_journal_head(addr
);
39 return seastar::do_with(
41 [this](auto &transaction
) {
42 logger().debug("TransactionManager::mkfs: about to cache.mkfs");
44 return cache
.mkfs(*transaction
45 ).safe_then([this, &transaction
] {
46 return lba_manager
.mkfs(*transaction
);
47 }).safe_then([this, &transaction
] {
48 logger().debug("TransactionManager::mkfs: about to submit_transaction");
49 return submit_transaction(std::move(transaction
)).handle_error(
50 crimson::ct_error::eagain::handle([] {
51 ceph_assert(0 == "eagain impossible");
52 return mkfs_ertr::now();
54 mkfs_ertr::pass_further
{}
59 return journal
.close();
63 TransactionManager::mount_ertr::future
<> TransactionManager::mount()
66 return journal
.replay([this](auto seq
, auto paddr
, const auto &e
) {
67 return cache
.replay_delta(seq
, paddr
, e
);
69 return journal
.open_for_write();
70 }).safe_then([this](auto addr
) {
71 segment_cleaner
.set_journal_head(addr
);
72 return seastar::do_with(
73 make_weak_transaction(),
75 return cache
.init_cached_extents(*t
, [this](auto &t
, auto &e
) {
76 return lba_manager
.init_cached_extent(t
, e
);
77 }).safe_then([this, &t
] {
78 assert(segment_cleaner
.debug_check_space(
79 *segment_cleaner
.get_empty_space_tracker()));
80 return lba_manager
.scan_mapped_space(
82 [this](paddr_t addr
, extent_len_t len
) {
83 logger().debug("TransactionManager::mount: marking {}~{} used",
86 segment_cleaner
.mark_space_used(
89 /* init_scan = */ true);
94 segment_cleaner
.complete_init();
96 mount_ertr::pass_further
{},
97 crimson::ct_error::all_same_way([] {
98 ceph_assert(0 == "unhandled error");
99 return mount_ertr::now();
103 TransactionManager::close_ertr::future
<> TransactionManager::close() {
106 return journal
.close();
110 TransactionManager::ref_ret
TransactionManager::inc_ref(
112 LogicalCachedExtentRef
&ref
)
114 return lba_manager
.incref_extent(t
, ref
->get_laddr()).safe_then([](auto r
) {
117 ref_ertr::pass_further
{},
118 ct_error::all_same_way([](auto e
) {
119 ceph_assert(0 == "unhandled error, TODO");
123 TransactionManager::ref_ret
TransactionManager::inc_ref(
127 return lba_manager
.incref_extent(t
, offset
).safe_then([](auto result
) {
128 return result
.refcount
;
132 TransactionManager::ref_ret
TransactionManager::dec_ref(
134 LogicalCachedExtentRef
&ref
)
136 return lba_manager
.decref_extent(t
, ref
->get_laddr()
137 ).safe_then([this, &t
, ref
](auto ret
) {
138 if (ret
.refcount
== 0) {
140 "TransactionManager::dec_ref: extent {} refcount 0",
142 cache
.retire_extent(t
, ref
);
148 TransactionManager::ref_ret
TransactionManager::dec_ref(
152 return lba_manager
.decref_extent(t
, offset
153 ).safe_then([this, offset
, &t
](auto result
) -> ref_ret
{
154 if (result
.refcount
== 0) {
156 "TransactionManager::dec_ref: offset {} refcount 0",
158 return cache
.retire_extent_if_cached(t
, result
.addr
).safe_then([] {
160 ref_ertr::ready_future_marker
{},
165 ref_ertr::ready_future_marker
{},
171 TransactionManager::submit_transaction_ertr::future
<>
172 TransactionManager::submit_transaction(
175 logger().debug("TransactionManager::submit_transaction");
176 return segment_cleaner
.do_immediate_work(*t
177 ).safe_then([this, t
=std::move(t
)]() mutable -> submit_transaction_ertr::future
<> {
178 auto record
= cache
.try_construct_record(*t
);
180 return crimson::ct_error::eagain::make();
183 return journal
.submit_record(std::move(*record
)
184 ).safe_then([this, t
=std::move(t
)](auto p
) mutable {
185 auto [addr
, journal_seq
] = p
;
186 segment_cleaner
.set_journal_head(journal_seq
);
187 cache
.complete_commit(*t
, addr
, journal_seq
, &segment_cleaner
);
188 lba_manager
.complete_transaction(*t
);
189 auto to_release
= t
->get_segment_to_release();
190 if (to_release
!= NULL_SEG_ID
) {
191 segment_cleaner
.mark_segment_released(to_release
);
192 return segment_manager
.release(to_release
);
194 return SegmentManager::release_ertr::now();
197 submit_transaction_ertr::pass_further
{},
198 crimson::ct_error::all_same_way([](auto e
) {
199 ceph_assert(0 == "Hit error submitting to journal");
204 TransactionManager::get_next_dirty_extents_ret
205 TransactionManager::get_next_dirty_extents(journal_seq_t seq
)
207 return cache
.get_next_dirty_extents(seq
);
210 TransactionManager::rewrite_extent_ret
TransactionManager::rewrite_extent(
212 CachedExtentRef extent
)
215 auto updated
= cache
.update_extent_from_transaction(t
, extent
);
218 "{}: {} is already retired, skipping",
221 return rewrite_extent_ertr::now();
226 if (extent
->get_type() == extent_types_t::ROOT
) {
228 "{}: marking root {} for rewrite",
231 cache
.duplicate_for_write(t
, extent
);
232 return rewrite_extent_ertr::now();
234 return lba_manager
.rewrite_extent(t
, extent
);
237 TransactionManager::get_extent_if_live_ret
TransactionManager::get_extent_if_live(
245 auto status
= cache
.get_extent_if_cached(t
, addr
, &ret
);
246 if (status
!= Transaction::get_extent_ret::ABSENT
) {
247 return get_extent_if_live_ret(
248 get_extent_if_live_ertr::ready_future_marker
{},
252 if (is_logical_type(type
)) {
253 return lba_manager
.get_mapping(
256 len
).safe_then([=, &t
](lba_pin_list_t pins
) {
257 ceph_assert(pins
.size() <= 1);
259 return get_extent_if_live_ret(
260 get_extent_if_live_ertr::ready_future_marker
{},
264 auto pin
= std::move(pins
.front());
266 ceph_assert(pin
->get_laddr() == laddr
);
267 ceph_assert(pin
->get_length() == (extent_len_t
)len
);
268 if (pin
->get_paddr() == addr
) {
269 return cache
.get_extent_by_type(
275 [this, pin
=std::move(pin
)](CachedExtentRef ret
) mutable {
276 auto lref
= ret
->cast
<LogicalCachedExtent
>();
277 if (!lref
->has_pin()) {
278 lref
->set_pin(std::move(pin
));
279 lba_manager
.add_pin(lref
->get_pin());
281 return get_extent_if_live_ret(
282 get_extent_if_live_ertr::ready_future_marker
{},
286 return get_extent_if_live_ret(
287 get_extent_if_live_ertr::ready_future_marker
{},
293 "TransactionManager::get_extent_if_live: non-logical extent {}",
295 return lba_manager
.get_physical_extent_if_live(
304 TransactionManager::~TransactionManager() {}