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

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