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(-) --- autofs-5.0.7.orig/CHANGELOG +++ autofs-5.0.7/CHANGELOG @@ -206,6 +206,7 @@ - add configuration option to use fqdn in mounts. - fix use-after-free in st_queue_handler(). - add config option to supress not found log message. +- wait for master map available at start. 25/07/2012 autofs-5.0.7 ======================= --- autofs-5.0.7.orig/daemon/automount.c +++ autofs-5.0.7/daemon/automount.c @@ -1379,9 +1379,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 = time(NULL); pthread_t thid; int status; @@ -1470,7 +1471,7 @@ static void *statemachine(void *arg) break; case SIGHUP: - do_hup_signal(master_list, time(NULL)); + do_hup_signal(master_list); break; default: @@ -2031,12 +2032,56 @@ static void remove_empty_args(char **arg *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 = 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 = time(NULL); struct rlimit rlim; @@ -2429,14 +2474,16 @@ int main(int argc, char *argv[]) dh_tirpc = dlopen("libtirpc.so.1", 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); } /* @@ -2449,6 +2496,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); --- autofs-5.0.7.orig/daemon/lookup.c +++ autofs-5.0.7/daemon/lookup.c @@ -241,6 +241,7 @@ int lookup_nss_read_master(struct master } /* 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 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); --- autofs-5.0.7.orig/lib/master.c +++ autofs-5.0.7/lib/master.c @@ -922,7 +922,10 @@ int master_read_master(struct master *ma 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); } --- autofs-5.0.7.orig/modules/lookup_file.c +++ autofs-5.0.7/modules/lookup_file.c @@ -506,6 +506,12 @@ int lookup_read_master(struct master *ma 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; --- autofs-5.0.7.orig/modules/lookup_nisplus.c +++ autofs-5.0.7/modules/lookup_nisplus.c @@ -149,19 +149,25 @@ int lookup_read_master(struct master *ma 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); --- autofs-5.0.7.orig/modules/lookup_yp.c +++ autofs-5.0.7/modules/lookup_yp.c @@ -282,9 +282,9 @@ int lookup_read_master(struct master *ma 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 *ma 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; }