From: Bill Scales Date: Mon, 23 Jun 2025 09:12:10 +0000 (+0100) Subject: osd: rewind_divergent_log needs to dirty log if crt changes or ... X-Git-Tag: testing/wip-vshankar-testing-20250813.085004-debug~8^2~19 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d8f78adf85f8cb11deeae3683a28db92046779b5;p=ceph-ci.git osd: rewind_divergent_log needs to dirty log if crt changes or ... 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 --- diff --git a/src/osd/PGLog.cc b/src/osd/PGLog.cc index 39b13beb4dc..d0c06cab72a 100644 --- a/src/osd/PGLog.cc +++ b/src/osd/PGLog.cc @@ -349,10 +349,18 @@ void PGLog::rewind_divergent_log(eversion_t newhead, 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; } diff --git a/src/osd/PGLog.h b/src/osd/PGLog.h index 8242a416abf..727786bf15e 100644 --- a/src/osd/PGLog.h +++ b/src/osd/PGLog.h @@ -296,8 +296,8 @@ public: eversion_t previous_version) {}); } - mempool::osd_pglog::list rewind_from_head(eversion_t newhead) { - auto divergent = pg_log_t::rewind_from_head(newhead); + mempool::osd_pglog::list 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; diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index c6d29d1e6a6..0e116e06fab 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -4746,7 +4746,7 @@ public: std::move(childdups)); } - mempool::osd_pglog::list rewind_from_head(eversion_t newhead) { + mempool::osd_pglog::list rewind_from_head(eversion_t newhead, bool *dirty_log = nullptr) { ceph_assert(newhead >= tail); mempool::osd_pglog::list::iterator p = log.end(); @@ -4776,11 +4776,19 @@ public: } 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; }