ITS#10164 back-meta hangs when used with dynlist overlay

Make sure every proxied operation has a separate candidates structure.
This commit is contained in:
Nadezhda Ivanova 2024-02-07 16:35:48 +02:00 committed by Quanah Gibson-Mount
parent aedc51888a
commit 493e991ebc
10 changed files with 67 additions and 95 deletions

View File

@ -47,15 +47,17 @@ meta_back_add( Operation *op, SlapReply *rs )
int msgid;
ldap_back_send_t retrying = LDAP_BACK_RETRYING;
LDAPControl **ctrls = NULL;
SlapReply *candidates = NULL;
Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
op->o_req_dn.bv_val );
/*
* get the current connection
*/
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
candidates = meta_back_candidates_get( op );
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}
@ -181,7 +183,7 @@ retry:;
mt->mt_timeout[ SLAP_OP_ADD ], ( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
/* if the identity changed, there might be need to re-authz */
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
goto retry;
@ -205,7 +207,7 @@ done:;
if ( mc ) {
meta_back_release_conn( mi, mc );
}
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}

View File

@ -489,7 +489,8 @@ meta_back_getconn(
Operation *op,
SlapReply *rs,
int *candidate,
ldap_back_send_t sendok );
ldap_back_send_t sendok,
SlapReply *candidates );
extern void
meta_back_release_conn_lock(
@ -504,7 +505,8 @@ meta_back_retry(
SlapReply *rs,
metaconn_t **mcp,
int candidate,
ldap_back_send_t sendok );
ldap_back_send_t sendok,
SlapReply *candidates );
extern void
meta_back_conn_free(
@ -538,7 +540,8 @@ meta_back_dobind(
Operation *op,
SlapReply *rs,
metaconn_t *mc,
ldap_back_send_t sendok );
ldap_back_send_t sendok,
SlapReply *candidates );
extern int
meta_back_single_dobind(
@ -625,7 +628,8 @@ meta_back_select_unique_candidate(
extern int
meta_clear_unused_candidates(
Operation *op,
int candidate );
int candidate,
SlapReply *candidates );
extern int
meta_clear_one_candidate(

View File

@ -89,10 +89,11 @@ meta_back_bind( Operation *op, SlapReply *rs )
return rs->sr_err;
}
candidates = meta_back_candidates_get( op );
/* we need meta_back_getconn() not send result even on error,
* because we want to intercept the error and make it
* invalidCredentials */
mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_BIND_DONTSEND );
mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_BIND_DONTSEND, candidates );
if ( !mc ) {
Debug(LDAP_DEBUG_ANY,
"%s meta_back_bind: no target " "for dn \"%s\" (%d%s%s).\n",
@ -110,11 +111,10 @@ meta_back_bind( Operation *op, SlapReply *rs )
break;
}
send_ldap_result( op, rs );
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}
candidates = meta_back_candidates_get( op );
/*
* Each target is scanned ...
*/
@ -284,10 +284,12 @@ meta_back_bind( Operation *op, SlapReply *rs )
rs->sr_err = slap_map_api2result( rs );
}
send_ldap_result( op, rs );
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}
op->o_tmpfree( candidates, op->o_tmpmemctx );
return LDAP_SUCCESS;
}
@ -672,7 +674,8 @@ meta_back_dobind(
Operation *op,
SlapReply *rs,
metaconn_t *mc,
ldap_back_send_t sendok )
ldap_back_send_t sendok,
SlapReply *candidates )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
@ -680,8 +683,6 @@ meta_back_dobind(
i,
isroot = 0;
SlapReply *candidates;
if ( be_isroot( op ) ) {
isroot = 1;
}
@ -704,8 +705,6 @@ meta_back_dobind(
goto done;
}
candidates = meta_back_candidates_get( op );
for ( i = 0; i < mi->mi_ntargets; i++ ) {
metatarget_t *mt = mi->mi_targets[ i ];
metasingleconn_t *msc = &mc->mc_conns[ i ];
@ -761,7 +760,7 @@ retry_binding:;
if ( rc == LDAP_UNAVAILABLE ) {
/* FIXME: meta_back_retry() already re-calls
* meta_back_single_dobind() */
if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
if ( meta_back_retry( op, rs, &mc, i, sendok, candidates ) ) {
goto retry_ok;
}

View File

@ -222,11 +222,11 @@ meta_back_select_unique_candidate(
int
meta_clear_unused_candidates(
Operation *op,
int candidate )
int candidate,
SlapReply *candidates )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
int i;
SlapReply *candidates = meta_back_candidates_get( op );
for ( i = 0; i < mi->mi_ntargets; ++i ) {
if ( i == candidate ) {

View File

@ -46,9 +46,12 @@ meta_back_compare( Operation *op, SlapReply *rs )
int msgid;
ldap_back_send_t retrying = LDAP_BACK_RETRYING;
LDAPControl **ctrls = NULL;
SlapReply *candidates = NULL;
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
candidates = meta_back_candidates_get( op );
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}
@ -127,7 +130,7 @@ retry:;
mt->mt_timeout[ SLAP_OP_COMPARE ], ( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
/* if the identity changed, there might be need to re-authz */
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
goto retry;
@ -149,6 +152,7 @@ cleanup:;
meta_back_release_conn( mi, mc );
}
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}

View File

@ -699,7 +699,8 @@ meta_back_retry(
SlapReply *rs,
metaconn_t **mcp,
int candidate,
ldap_back_send_t sendok )
ldap_back_send_t sendok,
SlapReply *candidates )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metatarget_t *mt = mi->mi_targets[ candidate ];
@ -971,64 +972,14 @@ meta_back_get_candidate(
return candidate;
}
static void *meta_back_candidates_dummy;
static void
meta_back_candidates_keyfree(
void *key,
void *data )
{
metacandidates_t *mc = (metacandidates_t *)data;
ber_memfree_x( mc->mc_candidates, NULL );
ber_memfree_x( data, NULL );
}
SlapReply *
meta_back_candidates_get( Operation *op )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metacandidates_t *mc;
SlapReply *candidates;
if ( op->o_threadctx ) {
void *data = NULL;
ldap_pvt_thread_pool_getkey( op->o_threadctx,
&meta_back_candidates_dummy, &data, NULL );
mc = (metacandidates_t *)data;
} else {
mc = mi->mi_candidates;
}
if ( mc == NULL ) {
mc = ch_calloc( sizeof( metacandidates_t ), 1 );
mc->mc_ntargets = mi->mi_ntargets;
mc->mc_candidates = ch_calloc( sizeof( SlapReply ), mc->mc_ntargets );
if ( op->o_threadctx ) {
void *data = NULL;
data = (void *)mc;
ldap_pvt_thread_pool_setkey( op->o_threadctx,
&meta_back_candidates_dummy, data,
meta_back_candidates_keyfree,
NULL, NULL );
} else {
mi->mi_candidates = mc;
}
} else if ( mc->mc_ntargets < mi->mi_ntargets ) {
/* NOTE: in the future, may want to allow back-config
* to add/remove targets from back-meta... */
mc->mc_candidates = ch_realloc( mc->mc_candidates,
sizeof( SlapReply ) * mi->mi_ntargets );
memset( &mc->mc_candidates[ mc->mc_ntargets ], 0,
sizeof( SlapReply ) * ( mi->mi_ntargets - mc->mc_ntargets ) );
mc->mc_ntargets = mi->mi_ntargets;
}
return mc->mc_candidates;
candidates = op->o_tmpcalloc( mi->mi_ntargets, sizeof( SlapReply ), op->o_tmpmemctx );
return candidates;
}
/*
@ -1066,10 +1017,11 @@ meta_back_candidates_get( Operation *op )
*/
metaconn_t *
meta_back_getconn(
Operation *op,
Operation *op,
SlapReply *rs,
int *candidate,
ldap_back_send_t sendok )
ldap_back_send_t sendok,
SlapReply *candidates )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metaconn_t *mc = NULL,
@ -1090,8 +1042,6 @@ meta_back_getconn(
struct berval ndn = op->o_req_ndn,
pndn;
SlapReply *candidates = meta_back_candidates_get( op );
/* Internal searches are privileged and shared. So is root. */
if ( ( !BER_BVISEMPTY( &op->o_ndn ) && META_BACK_PROXYAUTHZ_ALWAYS( mi ) )
|| ( BER_BVISEMPTY( &op->o_ndn ) && META_BACK_PROXYAUTHZ_ANON( mi ) )
@ -1474,7 +1424,7 @@ retry_lock2:;
/*
* Clear all other candidates
*/
( void )meta_clear_unused_candidates( op, i );
( void )meta_clear_unused_candidates( op, i, candidates );
mt = mi->mi_targets[ i ];
msc = &mc->mc_conns[ i ];

View File

@ -43,9 +43,12 @@ meta_back_delete( Operation *op, SlapReply *rs )
int msgid;
ldap_back_send_t retrying = LDAP_BACK_RETRYING;
LDAPControl **ctrls = NULL;
SlapReply *candidates = NULL;
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
candidates = meta_back_candidates_get( op );
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}
@ -79,7 +82,7 @@ retry:;
mt->mt_timeout[ SLAP_OP_DELETE ], ( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
/* if the identity changed, there might be need to re-authz */
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
goto retry;
@ -98,6 +101,7 @@ cleanup:;
meta_back_release_conn( mi, mc );
}
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}

