mirror of
https://git.centos.org/rpms/389-ds-base.git
synced 2025-02-23 16:22:54 +00:00
import 389-ds-base-1.3.5.10-18.el7_3
This commit is contained in:
parent
4aa5b29fff
commit
7231508e62
10 changed files with 1330 additions and 2 deletions
|
@ -0,0 +1,100 @@
|
|||
From 50b73af8729b6753c71ba6206632561b5974523d Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@redhat.com>
|
||||
Date: Wed, 11 Jan 2017 14:14:40 -0800
|
||||
Subject: [PATCH 61/67] Ticket #49080 - shadowExpire should not be a calculated
|
||||
value
|
||||
|
||||
Description: Reverting the changes made on shadowExpire in the ticket 548.
|
||||
|
||||
Thanks to Gordon Messmer (gordon.messmer@gmail.com) for providing the original patch.
|
||||
|
||||
Reviewed by William Brown <wibrown@redhat.com> (Thanks!!).
|
||||
|
||||
(cherry picked from commit 14eb192b0f99ae3d811fd8a5bb40713bc85ea533)
|
||||
(cherry picked from commit 2ca12fc5b79dbbb8889eba6da7b4ce59cd6cb86d)
|
||||
---
|
||||
ldap/servers/slapd/pw.c | 29 +++++------------------------
|
||||
1 file changed, 5 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
|
||||
index 6f02f90..ce1ca2a 100644
|
||||
--- a/ldap/servers/slapd/pw.c
|
||||
+++ b/ldap/servers/slapd/pw.c
|
||||
@@ -2803,7 +2803,6 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
const char *dn = NULL;
|
||||
passwdPolicy *pwpolicy = NULL;
|
||||
long long shadowval = 0;
|
||||
- long long exptime = 0;
|
||||
Slapi_Mods *smods = NULL;
|
||||
LDAPMod **mods;
|
||||
long long sval;
|
||||
@@ -2811,7 +2810,6 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
char *shmin = NULL;
|
||||
char *shmax = NULL;
|
||||
char *shwarn = NULL;
|
||||
- char *shexp = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (!e || !*e) {
|
||||
@@ -2861,7 +2859,6 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
/* shadowMax - the maximum number of days for which the user password remains valid. */
|
||||
if (pwpolicy->pw_maxage > 0) {
|
||||
shadowval = pwpolicy->pw_maxage / _SEC_PER_DAY;
|
||||
- exptime = time_plus_sec(current_time(), pwpolicy->pw_maxage);
|
||||
if (shadowval > _MAX_SHADOW) {
|
||||
shadowval = _MAX_SHADOW;
|
||||
}
|
||||
@@ -2903,22 +2900,6 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
shwarn = slapi_ch_smprintf("%lld", shadowval);
|
||||
}
|
||||
|
||||
- /* shadowExpire - the date on which the user login will be disabled. */
|
||||
- if (exptime) {
|
||||
- shexp = slapi_entry_attr_get_charptr(*e, "shadowExpire");
|
||||
- exptime /= _SEC_PER_DAY;
|
||||
- if (shexp) {
|
||||
- sval = strtoll(shexp, NULL, 0);
|
||||
- if (sval != exptime) {
|
||||
- slapi_ch_free_string(&shexp);
|
||||
- shexp = slapi_ch_smprintf("%lld", exptime);
|
||||
- mod_num++;
|
||||
- }
|
||||
- } else {
|
||||
- mod_num++;
|
||||
- shexp = slapi_ch_smprintf("%lld", exptime);
|
||||
- }
|
||||
- }
|
||||
smods = slapi_mods_new();
|
||||
slapi_mods_init(smods, mod_num);
|
||||
if (shmin) {
|
||||
@@ -2933,10 +2914,6 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
slapi_mods_add(smods, LDAP_MOD_REPLACE, "shadowWarning", strlen(shwarn), shwarn);
|
||||
slapi_ch_free_string(&shwarn);
|
||||
}
|
||||
- if (shexp) {
|
||||
- slapi_mods_add(smods, LDAP_MOD_REPLACE, "shadowExpire", strlen(shexp), shexp);
|
||||
- slapi_ch_free_string(&shexp);
|
||||
- }
|
||||
/* Apply the mods to create the resulting entry. */
|
||||
mods = slapi_mods_get_ldapmods_byref(smods);
|
||||
if (mods) {
|
||||
@@ -2947,11 +2924,15 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
}
|
||||
slapi_mods_free(&smods);
|
||||
|
||||
-#if 0 /* These 2 attributes are no need (or not able) to auto-fill. */
|
||||
+#if 0 /* These 3 attributes are no need (or not able) to auto-fill. */
|
||||
/*
|
||||
* shadowInactive - the number of days of inactivity allowed for the user.
|
||||
* Password Policy does not have the corresponding parameter.
|
||||
*
|
||||
+ * shadowExpire - the number of days since Jan 1, 1970 after which the
|
||||
+ * account, not the password, will expire. This is not affected by the
|
||||
+ * Password Policy.
|
||||
+ *
|
||||
* shadowFlag - not currently in use.
|
||||
*/
|
||||
#endif
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
From 96ad7ec4fa84dd32439e3473c0128612dd5f9d49 Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@redhat.com>
|
||||
Date: Wed, 11 Jan 2017 15:04:42 -0800
|
||||
Subject: [PATCH 62/67] Ticket #49082 - Fix password expiration related shadow
|
||||
attributes
|
||||
|
||||
The original patch was provided by Gordon Messmer (gordon.messmer@gmail.com)
|
||||
with the description:
|
||||
Bug description:
|
||||
Shadow attributes (in /etc/shadow and in LDAP) are typically unset when no
|
||||
policy is in place. 389-ds will incorrectly return values (possibly set to 0)
|
||||
when there is no policy.
|
||||
|
||||
Fix description:
|
||||
Only auto-fill shadow attributes when a password policy is available. These
|
||||
are empty when no policy is in place.
|
||||
|
||||
Don't auto-fill expiration related shadow attributes if passwords never expire.
|
||||
|
||||
Reviewed by William Brown <wibrown@redhat.com> (Thanks!!).
|
||||
|
||||
(cherry picked from commit 5bcd966b73708f6b558f01e6b11a7a11e8d3b126)
|
||||
(cherry picked from commit faae0fa5a4a6b3d590c1a9e068d9436965cc49c9)
|
||||
---
|
||||
ldap/servers/slapd/pw.c | 74 +++++++++++++++++++++++++------------------------
|
||||
1 file changed, 38 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
|
||||
index ce1ca2a..30a2cb9 100644
|
||||
--- a/ldap/servers/slapd/pw.c
|
||||
+++ b/ldap/servers/slapd/pw.c
|
||||
@@ -2802,7 +2802,7 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
{
|
||||
const char *dn = NULL;
|
||||
passwdPolicy *pwpolicy = NULL;
|
||||
- long long shadowval = 0;
|
||||
+ long long shadowval = -1;
|
||||
Slapi_Mods *smods = NULL;
|
||||
LDAPMod **mods;
|
||||
long long sval;
|
||||
@@ -2840,64 +2840,66 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
|
||||
if (shadowval > _MAX_SHADOW) {
|
||||
shadowval = _MAX_SHADOW;
|
||||
}
|
||||
- } else {
|
||||
- shadowval = 0;
|
||||
}
|
||||
- shmin = slapi_entry_attr_get_charptr(*e, "shadowMin");
|
||||
- if (shmin) {
|
||||
- sval = strtoll(shmin, NULL, 0);
|
||||
- if (sval != shadowval) {
|
||||
- slapi_ch_free_string(&shmin);
|
||||
- shmin = slapi_ch_smprintf("%lld", shadowval);
|
||||
+ if (shadowval > 0) {
|
||||
+ shmin = slapi_entry_attr_get_charptr(*e, "shadowMin");
|
||||
+ if (shmin) {
|
||||
+ sval = strtoll(shmin, NULL, 0);
|
||||
+ if (sval != shadowval) {
|
||||
+ slapi_ch_free_string(&shmin);
|
||||
+ shmin = slapi_ch_smprintf("%lld", shadowval);
|
||||
+ mod_num++;
|
||||
+ }
|
||||
+ } else {
|
||||
mod_num++;
|
||||
+ shmin = slapi_ch_smprintf("%lld", shadowval);
|
||||
}
|
||||
- } else {
|
||||
- mod_num++;
|
||||
- shmin = slapi_ch_smprintf("%lld", shadowval);
|
||||
}
|
||||
|
||||
/* shadowMax - the maximum number of days for which the user password remains valid. */
|
||||
- if (pwpolicy->pw_maxage > 0) {
|
||||
+ shadowval = -1;
|
||||
+ if (pwpolicy->pw_exp == 1 && pwpolicy->pw_maxage > 0) {
|
||||
shadowval = pwpolicy->pw_maxage / _SEC_PER_DAY;
|
||||
if (shadowval > _MAX_SHADOW) {
|
||||
shadowval = _MAX_SHADOW;
|
||||
}
|
||||
- } else {
|
||||
- shadowval = _MAX_SHADOW;
|
||||
}
|
||||
- shmax = slapi_entry_attr_get_charptr(*e, "shadowMax");
|
||||
- if (shmax) {
|
||||
- sval = strtoll(shmax, NULL, 0);
|
||||
- if (sval != shadowval) {
|
||||
- slapi_ch_free_string(&shmax);
|
||||
- shmax = slapi_ch_smprintf("%lld", shadowval);
|
||||
+ if (shadowval > 0) {
|
||||
+ shmax = slapi_entry_attr_get_charptr(*e, "shadowMax");
|
||||
+ if (shmax) {
|
||||
+ sval = strtoll(shmax, NULL, 0);
|
||||
+ if (sval != shadowval) {
|
||||
+ slapi_ch_free_string(&shmax);
|
||||
+ shmax = slapi_ch_smprintf("%lld", shadowval);
|
||||
+ mod_num++;
|
||||
+ }
|
||||
+ } else {
|
||||
mod_num++;
|
||||
+ shmax = slapi_ch_smprintf("%lld", shadowval);
|
||||
}
|
||||
- } else {
|
||||
- mod_num++;
|
||||
- shmax = slapi_ch_smprintf("%lld", shadowval);
|
||||
}
|
||||
|
||||
/* shadowWarning - the number of days of advance warning given to the user before the user password expires. */
|
||||
- if (pwpolicy->pw_warning > 0) {
|
||||
+ shadowval = -1;
|
||||
+ if (pwpolicy->pw_exp == 1 && pwpolicy->pw_warning > 0) {
|
||||
shadowval = pwpolicy->pw_warning / _SEC_PER_DAY;
|
||||
if (shadowval > _MAX_SHADOW) {
|
||||
shadowval = _MAX_SHADOW;
|
||||
}
|
||||
- } else {
|
||||
- shadowval = 0;
|
||||
}
|
||||
- shwarn = slapi_entry_attr_get_charptr(*e, "shadowWarning");
|
||||
- if (shwarn) {
|
||||
- sval = strtoll(shwarn, NULL, 0);
|
||||
- if (sval != shadowval) {
|
||||
- slapi_ch_free_string(&shwarn);
|
||||
- shwarn = slapi_ch_smprintf("%lld", shadowval);
|
||||
+ if (shadowval > 0) {
|
||||
+ shwarn = slapi_entry_attr_get_charptr(*e, "shadowWarning");
|
||||
+ if (shwarn) {
|
||||
+ sval = strtoll(shwarn, NULL, 0);
|
||||
+ if (sval != shadowval) {
|
||||
+ slapi_ch_free_string(&shwarn);
|
||||
+ shwarn = slapi_ch_smprintf("%lld", shadowval);
|
||||
+ mod_num++;
|
||||
+ }
|
||||
+ } else {
|
||||
mod_num++;
|
||||
+ shwarn = slapi_ch_smprintf("%lld", shadowval);
|
||||
}
|
||||
- } else {
|
||||
- mod_num++;
|
||||
- shwarn = slapi_ch_smprintf("%lld", shadowval);
|
||||
}
|
||||
|
||||
smods = slapi_mods_new();
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From ee9b5c5dc3f4382ee73abefb9d2e3c275e62d6c8 Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@redhat.com>
|
||||
Date: Wed, 11 Jan 2017 15:14:07 -0800
|
||||
Subject: [PATCH 63/67] Ticket #49082 - Adjusted the CI test case to the fix.
|
||||
|
||||
Description: Fix password expiration related shadow attributes
|
||||
(cherry picked from commit 5a6a5a18d0458bd147af57a06158245f329ddba3)
|
||||
(cherry picked from commit b9e565df5d304ba9fb516b987ad62480590a5845)
|
||||
---
|
||||
dirsrvtests/tests/tickets/ticket548_test.py | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/dirsrvtests/tests/tickets/ticket548_test.py b/dirsrvtests/tests/tickets/ticket548_test.py
|
||||
index d29fa53..dea7c3c 100644
|
||||
--- a/dirsrvtests/tests/tickets/ticket548_test.py
|
||||
+++ b/dirsrvtests/tests/tickets/ticket548_test.py
|
||||
@@ -98,6 +98,13 @@ def set_global_pwpolicy(topology, min_=1, max_=10, warn=3):
|
||||
log.error('Failed to set passwordMinAge: error ' + e.message['desc'])
|
||||
assert False
|
||||
|
||||
+ log.info(" Set global password Expiration -- on\n")
|
||||
+ try:
|
||||
+ topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordExp', 'on')])
|
||||
+ except ldap.LDAPError as e:
|
||||
+ log.error('Failed to set passwordExp: error ' + e.message['desc'])
|
||||
+ assert False
|
||||
+
|
||||
log.info(" Set global password Max Age -- %s days\n" % max_)
|
||||
try:
|
||||
topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordMaxAge', '%s' % max_secs)])
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,631 @@
|
|||
From d1477e4a03d85aec79b497db4531d9e484029139 Mon Sep 17 00:00:00 2001
|
||||
From: Ludwig Krispenz <lkrispen@redhat.com>
|
||||
Date: Tue, 24 Jan 2017 15:07:19 +0100
|
||||
Subject: [PATCH 64/67] Ticket 49008 backport 1.3.5 : aborted operation can
|
||||
leave RUV in incorrect state
|
||||
|
||||
Bug description:
|
||||
If a plugin operation succeeded, but the operation itself fails and is aborted the RUV is in an incorrect state (rolled up to the succesful plugin op)
|
||||
|
||||
Fix Decription:
|
||||
Introduce a "primary_csn", this is the csn of the main operation, either a client operation or a replicated operation.
|
||||
csns generated by internal operations, eg by plugins are secondary csn.
|
||||
|
||||
Maintain the primary csn in thread local data, like it is used for the agreement name (or txn stack): prim_csn.
|
||||
|
||||
Extend the data structure of the pending list to keep prim_csn for each inserted csn
|
||||
|
||||
If a csn is created or received check prim_csn: if it exists use it, if it doesn't exist set it
|
||||
|
||||
when inserting a csn to the pending list pass the prim_csn
|
||||
|
||||
when cancelling a csn, if it is the prim_csn also cancell all secondary csns
|
||||
|
||||
when committing a csn,
|
||||
|
||||
if it is not the primary csn, do nothing
|
||||
|
||||
if it is the prim_csn trigger the pending list rollup, stop at the first not committed csn
|
||||
|
||||
if the RID of the prim_csn is not the local RID also rollup the pending list for the local RID.
|
||||
|
||||
Reviewed by: Thierry, Thanks
|
||||
|
||||
(cherry picked from commit 79a3deafe943a3ce5c31c50272939146d17bd7ac)
|
||||
---
|
||||
ldap/servers/plugins/replication/csnpl.c | 75 +++++++++++++++++++++---
|
||||
ldap/servers/plugins/replication/csnpl.h | 5 +-
|
||||
ldap/servers/plugins/replication/repl5.h | 2 +
|
||||
ldap/servers/plugins/replication/repl5_init.c | 22 +++++++
|
||||
ldap/servers/plugins/replication/repl5_plugins.c | 40 ++++++++-----
|
||||
ldap/servers/plugins/replication/repl5_replica.c | 6 +-
|
||||
ldap/servers/plugins/replication/repl5_ruv.c | 74 +++++++++++++++++------
|
||||
ldap/servers/plugins/replication/repl5_ruv.h | 4 +-
|
||||
ldap/servers/slapd/csn.c | 15 +++++
|
||||
ldap/servers/slapd/slapi-private.h | 2 +
|
||||
10 files changed, 195 insertions(+), 50 deletions(-)
|
||||
|
||||
diff --git a/ldap/servers/plugins/replication/csnpl.c b/ldap/servers/plugins/replication/csnpl.c
|
||||
index acd38d0..db1ae13 100644
|
||||
--- a/ldap/servers/plugins/replication/csnpl.c
|
||||
+++ b/ldap/servers/plugins/replication/csnpl.c
|
||||
@@ -24,8 +24,9 @@ struct csnpl
|
||||
|
||||
typedef struct _csnpldata
|
||||
{
|
||||
- PRBool committed; /* True if CSN committed */
|
||||
- CSN *csn; /* The actual CSN */
|
||||
+ PRBool committed; /* True if CSN committed */
|
||||
+ CSN *csn; /* The actual CSN */
|
||||
+ const CSN *prim_csn; /* The primary CSN of an operation consising of multiple sub ops*/
|
||||
} csnpldata;
|
||||
|
||||
/* forward declarations */
|
||||
@@ -103,7 +104,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)
|
||||
+int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn)
|
||||
{
|
||||
int rc;
|
||||
csnpldata *csnplnode;
|
||||
@@ -131,6 +132,7 @@ int csnplInsert (CSNPL *csnpl, const CSN *csn)
|
||||
csnplnode = (csnpldata *)slapi_ch_malloc(sizeof(csnpldata));
|
||||
csnplnode->committed = PR_FALSE;
|
||||
csnplnode->csn = csn_dup(csn);
|
||||
+ csnplnode->prim_csn = prim_csn;
|
||||
csn_as_string(csn, PR_FALSE, csn_str);
|
||||
rc = llistInsertTail (csnpl->csnList, csn_str, csnplnode);
|
||||
|
||||
@@ -186,6 +188,57 @@ int csnplRemove (CSNPL *csnpl, const CSN *csn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int csnplRemoveAll (CSNPL *csnpl, const CSN *csn)
|
||||
+{
|
||||
+ csnpldata *data;
|
||||
+ void *iterator;
|
||||
+
|
||||
+ slapi_rwlock_wrlock (csnpl->csnLock);
|
||||
+ data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
|
||||
+ while (NULL != data)
|
||||
+ {
|
||||
+ if (csn_is_equal(data->csn, csn) ||
|
||||
+ csn_is_equal(data->prim_csn, csn)) {
|
||||
+ csnpldata_free(&data);
|
||||
+ data = (csnpldata *)llistRemoveCurrentAndGetNext(csnpl->csnList, &iterator);
|
||||
+ } else {
|
||||
+ data = (csnpldata *)llistGetNext (csnpl->csnList, &iterator);
|
||||
+ }
|
||||
+ }
|
||||
+#ifdef DEBUG
|
||||
+ _csnplDumpContentNoLock(csnpl, "csnplRemoveAll");
|
||||
+#endif
|
||||
+ slapi_rwlock_unlock (csnpl->csnLock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
|
||||
+{
|
||||
+ csnpldata *data;
|
||||
+ void *iterator;
|
||||
+ char csn_str[CSN_STRSIZE];
|
||||
+
|
||||
+ csn_as_string(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);
|
||||
+ data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
|
||||
+ while (NULL != data)
|
||||
+ {
|
||||
+ 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)) {
|
||||
+ data->committed = PR_TRUE;
|
||||
+ }
|
||||
+ data = (csnpldata *)llistGetNext (csnpl->csnList, &iterator);
|
||||
+ }
|
||||
+ slapi_rwlock_unlock (csnpl->csnLock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int csnplCommit (CSNPL *csnpl, const CSN *csn)
|
||||
{
|
||||
csnpldata *data;
|
||||
@@ -276,13 +329,12 @@ csnplRollUp(CSNPL *csnpl, CSN **first_commited)
|
||||
*first_commited = NULL;
|
||||
}
|
||||
data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
|
||||
- while (NULL != data)
|
||||
+ while (NULL != data && data->committed)
|
||||
{
|
||||
if (NULL != largest_committed_csn && freeit)
|
||||
{
|
||||
csn_free(&largest_committed_csn);
|
||||
}
|
||||
- if (data->committed) {
|
||||
freeit = PR_TRUE;
|
||||
largest_committed_csn = data->csn; /* Save it */
|
||||
if (first_commited && (*first_commited == NULL)) {
|
||||
@@ -294,9 +346,6 @@ csnplRollUp(CSNPL *csnpl, CSN **first_commited)
|
||||
data->csn = NULL;
|
||||
csnpldata_free(&data);
|
||||
data = (csnpldata *)llistRemoveCurrentAndGetNext(csnpl->csnList, &iterator);
|
||||
- } else {
|
||||
- data = (csnpldata *)llistGetNext (csnpl->csnList, &iterator);
|
||||
- }
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -326,6 +375,7 @@ static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller)
|
||||
csnpldata *data;
|
||||
void *iterator;
|
||||
char csn_str[CSN_STRSIZE];
|
||||
+ char primcsn_str[CSN_STRSIZE];
|
||||
|
||||
data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
|
||||
if (data) {
|
||||
@@ -334,11 +384,18 @@ static void _csnplDumpContentNoLock(CSNPL *csnpl, const char *caller)
|
||||
}
|
||||
while (data)
|
||||
{
|
||||
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "%s, %s\n",
|
||||
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "%s,(prim %s), %s\n",
|
||||
csn_as_string(data->csn, PR_FALSE, csn_str),
|
||||
+ data->prim_csn ? csn_as_string(data->prim_csn, PR_FALSE, primcsn_str) : " ",
|
||||
data->committed ? "committed" : "not committed");
|
||||
data = (csnpldata *)llistGetNext (csnpl->csnList, &iterator);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+/* wrapper around csn_free, to satisfy NSPR thread context API */
|
||||
+void
|
||||
+csnplFreeCSN (void *arg)
|
||||
+{
|
||||
+ csn_free((CSN **)&arg);
|
||||
+}
|
||||
diff --git a/ldap/servers/plugins/replication/csnpl.h b/ldap/servers/plugins/replication/csnpl.h
|
||||
index 32e3ff7..f5c28f5 100644
|
||||
--- a/ldap/servers/plugins/replication/csnpl.h
|
||||
+++ b/ldap/servers/plugins/replication/csnpl.h
|
||||
@@ -22,10 +22,13 @@ typedef struct csnpl CSNPL;
|
||||
|
||||
CSNPL* csnplNew ();
|
||||
void csnplFree (CSNPL **csnpl);
|
||||
-int csnplInsert (CSNPL *csnpl, const CSN *csn);
|
||||
+int csnplInsert (CSNPL *csnpl, const CSN *csn, const CSN *prim_csn);
|
||||
int csnplRemove (CSNPL *csnpl, const CSN *csn);
|
||||
+int csnplRemoveAll (CSNPL *csnpl, const CSN *csn);
|
||||
+int csnplCommitAll (CSNPL *csnpl, const CSN *csn);
|
||||
CSN* csnplGetMinCSN (CSNPL *csnpl, PRBool *committed);
|
||||
int csnplCommit (CSNPL *csnpl, const CSN *csn);
|
||||
CSN *csnplRollUp(CSNPL *csnpl, CSN ** first);
|
||||
void csnplDumpContent(CSNPL *csnpl, const char *caller);
|
||||
+
|
||||
#endif
|
||||
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
|
||||
index 4ab2355..27ad416 100644
|
||||
--- a/ldap/servers/plugins/replication/repl5.h
|
||||
+++ b/ldap/servers/plugins/replication/repl5.h
|
||||
@@ -232,6 +232,8 @@ int multimaster_be_betxnpostop_modify (Slapi_PBlock *pb);
|
||||
extern int repl5_is_betxn;
|
||||
char* get_thread_private_agmtname ();
|
||||
void set_thread_private_agmtname (const char *agmtname);
|
||||
+void set_thread_primary_csn (const CSN *prim_csn);
|
||||
+CSN* get_thread_primary_csn(void);
|
||||
void* get_thread_private_cache ();
|
||||
void set_thread_private_cache (void *buf);
|
||||
char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);
|
||||
diff --git a/ldap/servers/plugins/replication/repl5_init.c b/ldap/servers/plugins/replication/repl5_init.c
|
||||
index 0304ed5..1570655 100644
|
||||
--- a/ldap/servers/plugins/replication/repl5_init.c
|
||||
+++ b/ldap/servers/plugins/replication/repl5_init.c
|
||||
@@ -136,6 +136,7 @@ static int multimaster_started_flag = 0;
|
||||
/* Thread private data and interface */
|
||||
static PRUintn thread_private_agmtname; /* thread private index for logging*/
|
||||
static PRUintn thread_private_cache;
|
||||
+static PRUintn thread_primary_csn;
|
||||
|
||||
char*
|
||||
get_thread_private_agmtname()
|
||||
@@ -153,6 +154,26 @@ set_thread_private_agmtname(const char *agmtname)
|
||||
PR_SetThreadPrivate(thread_private_agmtname, (void *)agmtname);
|
||||
}
|
||||
|
||||
+CSN*
|
||||
+get_thread_primary_csn(void)
|
||||
+{
|
||||
+ CSN *prim_csn = NULL;
|
||||
+ if (thread_primary_csn)
|
||||
+ prim_csn = (CSN *)PR_GetThreadPrivate(thread_primary_csn);
|
||||
+ return prim_csn;
|
||||
+}
|
||||
+void
|
||||
+set_thread_primary_csn(const CSN *prim_csn)
|
||||
+{
|
||||
+ if (thread_primary_csn) {
|
||||
+ if (prim_csn) {
|
||||
+ PR_SetThreadPrivate(thread_primary_csn, (void *)csn_dup(prim_csn));
|
||||
+ } else {
|
||||
+ PR_SetThreadPrivate(thread_primary_csn, NULL);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void*
|
||||
get_thread_private_cache ()
|
||||
{
|
||||
@@ -721,6 +742,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);
|
||||
|
||||
/* 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 b331c81..84624e9 100644
|
||||
--- a/ldap/servers/plugins/replication/repl5_plugins.c
|
||||
+++ b/ldap/servers/plugins/replication/repl5_plugins.c
|
||||
@@ -1033,9 +1033,11 @@ static int
|
||||
write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||
{
|
||||
Slapi_Operation *op = NULL;
|
||||
+ CSN *opcsn;
|
||||
+ CSN *prim_csn;
|
||||
int rc;
|
||||
slapi_operation_parameters *op_params = NULL;
|
||||
- Object *repl_obj;
|
||||
+ Object *repl_obj = NULL;
|
||||
int return_value = SLAPI_PLUGIN_SUCCESS;
|
||||
Replica *r;
|
||||
Slapi_Backend *be;
|
||||
@@ -1063,17 +1065,17 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||
{
|
||||
return return_value;
|
||||
}
|
||||
+ /* we only log changes for operations applied to a replica */
|
||||
+ repl_obj = replica_get_replica_for_op (pb);
|
||||
+ if (repl_obj == NULL)
|
||||
+ return return_value;
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
|
||||
if (rc) { /* op failed - just return */
|
||||
- return return_value;
|
||||
+ cancel_opcsn(pb);
|
||||
+ goto common_return;
|
||||
}
|
||||
|
||||
- /* we only log changes for operations applied to a replica */
|
||||
- repl_obj = replica_get_replica_for_op (pb);
|
||||
- if (repl_obj == NULL)
|
||||
- return return_value;
|
||||
-
|
||||
r = (Replica*)object_get_data (repl_obj);
|
||||
PR_ASSERT (r);
|
||||
|
||||
@@ -1108,7 +1110,7 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||
|
||||
slapi_pblock_get (pb, SLAPI_OPERATION_PARAMETERS, &op_params);
|
||||
if (NULL == op_params) {
|
||||
- return return_value;
|
||||
+ goto common_return;
|
||||
}
|
||||
|
||||
/* need to set uniqueid operation parameter */
|
||||
@@ -1127,19 +1129,18 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||
slapi_pblock_get (pb, SLAPI_ENTRY_PRE_OP, &e);
|
||||
}
|
||||
if (NULL == e) {
|
||||
- return return_value;
|
||||
+ goto common_return;
|
||||
}
|
||||
uniqueid = slapi_entry_get_uniqueid (e);
|
||||
if (NULL == uniqueid) {
|
||||
- return return_value;
|
||||
+ goto common_return;
|
||||
}
|
||||
op_params->target_address.uniqueid = slapi_ch_strdup (uniqueid);
|
||||
}
|
||||
|
||||
if( op_params->csn && is_cleaned_rid(csn_get_replicaid(op_params->csn))){
|
||||
/* this RID has been cleaned */
|
||||
- object_release (repl_obj);
|
||||
- return return_value;
|
||||
+ goto common_return;
|
||||
}
|
||||
|
||||
/* we might have stripped all the mods - in that case we do not
|
||||
@@ -1152,7 +1153,7 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||
{
|
||||
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
|
||||
"write_changelog_and_ruv: Skipped due to DISKFULL\n");
|
||||
- return return_value;
|
||||
+ goto common_return;
|
||||
}
|
||||
slapi_pblock_get(pb, SLAPI_TXN, &txn);
|
||||
rc = cl5WriteOperationTxn(repl_name, repl_gen, op_params,
|
||||
@@ -1188,7 +1189,6 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||
*/
|
||||
if (0 == return_value) {
|
||||
char csn_str[CSN_STRSIZE] = {'\0'};
|
||||
- CSN *opcsn;
|
||||
int rc;
|
||||
const char *dn = op_params ? REPL_GET_DN(&op_params->target_address) : "unknown";
|
||||
Slapi_DN *sdn = op_params ? (&op_params->target_address)->sdn : NULL;
|
||||
@@ -1220,7 +1220,15 @@ write_changelog_and_ruv (Slapi_PBlock *pb)
|
||||
}
|
||||
}
|
||||
|
||||
- object_release (repl_obj);
|
||||
+common_return:
|
||||
+ opcsn = operation_get_csn(op);
|
||||
+ prim_csn = get_thread_primary_csn();
|
||||
+ if (csn_is_equal(opcsn, prim_csn)) {
|
||||
+ set_thread_primary_csn(NULL);
|
||||
+ }
|
||||
+ if (repl_obj) {
|
||||
+ object_release (repl_obj);
|
||||
+ }
|
||||
return return_value;
|
||||
}
|
||||
|
||||
@@ -1417,7 +1425,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);
|
||||
+ ruv_cancel_csn_inprogress ((RUV*)object_get_data (ruv_obj), opcsn, replica_get_rid(r));
|
||||
object_release (ruv_obj);
|
||||
}
|
||||
|
||||
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
|
||||
index 7360d97..602653a 100644
|
||||
--- a/ldap/servers/plugins/replication/repl5_replica.c
|
||||
+++ b/ldap/servers/plugins/replication/repl5_replica.c
|
||||
@@ -903,7 +903,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, rid == r->repl_rid);
|
||||
+ rc = ruv_update_ruv (ruv, updated_csn, replica_purl, r->repl_rid);
|
||||
if (RUV_COVERS_CSN == rc)
|
||||
{
|
||||
slapi_log_error(SLAPI_LOG_REPL,
|
||||
@@ -3626,7 +3626,7 @@ assign_csn_callback(const CSN *csn, void *data)
|
||||
|
||||
if (NULL != r->min_csn_pl)
|
||||
{
|
||||
- if (csnplInsert(r->min_csn_pl, csn) != 0)
|
||||
+ if (csnplInsert(r->min_csn_pl, csn, NULL) != 0)
|
||||
{
|
||||
char csn_str[CSN_STRSIZE]; /* For logging only */
|
||||
/* Ack, we can't keep track of min csn. Punt. */
|
||||
@@ -3674,7 +3674,7 @@ abort_csn_callback(const CSN *csn, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
- ruv_cancel_csn_inprogress (ruv, csn);
|
||||
+ ruv_cancel_csn_inprogress (ruv, csn, replica_get_rid(r));
|
||||
replica_unlock(r->repl_lock);
|
||||
|
||||
object_release (ruv_obj);
|
||||
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
|
||||
index 5d6e1c3..c2d3bb4 100644
|
||||
--- a/ldap/servers/plugins/replication/repl5_ruv.c
|
||||
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
|
||||
@@ -77,6 +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);
|
||||
|
||||
/* API implementation */
|
||||
|
||||
@@ -1602,6 +1603,7 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
|
||||
char csn_str[CSN_STRSIZE];
|
||||
int rc = RUV_SUCCESS;
|
||||
int rid = csn_get_replicaid (csn);
|
||||
+ CSN *prim_csn;
|
||||
|
||||
PR_ASSERT (ruv && csn);
|
||||
|
||||
@@ -1639,8 +1641,12 @@ int ruv_add_csn_inprogress (RUV *ruv, const CSN *csn)
|
||||
rc = RUV_COVERS_CSN;
|
||||
goto done;
|
||||
}
|
||||
-
|
||||
- rc = csnplInsert (replica->csnpl, csn);
|
||||
+ prim_csn = get_thread_primary_csn();
|
||||
+ if (prim_csn == NULL) {
|
||||
+ set_thread_primary_csn(csn);
|
||||
+ prim_csn = get_thread_primary_csn();
|
||||
+ }
|
||||
+ rc = csnplInsert (replica->csnpl, csn, prim_csn);
|
||||
if (rc == 1) /* we already seen this csn */
|
||||
{
|
||||
if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
|
||||
@@ -1648,6 +1654,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);
|
||||
rc = RUV_COVERS_CSN;
|
||||
}
|
||||
else if(rc != 0)
|
||||
@@ -1672,24 +1679,36 @@ done:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn)
|
||||
+int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
|
||||
{
|
||||
RUVElement* replica;
|
||||
int rc = RUV_SUCCESS;
|
||||
+ CSN *prim_csn = NULL;
|
||||
+
|
||||
|
||||
PR_ASSERT (ruv && csn);
|
||||
|
||||
+ prim_csn = get_thread_primary_csn();
|
||||
/* locate ruvElement */
|
||||
slapi_rwlock_wrlock (ruv->lock);
|
||||
replica = ruvGetReplica (ruv, csn_get_replicaid (csn));
|
||||
- if (replica == NULL)
|
||||
- {
|
||||
+ if (replica == NULL) {
|
||||
/* ONREPL - log error */
|
||||
- rc = RUV_NOTFOUND;
|
||||
- goto done;
|
||||
- }
|
||||
-
|
||||
- rc = csnplRemove (replica->csnpl, csn);
|
||||
+ 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) {
|
||||
+ replica = ruvGetReplica (ruv, local_rid);
|
||||
+ rc = csnplRemoveAll (replica->csnpl, prim_csn);
|
||||
+ }
|
||||
+ } else {
|
||||
+ rc = csnplRemove (replica->csnpl, csn);
|
||||
+ }
|
||||
if (rc != 0)
|
||||
rc = RUV_NOTFOUND;
|
||||
else
|
||||
@@ -1700,19 +1719,37 @@ done:
|
||||
return rc;
|
||||
}
|
||||
|
||||
-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool isLocal)
|
||||
+int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, ReplicaId local_rid)
|
||||
+{
|
||||
+ int rc=RUV_SUCCESS;
|
||||
+ RUVElement *replica;
|
||||
+ ReplicaId prim_rid;
|
||||
+
|
||||
+ CSN *prim_csn = get_thread_primary_csn();
|
||||
+
|
||||
+ if (! csn_is_equal(csn, prim_csn)) {
|
||||
+ /* not a primary csn, nothing to do */
|
||||
+ return rc;
|
||||
+ }
|
||||
+ slapi_rwlock_wrlock (ruv->lock);
|
||||
+ 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_unlock (ruv->lock);
|
||||
+ return rc;
|
||||
+}
|
||||
+static int
|
||||
+ruv_update_ruv_element (RUV *ruv, RUVElement *replica, const CSN *csn, const char *replica_purl, PRBool isLocal)
|
||||
{
|
||||
int rc=RUV_SUCCESS;
|
||||
char csn_str[CSN_STRSIZE];
|
||||
CSN *max_csn;
|
||||
CSN *first_csn = NULL;
|
||||
- RUVElement *replica;
|
||||
|
||||
- PR_ASSERT (ruv && csn);
|
||||
-
|
||||
- slapi_rwlock_wrlock (ruv->lock);
|
||||
-
|
||||
- replica = ruvGetReplica (ruv, csn_get_replicaid (csn));
|
||||
if (replica == NULL)
|
||||
{
|
||||
/* we should have a ruv element at this point because it would have
|
||||
@@ -1722,7 +1759,7 @@ int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool i
|
||||
goto done;
|
||||
}
|
||||
|
||||
- if (csnplCommit(replica->csnpl, csn) != 0)
|
||||
+ if (csnplCommitAll(replica->csnpl, csn) != 0)
|
||||
{
|
||||
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "ruv_update_ruv: cannot commit csn %s\n",
|
||||
csn_as_string(csn, PR_FALSE, csn_str));
|
||||
@@ -1763,7 +1800,6 @@ int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool i
|
||||
}
|
||||
|
||||
done:
|
||||
- slapi_rwlock_unlock (ruv->lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
|
||||
index e9eff5a..c8960fd 100644
|
||||
--- a/ldap/servers/plugins/replication/repl5_ruv.h
|
||||
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
|
||||
@@ -109,8 +109,8 @@ 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);
|
||||
-int ruv_update_ruv (RUV *ruv, const CSN *csn, const char *replica_purl, PRBool isLocal);
|
||||
+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_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/csn.c b/ldap/servers/slapd/csn.c
|
||||
index a3f4815..175f82a 100644
|
||||
--- a/ldap/servers/slapd/csn.c
|
||||
+++ b/ldap/servers/slapd/csn.c
|
||||
@@ -268,6 +268,21 @@ csn_as_attr_option_string(CSNType t,const CSN *csn,char *ss)
|
||||
return s;
|
||||
}
|
||||
|
||||
+int
|
||||
+csn_is_equal(const CSN *csn1, const CSN *csn2)
|
||||
+{
|
||||
+ int retval = 0;
|
||||
+ if ((csn1 == NULL && csn2 == NULL) ||
|
||||
+ (csn1 && csn2 &&
|
||||
+ csn1->tstamp == csn2->tstamp &&
|
||||
+ csn1->seqnum == csn2->seqnum &&
|
||||
+ csn1->rid == csn2->rid &&
|
||||
+ csn1->subseqnum == csn2->subseqnum)) {
|
||||
+ retval = 1;
|
||||
+ }
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
int
|
||||
csn_compare_ext(const CSN *csn1, const CSN *csn2, unsigned int flags)
|
||||
{
|
||||
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
|
||||
index 52d1c4a..e909e9c 100644
|
||||
--- a/ldap/servers/slapd/slapi-private.h
|
||||
+++ b/ldap/servers/slapd/slapi-private.h
|
||||
@@ -166,6 +166,7 @@ time_t csn_get_time(const CSN *csn);
|
||||
PRUint16 csn_get_seqnum(const CSN *csn);
|
||||
PRUint16 csn_get_subseqnum(const CSN *csn);
|
||||
char *csn_as_string(const CSN *csn, PRBool replicaIdOrder, char *ss); /* WARNING: ss must be CSN_STRSIZE bytes, or NULL. */
|
||||
+int csn_is_equal(const CSN *csn1, const CSN *csn2);
|
||||
int csn_compare(const CSN *csn1, const CSN *csn2);
|
||||
int csn_compare_ext(const CSN *csn1, const CSN *csn2, unsigned int flags);
|
||||
#define CSN_COMPARE_SKIP_SUBSEQ 0x1
|
||||
@@ -181,6 +182,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);
|
||||
/*
|
||||
* csnset.c
|
||||
*/
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
From 0085cfb4c4ff6722898e97704a67dcdfcba53388 Mon Sep 17 00:00:00 2001
|
||||
From: Noriko Hosoi <nhosoi@redhat.com>
|
||||
Date: Wed, 25 Jan 2017 13:39:08 -0800
|
||||
Subject: [PATCH 65/67] Ticket 49008 backport 1.3.5 : aborted operation can
|
||||
leave RUV in incorrect state
|
||||
|
||||
Description: Fixed 2 backport errors in commit 79a3deafe943a3ce5c31c50272939146d17bd7ac.
|
||||
(cherry picked from commit 3fa6596bdc677cdb3fb65b7baf6fd567485c91a7)
|
||||
---
|
||||
ldap/servers/plugins/replication/csnpl.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ldap/servers/plugins/replication/csnpl.c b/ldap/servers/plugins/replication/csnpl.c
|
||||
index db1ae13..a696fc1 100644
|
||||
--- a/ldap/servers/plugins/replication/csnpl.c
|
||||
+++ b/ldap/servers/plugins/replication/csnpl.c
|
||||
@@ -220,14 +220,14 @@ int csnplCommitAll (CSNPL *csnpl, const CSN *csn)
|
||||
char csn_str[CSN_STRSIZE];
|
||||
|
||||
csn_as_string(csn, PR_FALSE, csn_str);
|
||||
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
||||
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
|
||||
"csnplCommitALL: committing all csns for csn %s\n", csn_str);
|
||||
slapi_rwlock_wrlock (csnpl->csnLock);
|
||||
data = (csnpldata *)llistGetFirst(csnpl->csnList, &iterator);
|
||||
while (NULL != data)
|
||||
{
|
||||
csn_as_string(data->csn, PR_FALSE, csn_str);
|
||||
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
||||
+ slapi_log_error(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)) {
|
||||
--
|
||||
2.9.3
|
||||
|
207
SOURCES/0066-Ticket-49079-deadlock-on-cos-cache-rebuild.patch
Normal file
207
SOURCES/0066-Ticket-49079-deadlock-on-cos-cache-rebuild.patch
Normal file
|
@ -0,0 +1,207 @@
|
|||
From 5391c666e58af5841eab88c98505f99c8ed20d6b Mon Sep 17 00:00:00 2001
|
||||
From: Thierry Bordaz <tbordaz@redhat.com>
|
||||
Date: Tue, 10 Jan 2017 14:32:53 +0100
|
||||
Subject: [PATCH 66/67] Ticket 49079: deadlock on cos cache rebuild
|
||||
|
||||
Bug Description:
|
||||
To rebuild the cache cos_cache_creation the thread gets cos definitions from backend.
|
||||
It means change_lock is held then cos_cache_creation will acquire some backend pages.
|
||||
|
||||
A deadlock can happen if cos_post_op is called while backend is locked.
|
||||
For example if a bepreop (urp) does an internal update on a cos definition.
|
||||
Then the thread holds backend pages, that will be needed by cos_cache_creation,
|
||||
and will acquire change_lock for notification of the cos_cache thread
|
||||
|
||||
Fix Description:
|
||||
|
||||
Let cos cache rebuild thread run without holding change_lock.
|
||||
The lock prevents parallel run but a flag can do the same.
|
||||
|
||||
https://fedorahosted.org/389/ticket/49079
|
||||
|
||||
Reviewed by: William Brown and Ludwig Krispenz (thanks to you both !!)
|
||||
|
||||
Platforms tested: F23
|
||||
|
||||
Flag Day: no
|
||||
|
||||
Doc impact: no
|
||||
|
||||
(cherry picked from commit ac44337bd97fe63071e7d83e9dcd788f2af1feab)
|
||||
(cherry picked from commit 3ac12cb94a8873b0fa4ddb12f924cc58bd9c9872)
|
||||
---
|
||||
ldap/servers/plugins/cos/cos_cache.c | 73 ++++++++++++++++++++++++++++++------
|
||||
1 file changed, 61 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/ldap/servers/plugins/cos/cos_cache.c b/ldap/servers/plugins/cos/cos_cache.c
|
||||
index 8a32630..87b4ba5 100644
|
||||
--- a/ldap/servers/plugins/cos/cos_cache.c
|
||||
+++ b/ldap/servers/plugins/cos/cos_cache.c
|
||||
@@ -111,7 +111,9 @@ void * cos_get_plugin_identity();
|
||||
/* the global plugin handle */
|
||||
static volatile vattr_sp_handle *vattr_handle = NULL;
|
||||
|
||||
+/* both variables are protected by change_lock */
|
||||
static int cos_cache_notify_flag = 0;
|
||||
+static PRBool cos_cache_at_work = PR_FALSE;
|
||||
|
||||
/* service definition cache structs */
|
||||
|
||||
@@ -199,7 +201,8 @@ typedef struct _cos_cache cosCache;
|
||||
static cosCache *pCache; /* always the current global cache, only use getref to get */
|
||||
|
||||
/* the place to start if you want a new cache */
|
||||
-static int cos_cache_create();
|
||||
+static int cos_cache_create_unlock(void);
|
||||
+static int cos_cache_creation_lock(void);
|
||||
|
||||
/* cache index related functions */
|
||||
static int cos_cache_index_all(cosCache *pCache);
|
||||
@@ -386,7 +389,7 @@ static void cos_cache_wait_on_change(void *arg)
|
||||
pCache = 0;
|
||||
|
||||
/* create initial cache */
|
||||
- cos_cache_create();
|
||||
+ cos_cache_creation_lock();
|
||||
|
||||
slapi_lock_mutex(start_lock);
|
||||
started = 1;
|
||||
@@ -419,7 +422,7 @@ static void cos_cache_wait_on_change(void *arg)
|
||||
* before we go running off doing lots of stuff lets check if we should stop
|
||||
*/
|
||||
if(keeprunning) {
|
||||
- cos_cache_create();
|
||||
+ cos_cache_creation_lock();
|
||||
}
|
||||
cos_cache_notify_flag = 0; /* Dealt with it */
|
||||
}/* while */
|
||||
@@ -431,22 +434,25 @@ static void cos_cache_wait_on_change(void *arg)
|
||||
LDAPDebug( LDAP_DEBUG_TRACE, "<-- cos_cache_wait_on_change thread exit\n",0,0,0);
|
||||
}
|
||||
|
||||
+
|
||||
/*
|
||||
- cos_cache_create
|
||||
+ cos_cache_create_unlock
|
||||
---------------------
|
||||
Walks the definitions in the DIT and creates the cache.
|
||||
Once created, it swaps the new cache for the old one,
|
||||
releasing its refcount to the old cache and allowing it
|
||||
to be destroyed.
|
||||
+
|
||||
+ called while change_lock is NOT held
|
||||
*/
|
||||
-static int cos_cache_create()
|
||||
+static int cos_cache_create_unlock(void)
|
||||
{
|
||||
int ret = -1;
|
||||
cosCache *pNewCache;
|
||||
static int firstTime = 1;
|
||||
int cache_built = 0;
|
||||
|
||||
- LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_cache_create\n",0,0,0);
|
||||
+ LDAPDebug( LDAP_DEBUG_TRACE, "--> cos_cache_create_unlock\n",0,0,0);
|
||||
|
||||
pNewCache = (cosCache*)slapi_ch_malloc(sizeof(cosCache));
|
||||
if(pNewCache)
|
||||
@@ -509,21 +515,21 @@ static int cos_cache_create()
|
||||
{
|
||||
/* we should not go on without proper schema checking */
|
||||
cos_cache_release(pNewCache);
|
||||
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_create: failed to cache the schema\n",0,0,0);
|
||||
+ LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_create_unlock: failed to cache the schema\n",0,0,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* currently we cannot go on without the indexes */
|
||||
cos_cache_release(pNewCache);
|
||||
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_create: failed to index cache\n",0,0,0);
|
||||
+ LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_create_unlock: failed to index cache\n",0,0,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(firstTime)
|
||||
{
|
||||
- LDAPDebug( LDAP_DEBUG_PLUGIN, "cos_cache_create: cos disabled\n",0,0,0);
|
||||
+ LDAPDebug( LDAP_DEBUG_PLUGIN, "cos_cache_create_unlock: cos disabled\n",0,0,0);
|
||||
firstTime = 0;
|
||||
}
|
||||
|
||||
@@ -531,7 +537,7 @@ static int cos_cache_create()
|
||||
}
|
||||
}
|
||||
else
|
||||
- LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_create: memory allocation failure\n",0,0,0);
|
||||
+ LDAPDebug( LDAP_DEBUG_ANY, "cos_cache_create_unlock: memory allocation failure\n",0,0,0);
|
||||
|
||||
|
||||
/* make sure we have a new cache */
|
||||
@@ -563,10 +569,53 @@ static int cos_cache_create()
|
||||
|
||||
}
|
||||
|
||||
- LDAPDebug( LDAP_DEBUG_TRACE, "<-- cos_cache_create\n",0,0,0);
|
||||
+ LDAPDebug( LDAP_DEBUG_TRACE, "<-- cos_cache_create_unlock\n",0,0,0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* cos_cache_creation_lock is called with change_lock being hold:
|
||||
+ * slapi_lock_mutex(change_lock)
|
||||
+ *
|
||||
+ * To rebuild the cache cos_cache_creation gets cos definitions from backend, that
|
||||
+ * means change_lock is held then cos_cache_creation will acquire some backend pages.
|
||||
+ *
|
||||
+ * A deadlock can happen if cos_post_op is called while backend is locked.
|
||||
+ * For example if a bepreop (urp) does an internal update on a cos definition,
|
||||
+ * the thread holds backend pages that will be needed by cos_cache_creation.
|
||||
+ *
|
||||
+ * A solution is to use a flag 'cos_cache_at_work' protected by change_lock,
|
||||
+ * release change_lock, recreate the cos_cache, acquire change_lock reset the flag.
|
||||
+ *
|
||||
+ * returned value: result of cos_cache_create_unlock
|
||||
+ *
|
||||
+ */
|
||||
+static int cos_cache_creation_lock(void)
|
||||
+{
|
||||
+ int ret = -1;
|
||||
+ int max_tries = 10;
|
||||
+
|
||||
+ for (; max_tries != 0; max_tries--) {
|
||||
+ /* if the cos_cache is already under work (cos_cache_create_unlock)
|
||||
+ * wait 1 second
|
||||
+ */
|
||||
+ if (cos_cache_at_work) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_creation_lock already rebuilding cos_cache... retry\n");
|
||||
+ DS_Sleep (PR_MillisecondsToInterval(1000));
|
||||
+ continue;
|
||||
+ }
|
||||
+ cos_cache_at_work = PR_TRUE;
|
||||
+ slapi_unlock_mutex(change_lock);
|
||||
+ ret = cos_cache_create_unlock();
|
||||
+ slapi_lock_mutex(change_lock);
|
||||
+ cos_cache_at_work = PR_FALSE;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (!max_tries) {
|
||||
+ slapi_log_error(SLAPI_LOG_FATAL, COS_PLUGIN_SUBSYSTEM, "--> cos_cache_creation_lock rebuilt was to long, skip this rebuild\n");
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
|
||||
/*
|
||||
cos_cache_build_definition_list
|
||||
@@ -1639,7 +1688,7 @@ int cos_cache_getref(cos_cache **pptheCache)
|
||||
slapi_lock_mutex(change_lock);
|
||||
if(pCache == NULL)
|
||||
{
|
||||
- if(cos_cache_create())
|
||||
+ if(cos_cache_creation_lock())
|
||||
{
|
||||
/* there was a problem or no COS definitions were found */
|
||||
LDAPDebug( LDAP_DEBUG_PLUGIN, "cos_cache_getref: no cos cache created\n",0,0,0);
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
From 451838933f9989d1ff9c46dbb3cae7619166a4d8 Mon Sep 17 00:00:00 2001
|
||||
From: Thierry Bordaz <tbordaz@redhat.com>
|
||||
Date: Fri, 21 Oct 2016 16:28:59 +0200
|
||||
Subject: [PATCH 67/67] Ticket 49016 - (un)register/migration/remove may fail
|
||||
if there is no suffix on 'userRoot' backend
|
||||
|
||||
Bug Description:
|
||||
If an instance has no suffix on 'userRoot' backend, then the info structure
|
||||
may contain empty 'Suffix'.
|
||||
In fact if the last backend has no suffix (like cn=config), it overwite all
|
||||
previsously found value.
|
||||
This affect register (and possibly unregister/migrate/remove)
|
||||
|
||||
Fix Description:
|
||||
Before overwriting the 'Suffix' value, check that the found backend contains
|
||||
'nsslapd-suffix'.
|
||||
|
||||
https://fedorahosted.org/389/ticket/49016
|
||||
|
||||
Reviewed by: Noriko Hosoi (Thank you Noriko)
|
||||
|
||||
Platforms tested: RHEL 7.2
|
||||
|
||||
Flag Day: no
|
||||
|
||||
Doc impact: no
|
||||
|
||||
(cherry picked from commit 1bafab5ae1e894ae3680679e03e457b9ace7e7d2)
|
||||
---
|
||||
ldap/admin/src/scripts/DSUtil.pm.in | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in
|
||||
index 756d6ea..eac59a3 100644
|
||||
--- a/ldap/admin/src/scripts/DSUtil.pm.in
|
||||
+++ b/ldap/admin/src/scripts/DSUtil.pm.in
|
||||
@@ -975,7 +975,9 @@ sub createInfFromConfig {
|
||||
}
|
||||
# use the userRoot suffix if available
|
||||
while ($ent) {
|
||||
- $suffix = $ent->getValues('nsslapd-suffix');
|
||||
+ if ($ent->getValues('nsslapd-suffix')) {
|
||||
+ $suffix = $ent->getValues('nsslapd-suffix');
|
||||
+ }
|
||||
last if ($ent->hasValue('cn', 'userRoot', 1));
|
||||
$ent = $conn->nextEntry();
|
||||
}
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
From 99a0def5c6b9910616d95ee7cd15ecad5b406951 Mon Sep 17 00:00:00 2001
|
||||
From: Thierry Bordaz <tbordaz@redhat.com>
|
||||
Date: Mon, 30 Jan 2017 17:38:01 +0100
|
||||
Subject: [PATCH] Ticket 49016 - (un)register/migration/remove may fail if
|
||||
there is no suffix on 'userRoot' backend
|
||||
|
||||
Bug Description:
|
||||
Previous fix was incomplete in case none of the backend entries have
|
||||
'nsslapd-suffix' value
|
||||
|
||||
Fix Description:
|
||||
|
||||
Just return if $suffix keep unmodified
|
||||
|
||||
https://fedorahosted.org/389/ticket/49016
|
||||
|
||||
Reviewed by: nhosoi
|
||||
|
||||
Platforms tested: F23, F25
|
||||
|
||||
Flag Day: no
|
||||
|
||||
Doc impact: no
|
||||
|
||||
(cherry picked from commit bd5fdfc8f4a560eae99672b712235c1260ee42b0)
|
||||
(cherry picked from commit 1abb0ffb2930d019f58d5dac1937ddbb56c9287f)
|
||||
---
|
||||
ldap/admin/src/scripts/DSUtil.pm.in | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ldap/admin/src/scripts/DSUtil.pm.in b/ldap/admin/src/scripts/DSUtil.pm.in
|
||||
index eac59a3..c8eb14d 100644
|
||||
--- a/ldap/admin/src/scripts/DSUtil.pm.in
|
||||
+++ b/ldap/admin/src/scripts/DSUtil.pm.in
|
||||
@@ -965,7 +965,7 @@ sub createInfFromConfig {
|
||||
$inf->{slapd}->{ServerPort} = $ent->getValues('nsslapd-port');
|
||||
$inf->{slapd}->{ServerIdentifier} = $id;
|
||||
|
||||
- my $suffix;
|
||||
+ my $suffix = "";
|
||||
$ent = $conn->search("cn=ldbm database,cn=plugins,cn=config",
|
||||
"one", "(objectclass=*)");
|
||||
if (!$ent) {
|
||||
@@ -981,6 +981,12 @@ sub createInfFromConfig {
|
||||
last if ($ent->hasValue('cn', 'userRoot', 1));
|
||||
$ent = $conn->nextEntry();
|
||||
}
|
||||
+ if ( "" eq "$suffix" )
|
||||
+ {
|
||||
+ push @{$errs}, "error_opening_dseldif", $fname, $!;
|
||||
+ $conn->close();
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
# we also need the instance dir
|
||||
$ent = $conn->search("cn=config", "base", "(objectclass=*)");
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
From 7a5d77d8a65d65ed7c5fa94abf952669993f45c2 Mon Sep 17 00:00:00 2001
|
||||
From: Ludwig Krispenz <lkrispen@redhat.com>
|
||||
Date: Tue, 7 Feb 2017 17:02:00 +0100
|
||||
Subject: [PATCH] fix for reg in 49008, check if ruv element exists
|
||||
|
||||
(cherry picked from commit 23d98baa8aadab80691680ba065563ad1e35591c)
|
||||
---
|
||||
ldap/servers/plugins/replication/repl5_ruv.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
|
||||
index c2d3bb4..5086313 100644
|
||||
--- a/ldap/servers/plugins/replication/repl5_ruv.c
|
||||
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
|
||||
@@ -1703,8 +1703,14 @@ int ruv_cancel_csn_inprogress (RUV *ruv, const CSN *csn, ReplicaId local_rid)
|
||||
replica = ruvGetReplica (ruv, prim_rid);
|
||||
rc = csnplRemoveAll (replica->csnpl, prim_csn);
|
||||
if (prim_rid != local_rid) {
|
||||
- replica = ruvGetReplica (ruv, local_rid);
|
||||
- rc = csnplRemoveAll (replica->csnpl, prim_csn);
|
||||
+ if( local_rid != READ_ONLY_REPLICA_ID) {
|
||||
+ replica = ruvGetReplica (ruv, local_rid);
|
||||
+ if (replica) {
|
||||
+ rc = csnplRemoveAll (replica->csnpl, prim_csn);
|
||||
+ } else {
|
||||
+ rc = RUV_NOTFOUND;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
rc = csnplRemove (replica->csnpl, csn);
|
||||
--
|
||||
2.7.4
|
||||
|
|
@ -34,9 +34,9 @@
|
|||
Summary: 389 Directory Server (base)
|
||||
Name: 389-ds-base
|
||||
Version: 1.3.5.10
|
||||
Release: %{?relprefix}15%{?prerel}%{?dist}
|
||||
Release: %{?relprefix}18%{?prerel}%{?dist}
|
||||
License: GPLv3+
|
||||
URL: https://port389.org/
|
||||
URL: https://www.port389.org/
|
||||
Group: System Environment/Daemons
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
Obsoletes: %{name}-selinux
|
||||
|
@ -196,6 +196,15 @@ Patch57: 0057-Ticket-49020-do-not-treat-missing-csn-as-fatal.patch
|
|||
Patch58: 0058-Ticket-48964-cleanallruv-changelog-purging-removes-w.patch
|
||||
Patch59: 0059-Ticket-48964-should-not-free-repl-name-after-purging.patch
|
||||
Patch60: 0060-Ticket-49074-incompatible-nsEncryptionConfig-object-.patch
|
||||
Patch61: 0061-Ticket-49080-shadowExpire-should-not-be-a-calculated.patch
|
||||
Patch62: 0062-Ticket-49082-Fix-password-expiration-related-shadow-.patch
|
||||
Patch63: 0063-Ticket-49082-Adjusted-the-CI-test-case-to-the-fix.patch
|
||||
Patch64: 0064-Ticket-49008-backport-1.3.5-aborted-operation-can-le.patch
|
||||
Patch65: 0065-Ticket-49008-backport-1.3.5-aborted-operation-can-le.patch
|
||||
Patch66: 0066-Ticket-49079-deadlock-on-cos-cache-rebuild.patch
|
||||
Patch67: 0067-Ticket-49016-un-register-migration-remove-may-fail-i.patch
|
||||
Patch68: 0068-Ticket-49016-un-register-migration-remove-may-fail-i.patch
|
||||
Patch69: 0069-fix-for-reg-in-49008-check-if-ruv-element-exists.patch
|
||||
|
||||
%description
|
||||
389 Directory Server is an LDAPv3 compliant server. The base package includes
|
||||
|
@ -342,6 +351,15 @@ cp %{SOURCE2} README.devel
|
|||
%patch58 -p1
|
||||
%patch59 -p1
|
||||
%patch60 -p1
|
||||
%patch61 -p1
|
||||
%patch62 -p1
|
||||
%patch63 -p1
|
||||
%patch64 -p1
|
||||
%patch65 -p1
|
||||
%patch66 -p1
|
||||
%patch67 -p1
|
||||
%patch68 -p1
|
||||
%patch69 -p1
|
||||
|
||||
%build
|
||||
%if %{use_nunc_stans}
|
||||
|
@ -579,6 +597,21 @@ fi
|
|||
%{_sysconfdir}/%{pkgname}/dirsrvtests
|
||||
|
||||
%changelog
|
||||
* Thu Feb 16 2017 Mark Reynolds <mreynolds@redhat.com> - 1.3.5.10-18
|
||||
- Release 1.3.5.10-18
|
||||
- Resolves: bug 1387340 - Aborted operation can leave RUV in incorrect state
|
||||
|
||||
* Tue Jan 31 2017 Noriko Hosoi <nhosoi@redhat.com> - 1.3.5.10-17
|
||||
- Release 1.3.5.10-17
|
||||
- Resolves: bug 1414677 - (un)register/migration/remove may fail if there is no suffix (DS 49016)
|
||||
|
||||
* Wed Jan 25 2017 Noriko Hosoi <nhosoi@redhat.com> - 1.3.5.10-16
|
||||
- Release 1.3.5.10-16
|
||||
- Resolves: bug 1414677 - (un)register/migration/remove may fail if there is no suffix (DS 49016)
|
||||
- Resolves: bug 1414678 - deadlock on cos cache rebuild (DS 49079)
|
||||
- Resolves: bug 1414679 - Release 1.3.5 may allow expired accounts access to systems (DS 49080, DS 49082)
|
||||
- Resolves: bug 1416368 - Aborted operation can leave RUV in incorrect state (DS 49008)
|
||||
|
||||
* Wed Jan 4 2017 Noriko Hosoi <nhosoi@redhat.com> - 1.3.5.10-15
|
||||
- Release 1.3.5.10-15
|
||||
- Resolves: bug 1402325 - do not treat missing csn as fatal (DS 48964)
|
||||
|
|
Loading…
Add table
Reference in a new issue