From 2b63dd25fc1c73fa42e52e9ea4ab5a45dd9422a0 Mon Sep 17 00:00:00 2001 From: Samuel Just Date: Fri, 20 Feb 2015 13:43:46 -0800 Subject: [PATCH] DBObjectMap: lock header_lock on sync() Otherwise, we can race with another thread updating state.seq resulting in the old, smaller value getting persisted. If there is a crash at that time, we will reuse a sequence number, resulting in an inconsistent node tree and bug #9891. Fixes: 9891 Backport: giant, firefly, dumpling Signed-off-by: Samuel Just --- src/os/DBObjectMap.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/os/DBObjectMap.cc b/src/os/DBObjectMap.cc index 6e96bc80dc35b..b856849848656 100644 --- a/src/os/DBObjectMap.cc +++ b/src/os/DBObjectMap.cc @@ -984,6 +984,8 @@ int DBObjectMap::upgrade_to_v2() } state.v = 2; + + Mutex::Locker l(header_lock); KeyValueDB::Transaction t = db->get_transaction(); write_state(t); db->submit_transaction_sync(t); @@ -1031,7 +1033,6 @@ int DBObjectMap::init(bool do_upgrade) int DBObjectMap::sync(const ghobject_t *oid, const SequencerPosition *spos) { KeyValueDB::Transaction t = db->get_transaction(); - write_state(t); if (oid) { assert(spos); MapHeaderLock hl(this, *oid); @@ -1042,11 +1043,18 @@ int DBObjectMap::sync(const ghobject_t *oid, header->spos = *spos; set_map_header(hl, *oid, *header, t); } + Mutex::Locker l(header_lock); + write_state(t); + return db->submit_transaction_sync(t); + } else { + Mutex::Locker l(header_lock); + write_state(t); + return db->submit_transaction_sync(t); } - return db->submit_transaction_sync(t); } int DBObjectMap::write_state(KeyValueDB::Transaction _t) { + assert(header_lock.is_locked_by_me()); dout(20) << "dbobjectmap: seq is " << state.seq << dendl; KeyValueDB::Transaction t = _t ? _t : db->get_transaction(); bufferlist bl; -- 2.39.5