From: Pierangelo Masarati Date: Fri, 7 Apr 2006 01:28:56 +0000 (+0000) Subject: actually, if a connection is already in the AVL tree, use it if not binding; otherwis... X-Git-Tag: OPENLDAP_REL_ENG_2_4_0ALPHA~19 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=8c1b8d3f7b8f84c6ee3bce5e036d954d99840584;p=openldap actually, if a connection is already in the AVL tree, use it if not binding; otherwise use a tainted one; taint connections that must be freed when refcnt goes to zero --- diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index f6c25b2496..8a19a72c05 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -60,6 +60,7 @@ typedef struct ldapconn_t { #define LDAP_BACK_FCONN_ISPRIV (0x04) #define LDAP_BACK_FCONN_ISTLS (0x08) #define LDAP_BACK_FCONN_BINDING (0x10) +#define LDAP_BACK_FCONN_TAINTED (0x20) #define LDAP_BACK_CONN_ISBOUND(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND) #define LDAP_BACK_CONN_ISBOUND_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND) @@ -80,6 +81,9 @@ typedef struct ldapconn_t { #define LDAP_BACK_CONN_BINDING(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_BINDING) #define LDAP_BACK_CONN_BINDING_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_BINDING) #define LDAP_BACK_CONN_BINDING_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_BINDING) +#define LDAP_BACK_CONN_TAINTED(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_TAINTED) +#define LDAP_BACK_CONN_TAINTED_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_TAINTED) +#define LDAP_BACK_CONN_TAINTED_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_TAINTED) unsigned lc_refcnt; unsigned lc_binding; diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index dab6c56b75..cc497ff04c 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -654,12 +654,26 @@ retry_lock: (void *)lc, refcnt, binding ); /* Err could be -1 in case a duplicate ldapconn is inserted */ - if ( rs->sr_err != 0 ) { + switch ( rs->sr_err ) { + case 0: + break; + + case -1: + if ( !( sendok & LDAP_BACK_BINDING ) ) { + /* duplicate: free and try to get the newly created one */ + goto retry_lock; + } + /* taint connection, so that it'll be freed when released */ + LDAP_BACK_CONN_TAINTED_SET( lc ); + break; + + default: ldap_back_conn_free( lc ); rs->sr_err = LDAP_OTHER; + rs->sr_text = "proxy bind collision"; if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { - send_ldap_error( op, rs, LDAP_OTHER, - "internal server error" ); + send_ldap_result( op, rs ); + rs->sr_text = NULL; } return NULL; } @@ -679,6 +693,7 @@ retry_lock: (void *)avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conndnlc_cmp ); ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); + LDAP_BACK_CONN_TAINTED_SET( lc ); } if ( LogTest( LDAP_DEBUG_TRACE ) ) { @@ -688,7 +703,6 @@ retry_lock: Debug( LDAP_DEBUG_TRACE, "=>ldap_back_getconn: %s.\n", buf, 0, 0 ); } - } if ( li->li_idle_timeout && lc ) { @@ -712,8 +726,10 @@ ldap_back_release_conn_lock( ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); } assert( lc->lc_refcnt > 0 ); - lc->lc_refcnt--; LDAP_BACK_CONN_BINDING_CLEAR( lc ); + if ( --lc->lc_refcnt == 0 && LDAP_BACK_CONN_TAINTED( lc ) ) { + ldap_back_freeconn( op, rs, 0 ); + } if ( dolock ) { ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index 9d6eba8ab8..cfb7790d81 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -293,9 +293,8 @@ extern void meta_back_release_conn_lock( Operation *op, metaconn_t *mc, - int dofree, int dolock ); -#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 0, 1 ) +#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 1 ) extern int meta_back_retry( diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index 43f8297378..6a915f9efa 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -616,7 +616,8 @@ done:; rs->sr_err = rc; if ( rc != LDAP_SUCCESS && META_BACK_ONERR_STOP( mi ) ) { LDAP_BACK_CONN_BINDING_CLEAR( msc ); - meta_back_release_conn_lock( op, mc, 1, dolock ); + LDAP_BACK_CONN_TAINTED_SET( mc ); + meta_back_release_conn_lock( op, mc, dolock ); *mcp = NULL; if ( sendok & LDAP_BACK_SENDERR ) { diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 657881ca50..36d85be07f 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -531,7 +531,8 @@ meta_back_retry( if ( binding ) { LDAP_BACK_CONN_BINDING_CLEAR( msc ); } - meta_back_release_conn_lock( op, mc, 1, 0 ); + LDAP_BACK_CONN_TAINTED_SET( mc ); + meta_back_release_conn_lock( op, mc, 0 ); *mcp = NULL; } @@ -810,6 +811,7 @@ retry_lock: /* don't let anyone else use this expired connection */ (void)avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc, meta_back_conndnmc_cmp ); + LDAP_BACK_CONN_TAINTED_SET( mc ); Debug( LDAP_DEBUG_TRACE, "%s meta_back_getconn: mc=%p conn=%ld expired.\n", op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc->mc_conn ) ); @@ -1183,7 +1185,6 @@ done:; } if ( new_conn ) { - if ( mi->mi_conn_ttl ) { mc->mc_create_time = op->o_time; } @@ -1203,19 +1204,29 @@ done:; /* * Err could be -1 in case a duplicate metaconn is inserted - * - * FIXME: what if the same client issues more than one - * asynchronous operations? */ - if ( err != 0 ) { + switch ( err ) { + case 0: + break; + + case -1: + if ( !( sendok & LDAP_BACK_BINDING ) ) { + /* duplicate: free and try to get the newly created one */ + goto retry_lock; + } + LDAP_BACK_CONN_TAINTED_SET( mc ); + break; + + default: Debug( LDAP_DEBUG_ANY, "%s meta_back_getconn: candidates=%d conn=%ld insert failed\n", op->o_log_prefix, ncandidates, LDAP_BACK_PCONN_ID( mc->mc_conn ) ); - rs->sr_err = LDAP_OTHER; - rs->sr_text = "Internal server error"; meta_back_freeconn( op, mc ); + + rs->sr_err = LDAP_OTHER; + rs->sr_text = "proxy bind collision"; if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); rs->sr_text = NULL; @@ -1242,7 +1253,6 @@ void meta_back_release_conn_lock( Operation *op, metaconn_t *mc, - int dofree, int dolock ) { metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; @@ -1255,10 +1265,7 @@ meta_back_release_conn_lock( assert( mc->mc_refcnt > 0 ); mc->mc_refcnt--; LDAP_BACK_CONN_BINDING_CLEAR( mc ); - if ( dofree - || ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl ) - || ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) ) - { + if ( LDAP_BACK_CONN_TAINTED( mc ) ) { Debug( LDAP_DEBUG_TRACE, "%s meta_back_release_conn: mc=%p conn=%ld expired.\n", op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc->mc_conn ) ); (void)avl_delete( &mi->mi_conninfo.lai_tree,