new EphemeralSegmentManager(DEFAULT_TEST_EPHEMERAL));
}
+device_config_t get_ephemeral_device_config(
+ std::size_t index, std::size_t num_devices)
+{
+ assert(num_devices > index);
+ magic_t magic = 0xabcd;
+ auto type = device_type_t::SEGMENTED;
+ bool is_major_device;
+ secondary_device_set_t secondary_devices;
+ if (index == 0) {
+ is_major_device = true;
+ for (std::size_t secondary_index = index + 1;
+ secondary_index < num_devices;
+ ++secondary_index) {
+ device_id_t secondary_id = static_cast<device_id_t>(secondary_index);
+ secondary_devices.insert({
+ secondary_index, device_spec_t{magic, type, secondary_id}
+ });
+ }
+ } else { // index > 0
+ is_major_device = false;
+ }
+
+ device_id_t id = static_cast<device_id_t>(index);
+ seastore_meta_t meta = {};
+ return {is_major_device,
+ device_spec_t{magic, type, id},
+ meta,
+ secondary_devices};
+}
+
EphemeralSegment::EphemeralSegment(
EphemeralSegmentManager &manager, segment_id_t id)
: manager(manager), id(id) {}
});
}
+EphemeralSegmentManager::mkfs_ret
+EphemeralSegmentManager::mkfs(device_config_t _config)
+{
+ logger().info(
+ "Mkfs ephemeral segment manager with {}",
+ _config);
+ device_config = _config;
+ return mkfs_ertr::now();
+}
+
Segment::write_ertr::future<> EphemeralSegmentManager::segment_write(
paddr_t addr,
ceph::bufferlist bl,
EphemeralSegmentManager::init_ertr::future<> EphemeralSegmentManager::init()
{
- logger().debug(
+ logger().info(
"Initing ephemeral segment manager with config {}",
config);
- meta = seastore_meta_t{};
-
if (config.block_size % (4<<10) != 0) {
return crimson::ct_error::invarg::make();
}
size_t size = 0;
size_t block_size = 0;
size_t segment_size = 0;
- magic_t magic = 0;
- device_id_t id = 0;
};
constexpr ephemeral_config_t DEFAULT_TEST_EPHEMERAL = {
1 << 30,
4 << 10,
- 8 << 20,
- 0xabcd,
- 0
+ 8 << 20
};
std::ostream &operator<<(std::ostream &, const ephemeral_config_t &);
+
EphemeralSegmentManagerRef create_test_ephemeral();
+device_config_t get_ephemeral_device_config(
+ std::size_t index, std::size_t num_devices);
+
class EphemeralSegment final : public Segment {
friend class EphemeralSegmentManager;
EphemeralSegmentManager &manager;
using segment_state_t = Segment::segment_state_t;
const ephemeral_config_t config;
- std::optional<seastore_meta_t> meta;
+ std::optional<device_config_t> device_config;
size_t get_offset(paddr_t addr) {
auto& seg_addr = addr.as_seg_paddr();
Segment::close_ertr::future<> segment_close(segment_id_t id);
- secondary_device_set_t sec_device_set;
-
public:
EphemeralSegmentManager(
ephemeral_config_t config)
return close_ertr::now();
}
- device_id_t get_device_id() const {
- return config.id;
+ device_id_t get_device_id() const final {
+ assert(device_config);
+ return device_config->spec.id;
}
- using init_ertr = crimson::errorator<
- crimson::ct_error::enospc,
- crimson::ct_error::invarg,
- crimson::ct_error::erange>;
- init_ertr::future<> init();
-
- mount_ret mount() {
+ mount_ret mount() final {
return mount_ertr::now();
}
- mkfs_ret mkfs(device_config_t) {
- return mkfs_ertr::now();
- }
+ mkfs_ret mkfs(device_config_t) final;
open_ertr::future<SegmentRef> open(segment_id_t id) final;
}
const seastore_meta_t &get_meta() const final {
- assert(meta);
- return *meta;
+ assert(device_config);
+ return device_config->meta;
}
secondary_device_set_t& get_secondary_devices() final {
- return sec_device_set;
+ assert(device_config);
+ return device_config->secondary_devices;
}
magic_t get_magic() const final {
- return config.magic;
+ return device_config->spec.magic;
}
+ using init_ertr = crimson::errorator<
+ crimson::ct_error::enospc,
+ crimson::ct_error::invarg>;
+ init_ertr::future<> init();
+
void remount();
// public so tests can bypass segment interface when simpler
virtual LBAManager::mkfs_ret test_structure_setup(Transaction &t) = 0;
seastar::future<> set_up_fut() final {
segment_manager = segment_manager::create_test_ephemeral();
- sms.reset(new SegmentManagerGroup());
- journal = journal::make_segmented(*this);
- epm.reset(new ExtentPlacementManager());
- cache.reset(new Cache(*epm));
-
- block_size = segment_manager->get_block_size();
- next = segment_id_t{segment_manager->get_device_id(), 0};
- sms->add_segment_manager(segment_manager.get());
- epm->add_device(segment_manager.get(), true);
- journal->set_write_pipeline(&pipeline);
-
return segment_manager->init(
).safe_then([this] {
+ return segment_manager->mkfs(
+ segment_manager::get_ephemeral_device_config(0, 1));
+ }).safe_then([this] {
+ sms.reset(new SegmentManagerGroup());
+ journal = journal::make_segmented(*this);
+ epm.reset(new ExtentPlacementManager());
+ cache.reset(new Cache(*epm));
+
+ block_size = segment_manager->get_block_size();
+ next = segment_id_t{segment_manager->get_device_id(), 0};
+ sms->add_segment_manager(segment_manager.get());
+ epm->add_device(segment_manager.get(), true);
+ journal->set_write_pipeline(&pipeline);
+
return journal->open_for_write().discard_result();
}).safe_then([this] {
return epm->open();
seastar::future<> set_up_fut() final {
segment_manager = segment_manager::create_test_ephemeral();
- 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(), true);
return segment_manager->init(
).safe_then([this] {
+ return segment_manager->mkfs(
+ segment_manager::get_ephemeral_device_config(0, 1));
+ }).safe_then([this] {
+ 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(), true);
return seastar::do_with(
get_transaction(),
[this](auto &ref_t) {
seastar::future<> set_up_fut() final {
segment_manager = segment_manager::create_test_ephemeral();
- block_size = segment_manager->get_block_size();
- sms.reset(new SegmentManagerGroup());
- next = segment_id_t(segment_manager->get_device_id(), 0);
- journal = journal::make_segmented(*this);
- journal->set_write_pipeline(&pipeline);
- sms->add_segment_manager(segment_manager.get());
return segment_manager->init(
).safe_then([this] {
+ return segment_manager->mkfs(
+ segment_manager::get_ephemeral_device_config(0, 1));
+ }).safe_then([this] {
+ block_size = segment_manager->get_block_size();
+ sms.reset(new SegmentManagerGroup());
+ next = segment_id_t(segment_manager->get_device_id(), 0);
+ journal = journal::make_segmented(*this);
+ journal->set_write_pipeline(&pipeline);
+ sms->add_segment_manager(segment_manager.get());
return journal->open_for_write();
}).safe_then(
[](auto){},
#pragma once
#include <random>
+#include <boost/iterator/counting_iterator.hpp>
#include "crimson/os/seastore/segment_cleaner.h"
#include "crimson/os/seastore/cache.h"
class EphemeralTestState {
protected:
segment_manager::EphemeralSegmentManagerRef segment_manager;
+ std::list<segment_manager::EphemeralSegmentManagerRef> secondary_segment_managers;
- EphemeralTestState() = default;
+ EphemeralTestState(std::size_t num_segment_managers) {
+ assert(num_segment_managers > 0);
+ secondary_segment_managers.resize(num_segment_managers - 1);
+ }
+
+ std::size_t get_num_devices() const {
+ return secondary_segment_managers.size() + 1;
+ }
virtual void _init() = 0;
void init() {
void restart() {
_teardown().get0();
destroy();
- static_cast<segment_manager::EphemeralSegmentManager*>(&*segment_manager)->remount();
+ segment_manager->remount();
+ for (auto &sec_sm : secondary_segment_managers) {
+ sec_sm->remount();
+ }
init();
_mount().handle_error(crimson::ct_error::assert_all{}).get0();
}
seastar::future<> tm_setup() {
segment_manager = segment_manager::create_test_ephemeral();
- init();
+ for (auto &sec_sm : secondary_segment_managers) {
+ sec_sm = segment_manager::create_test_ephemeral();
+ }
return segment_manager->init(
).safe_then([this] {
+ return crimson::do_for_each(
+ secondary_segment_managers.begin(),
+ secondary_segment_managers.end(),
+ [](auto &sec_sm)
+ {
+ return sec_sm->init();
+ });
+ }).safe_then([this] {
+ return segment_manager->mkfs(
+ segment_manager::get_ephemeral_device_config(0, get_num_devices()));
+ }).safe_then([this] {
+ return seastar::do_with(std::size_t(0), [this](auto &cnt) {
+ return crimson::do_for_each(
+ secondary_segment_managers.begin(),
+ secondary_segment_managers.end(),
+ [this, &cnt](auto &sec_sm)
+ {
+ ++cnt;
+ return sec_sm->mkfs(
+ segment_manager::get_ephemeral_device_config(cnt, get_num_devices()));
+ });
+ });
+ }).safe_then([this] {
+ init();
return _mkfs();
}).safe_then([this] {
return _teardown();
}).safe_then([this] {
destroy();
- static_cast<segment_manager::EphemeralSegmentManager*>(
- &*segment_manager)->remount();
+ segment_manager->remount();
+ for (auto &sec_sm : secondary_segment_managers) {
+ sec_sm->remount();
+ }
init();
return _mount();
}).handle_error(crimson::ct_error::assert_all{});
seastar::future<> tm_teardown() {
return _teardown().then([this] {
segment_manager.reset();
+ for (auto &sec_sm : secondary_segment_managers) {
+ sec_sm.reset();
+ }
});
}
};
LBAManager *lba_manager;
SegmentCleaner *segment_cleaner;
- TMTestState() : EphemeralTestState() {}
+ TMTestState() : EphemeralTestState(1) {}
virtual void _init() override {
tm = make_transaction_manager(true);
protected:
std::unique_ptr<SeaStore> seastore;
- SeaStoreTestState() : EphemeralTestState() {}
+ SeaStoreTestState() : EphemeralTestState(1) {}
virtual void _init() final {
seastore = get_seastore(