autofs-5.0.4 - uris list locking fix
From: Ian Kent <raven@themaw.net>
The ldap uris list doesn't need to change we just need to keep
track of current server uri in the list and try to connect in
a round robin order. Also it's possible multiple concurrent
connection attempts may not be able to use the full list of
servers (if one is present).
---
CHANGELOG | 1 +
include/lookup_ldap.h | 3 +-
modules/lookup_ldap.c | 68 ++++++++++++++++++++++---------------------------
3 files changed, 33 insertions(+), 39 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 3199e4d..b093451 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,7 @@
- clear the quoted flag after each character from program map input.
- use CLOEXEC flag for setmntent also.
- fix hosts map use after free.
+- fix uri list locking (again).
4/11/2008 autofs-5.0.4
-----------------------
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index f9ed778..b47bf5d 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -55,7 +55,8 @@ struct lookup_context {
* given in configuration.
*/
pthread_mutex_t uris_mutex;
- struct list_head *uri;
+ struct list_head *uris;
+ struct ldap_uri *uri;
char *cur_host;
struct ldap_searchdn *sdns;
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 6ba80eb..b6784e1 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -137,7 +137,7 @@ static void uris_mutex_unlock(struct lookup_context *ctxt)
return;
}
-int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
+int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
{
int rv;
@@ -147,16 +147,14 @@ int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt
rv = ldap_simple_bind_s(ldap, NULL, NULL);
if (rv != LDAP_SUCCESS) {
- if (!ctxt->uri) {
+ if (!ctxt->uris) {
crit(logopt, MODPREFIX
"Unable to bind to the LDAP server: "
"%s, error %s", ctxt->server ? "" : "(default)",
ldap_err2string(rv));
} else {
- struct ldap_uri *uri;
- uri = list_entry(ctxt->uri->next, struct ldap_uri, list);
info(logopt, MODPREFIX "Unable to bind to the LDAP server: "
- "%s, error %s", uri->uri, ldap_err2string(rv));
+ "%s, error %s", uri, ldap_err2string(rv));
}
return -1;
}
@@ -498,7 +496,7 @@ static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctx
return 0;
}
-static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
+static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
{
char *host = NULL, *nhost;
int rv, need_base = 1;
@@ -511,11 +509,11 @@ static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
rv = autofs_sasl_bind(logopt, ldap, ctxt);
debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv);
} else {
- rv = bind_ldap_anonymous(logopt, ldap, ctxt);
+ rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
}
#else
- rv = bind_ldap_anonymous(logopt, ldap, ctxt);
+ rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
#endif
@@ -584,7 +582,7 @@ static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context
if (!ldap)
return NULL;
- if (!do_bind(logopt, ldap, ctxt)) {
+ if (!do_bind(logopt, ldap, uri, ctxt)) {
unbind_ldap_connection(logopt, ldap, ctxt);
return NULL;
}
@@ -612,7 +610,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c
return NULL;
}
- if (!do_bind(logopt, ldap, ctxt)) {
+ if (!do_bind(logopt, ldap, uri, ctxt)) {
unbind_ldap_connection(logopt, ldap, ctxt);
autofs_sasl_dispose(ctxt);
error(logopt, MODPREFIX "cannot bind to server");
@@ -638,36 +636,34 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
{
LDAP *ldap = NULL;
struct ldap_uri *this;
- struct list_head *p;
- LIST_HEAD(tmp);
+ struct list_head *p, *first;
/* Try each uri in list, add connect fails to tmp list */
uris_mutex_lock(ctxt);
- p = ctxt->uri->next;
- while(p != ctxt->uri) {
+ if (!ctxt->uri)
+ first = ctxt->uris;
+ else
+ first = &ctxt->uri->list;
+ uris_mutex_unlock(ctxt);
+ p = first->next;
+ while(p != first) {
+ /* Skip list head */
+ if (p == ctxt->uris) {
+ p = p->next;
+ continue;
+ }
this = list_entry(p, struct ldap_uri, list);
- uris_mutex_unlock(ctxt);
debug(logopt, "trying server %s", this->uri);
ldap = connect_to_server(logopt, this->uri, ctxt);
if (ldap) {
info(logopt, "connected to uri %s", this->uri);
uris_mutex_lock(ctxt);
+ ctxt->uri = this;
+ uris_mutex_unlock(ctxt);
break;
}
- uris_mutex_lock(ctxt);
p = p->next;
- list_del_init(&this->list);
- list_add_tail(&this->list, &tmp);
}
- /*
- * Successfuly connected uri (head of list) and untried uris are
- * in ctxt->uri list. Make list of remainder and failed uris with
- * failed uris at end and assign back to ctxt-uri.
- */
- list_splice(ctxt->uri, &tmp);
- INIT_LIST_HEAD(ctxt->uri);
- list_splice(&tmp, ctxt->uri);
- uris_mutex_unlock(ctxt);
return ldap;
}
@@ -677,23 +673,19 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
struct ldap_uri *this;
LDAP *ldap;
- if (ctxt->server || !ctxt->uri) {
+ if (ctxt->server || !ctxt->uris) {
ldap = do_connect(logopt, ctxt->server, ctxt);
return ldap;
}
uris_mutex_lock(ctxt);
- this = list_entry(ctxt->uri->next, struct ldap_uri, list);
+ this = ctxt->uri;
uris_mutex_unlock(ctxt);
ldap = do_connect(logopt, this->uri, ctxt);
if (ldap)
return ldap;
- /* Failed to connect, put at end of list */
- uris_mutex_lock(ctxt);
- list_del_init(&this->list);
- list_add_tail(&this->list, ctxt->uri);
- uris_mutex_unlock(ctxt);
+ /* Failed to connect, try to find a new server */
#ifdef WITH_SASL
autofs_sasl_dispose(ctxt);
@@ -1259,8 +1251,8 @@ static void free_context(struct lookup_context *ctxt)
free(ctxt->cur_host);
if (ctxt->base)
free(ctxt->base);
- if (ctxt->uri)
- defaults_free_uris(ctxt->uri);
+ if (ctxt->uris)
+ defaults_free_uris(ctxt->uris);
ret = pthread_mutex_destroy(&ctxt->uris_mutex);
if (ret)
fatal(ret);
@@ -1344,7 +1336,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
if (uris) {
validate_uris(uris);
if (!list_empty(uris))
- ctxt->uri = uris;
+ ctxt->uris = uris;
else {
error(LOGOPT_ANY,
"no valid uris found in config list"
@@ -1375,7 +1367,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
}
#endif
- if (ctxt->server || !ctxt->uri) {
+ if (ctxt->server || !ctxt->uris) {
ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt);
if (!ldap) {
free_context(ctxt);