diff --git a/CHANGELOG b/CHANGELOG index 8e4a8c1..bfc36c8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -31,6 +31,7 @@ - allow hostname to start with numeric when validating. - fix included map lookup. - fix directory cleanup on expire. +- fix task cancelation at shutdown. 13/7/2006 autofs-5.0.1 rc1 -------------------------- diff --git a/daemon/automount.c b/daemon/automount.c index 14b385c..8195349 100644 --- a/daemon/automount.c +++ b/daemon/automount.c @@ -614,8 +614,12 @@ static int get_pkt(struct autofs_point * state_mutex_unlock(ap); - if (post_state != ST_INVAL) + if (post_state != ST_INVAL) { + if (post_state == ST_SHUTDOWN_PENDING || + post_state == ST_SHUTDOWN_FORCE) + st_remove_tasks(ap); st_add_task(ap, post_state); + } if (next_state == ST_SHUTDOWN) return -1; @@ -1064,7 +1068,6 @@ static void handle_mounts_cleanup(void * /* If we have been canceled then we may hold the state mutex. */ mutex_operation_wait(&ap->state_mutex); - st_remove_tasks(ap); umount_autofs(ap, 1); master_signal_submount(ap, MASTER_SUBMNT_JOIN); diff --git a/daemon/direct.c b/daemon/direct.c index ffb3009..b08cbdd 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -761,6 +761,13 @@ static int expire_direct(int ioctlfd, co return (retries >= 0); } +static void mnts_cleanup(void *arg) +{ + struct mnt_list *mnts = (struct mnt_list *) arg; + free_mnt_list(mnts); + return; +} + void *expire_proc_direct(void *arg) { struct mnt_list *mnts, *next; @@ -768,8 +775,8 @@ void *expire_proc_direct(void *arg) struct autofs_point *ap; struct mapent *me = NULL; unsigned int now; - int ioctlfd = -1; - int status, ret; + int ioctlfd, cur_state; + int status, ret, left; ea = (struct expire_args *) arg; @@ -779,7 +786,7 @@ void *expire_proc_direct(void *arg) ap = ea->ap; now = ea->when; - ea->status = 0; + ea->status = 1; ea->signaled = 1; status = pthread_cond_signal(&ea->cond); @@ -797,18 +804,24 @@ void *expire_proc_direct(void *arg) if (status) fatal(status); + left = 0; + /* Get a list of real mounts and expire them if possible */ mnts = get_mnt_list(_PROC_MOUNTS, "/", 0); + pthread_cleanup_push(mnts_cleanup, mnts); for (next = mnts; next; next = next->next) { if (!strcmp(next->fs_type, "autofs")) { /* * If we have submounts check if this path lives below * one of them and pass on state change. */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); if (strstr(next->opts, "indirect")) { master_notify_submount(ap, next->path, ap->state); + pthread_setcancelstate(cur_state, NULL); continue; } + pthread_setcancelstate(cur_state, NULL); /* Skip offsets */ if (strstr(next->opts, "offset")) @@ -834,11 +847,15 @@ void *expire_proc_direct(void *arg) debug(ap->logopt, "send expire to trigger %s", next->path); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ret = expire_direct(ioctlfd, next->path, now, ap->logopt); if (!ret) - ea->status++; + left++; + pthread_setcancelstate(cur_state, NULL); } - free_mnt_list(mnts); + pthread_cleanup_pop(1); + + ea->status = left; pthread_cleanup_pop(1); diff --git a/daemon/indirect.c b/daemon/indirect.c index 729c9de..cff4f1c 100644 --- a/daemon/indirect.c +++ b/daemon/indirect.c @@ -402,6 +402,13 @@ static int expire_indirect(struct autofs return (retries >= 0); } +static void mnts_cleanup(void *arg) +{ + struct mnt_list *mnts = (struct mnt_list *) arg; + free_mnt_list(mnts); + return; +} + void *expire_proc_indirect(void *arg) { struct autofs_point *ap; @@ -410,8 +417,8 @@ void *expire_proc_indirect(void *arg) struct expire_args *ea; unsigned int now; int offsets, submnts, count; - int ioctlfd; - int status, ret; + int ioctlfd, cur_state; + int status, ret, left; ea = (struct expire_args *) arg; @@ -421,7 +428,7 @@ void *expire_proc_indirect(void *arg) ap = ea->ap; now = ea->when; - ea->status = 0; + ea->status = 1; ea->signaled = 1; status = pthread_cond_signal(&ea->cond); @@ -439,8 +446,11 @@ void *expire_proc_indirect(void *arg) if (status) fatal(status); + left = 0; + /* Get a list of real mounts and expire them if possible */ mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0); + pthread_cleanup_push(mnts_cleanup, mnts); for (next = mnts; next; next = next->next) { char *ind_key; int ret; @@ -450,8 +460,10 @@ void *expire_proc_indirect(void *arg) * If we have submounts check if this path lives below * one of them and pass on the state change. */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); if (strstr(next->opts, "indirect")) master_notify_submount(ap, next->path, ap->state); + pthread_setcancelstate(cur_state, NULL); continue; } @@ -486,11 +498,13 @@ void *expire_proc_indirect(void *arg) debug(ap->logopt, "expire %s", next->path); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ret = expire_indirect(ap, ioctlfd, next->path, now); if (!ret) - ea->status++; + left++; + pthread_setcancelstate(cur_state, NULL); } - free_mnt_list(mnts); + pthread_cleanup_pop(1); /* * If there are no more real mounts left we could still @@ -498,13 +512,16 @@ void *expire_proc_indirect(void *arg) * umount them here. */ if (mnts) { + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ret = expire_indirect(ap, ap->ioctlfd, ap->path, now); if (!ret) - ea->status++; + left++; + pthread_setcancelstate(cur_state, NULL); } count = offsets = submnts = 0; mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0); + pthread_cleanup_push(mnts_cleanup, mnts); /* Are there any real mounts left */ for (next = mnts; next; next = next->next) { if (strcmp(next->fs_type, "autofs")) @@ -516,7 +533,7 @@ void *expire_proc_indirect(void *arg) offsets++; } } - free_mnt_list(mnts); + pthread_cleanup_pop(1); if (submnts) debug(ap->logopt, @@ -531,12 +548,12 @@ void *expire_proc_indirect(void *arg) /* If we are trying to shutdown make sure we can umount */ if (!ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) { - if (!ret) { + if (!ret) msg("mount still busy %s", ap->path); - ea->status++; - } } + ea->status = left; + pthread_cleanup_pop(1); return NULL; diff --git a/daemon/lookup.c b/daemon/lookup.c index dd620cf..dacb678 100644 --- a/daemon/lookup.c +++ b/daemon/lookup.c @@ -71,6 +71,14 @@ static int check_nss_result(struct nss_s return -1; } +static void nsslist_cleanup(void *arg) +{ + struct list_head *nsslist = (struct list_head *) arg; + if (!list_empty(nsslist)) + free_sources(nsslist); + return; +} + static int do_read_master(struct master *master, char *type, time_t age) { struct lookup_mod *lookup; @@ -313,6 +321,14 @@ static int read_source_instance(struct a return do_read_map(ap, instance, age); } +static void argv_cleanup(void *arg) +{ + struct map_source *tmap = (struct map_source *) arg; + /* path is freed in free_argv */ + free_argv(tmap->argc, tmap->argv); + return; +} + static enum nsswitch_status read_map_source(struct nss_source *this, struct autofs_point *ap, struct map_source *map, time_t age) { @@ -380,10 +396,9 @@ static enum nsswitch_status read_map_sou return NSS_STATUS_UNKNOWN; } + pthread_cleanup_push(argv_cleanup, &tmap); result = read_file_source_instance(ap, &tmap, age); - - /* path is freed in free_argv */ - free_argv(tmap.argc, tmap.argv); + pthread_cleanup_pop(1); return result; } @@ -413,8 +428,6 @@ int lookup_nss_read_map(struct autofs_po continue; } - sched_yield(); - if (map->type) { debug(ap->logopt, "reading map %s %s", map->type, map->argv[0]); @@ -446,7 +459,9 @@ int lookup_nss_read_map(struct autofs_po INIT_LIST_HEAD(&nsslist); + pthread_cleanup_push(nsslist_cleanup, &nsslist); status = nsswitch_parse(&nsslist); + pthread_cleanup_pop(0); if (status) { error(ap->logopt, "can't to read name service switch config."); @@ -454,6 +469,7 @@ int lookup_nss_read_map(struct autofs_po break; } + pthread_cleanup_push(nsslist_cleanup, &nsslist); head = &nsslist; list_for_each(p, head) { this = list_entry(p, struct nss_source, list); @@ -472,9 +488,7 @@ int lookup_nss_read_map(struct autofs_po break; } } - - if (!list_empty(&nsslist)) - free_sources(&nsslist); + pthread_cleanup_pop(1); if (!map) break; @@ -876,6 +890,7 @@ int lookup_prune_cache(struct autofs_poi char *path; int status = CHE_FAIL; + pthread_cleanup_push(master_source_lock_cleanup, entry); master_source_readlock(entry); map = entry->first; @@ -885,6 +900,7 @@ int lookup_prune_cache(struct autofs_poi continue; } mc = map->mc; + pthread_cleanup_push(cache_lock_cleanup, mc); cache_readlock(mc); me = cache_enumerate(mc, NULL); while (me) { @@ -958,12 +974,12 @@ next: free(path); free(next_key); } - cache_unlock(mc); + pthread_cleanup_pop(1); map->stale = 0; map = map->next; } - master_source_unlock(entry); + pthread_cleanup_pop(1); return 1; } @@ -976,7 +992,6 @@ struct mapent *lookup_source_valid_mapen struct mapent_cache *mc; struct mapent *me = NULL; - pthread_cleanup_push(master_source_lock_cleanup, entry); master_source_readlock(entry); map = entry->first; while (map) { @@ -1000,7 +1015,7 @@ struct mapent *lookup_source_valid_mapen cache_unlock(mc); map = map->next; } - pthread_cleanup_pop(1); + master_source_unlock(entry); return me; } @@ -1013,7 +1028,6 @@ struct mapent *lookup_source_mapent(stru struct mapent_cache *mc; struct mapent *me = NULL; - pthread_cleanup_push(master_source_lock_cleanup, entry); master_source_readlock(entry); map = entry->first; while (map) { @@ -1028,7 +1042,7 @@ struct mapent *lookup_source_mapent(stru cache_unlock(mc); map = map->next; } - pthread_cleanup_pop(1); + master_source_unlock(entry); return me; } diff --git a/daemon/state.c b/daemon/state.c index d38a64f..47fee39 100644 --- a/daemon/state.c +++ b/daemon/state.c @@ -30,15 +30,11 @@ struct state_queue { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static unsigned int signaled = 0; static LIST_HEAD(state_queue); -static unsigned int signaled = 0; static void st_set_thid(struct autofs_point *, pthread_t); -static pthread_mutex_t task_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t task_cond = PTHREAD_COND_INITIALIZER; -static unsigned int task_signaled; - #define st_mutex_lock() \ do { \ int status = pthread_mutex_lock(&mutex); \ @@ -53,20 +49,6 @@ do { \ fatal(status); \ } while (0) -#define task_mutex_lock() \ -do { \ - int status = pthread_mutex_lock(&task_mutex); \ - if (status) \ - fatal(status); \ -} while (0) - -#define task_mutex_unlock() \ -do { \ - int status = pthread_mutex_unlock(&task_mutex); \ - if (status) \ - fatal(status); \ -} while (0) - int do_mount_autofs_direct(struct autofs_point *, struct mnt_list *, struct mapent *); void dump_state_queue(void) @@ -116,12 +98,14 @@ void expire_cleanup(void *arg) struct autofs_point *ap; int statefd; enum states next = ST_INVAL; - int success, ret; + int success, ret, cur_state; ea = (struct expire_args *) arg; ap = ea->ap; success = ea->status; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + state_mutex_lock(ap); debug(ap->logopt, @@ -195,6 +179,8 @@ #endif free(ea); + pthread_setcancelstate(cur_state, NULL); + return; } @@ -333,13 +319,20 @@ static void do_readmap_cleanup(void *arg return; } +static void tree_mnts_cleanup(void *arg) +{ + struct mnt_list *mnts = (struct mnt_list *) arg; + tree_free_mnt_tree(mnts); + return; +} + static void *do_readmap(void *arg) { struct autofs_point *ap; struct map_source *map; struct mapent_cache *mc; struct readmap_args *ra; - struct mnt_list *mnts; + struct mnt_list *mnts; int status; time_t now; @@ -378,6 +371,7 @@ static void *do_readmap(void *arg) } else { struct mapent *me; mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/"); + pthread_cleanup_push(tree_mnts_cleanup, mnts); pthread_cleanup_push(master_source_lock_cleanup, ap->entry); master_source_readlock(ap->entry); map = ap->entry->first; @@ -406,7 +400,7 @@ static void *do_readmap(void *arg) pthread_cleanup_pop(1); map = map->next; } - tree_free_mnt_tree(mnts); + pthread_cleanup_pop(1); pthread_cleanup_pop(1); lookup_prune_cache(ap, now); } @@ -617,12 +611,10 @@ int st_add_task(struct autofs_point *ap, unsigned int empty = 1; int status; - state_mutex_lock(ap); - /* Task termination marker, poke state machine */ if (state == ST_READY) { + state_mutex_lock(ap); st_ready(ap); - state_mutex_unlock(ap); st_mutex_lock(); @@ -637,11 +629,11 @@ int st_add_task(struct autofs_point *ap, return 1; } + state_mutex_lock(ap); if (ap->state == ST_SHUTDOWN) { state_mutex_unlock(ap); return 1; } - state_mutex_unlock(ap); new = malloc(sizeof(struct state_queue)); @@ -710,8 +702,13 @@ void st_remove_tasks(struct autofs_point if (task->ap != ap) continue; - if (task->busy) - task->cancel = 1; + if (task->busy) { + /* We only cancel readmap, prune and expire */ + if (task->state == ST_EXPIRE || + task->state == ST_PRUNE || + task->state == ST_READMAP) + task->cancel = 1; + } q = (&task->pending)->next; while(q != &task->pending) { @@ -734,27 +731,15 @@ void st_remove_tasks(struct autofs_point } -static void *do_run_task(void *arg) +static int run_state_task(struct state_queue *task) { - struct state_queue *task; struct autofs_point *ap; enum states next_state, state; unsigned long ret = 1; - int status; - task_mutex_lock(); - - task = (struct state_queue *) arg; ap = task->ap; next_state = task->state; - task_signaled = 1; - status = pthread_cond_signal(&task_cond); - if (status) - fatal(status); - - task_mutex_unlock(); - state_mutex_lock(ap); state = ap->state; @@ -789,33 +774,7 @@ static void *do_run_task(void *arg) state_mutex_unlock(ap); - return (void *) ret; -} - -static int run_state_task(struct state_queue *task) -{ - pthread_t thid; - int status; - - task_mutex_lock(); - - status = pthread_create(&thid, &thread_attr, do_run_task, task); - if (status) { - error(task->ap->logopt, "error running task"); - task_mutex_unlock(); - return 0; - } - - task_signaled = 0; - while (!task_signaled) { - status = pthread_cond_wait(&task_cond, &task_mutex); - if (status) - fatal(status); - } - - task_mutex_unlock(); - - return 1; + return ret; } static void st_set_thid(struct autofs_point *ap, pthread_t thid) @@ -838,12 +797,10 @@ static void *st_queue_handler(void *arg) struct list_head *head; struct list_head *p; struct timespec wait; - int status; + int status, ret; st_mutex_lock(); - head = &state_queue; - while (1) { /* * If the state queue list is empty, wait until an @@ -862,24 +819,25 @@ static void *st_queue_handler(void *arg) } } - list_for_each(p, head) { + p = head->next; + while(p != head) { struct state_queue *task; task = list_entry(p, struct state_queue, list); + p = p->next; /* debug(LOGOPT_NONE, "task %p ap %p state %d next %d busy %d", task, task->ap, task->ap->state, task->state, task->busy); */ - task->busy = 1; - /* - * TODO: field return code and delete immediately - * on fail - */ - /* TODO: field return code and delete immediately on fail */ - run_state_task(task); + + ret = run_state_task(task); + if (!ret) { + list_del(&task->list); + free(task); + } } while (1) { @@ -912,24 +870,30 @@ static void *st_queue_handler(void *arg) if (!task->busy) { /* Start a new task */ task->busy = 1; - /* - * TODO: field return code and delete - * immediately on fail - */ - run_state_task(task); + + ret = run_state_task(task); + if (!ret) + goto remove; continue; } -/* - if (task->thid && task->cancel) + + /* Still starting up */ + if (!task->thid) + continue; + + if (task->cancel) { pthread_cancel(task->thid); -*/ + task->cancel = 0; + continue; + } + /* Still busy */ if (task->thid) { status = pthread_kill(task->thid, 0); if (status != ESRCH) continue; } - +remove: /* No more tasks for this queue */ if (list_empty(&task->pending)) { list_del(&task->list); diff --git a/modules/lookup_file.c b/modules/lookup_file.c index 47a208b..028c1ec 100644 --- a/modules/lookup_file.c +++ b/modules/lookup_file.c @@ -67,31 +67,31 @@ int lookup_init(const char *mapfmt, int } if (argc < 1) { - crit(LOGOPT_ANY, MODPREFIX "No map name"); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "No map name"); return 1; } ctxt->mapname = argv[0]; if (ctxt->mapname[0] != '/') { - msg(MODPREFIX "file map %s is not an absolute pathname", - ctxt->mapname); free(ctxt); + msg(MODPREFIX "file map %s is not an absolute pathname", + argv[0]); return 1; } if (access(ctxt->mapname, R_OK)) { - msg(MODPREFIX "file map %s missing or not readable", - ctxt->mapname); free(ctxt); + msg(MODPREFIX "file map %s missing or not readable", + argv[0]); return 1; } if (stat(ctxt->mapname, &st)) { - crit(LOGOPT_ANY, MODPREFIX "file map %s, could not stat", - ctxt->mapname); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "file map %s, could not stat", + argv[0]); return 1; } @@ -102,8 +102,8 @@ int lookup_init(const char *mapfmt, int ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); if (!ctxt->parse) { - crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); return 1; } *context = ctxt; @@ -345,7 +345,7 @@ int lookup_read_master(struct master *ma struct stat st; FILE *f; unsigned int path_len, ent_len; - int entry; + int entry, cur_state; if (master->recurse) return NSS_STATUS_UNAVAIL; @@ -357,18 +357,17 @@ int lookup_read_master(struct master *ma return NSS_STATUS_UNAVAIL; } - path = malloc(KEY_MAX_LEN + 1); + path = alloca(KEY_MAX_LEN + 1); if (!path) { error(LOGOPT_ANY, MODPREFIX "could not malloc storage for path"); return NSS_STATUS_UNAVAIL; } - ent = malloc(MAPENT_MAX_LEN + 1); + ent = alloca(MAPENT_MAX_LEN + 1); if (!ent) { error(LOGOPT_ANY, MODPREFIX "could not malloc storage for mapent"); - free(path); return NSS_STATUS_UNAVAIL; } @@ -377,8 +376,6 @@ int lookup_read_master(struct master *ma error(LOGOPT_ANY, MODPREFIX "could not open master map file %s", ctxt->mapname); - free(path); - free(ent); return NSS_STATUS_UNAVAIL; } @@ -425,8 +422,6 @@ int lookup_read_master(struct master *ma if (!buffer) { error(LOGOPT_ANY, MODPREFIX "could not malloc parse buffer"); - free(path); - free(ent); return NSS_STATUS_UNAVAIL; } memset(buffer, 0, blen); @@ -435,9 +430,10 @@ int lookup_read_master(struct master *ma strcat(buffer, " "); strcat(buffer, ent); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); master_parse_entry(buffer, timeout, logging, age); - free(buffer); + pthread_setcancelstate(cur_state, NULL); } if (feof(f)) @@ -447,17 +443,12 @@ int lookup_read_master(struct master *ma if (fstat(fileno(f), &st)) { crit(LOGOPT_ANY, MODPREFIX "file map %s, could not stat", ctxt->mapname); - free(path); - free(ent); return NSS_STATUS_UNAVAIL; } ctxt->mtime = st.st_mtime; fclose(f); - free(path); - free(ent); - return NSS_STATUS_SUCCESS; } @@ -515,9 +506,9 @@ prepare_plus_include(struct autofs_point 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"); - master_free_mapent(entry); return NULL; } iap = entry->ap; @@ -536,8 +527,8 @@ prepare_plus_include(struct autofs_point /* skip plus */ buf = strdup(key + 1); if (!buf) { - error(ap->logopt, MODPREFIX "failed to strdup key"); master_free_mapent(entry); + error(ap->logopt, MODPREFIX "failed to strdup key"); return NULL; } @@ -569,9 +560,9 @@ prepare_plus_include(struct autofs_point source = master_add_map_source(entry, type, fmt, age, argc, argv); if (!source) { - error(ap->logopt, "failed to creat map_source"); master_free_mapent(entry); free(buf); + error(ap->logopt, "failed to creat map_source"); return NULL; } source->mc = current->mc; @@ -611,18 +602,17 @@ int lookup_read_map(struct autofs_point return NSS_STATUS_UNAVAIL; } - key = malloc(KEY_MAX_LEN + 1); + key = alloca(KEY_MAX_LEN + 1); if (!key) { error(ap->logopt, MODPREFIX "could not malloc storage for key"); return NSS_STATUS_UNAVAIL; } - mapent = malloc(MAPENT_MAX_LEN + 1); + mapent = alloca(MAPENT_MAX_LEN + 1); if (!mapent) { error(ap->logopt, MODPREFIX "could not malloc storage for mapent"); - free(key); return NSS_STATUS_UNAVAIL; } @@ -630,8 +620,6 @@ int lookup_read_map(struct autofs_point if (!f) { error(ap->logopt, MODPREFIX "could not open map file %s", ctxt->mapname); - free(key); - free(mapent); return NSS_STATUS_UNAVAIL; } @@ -696,8 +684,6 @@ int lookup_read_map(struct autofs_point crit(ap->logopt, MODPREFIX "file map %s, could not stat", ctxt->mapname); - free(key); - free(mapent); return NSS_STATUS_UNAVAIL; } ctxt->mtime = st.st_mtime; @@ -705,9 +691,6 @@ int lookup_read_map(struct autofs_point fclose(f); - free(key); - free(mapent); - return NSS_STATUS_SUCCESS; } @@ -793,11 +776,12 @@ static int lookup_one(struct autofs_poin free(s_key); - fclose(f); cache_writelock(mc); ret = cache_update(mc, key, mapent, age); cache_unlock(mc); + fclose(f); + return ret; } } @@ -876,10 +860,12 @@ static int lookup_wild(struct autofs_poi if (eq == 0) continue; - fclose(f); cache_writelock(mc); ret = cache_update(mc, "*", mapent, age); cache_unlock(mc); + + fclose(f); + return ret; } } diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c index 855cb95..c0ced9e 100644 --- a/modules/lookup_ldap.c +++ b/modules/lookup_ldap.c @@ -1280,16 +1280,19 @@ int lookup_read_map(struct autofs_point { struct lookup_context *ctxt = (struct lookup_context *) context; int rv = LDAP_SUCCESS; - int ret; + int ret, cur_state; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); ret = read_one_map(ap, ctxt, age, &rv); if (ret != NSS_STATUS_SUCCESS) { switch (rv) { case LDAP_SIZELIMIT_EXCEEDED: case LDAP_UNWILLING_TO_PERFORM: + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_UNAVAIL; } } + pthread_setcancelstate(cur_state, NULL); return ret; } @@ -1507,7 +1510,7 @@ static int check_map_indirect(struct aut struct mapent *me, *exists; time_t now = time(NULL); time_t t_last_read; - int ret, need_map = 0; + int ret, cur_state, need_map = 0; source = ap->entry->current; ap->entry->current = NULL; @@ -1524,9 +1527,13 @@ static int check_map_indirect(struct aut 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 == CHE_FAIL) + if (ret == CHE_FAIL) { + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_NOTFOUND; + } + pthread_setcancelstate(cur_state, NULL); cache_readlock(mc); me = cache_lookup_first(mc); @@ -1540,8 +1547,8 @@ static int check_map_indirect(struct aut } if (ret == CHE_MISSING) { - cache_writelock(mc); 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); @@ -1641,12 +1648,10 @@ int lookup_mount(struct autofs_point *ap cache_readlock(mc); me = cache_lookup(mc, key); - if (me) { - pthread_cleanup_push(cache_lock_cleanup, mc); + if (me && me->mapent) { mapent_len = strlen(me->mapent); mapent = alloca(mapent_len + 1); strcpy(mapent, me->mapent); - pthread_cleanup_pop(0); } cache_unlock(mc); diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c index 500bc53..b0fe4a6 100644 --- a/modules/lookup_nisplus.c +++ b/modules/lookup_nisplus.c @@ -46,8 +46,8 @@ int lookup_init(const char *mapfmt, int } if (argc < 1) { - crit(LOGOPT_ANY, MODPREFIX "No map name"); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "No map name"); return 1; } ctxt->mapname = argv[0]; @@ -58,8 +58,8 @@ int lookup_init(const char *mapfmt, int */ ctxt->domainname = nis_local_directory(); if (!ctxt->domainname) { - crit(LOGOPT_ANY, MODPREFIX "NIS+ domain not set"); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "NIS+ domain not set"); return 1; } @@ -68,8 +68,8 @@ int lookup_init(const char *mapfmt, int ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); if (!ctxt->parse) { - crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); return 1; } *context = ctxt; @@ -89,11 +89,14 @@ int lookup_read_master(struct master *ma char *path, *ent; char *buffer; char buf[MAX_ERR_BUF]; + int cur_state; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); if (!tablename) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_UNAVAIL; } sprintf(tablename, "%s.org_dir.%s", ctxt->mapname, ctxt->domainname); @@ -104,6 +107,7 @@ int lookup_read_master(struct master *ma nis_freeresult(result); crit(LOGOPT_ANY, MODPREFIX "couldn't locat nis+ table %s", ctxt->mapname); + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_NOTFOUND; } @@ -114,6 +118,7 @@ int lookup_read_master(struct master *ma nis_freeresult(result); crit(LOGOPT_ANY, MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname); + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_UNAVAIL; } @@ -149,6 +154,7 @@ int lookup_read_master(struct master *ma } nis_freeresult(result); + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_SUCCESS; } @@ -164,6 +170,7 @@ int lookup_read_map(struct autofs_point unsigned int current, result_count; char *key, *mapent; char buf[MAX_ERR_BUF]; + int cur_state; source = ap->entry->current; ap->entry->current = NULL; @@ -171,10 +178,12 @@ int lookup_read_map(struct autofs_point mc = source->mc; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); if (!tablename) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_UNAVAIL; } sprintf(tablename, "%s.org_dir.%s", ctxt->mapname, ctxt->domainname); @@ -185,6 +194,7 @@ int lookup_read_map(struct autofs_point nis_freeresult(result); crit(ap->logopt, MODPREFIX "couldn't locat nis+ table %s", ctxt->mapname); + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_NOTFOUND; } @@ -195,6 +205,7 @@ int lookup_read_map(struct autofs_point nis_freeresult(result); crit(ap->logopt, MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname); + pthread_setcancelstate(cur_state, NULL); return NSS_STATUS_UNAVAIL; } @@ -233,6 +244,8 @@ int lookup_read_map(struct autofs_point source->age = age; + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_SUCCESS; } @@ -247,7 +260,7 @@ static int lookup_one(struct autofs_poin nis_object *this; char *mapent; time_t age = time(NULL); - int ret; + int ret, cur_state; char buf[MAX_ERR_BUF]; source = ap->entry->current; @@ -256,11 +269,13 @@ static int lookup_one(struct autofs_poin mc = source->mc; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); tablename = alloca(strlen(key) + strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); if (!tablename) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); return -1; } sprintf(tablename, "[key=%s],%s.org_dir.%s", key, ctxt->mapname, @@ -269,6 +284,7 @@ static int lookup_one(struct autofs_poin result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) { nis_freeresult(result); + pthread_setcancelstate(cur_state, NULL); if (result->status == NIS_NOTFOUND || result->status == NIS_S_NOTFOUND) return CHE_MISSING; @@ -284,6 +300,7 @@ static int lookup_one(struct autofs_poin cache_unlock(mc); nis_freeresult(result); + pthread_setcancelstate(cur_state, NULL); return ret; } @@ -297,7 +314,7 @@ static int lookup_wild(struct autofs_poi nis_object *this; char *mapent; time_t age = time(NULL); - int ret; + int ret, cur_state; char buf[MAX_ERR_BUF]; source = ap->entry->current; @@ -306,10 +323,12 @@ static int lookup_wild(struct autofs_poi mc = source->mc; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); if (!tablename) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); return -1; } sprintf(tablename, "[key=*],%s.org_dir.%s", ctxt->mapname, @@ -318,6 +337,7 @@ static int lookup_wild(struct autofs_poi result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) { nis_freeresult(result); + pthread_setcancelstate(cur_state, NULL); if (result->status == NIS_NOTFOUND || result->status == NIS_S_NOTFOUND) return CHE_MISSING; @@ -332,6 +352,7 @@ static int lookup_wild(struct autofs_poi cache_unlock(mc); nis_freeresult(result); + pthread_setcancelstate(cur_state, NULL); return ret; } @@ -493,12 +514,10 @@ int lookup_mount(struct autofs_point *ap cache_readlock(mc); me = cache_lookup(mc, key); - if (me) { - pthread_cleanup_push(cache_lock_cleanup, mc); + if (me && me->mapent) { mapent_len = strlen(me->mapent); mapent = alloca(mapent_len + 1); strcpy(mapent, me->mapent); - pthread_cleanup_pop(0); } cache_unlock(mc); diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c index ccf6d60..275610a 100644 --- a/modules/lookup_yp.c +++ b/modules/lookup_yp.c @@ -117,8 +117,8 @@ int lookup_init(const char *mapfmt, int memset(ctxt, 0, sizeof(struct lookup_context)); if (argc < 1) { - crit(LOGOPT_ANY, MODPREFIX "no map name"); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "no map name"); return 1; } ctxt->mapname = argv[0]; @@ -128,9 +128,9 @@ int lookup_init(const char *mapfmt, int /* This should, but doesn't, take a const char ** */ err = yp_get_default_domain((char **) &ctxt->domainname); if (err) { + free(ctxt); debug(LOGOPT_NONE, MODPREFIX "map %s: %s", ctxt->mapname, yperr_string(err)); - free(ctxt); return 1; } @@ -141,8 +141,8 @@ int lookup_init(const char *mapfmt, int ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); if (!ctxt->parse) { - crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); free(ctxt); + crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); return 1; } *context = ctxt; @@ -176,7 +176,7 @@ int yp_all_master_callback(int status, c len = ypkeylen + 1 + vallen + 1; - buffer = malloc(len); + buffer = alloca(len); if (!buffer) { error(LOGOPT_ANY, MODPREFIX "could not malloc parse buffer"); return 0; @@ -189,8 +189,6 @@ int yp_all_master_callback(int status, c master_parse_entry(buffer, timeout, logging, age); - free(buffer); - return 0; } @@ -600,12 +598,10 @@ int lookup_mount(struct autofs_point *ap cache_readlock(mc); me = cache_lookup(mc, key); - if (me) { - pthread_cleanup_push(cache_lock_cleanup, mc); + if (me && me->mapent) { mapent_len = strlen(me->mapent); mapent = alloca(mapent_len + 1); strcpy(mapent, me->mapent); - pthread_cleanup_pop(0); } cache_unlock(mc); diff --git a/modules/parse_sun.c b/modules/parse_sun.c index b3f5d67..c132422 100644 --- a/modules/parse_sun.c +++ b/modules/parse_sun.c @@ -407,7 +407,9 @@ static char *concat_options(char *left, return NULL; } - sprintf(ret, "%s,%s", left, right); + strcpy(ret, left); + strcat(ret, ","); + strcat(ret, right); free(left); free(right); @@ -422,7 +424,7 @@ static int sun_mount(struct autofs_point { char *fstype = "nfs"; /* Default filesystem type */ int nonstrict = 1; - int rv; + int rv, cur_state; char *mountpoint; char *what; @@ -520,6 +522,7 @@ static int sun_mount(struct autofs_point "mounting root %s, mountpoint %s, what %s, fstype %s, options %s", root, mountpoint, what, fstype, options); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); if (!strcmp(fstype, "nfs")) { rv = mount_nfs->mount_mount(ap, root, mountpoint, strlen(mountpoint), what, fstype, options, mount_nfs->context); @@ -528,6 +531,7 @@ static int sun_mount(struct autofs_point rv = do_mount(ap, root, mountpoint, strlen(mountpoint), what, fstype, options); } + pthread_setcancelstate(cur_state, NULL); if (nonstrict && rv) return -rv; @@ -878,7 +882,7 @@ int parse_mount(struct autofs_point *ap, char *pmapent, *options; const char *p; int mapent_len, rv = 0; - int optlen; + int optlen, cur_state; int slashify = ctxt->slashify_colons; source = ap->entry->current; @@ -962,8 +966,8 @@ int parse_mount(struct autofs_point *ap, m_root = alloca(m_root_len + 1); if (!m_root) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); - error(ap->logopt, MODPREFIX "alloca: %s", estr); free(options); + error(ap->logopt, MODPREFIX "alloca: %s", estr); return 1; } strcpy(m_root, name); @@ -972,8 +976,8 @@ int parse_mount(struct autofs_point *ap, m_root = alloca(m_root_len + 1); if (!m_root) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); - error(ap->logopt, MODPREFIX "alloca: %s", estr); free(options); + error(ap->logopt, MODPREFIX "alloca: %s", estr); return 1; } strcpy(m_root, ap->path); @@ -1007,13 +1011,14 @@ int parse_mount(struct autofs_point *ap, } if (!me) { - error(ap->logopt, - MODPREFIX "can't find multi root %s", name); free(options); cache_unlock(mc); + error(ap->logopt, + MODPREFIX "can't find multi root %s", name); return 1; } + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); cache_multi_lock(me); /* It's a multi-mount; deal with it */ do { @@ -1038,6 +1043,7 @@ int parse_mount(struct autofs_point *ap, cache_multi_unlock(me); cache_unlock(mc); free(options); + pthread_setcancelstate(cur_state, NULL); return 1; } @@ -1051,6 +1057,7 @@ int parse_mount(struct autofs_point *ap, cache_unlock(mc); free(path); free(options); + pthread_setcancelstate(cur_state, NULL); return 1; } @@ -1073,6 +1080,7 @@ int parse_mount(struct autofs_point *ap, free(options); free(myoptions); free(loc); + pthread_setcancelstate(cur_state, NULL); return 1; } @@ -1101,6 +1109,7 @@ int parse_mount(struct autofs_point *ap, cache_multi_unlock(me); cache_unlock(mc); free(options); + pthread_setcancelstate(cur_state, NULL); return 1; } @@ -1118,6 +1127,7 @@ int parse_mount(struct autofs_point *ap, cache_multi_unlock(me); cache_unlock(mc); free(options); + pthread_setcancelstate(cur_state, NULL); return rv; } } @@ -1128,6 +1138,7 @@ int parse_mount(struct autofs_point *ap, cache_multi_unlock(me); cache_unlock(mc); free(options); + pthread_setcancelstate(cur_state, NULL); return 1; } @@ -1135,6 +1146,7 @@ int parse_mount(struct autofs_point *ap, cache_unlock(mc); free(options); + pthread_setcancelstate(cur_state, NULL); return rv; } else { @@ -1145,24 +1157,24 @@ int parse_mount(struct autofs_point *ap, /* Location can't begin with a '/' */ if (*p == '/') { + free(options); warn(ap->logopt, MODPREFIX "error location begins with \"/\""); - free(options); return 1; } l = chunklen(p, check_colon(p)); loc = dequote(p, l, ap->logopt); if (!loc) { - warn(ap->logopt, MODPREFIX "null location or out of memory"); free(options); + warn(ap->logopt, MODPREFIX "null location or out of memory"); return 1; } if (!validate_location(loc)) { - warn(ap->logopt, MODPREFIX "invalid location"); free(loc); free(options); + warn(ap->logopt, MODPREFIX "invalid location"); return 1; } @@ -1178,18 +1190,18 @@ int parse_mount(struct autofs_point *ap, l = chunklen(p, check_colon(p)); ent = dequote(p, l, ap->logopt); if (!ent) { - warn(ap->logopt, - MODPREFIX "null location or out of memory"); free(loc); free(options); + warn(ap->logopt, + MODPREFIX "null location or out of memory"); return 1; } if (!validate_location(ent)) { - warn(ap->logopt, MODPREFIX "invalid location"); free(ent); free(loc); free(options); + warn(ap->logopt, MODPREFIX "invalid location"); return 1; } @@ -1198,10 +1210,10 @@ int parse_mount(struct autofs_point *ap, loc = realloc(loc, strlen(loc) + l + 2); if (!loc) { - error(ap->logopt, MODPREFIX "out of memory"); free(ent); free(loc); free(options); + error(ap->logopt, MODPREFIX "out of memory"); return 1; } @@ -1216,10 +1228,10 @@ int parse_mount(struct autofs_point *ap, loclen = strlen(loc); if (loclen == 0) { - error(ap->logopt, - MODPREFIX "entry %s is empty!", name); free(loc); free(options); + error(ap->logopt, + MODPREFIX "entry %s is empty!", name); return 1; } @@ -1242,12 +1254,14 @@ int parse_mount(struct autofs_point *ap, * If it's a multi-mount insert the triggers * These are always direct mount triggers so root = "" */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); cache_readlock(mc); me = cache_lookup_distinct(mc, name); if (me) { mount_subtree_offsets(ap, mc, me); } cache_unlock(mc); + pthread_setcancelstate(cur_state, NULL); } return rv; }