]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: EC Optimizations fix peering bug causing unfound objects
authorBill Scales <bill_scales@uk.ibm.com>
Fri, 27 Jun 2025 12:35:58 +0000 (13:35 +0100)
committerAlex Ainscow <aainscow@uk.ibm.com>
Sun, 7 Sep 2025 23:10:41 +0000 (00:10 +0100)
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 <bill_scales@uk.ibm.com>
(cherry picked from commit 83a9c0a9f8e9ed4f514adb32f1ae2df1602c3f88)

src/osd/PeeringState.cc

index d8b0af10cb214e1616fdf24277da0ce791133d1a..521af37c836f582f5fe5e6033c7bb4a3a5c487d6 100644 (file)
@@ -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<pg_log_entry_t>::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