logger().debug("replay_segment: starting at {}", seq);
return seastar::do_with(
delta_scan_handler_t(
- [&handler, seq](auto addr, auto base, const auto &delta) {
- return handler(
- journal_seq_t{seq.segment_seq, addr},
- base,
- delta);
+ [=, &handler](auto addr, auto base, const auto &delta) {
+ /* The journal may validly contain deltas for extents in since released
+ * segments. We can detect those cases by whether the segment in question
+ * currently has a sequence number > the current journal segment seq.
+ * We can safely skip these deltas because the extent must already have
+ * been rewritten.
+ *
+ * Note, this comparison exploits the fact that SEGMENT_SEQ_NULL is
+ * a large number.
+ */
+ if (delta.paddr != P_ADDR_NULL &&
+ segment_provider->get_seq(delta.paddr.segment) > seq.segment_seq) {
+ return replay_ertr::now();
+ } else {
+ return handler(
+ journal_seq_t{seq.segment_seq, addr},
+ base,
+ delta);
+ }
}),
[this, seq](auto &dhandler) {
return scan_segment(
virtual void init_mark_segment_closed(
segment_id_t segment, segment_seq_t seq) {}
+ virtual segment_seq_t get_seq(segment_id_t id) { return 0; }
+
virtual ~JournalSegmentProvider() {}
};