Blame SOURCES/autofs-5.1.6-improve-sss-getautomntbyname-error-handling.patch

63b9c2
autofs-5.1.6 - improve sss getautomntbyname() error handling
63b9c2
63b9c2
From: Ian Kent <raven@themaw.net>
63b9c2
63b9c2
Recent versions of the sss autofs access library will return EHOSTDOWN
63b9c2
if the backend server is down.
63b9c2
63b9c2
The presence of this improvement in error handling is determined by an
63b9c2
added function to get the sss autofs protocol version.
63b9c2
63b9c2
Update the getautomntbyname() function to use this.
63b9c2
63b9c2
Also introduce a wait function so we can wait (for a while) for the host
63b9c2
to come back up.
63b9c2
63b9c2
Signed-off-by: Ian Kent <raven@themaw.net>
63b9c2
---
63b9c2
 CHANGELOG            |    1 
63b9c2
 modules/lookup_sss.c |  106 ++++++++++++++++++++++++++++++++++++++++++++------
63b9c2
 2 files changed, 95 insertions(+), 12 deletions(-)
63b9c2
63b9c2
diff --git a/CHANGELOG b/CHANGELOG
63b9c2
index 8b662d7..309def2 100644
63b9c2
--- a/CHANGELOG
63b9c2
+++ b/CHANGELOG
63b9c2
@@ -107,6 +107,7 @@ xx/xx/2018 autofs-5.1.5
63b9c2
 - sss introduce a flag to indicate map being read.
63b9c2
 - update sss timeout documentation.
63b9c2
 - refactor sss getautomntbyname().
63b9c2
+- improve sss getautomntbyname() error handling.
63b9c2
 
63b9c2
 19/12/2017 autofs-5.1.4
63b9c2
 - fix spec file url.
63b9c2
diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c
63b9c2
index 1a56ea1..70efc11 100644
63b9c2
--- a/modules/lookup_sss.c
63b9c2
+++ b/modules/lookup_sss.c
63b9c2
@@ -566,27 +566,106 @@ free:
63b9c2
 	return err;
63b9c2
 }
63b9c2
 
63b9c2
+static int getautomntbyname_wait(unsigned int logopt,
63b9c2
+			 struct lookup_context *ctxt,
63b9c2
+			 char *key, char **value, void *sss_ctxt,
63b9c2
+			 unsigned int flags)
63b9c2
+{
63b9c2
+	unsigned int retries;
63b9c2
+	unsigned int retry = 0;
63b9c2
+	int ret = 0;
63b9c2
+
63b9c2
+	retries = calculate_retry_count(ctxt, flags);
63b9c2
+	if (retries == 0) {
63b9c2
+		if (proto_version(ctxt) == 0)
63b9c2
+			return EINVAL;
63b9c2
+		return ENOENT;
63b9c2
+	}
63b9c2
+
63b9c2
+	warn(logopt,
63b9c2
+	"can't contact sssd to to lookup key value, retry for %d seconds",
63b9c2
+	retries);
63b9c2
+
63b9c2
+	while (++retry <= retries) {
63b9c2
+		struct timespec t = { SSS_WAIT_INTERVAL, 0 };
63b9c2
+		struct timespec r;
63b9c2
+
63b9c2
+		ret = ctxt->getautomntbyname_r(key, value, sss_ctxt);
63b9c2
+		if (proto_version(ctxt) == 0) {
63b9c2
+			if (ret != ENOENT)
63b9c2
+				break;
63b9c2
+		} else {
63b9c2
+			if (ret != EHOSTDOWN)
63b9c2
+				break;
63b9c2
+		}
63b9c2
+
63b9c2
+		while (nanosleep(&t, &r) == -1 && errno == EINTR)
63b9c2
+			memcpy(&t, &r, sizeof(struct timespec));
63b9c2
+	}
63b9c2
+
63b9c2
+	if (!ret)
63b9c2
+		info(logopt,
63b9c2
+		     "successfully contacted sssd to lookup key value");
63b9c2
+	else {
63b9c2
+		if (proto_version(ctxt) == 0 && retry > retries)
63b9c2
+			ret = ETIMEDOUT;
63b9c2
+	}
63b9c2
+	return ret;
63b9c2
+}
63b9c2
+
63b9c2
 static int getautomntbyname(unsigned int logopt,
63b9c2
 			    struct lookup_context *ctxt,
63b9c2
-			    char *key, char **value, void *sss_ctxt)
63b9c2
+			    char *key, char **value, void *sss_ctxt,
63b9c2
+			    unsigned int flags)
63b9c2
 {
63b9c2
 	char buf[MAX_ERR_BUF];
63b9c2
 	char *estr;
63b9c2
-	int ret = NSS_STATUS_UNAVAIL;
63b9c2
+	int err = NSS_STATUS_UNAVAIL;
63b9c2
+	int ret;
63b9c2
 
63b9c2
 	ret = ctxt->getautomntbyname_r(key, value, sss_ctxt);
63b9c2
 	if (ret) {
63b9c2
 		/* Host has gone down */
63b9c2
 		if (ret == ECONNREFUSED)
63b9c2
-			return NSS_STATUS_UNKNOWN;
63b9c2
-
63b9c2
-		if (ret != ENOENT)
63b9c2
 			goto error;
63b9c2
 
63b9c2
-		ret = NSS_STATUS_NOTFOUND;
63b9c2
-		goto free;
63b9c2
+		if (proto_version(ctxt) == 0) {
63b9c2
+			if (ret != ENOENT)
63b9c2
+				goto error;
63b9c2
+			/* For prorocol version 0 ENOENT can only be
63b9c2
+			 * used to indicate no entry was found. So it
63b9c2
+			 * can't be used to determine if we need to wait
63b9c2
+			 * on sss.
63b9c2
+			 */
63b9c2
+			err = NSS_STATUS_NOTFOUND;
63b9c2
+			goto free;
63b9c2
+		} else {
63b9c2
+			if (ret == ENOENT) {
63b9c2
+				err = NSS_STATUS_NOTFOUND;
63b9c2
+				goto free;
63b9c2
+			}
63b9c2
+			if (ret != EHOSTDOWN)
63b9c2
+				goto error;
63b9c2
+		}
63b9c2
+
63b9c2
+		ret = getautomntbyname_wait(logopt, ctxt,
63b9c2
+					    key, value, sss_ctxt, flags);
63b9c2
+		if (ret) {
63b9c2
+			if (ret == ECONNREFUSED)
63b9c2
+				goto free;
63b9c2
+			if (ret == ETIMEDOUT)
63b9c2
+				goto error;
63b9c2
+			/* sss proto version 0 and sss timeout not set */
63b9c2
+			if (ret == EINVAL)
63b9c2
+				goto free;
63b9c2
+			if (ret == ENOENT) {
63b9c2
+				err = NSS_STATUS_NOTFOUND;
63b9c2
+				goto free;
63b9c2
+			}
63b9c2
+			goto error;
63b9c2
+		}
63b9c2
 	}
63b9c2
-	return ret;
63b9c2
+	return NSS_STATUS_SUCCESS;
63b9c2
 
63b9c2
 error:
63b9c2
 	estr = strerror_r(ret, buf, MAX_ERR_BUF);
63b9c2
@@ -596,7 +675,7 @@ free:
63b9c2
 		free(*value);
63b9c2
 		*value = NULL;
63b9c2
 	}
