[PATCH 23/37] autofs-5.1.2 - wait for master map available at start

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If the network map source isn't available at start the master map
can't be read. In this case we should wait until it is available
so we can get a startup map.

Signed-off-by: Ian Kent <raven@xxxxxxxxxx>
---
 CHANGELOG                |    1 +
 daemon/automount.c       |   81 ++++++++++++++++++++++++++++++++++++++++------
 daemon/lookup.c          |    8 +++++
 lib/master.c             |    3 ++
 modules/lookup_file.c    |    6 +++
 modules/lookup_nisplus.c |   14 ++++++--
 modules/lookup_yp.c      |   13 +++++--
 7 files changed, 108 insertions(+), 18 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 686d404..d1bc1e1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -20,6 +20,7 @@ xx/xx/2016 autofs-5.1.3
 - fix _strncmp() usage.
 - fix create_client() RPC client handling.
 - update and add README for old autofs schema.
+- wait for master map available at start.
 
 15/06/2016 autofs-5.1.2
 =======================
diff --git a/daemon/automount.c b/daemon/automount.c
index 9d4c2b7..14af9ff 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1403,9 +1403,10 @@ static void *do_read_master(void *arg)
 	return NULL;
 }
 
-static int do_hup_signal(struct master *master, time_t age)
+static int do_hup_signal(struct master *master)
 {
 	unsigned int logopt = master->logopt;
+	time_t age = monotonic_time(NULL);
 	pthread_t thid;
 	int status;
 
@@ -1494,7 +1495,7 @@ static void *statemachine(void *arg)
 			break;
 
 		case SIGHUP:
-			do_hup_signal(master_list, monotonic_time(NULL));
+			do_hup_signal(master_list);
 			break;
 
 		default:
@@ -2052,12 +2053,56 @@ static void remove_empty_args(char **argv, int *argc)
 	*argc = j;
 }
 
+static int do_master_read_master(struct master *master, int wait)
+{
+	sigset_t signalset;
+	/* Wait must be at least 1 second */
+	unsigned int retry_wait = 2;
+	unsigned int elapsed = 0;
+	int max_wait = wait;
+	int ret = 0;
+	time_t age;
+
+	sigemptyset(&signalset);
+	sigaddset(&signalset, SIGTERM);
+	sigaddset(&signalset, SIGINT);
+	sigaddset(&signalset, SIGHUP);
+	sigprocmask(SIG_UNBLOCK, &signalset, NULL);
+
+	while (1) {
+		struct timespec t = { retry_wait, 0 };
+
+		age = monotonic_time(NULL);
+		if (master_read_master(master, age, 0)) {
+			ret = 1;
+			break;
+		}
+
+		if (nanosleep(&t, NULL) == -1)
+			break;
+
+		if (max_wait > 0) {
+			elapsed += retry_wait;
+			if (elapsed >= max_wait) {
+				logmsg("problem reading master map, "
+					"maximum wait exceeded");
+				break;
+			}
+		}
+	}
+
+	sigprocmask(SIG_BLOCK, &signalset, NULL);
+
+	return ret;
+}
+
 int main(int argc, char *argv[])
 {
 	int res, opt, status;
 	int logpri = -1;
 	unsigned ghost, logging, daemon_check;
 	unsigned dumpmaps, foreground, have_global_options;
+	unsigned master_read;
 	time_t timeout;
 	time_t age = monotonic_time(NULL);
 	struct rlimit rlim;
@@ -2452,14 +2497,16 @@ int main(int argc, char *argv[])
 		dh_tirpc = dlopen("libtirpc.so.3", RTLD_NOW);
 #endif
 
-	if (!master_read_master(master_list, age, 0)) {
-		master_kill(master_list);
-		*pst_stat = 3;
-		res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
-		close(start_pipefd[1]);
-		release_flag_file();
-		macro_free_global_table();
-		exit(3);
+	master_read = master_read_master(master_list, age, 0);
+	if (!master_read) {
+		if (foreground)
+			logerr("%s: failed to read master map, "
+			       "will retry!",
+			       program);
+		else
+			logerr("%s: failed to read master map, "
+			       "will retry in background!",
+			       program);
 	}
 
 	/*
@@ -2472,6 +2519,20 @@ int main(int argc, char *argv[])
 	res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
 	close(start_pipefd[1]);
 
+	if (!master_read) {
+		/*
+		 * Read master map, waiting until it is available, unless
+		 * a signal is received, in which case exit returning an
+		 * error.
+		 */
+		if (!do_master_read_master(master_list, -1)) {
+			logerr("%s: failed to read master map!", program);
+			master_kill(master_list);
+			release_flag_file();
+			exit(3);
+		}
+	}
+
 	state_mach_thid = pthread_self();
 	statemachine(NULL);
 
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 582b5c9..0c2a01f 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -241,6 +241,7 @@ int lookup_nss_read_master(struct master *master, time_t age)
 	}
 
 	/* First one gets it */
