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

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