From 80c756b00927a306249de2d5887c4f4f64e4c679 Mon Sep 17 00:00:00 2001 From: Ronen Friedman Date: Mon, 10 May 2021 16:15:16 +0300 Subject: [PATCH] osd/scrub: separate between PG state flags and internal scrubber operation Modify the scrubber to rely on internal flags for 'should we repair' and 'is this a deep scrub', instead of using PG_STATE_REPAIR & PG_STATE_DEEP_SCRUB. This enables us to implement the 'fix-as-you-go deepscrub' functionality of 'osd_scrub_auto_repair', without displaying REPAIR status to the user. Fixes: https://tracker.ceph.com/issues/50446 Signed-off-by: Ronen Friedman Co-Authored by: Neha Ojha --- src/osd/PrimaryLogScrub.cc | 72 ++++++++++++++++--------------------- src/osd/PrimaryLogScrub.h | 2 -- src/osd/pg_scrubber.cc | 73 +++++++++++++++++++++++--------------- src/osd/pg_scrubber.h | 29 ++++++++++++++- 4 files changed, 104 insertions(+), 72 deletions(-) diff --git a/src/osd/PrimaryLogScrub.cc b/src/osd/PrimaryLogScrub.cc index db44416f988..3747cd69841 100644 --- a/src/osd/PrimaryLogScrub.cc +++ b/src/osd/PrimaryLogScrub.cc @@ -47,10 +47,6 @@ void PrimaryLogScrub::_scrub_finish() << " info stats: " << (info.stats.stats_invalid ? "invalid" : "valid") << dendl; - bool repair = state_test(PG_STATE_REPAIR); - bool deep_scrub = state_test(PG_STATE_DEEP_SCRUB); - const char* mode = (repair ? "repair" : (deep_scrub ? "deep-scrub" : "scrub")); - if (info.stats.stats_invalid) { m_pl_pg->recovery_state.update_stats([=](auto& history, auto& stats) { stats.stats = m_scrub_cstat; @@ -62,7 +58,7 @@ void PrimaryLogScrub::_scrub_finish() m_pl_pg->agent_choose_mode(); } - dout(10) << mode << " got " << m_scrub_cstat.sum.num_objects << "/" + dout(10) << m_mode_desc << " got " << m_scrub_cstat.sum.num_objects << "/" << info.stats.stats.sum.num_objects << " objects, " << m_scrub_cstat.sum.num_object_clones << "/" << info.stats.stats.sum.num_object_clones << " clones, " @@ -100,7 +96,7 @@ void PrimaryLogScrub::_scrub_finish() !info.stats.manifest_stats_invalid) || m_scrub_cstat.sum.num_whiteouts != info.stats.stats.sum.num_whiteouts || m_scrub_cstat.sum.num_bytes != info.stats.stats.sum.num_bytes) { - m_osds->clog->error() << info.pgid << " " << mode << " : stat mismatch, got " + m_osds->clog->error() << info.pgid << " " << m_mode_desc << " : stat mismatch, got " << m_scrub_cstat.sum.num_objects << "/" << info.stats.stats.sum.num_objects << " objects, " << m_scrub_cstat.sum.num_object_clones << "/" @@ -125,7 +121,7 @@ void PrimaryLogScrub::_scrub_finish() << " hit_set_archive bytes."; ++m_shallow_errors; - if (repair) { + if (m_is_repair) { ++m_fixed_count; m_pl_pg->recovery_state.update_stats([this](auto& history, auto& stats) { stats.stats = m_scrub_cstat; @@ -142,7 +138,7 @@ void PrimaryLogScrub::_scrub_finish() } } // Clear object context cache to get repair information - if (repair) + if (m_is_repair) m_pl_pg->object_contexts.clear(); } @@ -157,15 +153,14 @@ void PrimaryLogScrub::log_missing(int missing, LogChannelRef clog, const spg_t& pgid, const char* func, - const char* mode, bool allow_incomplete_clones) { ceph_assert(head); if (allow_incomplete_clones) { - dout(20) << func << " " << mode << " " << pgid << " " << *head << " skipped " + dout(20) << func << " " << m_mode_desc << " " << pgid << " " << *head << " skipped " << missing << " clone(s) in cache tier" << dendl; } else { - clog->info() << mode << " " << pgid << " " << *head << " : " << missing + clog->info() << m_mode_desc << " " << pgid << " " << *head << " : " << missing << " missing clone(s)"; } } @@ -174,7 +169,6 @@ int PrimaryLogScrub::process_clones_to(const std::optional& head, const std::optional& snapset, LogChannelRef clog, const spg_t& pgid, - const char* mode, bool allow_incomplete_clones, std::optional target, vector::reverse_iterator* curclone, @@ -193,7 +187,7 @@ int PrimaryLogScrub::process_clones_to(const std::optional& head, // skip higher-numbered clones in the list. if (!allow_incomplete_clones) { next_clone.snap = **curclone; - clog->error() << mode << " " << pgid << " " << *head << " : expected clone " + clog->error() << m_mode_desc << " " << pgid << " " << *head << " : expected clone " << next_clone << " " << m_missing << " missing"; ++m_shallow_errors; e.set_clone_missing(next_clone.snap); @@ -239,10 +233,6 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, const PGPool& pool = m_pl_pg->pool; bool allow_incomplete_clones = pool.info.allow_incomplete_clones(); - bool repair = state_test(PG_STATE_REPAIR); - bool deep_scrub = state_test(PG_STATE_DEEP_SCRUB); - const char* mode = (repair ? "repair" : (deep_scrub ? "deep-scrub" : "scrub")); - std::optional all_clones; // Unspecified snapid_t or std::nullopt // traverse in reverse order. @@ -274,7 +264,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, // basic checks. if (p->second.attrs.count(OI_ATTR) == 0) { oi = std::nullopt; - m_osds->clog->error() << mode << " " << info.pgid << " " << soid << " : no '" + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : no '" << OI_ATTR << "' attr"; ++m_shallow_errors; soid_error.set_info_missing(); @@ -285,7 +275,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, oi = object_info_t(bv); } catch (ceph::buffer::error& e) { oi = std::nullopt; - m_osds->clog->error() << mode << " " << info.pgid << " " << soid + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : can't decode '" << OI_ATTR << "' attr " << e.what(); ++m_shallow_errors; soid_error.set_info_corrupted(); @@ -295,7 +285,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, if (oi) { if (m_pl_pg->pgbackend->be_get_ondisk_size(oi->size) != p->second.size) { - m_osds->clog->error() << mode << " " << info.pgid << " " << soid + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : on disk size (" << p->second.size << ") does not match object info size (" << oi->size << ") adjusted for ondisk to (" @@ -304,7 +294,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, ++m_shallow_errors; } - dout(20) << mode << " " << soid << " " << *oi << dendl; + dout(20) << m_mode_desc << " " << soid << " " << *oi << dendl; // A clone num_bytes will be added later when we have snapset if (!soid.is_snap()) { @@ -331,7 +321,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, // Expecting an object with snap for current head if (soid.has_snapset() || soid.get_head() != head->get_head()) { - dout(10) << __func__ << " " << mode << " " << info.pgid << " new object " << soid + dout(10) << __func__ << " " << m_mode_desc << " " << info.pgid << " new object " << soid << " while processing " << *head << dendl; target = all_clones; @@ -343,7 +333,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, // Log any clones we were expecting to be there up to target // This will set missing, but will be a no-op if snap.soid == *curclone. missing += - process_clones_to(head, snapset, m_osds->clog, info.pgid, mode, + process_clones_to(head, snapset, m_osds->clog, info.pgid, allow_incomplete_clones, target, &curclone, head_error); } @@ -363,10 +353,10 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, if (!expected) { // If we couldn't read the head's snapset, just ignore clones if (head && !snapset) { - m_osds->clog->error() << mode << " " << info.pgid << " " << soid + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : clone ignored due to missing snapset"; } else { - m_osds->clog->error() << mode << " " << info.pgid << " " << soid + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : is an unexpected clone"; } ++m_shallow_errors; @@ -382,7 +372,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, if (soid.has_snapset()) { if (missing) { - log_missing(missing, head, m_osds->clog, info.pgid, __func__, mode, + log_missing(missing, head, m_osds->clog, info.pgid, __func__, pool.info.allow_incomplete_clones()); } @@ -395,10 +385,10 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, head_error = soid_error; soid_error_count = 0; - dout(20) << __func__ << " " << mode << " new head " << head << dendl; + dout(20) << __func__ << " " << m_mode_desc << " new head " << head << dendl; if (p->second.attrs.count(SS_ATTR) == 0) { - m_osds->clog->error() << mode << " " << info.pgid << " " << soid << " : no '" + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : no '" << SS_ATTR << "' attr"; ++m_shallow_errors; snapset = std::nullopt; @@ -414,7 +404,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, } catch (ceph::buffer::error& e) { snapset = std::nullopt; m_osds->clog->error() - << mode << " " << info.pgid << " " << soid << " : can't decode '" << SS_ATTR + << m_mode_desc << " " << info.pgid << " " << soid << " : can't decode '" << SS_ATTR << "' attr " << e.what(); ++m_shallow_errors; head_error.set_snapset_corrupted(); @@ -429,7 +419,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, dout(20) << " snapset " << *snapset << dendl; if (snapset->seq == 0) { m_osds->clog->error() - << mode << " " << info.pgid << " " << soid << " : snaps.seq not set"; + << m_mode_desc << " " << info.pgid << " " << soid << " : snaps.seq not set"; ++m_shallow_errors; head_error.set_snapset_error(); } @@ -441,24 +431,24 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, ceph_assert(snapset); ceph_assert(soid.snap == *curclone); - dout(20) << __func__ << " " << mode << " matched clone " << soid << dendl; + dout(20) << __func__ << " " << m_mode_desc << " matched clone " << soid << dendl; if (snapset->clone_size.count(soid.snap) == 0) { - m_osds->clog->error() << mode << " " << info.pgid << " " << soid + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : is missing in clone_size"; ++m_shallow_errors; soid_error.set_size_mismatch(); } else { if (oi && oi->size != snapset->clone_size[soid.snap]) { m_osds->clog->error() - << mode << " " << info.pgid << " " << soid << " : size " << oi->size + << m_mode_desc << " " << info.pgid << " " << soid << " : size " << oi->size << " != clone_size " << snapset->clone_size[*curclone]; ++m_shallow_errors; soid_error.set_size_mismatch(); } if (snapset->clone_overlap.count(soid.snap) == 0) { - m_osds->clog->error() << mode << " " << info.pgid << " " << soid + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : is missing in clone_overlap"; ++m_shallow_errors; soid_error.set_size_mismatch(); @@ -481,7 +471,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, } if (bad_interval_set) { - m_osds->clog->error() << mode << " " << info.pgid << " " << soid + m_osds->clog->error() << m_mode_desc << " " << info.pgid << " " << soid << " : bad interval_set in clone_overlap"; ++m_shallow_errors; soid_error.set_size_mismatch(); @@ -502,18 +492,18 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, } if (doing_clones(snapset, curclone)) { - dout(10) << __func__ << " " << mode << " " << info.pgid + dout(10) << __func__ << " " << m_mode_desc << " " << info.pgid << " No more objects while processing " << *head << dendl; missing += - process_clones_to(head, snapset, m_osds->clog, info.pgid, mode, + process_clones_to(head, snapset, m_osds->clog, info.pgid, allow_incomplete_clones, all_clones, &curclone, head_error); } // There could be missing found by the test above or even // before dropping out of the loop for the last head. if (missing) { - log_missing(missing, head, m_osds->clog, info.pgid, __func__, mode, + log_missing(missing, head, m_osds->clog, info.pgid, __func__, allow_incomplete_clones); } if (head && (head_error.errors || soid_error_count)) @@ -528,12 +518,12 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, ObjectContextRef obc = m_pl_pg->get_object_context(p->first, false); if (!obc) { - m_osds->clog->error() << info.pgid << " " << mode + m_osds->clog->error() << info.pgid << " " << m_mode_desc << " cannot get object context for object " << p->first; continue; } if (obc->obs.oi.soid != p->first) { - m_osds->clog->error() << info.pgid << " " << mode << " " << p->first + m_osds->clog->error() << info.pgid << " " << m_mode_desc << " " << p->first << " : object has a valid oi attr with a mismatched name, " << " obc->obs.oi.soid: " << obc->obs.oi.soid; continue; @@ -564,7 +554,7 @@ void PrimaryLogScrub::scrub_snapshot_metadata(ScrubMap& scrubmap, m_pl_pg->simple_opc_submit(std::move(ctx)); } - dout(10) << __func__ << " (" << mode << ") finish" << dendl; + dout(10) << __func__ << " (" << m_mode_desc << ") finish" << dendl; } PrimaryLogScrub::PrimaryLogScrub(PrimaryLogPG* pg) : PgScrubber{pg}, m_pl_pg{pg} {} diff --git a/src/osd/PrimaryLogScrub.h b/src/osd/PrimaryLogScrub.h index d24fa092065..2cf0c71c300 100644 --- a/src/osd/PrimaryLogScrub.h +++ b/src/osd/PrimaryLogScrub.h @@ -62,14 +62,12 @@ class PrimaryLogScrub : public PgScrubber { LogChannelRef clog, const spg_t& pgid, const char* func, - const char* mode, bool allow_incomplete_clones); int process_clones_to(const std::optional& head, const std::optional& snapset, LogChannelRef clog, const spg_t& pgid, - const char* mode, bool allow_incomplete_clones, std::optional target, std::vector::reverse_iterator* curclone, diff --git a/src/osd/pg_scrubber.cc b/src/osd/pg_scrubber.cc index 9a5dba5085f..089a026b08e 100644 --- a/src/osd/pg_scrubber.cc +++ b/src/osd/pg_scrubber.cc @@ -333,6 +333,7 @@ void PgScrubber::reset_epoch(epoch_t epoch_queued) m_epoch_start = epoch_queued; m_needs_sleep = true; m_is_deep = state_test(PG_STATE_DEEP_SCRUB); + update_op_mode_text(); } unsigned int PgScrubber::scrub_requeue_priority(Scrub::scrub_prio_t with_priority) const @@ -744,6 +745,16 @@ std::string PgScrubber::dump_awaited_maps() const return m_maps_status.dump(); } +void PgScrubber::update_op_mode_text() +{ + auto visible_repair = state_test(PG_STATE_REPAIR); + m_mode_desc = (visible_repair ? "repair"sv : (m_is_deep ? "deep-scrub"sv : "scrub"sv)); + + dout(10) << __func__ << ": repair: visible: " << (visible_repair ? "true" : "false") + << ", internal: " << (m_is_repair ? "true" : "false") + << ". Displayed: " << m_mode_desc << dendl; +} + void PgScrubber::_request_scrub_map(pg_shard_t replica, eversion_t version, hobject_t start, @@ -1133,8 +1144,15 @@ void PgScrubber::set_op_parameters(requested_scrub_t& request) state_set(PG_STATE_DEEP_SCRUB); } - if (request.must_repair || m_flags.auto_repair) { + // m_is_repair is set for either 'must_repair' or 'repair-on-the-go' (i.e. + // deep-scrub with the auto_repair configuration flag set). m_is_repair value + // determines the scrubber behavior. + // PG_STATE_REPAIR, on the other hand, is only used for status reports (inc. the + // PG status as appearing in the logs). + m_is_repair = request.must_repair || m_flags.auto_repair; + if (request.must_repair) { state_set(PG_STATE_REPAIR); + // not calling update_op_mode_text() yet, as m_is_deep not set yet } // the publishing here seems to be required for tests synchronization @@ -1191,7 +1209,7 @@ void PgScrubber::scrub_compare_maps() ss.clear(); m_pg->get_pgbackend()->be_compare_scrubmaps( - maps, master_set, state_test(PG_STATE_REPAIR), m_missing, m_inconsistent, + maps, master_set, m_is_repair, m_missing, m_inconsistent, authoritative, missing_digest, m_shallow_errors, m_deep_errors, m_store.get(), m_pg->info.pgid, m_pg->recovery_state.get_acting(), ss); dout(2) << ss.str() << dendl; @@ -1228,7 +1246,7 @@ void PgScrubber::scrub_compare_maps() if (!m_store->empty()) { - if (state_test(PG_STATE_REPAIR)) { + if (m_is_repair) { dout(10) << __func__ << ": discarding scrub results" << dendl; m_store->flush(nullptr); } else { @@ -1439,25 +1457,25 @@ void PgScrubber::unreserve_replicas() [[nodiscard]] bool PgScrubber::scrub_process_inconsistent() { - dout(10) << __func__ << ": checking authoritative" << dendl; - - bool repair = state_test(PG_STATE_REPAIR); - const bool deep_scrub = state_test(PG_STATE_DEEP_SCRUB); - const char* mode = (repair ? "repair" : (deep_scrub ? "deep-scrub" : "scrub")); - dout(20) << __func__ << " deep_scrub: " << deep_scrub << " m_is_deep: " << m_is_deep - << " repair: " << repair << dendl; + dout(10) << __func__ << ": checking authoritative (mode=" + << m_mode_desc << ", auth remaining #: " << m_authoritative.size() + << ")" << dendl; // authoritative only store objects which are missing or inconsistent. if (!m_authoritative.empty()) { stringstream ss; - ss << m_pg->info.pgid << " " << mode << " " << m_missing.size() << " missing, " + ss << m_pg->info.pgid << " " << m_mode_desc << " " << m_missing.size() << " missing, " << m_inconsistent.size() << " inconsistent objects"; dout(2) << ss.str() << dendl; m_osds->clog->error(ss); - if (repair) { + if (m_is_repair) { state_clear(PG_STATE_CLEAN); + // we know we have a problem, so it's OK to set the user-visible flag + // even if we only reached here via auto-repair + state_set(PG_STATE_REPAIR); + update_op_mode_text(); for (const auto& [hobj, shrd_list] : m_authoritative) { @@ -1475,7 +1493,7 @@ void PgScrubber::unreserve_replicas() } } } - return (!m_authoritative.empty() && repair); + return (!m_authoritative.empty() && m_is_repair); } /* @@ -1492,24 +1510,21 @@ void PgScrubber::scrub_finish() // if the repair request comes from auto-repair and large number of errors, // we would like to cancel auto-repair - - bool repair = state_test(PG_STATE_REPAIR); - if (repair && m_flags.auto_repair && + if (m_is_repair && m_flags.auto_repair && m_authoritative.size() > m_pg->cct->_conf->osd_scrub_auto_repair_num_errors) { dout(10) << __func__ << " undoing the repair" << dendl; - state_clear(PG_STATE_REPAIR); - repair = false; + state_clear(PG_STATE_REPAIR); // not expected to be set, anyway + m_is_repair = false; + update_op_mode_text(); } - bool deep_scrub = state_test(PG_STATE_DEEP_SCRUB); - const char* mode = (repair ? "repair" : (deep_scrub ? "deep-scrub" : "scrub")); bool do_auto_scrub = false; // if a regular scrub had errors within the limit, do a deep scrub to auto repair if (m_flags.deep_scrub_on_error && m_authoritative.size() && m_authoritative.size() <= m_pg->cct->_conf->osd_scrub_auto_repair_num_errors) { - ceph_assert(!deep_scrub); + ceph_assert(!m_is_deep); do_auto_scrub = true; dout(15) << __func__ << " Try to auto repair after scrub errors" << dendl; } @@ -1523,16 +1538,16 @@ void PgScrubber::scrub_finish() { stringstream oss; - oss << m_pg->info.pgid.pgid << " " << mode << " "; + oss << m_pg->info.pgid.pgid << " " << m_mode_desc << " "; int total_errors = m_shallow_errors + m_deep_errors; if (total_errors) oss << total_errors << " errors"; else oss << "ok"; - if (!deep_scrub && m_pg->info.stats.stats.sum.num_deep_scrub_errors) + if (!m_is_deep && m_pg->info.stats.stats.sum.num_deep_scrub_errors) oss << " ( " << m_pg->info.stats.stats.sum.num_deep_scrub_errors << " remaining deep scrub error details lost)"; - if (repair) + if (m_is_repair) oss << ", " << m_fixed_count << " fixed"; if (total_errors) m_osds->clog->error(oss); @@ -1542,10 +1557,10 @@ void PgScrubber::scrub_finish() // Since we don't know which errors were fixed, we can only clear them // when every one has been fixed. - if (repair) { + if (m_is_repair) { if (m_fixed_count == m_shallow_errors + m_deep_errors) { - ceph_assert(deep_scrub); + ceph_assert(m_is_deep); m_shallow_errors = 0; m_deep_errors = 0; dout(20) << __func__ << " All may be fixed" << dendl; @@ -1574,7 +1589,7 @@ void PgScrubber::scrub_finish() // finish up ObjectStore::Transaction t; m_pg->recovery_state.update_stats( - [this, deep_scrub](auto& history, auto& stats) { + [this](auto& history, auto& stats) { dout(10) << "m_pg->recovery_state.update_stats()" << dendl; utime_t now = ceph_clock_now(); history.last_scrub = m_pg->recovery_state.get_info().last_update; @@ -1584,7 +1599,7 @@ void PgScrubber::scrub_finish() history.last_deep_scrub_stamp = now; } - if (deep_scrub) { + if (m_is_deep) { if ((m_shallow_errors == 0) && (m_deep_errors == 0)) history.last_clean_scrub_stamp = now; stats.stats.sum.num_shallow_scrub_errors = m_shallow_errors; @@ -1628,7 +1643,9 @@ void PgScrubber::scrub_finish() m_pg->queue_peering_event(PGPeeringEventRef(std::make_shared( get_osdmap_epoch(), get_osdmap_epoch(), PeeringState::DoRecovery()))); } else { + m_is_repair = false; state_clear(PG_STATE_REPAIR); + update_op_mode_text(); } cleanup_on_finish(); diff --git a/src/osd/pg_scrubber.h b/src/osd/pg_scrubber.h index bbbac38ca75..176a00a23e9 100644 --- a/src/osd/pg_scrubber.h +++ b/src/osd/pg_scrubber.h @@ -559,7 +559,7 @@ class PgScrubber : public ScrubPgIF, public ScrubMachineListener { /// Maps from objects with errors to missing peers HobjToShardSetMapping m_missing; - private: + protected: /** * 'm_is_deep' - is the running scrub a deep one? * @@ -570,6 +570,33 @@ class PgScrubber : public ScrubPgIF, public ScrubMachineListener { */ bool m_is_deep{false}; + /** + * If set: affects the backend & scrubber-backend functions called after all + * scrub maps are available. + * + * Replaces code that directly checks PG_STATE_REPAIR (which was meant to be + * a "user facing" status display only). + */ + bool m_is_repair{false}; + + /** + * User-readable summary of the scrubber's current mode of operation. Used for + * both osd.*.log and the cluster log. + * One of: + * "repair" + * "deep-scrub", + * "scrub + * + * Note: based on PG_STATE_REPAIR, and not on m_is_repair. I.e. for + * auto_repair will show as "deep-scrub" and not as "repair" (until the first error + * is detected). + */ + std::string_view m_mode_desc; + + void update_op_mode_text(); + +private: + /** * initiate a deep-scrub after the current scrub ended with errors. */ -- 2.39.5