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

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