From: Yehuda Sadeh Date: Tue, 30 Jan 2018 23:46:00 +0000 (-0800) Subject: rgw: sync trace, hold complete node longer X-Git-Tag: v13.0.2~269^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=1371df07deec145a241baef90afc6c5f5571d266;p=ceph.git rgw: sync trace, hold complete node longer Fixes: http://tracker.ceph.com/issues/22833 Inserting an entry to the complete_nodes list in RGWSyncTraceManager::finish_node() can trigger an eviction of another entry, which in turn will call finish_node() recursively. Avoid the destruction of that entry under the lockby holding a reference to it a little longer. Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_sync_trace.cc b/src/rgw/rgw_sync_trace.cc index 2cd2338c6d30..edfbd916c5df 100644 --- a/src/rgw/rgw_sync_trace.cc +++ b/src/rgw/rgw_sync_trace.cc @@ -257,18 +257,30 @@ bool RGWSyncTraceManager::call(std::string command, cmdmap_t& cmdmap, std::strin void RGWSyncTraceManager::finish_node(RGWSyncTraceNode *node) { - shunique_lock wl(lock, ceph::acquire_unique); - if (!node) { - return; - } - auto iter = nodes.find(node->handle); - if (iter == nodes.end()) { - /* not found, already finished */ - return; - } + RGWSyncTraceNodeRef old_node; - complete_nodes.push_back(iter->second); - nodes.erase(iter); + { + shunique_lock wl(lock, ceph::acquire_unique); + if (!node) { + return; + } + auto iter = nodes.find(node->handle); + if (iter == nodes.end()) { + /* not found, already finished */ + return; + } + + if (complete_nodes.full()) { + /* take a reference to the entry that is going to be evicted, + * can't let it get evicted under lock held, otherwise + * it's a deadlock as it will call finish_node() + */ + old_node = complete_nodes.front(); + } + + complete_nodes.push_back(iter->second); + nodes.erase(iter); + } }; #endif