0,
t.root->get_version() - 1,
MAX_SEG_SEQ,
+ segment_type_t::NULL_SEG,
std::move(delta_bl)
});
} else {
cleaner
? cleaner->get_seq(i->get_paddr().as_seg_paddr().get_segment_id())
: MAX_SEG_SEQ,
+ cleaner
+ ? cleaner->get_type(i->get_paddr().as_seg_paddr().get_segment_id())
+ : segment_type_t::NULL_SEG,
std::move(delta_bl)
});
i->last_committed_crc = final_crc;
virtual replay_ret replay(
delta_handler_t &&delta_handler) = 0;
- virtual SegmentSeqAllocator& get_segment_seq_allocator() = 0;
-
virtual ~Journal() {}
};
using JournalRef = std::unique_ptr<Journal>;
ExtentReader &scanner,
SegmentProvider &segment_provider)
: segment_provider(segment_provider),
- segment_seq_allocator(new SegmentSeqAllocator),
+ segment_seq_allocator(
+ new SegmentSeqAllocator(segment_type_t::JOURNAL)),
journal_segment_allocator("JOURNAL",
segment_type_t::JOURNAL,
segment_provider,
if (delta.paddr != P_ADDR_NULL) {
auto& seg_addr = delta.paddr.as_seg_paddr();
auto delta_paddr_segment_seq = segment_provider.get_seq(seg_addr.get_segment_id());
+ auto delta_paddr_segment_type = segment_provider.get_type(seg_addr.get_segment_id());
if (s_type == segment_type_t::NULL_SEG ||
- (delta_paddr_segment_seq != delta.ext_seq)) {
+ (delta_paddr_segment_seq != delta.ext_seq ||
+ delta_paddr_segment_type != delta.seg_type)) {
SUBDEBUG(seastore_cache,
- "delta is obsolete, delta_paddr_segment_seq={}, -- {}",
+ "delta is obsolete, delta_paddr_segment_seq={},"
+ " delta_paddr_segment_type={} -- {}",
segment_seq_printer_t{delta_paddr_segment_seq},
+ delta_paddr_segment_type,
delta);
- assert(delta_paddr_segment_seq > delta.ext_seq);
return replay_ertr::now();
}
}
write_pipeline = _write_pipeline;
}
- SegmentSeqAllocator& get_segment_seq_allocator() final {
- return *segment_seq_allocator;
- }
private:
submit_record_ret do_submit_record(
record_t &&record,
<< ", length: " << delta.length
<< ", pversion: " << delta.pversion
<< ", ext_seq: " << delta.ext_seq
+ << ", seg_type: " << delta.seg_type
<< ")";
}
static constexpr segment_seq_t NULL_SEG_SEQ = MAX_SEG_SEQ;
static constexpr segment_seq_t MAX_VALID_SEG_SEQ = MAX_SEG_SEQ - 2;
-enum class segment_type_t {
+enum class segment_type_t : uint8_t {
JOURNAL = 0,
OOL,
NULL_SEG,
seastore_off_t length = NULL_SEG_OFF; ///< extent length
extent_version_t pversion; ///< prior version
segment_seq_t ext_seq; ///< seq of the extent's segment
+ segment_type_t seg_type;
ceph::bufferlist bl; ///< payload
DENC(delta_info_t, v, p) {
denc(v.length, p);
denc(v.pversion, p);
denc(v.ext_seq, p);
+ denc(v.seg_type, p);
denc(v.bl, p);
DENC_FINISH(p);
}
: detailed(detailed),
config(config),
scanner(std::move(scr)),
+ ool_segment_seq_allocator(
+ new SegmentSeqAllocator(segment_type_t::OOL)),
gc_process(*this)
{}
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/segment_manager.h"
#include "crimson/os/seastore/transaction.h"
+#include "crimson/os/seastore/segment_seq_allocator.h"
namespace crimson::os::seastore {
virtual segment_seq_t get_seq(segment_id_t id) { return 0; }
+ virtual segment_type_t get_type(segment_id_t id) = 0;
+
virtual seastar::lowres_system_clock::time_point get_last_modified(
segment_id_t id) const = 0;
/// populated if there is an IO blocked on hard limits
std::optional<seastar::promise<>> blocked_io_wake;
+ SegmentSeqAllocatorRef ool_segment_seq_allocator;
+
public:
SegmentCleaner(
config_t config,
ExtentReaderRef&& scanner,
bool detailed = false);
+ SegmentSeqAllocator& get_ool_segment_seq_allocator() {
+ return *ool_segment_seq_allocator;
+ }
+
using mount_ertr = crimson::errorator<
crimson::ct_error::input_output_error>;
using mount_ret = mount_ertr::future<>;
return segments[id].journal_segment_seq;
}
+ segment_type_t get_type(segment_id_t id) final {
+ return segments[id].get_type();
+ }
+
void mark_segment_released(segment_id_t segment) {
stats.segments_released++;
return mark_empty(segment);
segment_seq_t seq,
segment_type_t s_type) {
crimson::get_logger(ceph_subsys_seastore_cleaner).debug(
- "SegmentCleaner::init_mark_segment_closed: segment {}, seq {}",
+ "SegmentCleaner::init_mark_segment_closed: segment {}, seq {}, s_type {}",
segment,
- segment_seq_printer_t{seq});
+ segment_seq_printer_t{seq},
+ s_type);
mark_closed(segment);
segments[segment].journal_segment_seq = seq;
assert(s_type != segment_type_t::NULL_SEG);
if (s_type == segment_type_t::JOURNAL) {
assert(journal_device_id == segment.device_id());
segments.new_journal_segment();
+ } else {
+ assert(s_type == segment_type_t::OOL);
+ ool_segment_seq_allocator->set_next_segment_seq(seq);
}
}
assert(stats.empty_segments > 0);
stats.empty_segments--;
crimson::get_logger(ceph_subsys_seastore_cleaner
- ).info("mark open: {} {}, empty_segments {}"
+ ).info("mark open: {} {} {}, empty_segments {}"
", opened_segments {}, should_block_on_gc {}"
", projected_avail_ratio {}, projected_reclaim_ratio {}",
segment,
segment_seq_printer_t{seq},
+ segment_info.type,
stats.empty_segments,
segments.get_opened_segments(),
should_block_on_gc(),
#include "crimson/os/seastore/logging.h"
#include "crimson/os/seastore/seastore_types.h"
+namespace crimson::os::seastore {
+class SegmentCleaner;
+}
+
namespace crimson::os::seastore::journal {
class SegmentedJournal;
}
class SegmentSeqAllocator {
public:
+ SegmentSeqAllocator(segment_type_t type)
+ : type(type) {}
segment_seq_t get_and_inc_next_segment_seq() {
return next_segment_seq++;
}
private:
void set_next_segment_seq(segment_seq_t seq) {
LOG_PREFIX(SegmentSeqAllocator::set_next_segment_seq);
- SUBINFO(seastore_journal, "next_segment_seq={}", segment_seq_printer_t{seq});
- next_segment_seq = seq;
+ SUBINFO(
+ seastore_journal,
+ "type {}, next_segment_seq={}, cur_segment_seq={}",
+ type,
+ segment_seq_printer_t{seq},
+ segment_seq_printer_t{next_segment_seq});
+ assert(type == segment_type_t::JOURNAL
+ ? seq >= next_segment_seq
+ : true);
+ if (seq > next_segment_seq)
+ next_segment_seq = seq;
}
segment_seq_t next_segment_seq = 0;
+ segment_type_t type = segment_type_t::NULL_SEG;
friend class journal::SegmentedJournal;
+ friend class SegmentCleaner;
};
using SegmentSeqAllocatorRef =
std::make_unique<SegmentedAllocator>(
*segment_cleaner,
*sm,
- journal->get_segment_seq_allocator()));
+ segment_cleaner->get_ool_segment_seq_allocator()));
}
~TransactionManager();
btree_test_base() = default;
std::map<segment_id_t, segment_seq_t> segment_seqs;
-
+ std::map<segment_id_t, segment_type_t> segment_types;
seastar::lowres_system_clock::time_point get_last_modified(
segment_id_t get_segment(
device_id_t id,
segment_seq_t seq,
- segment_type_t) final
+ segment_type_t type) final
{
auto ret = next;
next = segment_id_t{
next.device_id(),
next.device_segment_id() + 1};
segment_seqs[ret] = seq;
+ segment_types[ret] = type;
return ret;
}
return segment_seqs[id];
}
+ segment_type_t get_type(segment_id_t id) {
+ return segment_types[id];
+ }
+
journal_seq_t get_journal_tail_target() const final { return journal_seq_t{}; }
void update_journal_tail_committed(journal_seq_t committed) final {}
segment_id_t next;
std::map<segment_id_t, segment_seq_t> segment_seqs;
+ std::map<segment_id_t, segment_type_t> segment_types;
journal_test_t() = default;
segment_id_t get_segment(
device_id_t id,
segment_seq_t seq,
- segment_type_t) final
+ segment_type_t type) final
{
auto ret = next;
next = segment_id_t{
next.device_id(),
next.device_segment_id() + 1};
segment_seqs[ret] = seq;
+ segment_types[ret] = type;
return ret;
}
return segment_seqs[id];
}
+ segment_type_t get_type(segment_id_t id) final {
+ return segment_types[id];
+ }
+
journal_seq_t get_journal_tail_target() const final { return journal_seq_t{}; }
void update_journal_tail_committed(journal_seq_t paddr) final {}
block_size,
1,
MAX_SEG_SEQ,
+ segment_type_t::NULL_SEG,
bl
};
}