Skip to content

Commit 452e71d

Browse files
authored
Merge pull request ceph#62010 from ronen-fr/wip-rf-monotime
osd/scrub: tolerate non-monotonic scrub queue cutoff updates Reviewed-by: Radoslaw Zarzynski <[email protected]>
2 parents 6e7562f + d7f9aec commit 452e71d

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

src/common/not_before_queue.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,21 @@ class not_before_queue_t {
210210
/**
211211
* advance_time
212212
*
213-
* Advances the eligibility cutoff, argument must be non-decreasing in
214-
* successive calls.
213+
* Advances the eligibility cutoff.
214+
* Argument should be non-decreasing in successive calls.
215+
*
216+
* As for the scrub queue the cutoff is a time value, and as we have
217+
* encountered rare cases of clock resets (even the monotonic clock
218+
* can be slightly adjusted backwards on some kernels), "backward"
219+
* updates will be tolerated - ignored and not assert.
220+
*
221+
* \retval: true if the cutoff was advanced. False if we
222+
* had to ignore the update.
215223
*/
216-
void advance_time(T next_time) {
217-
assert(next_time >= current_time);
224+
bool advance_time(T next_time) {
225+
if (next_time < current_time) {
226+
return false;
227+
}
218228
current_time = next_time;
219229
while (true) {
220230
if (ineligible_queue.empty()) {
@@ -233,6 +243,7 @@ class not_before_queue_t {
233243
ineligible_queue.erase(typename ineligible_queue_t::const_iterator(iter));
234244
eligible_queue.insert(item);
235245
}
246+
return true;
236247
}
237248

238249
/**

src/osd/scrubber/osd_scrub_sched.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,15 @@ std::optional<Scrub::SchedEntry> ScrubQueue::pop_ready_entry(
9292
};
9393

9494
std::unique_lock lck{jobs_lock};
95-
to_scrub.advance_time(time_now);
95+
if (!to_scrub.advance_time(time_now)) {
96+
// the clock was not advanced
97+
dout(5) << fmt::format(
98+
": time now ({}) is earlier than the previous not-before "
99+
"cut-off time",
100+
time_now)
101+
<< dendl;
102+
// we still try to dequeue, mainly to handle possible corner cases
103+
}
96104
return to_scrub.dequeue_by_pred(eligible_filtr);
97105
}
98106

src/test/test_not_before_queue.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ TEST_F(NotBeforeTest, NotBefore) {
111111
ASSERT_EQ(queue.dequeue(), std::make_optional(e5));
112112
ASSERT_EQ(queue.dequeue(), std::nullopt);
113113

114-
queue.advance_time(1);
114+
EXPECT_TRUE(queue.advance_time(1U));
115+
// a 2'nd call using earlier time - should fail
116+
EXPECT_FALSE(queue.advance_time(0U));
115117

116118
EXPECT_EQ(queue.dequeue(), std::make_optional(e1));
117119
EXPECT_EQ(queue.dequeue(), std::make_optional(e2));
@@ -244,7 +246,7 @@ TEST_F(NotBeforeTest, RemoveIfByClass_with_cond) {
244246
53U, [](const tv_t &v) { return v.ordering_value == 44; }),
245247
2);
246248

247-
ASSERT_EQ(queue.total_count(), 17);
249+
ASSERT_EQ(queue.total_count(), 17U);
248250
EXPECT_EQ(
249251
queue.remove_if_by_class(
250252
57U, [](const tv_t &v) { return v.ordering_value > 10; }, 20),
@@ -294,14 +296,15 @@ TEST_F(NotBeforeTest, accumulate_1) {
294296
EXPECT_EQ(res_all, "abcdefgh");
295297

296298
// set time to 20: the order changes: 2, 4, 1, 3
297-
queue.advance_time(20);
299+
EXPECT_TRUE(queue.advance_time(20));
300+
EXPECT_FALSE(queue.advance_time(18));
298301
acc_just_elig = acc_just_elig_templ;
299302
res = queue.accumulate<std::string, decltype(acc_just_elig)>(
300303
std::move(acc_just_elig));
301304
EXPECT_EQ(res, "jpor");
302305

303306
// at 35: 2, 4, 1, 7, 8, 3
304-
queue.advance_time(35);
307+
EXPECT_TRUE(queue.advance_time(35));
305308
acc_just_elig = acc_just_elig_templ;
306309
res = queue.accumulate<std::string, decltype(acc_just_elig)>(
307310
std::move(acc_just_elig));

0 commit comments

Comments
 (0)