rollback_info_trimmed_to changes
PGLog::rewind_divergent_log was only causing the log to be marked
dirty and checkpointed if there were divergent entries. However
after a PG split it is possible that the log can be rewound
modifying crt and/or rollback_info_trimmed_to without creating
divergent entries because the entries being rolled back were
all split into the other PG.
Failing to checkpoint the log generates a window where if the OSD
is reset you can end up with crt (and rollback_info_trimmed_to) > head.
One consequence of this is asserts like
ceph_assert(rollback_info_trimmed_to == head); firing.
Fixes: https://tracker.ceph.com/issues/55141
Signed-off-by: Bill Scales <bill_scales@uk.ibm.com>
(cherry picked from commit
d8f78adf85f8cb11deeae3683a28db92046779b5)
if (info.last_complete > newhead)
info.last_complete = newhead;
- auto divergent = log.rewind_from_head(newhead);
+ bool need_dirty_log;
+ auto divergent = log.rewind_from_head(newhead, &need_dirty_log);
if (!divergent.empty()) {
mark_dirty_from(divergent.front().version);
+ } else if (need_dirty_log) {
+ // can_rollback_to and/or rollback_info_trimmed_to have been modified
+ // and need checkpointing
+ dout(10) << "rewind_divergent_log crt = "
+ << log.get_can_rollback_to() << dendl;
+ dirty_log = true;
}
+
for (auto &&entry: divergent) {
dout(10) << "rewind_divergent_log future divergent " << entry << dendl;
}
eversion_t previous_version) {});
}
- mempool::osd_pglog::list<pg_log_entry_t> rewind_from_head(eversion_t newhead) {
- auto divergent = pg_log_t::rewind_from_head(newhead);
+ mempool::osd_pglog::list<pg_log_entry_t> rewind_from_head(eversion_t newhead, bool *dirty_log = nullptr) {
+ auto divergent = pg_log_t::rewind_from_head(newhead, dirty_log);
index();
reset_rollback_info_trimmed_to_riter();
return divergent;
std::move(childdups));
}
- mempool::osd_pglog::list<pg_log_entry_t> rewind_from_head(eversion_t newhead) {
+ mempool::osd_pglog::list<pg_log_entry_t> rewind_from_head(eversion_t newhead, bool *dirty_log = nullptr) {
ceph_assert(newhead >= tail);
mempool::osd_pglog::list<pg_log_entry_t>::iterator p = log.end();
}
head = newhead;
- if (can_rollback_to > newhead)
+ if (can_rollback_to > newhead) {
can_rollback_to = newhead;
+ if (dirty_log) {
+ *dirty_log = true;
+ }
+ }
- if (rollback_info_trimmed_to > newhead)
+ if (rollback_info_trimmed_to > newhead) {
rollback_info_trimmed_to = newhead;
+ if (dirty_log) {
+ *dirty_log = true;
+ }
+ }
return divergent;
}