|
|
dc8c34 |
From 55e8358edd9c53cf96f7745e3cf241fd72b11b77 Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
dc8c34 |
Date: Wed, 16 Apr 2014 15:21:21 -0400
|
|
|
dc8c34 |
Subject: [PATCH 202/225] Ticket 47782 - Parent numbordinate count can be
|
|
|
dc8c34 |
incorrectly updated if an error occurs
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Bug Description: When adding and deleting entries there is a small chance that the modified
|
|
|
dc8c34 |
parent entry(numbsubordinates) could be replaced in the entry cache, even
|
|
|
dc8c34 |
if the operation fails.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Fix Description: For deletes we can simply move the cache entry switching to a safe location,
|
|
|
dc8c34 |
but for adds we need to unswitch the parent's entry in the cache.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/47782
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Reviewed by: nhosoi(Thanks!)
|
|
|
dc8c34 |
(cherry picked from commit ac8ada32de4bcc3dfd0a3e2958cefd91f98c4170)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_add.c | 13 +++++++++
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 12 ++++----
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 38 ++++++++++++++++++++++++++
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 1 +
|
|
|
dc8c34 |
4 files changed, 58 insertions(+), 6 deletions(-)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
|
|
dc8c34 |
index 554822c..0ade23c 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
|
|
dc8c34 |
@@ -117,6 +117,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
int is_ruv = 0; /* True if the current entry is RUV */
|
|
|
dc8c34 |
CSN *opcsn = NULL;
|
|
|
dc8c34 |
entry_address addr = {0};
|
|
|
dc8c34 |
+ int parent_switched = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e );
|
|
|
dc8c34 |
@@ -974,6 +975,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* switch the parent entry copy into play */
|
|
|
dc8c34 |
modify_switch_entries( &parent_modify_c,be);
|
|
|
dc8c34 |
+ parent_switched = 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (ruv_c_init) {
|
|
|
dc8c34 |
@@ -1046,6 +1048,17 @@ error_return:
|
|
|
dc8c34 |
dblayer_remember_disk_filled(li);
|
|
|
dc8c34 |
ldbm_nasty("Add",80,rc);
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
+ } else if (0 == rc) {
|
|
|
dc8c34 |
+ rc = SLAPI_FAIL_GENERAL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (parent_switched){
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * Restore the old parent entry, switch the new with the original.
|
|
|
dc8c34 |
+ * Otherwise the numsubordinate count will be off, and could later
|
|
|
dc8c34 |
+ * be written to disk.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ modify_unswitch_entries( &parent_modify_c,be);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diskfull_return:
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
|
|
dc8c34 |
index 7c036df..c80d75a 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
|
|
dc8c34 |
@@ -1095,12 +1095,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
CACHE_RETURN(&inst->inst_cache, &e);
|
|
|
dc8c34 |
e = NULL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- if (parent_found)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- /* Replace the old parent entry with the newly modified one */
|
|
|
dc8c34 |
- modify_switch_entries( &parent_modify_c,be);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (ruv_c_init) {
|
|
|
dc8c34 |
if (modify_switch_entries(&ruv_c, be) != 0 ) {
|
|
|
dc8c34 |
@@ -1112,6 +1106,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ if (parent_found)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ /* Replace the old parent entry with the newly modified one */
|
|
|
dc8c34 |
+ modify_switch_entries( &parent_modify_c,be);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
rc= 0;
|
|
|
dc8c34 |
goto common_return;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
index b8b6114..be47fcc 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
@@ -122,6 +122,44 @@ int modify_switch_entries(modify_context *mc,backend *be)
|
|
|
dc8c34 |
return ret;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * Switch the new with the old(original) - undoing modify_switch_entries()
|
|
|
dc8c34 |
+ * This expects modify_term() to be called next, as the old "new" entry
|
|
|
dc8c34 |
+ * is now gone(replaced by the original entry).
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+modify_unswitch_entries(modify_context *mc,backend *be)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ struct backentry *tmp_be;
|
|
|
dc8c34 |
+ ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
|
|
|
dc8c34 |
+ int ret = 0;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (mc->old_entry!=NULL && mc->new_entry!=NULL) {
|
|
|
dc8c34 |
+ /* switch the entries, and reset the new, new, entry */
|
|
|
dc8c34 |
+ tmp_be = mc->new_entry;
|
|
|
dc8c34 |
+ mc->new_entry = mc->old_entry;
|
|
|
dc8c34 |
+ mc->new_entry->ep_state = 0;
|
|
|
dc8c34 |
+ mc->new_entry->ep_refcnt = 0;
|
|
|
dc8c34 |
+ mc->new_entry_in_cache = 0;
|
|
|
dc8c34 |
+ mc->old_entry = tmp_be;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ ret = cache_replace(&(inst->inst_cache), mc->old_entry, mc->new_entry);
|
|
|
dc8c34 |
+ if (ret == 0) {
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * The new entry was originally locked, so since we did the
|
|
|
dc8c34 |
+ * switch we need to unlock the "new" entry, and return the
|
|
|
dc8c34 |
+ * "old" one. modify_term() will then return the "new" entry.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ cache_unlock_entry(&inst->inst_cache, mc->new_entry);
|
|
|
dc8c34 |
+ CACHE_RETURN( &(inst->inst_cache), &(mc->old_entry) );
|
|
|
dc8c34 |
+ mc->new_entry_in_cache = 1;
|
|
|
dc8c34 |
+ mc->old_entry = NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ return ret;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/* This routine does that part of a modify operation which involves
|
|
|
dc8c34 |
updating the on-disk data: updates idices, id2entry.
|
|
|
dc8c34 |
Copes properly with DB_LOCK_DEADLOCK. The caller must be able to cope with
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
index ee30c45..02b261b 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
@@ -350,6 +350,7 @@ void modify_init(modify_context *mc,struct backentry *old_entry);
|
|
|
dc8c34 |
int modify_apply_mods(modify_context *mc, Slapi_Mods *smods);
|
|
|
dc8c34 |
int modify_term(modify_context *mc,backend *be);
|
|
|
dc8c34 |
int modify_switch_entries(modify_context *mc,backend *be);
|
|
|
dc8c34 |
+int modify_unswitch_entries(modify_context *mc,backend *be);
|
|
|
dc8c34 |
int modify_apply_mods_ignore_error(modify_context *mc, Slapi_Mods *smods, int error);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.8.1.4
|
|
|
dc8c34 |
|