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