From b5fb783fd4b1f5f34ef9956f0f93cbe3a3e14645 Mon Sep 17 00:00:00 2001 From: Thierry Bordaz Date: Mon, 19 Oct 2015 11:03:54 +0200 Subject: [PATCH 363/363] Ticket 47978: Deadlock between two MODs on the same entry between entry cache and backend lock Bug Description: During a modify, the modified entry gets into the entry cache and is locked. If after the be_txn_postop/txn_commit and before the modify returns the modified entry gets out of the entry cache, the entry is not unlocked. It can lead to hang as soon as an other write operation hit that unlocked entry. This is a side effect of fix: #47834 - Tombstone_to_glue: if parents are also converted to glue, the target entry's DN must be adjusted. Fix Description: When the entry is locked, set a flag so that can later be unlocked independently of its presence in the entry cache https://fedorahosted.org/389/ticket/47978 Reviewed by: Noriko Hosoi (Thanks Noriko) Platforms tested: F22 (IPA CI test test_integration/test_vault.py, one failure out 2-4) Flag Day: no Doc impact: no (cherry picked from commit bdaed4e2fb4633d6fec16eb1ea55b7e2fcbd4df4) --- ldap/servers/slapd/back-ldbm/ldbm_modify.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c index 8b36e0f..15cfe2c 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c @@ -387,6 +387,7 @@ ldbm_back_modify( Slapi_PBlock *pb ) int repl_op; int opreturn = 0; int mod_count = 0; + int ec_locked = 0; slapi_pblock_get( pb, SLAPI_BACKEND, &be); slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li ); @@ -746,6 +747,7 @@ ldbm_back_modify( Slapi_PBlock *pb ) /* lock new entry in cache to prevent usage until we are complete */ cache_lock_entry( &inst->inst_cache, ec ); + ec_locked = 1; postentry = slapi_entry_dup( ec->ep_entry ); slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry ); @@ -861,7 +863,7 @@ common_return: slapi_mods_done(&smods); if(inst){ - if (cache_is_in_cache( &inst->inst_cache, ec)) + if (ec_locked || cache_is_in_cache( &inst->inst_cache, ec)) { cache_unlock_entry( &inst->inst_cache, ec); } else if (e) { -- 2.4.3