#include "segment_allocator.h"
+#include <sstream>
+
#include "crimson/os/seastore/logging.h"
#include "crimson/os/seastore/segment_cleaner.h"
namespace crimson::os::seastore::journal {
-static segment_nonce_t generate_nonce(
- segment_seq_t seq,
- const seastore_meta_t &meta)
-{
- return ceph_crc32c(
- seq,
- reinterpret_cast<const unsigned char *>(meta.seastore_id.bytes()),
- sizeof(meta.seastore_id.uuid));
-}
-
SegmentAllocator::SegmentAllocator(
std::string name,
segment_type_t type,
segment_manager{sm}
{
ceph_assert(type != segment_type_t::NULL_SEG);
+ std::ostringstream oss;
+ oss << "D?_" << name;
+ print_name = oss.str();
reset();
}
void SegmentAllocator::set_next_segment_seq(segment_seq_t seq)
{
LOG_PREFIX(SegmentAllocator::set_next_segment_seq);
- INFO("{} {} next_segment_seq={}",
- name, get_device_id(), segment_seq_printer_t{seq});
+ INFO("{} next_segment_seq={}",
+ print_name, segment_seq_printer_t{seq});
assert(type == segment_seq_to_type(seq));
next_segment_seq = seq;
}
{
LOG_PREFIX(SegmentAllocator::open);
ceph_assert(!current_segment);
- segment_seq_t new_segment_seq;
- if (type == segment_type_t::JOURNAL) {
- new_segment_seq = next_segment_seq++;
- } else { // OOL
- new_segment_seq = next_segment_seq;
- }
- assert(new_segment_seq == get_current_segment_seq());
- ceph_assert(segment_seq_to_type(new_segment_seq) == type);
+ std::ostringstream oss;
+ oss << "D" << device_id_printer_t{get_device_id()} << "_" << name;
+ print_name = oss.str();
+ segment_seq_t new_segment_seq = get_new_segment_seq_and_increment();
auto new_segment_id = segment_provider.get_segment(
get_device_id(), new_segment_seq);
return segment_manager.open(new_segment_id
journal_seq_t new_journal_tail;
if (type == segment_type_t::JOURNAL) {
new_journal_tail = segment_provider.get_journal_tail_target();
- current_segment_nonce = generate_nonce(
- new_segment_seq, segment_manager.get_meta());
} else { // OOL
new_journal_tail = NO_DELTAS;
- assert(current_segment_nonce == 0);
}
segment_id_t segment_id = sref->get_segment_id();
auto header = segment_header_t{
segment_id,
new_journal_tail,
current_segment_nonce};
- INFO("{} {} writing header to new segment ... -- {}",
- name, get_device_id(), header);
+ INFO("{} writing header to new segment ... -- {}",
+ print_name, header);
auto header_length = segment_manager.get_block_size();
bufferlist bl;
if (type == segment_type_t::JOURNAL) {
segment_provider.update_journal_tail_committed(new_journal_tail);
}
- DEBUG("{} {} rolled new segment id={}",
- name, get_device_id(), current_segment->get_segment_id());
+ DEBUG("{} rolled new segment id={}",
+ print_name, current_segment->get_segment_id());
ceph_assert(new_journal_seq.segment_seq == get_current_segment_seq());
return new_journal_seq;
});
paddr_t::make_seg_paddr(
current_segment->get_segment_id(), write_start_offset)
};
- TRACE("{} {} {}~{}", name, get_device_id(), write_start_seq, write_length);
+ TRACE("{} {}~{}", print_name, write_start_seq, write_length);
assert(write_length > 0);
assert((write_length % segment_manager.get_block_size()) == 0);
assert(!needs_roll(write_length));
if (current_segment) {
return close_segment(false);
} else {
- INFO("{} {} no current segment", name, get_device_id());
+ INFO("{} no current segment", print_name);
return close_segment_ertr::now();
}
}().finally([this] {
{
LOG_PREFIX(SegmentAllocator::close_segment);
assert(can_write());
- auto close_segment_id = current_segment->get_segment_id();
- INFO("{} {} close segment id={}, seq={}, written_to={}, nonce={}",
- name, get_device_id(),
+ // Note: make sure no one can access the current segment once closing
+ auto seg_to_close = std::move(current_segment);
+ auto close_segment_id = seg_to_close->get_segment_id();
+ INFO("{} close segment id={}, seq={}, written_to={}, nonce={}",
+ print_name,
close_segment_id,
segment_seq_printer_t{get_current_segment_seq()},
written_to,
if (is_rolling) {
segment_provider.close_segment(close_segment_id);
}
- segment_seq_t cur_segment_seq;
- if (type == segment_type_t::JOURNAL) {
- cur_segment_seq = next_segment_seq - 1;
- } else { // OOL
- cur_segment_seq = next_segment_seq;
- }
journal_seq_t cur_journal_tail;
if (type == segment_type_t::JOURNAL) {
cur_journal_tail = segment_provider.get_journal_tail_target();
cur_journal_tail = NO_DELTAS;
}
auto tail = segment_tail_t{
- cur_segment_seq,
+ get_current_segment_seq(),
close_segment_id,
cur_journal_tail,
current_segment_nonce,
assert(bl.length() ==
(size_t)segment_manager.get_rounded_tail_length());
- return current_segment->write(
+ return seg_to_close->write(
segment_manager.get_segment_size()
- segment_manager.get_rounded_tail_length(),
- bl).safe_then([this] {
- return current_segment->close();
- }).safe_then([this] {
- current_segment.reset();
+ bl
+ ).safe_then([seg_to_close=std::move(seg_to_close)] {
+ return seg_to_close->close();
}).handle_error(
close_segment_ertr::pass_further{},
crimson::ct_error::assert_all{
SegmentManager &sm);
const std::string& get_name() const {
- return name;
+ return print_name;
}
device_id_t get_device_id() const {
private:
void reset() {
current_segment.reset();
- if (type == segment_type_t::JOURNAL) {
- next_segment_seq = 0;
- } else { // OOL
- next_segment_seq = OOL_SEG_SEQ;
- }
- current_segment_nonce = 0;
written_to = 0;
+
+ // segment type related special handling
+ reset_segment_seq();
+ current_segment_nonce = 0;
}
// FIXME: remove the unnecessary is_rolling
using close_segment_ertr = base_ertr;
close_segment_ertr::future<> close_segment(bool is_rolling);
+ /*
+ * segment type related special handling
+ */
+
+ void reset_segment_seq() {
+ if (type == segment_type_t::JOURNAL) {
+ next_segment_seq = 0;
+ } else { // OOL
+ next_segment_seq = OOL_SEG_SEQ;
+ }
+ }
+
segment_seq_t get_current_segment_seq() const {
segment_seq_t ret;
if (type == segment_type_t::JOURNAL) {
return ret;
}
+ segment_seq_t get_new_segment_seq_and_increment() {
+ segment_seq_t new_segment_seq;
+ if (type == segment_type_t::JOURNAL) {
+ new_segment_seq = next_segment_seq++;
+ auto meta = segment_manager.get_meta();
+ current_segment_nonce = ceph_crc32c(
+ new_segment_seq,
+ reinterpret_cast<const unsigned char *>(meta.seastore_id.bytes()),
+ sizeof(meta.seastore_id.uuid));
+ } else { // OOL
+ new_segment_seq = next_segment_seq;
+ assert(current_segment_nonce == 0);
+ }
+ assert(new_segment_seq == get_current_segment_seq());
+ ceph_assert(segment_seq_to_type(new_segment_seq) == type);
+ return new_segment_seq;
+ }
+
const std::string name;
+ // device id is not available during construction,
+ // so generate the print_name later.
+ std::string print_name;
const segment_type_t type; // JOURNAL or OOL
SegmentProvider &segment_provider;
SegmentManager &segment_manager;
SegmentRef current_segment;
+ seastore_off_t written_to;
+
+ // segment type related special handling
segment_seq_t next_segment_seq;
segment_nonce_t current_segment_nonce;
- seastore_off_t written_to;
+ //3. journal tail written to both segment_header_t and segment_tail_t
};
/**