mirror of
https://git.centos.org/rpms/389-ds-base.git
synced 2025-02-24 00:32:54 +00:00
import 389-ds-base-1.3.6.1-19.el7_4
This commit is contained in:
parent
74ca47f593
commit
1c155e2849
7 changed files with 1794 additions and 43 deletions
|
@ -0,0 +1,47 @@
|
||||||
|
From 0fc3c803c34311eb05c5c7a7e710c8591b592649 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Thierry Bordaz <tbordaz@redhat.com>
|
||||||
|
Date: Thu, 27 Jul 2017 18:10:05 +0200
|
||||||
|
Subject: [PATCH] Ticket 49313 - Change the retrochangelog default cache size
|
||||||
|
|
||||||
|
Bug Description:
|
||||||
|
Default retroCL backend entry cache size is 2Mb.
|
||||||
|
It has been reported in many deployments that DB corruption could
|
||||||
|
be prevented by increasing entry cache to 200Mb.
|
||||||
|
There is no identified reproducible steps to debug this DB corruption.
|
||||||
|
So to prevent this problem we are increasing the entry cache
|
||||||
|
|
||||||
|
Fix Description:
|
||||||
|
Set default cn=changelog cache to 200Mb (based on production cases)
|
||||||
|
An other option would be to set a maximum number of entries but
|
||||||
|
as we do not know if it works to prevent DB corruption, let's prefere
|
||||||
|
entry cache size
|
||||||
|
|
||||||
|
https://pagure.io/389-ds-base/issue/49313
|
||||||
|
|
||||||
|
Reviewed by: William Brown
|
||||||
|
|
||||||
|
Platforms tested: F23
|
||||||
|
|
||||||
|
Flag Day: no
|
||||||
|
|
||||||
|
Doc impact: no
|
||||||
|
---
|
||||||
|
ldap/servers/plugins/retrocl/retrocl.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/plugins/retrocl/retrocl.h b/ldap/servers/plugins/retrocl/retrocl.h
|
||||||
|
index 6963d4b..eef1a17 100644
|
||||||
|
--- a/ldap/servers/plugins/retrocl/retrocl.h
|
||||||
|
+++ b/ldap/servers/plugins/retrocl/retrocl.h
|
||||||
|
@@ -58,7 +58,7 @@ typedef struct _cnumRet {
|
||||||
|
#else
|
||||||
|
#define RETROCL_DLL_DEFAULT_THREAD_STACKSIZE 131072L
|
||||||
|
#endif
|
||||||
|
-#define RETROCL_BE_CACHEMEMSIZE "2097152"
|
||||||
|
+#define RETROCL_BE_CACHEMEMSIZE "209715200"
|
||||||
|
#define RETROCL_BE_CACHESIZE "-1"
|
||||||
|
#define RETROCL_PLUGIN_NAME "DSRetroclPlugin"
|
||||||
|
|
||||||
|
--
|
||||||
|
2.9.4
|
||||||
|
|
|
@ -0,0 +1,795 @@
|
||||||
|
From 6b5aa0e288f1ea5553d4dd5d220d4e5daf50a247 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mark Reynolds <mreynolds@redhat.com>
|
||||||
|
Date: Mon, 31 Jul 2017 14:45:50 -0400
|
||||||
|
Subject: [PATCH] Ticket 49287 - v3 extend csnpl handling to multiple backends
|
||||||
|
|
||||||
|
The csn pending list mechanism failed if internal operation affected multiple backends
|
||||||
|
|
||||||
|
This fix is an extension to the fix in ticket 49008, the thread local data now also contains
|
||||||
|
a list of all affected replicas.
|
||||||
|
|
||||||
|
http://www.port389.org/docs/389ds/design/csn-pending-lists-and-ruv-update.html
|
||||||
|
|
||||||
|
Reviewed by: William, Thierry - thanks
|
||||||
|
---
|
||||||
|
ldap/servers/plugins/replication/csnpl.c | 85 ++++++++--
|
||||||
|
ldap/servers/plugins/replication/csnpl.h | 8 +-
|
||||||
|
ldap/servers/plugins/replication/repl5.h | 22 ++-
|
||||||
|
ldap/servers/plugins/replication/repl5_init.c | 48 +++++-
|
||||||
|
ldap/servers/plugins/replication/repl5_plugins.c | 16 +-
|
||||||
|
ldap/servers/plugins/replication/repl5_replica.c | 18 ++-
|
||||||
|
ldap/servers/plugins/replication/repl5_ruv.c | 191 ++++++++++++++---------
|
||||||
|
ldap/servers/plugins/replication/repl5_ruv.h | 6 +-
|
||||||
|
ldap/servers/slapd/slapi-private.h | 2 +-
|
||||||
|
9 files changed, 283 insertions(+), 113 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/plugins/replication/csnpl.c b/ldap/servers/plugins/replication/csnpl.c
|
||||||
|
index 4a0f5f5..12a0bb8 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/csnpl.c
|
||||||
|
+++ b/ldap/servers/plugins/replication/csnpl.c
|
||||||
|
@@ -14,7 +14,6 @@
|
||||||
|
|
||||||
|
#include "csnpl.h"
|
||||||
|
#include "llist.h"
|
||||||
|
-#include "repl_shared.h"
|
||||||
|
|
||||||
|
struct csnpl
|
||||||
|
{
|
||||||
|
@@ -22,13 +21,17 @@ struct csnpl
|
||||||
|
Slapi_RWLock* csnLock; /* lock to serialize access to PL */
|
||||||
|
};
|
||||||
|
|
||||||
|
+
|
||||||
|
typedef struct _csnpldata
|
||||||
|
{
|
||||||
|
PRBool committed; /* True if CSN committed */
|
||||||
|
CSN *csn; /* The actual CSN */
|
||||||
|
+ Replica * prim_replica; /* The replica where the prom csn was generated */
|
||||||
|
const CSN *prim_csn; /* The primary CSN of an operation consising of multiple sub ops*/
|
||||||
|
} csnpldata;
|
||||||
|
|
||||||
|
+static PRBool csn_primary_or_nested(csnpldata *csn_data, const CSNPL_CTX *csn_ctx);
|
||||||
|
+
|
||||||
|
/* forward declarations */
|
||||||
|
#ifdef DEBUG
|
||||||
|
static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller);
|
||||||
|
@@ -104,7 +107,7 @@ void csnplFree (CSNPL **csnpl)
|
||||||
|
* 1 if the csn has already been seen
|
||||||
|
* -1 for any other kind of errors
|
||||||
|
*/
|
||||||
|
-int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn)
|
||||||
|
+int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSNPL_CTX *prim_csn)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
csnpldata *csnplnode;
|
||||||
|
@@ -129,10 +132,13 @@ int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- csnplnode = (csnpldata *)slapi_ch_malloc(sizeof(csnpldata));
|
||||||
|
+ csnplnode = (csnpldata *)slapi_ch_calloc(1, sizeof(csnpldata));
|
||||||
|
csnplnode->committed = PR_FALSE;
|
||||||
|
csnplnode->csn = csn_dup(csn);
|
||||||
|
- csnplnode->prim_csn = prim_csn;
|
||||||
|
+ if (prim_csn) {
|
||||||
|
+ csnplnode->prim_csn = prim_csn->prim_csn;
|
||||||
|
+ csnplnode->prim_replica = prim_csn->prim_repl;
|
||||||
|
+ }
|
||||||
|
csn_as_string(csn, PR_FALSE, csn_str);
|
||||||
|
rc = llistInsertTail (csnpl->csnList, csn_str, csnplnode);
|
||||||
|
|
||||||
|
@@ -187,8 +193,58 @@ int csnplRemove (CSNPL *csnpl, const CSN *csn)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+PRBool csn_primary(Replica *replica, const CSN *csn, const CSNPL_CTX *csn_ctx)
|
||||||
|
+{
|
||||||
|
+ if (csn_ctx == NULL)
|
||||||
|
+ return PR_FALSE;
|
||||||
|
+
|
||||||
|
+ if (replica != csn_ctx->prim_repl) {
|
||||||
|
+ /* The CSNs are not from the same replication topology
|
||||||
|
+ * so even if the csn values are equal they are not related
|
||||||
|
+ * to the same operation
|
||||||
|
+ */
|
||||||
|
+ return PR_FALSE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Here the two CSNs belong to the same replication topology */
|
||||||
|
+
|
||||||
|
+ /* check if the CSN identifies the primary update */
|
||||||
|
+ if (csn_is_equal(csn, csn_ctx->prim_csn)) {
|
||||||
|
+ return PR_TRUE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return PR_FALSE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static PRBool csn_primary_or_nested(csnpldata *csn_data, const CSNPL_CTX *csn_ctx)
|
||||||
|
+{
|
||||||
|
+ if ((csn_data == NULL) || (csn_ctx == NULL))
|
||||||
|
+ return PR_FALSE;
|
||||||
|
+
|
||||||
|
+ if (csn_data->prim_replica != csn_ctx->prim_repl) {
|
||||||
|
+ /* The CSNs are not from the same replication topology
|
||||||
|
+ * so even if the csn values are equal they are not related
|
||||||
|
+ * to the same operation
|
||||||
|
+ */
|
||||||
|
+ return PR_FALSE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Here the two CSNs belong to the same replication topology */
|
||||||
|
+
|
||||||
|
+ /* First check if the CSN identifies the primary update */
|
||||||
|
+ if (csn_is_equal(csn_data->csn, csn_ctx->prim_csn)) {
|
||||||
|
+ return PR_TRUE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Second check if the CSN identifies a nested update */
|
||||||
|
+ if (csn_is_equal(csn_data->prim_csn, csn_ctx->prim_csn)) {
|
||||||
|
+ return PR_TRUE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return PR_FALSE;
|
||||||
|
+}
|
||||||
|
|
||||||
|
-int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
|
||||||
|
+int csnplRemoveAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx)
|
||||||
|
{
|
||||||
|
csnpldata *data;
|
||||||
|
void *iterator;
|
||||||
|
@@ -197,8 +253,7 @@ int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
|
||||||
|
data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
|
||||||
|
while (NULL != data)
|
||||||
|
{
|
||||||
|
- if (csn_is_equal(data->csn, csn) ||
|
||||||
|
- csn_is_equal(data->prim_csn, csn)) {
|
||||||
|
+ if (csn_primary_or_nested(data, csn_ctx)) {
|
||||||
|
csnpldata_free(&data);
|
||||||
|
data = (csnpldata *)llistRemoveCurrentAndGetNext(csnpl->csnList, &iterator);
|
||||||
|
} else {
|
||||||
|
@@ -213,13 +268,13 @@ int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
|
||||||
|
+int csnplCommitAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx)
|
||||||
|
{
|
||||||
|
csnpldata *data;
|
||||||
|
void *iterator;
|
||||||
|
char csn_str[CSN_STRSIZE];
|
||||||
|
|
||||||
|
- csn_as_string(csn, PR_FALSE, csn_str);
|
||||||
|
+ csn_as_string(csn_ctx->prim_csn, PR_FALSE, csn_str);
|
||||||
|
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
||||||
|
"csnplCommitALL: committing all csns for csn %s\n", csn_str);
|
||||||
|
slapi_rwlock_wrlock (csnpl->csnLock);
|
||||||
|
@@ -229,8 +284,7 @@ int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
|
||||||
|
csn_as_string(data->csn, PR_FALSE, csn_str);
|
||||||
|
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
||||||
|
"csnplCommitALL: processing data csn %s\n", csn_str);
|
||||||
|
- if (csn_is_equal(data->csn, csn) ||
|
||||||
|
- csn_is_equal(data->prim_csn, csn)) {
|
||||||
|
+ if (csn_primary_or_nested(data, csn_ctx)) {
|
||||||
|
data->committed = PR_TRUE;
|
||||||
|
}
|
||||||
|
data = (csnpldata *)llistGetNext (csnpl->csnList, &iterator);
|
||||||
|
@@ -395,7 +449,12 @@ static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller)
|
||||||
|
|
||||||
|
/* wrapper around csn_free, to satisfy NSPR thread context API */
|
||||||
|
void
|
||||||
|
-csnplFreeCSN (void *arg)
|
||||||
|
+csnplFreeCSNPL_CTX (void *arg)
|
||||||
|
{
|
||||||
|
- csn_free((CSN **)&arg);
|
||||||
|
+ CSNPL_CTX *csnpl_ctx = (CSNPL_CTX *)arg;
|
||||||
|
+ csn_free(&csnpl_ctx->prim_csn);
|
||||||
|
+ if (csnpl_ctx->sec_repl) {
|
||||||
|
+ slapi_ch_free((void **)&csnpl_ctx->sec_repl);
|
||||||
|
+ }
|
||||||
|
+ slapi_ch_free((void **)&csnpl_ctx);
|
||||||
|
}
|
||||||
|
diff --git a/ldap/servers/plugins/replication/csnpl.h b/ldap/servers/plugins/replication/csnpl.h
|
||||||
|
index 594c8f2..1036c62 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/csnpl.h
|
||||||
|
+++ b/ldap/servers/plugins/replication/csnpl.h
|
||||||
|
@@ -17,15 +17,17 @@
|
||||||
|
#define CSNPL_H
|
||||||
|
|
||||||
|
#include "slapi-private.h"
|
||||||
|
+#include "repl5.h"
|
||||||
|
|
||||||
|
typedef struct csnpl CSNPL;
|
||||||
|
|
||||||
|
CSNPL* csnplNew(void);
|
||||||
|
void csnplFree (CSNPL **csnpl);
|
||||||
|
-int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn);
|
||||||
|
+int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSNPL_CTX *prim_csn);
|
||||||
|
int csnplRemove (CSNPL *csnpl, const CSN *csn);
|
||||||
|
-int csnplRemoveAll (CSNPL *csnpl, const CSN *csn);
|
||||||
|
-int csnplCommitAll (CSNPL *csnpl, const CSN *csn);
|
||||||
|
+int csnplRemoveAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx);
|
||||||
|
+int csnplCommitAll (CSNPL *csnpl, const CSNPL_CTX *csn_ctx);
|
||||||
|
+PRBool csn_primary(Replica *replica, const CSN *csn, const CSNPL_CTX *csn_ctx);
|
||||||
|
CSN* csnplGetMinCSN (CSNPL *csnpl, PRBool *committed);
|
||||||
|
int csnplCommit (CSNPL *csnpl, const CSN *csn);
|
||||||
|
CSN *csnplRollUp(CSNPL *csnpl, CSN ** first);
|
||||||
|
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
|
||||||
|
index 1d8989c..718f64e 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/repl5.h
|
||||||
|
+++ b/ldap/servers/plugins/replication/repl5.h
|
||||||
|
@@ -228,12 +228,27 @@ int multimaster_be_betxnpostop_delete (Slapi_PBlock *pb);
|
||||||
|
int multimaster_be_betxnpostop_add (Slapi_PBlock *pb);
|
||||||
|
int multimaster_be_betxnpostop_modify (Slapi_PBlock *pb);
|
||||||
|
|
||||||
|
+/* In repl5_replica.c */
|
||||||
|
+typedef struct replica Replica;
|
||||||
|
+
|
||||||
|
+/* csn pending lists */
|
||||||
|
+#define CSNPL_CTX_REPLCNT 4
|
||||||
|
+typedef struct CSNPL_CTX
|
||||||
|
+{
|
||||||
|
+ CSN *prim_csn;
|
||||||
|
+ size_t repl_alloc; /* max number of replicas */
|
||||||
|
+ size_t repl_cnt; /* number of replicas affected by operation */
|
||||||
|
+ Replica *prim_repl; /* pirmary replica */
|
||||||
|
+ Replica **sec_repl; /* additional replicas affected */
|
||||||
|
+} CSNPL_CTX;
|
||||||
|
+
|
||||||
|
/* In repl5_init.c */
|
||||||
|
extern int repl5_is_betxn;
|
||||||
|
char* get_thread_private_agmtname(void);
|
||||||
|
void set_thread_private_agmtname (const char *agmtname);
|
||||||
|
-void set_thread_primary_csn (const CSN *prim_csn);
|
||||||
|
-CSN* get_thread_primary_csn(void);
|
||||||
|
+void set_thread_primary_csn (const CSN *prim_csn, Replica *repl);
|
||||||
|
+void add_replica_to_primcsn(CSNPL_CTX *prim_csn, Replica *repl);
|
||||||
|
+CSNPL_CTX* get_thread_primary_csn(void);
|
||||||
|
void* get_thread_private_cache(void);
|
||||||
|
void set_thread_private_cache (void *buf);
|
||||||
|
char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);
|
||||||
|
@@ -302,7 +317,6 @@ typedef struct repl_bos Repl_Bos;
|
||||||
|
|
||||||
|
/* In repl5_agmt.c */
|
||||||
|
typedef struct repl5agmt Repl_Agmt;
|
||||||
|
-typedef struct replica Replica;
|
||||||
|
|
||||||
|
#define TRANSPORT_FLAG_SSL 1
|
||||||
|
#define TRANSPORT_FLAG_TLS 2
|
||||||
|
@@ -629,6 +643,8 @@ PRUint64 replica_get_precise_purging(Replica *r);
|
||||||
|
void replica_set_precise_purging(Replica *r, PRUint64 on_off);
|
||||||
|
PRBool ignore_error_and_keep_going(int error);
|
||||||
|
void replica_check_release_timeout(Replica *r, Slapi_PBlock *pb);
|
||||||
|
+void replica_lock_replica(Replica *r);
|
||||||
|
+void replica_unlock_replica(Replica *r);
|
||||||
|
|
||||||
|
/* The functions below handles the state flag */
|
||||||
|
/* Current internal state flags */
|
||||||
|
diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c
|
||||||
|
index edffb84..b0bc515 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/repl5_init.c
|
||||||
|
+++ b/ldap/servers/plugins/replication/repl5_init.c
|
||||||
|
@@ -154,26 +154,62 @@ set_thread_private_agmtname(const char *agmtname)
|
||||||
|
PR_SetThreadPrivate(thread_private_agmtname, (void *)agmtname);
|
||||||
|
}
|
||||||
|
|
||||||
|
-CSN*
|
||||||
|
+CSNPL_CTX*
|
||||||
|
get_thread_primary_csn(void)
|
||||||
|
{
|
||||||
|
- CSN *prim_csn = NULL;
|
||||||
|
+ CSNPL_CTX *prim_csn = NULL;
|
||||||
|
if (thread_primary_csn)
|
||||||
|
- prim_csn = (CSN *)PR_GetThreadPrivate(thread_primary_csn);
|
||||||
|
+ prim_csn = (CSNPL_CTX *)PR_GetThreadPrivate(thread_primary_csn);
|
||||||
|
+
|
||||||
|
return prim_csn;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
-set_thread_primary_csn(const CSN *prim_csn)
|
||||||
|
+set_thread_primary_csn (const CSN *prim_csn, Replica *repl)
|
||||||
|
{
|
||||||
|
if (thread_primary_csn) {
|
||||||
|
if (prim_csn) {
|
||||||
|
- PR_SetThreadPrivate(thread_primary_csn, (void *)csn_dup(prim_csn));
|
||||||
|
+ CSNPL_CTX *csnpl_ctx = (CSNPL_CTX *)slapi_ch_calloc(1,sizeof(CSNPL_CTX));
|
||||||
|
+ csnpl_ctx->prim_csn = csn_dup(prim_csn);
|
||||||
|
+ /* repl_alloc, repl_cnt and sec_repl are 0 by calloc */
|
||||||
|
+ csnpl_ctx->prim_repl = repl;
|
||||||
|
+ PR_SetThreadPrivate(thread_primary_csn, (void *)csnpl_ctx);
|
||||||
|
} else {
|
||||||
|
PR_SetThreadPrivate(thread_primary_csn, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+add_replica_to_primcsn(CSNPL_CTX *csnpl_ctx, Replica *repl)
|
||||||
|
+{
|
||||||
|
+ size_t found = 0;
|
||||||
|
+ size_t it = 0;
|
||||||
|
+
|
||||||
|
+ if (repl == csnpl_ctx->prim_repl) return;
|
||||||
|
+
|
||||||
|
+ while (it < csnpl_ctx->repl_cnt) {
|
||||||
|
+ if (csnpl_ctx->sec_repl[it] == repl) {
|
||||||
|
+ found = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ it++;
|
||||||
|
+ }
|
||||||
|
+ if (found) return;
|
||||||
|
+
|
||||||
|
+ if (csnpl_ctx->repl_cnt < csnpl_ctx->repl_alloc) {
|
||||||
|
+ csnpl_ctx->sec_repl[csnpl_ctx->repl_cnt++] = repl;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ csnpl_ctx->repl_alloc += CSNPL_CTX_REPLCNT;
|
||||||
|
+ if (csnpl_ctx->repl_cnt == 0) {
|
||||||
|
+ csnpl_ctx->sec_repl = (Replica **)slapi_ch_calloc(csnpl_ctx->repl_alloc, sizeof(Replica *));
|
||||||
|
+ } else {
|
||||||
|
+ csnpl_ctx->sec_repl = (Replica **)slapi_ch_realloc((char *)csnpl_ctx->sec_repl, csnpl_ctx->repl_alloc * sizeof(Replica *));
|
||||||
|
+ }
|
||||||
|
+ csnpl_ctx->sec_repl[csnpl_ctx->repl_cnt++] = repl;
|
||||||
|
+ return;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void*
|
||||||
|
get_thread_private_cache ()
|
||||||
|
{
|
||||||
|
@@ -740,7 +776,7 @@ multimaster_start( Slapi_PBlock *pb )
|
||||||
|
/* Initialize thread private data for logging. Ignore if fails */
|
||||||
|
PR_NewThreadPrivateIndex (&thread_private_agmtname, NULL);
|
||||||
|
PR_NewThreadPrivateIndex (&thread_private_cache, NULL);
|
||||||
|
- PR_NewThreadPrivateIndex (&thread_primary_csn, csnplFreeCSN);
|
||||||
|
+ PR_NewThreadPrivateIndex (&thread_primary_csn, csnplFreeCSNPL_CTX);
|
||||||
|
|
||||||
|
/* Decode the command line args to see if we're dumping to LDIF */
|
||||||
|
is_ldif_dump = check_for_ldif_dump(pb);
|
||||||
|
diff --git a/ldap/servers/plugins/replication/repl5_plugins.c b/ldap/servers/plugins/replication/repl5_plugins.c
|
||||||
|
index 9ef06af..c31d9d5 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/repl5_plugins.c
|
||||||
|
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
|
||||||
|
@@ -45,6 +45,7 @@
|
||||||
|
#include "repl.h"
|
||||||
|
#include "cl5_api.h"
|
||||||
|
#include "urp.h"
|
||||||
|
+#include "csnpl.h"
|
||||||
|
|
||||||
|
static char *local_purl = NULL;
|
||||||
|
static char *purl_attrs[] = {"nsslapd-localhost", "nsslapd-port", "nsslapd-secureport", NULL};
|
||||||
|
@@ -1034,7 +1035,7 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||||
|
{
|
||||||
|
Slapi_Operation *op = NULL;
|
||||||
|
CSN *opcsn;
|
||||||
|
- CSN *prim_csn;
|
||||||
|
+ CSNPL_CTX *prim_csn;
|
||||||
|
int rc;
|
||||||
|
slapi_operation_parameters *op_params = NULL;
|
||||||
|
Object *repl_obj = NULL;
|
||||||
|
@@ -1070,14 +1071,15 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||||
|
if (repl_obj == NULL)
|
||||||
|
return return_value;
|
||||||
|
|
||||||
|
+ r = (Replica*)object_get_data (repl_obj);
|
||||||
|
+ PR_ASSERT (r);
|
||||||
|
+
|
||||||
|
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
|
||||||
|
if (rc) { /* op failed - just return */
|
||||||
|
cancel_opcsn(pb);
|
||||||
|
goto common_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- r = (Replica*)object_get_data (repl_obj);
|
||||||
|
- PR_ASSERT (r);
|
||||||
|
|
||||||
|
replica_check_release_timeout(r, pb);
|
||||||
|
|
||||||
|
@@ -1223,12 +1225,12 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||||
|
common_return:
|
||||||
|
opcsn = operation_get_csn(op);
|
||||||
|
prim_csn = get_thread_primary_csn();
|
||||||
|
- if (csn_is_equal(opcsn, prim_csn)) {
|
||||||
|
+ if (csn_primary(r, opcsn, prim_csn)) {
|
||||||
|
if (return_value == 0) {
|
||||||
|
/* the primary csn was succesfully committed
|
||||||
|
* unset it in the thread local data
|
||||||
|
*/
|
||||||
|
- set_thread_primary_csn(NULL);
|
||||||
|
+ set_thread_primary_csn(NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (repl_obj) {
|
||||||
|
@@ -1430,7 +1432,7 @@ cancel_opcsn (Slapi_PBlock *pb)
|
||||||
|
|
||||||
|
ruv_obj = replica_get_ruv (r);
|
||||||
|
PR_ASSERT (ruv_obj);
|
||||||
|
- ruv_cancel_csn_inprogress ((RUV*)object_get_data (ruv_obj), opcsn, replica_get_rid(r));
|
||||||
|
+ ruv_cancel_csn_inprogress (r, (RUV*)object_get_data (ruv_obj), opcsn, replica_get_rid(r));
|
||||||
|
object_release (ruv_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1491,7 +1493,7 @@ process_operation (Slapi_PBlock *pb, const CSN *csn)
|
||||||
|
ruv = (RUV*)object_get_data (ruv_obj);
|
||||||
|
PR_ASSERT (ruv);
|
||||||
|
|
||||||
|
- rc = ruv_add_csn_inprogress (ruv, csn);
|
||||||
|
+ rc = ruv_add_csn_inprogress (r, ruv, csn);
|
||||||
|
|
||||||
|
object_release (ruv_obj);
|
||||||
|
object_release (r_obj);
|
||||||
|
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
|
||||||
|
index 1bdc138..7927ac3 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/repl5_replica.c
|
||||||
|
+++ b/ldap/servers/plugins/replication/repl5_replica.c
|
||||||
|
@@ -923,7 +923,7 @@ replica_update_ruv(Replica *r, const CSN *updated_csn, const char *replica_purl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update max csn for local and remote replicas */
|
||||||
|
- rc = ruv_update_ruv (ruv, updated_csn, replica_purl, r->repl_rid);
|
||||||
|
+ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, r, r->repl_rid);
|
||||||
|
if (RUV_COVERS_CSN == rc)
|
||||||
|
{
|
||||||
|
slapi_log_err(SLAPI_LOG_REPL,
|
||||||
|
@@ -3663,7 +3663,7 @@ assign_csn_callback(const CSN *csn, void *data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- ruv_add_csn_inprogress (ruv, csn);
|
||||||
|
+ ruv_add_csn_inprogress (r, ruv, csn);
|
||||||
|
|
||||||
|
replica_unlock(r->repl_lock);
|
||||||
|
|
||||||
|
@@ -3692,13 +3692,13 @@ abort_csn_callback(const CSN *csn, void *data)
|
||||||
|
{
|
||||||
|
int rc = csnplRemove(r->min_csn_pl, csn);
|
||||||
|
if (rc) {
|
||||||
|
- slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "abort_csn_callback - csnplRemove failed");
|
||||||
|
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "abort_csn_callback - csnplRemove failed\n");
|
||||||
|
replica_unlock(r->repl_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- ruv_cancel_csn_inprogress (ruv, csn, replica_get_rid(r));
|
||||||
|
+ ruv_cancel_csn_inprogress (r, ruv, csn, replica_get_rid(r));
|
||||||
|
replica_unlock(r->repl_lock);
|
||||||
|
|
||||||
|
object_release (ruv_obj);
|
||||||
|
@@ -4489,3 +4489,13 @@ replica_check_release_timeout(Replica *r, Slapi_PBlock *pb)
|
||||||
|
}
|
||||||
|
replica_unlock(r->repl_lock);
|
||||||
|
}
|
||||||
|
+void
|
||||||
|
+replica_lock_replica(Replica *r)
|
||||||
|
+{
|
||||||
|
+ replica_lock(r->repl_lock);
|
||||||
|
+}
|
||||||
|
+void
|
||||||
|
+replica_unlock_replica(Replica *r)
|
||||||
|
+{
|
||||||
|
+ replica_unlock(r->repl_lock);
|
||||||
|
+}
|
||||||
|
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
|
||||||
|
index d59e6d2..39449b6 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/repl5_ruv.c
|
||||||
|
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
|
||||||
|
@@ -77,7 +77,7 @@ static char *get_replgen_from_berval(const struct berval *bval);
|
||||||
|
static const char * const prefix_replicageneration = "{replicageneration}";
|
||||||
|
static const char * const prefix_ruvcsn = "{replica "; /* intentionally missing '}' */
|
||||||
|
|
||||||
|
-static int ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSN *csn, const char *replica_purl, PRBool isLocal);
|
||||||
|
+static int ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSNPL_CTX *prim_csn, const char *replica_purl, PRBool isLocal);
|
||||||
|
|
||||||
|
/* API implementation */
|
||||||
|
|
||||||
|
@@ -1599,13 +1599,13 @@ ruv_dump(const RUV *ruv, char *ruv_name, PRFileDesc *prFile)
|
||||||
|
|
||||||
|
/* this function notifies the ruv that there are operations in progress so that
|
||||||
|
they can be added to the pending list for the appropriate client. */
|
||||||
|
-int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
|
||||||
|
+int ruv_add_csn_inprogress (void *repl, RUV *ruv, const CSN *csn)
|
||||||
|
{
|
||||||
|
RUVElement* replica;
|
||||||
|
char csn_str[CSN_STRSIZE];
|
||||||
|
int rc = RUV_SUCCESS;
|
||||||
|
int rid = csn_get_replicaid (csn);
|
||||||
|
- CSN *prim_csn;
|
||||||
|
+ CSNPL_CTX *prim_csn;
|
||||||
|
|
||||||
|
PR_ASSERT (ruv && csn);
|
||||||
|
|
||||||
|
@@ -1645,8 +1645,13 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
|
||||||
|
}
|
||||||
|
prim_csn = get_thread_primary_csn();
|
||||||
|
if (prim_csn == NULL) {
|
||||||
|
- set_thread_primary_csn(csn);
|
||||||
|
+ set_thread_primary_csn(csn, (Replica *)repl);
|
||||||
|
prim_csn = get_thread_primary_csn();
|
||||||
|
+ } else {
|
||||||
|
+ /* the prim csn data already exist, need to check if
|
||||||
|
+ * current replica is already present
|
||||||
|
+ */
|
||||||
|
+ add_replica_to_primcsn(prim_csn, (Replica *)repl);
|
||||||
|
}
|
||||||
|
rc = csnplInsert (replica->csnpl, csn, prim_csn);
|
||||||
|
if (rc == 1) /* we already seen this csn */
|
||||||
|
@@ -1656,7 +1661,7 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
|
||||||
|
"The csn %s has already be seen - ignoring\n",
|
||||||
|
csn_as_string (csn, PR_FALSE, csn_str));
|
||||||
|
}
|
||||||
|
- set_thread_primary_csn(NULL);
|
||||||
|
+ set_thread_primary_csn(NULL, NULL);
|
||||||
|
rc = RUV_COVERS_CSN;
|
||||||
|
}
|
||||||
|
else if(rc != 0)
|
||||||
|
@@ -1681,11 +1686,13 @@ done:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
|
||||||
|
+int ruv_cancel_csn_inprogress (void *repl, RUV *ruv, const CSN *csn, ReplicaId local_rid)
|
||||||
|
{
|
||||||
|
- RUVElement* replica;
|
||||||
|
+ RUVElement* repl_ruv;
|
||||||
|
int rc = RUV_SUCCESS;
|
||||||
|
- CSN *prim_csn = NULL;
|
||||||
|
+ CSNPL_CTX *prim_csn = NULL;
|
||||||
|
+ Replica *repl_it;
|
||||||
|
+ size_t it;
|
||||||
|
|
||||||
|
|
||||||
|
PR_ASSERT (ruv && csn);
|
||||||
|
@@ -1693,29 +1700,53 @@ int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
|
||||||
|
prim_csn = get_thread_primary_csn();
|
||||||
|
/* locate ruvElement */
|
||||||
|
slapi_rwlock_wrlock (ruv->lock);
|
||||||
|
- replica = ruvGetReplica (ruv, csn_get_replicaid (csn));
|
||||||
|
- if (replica == NULL) {
|
||||||
|
+ repl_ruv = ruvGetReplica (ruv, csn_get_replicaid (csn));
|
||||||
|
+ if (repl_ruv == NULL) {
|
||||||
|
/* ONREPL - log error */
|
||||||
|
rc = RUV_NOTFOUND;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
- if (csn_is_equal(csn, prim_csn)) {
|
||||||
|
- /* the prim csn is cancelled, lets remove all dependent csns */
|
||||||
|
- ReplicaId prim_rid = csn_get_replicaid (csn);
|
||||||
|
- replica = ruvGetReplica (ruv, prim_rid);
|
||||||
|
- rc = csnplRemoveAll (replica->csnpl, prim_csn);
|
||||||
|
- if (prim_rid != local_rid) {
|
||||||
|
- if( local_rid != READ_ONLY_REPLICA_ID) {
|
||||||
|
- replica = ruvGetReplica (ruv, local_rid);
|
||||||
|
- if (replica) {
|
||||||
|
- rc = csnplRemoveAll (replica->csnpl, prim_csn);
|
||||||
|
- } else {
|
||||||
|
- rc = RUV_NOTFOUND;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ if (csn_primary(repl, csn, prim_csn)) {
|
||||||
|
+ /* the prim csn is cancelled, lets remove all dependent csns */
|
||||||
|
+ /* for the primary replica we can have modifications for two RIDS:
|
||||||
|
+ * - the local RID for direct or internal operations
|
||||||
|
+ * - a remote RID if the primary csn is for a replciated op.
|
||||||
|
+ */
|
||||||
|
+ ReplicaId prim_rid = csn_get_replicaid(csn);
|
||||||
|
+ repl_ruv = ruvGetReplica(ruv, prim_rid);
|
||||||
|
+ if (!repl_ruv) {
|
||||||
|
+ rc = RUV_NOTFOUND;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+ rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
|
||||||
|
+
|
||||||
|
+ if (prim_rid != local_rid && local_rid != READ_ONLY_REPLICA_ID) {
|
||||||
|
+ repl_ruv = ruvGetReplica(ruv, local_rid);
|
||||||
|
+ if (!repl_ruv) {
|
||||||
|
+ rc = RUV_NOTFOUND;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
+ rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (it = 0; it < prim_csn->repl_cnt; it++) {
|
||||||
|
+ repl_it = prim_csn->sec_repl[it];
|
||||||
|
+ replica_lock_replica(repl_it);
|
||||||
|
+ local_rid = replica_get_rid(repl_it);
|
||||||
|
+ if (local_rid != READ_ONLY_REPLICA_ID) {
|
||||||
|
+ Object *ruv_obj = replica_get_ruv(repl_it);
|
||||||
|
+ RUV *ruv_it = object_get_data(ruv_obj);
|
||||||
|
+ repl_ruv = ruvGetReplica(ruv_it, local_rid);
|
||||||
|
+ if (repl_ruv) {
|
||||||
|
+ rc = csnplRemoveAll(repl_ruv->csnpl, prim_csn);
|
||||||
|
+ } else {
|
||||||
|
+ rc = RUV_NOTFOUND;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ replica_unlock_replica(repl_it);
|
||||||
|
+ }
|
||||||
|
} else {
|
||||||
|
- rc = csnplRemove (replica->csnpl, csn);
|
||||||
|
+ rc = csnplRemove (repl_ruv->csnpl, csn);
|
||||||
|
}
|
||||||
|
if (rc != 0)
|
||||||
|
rc = RUV_NOTFOUND;
|
||||||
|
@@ -1727,86 +1758,100 @@ done:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, ReplicaId local_rid)
|
||||||
|
+int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, void *replica, ReplicaId local_rid)
|
||||||
|
{
|
||||||
|
int rc=RUV_SUCCESS;
|
||||||
|
- RUVElement *replica;
|
||||||
|
+ RUVElement *repl_ruv;
|
||||||
|
ReplicaId prim_rid;
|
||||||
|
+ Replica *repl_it = NULL;
|
||||||
|
+ size_t it = 0;
|
||||||
|
|
||||||
|
- CSN *prim_csn = get_thread_primary_csn();
|
||||||
|
+ CSNPL_CTX *prim_csn = get_thread_primary_csn();
|
||||||
|
|
||||||
|
- if (! csn_is_equal(csn, prim_csn)) {
|
||||||
|
+ if (! csn_primary(replica, csn, prim_csn)) {
|
||||||
|
/* not a primary csn, nothing to do */
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
- slapi_rwlock_wrlock (ruv->lock);
|
||||||
|
+
|
||||||
|
+ /* first handle primary replica
|
||||||
|
+ * there can be two ruv elements affected
|
||||||
|
+ */
|
||||||
|
prim_rid = csn_get_replicaid (csn);
|
||||||
|
- replica = ruvGetReplica (ruv, local_rid);
|
||||||
|
- rc = ruv_update_ruv_element(ruv, replica, csn, replica_purl, PR_TRUE);
|
||||||
|
- if ( rc || local_rid == prim_rid) goto done;
|
||||||
|
- replica = ruvGetReplica (ruv, prim_rid);
|
||||||
|
- rc = ruv_update_ruv_element(ruv, replica, csn, replica_purl, PR_FALSE);
|
||||||
|
-done:
|
||||||
|
+ slapi_rwlock_wrlock (ruv->lock);
|
||||||
|
+ if ( local_rid != prim_rid) {
|
||||||
|
+ repl_ruv = ruvGetReplica (ruv, prim_rid);
|
||||||
|
+ rc = ruv_update_ruv_element(ruv, repl_ruv, prim_csn, replica_purl, PR_FALSE);
|
||||||
|
+ }
|
||||||
|
+ repl_ruv = ruvGetReplica (ruv, local_rid);
|
||||||
|
+ rc = ruv_update_ruv_element(ruv, repl_ruv, prim_csn, replica_purl, PR_TRUE);
|
||||||
|
slapi_rwlock_unlock (ruv->lock);
|
||||||
|
+ if (rc) return rc;
|
||||||
|
+
|
||||||
|
+ /* now handle secondary replicas */
|
||||||
|
+ for (it=0; it<prim_csn->repl_cnt; it++) {
|
||||||
|
+ repl_it = prim_csn->sec_repl[it];
|
||||||
|
+ replica_lock_replica(repl_it);
|
||||||
|
+ Object *ruv_obj = replica_get_ruv (repl_it);
|
||||||
|
+ RUV *ruv_it = object_get_data (ruv_obj);
|
||||||
|
+ slapi_rwlock_wrlock (ruv_it->lock);
|
||||||
|
+ repl_ruv = ruvGetReplica (ruv_it, replica_get_rid(repl_it));
|
||||||
|
+ rc = ruv_update_ruv_element(ruv_it, repl_ruv, prim_csn, replica_purl, PR_TRUE);
|
||||||
|
+ slapi_rwlock_unlock (ruv_it->lock);
|
||||||
|
+ replica_unlock_replica(repl_it);
|
||||||
|
+ if (rc) break;
|
||||||
|
+ }
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
-ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSN *csn, const char *replica_purl, PRBool isLocal)
|
||||||
|
+ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSNPL_CTX *prim_csn, const char *replica_purl, PRBool isLocal)
|
||||||
|
{
|
||||||
|
int rc=RUV_SUCCESS;
|
||||||
|
char csn_str[CSN_STRSIZE];
|
||||||
|
CSN *max_csn;
|
||||||
|
CSN *first_csn = NULL;
|
||||||
|
|
||||||
|
- if (replica == NULL)
|
||||||
|
- {
|
||||||
|
+ if (replica == NULL) {
|
||||||
|
/* we should have a ruv element at this point because it would have
|
||||||
|
been added by ruv_add_inprogress function */
|
||||||
|
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - "
|
||||||
|
- "Can't locate RUV element for replica %d\n", csn_get_replicaid (csn));
|
||||||
|
+ "Can't locate RUV element for replica %d\n", csn_get_replicaid (prim_csn->prim_csn));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (csnplCommitAll(replica->csnpl, csn) != 0)
|
||||||
|
- {
|
||||||
|
- slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "ruv_update_ruv - Cannot commit csn %s\n",
|
||||||
|
- csn_as_string(csn, PR_FALSE, csn_str));
|
||||||
|
+ if (csnplCommitAll(replica->csnpl, prim_csn) != 0) {
|
||||||
|
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "ruv_update_ruv - Cannot commit csn %s\n",
|
||||||
|
+ csn_as_string(prim_csn->prim_csn, PR_FALSE, csn_str));
|
||||||
|
rc = RUV_CSNPL_ERROR;
|
||||||
|
goto done;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
+ } else {
|
||||||
|
if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
|
||||||
|
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - "
|
||||||
|
- "Successfully committed csn %s\n", csn_as_string(csn, PR_FALSE, csn_str));
|
||||||
|
+ "Successfully committed csn %s\n", csn_as_string(prim_csn->prim_csn, PR_FALSE, csn_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((max_csn = csnplRollUp(replica->csnpl, &first_csn)) != NULL)
|
||||||
|
- {
|
||||||
|
-#ifdef DEBUG
|
||||||
|
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - Rolled up to csn %s\n",
|
||||||
|
- csn_as_string(max_csn, PR_FALSE, csn_str)); /* XXXggood remove debugging */
|
||||||
|
-#endif
|
||||||
|
+ if ((max_csn = csnplRollUp(replica->csnpl, &first_csn)) != NULL) {
|
||||||
|
+ slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "ruv_update_ruv - Rolled up to csn %s\n",
|
||||||
|
+ csn_as_string(max_csn, PR_FALSE, csn_str)); /* XXXggood remove debugging */
|
||||||
|
/* replica object sets min csn for local replica */
|
||||||
|
- if (!isLocal && replica->min_csn == NULL) {
|
||||||
|
- /* bug 559223 - it seems that, under huge stress, a server might pass
|
||||||
|
- * through this code when more than 1 change has already been sent and commited into
|
||||||
|
- * the pending lists... Therefore, as we are trying to set the min_csn ever
|
||||||
|
- * generated by this replica, we need to set the first_csn as the min csn in the
|
||||||
|
- * ruv */
|
||||||
|
- set_min_csn_nolock(ruv, first_csn, replica_purl);
|
||||||
|
- }
|
||||||
|
- /* only update the max_csn in the RUV if it is greater than the existing one */
|
||||||
|
- rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
|
||||||
|
- /* It is possible that first_csn points to max_csn.
|
||||||
|
- We need to free it once */
|
||||||
|
- if (max_csn != first_csn) {
|
||||||
|
- csn_free(&first_csn);
|
||||||
|
- }
|
||||||
|
- csn_free(&max_csn);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
+ if (!isLocal && replica->min_csn == NULL) {
|
||||||
|
+ /* bug 559223 - it seems that, under huge stress, a server might pass
|
||||||
|
+ * through this code when more than 1 change has already been sent and commited into
|
||||||
|
+ * the pending lists... Therefore, as we are trying to set the min_csn ever
|
||||||
|
+ * generated by this replica, we need to set the first_csn as the min csn in the
|
||||||
|
+ * ruv */
|
||||||
|
+ set_min_csn_nolock(ruv, first_csn, replica_purl);
|
||||||
|
+ }
|
||||||
|
+ /* only update the max_csn in the RUV if it is greater than the existing one */
|
||||||
|
+ rc = set_max_csn_nolock_ext(ruv, max_csn, replica_purl, PR_TRUE /* must be greater */);
|
||||||
|
+ /* It is possible that first_csn points to max_csn.
|
||||||
|
+ We need to free it once */
|
||||||
|
+ if (max_csn != first_csn) {
|
||||||
|
+ csn_free(&first_csn);
|
||||||
|
+ }
|
||||||
|
+ csn_free(&max_csn);
|
||||||
|
+ }
|
||||||
|
done:
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
|
||||||
|
index c8960fd..f3cd38b 100644
|
||||||
|
--- a/ldap/servers/plugins/replication/repl5_ruv.h
|
||||||
|
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
|
||||||
|
@@ -108,9 +108,9 @@ int ruv_to_bervals(const RUV *ruv, struct berval ***bvals);
|
||||||
|
PRInt32 ruv_replica_count (const RUV *ruv);
|
||||||
|
char **ruv_get_referrals(const RUV *ruv);
|
||||||
|
void ruv_dump(const RUV *ruv, char *ruv_name, PRFileDesc *prFile);
|
||||||
|
-int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn);
|
||||||
|
-int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId rid);
|
||||||
|
-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, ReplicaId local_rid);
|
||||||
|
+int ruv_add_csn_inprogress (void *repl, RUV *ruv, const CSN *csn);
|
||||||
|
+int ruv_cancel_csn_inprogress (void *repl, RUV *ruv, const CSN *csn, ReplicaId rid);
|
||||||
|
+int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, void *replica, ReplicaId local_rid);
|
||||||
|
int ruv_move_local_supplier_to_first(RUV *ruv, ReplicaId rid);
|
||||||
|
int ruv_get_first_id_and_purl(RUV *ruv, ReplicaId *rid, char **replica_purl );
|
||||||
|
int ruv_local_contains_supplier(RUV *ruv, ReplicaId rid);
|
||||||
|
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
|
||||||
|
index 0836d66..3910dbe 100644
|
||||||
|
--- a/ldap/servers/slapd/slapi-private.h
|
||||||
|
+++ b/ldap/servers/slapd/slapi-private.h
|
||||||
|
@@ -193,7 +193,7 @@ const CSN *csn_max(const CSN *csn1,const CSN *csn2);
|
||||||
|
a csn from the set.*/
|
||||||
|
int csn_increment_subsequence (CSN *csn);
|
||||||
|
|
||||||
|
-void csnplFreeCSN (void *arg);
|
||||||
|
+void csnplFreeCSNPL_CTX (void *arg);
|
||||||
|
/*
|
||||||
|
* csnset.c
|
||||||
|
*/
|
||||||
|
--
|
||||||
|
2.9.4
|
||||||
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
From 95b39e29361812a62f2e038c89a88d717c82794e Mon Sep 17 00:00:00 2001
|
||||||
|
From: William Brown <firstyear@redhat.com>
|
||||||
|
Date: Mon, 31 Jul 2017 14:13:49 +1000
|
||||||
|
Subject: [PATCH] Ticket 49336 - SECURITY: Locked account provides different
|
||||||
|
return code
|
||||||
|
|
||||||
|
Bug Description: The directory server password lockout policy prevents binds
|
||||||
|
from operating once a threshold of failed passwords has been met. During
|
||||||
|
this lockout, if you bind with a successful password, a different error code
|
||||||
|
is returned. This means that an attacker has no ratelimit or penalty during
|
||||||
|
an account lock, and can continue to attempt passwords via bruteforce, using
|
||||||
|
the change in return code to ascertain a sucessful password auth.
|
||||||
|
|
||||||
|
Fix Description: Move the account lock check *before* the password bind
|
||||||
|
check. If the account is locked, we do not mind disclosing this as the
|
||||||
|
attacker will either ignore it (and will not bind anyway), or they will
|
||||||
|
be forced to back off as the attack is not working preventing the
|
||||||
|
bruteforce.
|
||||||
|
|
||||||
|
https://pagure.io/389-ds-base/issue/49336
|
||||||
|
|
||||||
|
Author: wibrown
|
||||||
|
|
||||||
|
Review by: tbordaz (Thanks!)
|
||||||
|
|
||||||
|
Signed-off-by: Mark Reynolds <mreynolds@redhat.com>
|
||||||
|
---
|
||||||
|
.../suites/password/pwd_lockout_bypass_test.py | 55 ++++++++++++++++++++++
|
||||||
|
ldap/servers/slapd/bind.c | 29 ++++++++----
|
||||||
|
ldap/servers/slapd/pw_verify.c | 15 +++---
|
||||||
|
3 files changed, 84 insertions(+), 15 deletions(-)
|
||||||
|
create mode 100644 dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e4add72
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
|
||||||
|
@@ -0,0 +1,55 @@
|
||||||
|
+# --- BEGIN COPYRIGHT BLOCK ---
|
||||||
|
+# Copyright (C) 2017 Red Hat, Inc.
|
||||||
|
+# All rights reserved.
|
||||||
|
+#
|
||||||
|
+# License: GPL (version 3 or any later version).
|
||||||
|
+# See LICENSE for details.
|
||||||
|
+# --- END COPYRIGHT BLOCK ---
|
||||||
|
+#
|
||||||
|
+import pytest
|
||||||
|
+from lib389.tasks import *
|
||||||
|
+from lib389.utils import *
|
||||||
|
+from lib389.topologies import topology_st
|
||||||
|
+from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
|
||||||
|
+import ldap
|
||||||
|
+
|
||||||
|
+# The irony of these names is not lost on me.
|
||||||
|
+GOOD_PASSWORD = 'password'
|
||||||
|
+BAD_PASSWORD = 'aontseunao'
|
||||||
|
+
|
||||||
|
+logging.getLogger(__name__).setLevel(logging.INFO)
|
||||||
|
+log = logging.getLogger(__name__)
|
||||||
|
+
|
||||||
|
+def test_lockout_bypass(topology_st):
|
||||||
|
+ inst = topology_st.standalone
|
||||||
|
+
|
||||||
|
+ # Configure the lock policy
|
||||||
|
+ inst.config.set('passwordMaxFailure', '1')
|
||||||
|
+ inst.config.set('passwordLockoutDuration', '99999')
|
||||||
|
+ inst.config.set('passwordLockout', 'on')
|
||||||
|
+
|
||||||
|
+ # Create the account
|
||||||
|
+ users = UserAccounts(inst, DEFAULT_SUFFIX)
|
||||||
|
+ testuser = users.create(properties=TEST_USER_PROPERTIES)
|
||||||
|
+ testuser.set('userPassword', GOOD_PASSWORD)
|
||||||
|
+
|
||||||
|
+ conn = testuser.bind(GOOD_PASSWORD)
|
||||||
|
+ assert conn != None
|
||||||
|
+ conn.unbind_s()
|
||||||
|
+
|
||||||
|
+ # Bind with bad creds twice
|
||||||
|
+ # This is the failure.
|
||||||
|
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
||||||
|
+ conn = testuser.bind(BAD_PASSWORD)
|
||||||
|
+ # Now we should not be able to ATTEMPT the bind. It doesn't matter that
|
||||||
|
+ # we disclose that we have hit the rate limit here, what matters is that
|
||||||
|
+ # it exists.
|
||||||
|
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
|
||||||
|
+ conn = testuser.bind(BAD_PASSWORD)
|
||||||
|
+
|
||||||
|
+ # now bind with good creds
|
||||||
|
+ # Should be error 19 still.
|
||||||
|
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
|
||||||
|
+ conn = testuser.bind(GOOD_PASSWORD)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
|
||||||
|
index 7f4414f..064ace1 100644
|
||||||
|
--- a/ldap/servers/slapd/bind.c
|
||||||
|
+++ b/ldap/servers/slapd/bind.c
|
||||||
|
@@ -662,12 +662,14 @@ do_bind( Slapi_PBlock *pb )
|
||||||
|
/* We could be serving multiple database backends. Select the appropriate one */
|
||||||
|
/* pw_verify_be_dn will select the backend we need for us. */
|
||||||
|
|
||||||
|
- if (auto_bind) {
|
||||||
|
- /* We have no password material. We should just check who we are binding as. */
|
||||||
|
- rc = pw_validate_be_dn(pb, &referral);
|
||||||
|
- } else {
|
||||||
|
- rc = pw_verify_be_dn(pb, &referral);
|
||||||
|
- }
|
||||||
|
+ /*
|
||||||
|
+ * WARNING: We have to validate *all* other conditions *first* before
|
||||||
|
+ * we attempt the bind!
|
||||||
|
+ *
|
||||||
|
+ * this is because ldbm_bind.c will SEND THE FAILURE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ rc = pw_validate_be_dn(pb, &referral);
|
||||||
|
|
||||||
|
if (rc == SLAPI_BIND_NO_BACKEND) {
|
||||||
|
send_nobackend_ldap_result( pb );
|
||||||
|
@@ -736,8 +738,18 @@ do_bind( Slapi_PBlock *pb )
|
||||||
|
myrc = 0;
|
||||||
|
}
|
||||||
|
if (!auto_bind) {
|
||||||
|
- /*
|
||||||
|
- * There could be a race that bind_target_entry was not added
|
||||||
|
+ /*
|
||||||
|
+ * Okay, we've made it here. FINALLY check if the entry really
|
||||||
|
+ * can bind or not. THIS IS THE PASSWORD CHECK.
|
||||||
|
+ */
|
||||||
|
+ rc = pw_verify_be_dn(pb, &referral);
|
||||||
|
+ if (rc != SLAPI_BIND_SUCCESS) {
|
||||||
|
+ /* Invalid pass - lets bail ... */
|
||||||
|
+ goto bind_failed;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * There could be a race that bind_target_entry was not added
|
||||||
|
* when bind_target_entry was retrieved before be_bind, but it
|
||||||
|
* was in be_bind. Since be_bind returned SLAPI_BIND_SUCCESS,
|
||||||
|
* the entry is in the DS. So, we need to retrieve it once more.
|
||||||
|
@@ -786,6 +798,7 @@ do_bind( Slapi_PBlock *pb )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { /* if auto_bind || rc == slapi_bind_success | slapi_bind_anonymous */
|
||||||
|
+ bind_failed:
|
||||||
|
if (rc == LDAP_OPERATIONS_ERROR) {
|
||||||
|
send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL );
|
||||||
|
goto free_and_return;
|
||||||
|
diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
|
||||||
|
index 852b027..cb182ed 100644
|
||||||
|
--- a/ldap/servers/slapd/pw_verify.c
|
||||||
|
+++ b/ldap/servers/slapd/pw_verify.c
|
||||||
|
@@ -55,7 +55,7 @@ pw_verify_root_dn(const char *dn, const Slapi_Value *cred)
|
||||||
|
int
|
||||||
|
pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
|
||||||
|
{
|
||||||
|
- int rc = 0;
|
||||||
|
+ int rc = SLAPI_BIND_SUCCESS;
|
||||||
|
Slapi_Backend *be = NULL;
|
||||||
|
|
||||||
|
if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
|
||||||
|
@@ -109,14 +109,10 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
|
||||||
|
slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, &cred);
|
||||||
|
slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
|
||||||
|
|
||||||
|
- if (pb_sdn != NULL || cred != NULL) {
|
||||||
|
+ if (pb_sdn == NULL) {
|
||||||
|
return LDAP_OPERATIONS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (*referral) {
|
||||||
|
- return SLAPI_BIND_REFERRAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
/* We need a slapi_sdn_isanon? */
|
||||||
|
if (method == LDAP_AUTH_SIMPLE && cred->bv_len == 0) {
|
||||||
|
return SLAPI_BIND_ANONYMOUS;
|
||||||
|
@@ -130,7 +126,11 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
|
||||||
|
if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
|
||||||
|
return SLAPI_BIND_NO_BACKEND;
|
||||||
|
}
|
||||||
|
- slapi_be_Unlock(be);
|
||||||
|
+
|
||||||
|
+ if (*referral) {
|
||||||
|
+ slapi_be_Unlock(be);
|
||||||
|
+ return SLAPI_BIND_REFERRAL;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
slapi_pblock_set(pb, SLAPI_BACKEND, be);
|
||||||
|
slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
|
||||||
|
@@ -138,6 +138,7 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
|
||||||
|
set_db_default_result_handlers(pb);
|
||||||
|
|
||||||
|
/* The backend associated with this identity is real. */
|
||||||
|
+ slapi_be_Unlock(be);
|
||||||
|
|
||||||
|
return SLAPI_BIND_SUCCESS;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.9.4
|
||||||
|
|
177
SOURCES/0059-Ticket-49298-force-sync-on-shutdown.patch
Normal file
177
SOURCES/0059-Ticket-49298-force-sync-on-shutdown.patch
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
From ba30cc562f5ebd58955502a19edbf9720a45b655 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mark Reynolds <mreynolds@redhat.com>
|
||||||
|
Date: Tue, 8 Aug 2017 13:02:53 -0400
|
||||||
|
Subject: [PATCH] Ticket 49298 - force sync() on shutdown
|
||||||
|
|
||||||
|
Bug Description: During shutdown on xfs we would occasionally
|
||||||
|
see a broke dse.ldif (specifically, empty). This happens due to
|
||||||
|
a bug in xfs where the directory isn't synced on rename().
|
||||||
|
|
||||||
|
Fix Description: As we shutdown call sync() to force all our
|
||||||
|
writes to disk - dse.ldif, logs, db, all of it.
|
||||||
|
|
||||||
|
https://pagure.io/389-ds-base/issue/49298
|
||||||
|
---
|
||||||
|
ldap/servers/slapd/dse.c | 59 +++++++++++++++++++++++++++++------------------
|
||||||
|
ldap/servers/slapd/main.c | 9 ++++----
|
||||||
|
2 files changed, 42 insertions(+), 26 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/dse.c b/ldap/servers/slapd/dse.c
|
||||||
|
index 5715c83..fa1aacc 100644
|
||||||
|
--- a/ldap/servers/slapd/dse.c
|
||||||
|
+++ b/ldap/servers/slapd/dse.c
|
||||||
|
@@ -40,6 +40,8 @@
|
||||||
|
#include "slap.h"
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
|
+#include <unistd.h> /* provides fsync/close */
|
||||||
|
+
|
||||||
|
/* #define SLAPI_DSE_DEBUG */ /* define this to force trace log */
|
||||||
|
/* messages to always be logged */
|
||||||
|
|
||||||
|
@@ -72,11 +74,11 @@
|
||||||
|
struct dse_callback
|
||||||
|
{
|
||||||
|
int operation;
|
||||||
|
- int flags;
|
||||||
|
- Slapi_DN *base;
|
||||||
|
- int scope;
|
||||||
|
- char *filter; /* NULL means match all entries */
|
||||||
|
- Slapi_Filter *slapifilter; /* NULL means match all entries */
|
||||||
|
+ int flags;
|
||||||
|
+ Slapi_DN *base;
|
||||||
|
+ int scope;
|
||||||
|
+ char *filter; /* NULL means match all entries */
|
||||||
|
+ Slapi_Filter *slapifilter; /* NULL means match all entries */
|
||||||
|
int (*fn)(Slapi_PBlock *,Slapi_Entry *,Slapi_Entry *,int*,char*,void *);
|
||||||
|
void *fn_arg;
|
||||||
|
struct slapdplugin *plugin;
|
||||||
|
@@ -89,13 +91,14 @@ struct dse
|
||||||
|
char *dse_tmpfile; /* and written to when changes are made via LDAP */
|
||||||
|
char *dse_fileback; /* contain the latest info, just before a new change */
|
||||||
|
char *dse_filestartOK; /* contain the latest info with which the server has successfully started */
|
||||||
|
+ char *dse_configdir; /* The location of config files - allows us to fsync the dir post rename */
|
||||||
|
Avlnode *dse_tree;
|
||||||
|
struct dse_callback *dse_callback;
|
||||||
|
Slapi_RWLock *dse_rwlock; /* a read-write lock to protect the whole dse backend */
|
||||||
|
- char **dse_filelist; /* these are additional read only files used to */
|
||||||
|
- /* initialize the dse */
|
||||||
|
- int dse_is_updateable; /* if non-zero, this DSE can be written to */
|
||||||
|
- int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
|
||||||
|
+ char **dse_filelist; /* these are additional read only files used to */
|
||||||
|
+ /* initialize the dse */
|
||||||
|
+ int dse_is_updateable; /* if non-zero, this DSE can be written to */
|
||||||
|
+ int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dse_node
|
||||||
|
@@ -361,37 +364,39 @@ dse_new( char *filename, char *tmpfilename, char *backfilename, char *startokfil
|
||||||
|
if (!strstr(filename, realconfigdir))
|
||||||
|
{
|
||||||
|
pdse->dse_filename = slapi_ch_smprintf("%s/%s", realconfigdir, filename );
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ } else {
|
||||||
|
pdse->dse_filename = slapi_ch_strdup(filename);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (!strstr(tmpfilename, realconfigdir)) {
|
||||||
|
pdse->dse_tmpfile = slapi_ch_smprintf("%s/%s", realconfigdir, tmpfilename );
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ } else {
|
||||||
|
pdse->dse_tmpfile = slapi_ch_strdup(tmpfilename);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pdse->dse_configdir = slapi_ch_strdup(realconfigdir);
|
||||||
|
|
||||||
|
if ( backfilename != NULL )
|
||||||
|
{
|
||||||
|
if (!strstr(backfilename, realconfigdir)) {
|
||||||
|
pdse->dse_fileback = slapi_ch_smprintf("%s/%s", realconfigdir, backfilename );
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ } else {
|
||||||
|
pdse->dse_fileback = slapi_ch_strdup(backfilename);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
pdse->dse_fileback = NULL;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if ( startokfilename != NULL )
|
||||||
|
{
|
||||||
|
if (!strstr(startokfilename, realconfigdir)) {
|
||||||
|
pdse->dse_filestartOK = slapi_ch_smprintf("%s/%s", realconfigdir, startokfilename );
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ } else {
|
||||||
|
pdse->dse_filestartOK = slapi_ch_strdup(startokfilename);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
pdse->dse_filestartOK = NULL;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
pdse->dse_tree= NULL;
|
||||||
|
pdse->dse_callback= NULL;
|
||||||
|
@@ -440,6 +445,7 @@ dse_destroy(struct dse *pdse)
|
||||||
|
slapi_ch_free((void **)&(pdse->dse_tmpfile));
|
||||||
|
slapi_ch_free((void **)&(pdse->dse_fileback));
|
||||||
|
slapi_ch_free((void **)&(pdse->dse_filestartOK));
|
||||||
|
+ slapi_ch_free((void **)&(pdse->dse_configdir));
|
||||||
|
dse_callback_deletelist(&pdse->dse_callback);
|
||||||
|
charray_free(pdse->dse_filelist);
|
||||||
|
nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry);
|
||||||
|
@@ -991,8 +997,9 @@ dse_write_file_nolock(struct dse* pdse)
|
||||||
|
FPWrapper fpw;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
- if (dont_ever_write_dse_files)
|
||||||
|
+ if (dont_ever_write_dse_files) {
|
||||||
|
return rc;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
fpw.fpw_rc = 0;
|
||||||
|
fpw.fpw_prfd = NULL;
|
||||||
|
@@ -1042,6 +1049,14 @@ dse_write_file_nolock(struct dse* pdse)
|
||||||
|
pdse->dse_tmpfile, pdse->dse_filename,
|
||||||
|
rc, slapd_system_strerror( rc ));
|
||||||
|
}
|
||||||
|
+ /*
|
||||||
|
+ * We have now written to the tmp location, and renamed it
|
||||||
|
+ * we need to open and fsync the dir to make the rename stick.
|
||||||
|
+ */
|
||||||
|
+ int fp_configdir = open(pdse->dse_configdir, O_PATH | O_DIRECTORY);
|
||||||
|
+ fsync(fp_configdir);
|
||||||
|
+ close(fp_configdir);
|
||||||
|
+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fpw.fpw_prfd)
|
||||||
|
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
|
||||||
|
index ba1f5e8..3351464 100644
|
||||||
|
--- a/ldap/servers/slapd/main.c
|
||||||
|
+++ b/ldap/servers/slapd/main.c
|
||||||
|
@@ -1154,11 +1154,12 @@ cleanup:
|
||||||
|
ndn_cache_destroy();
|
||||||
|
NSS_Shutdown();
|
||||||
|
PR_Cleanup();
|
||||||
|
-#if defined( hpux )
|
||||||
|
- exit( return_value );
|
||||||
|
-#else
|
||||||
|
+ /*
|
||||||
|
+ * Server has stopped, lets force everything to disk: logs
|
||||||
|
+ * db, dse.ldif, all of it.
|
||||||
|
+ */
|
||||||
|
+ sync();
|
||||||
|
return return_value;
|
||||||
|
-#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
2.9.4
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
From c903f66194f04e97fc684f5a9654cedb27530931 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ludwig Krispenz <lkrispen@redhat.com>
|
||||||
|
Date: Mon, 31 Jul 2017 10:51:08 +0200
|
||||||
|
Subject: [PATCH 1/3] Ticket 49334 - fix backup restore if changelog exists
|
||||||
|
|
||||||
|
The corrcect flag to copy a directory in backup/restore must be passed for the changelog directory
|
||||||
|
|
||||||
|
Reviewed by: William, thanks
|
||||||
|
---
|
||||||
|
ldap/servers/slapd/back-ldbm/dblayer.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
|
||||||
|
index ff97aa4..3a97f2f 100644
|
||||||
|
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
|
||||||
|
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
|
||||||
|
@@ -6143,7 +6143,7 @@ dblayer_backup(struct ldbminfo *li, char *dest_dir, Slapi_Task *task)
|
||||||
|
return_value = dblayer_copy_directory(li, task, changelogdir,
|
||||||
|
changelog_destdir,
|
||||||
|
0 /* backup */,
|
||||||
|
- &cnt, 1, 0, 0);
|
||||||
|
+ &cnt, 0, 0, 1);
|
||||||
|
if (return_value) {
|
||||||
|
slapi_log_err(SLAPI_LOG_ERR,
|
||||||
|
"dblayer_backup", "Error in copying directory "
|
||||||
|
@@ -6823,7 +6823,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *
|
||||||
|
*cldirname = '\0';
|
||||||
|
return_value = dblayer_copy_directory(li, task, filename1,
|
||||||
|
changelogdir, 1 /* restore */,
|
||||||
|
- &cnt, 1, 0 ,0);
|
||||||
|
+ &cnt, 0, 0 ,1);
|
||||||
|
*cldirname = '/';
|
||||||
|
if (return_value) {
|
||||||
|
slapi_log_err(SLAPI_LOG_ERR,
|
||||||
|
--
|
||||||
|
2.9.4
|
||||||
|
|
|
@ -0,0 +1,502 @@
|
||||||
|
From b0954a5df7841330732a5ab532c528a68cf380cf Mon Sep 17 00:00:00 2001
|
||||||
|
From: William Brown <firstyear@redhat.com>
|
||||||
|
Date: Fri, 18 Aug 2017 13:00:46 +1000
|
||||||
|
Subject: [PATCH] Ticket 49356 - mapping tree crash can occur during tot init
|
||||||
|
|
||||||
|
Bug Description: Two faults were found in the handling of the mapping
|
||||||
|
tree of 389 directory server. The first fault was that the tree-free
|
||||||
|
check was not performed atomically and may cause an incorrect operations
|
||||||
|
error to be returned. The second was that during a total init the referral
|
||||||
|
would not lock the be, but the pw_verify code assumed a be was locked.
|
||||||
|
This caused a segfault.
|
||||||
|
|
||||||
|
Fix Description: Fix the freed check to use atomics. Fix the pw_verify
|
||||||
|
to assert be is NULL (which is correct, there is no backend).
|
||||||
|
|
||||||
|
https://pagure.io/389-ds-base/issue/49356
|
||||||
|
|
||||||
|
Author: wibrown
|
||||||
|
|
||||||
|
Review by: mreynolds (THanks!)
|
||||||
|
---
|
||||||
|
.../mapping_tree/referral_during_tot_init.py | 57 ++++++++
|
||||||
|
ldap/servers/slapd/fedse.c | 10 ++
|
||||||
|
ldap/servers/slapd/main.c | 10 --
|
||||||
|
ldap/servers/slapd/mapping_tree.c | 150 +++++++++++----------
|
||||||
|
ldap/servers/slapd/pw_verify.c | 8 +-
|
||||||
|
5 files changed, 150 insertions(+), 85 deletions(-)
|
||||||
|
create mode 100644 dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
|
||||||
|
|
||||||
|
diff --git a/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e5aee7d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/dirsrvtests/tests/suites/mapping_tree/referral_during_tot_init.py
|
||||||
|
@@ -0,0 +1,57 @@
|
||||||
|
+# --- BEGIN COPYRIGHT BLOCK ---
|
||||||
|
+# Copyright (C) 2017 Red Hat, Inc.
|
||||||
|
+# All rights reserved.
|
||||||
|
+#
|
||||||
|
+# License: GPL (version 3 or any later version).
|
||||||
|
+# See LICENSE for details.
|
||||||
|
+# --- END COPYRIGHT BLOCK ---
|
||||||
|
+#
|
||||||
|
+import ldap
|
||||||
|
+import pytest
|
||||||
|
+from lib389.topologies import topology_m2
|
||||||
|
+from lib389._constants import (DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2, TASK_WAIT)
|
||||||
|
+
|
||||||
|
+from lib389.idm.user import (TEST_USER_PROPERTIES, UserAccounts)
|
||||||
|
+
|
||||||
|
+def test_referral_during_tot(topology_m2):
|
||||||
|
+
|
||||||
|
+ master1 = topology_m2.ms["master1"]
|
||||||
|
+ master2 = topology_m2.ms["master2"]
|
||||||
|
+
|
||||||
|
+ # Create a bunch of entries on master1
|
||||||
|
+ ldif_dir = master1.get_ldif_dir()
|
||||||
|
+ import_ldif = ldif_dir + '/ref_during_tot_import.ldif'
|
||||||
|
+ master1.buildLDIF(10000, import_ldif)
|
||||||
|
+
|
||||||
|
+ master1.stop()
|
||||||
|
+ try:
|
||||||
|
+ master1.ldif2db(bename=None, excludeSuffixes=None, encrypt=False, suffixes=[DEFAULT_SUFFIX], import_file=import_ldif)
|
||||||
|
+ except:
|
||||||
|
+ pass
|
||||||
|
+ # master1.tasks.importLDIF(suffix=DEFAULT_SUFFIX, input_file=import_ldif, args={TASK_WAIT: True})
|
||||||
|
+ master1.start()
|
||||||
|
+ users = UserAccounts(master1, DEFAULT_SUFFIX, rdn='ou=Accounting')
|
||||||
|
+
|
||||||
|
+ u = users.create(properties=TEST_USER_PROPERTIES)
|
||||||
|
+ u.set('userPassword', 'password')
|
||||||
|
+
|
||||||
|
+ binddn = u.dn
|
||||||
|
+ bindpw = 'password'
|
||||||
|
+
|
||||||
|
+ # Now export them to master2
|
||||||
|
+ master1.agreement.init(DEFAULT_SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
|
||||||
|
+
|
||||||
|
+ # While that's happening try to bind as a user to master 2
|
||||||
|
+ # This should trigger the referral code.
|
||||||
|
+ for i in range(0, 100):
|
||||||
|
+ conn = ldap.initialize(master2.toLDAPURL())
|
||||||
|
+ conn.set_option(ldap.OPT_REFERRALS, False)
|
||||||
|
+ try:
|
||||||
|
+ conn.simple_bind_s(binddn, bindpw)
|
||||||
|
+ conn.unbind_s()
|
||||||
|
+ except ldap.REFERRAL:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+ # Done.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
diff --git a/ldap/servers/slapd/fedse.c b/ldap/servers/slapd/fedse.c
|
||||||
|
index 13a3c74..c2a862b 100644
|
||||||
|
--- a/ldap/servers/slapd/fedse.c
|
||||||
|
+++ b/ldap/servers/slapd/fedse.c
|
||||||
|
@@ -1853,6 +1853,16 @@ setup_internal_backends(char *configdir)
|
||||||
|
be_addsuffix(be,&monitor);
|
||||||
|
be_addsuffix(be,&config);
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Now that the be's are in place, we can
|
||||||
|
+ * setup the mapping tree.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ if (mapping_tree_init()) {
|
||||||
|
+ slapi_log_err(SLAPI_LOG_EMERG, "setup_internal_backends", "Failed to init mapping tree\n");
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
add_internal_entries();
|
||||||
|
|
||||||
|
add_easter_egg_entry();
|
||||||
|
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
|
||||||
|
index 552d54d..1d9afce 100644
|
||||||
|
--- a/ldap/servers/slapd/main.c
|
||||||
|
+++ b/ldap/servers/slapd/main.c
|
||||||
|
@@ -1034,16 +1034,6 @@ main( int argc, char **argv)
|
||||||
|
|
||||||
|
ps_init_psearch_system(); /* must come before plugin_startall() */
|
||||||
|
|
||||||
|
- /* Initailize the mapping tree */
|
||||||
|
-
|
||||||
|
- if (mapping_tree_init())
|
||||||
|
- {
|
||||||
|
- slapi_log_err(SLAPI_LOG_EMERG, "main", "Failed to init mapping tree\n");
|
||||||
|
- return_value = 1;
|
||||||
|
- goto cleanup;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* initialize UniqueID generator - must be done once backends are started
|
||||||
|
and event queue is initialized but before plugins are started */
|
||||||
|
/* Note: This DN is no need to be normalized. */
|
||||||
|
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
|
||||||
|
index 1b8d2d9..dfb6584 100644
|
||||||
|
--- a/ldap/servers/slapd/mapping_tree.c
|
||||||
|
+++ b/ldap/servers/slapd/mapping_tree.c
|
||||||
|
@@ -88,13 +88,13 @@ struct mt_node
|
||||||
|
* release backend lock
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
-static Slapi_RWLock *myLock; /* global lock on the mapping tree structures */
|
||||||
|
+static Slapi_RWLock *myLock = NULL; /* global lock on the mapping tree structures */
|
||||||
|
|
||||||
|
|
||||||
|
static mapping_tree_node *mapping_tree_root = NULL;
|
||||||
|
-static int mapping_tree_inited = 0;
|
||||||
|
-static int mapping_tree_freed = 0;
|
||||||
|
-static int extension_type = -1; /* type returned from the factory */
|
||||||
|
+static int32_t mapping_tree_inited = 0;
|
||||||
|
+static int32_t mapping_tree_freed = 0;
|
||||||
|
+static int extension_type = -1; /* type returned from the factory */
|
||||||
|
|
||||||
|
/* The different states a mapping tree node can be in. */
|
||||||
|
#define MTN_DISABLED 0 /* The server acts like the node isn't there. */
|
||||||
|
@@ -1659,22 +1659,24 @@ add_internal_mapping_tree_node(const char *subtree, Slapi_Backend *be, mapping_t
|
||||||
|
{
|
||||||
|
Slapi_DN *dn;
|
||||||
|
mapping_tree_node *node;
|
||||||
|
- backend ** be_list = (backend **) slapi_ch_malloc(sizeof(backend *));
|
||||||
|
+ backend **be_list = (backend **)slapi_ch_malloc(sizeof(backend *));
|
||||||
|
+ int *be_states = (int *)slapi_ch_malloc(sizeof(int));
|
||||||
|
|
||||||
|
be_list[0] = be;
|
||||||
|
+ be_states[0] = SLAPI_BE_STATE_ON;
|
||||||
|
|
||||||
|
dn = slapi_sdn_new_dn_byval(subtree);
|
||||||
|
- node= mapping_tree_node_new(
|
||||||
|
- dn,
|
||||||
|
- be_list,
|
||||||
|
- NULL, /* backend_name */
|
||||||
|
- NULL,
|
||||||
|
- 1, /* number of backends at this node */
|
||||||
|
- 1, /* size of backend list structure */
|
||||||
|
- NULL, /* referral */
|
||||||
|
- parent,
|
||||||
|
- MTN_BACKEND,
|
||||||
|
- 1, /* The config node is a private node.
|
||||||
|
+ node = mapping_tree_node_new(
|
||||||
|
+ dn,
|
||||||
|
+ be_list,
|
||||||
|
+ NULL, /* backend_name */
|
||||||
|
+ be_states, /* be state */
|
||||||
|
+ 1, /* number of backends at this node */
|
||||||
|
+ 1, /* size of backend list structure */
|
||||||
|
+ NULL, /* referral */
|
||||||
|
+ parent,
|
||||||
|
+ MTN_BACKEND,
|
||||||
|
+ 1, /* The config node is a private node.
|
||||||
|
* People can't see or change it. */
|
||||||
|
NULL, NULL, NULL, 0); /* no distribution */
|
||||||
|
return node;
|
||||||
|
@@ -1722,17 +1724,20 @@ mapping_tree_init()
|
||||||
|
|
||||||
|
/* we call this function from a single thread, so it should be ok */
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
- /* shutdown has been detected */
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (mapping_tree_inited)
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
+ /* shutdown has been detected */
|
||||||
|
return 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- /* ONREPL - I have moved this up because otherwise we can endup calling this
|
||||||
|
+ /* ONREPL - I have moved this up because otherwise we can endup calling this
|
||||||
|
* function recursively */
|
||||||
|
+ if (myLock != NULL) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ myLock = slapi_new_rwlock();
|
||||||
|
+ slapi_rwlock_wrlock(myLock);
|
||||||
|
|
||||||
|
+ /* Should be fenced by the rwlock. */
|
||||||
|
mapping_tree_inited = 1;
|
||||||
|
|
||||||
|
slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_OID,
|
||||||
|
@@ -1740,10 +1745,8 @@ mapping_tree_init()
|
||||||
|
slapi_register_supported_control(MTN_CONTROL_USE_ONE_BACKEND_EXT_OID,
|
||||||
|
SLAPI_OPERATION_SEARCH);
|
||||||
|
|
||||||
|
- myLock = slapi_new_rwlock();
|
||||||
|
-
|
||||||
|
- be= slapi_be_select_by_instance_name(DSE_BACKEND);
|
||||||
|
- mapping_tree_root= add_internal_mapping_tree_node("", be, NULL);
|
||||||
|
+ be = slapi_be_select_by_instance_name(DSE_BACKEND);
|
||||||
|
+ mapping_tree_root = add_internal_mapping_tree_node("", be, NULL);
|
||||||
|
|
||||||
|
/* We also need to add the config and schema backends to the mapping tree.
|
||||||
|
* They are special in that users will not know about it's node in the
|
||||||
|
@@ -1757,17 +1760,23 @@ mapping_tree_init()
|
||||||
|
node= add_internal_mapping_tree_node("cn=schema", be, mapping_tree_root);
|
||||||
|
mapping_tree_node_add_child(mapping_tree_root, node);
|
||||||
|
|
||||||
|
- /*
|
||||||
|
+ slapi_rwlock_unlock(myLock);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
* Now we need to look under cn=mapping tree, cn=config to find the rest
|
||||||
|
* of the mapping tree entries.
|
||||||
|
* Builds the mapping tree from entries in the DIT. This function just
|
||||||
|
* calls mapping_tree_node_get_children with the special case for the
|
||||||
|
* root node.
|
||||||
|
*/
|
||||||
|
- if (mapping_tree_node_get_children(mapping_tree_root, 1))
|
||||||
|
+
|
||||||
|
+ if (mapping_tree_node_get_children(mapping_tree_root, 1)) {
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ slapi_rwlock_wrlock(myLock);
|
||||||
|
mtn_create_extension(mapping_tree_root);
|
||||||
|
+ slapi_rwlock_unlock(myLock);
|
||||||
|
|
||||||
|
/* setup the dse callback functions for the ldbm instance config entry */
|
||||||
|
{
|
||||||
|
@@ -1840,8 +1849,8 @@ mapping_tree_free ()
|
||||||
|
*/
|
||||||
|
slapi_unregister_backend_state_change_all();
|
||||||
|
/* recursively free tree nodes */
|
||||||
|
- mtn_free_node (&mapping_tree_root);
|
||||||
|
- mapping_tree_freed = 1;
|
||||||
|
+ mtn_free_node(&mapping_tree_root);
|
||||||
|
+ __atomic_store_4(&mapping_tree_freed, 1, __ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function returns the first node to parse when a search is done
|
||||||
|
@@ -2083,14 +2092,12 @@ int slapi_dn_write_needs_referral(Slapi_DN *target_sdn, Slapi_Entry **referral)
|
||||||
|
mapping_tree_node *target_node = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shutdown detected */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if(!mapping_tree_inited) {
|
||||||
|
- mapping_tree_init();
|
||||||
|
- }
|
||||||
|
+ PR_ASSERT(mapping_tree_inited == 1);
|
||||||
|
|
||||||
|
if (target_sdn) {
|
||||||
|
mtn_lock();
|
||||||
|
@@ -2157,8 +2164,8 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
|
||||||
|
int fixup = 0;
|
||||||
|
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
- /* shutdown detected */
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
+ /* shutdown detected */
|
||||||
|
return LDAP_OPERATIONS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2175,9 +2182,7 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
|
||||||
|
target_sdn = operation_get_target_spec (op);
|
||||||
|
fixup = operation_is_flag_set(op, OP_FLAG_TOMBSTONE_FIXUP);
|
||||||
|
|
||||||
|
- if(!mapping_tree_inited) {
|
||||||
|
- mapping_tree_init();
|
||||||
|
- }
|
||||||
|
+ PR_ASSERT(mapping_tree_inited == 1);
|
||||||
|
|
||||||
|
be[0] = NULL;
|
||||||
|
if (referral) {
|
||||||
|
@@ -2188,8 +2193,9 @@ int slapi_mapping_tree_select(Slapi_PBlock *pb, Slapi_Backend **be, Slapi_Entry
|
||||||
|
|
||||||
|
/* Get the mapping tree node that is the best match for the target dn. */
|
||||||
|
target_node = slapi_get_mapping_tree_node_by_dn(target_sdn);
|
||||||
|
- if (target_node == NULL)
|
||||||
|
+ if (target_node == NULL) {
|
||||||
|
target_node = mapping_tree_root;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* The processing of the base scope root DSE search and all other LDAP operations on ""
|
||||||
|
* will be transferred to the internal DSE backend
|
||||||
|
@@ -2266,8 +2272,8 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
|
||||||
|
Slapi_DN *sdn = NULL;
|
||||||
|
int flag_partial_result = 0;
|
||||||
|
int op_type;
|
||||||
|
-
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
return LDAP_OPERATIONS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2287,9 +2293,7 @@ int slapi_mapping_tree_select_all(Slapi_PBlock *pb, Slapi_Backend **be_list,
|
||||||
|
slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
|
||||||
|
slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
|
||||||
|
|
||||||
|
- if(!mapping_tree_inited){
|
||||||
|
- mapping_tree_init();
|
||||||
|
- }
|
||||||
|
+ PR_ASSERT(mapping_tree_inited == 1);
|
||||||
|
|
||||||
|
mtn_lock();
|
||||||
|
|
||||||
|
@@ -2448,8 +2452,8 @@ int slapi_mapping_tree_select_and_check(Slapi_PBlock *pb,char *newdn, Slapi_Back
|
||||||
|
Slapi_Operation *op;
|
||||||
|
int ret;
|
||||||
|
int need_unlock = 0;
|
||||||
|
-
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
return LDAP_OPERATIONS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2635,7 +2639,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
|
||||||
|
int flag_stop = 0;
|
||||||
|
struct slapi_componentid *cid = NULL;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shut down detected */
|
||||||
|
return LDAP_OPERATIONS_ERROR;
|
||||||
|
}
|
||||||
|
@@ -2719,21 +2723,22 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
|
||||||
|
} else {
|
||||||
|
/* This MTN has not been linked to its backend
|
||||||
|
* instance yet. */
|
||||||
|
- target_node->mtn_be[*index] =
|
||||||
|
- slapi_be_select_by_instance_name(
|
||||||
|
- target_node->mtn_backend_names[*index]);
|
||||||
|
- *be = target_node->mtn_be[*index];
|
||||||
|
- if(*be==NULL) {
|
||||||
|
- slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
|
||||||
|
- "Warning: Mapping tree node entry for %s "
|
||||||
|
- "point to an unknown backend : %s\n",
|
||||||
|
- slapi_sdn_get_dn(target_node->mtn_subtree),
|
||||||
|
- target_node->mtn_backend_names[*index]);
|
||||||
|
- /* Well there's still not backend instance for
|
||||||
|
- * this MTN, so let's have the default backend
|
||||||
|
- * deal with this.
|
||||||
|
- */
|
||||||
|
- *be = defbackend_get_backend();
|
||||||
|
+ /* WARNING: internal memory dse backends don't provide NAMES */
|
||||||
|
+ if (target_node->mtn_backend_names != NULL) {
|
||||||
|
+ target_node->mtn_be[*index] = slapi_be_select_by_instance_name(target_node->mtn_backend_names[*index]);
|
||||||
|
+ *be = target_node->mtn_be[*index];
|
||||||
|
+ if (*be == NULL) {
|
||||||
|
+ slapi_log_err(SLAPI_LOG_BACKLDBM, "mtn_get_be",
|
||||||
|
+ "Warning: Mapping tree node entry for %s "
|
||||||
|
+ "point to an unknown backend : %s\n",
|
||||||
|
+ slapi_sdn_get_dn(target_node->mtn_subtree),
|
||||||
|
+ target_node->mtn_backend_names[*index]);
|
||||||
|
+ /* Well there's still not backend instance for
|
||||||
|
+ * this MTN, so let's have the default backend
|
||||||
|
+ * deal with this.
|
||||||
|
+ */
|
||||||
|
+ *be = defbackend_get_backend();
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2745,10 +2750,11 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
|
||||||
|
result = LDAP_OPERATIONS_ERROR;
|
||||||
|
*be = defbackend_get_backend();
|
||||||
|
}
|
||||||
|
- if (flag_stop)
|
||||||
|
+ if (flag_stop) {
|
||||||
|
*index = SLAPI_BE_NO_BACKEND;
|
||||||
|
- else
|
||||||
|
+ } else {
|
||||||
|
(*index)++;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@@ -2822,7 +2828,7 @@ static mapping_tree_node *best_matching_child(mapping_tree_node *parent,
|
||||||
|
mapping_tree_node *highest_match_node = NULL;
|
||||||
|
mapping_tree_node *current;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shutdown detected */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@@ -2849,7 +2855,7 @@ mtn_get_mapping_tree_node_by_entry(mapping_tree_node* node, const Slapi_DN *dn)
|
||||||
|
{
|
||||||
|
mapping_tree_node *found_node = NULL;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shutdown detected */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@@ -2895,7 +2901,7 @@ slapi_get_mapping_tree_node_by_dn(const Slapi_DN *dn)
|
||||||
|
mapping_tree_node *current_best_match = mapping_tree_root;
|
||||||
|
mapping_tree_node *next_best_match = mapping_tree_root;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shutdown detected */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@@ -2929,7 +2935,7 @@ get_mapping_tree_node_by_name(mapping_tree_node * node, char * be_name)
|
||||||
|
int i;
|
||||||
|
mapping_tree_node *found_node = NULL;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shutdown detected */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@@ -2980,7 +2986,7 @@ slapi_get_mapping_tree_node_configdn (const Slapi_DN *root)
|
||||||
|
{
|
||||||
|
char *dn = NULL;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shutdown detected */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@@ -3007,7 +3013,7 @@ slapi_get_mapping_tree_node_configsdn (const Slapi_DN *root)
|
||||||
|
char *dn = NULL;
|
||||||
|
Slapi_DN *sdn = NULL;
|
||||||
|
|
||||||
|
- if(mapping_tree_freed){
|
||||||
|
+ if (__atomic_load_4(&mapping_tree_freed, __ATOMIC_RELAXED)) {
|
||||||
|
/* shutdown detected */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
diff --git a/ldap/servers/slapd/pw_verify.c b/ldap/servers/slapd/pw_verify.c
|
||||||
|
index cb182ed..1f0c18a 100644
|
||||||
|
--- a/ldap/servers/slapd/pw_verify.c
|
||||||
|
+++ b/ldap/servers/slapd/pw_verify.c
|
||||||
|
@@ -58,12 +58,14 @@ pw_verify_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
|
||||||
|
int rc = SLAPI_BIND_SUCCESS;
|
||||||
|
Slapi_Backend *be = NULL;
|
||||||
|
|
||||||
|
- if (slapi_mapping_tree_select(pb, &be, referral, NULL, 0) != LDAP_SUCCESS) {
|
||||||
|
+ int mt_result = slapi_mapping_tree_select(pb, &be, referral, NULL, 0);
|
||||||
|
+ if (mt_result != LDAP_SUCCESS) {
|
||||||
|
return SLAPI_BIND_NO_BACKEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*referral) {
|
||||||
|
- slapi_be_Unlock(be);
|
||||||
|
+ /* If we have a referral, this is NULL */
|
||||||
|
+ PR_ASSERT(be == NULL);
|
||||||
|
return SLAPI_BIND_REFERRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -128,7 +130,7 @@ pw_validate_be_dn(Slapi_PBlock *pb, Slapi_Entry **referral)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*referral) {
|
||||||
|
- slapi_be_Unlock(be);
|
||||||
|
+ PR_ASSERT(be == NULL);
|
||||||
|
return SLAPI_BIND_REFERRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.9.4
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
# also need the relprefix field for a pre-release e.g. .0 - also comment out for official release
|
# also need the relprefix field for a pre-release e.g. .0 - also comment out for official release
|
||||||
#% global relprefix 0.
|
#% global relprefix 0.
|
||||||
|
|
||||||
%global use_openldap 1
|
|
||||||
%global use_db4 0
|
|
||||||
# If perl-Socket-2.000 or newer is available, set 0 to use_Socket6.
|
# If perl-Socket-2.000 or newer is available, set 0 to use_Socket6.
|
||||||
%global use_Socket6 0
|
%global use_Socket6 0
|
||||||
%global use_nunc_stans 1
|
%global use_nunc_stans 1
|
||||||
|
@ -32,7 +30,7 @@
|
||||||
Summary: 389 Directory Server (base)
|
Summary: 389 Directory Server (base)
|
||||||
Name: 389-ds-base
|
Name: 389-ds-base
|
||||||
Version: 1.3.6.1
|
Version: 1.3.6.1
|
||||||
Release: %{?relprefix}16%{?prerel}%{?dist}
|
Release: %{?relprefix}19%{?prerel}%{?dist}
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
URL: https://www.port389.org/
|
URL: https://www.port389.org/
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
|
@ -43,17 +41,9 @@ Provides: ldif2ldbm >= 0
|
||||||
|
|
||||||
BuildRequires: nspr-devel
|
BuildRequires: nspr-devel
|
||||||
BuildRequires: nss-devel
|
BuildRequires: nss-devel
|
||||||
BuildRequires: svrcore-devel >= 4.1.2
|
BuildRequires: svrcore-devel >= 4.1.3
|
||||||
%if %{use_openldap}
|
|
||||||
BuildRequires: openldap-devel
|
BuildRequires: openldap-devel
|
||||||
%else
|
|
||||||
BuildRequires: mozldap-devel
|
|
||||||
%endif
|
|
||||||
%if %{use_db4}
|
|
||||||
BuildRequires: db4-devel
|
|
||||||
%else
|
|
||||||
BuildRequires: libdb-devel
|
BuildRequires: libdb-devel
|
||||||
%endif
|
|
||||||
BuildRequires: cyrus-sasl-devel
|
BuildRequires: cyrus-sasl-devel
|
||||||
BuildRequires: icu
|
BuildRequires: icu
|
||||||
BuildRequires: libicu-devel
|
BuildRequires: libicu-devel
|
||||||
|
@ -93,11 +83,7 @@ Requires: libsemanage-python
|
||||||
Requires: selinux-policy >= 3.13.1-137
|
Requires: selinux-policy >= 3.13.1-137
|
||||||
|
|
||||||
# the following are needed for some of our scripts
|
# the following are needed for some of our scripts
|
||||||
%if %{use_openldap}
|
|
||||||
Requires: openldap-clients
|
Requires: openldap-clients
|
||||||
%else
|
|
||||||
Requires: mozldap-tools
|
|
||||||
%endif
|
|
||||||
# use_openldap assumes perl-Mozilla-LDAP is built with openldap support
|
# use_openldap assumes perl-Mozilla-LDAP is built with openldap support
|
||||||
Requires: perl-Mozilla-LDAP
|
Requires: perl-Mozilla-LDAP
|
||||||
|
|
||||||
|
@ -112,11 +98,7 @@ Requires: cyrus-sasl-md5
|
||||||
Requires: cyrus-sasl-plain
|
Requires: cyrus-sasl-plain
|
||||||
|
|
||||||
# this is needed for verify-db.pl
|
# this is needed for verify-db.pl
|
||||||
%if %{use_db4}
|
|
||||||
Requires: db4-utils
|
|
||||||
%else
|
|
||||||
Requires: libdb-utils
|
Requires: libdb-utils
|
||||||
%endif
|
|
||||||
|
|
||||||
# This picks up libperl.so as a Requires, so we add this versioned one
|
# This picks up libperl.so as a Requires, so we add this versioned one
|
||||||
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
|
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
|
||||||
|
@ -137,7 +119,7 @@ Requires: perl-Socket
|
||||||
%endif
|
%endif
|
||||||
Requires: perl-NetAddr-IP
|
Requires: perl-NetAddr-IP
|
||||||
Requires: systemd-libs
|
Requires: systemd-libs
|
||||||
Requires: svrcore >= 4.1.2
|
Requires: svrcore >= 4.1.3
|
||||||
|
|
||||||
# upgrade path from monolithic % {name} (including -libs & -devel) to % {name} + % {name}-snmp
|
# upgrade path from monolithic % {name} (including -libs & -devel) to % {name} + % {name}-snmp
|
||||||
Obsoletes: %{name} <= 1.3.5.4
|
Obsoletes: %{name} <= 1.3.5.4
|
||||||
|
@ -207,6 +189,12 @@ Patch52: 0052-Ticket-49257-Reject-nsslapd-cachememsize-nsslapd-cac.patc
|
||||||
Patch53: 0053-Ticket-49257-Reject-dbcachesize-updates-while-auto-c.patch
|
Patch53: 0053-Ticket-49257-Reject-dbcachesize-updates-while-auto-c.patch
|
||||||
Patch54: 0054-Ticket-49184-adjust-logging-level-in-MO-plugin.patch
|
Patch54: 0054-Ticket-49184-adjust-logging-level-in-MO-plugin.patch
|
||||||
Patch55: 0055-Ticket-49241-add-symblic-link-location-to-db2bak.pl-.patch
|
Patch55: 0055-Ticket-49241-add-symblic-link-location-to-db2bak.pl-.patch
|
||||||
|
Patch56: 0056-Ticket-49313-Change-the-retrochangelog-default-cache.patch
|
||||||
|
Patch57: 0057-Ticket-49287-v3-extend-csnpl-handling-to-multiple-ba.patch
|
||||||
|
Patch58: 0058-Ticket-49336-SECURITY-Locked-account-provides-differ.patch
|
||||||
|
Patch59: 0059-Ticket-49298-force-sync-on-shutdown.patch
|
||||||
|
Patch60: 0060-Ticket-49334-fix-backup-restore-if-changelog-exists.patch
|
||||||
|
Patch61: 0061-Ticket-49356-mapping-tree-crash-can-occur-during-tot.patch
|
||||||
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
|
@ -218,17 +206,9 @@ Summary: Core libraries for 389 Directory Server
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
BuildRequires: nspr-devel
|
BuildRequires: nspr-devel
|
||||||
BuildRequires: nss-devel
|
BuildRequires: nss-devel
|
||||||
BuildRequires: svrcore-devel >= 4.1.2
|
BuildRequires: svrcore-devel >= 4.1.3
|
||||||
%if %{use_openldap}
|
|
||||||
BuildRequires: openldap-devel
|
BuildRequires: openldap-devel
|
||||||
%else
|
|
||||||
BuildRequires: mozldap-devel
|
|
||||||
%endif
|
|
||||||
%if %{use_db4}
|
|
||||||
BuildRequires: db4-devel
|
|
||||||
%else
|
|
||||||
BuildRequires: libdb-devel
|
BuildRequires: libdb-devel
|
||||||
%endif
|
|
||||||
BuildRequires: cyrus-sasl-devel
|
BuildRequires: cyrus-sasl-devel
|
||||||
BuildRequires: libicu-devel
|
BuildRequires: libicu-devel
|
||||||
BuildRequires: pcre-devel
|
BuildRequires: pcre-devel
|
||||||
|
@ -251,12 +231,8 @@ Requires: %{name}-libs = %{version}-%{release}
|
||||||
Requires: pkgconfig
|
Requires: pkgconfig
|
||||||
Requires: nspr-devel
|
Requires: nspr-devel
|
||||||
Requires: nss-devel
|
Requires: nss-devel
|
||||||
Requires: svrcore-devel >= 4.1.2
|
Requires: svrcore-devel >= 4.1.3
|
||||||
%if %{use_openldap}
|
|
||||||
Requires: openldap-devel
|
Requires: openldap-devel
|
||||||
%else
|
|
||||||
Requires: mozldap-devel
|
|
||||||
%endif
|
|
||||||
%if %{use_nunc_stans}
|
%if %{use_nunc_stans}
|
||||||
Requires: libtalloc
|
Requires: libtalloc
|
||||||
Requires: libevent
|
Requires: libevent
|
||||||
|
@ -345,12 +321,15 @@ cp %{SOURCE2} README.devel
|
||||||
%patch53 -p1
|
%patch53 -p1
|
||||||
%patch54 -p1
|
%patch54 -p1
|
||||||
%patch55 -p1
|
%patch55 -p1
|
||||||
|
%patch56 -p1
|
||||||
|
%patch57 -p1
|
||||||
|
%patch58 -p1
|
||||||
|
%patch59 -p1
|
||||||
|
%patch60 -p1
|
||||||
|
%patch61 -p1
|
||||||
%build
|
%build
|
||||||
|
|
||||||
%if %{use_openldap}
|
|
||||||
OPENLDAP_FLAG="--with-openldap"
|
OPENLDAP_FLAG="--with-openldap"
|
||||||
%endif
|
|
||||||
%{?with_tmpfiles_d: TMPFILES_FLAG="--with-tmpfiles-d=%{with_tmpfiles_d}"}
|
%{?with_tmpfiles_d: TMPFILES_FLAG="--with-tmpfiles-d=%{with_tmpfiles_d}"}
|
||||||
# hack hack hack https://bugzilla.redhat.com/show_bug.cgi?id=833529
|
# hack hack hack https://bugzilla.redhat.com/show_bug.cgi?id=833529
|
||||||
NSSARGS="--with-svrcore-inc=%{_includedir} --with-svrcore-lib=%{_libdir} --with-nss-lib=%{_libdir} --with-nss-inc=%{_includedir}/nss3"
|
NSSARGS="--with-svrcore-inc=%{_includedir} --with-svrcore-lib=%{_libdir} --with-nss-lib=%{_libdir} --with-nss-inc=%{_includedir}/nss3"
|
||||||
|
@ -442,11 +421,7 @@ HOMEDIR="/usr/share/dirsrv"
|
||||||
|
|
||||||
getent group $GROUPNAME >/dev/null || /usr/sbin/groupadd -f -g $ALLOCATED_GID -r $GROUPNAME
|
getent group $GROUPNAME >/dev/null || /usr/sbin/groupadd -f -g $ALLOCATED_GID -r $GROUPNAME
|
||||||
if ! getent passwd $USERNAME >/dev/null ; then
|
if ! getent passwd $USERNAME >/dev/null ; then
|
||||||
if ! getent passwd $ALLOCATED_UID >/dev/null ; then
|
/usr/sbin/useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
|
||||||
/usr/sbin/useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
|
|
||||||
else
|
|
||||||
/usr/sbin/useradd -r -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo looking for instances in %{_sysconfdir}/%{pkgname} > $output 2>&1 || :
|
echo looking for instances in %{_sysconfdir}/%{pkgname} > $output 2>&1 || :
|
||||||
|
@ -583,6 +558,23 @@ fi
|
||||||
%{_sysconfdir}/%{pkgname}/dirsrvtests
|
%{_sysconfdir}/%{pkgname}/dirsrvtests
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Aug 21 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.19-1
|
||||||
|
- Bump version to 1.3.6.19-1
|
||||||
|
- Remove old mozldap and db4 requirements
|
||||||
|
- Resolves: Bug 1483865 - Crash while binding to a server during replication online init
|
||||||
|
|
||||||
|
* Tue Aug 8 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-18
|
||||||
|
- Bump version to 1.3.6.1-18
|
||||||
|
- Require srvcore 4.1.3
|
||||||
|
- Resolves: Bug 1479757 - dse.ldif and fsync
|
||||||
|
- Resolves: Bug 1479755 - backup fails if changelog is enabled
|
||||||
|
- Resolves: Bug 1479756 - Locked account provides different return code if password is correct
|
||||||
|
|
||||||
|
* Mon Jul 31 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-17
|
||||||
|
- Bump version to 1.3.6.1-17
|
||||||
|
- Resolves: Bug 1476161 - replication halt - pending list first CSN not committed, pending list increasing
|
||||||
|
- Resolves: Bug 1476162 - Change the retrochangelog default cache size
|
||||||
|
|
||||||
* Tue Jun 6 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-16
|
* Tue Jun 6 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.6.1-16
|
||||||
- Bump version to 1.3.6.1-16
|
- Bump version to 1.3.6.1-16
|
||||||
- Resolves: Bug 1444938 - nsslapd-allowed-sasl-mechanisms doesn't reset to default values without a restart
|
- Resolves: Bug 1444938 - nsslapd-allowed-sasl-mechanisms doesn't reset to default values without a restart
|
||||||
|
|
Loading…
Add table
Reference in a new issue