Example #1
0
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;
}
Example #2
0
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;
}