do
activate_osd $dir $osd || return 1
done
+ ceph tell osd.* config set osd_shallow_scrub_chunk_max 25
+ ceph tell osd.* config set osd_shallow_scrub_chunk_min 5
+ ceph tell osd.* config set osd_pg_stat_report_interval_max 1
+
wait_for_clean || return 1
+ ceph tell osd.* config get osd_shallow_scrub_chunk_max
+ ceph tell osd.* config get osd_shallow_scrub_chunk_min
+ ceph tell osd.* config get osd_pg_stat_report_interval_max
+ ceph tell osd.* config get osd_scrub_chunk_max
+ ceph tell osd.* config get osd_scrub_chunk_min
+
local pgid="${poolid}.0"
if ! pg_scrub "$pgid" ; then
return 1
activate_osd $dir $osd || return 1
done
+ ceph tell osd.* config set osd_shallow_scrub_chunk_max 3
+ ceph tell osd.* config set osd_shallow_scrub_chunk_min 3
+ ceph tell osd.* config set osd_scrub_chunk_min 3
+ ceph tell osd.* config set osd_pg_stat_report_interval_max 1
wait_for_clean || return 1
local pgid="${poolid}.0"
function TEST_scrub_snaps_replica() {
local dir=$1
ORIG_ARGS=$CEPH_ARGS
- CEPH_ARGS+=" --osd_scrub_chunk_min=3 --osd_scrub_chunk_max=3"
+ CEPH_ARGS+=" --osd_scrub_chunk_min=3 --osd_scrub_chunk_max=20 --osd_shallow_scrub_chunk_min=3 --osd_shallow_scrub_chunk_max=3 --osd_pg_stat_report_interval_max=1"
_scrub_snaps_multi $dir replica
err=$?
CEPH_ARGS=$ORIG_ARGS
function TEST_scrub_snaps_primary() {
local dir=$1
ORIG_ARGS=$CEPH_ARGS
- CEPH_ARGS+=" --osd_scrub_chunk_min=3 --osd_scrub_chunk_max=3"
+ CEPH_ARGS+=" --osd_scrub_chunk_min=3 --osd_scrub_chunk_max=20 --osd_shallow_scrub_chunk_min=3 --osd_shallow_scrub_chunk_max=3 --osd_pg_stat_report_interval_max=1"
_scrub_snaps_multi $dir primary
err=$?
CEPH_ARGS=$ORIG_ARGS
- name: osd_scrub_chunk_min
type: int
level: advanced
- desc: Minimum number of objects to scrub in a single chunk
+ desc: Minimum number of objects to deep-scrub in a single chunk
fmt_desc: The minimal number of object store chunks to scrub during single operation.
Ceph blocks writes to single chunk during scrub.
default: 5
- name: osd_scrub_chunk_max
type: int
level: advanced
- desc: Maximum number of objects to scrub in a single chunk
+ desc: Maximum number of objects to deep-scrub in a single chunk
fmt_desc: The maximum number of object store chunks to scrub during single operation.
default: 25
see_also:
- osd_scrub_chunk_min
with_legacy: true
+- name: osd_shallow_scrub_chunk_min
+ type: int
+ level: advanced
+ desc: Minimum number of objects to scrub in a single chunk
+ fmt_desc: The minimum number of object store chunks to scrub during single operation.
+ Not applicable to deep scrubs.
+ Ceph blocks writes to single chunk during scrub.
+ default: 50
+ see_also:
+ - osd_shallow_scrub_chunk_max
+ - osd_scrub_chunk_min
+ with_legacy: true
+- name: osd_shallow_scrub_chunk_max
+ type: int
+ level: advanced
+ desc: Maximum number of objects to scrub in a single chunk
+ fmt_desc: The maximum number of object store chunks to scrub during single operation.
+ Not applicable to deep scrubs.
+ default: 100
+ see_also:
+ - osd_shallow_scrub_chunk_min
+ - osd_scrub_chunk_max
+ with_legacy: true
# sleep between [deep]scrub ops
- name: osd_scrub_sleep
type: float
}
}
+
+namespace {
+
+/**
+ * an aux function to be used in select_range() below, to
+ * select the correct chunk size based on the type of scrub
+ */
+int size_from_conf(
+ bool is_deep,
+ const ceph::common::ConfigProxy& conf,
+ std::string_view deep_opt,
+ std::string_view shallow_opt)
+{
+ if (!is_deep) {
+ auto sz = conf.get_val<int64_t>(shallow_opt);
+ if (sz != 0) {
+ // assuming '0' means that no distinction was yet configured between
+ // deep and shallow scrubbing
+ return static_cast<int>(sz);
+ }
+ }
+ return static_cast<int>(conf.get_val<int64_t>(deep_opt));
+}
+} // anonymous namespace
+
/*
* The selected range is set directly into 'm_start' and 'm_end'
* setting:
* left end of the range if we are a tier because they may legitimately
* not exist (see _scrub).
*/
- int min_idx = static_cast<int>(
- std::max<int64_t>(3,
- m_pg->get_cct()->_conf->osd_scrub_chunk_min /
- (int)preemption_data.chunk_divisor()));
- int max_idx = static_cast<int>(
- std::max<int64_t>(min_idx,
- m_pg->get_cct()->_conf->osd_scrub_chunk_max /
- (int)preemption_data.chunk_divisor()));
+ const auto& conf = m_pg->get_cct()->_conf;
+ dout(20) << fmt::format(
+ "{} {} mins: {}d {}s, max: {}d {}s", __func__,
+ (m_is_deep ? "D" : "S"),
+ conf.get_val<int64_t>("osd_scrub_chunk_min"),
+ conf.get_val<int64_t>("osd_shallow_scrub_chunk_min"),
+ conf.get_val<int64_t>("osd_scrub_chunk_max"),
+ conf.get_val<int64_t>("osd_shallow_scrub_chunk_max"))
+ << dendl;
+
+ const int min_from_conf = size_from_conf(
+ m_is_deep, conf, "osd_scrub_chunk_min", "osd_shallow_scrub_chunk_min");
+ const int max_from_conf = size_from_conf(
+ m_is_deep, conf, "osd_scrub_chunk_max", "osd_shallow_scrub_chunk_max");
+
+ const int divisor = static_cast<int>(preemption_data.chunk_divisor());
+ const int min_chunk_sz = std::max(3, min_from_conf / divisor);
+ const int max_chunk_sz = std::max(min_chunk_sz, max_from_conf / divisor);
- dout(10) << __func__ << " Min: " << min_idx << " Max: " << max_idx
- << " Div: " << preemption_data.chunk_divisor() << dendl;
+ dout(10) << fmt::format(
+ "{}: Min: {} Max: {} Div: {}", __func__, min_chunk_sz,
+ max_chunk_sz, divisor)
+ << dendl;
hobject_t start = m_start;
hobject_t candidate_end;
std::vector<hobject_t> objects;
- int ret = m_pg->get_pgbackend()->objects_list_partial(start,
- min_idx,
- max_idx,
- &objects,
- &candidate_end);
+ int ret = m_pg->get_pgbackend()->objects_list_partial(
+ start, min_chunk_sz, max_chunk_sz, &objects, &candidate_end);
ceph_assert(ret >= 0);
if (!objects.empty()) {