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

d702dc
autofs-5.1.6 - improve sss getautomntent() 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 getautomntent() 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 |  126 ++++++++++++++++++++++++++++++++++++++++++++++----
d702dc
 2 files changed, 116 insertions(+), 11 deletions(-)
d702dc
d702dc
diff --git a/CHANGELOG b/CHANGELOG
d702dc
index ecd54e9..434e23d 100644
d702dc
--- a/CHANGELOG
d702dc
+++ b/CHANGELOG
d702dc
@@ -101,6 +101,7 @@ xx/xx/2018 autofs-5.1.5
d702dc
 - refactor sss setautomntent().
d702dc
 - improve sss setautomntent() error handling.
d702dc
 - refactor sss getautomntent().
d702dc
+- improve sss getautomntent() 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 5addd87..f366b48 100644
d702dc
--- a/modules/lookup_sss.c
d702dc
+++ b/modules/lookup_sss.c
d702dc
@@ -377,38 +377,136 @@ static int endautomntent(unsigned int logopt,
d702dc
 	return ret;
d702dc
 }
d702dc
 
d702dc
+static int getautomntent_wait(unsigned int logopt,
d702dc
+			 struct lookup_context *ctxt,
d702dc
+			 char **key, char **value, void *sss_ctxt)
d702dc
+{
d702dc
+	unsigned int retries;
d702dc
+	unsigned int retry = 0;
d702dc
+	int ret = 0;
d702dc
+
d702dc
+	retries = defaults_get_sss_master_map_wait();
d702dc
+
d702dc
+	/* Use the sss_master_map_wait configuration option
d702dc
+	 * for the time to wait when reading a map too. If
d702dc
+	 * it isn't set in the antofs configuration give it
d702dc
+	 * a sensible value since we want to wait for a host
d702dc
+	 * that's down in case it comes back up.
d702dc
+	 */
d702dc
+	if (retries <= 0) {
d702dc
+		/* Protocol version 0 cant't tell us about
d702dc
+		 * a host being down, return not found.
d702dc
+		 */
d702dc
+		if (proto_version(ctxt) == 0)
d702dc
+			return ENOENT;
d702dc
+		retries = 10;
d702dc
+	}
d702dc
+
d702dc
+	warn(logopt,
d702dc
+	 "can't contact sssd to to get map entry, 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->getautomntent_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 get map entry");
d702dc
+	else {
d702dc
+		if (retry == retries)
d702dc
+			ret = ETIMEDOUT;
d702dc
+	}
d702dc
+	return ret;
d702dc
+}
d702dc
+
d702dc
 static int getautomntent(unsigned int logopt,
d702dc
 			 struct lookup_context *ctxt,
d702dc
 			 char **key, char **value, int count, void *sss_ctxt)
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->getautomntent_r(key, value, sss_ctxt);
d702dc
 	if (ret) {
d702dc
 		/* Host has gone down */
d702dc
-		if (ret == ECONNREFUSED)
d702dc
-			return NSS_STATUS_UNKNOWN;
d702dc
-		if (ret != ENOENT)
d702dc
+		if (ret == ECONNREFUSED) {
d702dc
+			err = NSS_STATUS_UNKNOWN;
d702dc
 			goto error;
d702dc
-		if (!count) {
d702dc
-			ret = NSS_STATUS_NOTFOUND;
d702dc
+		}
d702dc
+
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 we've read all entries.
d702dc
+			 * So even if we haven't got any values yet we
d702dc
+			 * can't use it to determine if we need to wait
d702dc
+			 * on sss.
d702dc
+			 */
d702dc
+			err = NSS_STATUS_NOTFOUND;
d702dc
+			if (count)
d702dc
+				err = NSS_STATUS_SUCCESS;
d702dc
 			goto free;
d702dc
+		} else {
d702dc
+			if (ret == ENOENT) {
d702dc
+				err = NSS_STATUS_NOTFOUND;
d702dc
+				if (count)
d702dc
+					err = NSS_STATUS_SUCCESS;
d702dc
+				goto free;
d702dc
+			}
d702dc
+			if (ret != EHOSTDOWN)
d702dc
+				goto error;
d702dc
+		}
d702dc
+
d702dc
+		ret = getautomntent_wait(logopt, ctxt,
d702dc
+					 key, value, sss_ctxt);
d702dc
+		if (ret) {
d702dc
+			if (ret == ECONNREFUSED) {
d702dc
+				err = NSS_STATUS_UNKNOWN;
d702dc
+				goto free;
d702dc
+			}
d702dc
+			if (ret == ETIMEDOUT)
d702dc
+				goto error;
d702dc
+			if (ret == ENOENT) {
d702dc
+				err = NSS_STATUS_NOTFOUND;
d702dc
+				if (count)
d702dc
+					err = NSS_STATUS_SUCCESS;
d702dc
+				goto free;
d702dc
+			}
d702dc
+			goto error;
d702dc
 		}
d702dc
-		goto error;
d702dc
 	}
d702dc
-	return ret;
d702dc
+	return NSS_STATUS_SUCCESS;
d702dc
 
d702dc
 error:
d702dc
 	estr = strerror_r(ret, buf, MAX_ERR_BUF);
d702dc
 	error(logopt, MODPREFIX "getautomntent: %s", estr);
d702dc
 free:
d702dc
-	if (*key)
d702dc
+	if (*key) {
d702dc
 		free(*key);
d702dc
-	if (*value)
d702dc
+		*key = NULL;
d702dc
+	}
d702dc
+	if (*value) {
d702dc
 		free(*value);
d702dc
-	return ret;
d702dc
+		*value = NULL;
d702dc
+	}
d702dc
+	return err;
d702dc
 }
d702dc
 
d702dc
 int lookup_read_master(struct master *master, time_t age, void *context)
d702dc
@@ -439,6 +537,9 @@ int lookup_read_master(struct master *master, time_t age, void *context)
d702dc
 			return ret;
d702dc
 		}
d702dc
 
d702dc
+		if (!key || !value)
d702dc
+			break;
d702dc
+
d702dc
 		count++;
d702dc
 
d702dc
 		buffer_len = strlen(key) + 1 + strlen(value) + 2;
d702dc
@@ -523,6 +624,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
d702dc
 			return ret;
d702dc
 		}
d702dc
 
d702dc
+		if (!key || !value)
d702dc
+			break;
d702dc
+
d702dc
 		/*
d702dc
 		 * Ignore keys beginning with '+' as plus map
d702dc
 		 * inclusion is only valid in file maps.