Blame SOURCES/0085-Ticket-47649-Server-hangs-in-cos_cache-when-adding-a.patch

cc3dff
From f86b7bd86945df33843e90a7ac84d5967a7e7e82 Mon Sep 17 00:00:00 2001
cc3dff
From: Noriko Hosoi <nhosoi@redhat.com>
cc3dff
Date: Fri, 24 Jan 2014 18:12:32 -0800
cc3dff
Subject: [PATCH 85/85] Ticket #47649 - Server hangs in cos_cache when adding a
cc3dff
 user entry
cc3dff
cc3dff
Bug description: cos_dn_defs_cb reads cosDefinition and sets up the cos
cc3dff
Definition part of cos cache.  In the function, when processing
cc3dff
cosAttribute, cosTargetTree and cosTemlpateDn are missing, it sets the
cc3dff
parent dn of the cos definition dn.  This parent setting is needed only
cc3dff
when the 2 attributes are completely missing from the cos definition.
cc3dff
But if the attributes are located below cosAttribute (see the Example
cc3dff
cos definition), in addition to "cn=cosTemplates,ou=people,dc=example,
cc3dff
dc=com", the parent of "cn=generatePostalCode,ou=People,dc=example,dc=com"
cc3dff
is added to the cos cache as cosTemplateDn.
cc3dff
  Example cos definition:
cc3dff
    dn: cn=generatePostalCode,ou=People,dc=example,dc=com
cc3dff
    description: generate postalCode attr based on location
cc3dff
    objectClass: top
cc3dff
    objectClass: ldapsubentry
cc3dff
    objectClass: cossuperdefinition
cc3dff
    objectClass: cosClassicDefinition
cc3dff
    cosAttribute: postalCode
cc3dff
    costemplatedn: cn=cosTemplates,ou=people,dc=example,dc=com
cc3dff
    cosSpecifier: l
cc3dff
    cn: generatePostalCode
cc3dff
The mistakenly added cosTemplatedDn makes adding an entry under ou=People
cc3dff
notify recreating the cos cache.  The notification needs to be outside of
cc3dff
backend transaction since it causes a deadlock with the cos_cache_wait_
cc3dff
on_change thread which cannot read the DB due to the transaction but holds
cc3dff
the lock that the notifier thread is waiting for.
cc3dff
cc3dff
Fix description: The parent of the cos definition dn is set to the
cc3dff
cosTargetTree and the cosTemlpateDn, only when the attributes are
cc3dff
completely missing.
cc3dff
cc3dff
https://fedorahosted.org/389/ticket/47649
cc3dff
cc3dff
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
cc3dff
(cherry picked from commit 1e52401d3abd0377f55676f4a1508a02aaa7f955)
cc3dff
(cherry picked from commit 01c0794cde7eb91a1a4e477a0286533df4a4ae38)
cc3dff
(cherry picked from commit 1ebad4bd50fb1483998a32b5d3e232e89aeda0f7)
cc3dff
---
cc3dff
 ldap/servers/plugins/cos/cos_cache.c | 82 +++++++++++++++++++++---------------
cc3dff
 1 file changed, 48 insertions(+), 34 deletions(-)
cc3dff
cc3dff
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
cc3dff
index fed2aa9..a68e59f 100644
cc3dff
--- a/ldap/servers/plugins/cos/cos_cache.c
cc3dff
+++ b/ldap/servers/plugins/cos/cos_cache.c
cc3dff
@@ -727,7 +727,8 @@ struct dn_defs_info {
cc3dff
  * if a particular attempt to add a definition fails: info.ret gets set to
cc3dff
  * zero only if we succed to add a def.
cc3dff
 */
cc3dff
-static int 	cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
cc3dff
+static int 
cc3dff
+cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
cc3dff
 {
cc3dff
 	struct dn_defs_info *info;
cc3dff
 	cosAttrValue **pSneakyVal = 0;
cc3dff
@@ -877,31 +878,10 @@ static int 	cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
cc3dff
 					                      dnVals[valIndex]->bv_val);
cc3dff
 				}
cc3dff
 
cc3dff
-				if(!pCosTargetTree)
cc3dff
-				{
cc3dff
-					/* get the parent of the definition */
cc3dff
-					char *orig = slapi_dn_parent(pDn->val);
cc3dff
-					Slapi_DN *psdn = slapi_sdn_new_dn_byval(orig);
cc3dff
-					char *parent = (char *)slapi_sdn_get_dn(psdn);
cc3dff
-					if (!parent) {
cc3dff
-						parent = (char *)slapi_sdn_get_udn(psdn);
cc3dff
-						LDAPDebug(LDAP_DEBUG_ANY, 
cc3dff
-						  "cos_cache_build_definition_list: "
cc3dff
-						  "failed to normalize parent dn %s. "
cc3dff
-						  "Adding the pre normalized dn.\n", 
cc3dff
-						  parent, 0, 0);
cc3dff
-					}
cc3dff
-					cos_cache_add_attrval(&pCosTargetTree, parent);
cc3dff
-					if (!pCosTemplateDn) {
cc3dff
-						cos_cache_add_attrval(&pCosTemplateDn, parent);
cc3dff
-					}
cc3dff
-					slapi_sdn_free(&psdn);
cc3dff
-				}
cc3dff
-				
cc3dff
 				slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle,
