From: Dan van der Ster Date: Thu, 1 Jul 2021 14:12:26 +0000 (+0200) Subject: mon/OSDMonitor: account for PG merging in epoch_by_pg accounting X-Git-Tag: v15.2.15~9^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f30d1c43656c4b079d6d14a40dc5ad2d1a1892ab;p=ceph.git mon/OSDMonitor: account for PG merging in epoch_by_pg accounting After a pool has merged PGs, the epoch_by_pg accounting will refer to osdmap epochs of PGs that no longer exist. We'll never again get OSD beacons for these PGs, so the min epoch in epoch_by_pg will not advance until the mon leader has restarted. The effect of this is that osdmaps are not trimmed after a pool has undergone PG merging, until the mon leader restarts. To fix, we unconditionally resize epoch_by_pg to the pg_num of the pool during each beacon report. Fixes: https://tracker.ceph.com/issues/48212 Signed-off-by: Dan van der Ster (cherry picked from commit cf5ea22cc0b10560c9fa3fbd5d93431f874d38b9) --- diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 877ce53a6fd4..d69b8f542b72 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -318,11 +318,14 @@ bool is_unmanaged_snap_op_permitted(CephContext* cct, } // anonymous namespace -void LastEpochClean::Lec::report(ps_t ps, epoch_t last_epoch_clean) +void LastEpochClean::Lec::report(unsigned pg_num, ps_t ps, + epoch_t last_epoch_clean) { - if (epoch_by_pg.size() <= ps) { - epoch_by_pg.resize(ps + 1, 0); + if (ps >= pg_num) { + // removed PG + return; } + epoch_by_pg.resize(pg_num, 0); const auto old_lec = epoch_by_pg[ps]; if (old_lec >= last_epoch_clean) { // stale lec @@ -354,10 +357,11 @@ void LastEpochClean::remove_pool(uint64_t pool) report_by_pool.erase(pool); } -void LastEpochClean::report(const pg_t& pg, epoch_t last_epoch_clean) +void LastEpochClean::report(unsigned pg_num, const pg_t& pg, + epoch_t last_epoch_clean) { auto& lec = report_by_pool[pg.pool()]; - return lec.report(pg.ps(), last_epoch_clean); + return lec.report(pg_num, pg.ps(), last_epoch_clean); } epoch_t LastEpochClean::get_lower_bound(const OSDMap& latest) const @@ -4322,7 +4326,10 @@ bool OSDMonitor::prepare_beacon(MonOpRequestRef op) osd_epochs[from] = beacon->version; for (const auto& pg : beacon->pgs) { - last_epoch_clean.report(pg, beacon->min_last_epoch_clean); + if (auto* pool = osdmap.get_pg_pool(pg.pool()); pool != nullptr) { + unsigned pg_num = pool->get_pg_num(); + last_epoch_clean.report(pg_num, pg, beacon->min_last_epoch_clean); + } } if (osdmap.osd_xinfo[from].last_purged_snaps_scrub < diff --git a/src/mon/OSDMonitor.h b/src/mon/OSDMonitor.h index fb941a6a0e56..7986eb02d703 100644 --- a/src/mon/OSDMonitor.h +++ b/src/mon/OSDMonitor.h @@ -111,11 +111,11 @@ class LastEpochClean { vector epoch_by_pg; ps_t next_missing = 0; epoch_t floor = std::numeric_limits::max(); - void report(ps_t pg, epoch_t last_epoch_clean); + void report(unsigned pg_num, ps_t pg, epoch_t last_epoch_clean); }; std::map report_by_pool; public: - void report(const pg_t& pg, epoch_t last_epoch_clean); + void report(unsigned pg_num, const pg_t& pg, epoch_t last_epoch_clean); void remove_pool(uint64_t pool); epoch_t get_lower_bound(const OSDMap& latest) const;