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

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