+	result = NSS_STATUS_UNKNOWN;
 	head = &nsslist;
 	list_for_each(p, head) {
 		struct nss_source *this;
@@ -248,6 +249,13 @@ int lookup_nss_read_master(struct master *master, time_t age)
 
 		this = list_entry(p, struct nss_source, list);
 
+		if (strncmp(this->source, "files", 5) &&
+		    strncmp(this->source, "nis", 3) &&
+		    strncmp(this->source, "nisplus", 7) &&
+		    strncmp(this->source, "ldap", 4) &&
+		    strncmp(this->source, "sss", 3))
+			continue;
+
 		debug(logopt,
 		      "reading master %s %s", this->source, master->name);
 
diff --git a/lib/master.c b/lib/master.c
index 9ffdd1a..4c6e79b 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -923,7 +923,10 @@ int master_read_master(struct master *master, time_t age, int readall)
 		master_mount_mounts(master, age, readall);
 	else {
 		master->read_fail = 0;
+		/* HUP signal sets readall == 1 only */
 		if (!readall)
+			return 0;
+		else
 			master_mount_mounts(master, age, readall);
 	}
 
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index d87ec73..d5f8c9e 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -507,6 +507,12 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 				     MODPREFIX
 				     "failed to read included master map %s",
 				     master->name);
+				/*
+				 * If we're starting up wee need the whole
+				 * master map initially, so tell the upper
+				 * layer to retry.
+				 */
+				master->read_fail = 1;
 			}
 			master->depth--;
 			master->recurse = 0;
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index 7832611..c8b75e6 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -149,19 +149,25 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		logerr(MODPREFIX "malloc: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
-		return NSS_STATUS_UNAVAIL;
+		return NSS_STATUS_UNKNOWN;
 	}
 	sprintf(tablename, "%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
 
 	/* check that the table exists */
 	result = nis_lookup(tablename, FOLLOW_PATH | FOLLOW_LINKS);
 	if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
+		int status = result->status;
 		nis_freeresult(result);
-		crit(logopt,
-		     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
 		free(tablename);
 		pthread_setcancelstate(cur_state, NULL);
-		return NSS_STATUS_NOTFOUND;
+		if (status == NIS_UNAVAIL || status == NIS_FAIL)
+			return NSS_STATUS_UNAVAIL;
+		else {
+			crit(logopt,
+			     MODPREFIX "couldn't locate nis+ table %s",
+			     ctxt->mapname);
+			return NSS_STATUS_NOTFOUND;
+		}
 	}
 
 	sprintf(tablename, "[],%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 502d850..0d319fd 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -282,9 +282,9 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	char *mapname;
 	int err;
 
-	mapname = alloca(strlen(ctxt->mapname) + 1);
+	mapname = malloc(strlen(ctxt->mapname) + 1);
 	if (!mapname)
-		return 0;
+		return NSS_STATUS_UNKNOWN;
 
 	strcpy(mapname, ctxt->mapname);
 
@@ -308,19 +308,24 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 			err = yp_all((char *) ctxt->domainname, mapname, &ypcb);
 		}
 
-		if (err == YPERR_SUCCESS)
+		if (err == YPERR_SUCCESS) {
+			free(mapname);
 			return NSS_STATUS_SUCCESS;
+		}
 
 		info(logopt,
 		     MODPREFIX "read of master map %s failed: %s",
 		     mapname, yperr_string(err));
 
-		if (err == YPERR_PMAP || err == YPERR_YPSERV)
+		free(mapname);
+
+		if (err == YPERR_YPSERV || err == YPERR_DOMAIN)
 			return NSS_STATUS_UNAVAIL;
 
 		return NSS_STATUS_NOTFOUND;
 	}
 
+	free(mapname);
 	return NSS_STATUS_SUCCESS;
 }
 

--
To unsubscribe from this list: send the line "unsubscribe autofs" in



[Index of Archives]     [Linux Filesystem Development]     [Linux Ext4]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux