ebc913e
From dcb46ca16114e51108c1a0549235af5623f7596b Mon Sep 17 00:00:00 2001
ebc913e
From: Rich Megginson <rmeggins@redhat.com>
ebc913e
Date: Sat, 7 Apr 2012 09:05:18 -0600
ebc913e
Subject: [PATCH 2/4] Bug 808770 - [abrt] 389-ds-base-1.2.10.4-2.fc16: index_range_read_ext: Process /usr/sbin/ns-slapd was killed by signal 11 (SIGSEGV)
ebc913e
ebc913e
https://bugzilla.redhat.com/show_bug.cgi?id=808770
ebc913e
Resolves: bug 808770
ebc913e
Bug Description: [abrt] 389-ds-base-1.2.10.4-2.fc16: index_range_read_ext: Process /usr/sbin/ns-slapd was killed by signal 11 (SIGSEGV)
ebc913e
Reviewed by: ???
ebc913e
Branch: master
ebc913e
Fix Description:
ebc913e
1) Entries can be deleted out from under a search operation.  The range read
ebc913e
code was not handling this situation correctly.  The code should notice that
ebc913e
the index query was empty, and continue to the next highest key in the range.
ebc913e
2) DB cursor c_close() functions can return DB_LOCK_DEADLOCK that must be
ebc913e
reported to the higher level operation functions.  If not, then subsequent
ebc913e
operations in the same transaction fail.  When a DB_LOCK_DEADLOCK is returned
ebc913e
by any DB update operation in the transaction, the transaction must be aborted
ebc913e
and a new transaction begun before any other transacted db operations can
ebc913e
occur.
ebc913e
Platforms tested: RHEL6 x86_64
ebc913e
Flag Day: no
ebc913e
Doc impact: no
ebc913e
---
ebc913e
 ldap/servers/slapd/back-ldbm/idl_new.c       |   44 ++++++++++++++-----
ebc913e
 ldap/servers/slapd/back-ldbm/ldbm_delete.c   |   31 +++++++++++--
ebc913e
 ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c |   60 ++++++++++++++++++++-----
ebc913e
 3 files changed, 107 insertions(+), 28 deletions(-)
ebc913e
ebc913e
diff --git a/ldap/servers/slapd/back-ldbm/idl_new.c b/ldap/servers/slapd/back-ldbm/idl_new.c
ebc913e
index 4667c87..d62511c 100644
ebc913e
--- a/ldap/servers/slapd/back-ldbm/idl_new.c
ebc913e
+++ b/ldap/servers/slapd/back-ldbm/idl_new.c
ebc913e
@@ -333,8 +333,14 @@ IDList * idl_new_fetch(
ebc913e
 error:
ebc913e
     /* Close the cursor */
ebc913e
     if (NULL != cursor) {
ebc913e
-        if (0 != cursor->c_close(cursor)) {
ebc913e
-            ldbm_nasty(filename,3,ret);
ebc913e
+        int ret2 = cursor->c_close(cursor);
ebc913e
+        if (ret2) {
ebc913e
+            ldbm_nasty(filename,3,ret2);
ebc913e
+            if (!ret) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                ret = ret2;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     *flag_err = ret;
ebc913e
@@ -418,8 +424,9 @@ int idl_new_insert_key(
ebc913e
 error:
ebc913e
     /* Close the cursor */
ebc913e
     if (NULL != cursor) {
ebc913e
-        if (0 != cursor->c_close(cursor)) {
ebc913e
-            ldbm_nasty(filename,56,ret);
ebc913e
+        int ret2 = cursor->c_close(cursor);
ebc913e
+        if (ret2) {
ebc913e
+            ldbm_nasty(filename,56,ret2);
ebc913e
         }
ebc913e
     }
ebc913e
 #else
ebc913e
@@ -439,7 +446,7 @@ error:
ebc913e
             /* this is okay */
ebc913e
             ret = 0;
ebc913e
         } else {
ebc913e
-            ldbm_nasty(filename,50,ret);
ebc913e
+            ldbm_nasty(filename,60,ret);
ebc913e
         }
ebc913e
     }
ebc913e
 #endif
ebc913e
@@ -491,8 +498,14 @@ int idl_new_delete_key(
ebc913e
 error:
ebc913e
     /* Close the cursor */
ebc913e
     if (NULL != cursor) {
ebc913e
-        if (0 != cursor->c_close(cursor)) {
ebc913e
-            ldbm_nasty(filename,24,ret);
ebc913e
+        int ret2 = cursor->c_close(cursor);
ebc913e
+        if (ret2) {
ebc913e
+            ldbm_nasty(filename,24,ret2);
ebc913e
+            if (!ret) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                ret = ret2;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     return ret;
ebc913e
@@ -559,14 +572,17 @@ static int idl_new_store_allids(backend *be, DB *db, DBT *key, DB_TXN *txn)
ebc913e
 error:
ebc913e
     /* Close the cursor */
ebc913e
     if (NULL != cursor) {
ebc913e
-        if (0 != cursor->c_close(cursor)) {
ebc913e
-            ldbm_nasty(filename,33,ret);
ebc913e
+        int ret2 = cursor->c_close(cursor);
ebc913e
+        if (ret2) {
ebc913e
+            ldbm_nasty(filename,33,ret2);
ebc913e
         }
ebc913e
     }
ebc913e
     return ret;
ebc913e
+#ifdef KRAZY_K0DE
ebc913e
 	/* If this function is called in "no-allids" mode, then it's a bug */
ebc913e
 	ldbm_nasty(filename,63,0);
ebc913e
 	return -1;
ebc913e
+#endif
ebc913e
 }
ebc913e
 #endif
ebc913e
 
ebc913e
@@ -662,8 +678,14 @@ int idl_new_store_block(
ebc913e
 error:
ebc913e
     /* Close the cursor */
ebc913e
     if (NULL != cursor) {
ebc913e
-        if (0 != cursor->c_close(cursor)) {
ebc913e
-            ldbm_nasty(filename,49,ret);
ebc913e
+        int ret2 = cursor->c_close(cursor);
ebc913e
+        if (ret2) {
ebc913e
+            ldbm_nasty(filename,49,ret2);
ebc913e
+            if (!ret) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                ret = ret2;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     return ret;
ebc913e
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
ebc913e
index b07f634..014af73 100644
ebc913e
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
ebc913e
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
ebc913e
@@ -692,6 +692,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
ebc913e
 					retval = index_addordel_values_sv(be, LDBM_PARENTID_STR, 
ebc913e
 					                                  svals, NULL, e->ep_id, 
ebc913e
 					                                  BE_INDEX_ADD, &txn);
ebc913e
+					if (DB_LOCK_DEADLOCK == retval) {
ebc913e
+						LDAPDebug0Args( LDAP_DEBUG_ARGS,
ebc913e
+										"delete (updating " LDBM_PARENTID_STR ") DB_LOCK_DEADLOCK\n");
ebc913e
+						/* Retry txn */
ebc913e
+						continue;
ebc913e
+					}
ebc913e
 					if ( retval ) {
ebc913e
 						LDAPDebug( LDAP_DEBUG_TRACE, 
ebc913e
 								"delete (deleting %s) failed, err=%d %s\n",
ebc913e
@@ -703,18 +709,33 @@ ldbm_back_delete( Slapi_PBlock *pb )
ebc913e
 						goto error_return;
ebc913e
 					}
ebc913e
 				}
ebc913e
-				entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
ebc913e
-				retval =
ebc913e
-				        entryrdn_index_entry(be, tombstone, BE_INDEX_ADD, &txn);
ebc913e
+				retval = entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
ebc913e
+				if (DB_LOCK_DEADLOCK == retval) {
ebc913e
+					LDAPDebug0Args( LDAP_DEBUG_ARGS,
ebc913e
+								"delete (deleting entryrdn) DB_LOCK_DEADLOCK\n");
ebc913e
+					/* Retry txn */
ebc913e
+					continue;
ebc913e
+				}
ebc913e
+				if (0 != retval) {
ebc913e
+					LDAPDebug2Args( LDAP_DEBUG_TRACE, 
ebc913e
+								"delete (deleting entryrdn) failed, err=%d %s\n",
ebc913e
+								retval,
ebc913e
+								(msg = dblayer_strerror( retval )) ? msg : "" );
ebc913e
+					if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
ebc913e
+					DEL_SET_ERROR(ldap_result_code, 
ebc913e
+								  LDAP_OPERATIONS_ERROR, retry_count);
ebc913e
+					goto error_return;
ebc913e
+				}
ebc913e
+				retval = entryrdn_index_entry(be, tombstone, BE_INDEX_ADD, &txn);
ebc913e
 				if (DB_LOCK_DEADLOCK == retval) {
ebc913e
 					LDAPDebug0Args( LDAP_DEBUG_ARGS,
ebc913e
-								"delete (adding entryrdn) DB_LOCK_DEADLOCK\n");
ebc913e
+								"adding (adding tombstone entryrdn) DB_LOCK_DEADLOCK\n");
ebc913e
 					/* Retry txn */
ebc913e
 					continue;
ebc913e
 				}
ebc913e
 				if (0 != retval) {
ebc913e
 					LDAPDebug2Args( LDAP_DEBUG_TRACE, 
ebc913e
-								"delete (adding entryrdn) failed, err=%d %s\n",
ebc913e
+								"adding (adding tombstone entryrdn) failed, err=%d %s\n",
ebc913e
 								retval,
ebc913e
 								(msg = dblayer_strerror( retval )) ? msg : "" );
ebc913e
 					if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
ebc913e
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
ebc913e
index 2a7b1e4..4eba4ed 100644
ebc913e
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
ebc913e
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
ebc913e
@@ -280,9 +280,15 @@ bail:
ebc913e
     if (cursor) {
ebc913e
         int myrc = cursor->c_close(cursor);
ebc913e
         if (0 != myrc) {
ebc913e
-            slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
ebc913e
+            int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
ebc913e
+            slapi_log_error(loglevel, ENTRYRDN_TAG,
ebc913e
                   "entryrdn_index_entry: Failed to close cursor: %s(%d)\n",
ebc913e
-                  dblayer_strerror(rc), rc);
ebc913e
+                  dblayer_strerror(myrc), myrc);
ebc913e
+            if (!rc) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                rc = myrc;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     if (db) {
ebc913e
@@ -388,9 +394,15 @@ bail:
ebc913e
     if (cursor) {
ebc913e
         int myrc = cursor->c_close(cursor);
ebc913e
         if (0 != myrc) {
ebc913e
-            slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
ebc913e
-                            "entryrdn_index_read: Failed to close cursor: "
ebc913e
-                            "%s(%d)\n", dblayer_strerror(rc), rc);
ebc913e
+            int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
ebc913e
+            slapi_log_error(loglevel, ENTRYRDN_TAG,
ebc913e
+                  "entryrdn_index_read: Failed to close cursor: %s(%d)\n",
ebc913e
+                  dblayer_strerror(myrc), myrc);
ebc913e
+            if (!rc) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                rc = myrc;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     if (db) {
ebc913e
@@ -841,9 +853,15 @@ bail:
ebc913e
     if (cursor) {
ebc913e
         int myrc = cursor->c_close(cursor);
ebc913e
         if (0 != myrc) {
ebc913e
-            slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
ebc913e
+            int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
ebc913e
+            slapi_log_error(loglevel, ENTRYRDN_TAG,
ebc913e
                   "entryrdn_rename_subtree: Failed to close cursor: %s(%d)\n",
ebc913e
-                  dblayer_strerror(rc), rc);
ebc913e
+                  dblayer_strerror(myrc), myrc);
ebc913e
+            if (!rc) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                rc = myrc;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     if (db) {
ebc913e
@@ -983,9 +1001,15 @@ bail:
ebc913e
     if (cursor) {
ebc913e
         int myrc = cursor->c_close(cursor);
ebc913e
         if (0 != myrc) {
ebc913e
-            slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
ebc913e
+            int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
ebc913e
+            slapi_log_error(loglevel, ENTRYRDN_TAG,
ebc913e
                   "entryrdn_get_subordinates: Failed to close cursor: %s(%d)\n",
ebc913e
-                  dblayer_strerror(rc), rc);
ebc913e
+                  dblayer_strerror(myrc), myrc);
ebc913e
+            if (!rc) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                rc = myrc;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     if (db) {
ebc913e
@@ -1147,9 +1171,15 @@ bail:
ebc913e
     if (cursor) {
ebc913e
         int myrc = cursor->c_close(cursor);
ebc913e
         if (0 != myrc) {
ebc913e
-            slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
ebc913e
+            int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
ebc913e
+            slapi_log_error(loglevel, ENTRYRDN_TAG,
ebc913e
                   "entryrdn_lookup_dn: Failed to close cursor: %s(%d)\n",
ebc913e
                   dblayer_strerror(myrc), myrc);
ebc913e
+            if (!rc) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                rc = myrc;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     /* it is guaranteed that db is not NULL. */
ebc913e
@@ -1294,9 +1324,15 @@ bail:
ebc913e
     if (cursor) {
ebc913e
         int myrc = cursor->c_close(cursor);
ebc913e
         if (0 != myrc) {
ebc913e
-            slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
ebc913e
+            int loglevel = (myrc == DB_LOCK_DEADLOCK) ? SLAPI_LOG_TRACE : SLAPI_LOG_FATAL;
ebc913e
+            slapi_log_error(loglevel, ENTRYRDN_TAG,
ebc913e
                   "entryrdn_get_parent: Failed to close cursor: %s(%d)\n",
ebc913e
-                  dblayer_strerror(rc), rc);
ebc913e
+                  dblayer_strerror(myrc), myrc);
ebc913e
+            if (!rc) {
ebc913e
+                /* if cursor close returns DEADLOCK, we must bubble that up
ebc913e
+                   to the higher layers for retries */
ebc913e
+                rc = myrc;
ebc913e
+            }
ebc913e
         }
ebc913e
     }
ebc913e
     /* it is guaranteed that db is not NULL. */
ebc913e
-- 
ebc913e
1.7.1
ebc913e