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

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