diff options
Diffstat (limited to 'src/osd/scrubber/PrimaryLogScrub.cc')
-rw-r--r-- | src/osd/scrubber/PrimaryLogScrub.cc | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/src/osd/scrubber/PrimaryLogScrub.cc b/src/osd/scrubber/PrimaryLogScrub.cc new file mode 100644 index 000000000..74661ab12 --- /dev/null +++ b/src/osd/scrubber/PrimaryLogScrub.cc @@ -0,0 +1,260 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "./PrimaryLogScrub.h" + +#include <sstream> + +#include "common/scrub_types.h" +#include "osd/PeeringState.h" +#include "osd/PrimaryLogPG.h" +#include "osd/osd_types_fmt.h" + +#include "scrub_machine.h" + +#define dout_context (m_osds->cct) +#define dout_subsys ceph_subsys_osd +#undef dout_prefix +#define dout_prefix _prefix(_dout, this) + +template <class T> +static ostream& _prefix(std::ostream* _dout, T* t) +{ + return t->gen_prefix(*_dout); +} + +using namespace Scrub; + +bool PrimaryLogScrub::get_store_errors(const scrub_ls_arg_t& arg, + scrub_ls_result_t& res_inout) const +{ + if (!m_store) { + return false; + } + + if (arg.get_snapsets) { + res_inout.vals = m_store->get_snap_errors(m_pg->get_pgid().pool(), + arg.start_after, + arg.max_return); + } else { + res_inout.vals = m_store->get_object_errors(m_pg->get_pgid().pool(), + arg.start_after, + arg.max_return); + } + return true; +} + +/// \todo combine the multiple transactions into a single one +void PrimaryLogScrub::submit_digest_fixes(const digests_fixes_t& fixes) +{ + // note: the following line was modified from '+=' to '=', as we should not + // encounter previous-chunk digest updates after starting a new chunk + num_digest_updates_pending = fixes.size(); + dout(10) << __func__ + << ": num_digest_updates_pending: " << num_digest_updates_pending + << dendl; + + for (auto& [obj, dgs] : fixes) { + + ObjectContextRef obc = m_pl_pg->get_object_context(obj, false); + if (!obc) { + m_osds->clog->error() << m_pg_id << " " << m_mode_desc + << " cannot get object context for object " << obj; + num_digest_updates_pending--; + continue; + } + dout(15) << fmt::format( + "{}: {}, pg[{}] {}/{}", __func__, num_digest_updates_pending, + m_pg_id, obj, dgs) + << dendl; + if (obc->obs.oi.soid != obj) { + m_osds->clog->error() + << m_pg_id << " " << m_mode_desc << " " << obj + << " : object has a valid oi attr with a mismatched name, " + << " obc->obs.oi.soid: " << obc->obs.oi.soid; + num_digest_updates_pending--; + continue; + } + + PrimaryLogPG::OpContextUPtr ctx = m_pl_pg->simple_opc_create(obc); + ctx->at_version = m_pl_pg->get_next_version(); + ctx->mtime = utime_t(); // do not update mtime + if (dgs.first) { + ctx->new_obs.oi.set_data_digest(*dgs.first); + } else { + ctx->new_obs.oi.clear_data_digest(); + } + if (dgs.second) { + ctx->new_obs.oi.set_omap_digest(*dgs.second); + } else { + ctx->new_obs.oi.clear_omap_digest(); + } + m_pl_pg->finish_ctx(ctx.get(), pg_log_entry_t::MODIFY); + + + ctx->register_on_success([this]() { + if ((num_digest_updates_pending >= 1) && + (--num_digest_updates_pending == 0)) { + m_osds->queue_scrub_digest_update(m_pl_pg, + m_pl_pg->is_scrub_blocking_ops()); + } + }); + + m_pl_pg->simple_opc_submit(std::move(ctx)); + } +} + +// a forwarder used by the scrubber backend + +void PrimaryLogScrub::add_to_stats(const object_stat_sum_t& stat) +{ + m_scrub_cstat.add(stat); +} + + +void PrimaryLogScrub::_scrub_finish() +{ + auto& info = m_pg->get_pg_info(ScrubberPasskey{}); ///< a temporary alias + + dout(10) << __func__ << " info stats: " + << (info.stats.stats_invalid ? "invalid" : "valid") + << " m_is_repair: " << m_is_repair << dendl; + + if (info.stats.stats_invalid) { + m_pl_pg->recovery_state.update_stats([=, this](auto& history, auto& stats) { + stats.stats = m_scrub_cstat; + stats.stats_invalid = false; + return false; + }); + + if (m_pl_pg->agent_state) { + m_pl_pg->agent_choose_mode(); + } + } + + 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, " + << m_scrub_cstat.sum.num_objects_dirty << "/" + << info.stats.stats.sum.num_objects_dirty << " dirty, " + << m_scrub_cstat.sum.num_objects_omap << "/" + << info.stats.stats.sum.num_objects_omap << " omap, " + << m_scrub_cstat.sum.num_objects_pinned << "/" + << info.stats.stats.sum.num_objects_pinned << " pinned, " + << m_scrub_cstat.sum.num_objects_hit_set_archive << "/" + << info.stats.stats.sum.num_objects_hit_set_archive + << " hit_set_archive, " << m_scrub_cstat.sum.num_bytes << "/" + << info.stats.stats.sum.num_bytes << " bytes, " + << m_scrub_cstat.sum.num_objects_manifest << "/" + << info.stats.stats.sum.num_objects_manifest << " manifest objects, " + << m_scrub_cstat.sum.num_bytes_hit_set_archive << "/" + << info.stats.stats.sum.num_bytes_hit_set_archive + << " hit_set_archive bytes." << dendl; + + if (m_scrub_cstat.sum.num_objects != info.stats.stats.sum.num_objects || + m_scrub_cstat.sum.num_object_clones != + info.stats.stats.sum.num_object_clones || + (m_scrub_cstat.sum.num_objects_dirty != + info.stats.stats.sum.num_objects_dirty && + !info.stats.dirty_stats_invalid) || + (m_scrub_cstat.sum.num_objects_omap != + info.stats.stats.sum.num_objects_omap && + !info.stats.omap_stats_invalid) || + (m_scrub_cstat.sum.num_objects_pinned != + info.stats.stats.sum.num_objects_pinned && + !info.stats.pin_stats_invalid) || + (m_scrub_cstat.sum.num_objects_hit_set_archive != + info.stats.stats.sum.num_objects_hit_set_archive && + !info.stats.hitset_stats_invalid) || + (m_scrub_cstat.sum.num_bytes_hit_set_archive != + info.stats.stats.sum.num_bytes_hit_set_archive && + !info.stats.hitset_bytes_stats_invalid) || + (m_scrub_cstat.sum.num_objects_manifest != + info.stats.stats.sum.num_objects_manifest && + !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 << " " << 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 << "/" + << info.stats.stats.sum.num_object_clones + << " clones, " << m_scrub_cstat.sum.num_objects_dirty + << "/" << info.stats.stats.sum.num_objects_dirty + << " dirty, " << m_scrub_cstat.sum.num_objects_omap + << "/" << info.stats.stats.sum.num_objects_omap + << " omap, " << m_scrub_cstat.sum.num_objects_pinned + << "/" << info.stats.stats.sum.num_objects_pinned + << " pinned, " + << m_scrub_cstat.sum.num_objects_hit_set_archive + << "/" + << info.stats.stats.sum.num_objects_hit_set_archive + << " hit_set_archive, " + << m_scrub_cstat.sum.num_whiteouts << "/" + << info.stats.stats.sum.num_whiteouts + << " whiteouts, " << m_scrub_cstat.sum.num_bytes + << "/" << info.stats.stats.sum.num_bytes << " bytes, " + << m_scrub_cstat.sum.num_objects_manifest << "/" + << info.stats.stats.sum.num_objects_manifest + << " manifest objects, " + << m_scrub_cstat.sum.num_bytes_hit_set_archive << "/" + << info.stats.stats.sum.num_bytes_hit_set_archive + << " hit_set_archive bytes."; + ++m_shallow_errors; + + if (m_is_repair) { + ++m_fixed_count; + m_pl_pg->recovery_state.update_stats([this](auto& history, auto& stats) { + stats.stats = m_scrub_cstat; + stats.dirty_stats_invalid = false; + stats.omap_stats_invalid = false; + stats.hitset_stats_invalid = false; + stats.hitset_bytes_stats_invalid = false; + stats.pin_stats_invalid = false; + stats.manifest_stats_invalid = false; + return false; + }); + m_pl_pg->publish_stats_to_osd(); + m_pl_pg->recovery_state.share_pg_info(); + } + } + // Clear object context cache to get repair information + if (m_is_repair) + m_pl_pg->object_contexts.clear(); +} + +PrimaryLogScrub::PrimaryLogScrub(PrimaryLogPG* pg) : PgScrubber{pg}, m_pl_pg{pg} +{} + +void PrimaryLogScrub::_scrub_clear_state() +{ + m_scrub_cstat = object_stat_collection_t(); +} + +void PrimaryLogScrub::stats_of_handled_objects( + const object_stat_sum_t& delta_stats, + const hobject_t& soid) +{ + // We scrub objects in hobject_t order, so objects before m_start have already + // been scrubbed and their stats have already been added to the scrubber. + // Objects after that point haven't been included in the scrubber's stats + // accounting yet, so they will be included when the scrubber gets to that + // object. + if (is_primary() && is_scrub_active()) { + if (soid < m_start) { + + dout(20) << fmt::format("{} {} < [{},{})", __func__, soid, m_start, m_end) + << dendl; + m_scrub_cstat.add(delta_stats); + + } else { + + dout(25) + << fmt::format("{} {} >= [{},{})", __func__, soid, m_start, m_end) + << dendl; + } + } +} |