public:
virtual device_id_t get_device_id() const = 0;
+ virtual seastore_off_t get_block_size() const = 0;
+
using read_ertr = crimson::errorator<
crimson::ct_error::input_output_error,
crimson::ct_error::invarg,
devices_by_id.resize(DEVICE_ID_MAX, nullptr);
}
- void add_device(Device* device) {
+ void add_device(Device* device, bool is_primary) {
auto device_id = device->get_device_id();
ceph_assert(devices_by_id[device_id] == nullptr);
devices_by_id[device_id] = device;
+ if (is_primary) {
+ ceph_assert(primary_device == nullptr);
+ primary_device = device;
+ }
}
void add_allocator(device_type_t type, ExtentAllocatorRef&& allocator) {
allocators[type].size());
}
+ seastore_off_t get_block_size() const {
+ assert(primary_device != nullptr);
+ // assume all the devices have the same block size
+ return primary_device->get_block_size();
+ }
+
+ Device& get_primary_device() {
+ assert(primary_device != nullptr);
+ return *primary_device;
+ }
+
using open_ertr = ExtentOolWriter::open_ertr;
open_ertr::future<> open() {
LOG_PREFIX(ExtentPlacementManager::open);
allocators.clear();
devices_by_id.clear();
devices_by_id.resize(DEVICE_ID_MAX, nullptr);
+ primary_device = nullptr;
});
}
std::map<device_type_t, std::vector<ExtentAllocatorRef>> allocators;
std::vector<Device*> devices_by_id;
+ Device* primary_device = nullptr;
};
using ExtentPlacementManagerRef = std::unique_ptr<ExtentPlacementManager>;
class ExtentReader {
public:
- seastore_off_t get_block_size() const {
- assert(segment_managers.size());
- // assume all segment managers have the same block size
- return segment_managers[0]->get_block_size();
- }
-
std::vector<SegmentManager*>& get_segment_managers() {
return segment_managers;
}
found_record_handler_t &handler ///< [in] handler for records
); ///< @return used budget
+ using release_ertr = SegmentManager::release_ertr;
+ release_ertr::future<> release_segment(segment_id_t id) {
+ assert(segment_managers[id.device_id()] != nullptr);
+ return segment_managers[id.device_id()]->release(id);
+ }
+
void add_segment_manager(SegmentManager* segment_manager) {
ceph_assert(!segment_managers[segment_manager->get_device_id()]);
segment_managers[segment_manager->get_device_id()] = segment_manager;
{
return segment_manager->mount(
).safe_then([this] {
- transaction_manager->add_segment_manager(segment_manager.get());
+ transaction_manager->add_segment_manager(segment_manager.get(), true);
auto sec_devices = segment_manager->get_secondary_devices();
return crimson::do_for_each(sec_devices, [this](auto& device_entry) {
device_id_t id = device_entry.first;
[this, sm=std::move(sm), magic]() mutable {
boost::ignore_unused(magic); // avoid clang warning;
assert(sm->get_magic() == magic);
- transaction_manager->add_segment_manager(sm.get());
+ transaction_manager->add_segment_manager(sm.get(), false);
secondaries.emplace_back(std::move(sm));
return seastar::now();
});
}).safe_then([this] {
return crimson::do_for_each(secondaries, [this](auto& sec_sm) {
return sec_sm->mount().safe_then([this, &sec_sm] {
- transaction_manager->add_segment_manager(sec_sm.get());
+ transaction_manager->add_segment_manager(sec_sm.get(), false);
return seastar::now();
});
});
}).safe_then([this] {
return segment_manager->mount();
}).safe_then([this] {
- transaction_manager->add_segment_manager(segment_manager.get());
+ transaction_manager->add_segment_manager(segment_manager.get(), true);
return transaction_manager->mkfs();
}).safe_then([this] {
for (auto& sec_sm : secondaries) {
- transaction_manager->add_segment_manager(sec_sm.get());
+ transaction_manager->add_segment_manager(sec_sm.get(), false);
}
- transaction_manager->add_segment_manager(segment_manager.get());
+ transaction_manager->add_segment_manager(segment_manager.get(), true);
return transaction_manager->mount();
}).safe_then([this] {
return repeat_eagain([this] {
struct stat st;
auto &olayout = onode.get_layout();
st.st_size = olayout.size;
- st.st_blksize = transaction_manager->get_block_size();
+ st.st_blksize = segment_manager->get_block_size();
st.st_blocks = (st.st_size + st.st_blksize - 1) / st.st_blksize;
st.st_nlink = 1;
DEBUGT("cid {}, oid {}, return size {}", t, c->get_cid(), oid, st.st_size);
return seastar::now();
}
+SegmentCleaner::release_ertr::future<>
+SegmentCleaner::maybe_release_segment(Transaction &t)
+{
+ auto to_release = t.get_segment_to_release();
+ if (to_release != NULL_SEG_ID) {
+ LOG_PREFIX(SegmentCleaner::maybe_release_segment);
+ INFOT("releasing segment {}", t, to_release);
+ return scanner->release_segment(to_release
+ ).safe_then([this, to_release] {
+ stats.segments_released++;
+ mark_empty(to_release);
+ });
+ } else {
+ return SegmentManager::release_ertr::now();
+ }
+}
+
}
laddr_t laddr,
seastore_off_t len) = 0;
- /**
- * release_segment
- *
- * Release segment.
- */
- using release_segment_ertr = SegmentManager::release_ertr;
- using release_segment_ret = release_segment_ertr::future<>;
- virtual release_segment_ret release_segment(
- segment_id_t id) = 0;
-
/**
* submit_transaction_direct
*
return segments[id].get_type();
}
- void mark_segment_released(segment_id_t segment) {
- stats.segments_released++;
- return mark_empty(segment);
- }
+ using release_ertr = ExtentReader::release_ertr;
+ release_ertr::future<> maybe_release_segment(Transaction &t);
void adjust_segment_util(double old_usage, double new_usage) {
assert(stats.segment_util.buckets[std::floor(old_usage * 10)].count > 0);
/* Methods for discovering device geometry, segmentid set, etc */
virtual size_t get_size() const = 0;
- virtual seastore_off_t get_block_size() const = 0;
virtual seastore_off_t get_segment_size() const = 0;
virtual device_segment_id_t get_num_segments() const {
ceph_assert(get_size() % get_segment_size() == 0);
#include "crimson/os/seastore/logging.h"
#include "crimson/os/seastore/transaction_manager.h"
-#include "crimson/os/seastore/segment_manager.h"
#include "crimson/os/seastore/journal.h"
/*
namespace crimson::os::seastore {
TransactionManager::TransactionManager(
- SegmentManager &_segment_manager,
SegmentCleanerRef _segment_cleaner,
JournalRef _journal,
CacheRef _cache,
LBAManagerRef _lba_manager,
ExtentPlacementManagerRef&& epm,
ExtentReader& scanner)
- : segment_manager(_segment_manager),
- segment_cleaner(std::move(_segment_cleaner)),
+ : segment_cleaner(std::move(_segment_cleaner)),
cache(std::move(_cache)),
lba_manager(std::move(_lba_manager)),
journal(std::move(_journal)),
LOG_PREFIX(TransactionManager::mkfs);
INFO("enter");
return segment_cleaner->mount(
- segment_manager.get_device_id()
+ epm->get_primary_device().get_device_id()
).safe_then([this] {
return journal->open_for_write();
}).safe_then([this](auto addr) {
INFO("enter");
cache->init();
return segment_cleaner->mount(
- segment_manager.get_device_id()
+ epm->get_primary_device().get_device_id()
).safe_then([this] {
return journal->replay(
[this](const auto &offsets, const auto &e, auto last_modified) {
lba_manager->complete_transaction(tref);
segment_cleaner->update_journal_tail_target(
cache->get_oldest_dirty_from().value_or(start_seq));
- auto to_release = tref.get_segment_to_release();
- if (to_release != NULL_SEG_ID) {
- SUBDEBUGT(seastore_t, "releasing segment {}", tref, to_release);
- return segment_manager.release(to_release
- ).safe_then([this, to_release] {
- segment_cleaner->mark_segment_released(to_release);
- });
- } else {
- return SegmentManager::release_ertr::now();
- }
+ return segment_cleaner->maybe_release_segment(tref);
}).safe_then([FNAME, &tref] {
SUBTRACET(seastore_t, "completed", tref);
return tref.get_handle().complete();
auto lba_manager = lba_manager::create_lba_manager(sm, *cache);
return std::make_unique<TransactionManager>(
- sm,
std::move(segment_cleaner),
std::move(journal),
std::move(cache),
#include "crimson/os/seastore/segment_cleaner.h"
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/cache.h"
-#include "crimson/os/seastore/segment_manager.h"
#include "crimson/os/seastore/lba_manager.h"
#include "crimson/os/seastore/journal.h"
#include "crimson/os/seastore/extent_placement_manager.h"
using base_iertr = Cache::base_iertr;
TransactionManager(
- SegmentManager &segment_manager,
SegmentCleanerRef segment_cleaner,
JournalRef journal,
CacheRef cache,
laddr_t laddr,
seastore_off_t len) final;
- using release_segment_ret =
- SegmentCleaner::ExtentCallbackInterface::release_segment_ret;
- release_segment_ret release_segment(
- segment_id_t id) final {
- LOG_PREFIX(TransactionManager::release_segment);
- SUBDEBUG(seastore_tm, "{}", id);
- return segment_manager.release(id);
- }
-
/**
* read_root_meta
*
}
extent_len_t get_block_size() const {
- return segment_manager.get_block_size();
+ return epm->get_block_size();
}
store_statfs_t store_stat() const {
return segment_cleaner->stat();
}
- void add_segment_manager(SegmentManager* sm) {
+ void add_segment_manager(SegmentManager* sm, bool is_primary) {
LOG_PREFIX(TransactionManager::add_segment_manager);
- SUBDEBUG(seastore_tm, "adding segment manager {}", sm->get_device_id());
+ SUBDEBUG(seastore_tm, "adding segment manager {}, is_primary={}",
+ sm->get_device_id(), is_primary);
scanner.add_segment_manager(sm);
- epm->add_device(sm);
+ epm->add_device(sm, is_primary);
epm->add_allocator(
device_type_t::SEGMENTED,
std::make_unique<SegmentedAllocator>(
private:
friend class Transaction;
- // although there might be multiple devices backing seastore,
- // only one of them are supposed to hold the journal. This
- // segment manager is that device
- SegmentManager &segment_manager;
SegmentCleanerRef segment_cleaner;
CacheRef cache;
LBAManagerRef lba_manager;
void TMDriver::init()
{
tm = make_transaction_manager(*segment_manager, false /* detailed */);
- tm->add_segment_manager(segment_manager.get());
+ tm->add_segment_manager(segment_manager.get(), true);
}
void TMDriver::clear()
virtual FuturizedStore::mkfs_ertr::future<> _mkfs() final {
return TMTestState::_mkfs(
).safe_then([this] {
- tm->add_segment_manager(segment_manager.get());
+ tm->add_segment_manager(segment_manager.get(), true);
return tm->mount(
).safe_then([this] {
return repeat_eagain([this] {
block_size = segment_manager->get_block_size();
next = segment_id_t{segment_manager->get_device_id(), 0};
scanner_ref.add_segment_manager(segment_manager.get());
- epm->add_device(segment_manager.get());
+ epm->add_device(segment_manager.get(), true);
journal->set_write_pipeline(&pipeline);
return segment_manager->init(
epm.reset(new ExtentPlacementManager());
cache.reset(new Cache(*epm));
current = paddr_t::make_seg_paddr(segment_id_t(segment_manager->get_device_id(), 0), 0);
- epm->add_device(segment_manager.get());
+ epm->add_device(segment_manager.get(), true);
return segment_manager->init(
).safe_then([this] {
return seastar::do_with(
virtual void _init() override {
tm = make_transaction_manager(*segment_manager, true);
- tm->add_segment_manager(segment_manager.get());
+ tm->add_segment_manager(segment_manager.get(), true);
segment_cleaner = tm->get_segment_cleaner();
lba_manager = tm->get_lba_manager();
}