View File

@ -49,9 +49,12 @@ meta_back_modify( Operation *op, SlapReply *rs )
int msgid;
ldap_back_send_t retrying = LDAP_BACK_RETRYING;
LDAPControl **ctrls = NULL;
SlapReply *candidates = NULL;
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
candidates = meta_back_candidates_get( op );
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}
@ -180,7 +183,7 @@ retry:;
mt->mt_timeout[ SLAP_OP_MODIFY ], ( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
/* if the identity changed, there might be need to re-authz */
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
goto retry;
@ -205,6 +208,7 @@ cleanup:;
meta_back_release_conn( mi, mc );
}
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}

View File

@ -45,9 +45,12 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
ldap_back_send_t retrying = LDAP_BACK_RETRYING;
LDAPControl **ctrls = NULL;
struct berval newrdn = BER_BVNULL;
SlapReply *candidates = NULL;
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
candidates = meta_back_candidates_get( op );
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR, candidates );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR, candidates ) ) {
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}
@ -142,7 +145,7 @@ retry:;
mt->mt_timeout[ SLAP_OP_MODRDN ], ( LDAP_BACK_SENDRESULT | retrying ) );
if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
retrying &= ~LDAP_BACK_RETRYING;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR, candidates ) ) {
/* if the identity changed, there might be need to re-authz */
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
goto retry;
@ -172,6 +175,7 @@ cleanup:;
meta_back_release_conn( mi, mc );
}
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}

View File

@ -722,7 +722,7 @@ retry:;
break;
case LDAP_SERVER_DOWN:
if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND, candidates ) ) {
nretries = 0;
/* if the identity changed, there might be need to re-authz */
(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
@ -798,8 +798,9 @@ meta_back_search( Operation *op, SlapReply *rs )
* FIXME: in case of values return filter, we might want
* to map attrs and maybe rewrite value
*/
candidates = meta_back_candidates_get( op );
getconn:;
mc = meta_back_getconn( op, rs, NULL, sendok );
mc = meta_back_getconn( op, rs, NULL, sendok, candidates );
if ( !mc ) {
return rs->sr_err;
}
@ -807,7 +808,6 @@ getconn:;
dc.conn = op->o_conn;
dc.rs = rs;
if ( candidates == NULL ) candidates = meta_back_candidates_get( op );
/*
* Inits searches
*/
@ -1146,7 +1146,7 @@ really_bad:;
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
candidates[ i ].sr_type = REP_RESULT;
if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND, candidates ) ) {
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
{
@ -1997,6 +1997,7 @@ finish:;
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}
op->o_tmpfree( candidates, op->o_tmpmemctx );
return rs->sr_err;
}