autofs-5.1.2 - wait for master map available at start From: Ian Kent 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 --- 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 ab44b76..e35f1fd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -22,6 +22,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; }