prefix == "mark_unfound_lost" ||
prefix == "list_unfound" ||
prefix == "scrub" ||
- prefix == "deep_scrub"
+ prefix == "deep-scrub" ||
+ prefix == "schedule-scrub" || ///< dev/tests only!
+ prefix == "schedule-deep-scrub" ///< dev/tests only!
) {
string pgidstr;
pg_t pgid;
"");
ceph_assert(r == 0);
r = admin_socket->register_command(
- "pg " \
- "name=pgid,type=CephPgid " \
- "name=cmd,type=CephChoices,strings=scrub " \
- "name=time,type=CephInt,req=false",
+ "pg "
+ "name=pgid,type=CephPgid "
+ "name=cmd,type=CephChoices,strings=scrub",
asok_hook,
"");
ceph_assert(r == 0);
r = admin_socket->register_command(
- "pg " \
- "name=pgid,type=CephPgid " \
- "name=cmd,type=CephChoices,strings=deep_scrub " \
- "name=time,type=CephInt,req=false",
+ "pg "
+ "name=pgid,type=CephPgid "
+ "name=cmd,type=CephChoices,strings=deep-scrub",
asok_hook,
"");
ceph_assert(r == 0);
asok_hook,
"list unfound objects on this pg, perhaps starting at an offset given in JSON");
ceph_assert(r == 0);
+ // the operator commands (force a scrub)
+ r = admin_socket->register_command(
+ "scrub "
+ "name=pgid,type=CephPgid,req=false",
+ asok_hook,
+ "Trigger a scrub");
+ ceph_assert(r == 0);
+ r = admin_socket->register_command(
+ "deep-scrub "
+ "name=pgid,type=CephPgid,req=false",
+ asok_hook,
+ "Trigger a deep scrub");
+ ceph_assert(r == 0);
+ // debug/test commands (faking the timestamps)
r = admin_socket->register_command(
- "scrub " \
- "name=pgid,type=CephPgid,req=false " \
+ "schedule-scrub "
+ "name=pgid,type=CephPgid,req=false "
"name=time,type=CephInt,req=false",
asok_hook,
- "Trigger a scheduled scrub ");
+ "Schedule a scrub");
ceph_assert(r == 0);
r = admin_socket->register_command(
- "deep_scrub " \
- "name=pgid,type=CephPgid,req=false " \
+ "schedule-deep-scrub "
+ "name=pgid,type=CephPgid,req=false "
"name=time,type=CephInt,req=false",
asok_hook,
- "Trigger a scheduled deep scrub ");
+ "Schedule a deep scrub");
ceph_assert(r == 0);
}
f->close_section();
}
- else if (prefix == "scrub" ||
- prefix == "deep_scrub") {
- bool deep = (prefix == "deep_scrub");
- int64_t time = cmd_getval_or<int64_t>(cmdmap, "time", 0);
+ else if (prefix == "scrub" || prefix == "deep-scrub") {
+ if (is_primary()) {
+ scrub_level_t deep = (prefix == "deep-scrub") ? scrub_level_t::deep
+ : scrub_level_t::shallow;
+ m_scrubber->on_operator_forced_scrub(f.get(), deep, m_planned_scrub);
+ } else {
+ ss << "Not primary";
+ ret = -EPERM;
+ }
+ outbl.append(ss.str());
+ }
+ // the test/debug commands that schedule a scrub by modifying timestamps
+ else if (prefix == "schedule-scrub" || prefix == "schedule-deep-scrub") {
if (is_primary()) {
- const pg_pool_t *p = &pool.info;
- double pool_scrub_max_interval = 0;
- double scrub_max_interval;
- if (deep) {
- p->opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &pool_scrub_max_interval);
- scrub_max_interval = pool_scrub_max_interval > 0 ?
- pool_scrub_max_interval : g_conf()->osd_deep_scrub_interval;
- } else {
- p->opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &pool_scrub_max_interval);
- scrub_max_interval = pool_scrub_max_interval > 0 ?
- pool_scrub_max_interval : g_conf()->osd_scrub_max_interval;
- }
- // Instead of marking must_scrub force a schedule scrub
- utime_t stamp = ceph_clock_now();
- if (time == 0)
- stamp -= scrub_max_interval;
- else
- stamp -= (float)time;
- stamp -= 100.0; // push back last scrub more for good measure
- if (deep) {
- set_last_deep_scrub_stamp(stamp);
- }
- set_last_scrub_stamp(stamp); // for 'deep' as well, as we use this value to order scrubs
- f->open_object_section("result");
- f->dump_bool("deep", deep);
- f->dump_stream("stamp") << stamp;
- f->close_section();
+ scrub_level_t deep = (prefix == "schedule-deep-scrub")
+ ? scrub_level_t::deep
+ : scrub_level_t::shallow;
+ const int64_t offst = cmd_getval_or<int64_t>(cmdmap, "time", 0);
+ m_scrubber->on_operator_periodic_cmd(f.get(), deep, offst);
} else {
ss << "Not primary";
ret = -EPERM;
}
outbl.append(ss.str());
}
+
else {
ret = -ENOSYS;
ss << "prefix '" << prefix << "' not implemented";
}
+// handling Asok's "scrub" & "deep-scrub" commands
+
+namespace {
+void asok_response_section(
+ ceph::Formatter* f,
+ bool is_periodic,
+ scrub_level_t scrub_level,
+ utime_t stamp = utime_t{})
+{
+ f->open_object_section("result");
+ f->dump_bool("deep", (scrub_level == scrub_level_t::deep));
+ f->dump_bool("must", !is_periodic);
+ f->dump_stream("stamp") << stamp;
+ f->close_section();
+}
+} // namespace
+
+// when asked to force a "periodic" scrub by faking the timestamps
+void PgScrubber::on_operator_periodic_cmd(
+ ceph::Formatter* f,
+ scrub_level_t scrub_level,
+ int64_t offset)
+{
+ const auto cnf = populate_config_params();
+ dout(10) << fmt::format(
+ "{}: {} (cmd offset:{}) conf:{}", __func__,
+ (scrub_level == scrub_level_t::deep ? "deep" : "shallow"), offset,
+ cnf)
+ << dendl;
+
+ // move the relevant time-stamp backwards - enough to trigger a scrub
+
+ utime_t now_is = ceph_clock_now();
+ utime_t stamp = now_is;
+
+ if (offset > 0) {
+ stamp -= offset;
+ } else {
+ double max_iv =
+ (scrub_level == scrub_level_t::deep)
+ ? 2 * cnf.max_deep
+ : (cnf.max_shallow ? *cnf.max_shallow : cnf.shallow_interval);
+ dout(20) << fmt::format(
+ "{}: stamp:{:s} ms:{}/{}/{}", __func__, stamp,
+ (cnf.max_shallow ? "ms+" : "ms-"),
+ (cnf.max_shallow ? *cnf.max_shallow : -999.99),
+ cnf.shallow_interval)
+ << dendl;
+ stamp -= max_iv;
+ }
+ stamp -= 100.0; // for good measure
+
+ dout(10) << fmt::format("{}: stamp:{:s} ", __func__, stamp) << dendl;
+ asok_response_section(f, true, scrub_level, stamp);
+
+ if (scrub_level == scrub_level_t::deep) {
+ m_pg->set_last_deep_scrub_stamp(stamp);
+ }
+ // and in both cases:
+ m_pg->set_last_scrub_stamp(stamp);
+}
+
+// when asked to force a high-priority scrub
+void PgScrubber::on_operator_forced_scrub(
+ ceph::Formatter* f,
+ scrub_level_t scrub_level,
+ requested_scrub_t& request_flags)
+{
+ auto deep_req = scrub_requested(scrub_level, scrub_type_t::not_repair, request_flags);
+ asok_response_section(f, false, deep_req);
+}
+
// ----------------------------------------------------------------------------
pg_scrubbing_status_t get_schedule() const final;
+ void on_operator_periodic_cmd(
+ ceph::Formatter* f,
+ scrub_level_t scrub_level,
+ int64_t offset) final;
+
+ void on_operator_forced_scrub(
+ ceph::Formatter* f,
+ scrub_level_t scrub_level,
+ requested_scrub_t& request_flags) final;
+
void dump_scrubber(ceph::Formatter* f,
const requested_scrub_t& request_flags) const final;
virtual pg_scrubbing_status_t get_schedule() const = 0;
+
+ // // perform 'scrub'/'deep_scrub' asok commands
+
+ /// ... by faking the "last scrub" stamps
+ virtual void on_operator_periodic_cmd(
+ ceph::Formatter* f,
+ scrub_level_t scrub_level,
+ int64_t offset) = 0;
+
+ /// ... by requesting an "operator initiated" scrub
+ virtual void on_operator_forced_scrub(
+ ceph::Formatter* f,
+ scrub_level_t scrub_level,
+ requested_scrub_t& request_flags) = 0;
+
virtual void dump_scrubber(ceph::Formatter* f,
const requested_scrub_t& request_flags) const = 0;