--- autofs-5.0.1/include/automount.h.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/include/automount.h 2007-05-04 14:08:10.000000000 +0800 @@ -141,6 +141,7 @@ pthread_mutex_t multi_mutex; struct list_head multi_list; struct mapent_cache *mc; + struct map_source *source; /* Need to know owner if we're a multi-mount */ struct mapent *multi; /* Parent nesting point within multi-mount */ @@ -175,10 +176,10 @@ struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key); struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int start, struct list_head *head); struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix); -int cache_add(struct mapent_cache *mc, const char *key, const char *mapent, time_t age); +int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age); int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age); int cache_set_parents(struct mapent *mm); -int cache_update(struct mapent_cache *mc, const char *key, const char *mapent, time_t age); +int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age); int cache_delete(struct mapent_cache *mc, const char *key); void cache_multi_lock(struct mapent *me); void cache_multi_unlock(struct mapent *me); @@ -221,11 +222,11 @@ #define PARSE_MAX_BUF KEY_MAX_LEN + MAPENT_MAX_LEN + 2 int lookup_nss_read_master(struct master *master, time_t age); -int lookup_nss_read_map(struct autofs_point *ap, time_t age); +int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time_t age); int lookup_enumerate(struct autofs_point *ap, int (*fn)(struct autofs_point *,struct mapent *, int), time_t now); int lookup_ghost(struct autofs_point *ap); -int lookup_nss_mount(struct autofs_point *ap, const char *name, int name_len); +int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const char *name, int name_len); void lookup_close_lookup(struct autofs_point *ap); int lookup_prune_cache(struct autofs_point *ap, time_t age); struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type); --- autofs-5.0.1/include/master.h.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/include/master.h 2007-05-04 14:08:10.000000000 +0800 @@ -85,7 +85,8 @@ struct map_source * master_find_source_instance(struct map_source *, const char *, const char *, int, const char **); struct map_source * -master_add_source_instance(struct map_source *, const char *, const char *, time_t); +master_add_source_instance(struct map_source *, const char *, const char *, time_t, int, const char **); +void send_map_update_request(struct autofs_point *); void master_source_writelock(struct master_mapent *); void master_source_readlock(struct master_mapent *); void master_source_unlock(struct master_mapent *); --- autofs-5.0.1/modules/parse_sun.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/parse_sun.c 2007-05-04 14:08:10.000000000 +0800 @@ -1079,7 +1079,7 @@ * Not in the cache, perhaps it's a program map * or one that doesn't support enumeration */ - ret = cache_add(mc, name, mapent, time(NULL)); + ret = cache_add(mc, source, name, mapent, time(NULL)); if (ret == CHE_FAIL) { cache_unlock(mc); free(options); --- autofs-5.0.1/modules/lookup_nisplus.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_nisplus.c 2007-05-04 14:08:10.000000000 +0800 @@ -234,7 +234,7 @@ mapent = ENTRY_VAL(this, 1); cache_writelock(mc); - cache_update(mc, s_key, mapent, age); + cache_update(mc, source, s_key, mapent, age); cache_unlock(mc); free(s_key); @@ -296,7 +296,7 @@ this = NIS_RES_OBJECT(result); mapent = ENTRY_VAL(this, 1); cache_writelock(mc); - ret = cache_update(mc, key, mapent, age); + ret = cache_update(mc, source, key, mapent, age); cache_unlock(mc); nis_freeresult(result); @@ -348,7 +348,7 @@ this = NIS_RES_OBJECT(result); mapent = ENTRY_VAL(this, 1); cache_writelock(mc); - ret = cache_update(mc, "*", mapent, age); + ret = cache_update(mc, source, "*", mapent, age); cache_unlock(mc); nis_freeresult(result); @@ -366,7 +366,6 @@ struct mapent *me, *exists; time_t now = time(NULL); time_t t_last_read; - int need_map = 0; int ret = 0; source = ap->entry->current; @@ -375,12 +374,6 @@ mc = source->mc; - cache_readlock(mc); - exists = cache_lookup_distinct(mc, key); - if (exists && exists->mc != mc) - exists = NULL; - cache_unlock(mc); - master_source_current_wait(ap->entry); ap->entry->current = source; @@ -396,51 +389,62 @@ return NSS_STATUS_UNAVAIL; } - cache_readlock(mc); + pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + t_last_read = ap->exp_runfreq + 1; me = cache_lookup_first(mc); - t_last_read = me ? now - me->age : ap->exp_runfreq + 1; - cache_unlock(mc); - - if (t_last_read > ap->exp_runfreq) - if ((ret & CHE_UPDATED) || - (exists && (ret & CHE_MISSING))) - need_map = 1; + while (me) { + if (me->source == source) { + t_last_read = now - me->age; + break; + } + me = cache_lookup_next(mc, me); + } + exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ + if (exists && exists->source == source && ret & CHE_MISSING) { + if (exists->mapent) { + free(exists->mapent); + exists->mapent = NULL; + source->stale = 1; + exists->status = 0; + } + } + pthread_cleanup_pop(1); + + if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) + source->stale = 1; if (ret == CHE_MISSING) { int wild = CHE_MISSING; + struct mapent *we; master_source_current_wait(ap->entry); ap->entry->current = source; wild = lookup_wild(ap, ctxt); - if (wild == CHE_UPDATED || CHE_OK) - return NSS_STATUS_SUCCESS; - + /* + * Check for map change and update as needed for + * following cache lookup. + */ pthread_cleanup_push(cache_lock_cleanup, mc); cache_writelock(mc); - if (wild == CHE_MISSING) - cache_delete(mc, "*"); - - if (cache_delete(mc, key) && wild & (CHE_MISSING | CHE_FAIL)) - rmdir_path(ap, key, ap->dev); + we = cache_lookup_distinct(mc, "*"); + if (we) { + /* Wildcard entry existed and is now gone */ + if (we->source == source && wild & CHE_MISSING) { + cache_delete(mc, "*"); + source->stale = 1; + } + } else { + /* Wildcard not in map but now is */ + if (wild & (CHE_OK || CHE_UPDATED)) + source->stale = 1; + } pthread_cleanup_pop(1); - } - - /* Have parent update its map */ - if (ap->ghost && need_map) { - int status; - source->stale = 1; - - status = pthread_mutex_lock(&ap->state_mutex); - if (status) - fatal(status); - - nextstate(ap->state_pipe[1], ST_READMAP); - - status = pthread_mutex_unlock(&ap->state_mutex); - if (status) - fatal(status); + if (wild & (CHE_UPDATED || CHE_OK)) + return NSS_STATUS_SUCCESS; } if (ret == CHE_MISSING) @@ -514,7 +518,10 @@ cache_readlock(mc); me = cache_lookup(mc, key); - if (me && me->mapent && *me->mapent) { + /* Stale mapent => check for wildcard */ + if (me && !me->mapent) + me = cache_lookup_distinct(mc, "*"); + if (me && (me->source == source || *me->key == '/')) { mapent_len = strlen(me->mapent); mapent = alloca(mapent_len + 1); strcpy(mapent, me->mapent); @@ -535,7 +542,7 @@ cache_writelock(mc); me = cache_lookup_distinct(mc, key); if (!me) - rv = cache_update(mc, key, NULL, now); + rv = cache_update(mc, source, key, NULL, now); if (rv != CHE_FAIL) { me = cache_lookup_distinct(mc, key); me->status = time(NULL) + NEGATIVE_TIMEOUT; --- autofs-5.0.1/modules/lookup_file.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_file.c 2007-05-04 14:08:10.000000000 +0800 @@ -551,45 +551,20 @@ return 0; } -static struct autofs_point * +static struct map_source * prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned int inc) { - struct master *master; - struct master_mapent *entry; struct map_source *current; struct map_source *source; - struct autofs_point *iap; char *type, *map, *fmt; const char *argv[2]; - int ret, argc; - unsigned int timeout = ap->exp_timeout; - unsigned int logopt = ap->logopt; - unsigned int ghost = ap->ghost; + int argc; char *buf, *tmp; current = ap->entry->current; ap->entry->current = NULL; master_source_current_signal(ap->entry); - master = ap->entry->master; - - entry = master_new_mapent(master, ap->path, ap->entry->age); - if (!entry) { - error(ap->logopt, MODPREFIX "malloc failed for entry"); - return NULL; - } - - ret = master_add_autofs_point(entry, timeout, logopt, ghost, 0); - if (!ret) { - master_free_mapent(entry); - error(ap->logopt, - MODPREFIX "failed to add autofs_point to entry"); - return NULL; - } - iap = entry->ap; - iap->kpipefd = ap->kpipefd; - set_mnt_logging(iap); - /* * TODO: * Initially just consider the passed in key to be a simple map @@ -602,7 +577,6 @@ /* skip plus */ buf = strdup(key + 1); if (!buf) { - master_free_mapent(entry); error(ap->logopt, MODPREFIX "failed to strdup key"); return NULL; } @@ -633,21 +607,23 @@ argv[0] = map; argv[1] = NULL; - source = master_add_map_source(entry, type, fmt, age, argc, argv); + source = master_find_source_instance(current, type, fmt, argc, argv); if (!source) { - master_free_mapent(entry); - free(buf); - error(ap->logopt, "failed to creat map_source"); - return NULL; + source = master_add_source_instance(current, type, fmt, age, argc, argv); + if (!source) { + free(buf); + error(ap->logopt, "failed to add included map instance"); + return NULL; + } } - source->mc = current->mc; + source->depth = current->depth + 1; if (inc) source->recurse = 1; free(buf); - return iap; + return source; } int lookup_read_map(struct autofs_point *ap, time_t age, void *context) @@ -719,7 +695,7 @@ * included map. */ if (*key == '+') { - struct autofs_point *iap; + struct map_source *inc_source; unsigned int inc; int status; @@ -730,21 +706,18 @@ master_source_current_wait(ap->entry); ap->entry->current = source; - iap = prepare_plus_include(ap, age, key, inc); - if (!iap) { + inc_source = prepare_plus_include(ap, age, key, inc); + if (!inc_source) { debug(ap->logopt, "failed to select included map %s", key); continue; } /* Gim'ee some o' that 16k stack baby !! */ - status = lookup_nss_read_map(iap, age); + status = lookup_nss_read_map(ap, inc_source, age); if (!status) warn(ap->logopt, "failed to read included map %s", key); - - master_free_mapent_sources(iap->entry, 0); - master_free_mapent(iap->entry); } else { char *s_key; @@ -753,7 +726,7 @@ continue; cache_writelock(mc); - cache_update(mc, s_key, mapent, age); + cache_update(mc, source, s_key, mapent, age); cache_unlock(mc); free(s_key); @@ -819,7 +792,7 @@ * included map. */ if (*mkey == '+') { - struct autofs_point *iap; + struct map_source *inc_source; unsigned int inc; int status; @@ -831,8 +804,8 @@ master_source_current_wait(ap->entry); ap->entry->current = source; - iap = prepare_plus_include(ap, age, mkey, inc); - if (!iap) { + inc_source = prepare_plus_include(ap, age, mkey, inc); + if (!inc_source) { debug(ap->logopt, MODPREFIX "failed to select included map %s", @@ -841,11 +814,7 @@ } /* Gim'ee some o' that 16k stack baby !! */ - status = lookup_nss_mount(iap, key, key_len); - - master_free_mapent_sources(iap->entry, 0); - master_free_mapent(iap->entry); - + status = lookup_nss_mount(ap, inc_source, key, key_len); if (status) { fclose(f); return CHE_COMPLETED; @@ -872,7 +841,7 @@ free(s_key); cache_writelock(mc); - ret = cache_update(mc, key, mapent, age); + ret = cache_update(mc, source, key, mapent, age); cache_unlock(mc); fclose(f); @@ -932,7 +901,7 @@ continue; cache_writelock(mc); - ret = cache_update(mc, "*", mapent, age); + ret = cache_update(mc, source, "*", mapent, age); cache_unlock(mc); fclose(f); @@ -956,7 +925,6 @@ struct map_source *source; struct mapent_cache *mc; struct mapent *exists; - int need_map = 0; int ret = CHE_OK; source = ap->entry->current; @@ -965,12 +933,6 @@ mc = source->mc; - cache_readlock(mc); - exists = cache_lookup_distinct(mc, key); - if (exists && exists->mc != mc) - exists = NULL; - cache_unlock(mc); - master_source_current_wait(ap->entry); ap->entry->current = source; @@ -981,49 +943,53 @@ if (ret == CHE_FAIL) return NSS_STATUS_NOTFOUND; - if ((ret & CHE_UPDATED) || - (exists && (ret & CHE_MISSING))) - need_map = 1; + if (ret & CHE_UPDATED) + source->stale = 1; + + pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ + if (exists && exists->source == source && ret & CHE_MISSING) { + if (exists->mapent) { + free(exists->mapent); + exists->mapent = NULL; + exists->status = 0; + source->stale = 1; + } + } + pthread_cleanup_pop(1); if (ret == CHE_MISSING) { + struct mapent *we; int wild = CHE_MISSING; master_source_current_wait(ap->entry); ap->entry->current = source; wild = lookup_wild(ap, ctxt); - if (wild == CHE_COMPLETED || CHE_UPDATED || CHE_OK) - return NSS_STATUS_SUCCESS; -/* - if (wild == CHE_FAIL) - return NSS_STATUS_NOTFOUND; -*/ + /* + * Check for map change and update as needed for + * following cache lookup. + */ pthread_cleanup_push(cache_lock_cleanup, mc); cache_writelock(mc); - if (wild == CHE_MISSING) - cache_delete(mc, "*"); - - if (cache_delete(mc, key) && wild & (CHE_MISSING | CHE_FAIL)) - rmdir_path(ap, key, ap->dev); + we = cache_lookup_distinct(mc, "*"); + if (we) { + /* Wildcard entry existed and is now gone */ + if (we->source == source && (wild & CHE_MISSING)) { + cache_delete(mc, "*"); + source->stale = 1; + } + } else { + /* Wildcard not in map but now is */ + if (wild & (CHE_OK || CHE_UPDATED)) + source->stale = 1; + } pthread_cleanup_pop(1); - } - /* Have parent update its map ? */ - /* TODO: update specific map */ - if (ap->ghost && need_map) { - int status; - - source->stale = 1; - - status = pthread_mutex_lock(&ap->state_mutex); - if (status) - fatal(status); - - nextstate(ap->state_pipe[1], ST_READMAP); - - status = pthread_mutex_unlock(&ap->state_mutex); - if (status) - fatal(status); + if (wild & (CHE_OK || CHE_UPDATED)) + return NSS_STATUS_SUCCESS; } if (ret == CHE_MISSING) @@ -1113,7 +1079,10 @@ cache_readlock(mc); me = cache_lookup(mc, key); - if (me && me->mapent && *me->mapent) { + /* Stale mapent => check for wildcard */ + if (me && !me->mapent) + me = cache_lookup_distinct(mc, "*"); + if (me && (me->source == source || *me->key == '/')) { pthread_cleanup_push(cache_lock_cleanup, mc); mapent_len = strlen(me->mapent); mapent = alloca(mapent_len + 1); @@ -1136,7 +1105,7 @@ cache_writelock(mc); me = cache_lookup_distinct(mc, key); if (!me) - rv = cache_update(mc, key, NULL, now); + rv = cache_update(mc, source, key, NULL, now); if (rv != CHE_FAIL) { me = cache_lookup_distinct(mc, key); me->status = now + NEGATIVE_TIMEOUT; --- autofs-5.0.1/modules/lookup_program.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_program.c 2007-05-04 14:08:10.000000000 +0800 @@ -339,7 +339,7 @@ } cache_writelock(mc); - ret = cache_update(mc, name, mapent, time(NULL)); + ret = cache_update(mc, source, name, mapent, time(NULL)); cache_unlock(mc); if (ret == CHE_FAIL) return NSS_STATUS_UNAVAIL; --- autofs-5.0.1/modules/lookup_userhome.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_userhome.c 2007-05-04 14:08:10.000000000 +0800 @@ -78,7 +78,7 @@ } cache_writelock(mc); - ret = cache_update(mc, name, NULL, time(NULL)); + ret = cache_update(mc, source, name, NULL, time(NULL)); cache_unlock(mc); if (ret == CHE_FAIL) { --- autofs-5.0.1/modules/lookup_hosts.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_hosts.c 2007-05-04 14:08:10.000000000 +0800 @@ -97,7 +97,7 @@ while ((host = gethostent()) != NULL) { pthread_cleanup_push(cache_lock_cleanup, mc); cache_writelock(mc); - cache_update(mc, host->h_name, NULL, age); + cache_update(mc, source, host->h_name, NULL, age); cache_unlock(mc); pthread_cleanup_pop(0); } @@ -250,7 +250,7 @@ debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent); cache_writelock(mc); - cache_update(mc, name, mapent, now); + cache_update(mc, source, name, mapent, now); cache_unlock(mc); debug(LOGOPT_ANY, "source wait"); --- autofs-5.0.1/modules/lookup_hesiod.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_hesiod.c 2007-05-04 14:08:10.000000000 +0800 @@ -154,7 +154,7 @@ } cache_writelock(mc); - rv = cache_update(mc, name, best_record, time(NULL)); + rv = cache_update(mc, source, name, best_record, time(NULL)); cache_unlock(mc); if (rv == CHE_FAIL) return NSS_STATUS_UNAVAIL; --- autofs-5.0.1/modules/lookup_ldap.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_ldap.c 2007-05-04 14:08:10.000000000 +0800 @@ -1251,7 +1251,7 @@ goto next; cache_writelock(mc); - cache_update(mc, s_key, mapent, age); + cache_update(mc, source, s_key, mapent, age); cache_unlock(mc); free(s_key); @@ -1313,6 +1313,7 @@ char *attrs[3]; int scope = LDAP_SCOPE_SUBTREE; LDAP *ldap; + struct mapent *we; unsigned int wild = 0; int ret = CHE_MISSING; @@ -1466,7 +1467,7 @@ goto next; wild = 1; cache_writelock(mc); - cache_update(mc, "*", mapent, age); + cache_update(mc, source, "*", mapent, age); cache_unlock(mc); goto next; } @@ -1476,7 +1477,7 @@ goto next; cache_writelock(mc); - ret = cache_update(mc, s_key, mapent, age); + ret = cache_update(mc, source, s_key, mapent, age); cache_unlock(mc); free(s_key); @@ -1493,10 +1494,34 @@ ldap_msgfree(result); unbind_ldap_connection(ldap, ctxt); + /* Failed to find wild entry, update cache if needed */ + pthread_cleanup_push(cache_lock_cleanup, mc); cache_writelock(mc); - if (!wild && cache_lookup(mc, "*")) - cache_delete(mc, "*"); - cache_unlock(mc); + we = cache_lookup_distinct(mc, "*"); + if (we) { + /* Wildcard entry existed and is now gone */ + if (we->source == source && !wild) { + cache_delete(mc, "*"); + source->stale = 1; + } + } else { + /* Wildcard not in map but now is */ + if (wild) + source->stale = 1; + } + /* Not found in the map but found in the cache */ + if (ret == CHE_MISSING) { + struct mapent *exists = cache_lookup_distinct(mc, qKey); + if (exists && exists->source == source) { + if (exists->mapent) { + free(exists->mapent); + exists->mapent = NULL; + source->stale = 1; + exists->status = 0; + } + } + } + pthread_cleanup_pop(1); return ret; } @@ -1507,10 +1532,10 @@ { struct map_source *source; struct mapent_cache *mc; - struct mapent *me, *exists; + struct mapent *me; time_t now = time(NULL); time_t t_last_read; - int ret, cur_state, need_map = 0; + int ret, cur_state; source = ap->entry->current; ap->entry->current = NULL; @@ -1518,12 +1543,6 @@ mc = source->mc; - cache_readlock(mc); - exists = cache_lookup_distinct(mc, key); - if (exists && exists->mc != mc) - exists = NULL; - cache_unlock(mc); - master_source_current_wait(ap->entry); ap->entry->current = source; @@ -1535,44 +1554,28 @@ } 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); - t_last_read = me ? now - me->age : ap->exp_runfreq + 1; - cache_unlock(mc); - - if (t_last_read > ap->exp_runfreq) { - if ((ret & CHE_UPDATED) || - (exists && (ret & CHE_MISSING))) - need_map = 1; - } - - if (ret == CHE_MISSING && exists) { - pthread_cleanup_push(cache_lock_cleanup, mc); - cache_writelock(mc); - if (cache_delete(mc, key)) - rmdir_path(ap, key, ap->dev); - pthread_cleanup_pop(1); + while (me) { + if (me->source == source) { + t_last_read = now - me->age; + break; + } + me = cache_lookup_next(mc, me); } + cache_unlock(mc); - /* Have parent update its map */ - if (ap->ghost && need_map) { - int status; - + if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) source->stale = 1; - status = pthread_mutex_lock(&ap->state_mutex); - if (status) - fatal(status); - - nextstate(ap->state_pipe[1], ST_READMAP); - - status = pthread_mutex_unlock(&ap->state_mutex); - if (status) - fatal(status); - } - cache_readlock(mc); - if (ret == CHE_MISSING && !cache_lookup(mc, "*")) { + me = cache_lookup_distinct(mc, "*"); + if (ret == CHE_MISSING && (!me || me->source != source)) { cache_unlock(mc); return NSS_STATUS_NOTFOUND; } @@ -1648,7 +1651,10 @@ cache_readlock(mc); me = cache_lookup(mc, key); - if (me && me->mapent && *me->mapent) { + /* Stale mapent => check for wildcard */ + if (me && !me->mapent) + me = cache_lookup_distinct(mc, "*"); + if (me && (me->source == source || *me->key == '/')) { mapent_len = strlen(me->mapent); mapent = alloca(mapent_len + 1); strcpy(mapent, me->mapent); @@ -1670,7 +1676,7 @@ cache_writelock(mc); me = cache_lookup_distinct(mc, key); if (!me) - rv = cache_update(mc, key, NULL, now); + rv = cache_update(mc, source, key, NULL, now); if (rv != CHE_FAIL) { me = cache_lookup_distinct(mc, key); me->status = now + NEGATIVE_TIMEOUT; --- autofs-5.0.1/modules/lookup_yp.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/modules/lookup_yp.c 2007-05-04 14:08:10.000000000 +0800 @@ -272,7 +272,7 @@ *(mapent + vallen) = '\0'; cache_writelock(mc); - ret = cache_update(mc, key, mapent, age); + ret = cache_update(mc, source, key, mapent, age); cache_unlock(mc); free(key); @@ -389,7 +389,7 @@ } cache_writelock(mc); - ret = cache_update(mc, key, mapent, age); + ret = cache_update(mc, source, key, mapent, age); cache_unlock(mc); free(mapent); @@ -441,7 +441,7 @@ } cache_writelock(mc); - ret = cache_update(mc, "*", mapent, age); + ret = cache_update(mc, source, "*", mapent, age); cache_unlock(mc); free(mapent); @@ -456,7 +456,6 @@ struct mapent_cache *mc; struct mapent *exists; unsigned int map_order; - int need_map = 0; int ret = 0; source = ap->entry->current; @@ -465,12 +464,6 @@ mc = source->mc; - cache_readlock(mc); - exists = cache_lookup_distinct(mc, key); - if (exists && exists->mc != mc) - exists = NULL; - cache_unlock(mc); - master_source_current_wait(ap->entry); ap->entry->current = source; @@ -490,44 +483,53 @@ map_order = get_map_order(ctxt->domainname, ctxt->mapname); if (map_order > ctxt->order) { ctxt->order = map_order; - need_map = 1; + source->stale = 1; + } + + pthread_cleanup_push(cache_lock_cleanup, mc); + cache_writelock(mc); + exists = cache_lookup_distinct(mc, key); + /* Not found in the map but found in the cache */ + if (exists && exists->source == source && ret & CHE_MISSING) { + if (exists->mapent) { + free(exists->mapent); + exists->mapent = NULL; + source->stale = 1; + exists->status = 0; + } } + pthread_cleanup_pop(1); if (ret == CHE_MISSING) { + struct mapent *we; int wild = CHE_MISSING; master_source_current_wait(ap->entry); ap->entry->current = source; wild = lookup_wild(ap, ctxt); - if (wild == CHE_UPDATED || CHE_OK) - return NSS_STATUS_SUCCESS; - + /* + * Check for map change and update as needed for + * following cache lookup. + */ pthread_cleanup_push(cache_lock_cleanup, mc); cache_writelock(mc); - if (wild == CHE_MISSING) - cache_delete(mc, "*"); - - if (cache_delete(mc, key) && wild & (CHE_MISSING | CHE_FAIL)) - rmdir_path(ap, key, ap->dev); + we = cache_lookup_distinct(mc, "*"); + if (we) { + /* Wildcard entry existed and is now gone */ + if (we->source == source && (wild & CHE_MISSING)) { + cache_delete(mc, "*"); + source->stale = 1; + } + } else { + /* Wildcard not in map but now is */ + if (wild & (CHE_OK || CHE_UPDATED)) + source->stale = 1; + } pthread_cleanup_pop(1); - } - - /* Have parent update its map if needed */ - if (ap->ghost && need_map) { - int status; - source->stale = 1; - - status = pthread_mutex_lock(&ap->state_mutex); - if (status) - fatal(status); - - nextstate(ap->state_pipe[1], ST_READMAP); - - status = pthread_mutex_unlock(&ap->state_mutex); - if (status) - fatal(status); + if (wild & (CHE_OK || CHE_UPDATED)) + return NSS_STATUS_SUCCESS; } if (ret == CHE_MISSING) @@ -602,7 +604,10 @@ cache_readlock(mc); me = cache_lookup(mc, key); - if (me && me->mapent && *me->mapent) { + /* Stale mapent => check for wildcard */ + if (me && !me->mapent) + me = cache_lookup_distinct(mc, "*"); + if (me && (me->source == source || *me->key == '/')) { mapent_len = strlen(me->mapent); mapent = alloca(mapent_len + 1); strcpy(mapent, me->mapent); @@ -623,7 +628,7 @@ cache_writelock(mc); me = cache_lookup_distinct(mc, key); if (!me) - rv = cache_update(mc, key, NULL, now); + rv = cache_update(mc, source, key, NULL, now); if (rv != CHE_FAIL) { me = cache_lookup_distinct(mc, key); me->status = now + NEGATIVE_TIMEOUT; --- autofs-5.0.1/daemon/direct.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/daemon/direct.c 2007-05-04 14:08:10.000000000 +0800 @@ -526,7 +526,7 @@ return -1; /* TODO: check map type */ - if (lookup_nss_read_map(ap, now)) + if (lookup_nss_read_map(ap, NULL, now)) lookup_prune_cache(ap, now); else { error(ap->logopt, "failed to read direct map"); @@ -1413,7 +1413,7 @@ } cont: - status = lookup_nss_mount(ap, mt->name, strlen(mt->name)); + status = lookup_nss_mount(ap, NULL, mt->name, strlen(mt->name)); /* * Direct mounts are always a single mount. If it fails there's * nothing to undo so just complain --- autofs-5.0.1/daemon/indirect.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/daemon/indirect.c 2007-05-04 14:08:10.000000000 +0800 @@ -261,7 +261,7 @@ return -1; /* TODO: read map, determine map type is OK */ - if (lookup_nss_read_map(ap, now)) + if (lookup_nss_read_map(ap, NULL, now)) lookup_prune_cache(ap, now); else { error(ap->logopt, "failed to read map for %s", ap->path); @@ -884,7 +884,7 @@ free(tsv); } cont: - status = lookup_nss_mount(ap, mt->name, mt->len); + status = lookup_nss_mount(ap, NULL, mt->name, mt->len); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); if (status) { send_ready(ap->ioctlfd, mt->wait_queue_token); --- autofs-5.0.1/daemon/state.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/daemon/state.c 2007-05-04 14:08:10.000000000 +0800 @@ -378,7 +378,7 @@ pthread_cleanup_push(do_readmap_cleanup, ra); - status = lookup_nss_read_map(ap, now); + status = lookup_nss_read_map(ap, NULL, now); if (!status) pthread_exit(NULL); --- autofs-5.0.1/daemon/lookup.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/daemon/lookup.c 2007-05-04 14:08:10.000000000 +0800 @@ -261,11 +261,16 @@ if (!ap->ghost && ap->type != LKP_DIRECT) return NSS_STATUS_SUCCESS; + if (!map->stale) + return NSS_STATUS_SUCCESS; + master_source_current_wait(ap->entry); ap->entry->current = map; status = lookup->lookup_read_map(ap, age, lookup->context); + map->stale = 0; + /* * For maps that don't support enumeration return success * and do whatever we must to have autofs function with an @@ -302,7 +307,9 @@ instance = master_find_source_instance(map, type, format, 0, NULL); if (!instance) { - instance = master_add_source_instance(map, type, format, age); + int argc = map->argc; + const char **argv = map->argv; + instance = master_add_source_instance(map, type, format, age, argc, argv); if (!instance) return NSS_STATUS_UNAVAIL; instance->recurse = map->recurse; @@ -321,7 +328,9 @@ instance = master_find_source_instance(map, type, format, 0, NULL); if (!instance) { - instance = master_add_source_instance(map, type, format, age); + int argc = map->argc; + const char **argv = map->argv; + instance = master_add_source_instance(map, type, format, age, argc, argv); if (!instance) return NSS_STATUS_UNAVAIL; instance->recurse = map->recurse; @@ -343,7 +352,6 @@ struct autofs_point *ap, struct map_source *map, time_t age) { enum nsswitch_status result; - struct map_source *instance; struct map_source tmap; char *path; @@ -363,15 +371,6 @@ return NSS_STATUS_NOTFOUND; } - instance = master_find_source_instance(map, - "file", map->format, map->argc, map->argv); - if (!instance) - instance = master_find_source_instance(map, - "program", map->format, map->argc, map->argv); - - if (instance) - return read_file_source_instance(ap, map, age); - this->source[4] = '\0'; tmap.type = this->source; tmap.format = map->format; @@ -412,10 +411,12 @@ result = read_file_source_instance(ap, &tmap, age); pthread_cleanup_pop(1); + map->instance = tmap.instance; + return result; } -int lookup_nss_read_map(struct autofs_point *ap, time_t age) +int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time_t age) { struct master_mapent *entry = ap->entry; struct list_head nsslist; @@ -433,7 +434,10 @@ */ pthread_cleanup_push(master_source_lock_cleanup, entry); master_source_readlock(entry); - map = entry->maps; + if (source) + map = source; + else + map = entry->maps; while (map) { /* Is map source up to date or no longer valid */ if (!map->stale || entry->age > map->age) { @@ -655,7 +659,9 @@ instance = master_find_source_instance(map, type, format, 0, NULL); if (!instance) { - instance = master_add_source_instance(map, type, format, age); + int argc = map->argc; + const char **argv = map->argv; + instance = master_add_source_instance(map, type, format, age, argc, argv); if (!instance) return NSS_STATUS_NOTFOUND; instance->recurse = map->recurse; @@ -675,7 +681,9 @@ instance = master_find_source_instance(map, type, format, 0, NULL); if (!instance) { - instance = master_add_source_instance(map, type, format, age); + int argc = map->argc; + const char **argv = map->argv; + instance = master_add_source_instance(map, type, format, age, argc, argv); if (!instance) return NSS_STATUS_NOTFOUND; instance->recurse = map->recurse; @@ -690,7 +698,6 @@ const char *name, int name_len) { enum nsswitch_status result; - struct map_source *instance; struct map_source tmap; char *path; @@ -710,13 +717,6 @@ return NSS_STATUS_NOTFOUND; } - instance = master_find_source_instance(map, "file", map->format, 0, NULL); - if (!instance) - instance = master_find_source_instance(map, "program", map->format, 0, NULL); - - if (instance) - return lookup_name_file_source_instance(ap, map, name, name_len); - this->source[4] = '\0'; tmap.type = this->source; tmap.format = map->format; @@ -754,13 +754,15 @@ result = lookup_name_file_source_instance(ap, &tmap, name, name_len); + map->instance = tmap.instance; + /* path is freed in free_argv */ free_argv(tmap.argc, tmap.argv); return result; } -int lookup_nss_mount(struct autofs_point *ap, const char *name, int name_len) +int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const char *name, int name_len) { struct master_mapent *entry = ap->entry; struct list_head nsslist; @@ -777,7 +779,10 @@ */ pthread_cleanup_push(master_source_lock_cleanup, entry); master_source_readlock(entry); - map = entry->maps; + if (source) + map = source; + else + map = entry->maps; while (map) { /* * Only consider map sources that have been read since @@ -858,11 +863,28 @@ map = map->next; } + send_map_update_request(ap); pthread_cleanup_pop(1); return !result; } +static void lookup_close_lookup_instances(struct map_source *map) +{ + struct map_source *instance; + + instance = map->instance; + while (instance) { + lookup_close_lookup_instances(instance); + instance = instance->next; + } + + if (map->lookup) { + close_lookup(map->lookup); + map->lookup = NULL; + } +} + void lookup_close_lookup(struct autofs_point *ap) { struct map_source *map; @@ -872,21 +894,7 @@ return; while (map) { - struct map_source *instance; - - instance = map->instance; - while (instance) { - if (instance->lookup) { - close_lookup(instance->lookup); - instance->lookup = NULL; - } - instance = instance->next; - } - - if (map->lookup) { - close_lookup(map->lookup); - map->lookup = NULL; - } + lookup_close_lookup_instances(map); map = map->next; } return; @@ -927,6 +935,7 @@ map = entry->maps; while (map) { + /* Is the map stale */ if (!map->stale) { map = map->next; continue; @@ -958,7 +967,7 @@ if (is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) { debug(ap->logopt, - "prune posponed, %s is mounted", path); + "prune check posponed, %s mounted", path); free(key); free(path); continue; --- autofs-5.0.1/lib/master.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/lib/master.c 2007-05-04 14:08:10.000000000 +0800 @@ -292,10 +292,8 @@ return source; } -void master_free_map_source(struct map_source *source, unsigned int free_cache) +static void __master_free_map_source(struct map_source *source, unsigned int free_cache) { - int status; - if (source->type) free(source->type); if (source->format) @@ -318,20 +316,12 @@ if (source->instance) { struct map_source *instance, *next; - status = pthread_mutex_lock(&instance_mutex); - if (status) - fatal(status); - instance = source->instance; while (instance) { next = instance->next; - master_free_map_source(instance, 0); + __master_free_map_source(instance, 0); instance = next; } - - status = pthread_mutex_unlock(&instance_mutex); - if (status) - fatal(status); } free(source); @@ -339,6 +329,21 @@ return; } +void master_free_map_source(struct map_source *source, unsigned int free_cache) +{ + int status; + + status = pthread_mutex_lock(&instance_mutex); + if (status) + fatal(status); + + __master_free_map_source(source, free_cache); + + status = pthread_mutex_unlock(&instance_mutex); + if (status) + fatal(status); +} + struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv) { struct map_source *map; @@ -378,19 +383,15 @@ } struct map_source * -master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age) +master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv) { struct map_source *instance; struct map_source *new; char *ntype, *nformat; - const char **tmpargv, *name; + const char **tmpargv; int status; - if (!type) - return NULL; - - instance = master_find_source_instance(source, - type, format, source->argc, source->argv); + instance = master_find_source_instance(source, type, format, argc, argv); if (instance) return instance; @@ -399,12 +400,14 @@ return NULL; memset(new, 0, sizeof(struct map_source)); - ntype = strdup(type); - if (!ntype) { - master_free_map_source(new, 0); - return NULL; + if (type) { + ntype = strdup(type); + if (!ntype) { + master_free_map_source(new, 0); + return NULL; + } + new->type = ntype; } - new->type = ntype; if (format) { nformat = strdup(format); @@ -418,17 +421,16 @@ new->age = age; new->master_line = 0; new->mc = source->mc; + new->stale = 1; - tmpargv = copy_argv(source->argc, source->argv); + tmpargv = copy_argv(argc, argv); if (!tmpargv) { master_free_map_source(new, 0); return NULL; } - new->argc = source->argc; + new->argc = argc; new->argv = tmpargv; - name = new->argv[0]; - status = pthread_mutex_lock(&instance_mutex); if (status) fatal(status); @@ -451,6 +453,71 @@ return new; } +static void check_stale_instances(struct map_source *source) +{ + struct map_source *map; + + if (!source) + return; + + map = source->instance; + while (map) { + if (map->stale) { + source->stale = 1; + break; + } + check_stale_instances(map->instance); + map = map->next; + } + + return; +} + +void send_map_update_request(struct autofs_point *ap) +{ + struct map_source *map; + int status, need_update = 0; + + if (!ap->ghost) + return; + + status = pthread_mutex_lock(&instance_mutex); + if (status) + fatal(status); + + map = ap->entry->maps; + while (map) { + check_stale_instances(map); + map = map->next; + } + + map = ap->entry->maps; + while (map) { + if (map->stale) { + need_update = 1; + break; + } + map = map->next; + } + + status = pthread_mutex_unlock(&instance_mutex); + if (status) + fatal(status); + + if (!need_update) + return; + + status = pthread_mutex_lock(&ap->state_mutex); + if (status) + fatal(status); + nextstate(ap->state_pipe[1], ST_READMAP); + status = pthread_mutex_unlock(&ap->state_mutex); + if (status) + fatal(status); + + return; +} + void master_source_writelock(struct master_mapent *entry) { int status; --- autofs-5.0.1/lib/master_parse.y.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/lib/master_parse.y 2007-05-04 14:08:10.000000000 +0800 @@ -533,7 +533,7 @@ /* Add null map entries to the null map cache */ if (type && !strcmp(type, "null")) { cache_writelock(nc); - cache_update(nc, path, NULL, lineno); + cache_update(nc, NULL, path, NULL, lineno); cache_unlock(nc); local_free_vars(); return 1; --- autofs-5.0.1/lib/cache.c.map-update-source-only 2007-05-04 14:07:54.000000000 +0800 +++ autofs-5.0.1/lib/cache.c 2007-05-04 14:08:10.000000000 +0800 @@ -509,7 +509,7 @@ } /* cache must be write locked by caller */ -int cache_add(struct mapent_cache *mc, const char *key, const char *mapent, time_t age) +int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age) { struct mapent *me, *existing = NULL; char *pkey, *pent; @@ -541,6 +541,7 @@ me->age = age; me->status = 0; me->mc = mc; + me->source = ms; INIT_LIST_HEAD(&me->ino_index); INIT_LIST_HEAD(&me->multi_list); me->multi = NULL; @@ -618,7 +619,7 @@ if (me && me != owner) return CHE_DUPLICATE; - ret = cache_add(mc, key, mapent, age); + ret = cache_add(mc, owner->source, key, mapent, age); if (ret == CHE_FAIL) { warn(LOGOPT_ANY, "failed to add key %s to cache", key); return CHE_FAIL; @@ -686,7 +687,7 @@ } /* cache must be write locked by caller */ -int cache_update(struct mapent_cache *mc, const char *key, const char *mapent, time_t age) +int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age) { struct mapent *me = NULL; char *pent; @@ -694,7 +695,7 @@ me = cache_lookup(mc, key); if (!me || (*me->key == '*' && *key != '*')) { - ret = cache_add(mc, key, mapent, age); + ret = cache_add(mc, ms, key, mapent, age); if (!ret) { debug(LOGOPT_NONE, "failed for %s", key); return CHE_FAIL; @@ -705,9 +706,11 @@ if (me->age == age) return CHE_OK; - if (!mapent) + if (!mapent) { + if (me->mapent) + free(me->mapent); me->mapent = NULL; - else if (!me->mapent || strcmp(me->mapent, mapent) != 0) { + } else if (!me->mapent || strcmp(me->mapent, mapent) != 0) { pent = malloc(strlen(mapent) + 1); if (pent == NULL) return CHE_FAIL;