From 2cde19ad6be883e2fefa822fd53b99214b161836 Mon Sep 17 00:00:00 2001 From: Bill Scales Date: Fri, 27 Jun 2025 13:35:58 +0100 Subject: [PATCH] osd: EC Optimizations fix peering bug causing unfound objects Fix some unusual scenarios where peering was incorrectly declaring that objects were missing on stray shards. When proc_master_log rolls forward partial writes it need to update pwlc exactly the same way as if the write had been completed. This ensures that stray shards that were not updated because of partial writes do not cause objects to be incorrectly marked as missing. The fix also means some code in GetMissing which was trying to do a similar thing for shards that were acting, recovering or backfilling (but not stray) can be deleted. Signed-off-by: Bill Scales (cherry picked from commit 83a9c0a9f8e9ed4f514adb32f1ae2df1602c3f88) --- src/osd/PeeringState.cc | 75 +++++++---------------------------------- 1 file changed, 13 insertions(+), 62 deletions(-) diff --git a/src/osd/PeeringState.cc b/src/osd/PeeringState.cc index d8b0af10cb2..521af37c836 100644 --- a/src/osd/PeeringState.cc +++ b/src/osd/PeeringState.cc @@ -3337,6 +3337,8 @@ void PeeringState::proc_master_log( can_check_next_entry = true; } } + PGLog::LogEntryHandlerRef rollbacker{pl->get_log_handler(t)}; + bool update_pwlc = false; while (can_check_next_entry) { ++p; if (p == pg_log.get_log().log.end()) { @@ -3379,10 +3381,20 @@ void PeeringState::proc_master_log( // This entry can be kept, only shards that didn't participate in // the partial write missed the update psdout(20) << "keeping entry " << p->version << dendl; - olog.head = p->version; + rollbacker.get()->partial_write(&info, olog.head, *p); + update_pwlc = true; + olog.head = p->version; // We need to continue processing the log, so don't break. } + if (update_pwlc) { + psdout(20) << "applying pwlc updates" << dendl; + for (auto & [shard, peer] : peer_info) { + if (info.partial_writes_last_complete.contains(shard.shard)) { + apply_pwlc(info.partial_writes_last_complete[shard.shard], shard, peer); + } + } + } } // merge log into our own log to build master log. no need to // make any adjustments to their missing map; we are taking their @@ -7786,67 +7798,6 @@ PeeringState::GetMissing::GetMissing(my_context ctx) continue; } - // If the peer log is only divergent because of partial writes then - // roll forward the peer to cover writes it was not involved in. - if (pi.last_update < ps->info.last_update) { - // Search backwards through log looking for a match with peer's head - // entry - mempool::osd_pglog::list::const_iterator p = - ps->pg_log.get_log().log.end(); - while (p != ps->pg_log.get_log().log.begin()) { - --p; - if (p->version.version <= pi.last_update.version) { - break; - } - } - if (pi.last_update == pi.last_complete && - p->version == pi.last_update) { - // Matched peer's head entry - see if we can advance last_update - // because of partial written shards - eversion_t old_last_update = pi.last_update; - if (ps->info.partial_writes_last_complete.contains(i->shard) && - ps->info.partial_writes_last_complete[i->shard].first < - old_last_update) { - old_last_update = - ps->info.partial_writes_last_complete[i->shard].first; - } - ++p; - bool advanced = false; - while (p != ps->pg_log.get_log().log.end()) { - if (p->is_written_shard(i->shard)) { - psdout(20) << "log entry " << p->version - << " written_shards=" << p->written_shards - << " is divergent" << dendl; - break; - } - pi.last_update = p->version; - pi.last_complete = p->version; - // Update partial_writes_last_complete - if (ps->info.partial_writes_last_complete.contains(i->shard)) { - // Existing pwlc entry - only update if p->version is newer - if (ps->info.partial_writes_last_complete[i->shard].second < - p->version) { - ps->info.partial_writes_last_complete[i->shard] = - std::pair(old_last_update, p->version); - } - } else { - // No existing pwlc entry - create one - ps->info.partial_writes_last_complete[i->shard] = - std::pair(old_last_update, p->version); - } - advanced = true; - ++p; - } - if (advanced) { - psdout(20) << "shard " << i->shard << " pwlc=" - << ps->info.partial_writes_last_complete.at(i->shard) - << " last_complete=" << ps->info.last_complete - << " last_update=" << pi.last_update - << dendl; - } - } - } - if (pi.last_update == pi.last_complete && // peer has no missing pi.last_update == ps->info.last_update) { // peer is up to date // replica has no missing and identical log as us. no need to -- 2.39.5