63b9c2
-	return ret;
63b9c2
+	return err;
63b9c2
 }
63b9c2
 
63b9c2
 int lookup_read_master(struct master *master, time_t age, void *context)
63b9c2
@@ -802,7 +881,8 @@ static int lookup_one(struct autofs_point *ap,
63b9c2
 	if (ret)
63b9c2
 		return ret;
63b9c2
 
63b9c2
-	ret = getautomntbyname(ap->logopt, ctxt, qKey, &value, sss_ctxt);
63b9c2
+	ret = getautomntbyname(ap->logopt, ctxt,
63b9c2
+			       qKey, &value, sss_ctxt, SSS_LOOKUP_KEY);
63b9c2
 	if (ret == NSS_STATUS_NOTFOUND)
63b9c2
 		goto wild;
63b9c2
 	if (ret) {
63b9c2
@@ -829,13 +909,15 @@ static int lookup_one(struct autofs_point *ap,
63b9c2
 	return NSS_STATUS_SUCCESS;
63b9c2
 
63b9c2
 wild:
63b9c2
-	ret = getautomntbyname(ap->logopt, ctxt, "/", &value, sss_ctxt);
63b9c2
+	ret = getautomntbyname(ap->logopt, ctxt,
63b9c2
+			       "/", &value, sss_ctxt, SSS_LOOKUP_KEY);
63b9c2
 	if (ret) {
63b9c2
 		if (ret != NSS_STATUS_NOTFOUND) {
63b9c2
 			endautomntent(ap->logopt, ctxt, &sss_ctxt);
63b9c2
 			return ret;
63b9c2
 		}
63b9c2
-		ret = getautomntbyname(ap->logopt, ctxt, "*", &value, sss_ctxt);
63b9c2
+		ret = getautomntbyname(ap->logopt, ctxt,
63b9c2
+				       "*", &value, sss_ctxt, SSS_LOOKUP_KEY);
63b9c2
 		if (ret && ret != NSS_STATUS_NOTFOUND) {
63b9c2
 			endautomntent(ap->logopt, ctxt, &sss_ctxt);
63b9c2
 			return ret;