static int check_map_indirect(struct autofs_point *ap, char *key, int key_len, struct lookup_context *ctxt) { struct map_source *source; struct mapent_cache *mc; struct mapent *me; time_t now = time(NULL); time_t t_last_read; int ret, cur_state; source = ap->entry->current; ap->entry->current = NULL; master_source_current_signal(ap->entry); mc = source->mc; master_source_current_wait(ap->entry); ap->entry->current = source; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ret = lookup_one(ap, key, key_len, ctxt); if (ret == NSS_STATUS_NOTFOUND) { pthread_setcancelstate(cur_state, NULL); return ret; } else if (ret == NSS_STATUS_UNAVAIL) { /* * If the server is down and the entry exists in the cache * and belongs to this map return success and use the entry. */ struct mapent *exists = cache_lookup(mc, key); if (exists && exists->source == source) { pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_SUCCESS; } pthread_setcancelstate(cur_state, NULL); warn(ap->logopt, MODPREFIX "lookup for %s failed: connection failed", key); return ret; } pthread_setcancelstate(cur_state, NULL); /* * Check for map change and update as needed for * following cache lookup. */ cache_readlock(mc); t_last_read = ap->exp_runfreq + 1; me = cache_lookup_first(mc); while (me) { if (me->source == source) { t_last_read = now - me->age; break; } me = cache_lookup_next(mc, me); } cache_unlock(mc); if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) source->stale = 1; cache_readlock(mc); me = cache_lookup_distinct(mc, "*"); if (ret == CHE_MISSING && (!me || me->source != source)) { cache_unlock(mc); return NSS_STATUS_NOTFOUND; } cache_unlock(mc); return NSS_STATUS_SUCCESS; }
int lookup_mount(const char *root, const char *name, int name_len, void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; struct stat st; char key[KEY_MAX_LEN + 1]; int key_len; char mapent[MAPENT_MAX_LEN + 1]; struct mapent_cache *me; time_t now = time(NULL); time_t t_last_read; int need_hup = 0; int ret = 1; if (stat(ctxt->mapname, &st)) { crit(MODPREFIX "file map %s, could not stat", ctxt->mapname); return 1; } if (ap.type == LKP_DIRECT) key_len = snprintf(key, KEY_MAX_LEN, "%s/%s", root, name); else key_len = snprintf(key, KEY_MAX_LEN, "%s", name); if (key_len > KEY_MAX_LEN) return 1; me = cache_lookup_first(); t_last_read = me ? now - me->age : ap.exp_runfreq + 1; /* only if it has been modified */ if (st.st_mtime > ctxt->mtime) { ret = lookup_one(root, key, key_len, ctxt); if (!ret) return 1; debug("ret = %d", ret); if (t_last_read > ap.exp_runfreq) if (ret & (CHE_UPDATED | CHE_MISSING)) need_hup = 1; if (ret == CHE_MISSING) { int wild = CHE_MISSING; /* Maybe update wild card map entry */ if (ap.type == LKP_INDIRECT) { wild = lookup_wild(root, ctxt); if (wild == CHE_MISSING) cache_delete(root, "*", 0); } if (cache_delete(root, key, 0) && wild & (CHE_MISSING | CHE_FAIL)) rmdir_path(key); } } me = cache_lookup(key); if (me == NULL) { /* path component, do submount */ me = cache_partial_match(key); if (me) sprintf(mapent, "-fstype=autofs file:%s", ctxt->mapname); } else sprintf(mapent, me->mapent); if (me) { debug(MODPREFIX "%s -> %s", key, mapent); ret = ctxt->parse->parse_mount(root, name, name_len, mapent, ctxt->parse->context); } /* Have parent update its map ? */ if (need_hup) kill(getppid(), SIGHUP); return ret; }