Skip to content

Commit b341dc8

Browse files
pdillingerfacebook-github-bot
authored andcommitted
Fix possible out-of-order/inconsistent seqno-to-time mapping (#13279)
Summary: The crash test with COERCE_CONTEXT_SWITCH=1 is showing a failure: ``` db_stress: db/seqno_to_time_mapping.cc:480: bool rocksdb::SeqnoToTimeMapping::Append(rocksdb::SequenceNumber, uint64_t): Assertion `false' failed. ``` with `DBImpl::SetOptions()` in the call stack. This assertion and those around it are mostly there for catching systematic problems with recording the mappings, as small imprecisions here and there are not a problem in production. Nevertheless, we need to fix this to maintain the assertions for catching possible future systematic problems. Because the seqno and time are acquired before holding the DB mutex, there could be a race where T1 acquires latest seqno, T1 acquires latest seqno, T2 acquires unix time, T1 acquires unix time, and entries are not just saved out-of-order, but would represent an inconsistent (time traveling) mapping if they were saved. We can fix this by getting the seqno and unix times while under the mutex. (Hopefully this is not caused by non-monotonic clock adjustments.) Pull Request resolved: #13279 Test Plan: local run blackbox_crash_test with COERCE_CONTEXT_SWITCH=1. This is not really a production concern, and the conditions are not really reproducible in a unit test after the fix. Reviewed By: cbi42 Differential Revision: D67923314 Pulled By: pdillinger fbshipit-source-id: 6bfb6b05d6d449154fbaeb9196eedcfa21fe5ae1
1 parent 9b1d0c0 commit b341dc8

File tree

1 file changed

+31
-20
lines changed

1 file changed

+31
-20
lines changed

db/db_impl/db_impl.cc

+31-20
Original file line numberDiff line numberDiff line change
@@ -6812,17 +6812,24 @@ void DBImpl::RecordSeqnoToTimeMapping(uint64_t populate_historical_seconds) {
68126812
// for SeqnoToTimeMapping. We don't know how long it has been since the last
68136813
// sequence number was written, so we at least have a one-sided bound by
68146814
// sampling in this order.
6815-
SequenceNumber seqno = GetLatestSequenceNumber();
6816-
int64_t unix_time_signed = 0;
6817-
immutable_db_options_.clock->GetCurrentTime(&unix_time_signed)
6818-
.PermitUncheckedError(); // Ignore error
6819-
uint64_t unix_time = static_cast<uint64_t>(unix_time_signed);
6820-
6815+
// ALSO, to avoid out-of-order mappings, we need to get the seqno and times
6816+
// while holding the DB mutex. (This is really to make testing happy because
6817+
// it's fine to throw out extra close-but-not-quite-consistent mappings in
6818+
// production.)
68216819
std::vector<SuperVersionContext> sv_contexts;
6822-
if (populate_historical_seconds > 0) {
6823-
bool success = true;
6824-
{
6825-
InstrumentedMutexLock l(&mutex_);
6820+
bool success = true;
6821+
SequenceNumber seqno;
6822+
uint64_t unix_time;
6823+
{
6824+
InstrumentedMutexLock l(&mutex_);
6825+
6826+
seqno = GetLatestSequenceNumber();
6827+
int64_t unix_time_signed = 0;
6828+
immutable_db_options_.clock->GetCurrentTime(&unix_time_signed)
6829+
.PermitUncheckedError(); // Ignore error
6830+
unix_time = static_cast<uint64_t>(unix_time_signed);
6831+
6832+
if (populate_historical_seconds > 0) {
68266833
if (seqno > 1 && unix_time > populate_historical_seconds) {
68276834
// seqno=0 is reserved
68286835
SequenceNumber from_seqno = 1;
@@ -6836,7 +6843,20 @@ void DBImpl::RecordSeqnoToTimeMapping(uint64_t populate_historical_seconds) {
68366843
assert(unix_time > populate_historical_seconds);
68376844
success = false;
68386845
}
6846+
} else {
6847+
// FIXME: assert(seqno > 0);
6848+
// Always successful assuming seqno never go backwards
6849+
seqno_to_time_mapping_.Append(seqno, unix_time);
6850+
InstallSeqnoToTimeMappingInSV(&sv_contexts);
68396851
}
6852+
}
6853+
6854+
// clean up & report outside db mutex
6855+
for (SuperVersionContext& sv_context : sv_contexts) {
6856+
sv_context.Clean();
6857+
}
6858+
6859+
if (populate_historical_seconds > 0) {
68406860
if (success) {
68416861
ROCKS_LOG_INFO(
68426862
immutable_db_options_.info_log,
@@ -6851,16 +6871,7 @@ void DBImpl::RecordSeqnoToTimeMapping(uint64_t populate_historical_seconds) {
68516871
seqno, unix_time - populate_historical_seconds, unix_time);
68526872
}
68536873
} else {
6854-
InstrumentedMutexLock l(&mutex_);
6855-
// FIXME: assert(seqno > 0);
6856-
// Always successful assuming seqno never go backwards
6857-
seqno_to_time_mapping_.Append(seqno, unix_time);
6858-
InstallSeqnoToTimeMappingInSV(&sv_contexts);
6859-
}
6860-
6861-
// clean up outside db mutex
6862-
for (SuperVersionContext& sv_context : sv_contexts) {
6863-
sv_context.Clean();
6874+
assert(success);
68646875
}
68656876
}
68666877

0 commit comments

Comments
 (0)