diff --git a/CHANGELOG b/CHANGELOG index c47648d..48d811a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ ?/7/2006 autofs-5.0.1 --------------------- - code cleanup. +- fix race for current map source. 13/7/2006 autofs-5.0.1 rc1 -------------------------- diff --git a/daemon/direct.c b/daemon/direct.c index bb75755..93af751 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -531,7 +531,6 @@ force_umount: int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, int is_autofs_fs) { - struct map_source *map = ap->entry->current; struct mnt_params *mp; time_t timeout = ap->exp_timeout; struct stat st; @@ -636,7 +635,7 @@ int mount_autofs_offset(struct autofs_po goto out_close; } - cache_set_ino_index(map->mc, me->key, st.st_dev, st.st_ino); + cache_set_ino_index(me->source->mc, me->key, st.st_dev, st.st_ino); close(me->ioctlfd); me->ioctlfd = -1; diff --git a/daemon/lookup.c b/daemon/lookup.c index 0681407..cad98d2 100644 --- a/daemon/lookup.c +++ b/daemon/lookup.c @@ -411,11 +411,11 @@ int lookup_nss_read_map(struct autofs_po sched_yield(); - entry->current = map; - if (map->type) { debug(ap->logopt, "reading map %s %s", map->type, map->argv[0]); + master_source_current_wait(entry); + entry->current = map; result = do_read_map(ap, map, age); map = map->next; continue; @@ -432,10 +432,14 @@ int lookup_nss_read_map(struct autofs_po map->type = tmp; debug(ap->logopt, "reading map %s %s", tmp, map->argv[0]); + master_source_current_wait(entry); + entry->current = map; result = do_read_map(ap, map, age); } else { debug(ap->logopt, "reading map file %s", map->argv[0]); + master_source_current_wait(entry); + entry->current = map; result = read_file_source_instance(ap, map, age); } map = map->next; @@ -448,7 +452,7 @@ int lookup_nss_read_map(struct autofs_po if (result) { error(ap->logopt, "can't to read name service switch config."); - goto done; + break; } head = &nsslist; @@ -460,25 +464,28 @@ int lookup_nss_read_map(struct autofs_po debug(ap->logopt, "reading map %s %s", this->source, map->argv[0]); + master_source_current_wait(entry); + entry->current = map; result = read_map_source(this, ap, map, age); if (result == NSS_STATUS_UNKNOWN) continue; status = check_nss_result(this, result); if (status >= 0) { - free_sources(&nsslist); result = !status; - goto done; + map = NULL; + break; } } if (!list_empty(&nsslist)) free_sources(&nsslist); + if (!map) + break; + map = map->next; } -done: - entry->current = NULL; pthread_cleanup_pop(1); return !result; @@ -737,11 +744,14 @@ int lookup_nss_mount(struct autofs_point } sched_yield(); - entry->current = map; + if (map->type) { + master_source_current_wait(entry); + entry->current = map; result = do_lookup_mount(ap, map, name, name_len); + if (result == NSS_STATUS_SUCCESS) - goto done; + break; map = map->next; continue; @@ -756,12 +766,17 @@ int lookup_nss_mount(struct autofs_point continue; } map->type = tmp; + master_source_current_wait(entry); + entry->current = map; result = do_lookup_mount(ap, map, name, name_len); - } else + } else { + master_source_current_wait(entry); + entry->current = map; result = lookup_name_file_source_instance(ap, map, name, name_len); + } if (result == NSS_STATUS_SUCCESS) - goto done; + break; map = map->next; continue; @@ -774,7 +789,7 @@ int lookup_nss_mount(struct autofs_point error(ap->logopt, "can't to read name service switch config."); result = 1; - goto done; + break; } head = &nsslist; @@ -783,7 +798,10 @@ int lookup_nss_mount(struct autofs_point this = list_entry(p, struct nss_source, list); + master_source_current_wait(entry); + entry->current = map; result = lookup_map_name(this, ap, map, name, name_len); + if (result == NSS_STATUS_UNKNOWN) { map = map->next; continue; @@ -791,18 +809,19 @@ int lookup_nss_mount(struct autofs_point status = check_nss_result(this, result); if (status >= 0) { - free_sources(&nsslist); - goto done; + map = NULL; + break; } } if (!list_empty(&nsslist)) free_sources(&nsslist); + if (!map) + break; + map = map->next; } -done: - entry->current = NULL; pthread_cleanup_pop(1); return !result; diff --git a/daemon/state.c b/daemon/state.c index 4fda6df..a5305b6 100644 --- a/daemon/state.c +++ b/daemon/state.c @@ -372,7 +372,6 @@ static void *do_readmap(void *arg) map = map->next; continue; } - ap->entry->current = map; mc = map->mc; pthread_cleanup_push(cache_lock_cleanup, mc); cache_readlock(mc); @@ -392,9 +391,8 @@ static void *do_readmap(void *arg) pthread_cleanup_pop(1); map = map->next; } - pthread_cleanup_pop(1); tree_free_mnt_tree(mnts); - ap->entry->current = NULL; + pthread_cleanup_pop(1); lookup_prune_cache(ap, now); } diff --git a/include/master.h b/include/master.h index 8e1b375..dcd77eb 100644 --- a/include/master.h +++ b/include/master.h @@ -40,6 +40,8 @@ struct master_mapent { pthread_t thid; time_t age; pthread_rwlock_t source_lock; + pthread_mutex_t current_mutex; + pthread_cond_t current_cond; struct map_source *first; struct map_source *current; struct map_source *maps; @@ -81,6 +83,8 @@ void master_source_writelock(struct mast void master_source_readlock(struct master_mapent *); void master_source_unlock(struct master_mapent *); void master_source_lock_cleanup(void *); +void master_source_current_wait(struct master_mapent *); +void master_source_current_signal(struct master_mapent *); struct master_mapent *master_find_mapent(struct master *, const char *); struct master_mapent *master_new_mapent(const char *, time_t); void master_add_mapent(struct master *, struct master_mapent *); diff --git a/lib/master.c b/lib/master.c index f035af2..3cf0428 100644 --- a/lib/master.c +++ b/lib/master.c @@ -515,6 +515,49 @@ void master_source_lock_cleanup(void *ar return; } +void master_source_current_wait(struct master_mapent *entry) +{ + int status; + + status = pthread_mutex_lock(&entry->current_mutex); + if (status) { + error(LOGOPT_ANY, "entry current source lock failed"); + fatal(status); + } + + while (entry->current != NULL) { + status = pthread_cond_wait( + &entry->current_cond, &entry->current_mutex); + if (status) { + error(LOGOPT_ANY, + "entry current source condition wait failed"); + fatal(status); + } + } + + return; +} + +void master_source_current_signal(struct master_mapent *entry) +{ + int status; + + status = pthread_cond_signal(&entry->current_cond); + if (status) { + error(LOGOPT_ANY, + "entry current source condition signal failed"); + fatal(status); + } + + status = pthread_mutex_unlock(&entry->current_mutex); + if (status) { + error(LOGOPT_ANY, "entry current source unlock failed"); + fatal(status); + } + + return; +} + struct master_mapent *master_find_mapent(struct master *master, const char *path) { struct list_head *head, *p; @@ -575,6 +618,14 @@ struct master_mapent *master_new_mapent( if (status) fatal(status); + status = pthread_mutex_init(&entry->current_mutex, NULL); + if (status) + fatal(status); + + status = pthread_cond_init(&entry->current_cond, NULL); + if (status) + fatal(status); + INIT_LIST_HEAD(&entry->list); return entry; @@ -648,6 +699,14 @@ void master_free_mapent(struct master_ma if (status) fatal(status); + status = pthread_mutex_destroy(&entry->current_mutex); + if (status) + fatal(status); + + status = pthread_cond_destroy(&entry->current_cond); + if (status) + fatal(status); + free(entry); return; diff --git a/modules/lookup_file.c b/modules/lookup_file.c index dff7638..913af6a 100644 --- a/modules/lookup_file.c +++ b/modules/lookup_file.c @@ -459,7 +459,7 @@ static struct autofs_point * prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned int inc) { struct master_mapent *entry; - struct map_source *current = ap->entry->current; + struct map_source *current; struct map_source *source; struct autofs_point *iap; char *type, *map, *fmt; @@ -470,6 +470,10 @@ prepare_plus_include(struct autofs_point unsigned int ghost = ap->ghost; char *buf, *tmp; + current = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + entry = master_new_mapent(ap->path, ap->entry->age); if (!entry) { error(ap->logopt, MODPREFIX "malloc failed for entry"); @@ -549,14 +553,20 @@ prepare_plus_include(struct autofs_point int lookup_read_map(struct autofs_point *ap, time_t age, void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char *key; char *mapent; struct stat st; FILE *f; int entry; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + if (source->recurse) return NSS_STATUS_UNAVAIL; @@ -611,6 +621,9 @@ int lookup_read_map(struct autofs_point inc = check_self_include(key, ctxt); + master_source_current_wait(ap->entry); + ap->entry->current = source; + iap = prepare_plus_include(ap, age, key, inc); if (!iap) { debug(ap->logopt, @@ -664,14 +677,20 @@ static int lookup_one(struct autofs_poin const char *key, int key_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char mkey[KEY_MAX_LEN + 1]; char mapent[MAPENT_MAX_LEN + 1]; time_t age = time(NULL); FILE *f; int entry, ret; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + f = fopen(ctxt->mapname, "r"); if (!f) { error(ap->logopt, @@ -696,6 +715,9 @@ static int lookup_one(struct autofs_poin inc = check_self_include(mkey, ctxt); + master_source_current_wait(ap->entry); + ap->entry->current = source; + iap = prepare_plus_include(ap, age, mkey, inc); if (!iap) { debug(ap->logopt, @@ -733,14 +755,20 @@ static int lookup_one(struct autofs_poin static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char mkey[KEY_MAX_LEN + 1]; char mapent[MAPENT_MAX_LEN + 1]; time_t age = time(NULL); FILE *f; int entry, ret; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + f = fopen(ctxt->mapname, "r"); if (!f) { error(ap->logopt, @@ -762,6 +790,9 @@ static int lookup_wild(struct autofs_poi inc = check_self_include(mkey, ctxt); + master_source_current_wait(ap->entry); + ap->entry->current = source; + iap = prepare_plus_include(ap, age, mkey, inc); if (!iap) { debug(ap->logopt, @@ -801,18 +832,27 @@ static int check_map_indirect(struct aut char *key, int key_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; struct mapent *exists; int need_map = 0; int ret = CHE_OK; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + cache_readlock(mc); exists = cache_lookup_distinct(mc, key); if (exists && exists->source != source) exists = NULL; cache_unlock(mc); + master_source_current_wait(ap->entry); + ap->entry->current = source; + ret = lookup_one(ap, key, key_len, ctxt); if (ret == CHE_COMPLETED) return NSS_STATUS_COMPLETED; @@ -827,6 +867,9 @@ static int check_map_indirect(struct aut if (ret == CHE_MISSING) { 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; @@ -871,8 +914,8 @@ static int check_map_indirect(struct aut int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; struct mapent *me; char key[KEY_MAX_LEN + 1]; int key_len; @@ -881,6 +924,12 @@ int lookup_mount(struct autofs_point *ap int status = 0; int ret = 1; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + if (source->recurse) return NSS_STATUS_UNAVAIL; @@ -925,6 +974,9 @@ int lookup_mount(struct autofs_point *ap if (!lkp_key) return NSS_STATUS_UNKNOWN; + master_source_current_wait(ap->entry); + ap->entry->current = source; + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); free(lkp_key); if (status) { @@ -949,6 +1001,9 @@ int lookup_mount(struct autofs_point *ap cache_unlock(mc); if (mapent) { + master_source_current_wait(ap->entry); + ap->entry->current = source; + debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent); ret = ctxt->parse->parse_mount(ap, key, key_len, mapent, ctxt->parse->context); diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c index 36e8457..9a7794d 100644 --- a/modules/lookup_ldap.c +++ b/modules/lookup_ldap.c @@ -1071,8 +1071,8 @@ static int read_one_map(struct autofs_po struct lookup_context *ctxt, time_t age, int *result_ldap) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; int rv, i, l, count; char buf[MAX_ERR_BUF]; char *query; @@ -1084,10 +1084,11 @@ static int read_one_map(struct autofs_po int scope = LDAP_SCOPE_SUBTREE; LDAP *ldap; - if (ctxt == NULL) { - crit(ap->logopt, MODPREFIX "context was NULL"); - return NSS_STATUS_UNAVAIL; - } + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; class = ctxt->entry_obj_class; entry = ctxt->entry_attr; @@ -1278,8 +1279,8 @@ int lookup_read_map(struct autofs_point static int lookup_one(struct autofs_point *ap, char *qKey, int qKey_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; int rv, i, l, ql, count; char buf[MAX_ERR_BUF]; time_t age = time(NULL); @@ -1295,6 +1296,12 @@ static int lookup_one(struct autofs_poin unsigned int wild = 0; int ret = CHE_MISSING; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + if (ctxt == NULL) { crit(ap->logopt, MODPREFIX "context was NULL"); return CHE_FAIL; @@ -1465,19 +1472,28 @@ static int check_map_indirect(struct aut char *key, int key_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; struct mapent *me, *exists; time_t now = time(NULL); time_t t_last_read; int ret, need_map = 0; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + cache_readlock(mc); exists = cache_lookup_distinct(mc, key); if (exists && exists->source != source) exists = NULL; cache_unlock(mc); + master_source_current_wait(ap->entry); + ap->entry->current = source; + ret = lookup_one(ap, key, key_len, ctxt); if (ret == CHE_FAIL) return NSS_STATUS_NOTFOUND; @@ -1531,8 +1547,8 @@ static int check_map_indirect(struct aut int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; struct mapent *me; char key[KEY_MAX_LEN + 1]; int key_len; @@ -1541,6 +1557,12 @@ int lookup_mount(struct autofs_point *ap int status = 0; int ret = 1; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + debug(ap->logopt, MODPREFIX "looking up %s", name); key_len = snprintf(key, KEY_MAX_LEN, "%s", name); @@ -1575,6 +1597,9 @@ int lookup_mount(struct autofs_point *ap if (!lkp_key) return NSS_STATUS_UNKNOWN; + master_source_current_wait(ap->entry); + ap->entry->current = source; + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); free(lkp_key); if (status) { @@ -1596,6 +1621,9 @@ int lookup_mount(struct autofs_point *ap cache_unlock(mc); if (mapent) { + master_source_current_wait(ap->entry); + ap->entry->current = source; + debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent); ret = ctxt->parse->parse_mount(ap, key, key_len, mapent, ctxt->parse->context); diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c index 2f45ad8..cb5d620 100644 --- a/modules/lookup_nisplus.c +++ b/modules/lookup_nisplus.c @@ -156,8 +156,8 @@ int lookup_read_master(struct master *ma int lookup_read_map(struct autofs_point *ap, time_t age, void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char *tablename; nis_result *result; nis_object *this; @@ -165,6 +165,12 @@ int lookup_read_map(struct autofs_point char *key, *mapent; char buf[MAX_ERR_BUF]; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); if (!tablename) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); @@ -226,8 +232,8 @@ static int lookup_one(struct autofs_poin const char *key, int key_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char *tablename; nis_result *result; nis_object *this; @@ -236,6 +242,12 @@ static int lookup_one(struct autofs_poin int ret; char buf[MAX_ERR_BUF]; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + tablename = alloca(strlen(key) + strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); if (!tablename) { @@ -270,8 +282,8 @@ static int lookup_one(struct autofs_poin static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char *tablename; nis_result *result; nis_object *this; @@ -280,6 +292,12 @@ static int lookup_wild(struct autofs_poi int ret; char buf[MAX_ERR_BUF]; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); if (!tablename) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); @@ -314,20 +332,29 @@ static int check_map_indirect(struct aut char *key, int key_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; 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; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + cache_readlock(mc); exists = cache_lookup_distinct(mc, key); if (exists && exists->source != source) exists = NULL; cache_unlock(mc); + master_source_current_wait(ap->entry); + ap->entry->current = source; + /* check map and if change is detected re-read map */ ret = lookup_one(ap, key, key_len, ctxt); if (ret == CHE_FAIL) @@ -353,6 +380,9 @@ static int check_map_indirect(struct aut if (ret == CHE_MISSING) { 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; @@ -393,8 +423,8 @@ static int check_map_indirect(struct aut int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char key[KEY_MAX_LEN + 1]; int key_len; char *mapent = NULL; @@ -403,6 +433,12 @@ int lookup_mount(struct autofs_point *ap int status; int ret = 1; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + debug(ap->logopt, MODPREFIX "looking up %s", name); key_len = snprintf(key, KEY_MAX_LEN, "%s", name); @@ -436,6 +472,9 @@ int lookup_mount(struct autofs_point *ap if (!lkp_key) return NSS_STATUS_UNKNOWN; + master_source_current_wait(ap->entry); + ap->entry->current = source; + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); if (status) { debug(ap->logopt, @@ -456,6 +495,9 @@ int lookup_mount(struct autofs_point *ap cache_unlock(mc); if (mapent) { + master_source_current_wait(ap->entry); + ap->entry->current = source; + debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent); ret = ctxt->parse->parse_mount(ap, key, key_len, mapent, ctxt->parse->context); diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c index ad37697..4114aaa 100644 --- a/modules/lookup_yp.c +++ b/modules/lookup_yp.c @@ -50,6 +50,7 @@ struct callback_master_data { struct callback_data { struct autofs_point *ap; + struct map_source *source; time_t age; }; @@ -244,7 +245,7 @@ int yp_all_callback(int status, char *yp { struct callback_data *cbdata = (struct callback_data *) ypcb_data; struct autofs_point *ap = cbdata->ap; - struct map_source *source = ap->entry->current; + struct map_source *source = cbdata->source; struct mapent_cache *mc = source->mc; time_t age = cbdata->age; char *key; @@ -292,18 +293,22 @@ int lookup_read_map(struct autofs_point char *mapname; int err; - mapname = alloca(strlen(ctxt->mapname) + 1); - if (!mapname) - return 0; - - strcpy(mapname, ctxt->mapname); - ypcb_data.ap = ap; + ypcb_data.source = ap->entry->current; ypcb_data.age = age; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + ypcb.foreach = yp_all_callback; ypcb.data = (char *) &ypcb_data; + mapname = alloca(strlen(ctxt->mapname) + 1); + if (!mapname) + return 0; + + strcpy(mapname, ctxt->mapname); + err = yp_all((char *) ctxt->domainname, mapname, &ypcb); if (err != YPERR_SUCCESS) { @@ -333,14 +338,20 @@ static int lookup_one(struct autofs_poin const char *key, int key_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char *mapname; char *mapent; int mapent_len; time_t age = time(NULL); int ret; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + mapname = alloca(strlen(ctxt->mapname) + 1); if (!mapname) return 0; @@ -385,14 +396,20 @@ static int lookup_one(struct autofs_poin static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char *mapname; char *mapent; int mapent_len; time_t age = time(NULL); int ret; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + mapname = alloca(strlen(ctxt->mapname) + 1); if (!mapname) return 0; @@ -433,19 +450,28 @@ static int check_map_indirect(struct aut char *key, int key_len, struct lookup_context *ctxt) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; struct mapent *exists; unsigned int map_order; int need_map = 0; int ret = 0; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + cache_readlock(mc); exists = cache_lookup_distinct(mc, key); if (exists && exists->source != source) exists = NULL; cache_unlock(mc); + master_source_current_wait(ap->entry); + ap->entry->current = source; + /* check map and if change is detected re-read map */ ret = lookup_one(ap, key, key_len, ctxt); if (ret == CHE_FAIL) @@ -468,6 +494,9 @@ static int check_map_indirect(struct aut if (ret == CHE_MISSING) { 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; @@ -508,8 +537,8 @@ static int check_map_indirect(struct aut int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char key[KEY_MAX_LEN + 1]; int key_len; char *mapent = NULL; @@ -518,6 +547,12 @@ int lookup_mount(struct autofs_point *ap int status = 0; int ret = 1; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + debug(ap->logopt, MODPREFIX "looking up %s", name); key_len = snprintf(key, KEY_MAX_LEN, "%s", name); @@ -551,6 +586,9 @@ int lookup_mount(struct autofs_point *ap if (!lkp_key) return NSS_STATUS_UNKNOWN; + master_source_current_wait(ap->entry); + ap->entry->current = source; + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); free(lkp_key); if (status) { @@ -572,6 +610,9 @@ int lookup_mount(struct autofs_point *ap cache_unlock(mc); if (mapent) { + master_source_current_wait(ap->entry); + ap->entry->current = source; + debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent); ret = ctxt->parse->parse_mount(ap, key, key_len, mapent, ctxt->parse->context); diff --git a/modules/parse_hesiod.c b/modules/parse_hesiod.c index 8483a99..7f125eb 100644 --- a/modules/parse_hesiod.c +++ b/modules/parse_hesiod.c @@ -229,6 +229,9 @@ int parse_mount(struct autofs_point *ap, char *q; const char *p; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + p = mapent; q = fstype; diff --git a/modules/parse_sun.c b/modules/parse_sun.c index 7e0f211..d415660 100644 --- a/modules/parse_sun.c +++ b/modules/parse_sun.c @@ -753,13 +753,19 @@ add_offset_entry(struct autofs_point *ap const char *path, const char *myoptions, const char *loc, time_t age) { - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; char m_key[PATH_MAX + 1]; char m_mapent[MAPENT_MAX_LEN + 1]; int m_key_len, m_mapent_len; int ret; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + m_key_len = m_root_len + strlen(path) + 1; if (m_key_len > PATH_MAX) { error(ap->logopt, @@ -890,8 +896,8 @@ int parse_mount(struct autofs_point *ap, { struct parse_context *ctxt = (struct parse_context *) context; char buf[MAX_ERR_BUF]; - struct map_source *source = ap->entry->current; - struct mapent_cache *mc = source->mc; + struct map_source *source; + struct mapent_cache *mc; struct mapent *me; char *pmapent, *options; const char *p; @@ -899,6 +905,12 @@ int parse_mount(struct autofs_point *ap, int optlen; int slashify = ctxt->slashify_colons; + source = ap->entry->current; + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + + mc = source->mc; + if (!mapent) { error(ap->logopt, MODPREFIX "error: empty map entry"); return 1; @@ -1123,6 +1135,9 @@ int parse_mount(struct autofs_point *ap, p = skipspace(p); } + master_source_current_wait(ap->entry); + ap->entry->current = source; + status = add_offset_entry(ap, name, m_root, m_root_len, path, myoptions, loc, age);