Blame SOURCES/autofs-5.1.2-wait-for-master-map-available-at-start.patch

304803
autofs-5.1.2 - wait for master map available at start
304803
304803
From: Ian Kent <raven@themaw.net>
304803
304803
If the network map source isn't available at start the master map
304803
can't be read. In this case we should wait until it is available
304803
so we can get a startup map.
304803
304803
Signed-off-by: Ian Kent <raven@themaw.net>
304803
---
304803
 CHANGELOG                |    1 
304803
 daemon/automount.c       |   81 +++++++++++++++++++++++++++++++++++++++++------
304803
 daemon/lookup.c          |    8 ++++
304803
 lib/master.c             |    3 +
304803
 modules/lookup_file.c    |    6 +++
304803
 modules/lookup_nisplus.c |   14 +++++---
304803
 modules/lookup_yp.c      |   13 +++++--
304803
 7 files changed, 108 insertions(+), 18 deletions(-)
304803
304803
--- autofs-5.0.7.orig/CHANGELOG
304803
+++ autofs-5.0.7/CHANGELOG
304803
@@ -206,6 +206,7 @@
304803
 - add configuration option to use fqdn in mounts.
304803
 - fix use-after-free in st_queue_handler().
304803
 - add config option to supress not found log message.
304803
+- wait for master map available at start.
304803
 
304803
 25/07/2012 autofs-5.0.7
304803
 =======================
304803
--- autofs-5.0.7.orig/daemon/automount.c
304803
+++ autofs-5.0.7/daemon/automount.c
304803
@@ -1379,9 +1379,10 @@ static void *do_read_master(void *arg)
304803
 	return NULL;
304803
 }
304803
 
