:Type: Boolean
:Defaults: ``0``
+.. _scrub_min_interval:
+
+``scrub_min_interval``
+
+:Description: The maximum interval in seconds for pool scrubbing when
+ load is low. If it is 0, the value osd_scrub_min_interval
+ from config is used.
+
+:Type: Double
+:Default: ``0``
+
+.. _scrub_max_interval:
+
+``scrub_max_interval``
+
+:Description: The maximum interval in seconds for pool scrubbing
+ irrespective of cluster load. If it is 0, the value
+ osd_scrub_max_interval from config is used.
+
+:Type: Double
+:Default: ``0``
+
+.. _deep_scrub_interval:
+
+``deep_scrub_interval``
+
+:Description: The interval in seconds for pool “deep” scrubbing. If it
+ is 0, the value osd_deep_scrub_interval from config is used.
+
+:Type: Double
+:Default: ``0``
+
+
Get Pool Values
===============
:Type: Boolean
+
+``scrub_min_interval``
+
+:Description: see scrub_min_interval_
+
+:Type: Double
+
+
+``scrub_max_interval``
+
+:Description: see scrub_max_interval_
+
+:Type: Double
+
+
+``deep_scrub_interval``
+
+:Description: see deep_scrub_interval_
+
+:Type: Double
+
+
Set the Number of Object Replicas
=================================
expect_false ceph osd pool set $TEST_POOL_GETSET $flag 2
done
+ expect_false "ceph osd pool get $TEST_POOL_GETSET scrub_min_interval | grep '.'"
+ ceph osd pool set $TEST_POOL_GETSET scrub_min_interval 123456
+ ceph osd pool get $TEST_POOL_GETSET scrub_min_interval | grep 'scrub_min_interval: 123456'
+ ceph osd pool set $TEST_POOL_GETSET scrub_min_interval 0
+ expect_false "ceph osd pool get $TEST_POOL_GETSET scrub_min_interval | grep '.'"
+
+ expect_false "ceph osd pool get $TEST_POOL_GETSET scrub_max_interval | grep '.'"
+ ceph osd pool set $TEST_POOL_GETSET scrub_max_interval 123456
+ ceph osd pool get $TEST_POOL_GETSET scrub_max_interval | grep 'scrub_max_interval: 123456'
+ ceph osd pool set $TEST_POOL_GETSET scrub_max_interval 0
+ expect_false "ceph osd pool get $TEST_POOL_GETSET scrub_max_interval | grep '.'"
+
+ expect_false "ceph osd pool get $TEST_POOL_GETSET deep_scrub_interval | grep '.'"
+ ceph osd pool set $TEST_POOL_GETSET deep_scrub_interval 123456
+ ceph osd pool get $TEST_POOL_GETSET deep_scrub_interval | grep 'deep_scrub_interval: 123456'
+ ceph osd pool set $TEST_POOL_GETSET deep_scrub_interval 0
+ expect_false "ceph osd pool get $TEST_POOL_GETSET deep_scrub_interval | grep '.'"
+
ceph osd pool set $TEST_POOL_GETSET nopgchange 1
expect_false ceph osd pool set $TEST_POOL_GETSET pg_num 10
expect_false ceph osd pool set $TEST_POOL_GETSET pgp_num 10
"rename <srcpool> to <destpool>", "osd", "rw", "cli,rest")
COMMAND("osd pool get " \
"name=pool,type=CephPoolname " \
- "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|auid|target_max_objects|target_max_bytes|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|erasure_code_profile|min_read_recency_for_promote|all|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n", \
+ "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|auid|target_max_objects|target_max_bytes|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|erasure_code_profile|min_read_recency_for_promote|all|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n|scrub_min_interval|scrub_max_interval|deep_scrub_interval", \
"get pool parameter <var>", "osd", "r", "cli,rest")
COMMAND("osd pool set " \
"name=pool,type=CephPoolname " \
- "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|use_gmt_hitset|debug_fake_ec_pool|target_max_bytes|target_max_objects|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|auid|min_read_recency_for_promote|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n " \
+ "name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hashpspool|nodelete|nopgchange|nosizechange|write_fadvise_dontneed|noscrub|nodeep-scrub|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|use_gmt_hitset|debug_fake_ec_pool|target_max_bytes|target_max_objects|cache_target_dirty_ratio|cache_target_dirty_high_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age|auid|min_read_recency_for_promote|min_write_recency_for_promote|fast_read|hit_set_grade_decay_rate|hit_set_search_last_n|scrub_min_interval|scrub_max_interval|deep_scrub_interval " \
"name=val,type=CephString " \
"name=force,type=CephChoices,strings=--yes-i-really-mean-it,req=false", \
"set pool parameter <var> to <val>", "osd", "rw", "cli,rest")
CACHE_MIN_FLUSH_AGE, CACHE_MIN_EVICT_AGE,
ERASURE_CODE_PROFILE, MIN_READ_RECENCY_FOR_PROMOTE,
MIN_WRITE_RECENCY_FOR_PROMOTE, FAST_READ,
- HIT_SET_GRADE_DECAY_RATE, HIT_SET_SEARCH_LAST_N};
+ HIT_SET_GRADE_DECAY_RATE, HIT_SET_SEARCH_LAST_N,
+ SCRUB_MIN_INTERVAL, SCRUB_MAX_INTERVAL, DEEP_SCRUB_INTERVAL};
std::set<osd_pool_get_choices>
subtract_second_from_first(const std::set<osd_pool_get_choices>& first,
("min_write_recency_for_promote", MIN_WRITE_RECENCY_FOR_PROMOTE)
("fast_read", FAST_READ)
("hit_set_grade_decay_rate", HIT_SET_GRADE_DECAY_RATE)
- ("hit_set_search_last_n", HIT_SET_SEARCH_LAST_N);
+ ("hit_set_search_last_n", HIT_SET_SEARCH_LAST_N)
+ ("scrub_min_interval", SCRUB_MIN_INTERVAL)
+ ("scrub_max_interval", SCRUB_MAX_INTERVAL)
+ ("deep_scrub_interval", DEEP_SCRUB_INTERVAL);
typedef std::set<osd_pool_get_choices> choices_set_t;
f->dump_int("hit_set_search_last_n",
p->hit_set_search_last_n);
break;
+ case SCRUB_MIN_INTERVAL:
+ case SCRUB_MAX_INTERVAL:
+ case DEEP_SCRUB_INTERVAL:
+ for (i = ALL_CHOICES.begin(); i != ALL_CHOICES.end(); ++i) {
+ if (i->second == *it)
+ break;
+ }
+ assert(i != ALL_CHOICES.end());
+ p->opts.dump(i->first, f.get());
+ break;
}
f->close_section();
f->flush(rdata);
case FAST_READ:
ss << "fast_read: " << p->fast_read << "\n";
break;
+ case SCRUB_MIN_INTERVAL:
+ case SCRUB_MAX_INTERVAL:
+ case DEEP_SCRUB_INTERVAL:
+ for (i = ALL_CHOICES.begin(); i != ALL_CHOICES.end(); ++i) {
+ if (i->second == *it)
+ break;
+ }
+ assert(i != ALL_CHOICES.end());
+ {
+ pool_opts_t::key_t key = pool_opts_t::get_opt_desc(i->first).key;
+ if (p->opts.is_set(key)) {
+ ss << i->first << ": " << p->opts.get(key) << "\n";
+ }
+ }
+ break;
}
rdata.append(ss.str());
ss.str("");
return false;
}
-OSDService::ScrubJob::ScrubJob(const spg_t& pg, const utime_t& timestamp, bool must)
+OSDService::ScrubJob::ScrubJob(const spg_t& pg, const utime_t& timestamp,
+ double pool_scrub_min_interval,
+ double pool_scrub_max_interval, bool must)
: pgid(pg),
sched_time(timestamp),
deadline(timestamp)
{
// if not explicitly requested, postpone the scrub with a random delay
if (!must) {
- sched_time += g_conf->osd_scrub_min_interval;
+ double scrub_min_interval = pool_scrub_min_interval > 0 ?
+ pool_scrub_min_interval : g_conf->osd_scrub_min_interval;
+ double scrub_max_interval = pool_scrub_max_interval > 0 ?
+ pool_scrub_max_interval : g_conf->osd_scrub_max_interval;
+
+ sched_time += scrub_min_interval;
if (g_conf->osd_scrub_interval_randomize_ratio > 0) {
- sched_time += rand() % (int)(g_conf->osd_scrub_min_interval *
+ sched_time += rand() % (int)(scrub_min_interval *
g_conf->osd_scrub_interval_randomize_ratio);
}
- deadline += g_conf->osd_scrub_max_interval;
+ deadline += scrub_max_interval;
}
}
/// the hard upper bound of scrub time
utime_t deadline;
ScrubJob() {}
- explicit ScrubJob(const spg_t& pg, const utime_t& timestamp, bool must = true);
+ explicit ScrubJob(const spg_t& pg, const utime_t& timestamp,
+ double pool_scrub_min_interval = 0,
+ double pool_scrub_max_interval = 0, bool must = true);
/// order the jobs by sched_time
bool operator<(const ScrubJob& rhs) const;
};
set<ScrubJob> sched_scrub_pg;
/// @returns the scrub_reg_stamp used for unregister the scrub job
- utime_t reg_pg_scrub(spg_t pgid, utime_t t, bool must) {
- ScrubJob scrub(pgid, t, must);
+ utime_t reg_pg_scrub(spg_t pgid, utime_t t, double pool_scrub_min_interval,
+ double pool_scrub_max_interval, bool must) {
+ ScrubJob scrub(pgid, t, pool_scrub_min_interval, pool_scrub_max_interval,
+ must);
Mutex::Locker l(sched_scrub_lock);
sched_scrub_pg.insert(scrub);
return scrub.sched_time;
return false;
}
- bool time_for_deep = (ceph_clock_now(cct) >=
- info.history.last_deep_scrub_stamp + cct->_conf->osd_deep_scrub_interval);
+ double deep_scrub_interval = 0;
+ pool.info.opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &deep_scrub_interval);
+ if (deep_scrub_interval <= 0) {
+ deep_scrub_interval = cct->_conf->osd_deep_scrub_interval;
+ }
+ bool time_for_deep = ceph_clock_now(cct) >=
+ info.history.last_deep_scrub_stamp + deep_scrub_interval;
bool deep_coin_flip = false;
// Only add random deep scrubs when NOT user initiated scrub
}
// note down the sched_time, so we can locate this scrub, and remove it
// later on.
+ double scrub_min_interval = 0, scrub_max_interval = 0;
+ pool.info.opts.get(pool_opts_t::SCRUB_MIN_INTERVAL, &scrub_min_interval);
+ pool.info.opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &scrub_max_interval);
scrubber.scrub_reg_stamp = osd->reg_pg_scrub(info.pgid,
reg_stamp,
+ scrub_min_interval,
+ scrub_max_interval,
scrubber.must_scrub);
}
// -- pool_opts_t --
typedef std::map<std::string, pool_opts_t::opt_desc_t> opt_mapping_t;
-static opt_mapping_t opt_mapping;
+static opt_mapping_t opt_mapping = boost::assign::map_list_of
+ ("scrub_min_interval", pool_opts_t::opt_desc_t(
+ pool_opts_t::SCRUB_MIN_INTERVAL, pool_opts_t::DOUBLE))
+ ("scrub_max_interval", pool_opts_t::opt_desc_t(
+ pool_opts_t::SCRUB_MAX_INTERVAL, pool_opts_t::DOUBLE))
+ ("deep_scrub_interval", pool_opts_t::opt_desc_t(
+ pool_opts_t::DEEP_SCRUB_INTERVAL, pool_opts_t::DOUBLE));
bool pool_opts_t::is_opt_name(const std::string& name) {
return opt_mapping.find(name) != opt_mapping.end();
class pool_opts_t {
public:
enum key_t {
+ SCRUB_MIN_INTERVAL,
+ SCRUB_MAX_INTERVAL,
+ DEEP_SCRUB_INTERVAL,
};
enum type_t {
local size=$(ceph osd pool get $TEST_POOL size|awk '{print $2}')
local min_size=$(ceph osd pool get $TEST_POOL min_size|awk '{print $2}')
+
+ ceph osd pool set $TEST_POOL scrub_min_interval 123456 || return 1
+ ceph osd dump | grep 'pool ' | grep 'scrub_min_interval 123456' || return 1
+ ceph osd pool set $TEST_POOL scrub_min_interval 0 || return 1
+ ceph osd dump | grep 'pool ' | grep 'scrub_min_interval' && return 1
+ ceph osd pool set $TEST_POOL scrub_max_interval 123456 || return 1
+ ceph osd dump | grep 'pool ' | grep 'scrub_max_interval 123456' || return 1
+ ceph osd pool set $TEST_POOL scrub_max_interval 0 || return 1
+ ceph osd dump | grep 'pool ' | grep 'scrub_max_interval' && return 1
+ ceph osd pool set $TEST_POOL deep_scrub_interval 123456 || return 1
+ ceph osd dump | grep 'pool ' | grep 'deep_scrub_interval 123456' || return 1
+ ceph osd pool set $TEST_POOL deep_scrub_interval 0 || return 1
+ ceph osd dump | grep 'pool ' | grep 'deep_scrub_interval' && return 1
+
#replicated pool size restrict in 1 and 10
! ceph osd pool set $TEST_POOL 11 || return 1
#replicated pool min_size must be between in 1 and size
EXPECT_THROW(pool_opts_t::get_opt_desc("INVALID_OPT"), FailedAssertion);
}
+TEST(pool_opts_t, scrub_min_interval) {
+ EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_min_interval"));
+ EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_min_interval"),
+ pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MIN_INTERVAL,
+ pool_opts_t::DOUBLE));
+
+ pool_opts_t opts;
+ EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MIN_INTERVAL));
+ EXPECT_THROW(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL), FailedAssertion);
+ double val;
+ EXPECT_FALSE(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL, &val));
+ opts.set(pool_opts_t::SCRUB_MIN_INTERVAL, static_cast<double>(2015));
+ EXPECT_TRUE(opts.get(pool_opts_t::SCRUB_MIN_INTERVAL, &val));
+ EXPECT_EQ(val, 2015);
+ opts.unset(pool_opts_t::SCRUB_MIN_INTERVAL);
+ EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MIN_INTERVAL));
+}
+
+TEST(pool_opts_t, scrub_max_interval) {
+ EXPECT_TRUE(pool_opts_t::is_opt_name("scrub_max_interval"));
+ EXPECT_EQ(pool_opts_t::get_opt_desc("scrub_max_interval"),
+ pool_opts_t::opt_desc_t(pool_opts_t::SCRUB_MAX_INTERVAL,
+ pool_opts_t::DOUBLE));
+
+ pool_opts_t opts;
+ EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MAX_INTERVAL));
+ EXPECT_THROW(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL), FailedAssertion);
+ double val;
+ EXPECT_FALSE(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &val));
+ opts.set(pool_opts_t::SCRUB_MAX_INTERVAL, static_cast<double>(2015));
+ EXPECT_TRUE(opts.get(pool_opts_t::SCRUB_MAX_INTERVAL, &val));
+ EXPECT_EQ(val, 2015);
+ opts.unset(pool_opts_t::SCRUB_MAX_INTERVAL);
+ EXPECT_FALSE(opts.is_set(pool_opts_t::SCRUB_MAX_INTERVAL));
+}
+
+TEST(pool_opts_t, deep_scrub_interval) {
+ EXPECT_TRUE(pool_opts_t::is_opt_name("deep_scrub_interval"));
+ EXPECT_EQ(pool_opts_t::get_opt_desc("deep_scrub_interval"),
+ pool_opts_t::opt_desc_t(pool_opts_t::DEEP_SCRUB_INTERVAL,
+ pool_opts_t::DOUBLE));
+
+ pool_opts_t opts;
+ EXPECT_FALSE(opts.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL));
+ EXPECT_THROW(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL), FailedAssertion);
+ double val;
+ EXPECT_FALSE(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &val));
+ opts.set(pool_opts_t::DEEP_SCRUB_INTERVAL, static_cast<double>(2015));
+ EXPECT_TRUE(opts.get(pool_opts_t::DEEP_SCRUB_INTERVAL, &val));
+ EXPECT_EQ(val, 2015);
+ opts.unset(pool_opts_t::DEEP_SCRUB_INTERVAL);
+ EXPECT_FALSE(opts.is_set(pool_opts_t::DEEP_SCRUB_INTERVAL));
+}
+
/*
* Local Variables:
* compile-command: "cd ../.. ;
def test_pool_get(self):
for var in ('size', 'min_size', 'crash_replay_interval',
- 'pg_num', 'pgp_num', 'crush_ruleset', 'auid', 'fast_read'):
+ 'pg_num', 'pgp_num', 'crush_ruleset', 'auid', 'fast_read',
+ 'scrub_min_interval', 'scrub_max_interval',
+ 'deep_scrub_interval'):
self.assert_valid_command(['osd', 'pool', 'get', 'poolname', var])
assert_equal({}, validate_command(sigdict, ['osd', 'pool']))
assert_equal({}, validate_command(sigdict, ['osd', 'pool',
def test_pool_set(self):
for var in ('size', 'min_size', 'crash_replay_interval',
'pg_num', 'pgp_num', 'crush_ruleset',
- 'hashpspool', 'auid', 'fast_read'):
+ 'hashpspool', 'auid', 'fast_read',
+ 'scrub_min_interval', 'scrub_max_interval',
+ 'deep_scrub_interval'):
self.assert_valid_command(['osd', 'pool',
'set', 'poolname', var, 'value'])
assert_equal({}, validate_command(sigdict, ['osd', 'pool',