cc3dff
 				                        dnVals[valIndex]->bv_val, NULL, NULL);
cc3dff
 			} /* if(attrType is cosAttribute) */
cc3dff
-										
cc3dff
+
cc3dff
 			/*
cc3dff
 			 * Add the attributetype to the appropriate
cc3dff
 			 * list.
cc3dff
@@ -913,6 +893,47 @@ static int 	cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
cc3dff
 		ber_bvecfree( dnVals );
cc3dff
 		dnVals = NULL;
cc3dff
 	} while(!slapi_entry_next_attr(e, dnAttr, &dnAttr));
cc3dff
+
cc3dff
+	if (pCosAttribute && (!pCosTargetTree || !pCosTemplateDn)) {
cc3dff
+		/* get the parent of the definition */
cc3dff
+		char *orig = slapi_dn_parent(pDn->val);
cc3dff
+		char *parent = NULL;
cc3dff
+		if (orig) {
cc3dff
+			parent = slapi_create_dn_string("%s", orig);
cc3dff
+			if (!parent) {
cc3dff
+				parent = orig;
cc3dff
+				LDAPDebug1Arg(LDAP_DEBUG_ANY, 
cc3dff
+				              "cos_dn_defs_cb: "
cc3dff
+				              "failed to normalize parent dn %s. "
cc3dff
+				              "Adding the pre normalized dn.\n", 
cc3dff
+				              parent);
cc3dff
+			}
cc3dff
+			if (!pCosTargetTree) {
cc3dff
+				cos_cache_add_attrval(&pCosTargetTree, parent);
cc3dff
+			}
cc3dff
+			if (!pCosTemplateDn) {
cc3dff
+				cos_cache_add_attrval(&pCosTemplateDn, parent);
cc3dff
+			}
cc3dff
+			if (parent != orig) {
cc3dff
+				slapi_ch_free_string(&parent);
cc3dff
+			}
cc3dff
+			slapi_ch_free_string(&orig);
cc3dff
+		} else {
cc3dff
+			LDAPDebug1Arg(LDAP_DEBUG_ANY, 
cc3dff
+			              "cos_dn_defs_cb: "
cc3dff
+			              "failed to get parent dn of cos definition %s.\n",
cc3dff
+			              pDn->val);
cc3dff
+			if (!pCosTemplateDn) {
cc3dff
+				if (!pCosTargetTree) {
cc3dff
+					LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTargetTree and cosTemplateDn are not set.\n");
cc3dff
+				} else {
cc3dff
+					LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTemplateDn is not set.\n");
cc3dff
+				}
cc3dff
+			} else if (!pCosTargetTree) {
cc3dff
+				LDAPDebug0Args(LDAP_DEBUG_ANY, "cosTargetTree is not set.\n");
cc3dff
+			}
cc3dff
+		}
cc3dff
+	}
cc3dff
 	
cc3dff
 	/*
cc3dff
 	determine the type of class of service scheme 
cc3dff
@@ -951,9 +972,7 @@ static int 	cos_dn_defs_cb (Slapi_Entry* e, void *callback_data)
cc3dff
 	*/
cc3dff
 	
cc3dff
 	/* these must exist */
cc3dff
-	if(		pDn &&
cc3dff
-		pObjectclass && 
cc3dff
-		
cc3dff
+	if(pDn && pObjectclass && 
cc3dff
 		(
cc3dff
 		(cosType == COSTYPE_CLASSIC &&
cc3dff
 		pCosTemplateDn && 
cc3dff
@@ -3582,14 +3601,9 @@ static int cos_cache_entry_is_cos_related( Slapi_Entry *e) {
cc3dff
 			{
cc3dff
 				pObj = (char*)slapi_value_get_string(val);
cc3dff
 
cc3dff
-				/*
cc3dff
-				 * objectclasses are ascii--maybe strcasecmp() is faster than
cc3dff
-				 * slapi_utf8casecmp()
cc3dff
-				*/
cc3dff
-				if(	!strcasecmp(pObj, "cosdefinition") ||
cc3dff
-					!strcasecmp(pObj, "cossuperdefinition") ||
cc3dff
-					!strcasecmp(pObj, "costemplate")
cc3dff
-					)
cc3dff
+				if(!strcasecmp(pObj, "cosdefinition") ||
cc3dff
+				   !strcasecmp(pObj, "cossuperdefinition") ||
cc3dff
+				   !strcasecmp(pObj, "costemplate"))
cc3dff
 				{
cc3dff
 					rc = 1;
cc3dff
 				}
cc3dff
-- 
cc3dff
1.8.1.4
cc3dff