namespace crimson::os::seastore {
TransactionManager::TransactionManager(
- SegmentManager &segment_manager,
- SegmentCleaner &segment_cleaner,
- Journal &journal,
- Cache &cache,
- LBAManager &lba_manager)
- : segment_manager(segment_manager),
- segment_cleaner(segment_cleaner),
- cache(cache),
- lba_manager(lba_manager),
- journal(journal)
+ SegmentManager &_segment_manager,
+ SegmentCleanerRef _segment_cleaner,
+ JournalRef _journal,
+ CacheRef _cache,
+ LBAManagerRef _lba_manager)
+ : segment_manager(_segment_manager),
+ segment_cleaner(std::move(_segment_cleaner)),
+ cache(std::move(_cache)),
+ lba_manager(std::move(_lba_manager)),
+ journal(std::move(_journal))
{
- journal.set_write_pipeline(&write_pipeline);
+ segment_cleaner->set_extent_callback(this);
+ journal->set_write_pipeline(&write_pipeline);
}
TransactionManager::mkfs_ertr::future<> TransactionManager::mkfs()
{
- return journal.open_for_write().safe_then([this](auto addr) {
+ return journal->open_for_write().safe_then([this](auto addr) {
logger().debug("TransactionManager::mkfs: about to do_with");
- segment_cleaner.set_journal_head(addr);
+ segment_cleaner->set_journal_head(addr);
return seastar::do_with(
create_transaction(),
[this](auto &transaction) {
- logger().debug("TransactionManager::mkfs: about to cache.mkfs");
- cache.init();
- return cache.mkfs(*transaction
+ logger().debug("TransactionManager::mkfs: about to cache->mkfs");
+ cache->init();
+ return cache->mkfs(*transaction
).safe_then([this, &transaction] {
- return lba_manager.mkfs(*transaction);
+ return lba_manager->mkfs(*transaction);
}).safe_then([this, &transaction] {
logger().debug("TransactionManager::mkfs: about to submit_transaction");
return submit_transaction(std::move(transaction)).handle_error(
});
});
}).safe_then([this] {
- return journal.close();
+ return journal->close();
});
}
TransactionManager::mount_ertr::future<> TransactionManager::mount()
{
- cache.init();
- return journal.replay([this](auto seq, auto paddr, const auto &e) {
- return cache.replay_delta(seq, paddr, e);
+ cache->init();
+ return journal->replay([this](auto seq, auto paddr, const auto &e) {
+ return cache->replay_delta(seq, paddr, e);
}).safe_then([this] {
- return journal.open_for_write();
+ return journal->open_for_write();
}).safe_then([this](auto addr) {
- segment_cleaner.set_journal_head(addr);
+ segment_cleaner->set_journal_head(addr);
return seastar::do_with(
make_weak_transaction(),
[this](auto &t) {
- return cache.init_cached_extents(*t, [this](auto &t, auto &e) {
- return lba_manager.init_cached_extent(t, e);
+ return cache->init_cached_extents(*t, [this](auto &t, auto &e) {
+ return lba_manager->init_cached_extent(t, e);
}).safe_then([this, &t] {
- assert(segment_cleaner.debug_check_space(
- *segment_cleaner.get_empty_space_tracker()));
- return lba_manager.scan_mapped_space(
+ assert(segment_cleaner->debug_check_space(
+ *segment_cleaner->get_empty_space_tracker()));
+ return lba_manager->scan_mapped_space(
*t,
[this](paddr_t addr, extent_len_t len) {
logger().debug("TransactionManager::mount: marking {}~{} used",
addr,
len);
- segment_cleaner.mark_space_used(
+ segment_cleaner->mark_space_used(
addr,
len ,
/* init_scan = */ true);
});
});
}).safe_then([this] {
- segment_cleaner.complete_init();
+ segment_cleaner->complete_init();
}).handle_error(
mount_ertr::pass_further{},
crimson::ct_error::all_same_way([] {
}
TransactionManager::close_ertr::future<> TransactionManager::close() {
- return cache.close(
+ return cache->close(
).safe_then([this] {
- return journal.close();
+ return journal->close();
});
}
Transaction &t,
LogicalCachedExtentRef &ref)
{
- return lba_manager.incref_extent(t, ref->get_laddr()).safe_then([](auto r) {
+ return lba_manager->incref_extent(t, ref->get_laddr()).safe_then([](auto r) {
return r.refcount;
}).handle_error(
ref_ertr::pass_further{},
Transaction &t,
laddr_t offset)
{
- return lba_manager.incref_extent(t, offset).safe_then([](auto result) {
+ return lba_manager->incref_extent(t, offset).safe_then([](auto result) {
return result.refcount;
});
}
Transaction &t,
LogicalCachedExtentRef &ref)
{
- return lba_manager.decref_extent(t, ref->get_laddr()
+ return lba_manager->decref_extent(t, ref->get_laddr()
).safe_then([this, &t, ref](auto ret) {
if (ret.refcount == 0) {
logger().debug(
"TransactionManager::dec_ref: extent {} refcount 0",
*ref);
- cache.retire_extent(t, ref);
+ cache->retire_extent(t, ref);
}
return ret.refcount;
});
Transaction &t,
laddr_t offset)
{
- return lba_manager.decref_extent(t, offset
+ return lba_manager->decref_extent(t, offset
).safe_then([this, offset, &t](auto result) -> ref_ret {
if (result.refcount == 0) {
logger().debug(
"TransactionManager::dec_ref: offset {} refcount 0",
offset);
- return cache.retire_extent_if_cached(t, result.addr).safe_then([] {
+ return cache->retire_extent_if_cached(t, result.addr).safe_then([] {
return ref_ret(
ref_ertr::ready_future_marker{},
0);
auto &tref = *t;
return tref.handle.enter(write_pipeline.prepare
).then([this, &tref]() mutable {
- return segment_cleaner.do_immediate_work(tref);
+ return segment_cleaner->do_immediate_work(tref);
}).safe_then([this, &tref]() mutable
-> submit_transaction_ertr::future<> {
logger().debug("TransactionManager::submit_transaction after do_immediate");
- auto record = cache.try_construct_record(tref);
+ auto record = cache->try_construct_record(tref);
if (!record) {
return crimson::ct_error::eagain::make();
}
- return journal.submit_record(std::move(*record), tref.handle
+ return journal->submit_record(std::move(*record), tref.handle
).safe_then([this, &tref](auto p) mutable {
auto [addr, journal_seq] = p;
- segment_cleaner.set_journal_head(journal_seq);
- cache.complete_commit(tref, addr, journal_seq, &segment_cleaner);
- lba_manager.complete_transaction(tref);
+ segment_cleaner->set_journal_head(journal_seq);
+ cache->complete_commit(tref, addr, journal_seq, segment_cleaner.get());
+ lba_manager->complete_transaction(tref);
auto to_release = tref.get_segment_to_release();
if (to_release != NULL_SEG_ID) {
- segment_cleaner.mark_segment_released(to_release);
+ segment_cleaner->mark_segment_released(to_release);
return segment_manager.release(to_release);
} else {
return SegmentManager::release_ertr::now();
TransactionManager::get_next_dirty_extents_ret
TransactionManager::get_next_dirty_extents(journal_seq_t seq)
{
- return cache.get_next_dirty_extents(seq);
+ return cache->get_next_dirty_extents(seq);
}
TransactionManager::rewrite_extent_ret TransactionManager::rewrite_extent(
CachedExtentRef extent)
{
{
- auto updated = cache.update_extent_from_transaction(t, extent);
+ auto updated = cache->update_extent_from_transaction(t, extent);
if (!updated) {
logger().debug(
"{}: {} is already retired, skipping",
"{}: marking root {} for rewrite",
__func__,
*extent);
- cache.duplicate_for_write(t, extent);
+ cache->duplicate_for_write(t, extent);
return rewrite_extent_ertr::now();
}
- return lba_manager.rewrite_extent(t, extent);
+ return lba_manager->rewrite_extent(t, extent);
}
TransactionManager::get_extent_if_live_ret TransactionManager::get_extent_if_live(
segment_off_t len)
{
CachedExtentRef ret;
- auto status = cache.get_extent_if_cached(t, addr, &ret);
+ auto status = cache->get_extent_if_cached(t, addr, &ret);
if (status != Transaction::get_extent_ret::ABSENT) {
return get_extent_if_live_ret(
get_extent_if_live_ertr::ready_future_marker{},
}
if (is_logical_type(type)) {
- return lba_manager.get_mapping(
+ return lba_manager->get_mapping(
t,
laddr,
len).safe_then([=, &t](lba_pin_list_t pins) {
ceph_assert(pin->get_laddr() == laddr);
ceph_assert(pin->get_length() == (extent_len_t)len);
if (pin->get_paddr() == addr) {
- return cache.get_extent_by_type(
+ return cache->get_extent_by_type(
t,
type,
addr,
return crimson::ct_error::eagain::make();
} else {
lref->set_pin(std::move(pin));
- lba_manager.add_pin(lref->get_pin());
+ lba_manager->add_pin(lref->get_pin());
}
}
return get_extent_if_live_ret(
logger().debug(
"TransactionManager::get_extent_if_live: non-logical extent {}",
addr);
- return lba_manager.get_physical_extent_if_live(
+ return lba_manager->get_physical_extent_if_live(
t,
type,
addr,
TransactionManager(
SegmentManager &segment_manager,
- SegmentCleaner &segment_cleaner,
- Journal &journal,
- Cache &cache,
- LBAManager &lba_manager);
+ SegmentCleanerRef segment_cleaner,
+ JournalRef journal,
+ CacheRef cache,
+ LBAManagerRef lba_manager);
/// Writes initial metadata to disk
using mkfs_ertr = crimson::errorator<
std::unique_ptr<lba_pin_list_t> pin_list =
std::make_unique<lba_pin_list_t>();
auto &pin_list_ref = *pin_list;
- return lba_manager.get_mapping(
+ return lba_manager->get_mapping(
t, offset, length
).safe_then([this, &t, &pin_list_ref, &ret_ref](auto pins) {
crimson::get_logger(ceph_subsys_filestore).debug(
"read_extents: get_extent {}~{}",
pin->get_paddr(),
pin->get_length());
- return cache.get_extent<T>(
+ return cache->get_extent<T>(
t,
pin->get_paddr(),
pin->get_length()
return crimson::ct_error::eagain::make();
} else {
ref->set_pin(std::move(pin));
- lba_manager.add_pin(ref->get_pin());
+ lba_manager->add_pin(ref->get_pin());
}
}
ret_ref.push_back(std::make_pair(ref->get_laddr(), ref));
/// Obtain mutable copy of extent
LogicalCachedExtentRef get_mutable_extent(Transaction &t, LogicalCachedExtentRef ref) {
auto &logger = crimson::get_logger(ceph_subsys_filestore);
- auto ret = cache.duplicate_for_write(
+ auto ret = cache->duplicate_for_write(
t,
ref)->cast<LogicalCachedExtent>();
if (!ret->has_pin()) {
Transaction &t,
laddr_t hint,
extent_len_t len) {
- auto ext = cache.alloc_new_extent<T>(
+ auto ext = cache->alloc_new_extent<T>(
t,
len);
- return lba_manager.alloc_extent(
+ return lba_manager->alloc_extent(
t,
hint,
len,
scan_extents_ret scan_extents(
scan_extents_cursor &cursor,
extent_len_t bytes_to_read) final {
- return journal.scan_extents(cursor, bytes_to_read);
+ return journal->scan_extents(cursor, bytes_to_read);
}
using release_segment_ret =
using read_onode_root_ertr = base_ertr;
using read_onode_root_ret = read_onode_root_ertr::future<laddr_t>;
read_onode_root_ret read_onode_root(Transaction &t) {
- return cache.get_root(t).safe_then([](auto croot) {
+ return cache->get_root(t).safe_then([](auto croot) {
return croot->get_root().onode_root;
});
}
* Write onode-tree root logical address, must be called after read.
*/
void write_onode_root(Transaction &t, laddr_t addr) {
- auto croot = cache.get_root_fast(t);
- croot = cache.duplicate_for_write(t, croot)->cast<RootBlock>();
+ auto croot = cache->get_root_fast(t);
+ croot = cache->duplicate_for_write(t, croot)->cast<RootBlock>();
croot->get_root().onode_root = addr;
}
friend class Transaction;
SegmentManager &segment_manager;
- SegmentCleaner &segment_cleaner;
- Cache &cache;
- LBAManager &lba_manager;
- Journal &journal;
+ SegmentCleanerRef segment_cleaner;
+ CacheRef cache;
+ LBAManagerRef lba_manager;
+ JournalRef journal;
WritePipeline write_pipeline;
+
+public:
+ // Testing interfaces
+ auto get_segment_cleaner() {
+ return segment_cleaner.get();
+ }
+
+ auto get_lba_manager() {
+ return lba_manager.get();
+ }
};
using TransactionManagerRef = std::unique_ptr<TransactionManager>;
std::unique_ptr<segment_manager::EphemeralSegmentManager> segment_manager;
EphemeralTestState()
- : segment_manager(segment_manager::create_test_ephemeral()) {
- // init(); derived class must call
- }
+ : segment_manager(segment_manager::create_test_ephemeral()) {}
virtual void _init() = 0;
void init() {
}
seastar::future<> tm_setup() {
+ init();
return segment_manager->init(
).safe_then([this] {
return _mkfs();
}
};
+auto get_transaction_manager(
+ SegmentManager &segment_manager
+) {
+ auto segment_cleaner = std::make_unique<SegmentCleaner>(
+ SegmentCleaner::config_t::default_from_segment_manager(
+ segment_manager),
+ true);
+ auto journal = std::make_unique<Journal>(segment_manager);
+ auto cache = std::make_unique<Cache>(segment_manager);
+ auto lba_manager = lba_manager::create_lba_manager(segment_manager, *cache);
+
+ journal->set_segment_provider(&*segment_cleaner);
+
+ auto ret = std::make_unique<TransactionManager>(
+ segment_manager,
+ std::move(segment_cleaner),
+ std::move(journal),
+ std::move(cache),
+ std::move(lba_manager));
+ return ret;
+}
+
class TMTestState : public EphemeralTestState {
protected:
- std::unique_ptr<SegmentCleaner> segment_cleaner;
- std::unique_ptr<Journal> journal;
- std::unique_ptr<Cache> cache;
- LBAManagerRef lba_manager;
std::unique_ptr<TransactionManager> tm;
+ LBAManager *lba_manager;
+ SegmentCleaner *segment_cleaner;
- TMTestState() : EphemeralTestState() {
- init();
- }
+ TMTestState() : EphemeralTestState() {}
- void _init() final {
- segment_cleaner = std::make_unique<SegmentCleaner>(
- SegmentCleaner::config_t::default_from_segment_manager(
- *segment_manager),
- true);
- journal = std::make_unique<Journal>(*segment_manager);
- cache = std::make_unique<Cache>(*segment_manager);
- lba_manager = lba_manager::create_lba_manager(*segment_manager, *cache);
- tm = std::make_unique<TransactionManager>(
- *segment_manager, *segment_cleaner, *journal, *cache, *lba_manager);
-
- journal->set_segment_provider(&*segment_cleaner);
- segment_cleaner->set_extent_callback(&*tm);
+ virtual void _init() {
+ tm = get_transaction_manager(*segment_manager);
+ segment_cleaner = tm->get_segment_cleaner();
+ lba_manager = tm->get_lba_manager();
}
- void _destroy() final {
+ virtual void _destroy() {
+ segment_cleaner = nullptr;
+ lba_manager = nullptr;
tm.reset();
- lba_manager.reset();
- cache.reset();
- journal.reset();
- segment_cleaner.reset();
}
- seastar::future<> _teardown() final {
+ virtual seastar::future<> _teardown() {
return tm->close(
).handle_error(
crimson::ct_error::assert_all{"Error in teardown"}
);
}
- seastar::future<> _mount() final {
+ virtual seastar::future<> _mount() {
return tm->mount(
).handle_error(
crimson::ct_error::assert_all{"Error in mount"}
);
}
- seastar::future<> _mkfs() final {
+ virtual seastar::future<> _mkfs() {
return tm->mkfs(
).handle_error(
crimson::ct_error::assert_all{"Error in teardown"}