304803
-static int do_hup_signal(struct master *master, time_t age)
304803
+static int do_hup_signal(struct master *master)
304803
 {
304803
 	unsigned int logopt = master->logopt;
304803
+	time_t age = time(NULL);
304803
 	pthread_t thid;
304803
 	int status;
304803
 
304803
@@ -1470,7 +1471,7 @@ static void *statemachine(void *arg)
304803
 			break;
304803
 
304803
 		case SIGHUP:
304803
-			do_hup_signal(master_list, time(NULL));
304803
+			do_hup_signal(master_list);
304803
 			break;
304803
 
304803
 		default:
304803
@@ -2031,12 +2032,56 @@ static void remove_empty_args(char **arg
304803
 	*argc = j;
304803
 }
304803
 
304803
+static int do_master_read_master(struct master *master, int wait)
304803
+{
304803
+	sigset_t signalset;
304803
+	/* Wait must be at least 1 second */
304803
+	unsigned int retry_wait = 2;
304803
+	unsigned int elapsed = 0;
304803
+	int max_wait = wait;
304803
+	int ret = 0;
304803
+	time_t age;
304803
+
304803
+	sigemptyset(&signalset);
304803
+	sigaddset(&signalset, SIGTERM);
304803
+	sigaddset(&signalset, SIGINT);
304803
+	sigaddset(&signalset, SIGHUP);
304803
+	sigprocmask(SIG_UNBLOCK, &signalset, NULL);
304803
+
304803
+	while (1) {
304803
+		struct timespec t = { retry_wait, 0 };
304803
+
304803
+		age = time(NULL);
304803
+		if (master_read_master(master, age, 0)) {
304803
+			ret = 1;
304803
+			break;
304803
+		}
304803
+
304803
+		if (nanosleep(&t, NULL) == -1)
304803
+			break;
304803
+
304803
+		if (max_wait > 0) {
304803
+			elapsed += retry_wait;
304803
+			if (elapsed >= max_wait) {
304803
+				logmsg("problem reading master map, "
304803
+					"maximum wait exceeded");
304803
+				break;
304803
+			}
304803
+		}
304803
+	}
304803
+
304803
+	sigprocmask(SIG_BLOCK, &signalset, NULL);
304803
+
304803
+	return ret;
304803
+}
304803
+
304803
 int main(int argc, char *argv[])
304803
 {
304803
 	int res, opt, status;
304803
 	int logpri = -1;
304803
 	unsigned ghost, logging, daemon_check;
304803
 	unsigned dumpmaps, foreground, have_global_options;
304803
+	unsigned master_read;
304803
 	time_t timeout;
304803
 	time_t age = time(NULL);
304803
 	struct rlimit rlim;
304803
@@ -2429,14 +2474,16 @@ int main(int argc, char *argv[])
304803
 		dh_tirpc = dlopen("libtirpc.so.1", RTLD_NOW);
304803
 #endif
304803
 
304803
-	if (!master_read_master(master_list, age, 0)) {
304803
-		master_kill(master_list);
304803
-		*pst_stat = 3;
304803
-		res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
304803
-		close(start_pipefd[1]);
304803
-		release_flag_file();
304803
-		macro_free_global_table();
304803
-		exit(3);
304803
+	master_read = master_read_master(master_list, age, 0);
304803
+	if (!master_read) {
304803
+		if (foreground)
304803
+			logerr("%s: failed to read master map, "
304803
+			       "will retry!",
304803
+			       program);
304803
+		else
304803
+			logerr("%s: failed to read master map, "
304803
+			       "will retry in background!",
304803
+			       program);
304803
 	}
304803
 
304803
 	/*
304803
@@ -2449,6 +2496,20 @@ int main(int argc, char *argv[])
304803
 	res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
304803
 	close(start_pipefd[1]);
304803
 
304803
+	if (!master_read) {
304803
+		/*
304803
+		 * Read master map, waiting until it is available, unless
304803
+		 * a signal is received, in which case exit returning an
304803
+		 * error.
304803
+		 */
304803
+		if (!do_master_read_master(master_list, -1)) {
304803
+			logerr("%s: failed to read master map!", program);
304803
+			master_kill(master_list);
304803
+			release_flag_file();
304803
+			exit(3);
304803
+		}
304803
+	}
304803
+
304803
 	state_mach_thid = pthread_self();
304803
 	statemachine(NULL);
304803
 
304803
--- autofs-5.0.7.orig/daemon/lookup.c
304803
+++ autofs-5.0.7/daemon/lookup.c
304803
@@ -241,6 +241,7 @@ int lookup_nss_read_master(struct master
304803
 	}
304803
 
304803
 	/* First one gets it */
304803
+	result = NSS_STATUS_UNKNOWN;
304803
 	head = &nsslist;
304803
 	list_for_each(p, head) {
304803
 		struct nss_source *this;
304803
@@ -248,6 +249,13 @@ int lookup_nss_read_master(struct master
304803
 
304803
 		this = list_entry(p, struct nss_source, list);
304803
 
304803
+		if (strncmp(this->source, "files", 5) &&
304803
+		    strncmp(this->source, "nis", 3) &&
304803
+		    strncmp(this->source, "nisplus", 7) &&
304803
+		    strncmp(this->source, "ldap", 4) &&
304803
+		    strncmp(this->source, "sss", 3))
304803
+			continue;
304803
+
304803
 		debug(logopt,
304803
 		      "reading master %s %s", this->source, master->name);
304803
 
304803
--- autofs-5.0.7.orig/lib/master.c
304803
+++ autofs-5.0.7/lib/master.c
304803
@@ -922,7 +922,10 @@ int master_read_master(struct master *ma
304803
 		master_mount_mounts(master, age, readall);
304803
 	else {
304803
 		master->read_fail = 0;
304803
+		/* HUP signal sets readall == 1 only */
304803
 		if (!readall)
304803
+			return 0;
304803
+		else
304803
 			master_mount_mounts(master, age, readall);
304803
 	}
304803
 
304803
--- autofs-5.0.7.orig/modules/lookup_file.c
304803
+++ autofs-5.0.7/modules/lookup_file.c
304803
@@ -506,6 +506,12 @@ int lookup_read_master(struct master *ma
304803
 				     MODPREFIX
304803
 				     "failed to read included master map %s",
304803
 				     master->name);
304803
+				/*
304803
+				 * If we're starting up wee need the whole
304803
+				 * master map initially, so tell the upper
304803
+				 * layer to retry.
304803
+				 */
304803
+				master->read_fail = 1;
304803
 			}
304803
 			master->depth--;
304803
 			master->recurse = 0;
304803
--- autofs-5.0.7.orig/modules/lookup_nisplus.c
304803
+++ autofs-5.0.7/modules/lookup_nisplus.c
304803
@@ -149,19 +149,25 @@ int lookup_read_master(struct master *ma
304803
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
304803
 		logerr(MODPREFIX "malloc: %s", estr);
304803
 		pthread_setcancelstate(cur_state, NULL);
304803
-		return NSS_STATUS_UNAVAIL;
304803
+		return NSS_STATUS_UNKNOWN;
304803
 	}
304803
 	sprintf(tablename, "%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
304803
 
304803
 	/* check that the table exists */
304803
 	result = nis_lookup(tablename, FOLLOW_PATH | FOLLOW_LINKS);
304803
 	if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
304803
+		int status = result->status;
304803
 		nis_freeresult(result);
304803
-		crit(logopt,
304803
-		     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
304803
 		free(tablename);
304803
 		pthread_setcancelstate(cur_state, NULL);
304803
-		return NSS_STATUS_NOTFOUND;
304803
+		if (status == NIS_UNAVAIL || status == NIS_FAIL)
304803
+			return NSS_STATUS_UNAVAIL;
304803
+		else {
304803
+			crit(logopt,
304803
+			     MODPREFIX "couldn't locate nis+ table %s",
304803
+			     ctxt->mapname);
304803
+			return NSS_STATUS_NOTFOUND;
304803
+		}
304803
 	}
304803
 
304803
 	sprintf(tablename, "[],%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
304803
--- autofs-5.0.7.orig/modules/lookup_yp.c
304803
+++ autofs-5.0.7/modules/lookup_yp.c
304803
@@ -282,9 +282,9 @@ int lookup_read_master(struct master *ma
304803
 	char *mapname;
304803
 	int err;
304803
 
304803
-	mapname = alloca(strlen(ctxt->mapname) + 1);
304803
+	mapname = malloc(strlen(ctxt->mapname) + 1);
304803
 	if (!mapname)
304803
-		return 0;
304803
+		return NSS_STATUS_UNKNOWN;
304803
 
304803
 	strcpy(mapname, ctxt->mapname);
304803
 
304803
@@ -308,19 +308,24 @@ int lookup_read_master(struct master *ma
304803
 			err = yp_all((char *) ctxt->domainname, mapname, &ypcb);
304803
 		}
304803
 
304803
-		if (err == YPERR_SUCCESS)
304803
+		if (err == YPERR_SUCCESS) {
304803
+			free(mapname);
304803
 			return NSS_STATUS_SUCCESS;
304803
+		}
304803
 
304803
 		info(logopt,
304803
 		     MODPREFIX "read of master map %s failed: %s",
304803
 		     mapname, yperr_string(err));
304803
 
304803
-		if (err == YPERR_PMAP || err == YPERR_YPSERV)
304803
+		free(mapname);
304803
+
304803
+		if (err == YPERR_YPSERV || err == YPERR_DOMAIN)
304803
 			return NSS_STATUS_UNAVAIL;
304803
 
304803
 		return NSS_STATUS_NOTFOUND;
304803
 	}
304803
 
304803
+	free(mapname);
304803
 	return NSS_STATUS_SUCCESS;
304803
 }
304803