From 2b39a26150e2c15eb269284bcf33f08e1c6267e2 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 9 Jan 2006 09:14:53 +0000 Subject: [PATCH] ITS#4315 fix bind concurrency issue --- servers/slapd/back-ldap/back-ldap.h | 8 ++++++- servers/slapd/back-ldap/bind.c | 34 ++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 5e243bc3d6..f994fd116b 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -59,6 +59,7 @@ typedef struct ldapconn_t { #define LDAP_BACK_FCONN_ISBMASK (LDAP_BACK_FCONN_ISBOUND|LDAP_BACK_FCONN_ISANON) #define LDAP_BACK_FCONN_ISPRIV (0x04) #define LDAP_BACK_FCONN_ISTLS (0x08) +#define LDAP_BACK_FCONN_BINDING (0x10) #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) @@ -76,6 +77,9 @@ typedef struct ldapconn_t { #define LDAP_BACK_CONN_ISTLS_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISTLS) #define LDAP_BACK_CONN_ISTLS_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISTLS) #define LDAP_BACK_CONN_ISTLS_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISTLS, (mlc)) +#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) unsigned lc_refcnt; unsigned lc_flags; @@ -193,7 +197,9 @@ typedef enum ldap_back_send_t { LDAP_BACK_DONTSEND = 0x00, LDAP_BACK_SENDOK = 0x01, LDAP_BACK_SENDERR = 0x02, - LDAP_BACK_SENDRESULT = (LDAP_BACK_SENDOK|LDAP_BACK_SENDERR) + LDAP_BACK_SENDRESULT = (LDAP_BACK_SENDOK|LDAP_BACK_SENDERR), + LDAP_BACK_BINDING = 0x04, + LDAP_BACK_BIND_SERR = (LDAP_BACK_BINDING|LDAP_BACK_SENDERR) } ldap_back_send_t; /* define to use asynchronous StartTLS */ diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index cadcaa8b05..8083428730 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -56,7 +56,7 @@ ldap_back_bind( Operation *op, SlapReply *rs ) int rc = 0; ber_int_t msgid; - lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); + lc = ldap_back_getconn( op, rs, LDAP_BACK_BIND_SERR ); if ( !lc ) { return rs->sr_err; } @@ -489,21 +489,35 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok ) } } - /* Searches for a ldapconn in the avl tree */ - ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); + /* Explicit Bind requests always get their own conn */ + if ( sendok & LDAP_BACK_BINDING ) { + lc = NULL; + } else { + /* Searches for a ldapconn in the avl tree */ +retry_lock: + ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); - lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, - (caddr_t)&lc_curr, ldap_back_conn_cmp ); - if ( lc != NULL ) { - refcnt = ++lc->lc_refcnt; + lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, + (caddr_t)&lc_curr, ldap_back_conn_cmp ); + if ( lc != NULL ) { + refcnt = ++lc->lc_refcnt; + /* Don't reuse connections while they're still binding */ + if ( LDAP_BACK_CONN_BINDING( lc )) { + ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); + ldap_pvt_thread_yield(); + goto retry_lock; + } + } + ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } - ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); /* Looks like we didn't get a bind. Open a new session... */ if ( lc == NULL ) { if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) { return NULL; } + if ( sendok & LDAP_BACK_BINDING ) + LDAP_BACK_CONN_BINDING_SET( lc ); lc->lc_conn = lc_curr.lc_conn; ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn ); @@ -618,6 +632,7 @@ ldap_back_release_conn( ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); assert( lc->lc_refcnt > 0 ); lc->lc_refcnt--; + LDAP_BACK_CONN_BINDING_CLEAR( lc ); ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } @@ -650,6 +665,9 @@ ldap_back_dobind_int( return rc; } + while ( lc->lc_refcnt > 1 ) + ldap_pvt_thread_yield(); + /* * FIXME: we need to let clients use proxyAuthz * otherwise we cannot do symmetric pools of servers; -- 2.39.5