diff --git a/CHANGELOG b/CHANGELOG index 3baff69..c0c6dd6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,8 @@ - cthon fix expire of various forms of nested mounts. - cthon fix some shutdown races. - cthon corrections for above patch and fix shutdown expire. +- cthon fix expire of wildcard and program mounts broken by above + patches. 13/7/2006 autofs-5.0.1 rc1 -------------------------- diff --git a/daemon/automount.c b/daemon/automount.c index ff05ae2..9c3f1e9 100644 --- a/daemon/automount.c +++ b/daemon/automount.c @@ -375,7 +375,7 @@ int umount_multi(struct autofs_point *ap is_autofs_fs = fs.f_type == AUTOFS_SUPER_MAGIC ? 1 : 0; - me = lookup_source_mapent(ap, path); + me = lookup_source_mapent(ap, path, LKP_DISTINCT); if (!me) { char *ind_key; @@ -383,7 +383,7 @@ int umount_multi(struct autofs_point *ap if (ind_key) ind_key++; - me = lookup_source_mapent(ap, ind_key); + me = lookup_source_mapent(ap, ind_key, LKP_DISTINCT); if (!me) { warn(ap->logopt, "map entry not found for %s", path); return 0; diff --git a/daemon/direct.c b/daemon/direct.c index c155617..974a50e 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -721,10 +721,10 @@ out_err: return -1; } -static int expire_direct(int ioctlfd, const char *path, unsigned int when, int count, unsigned int logopt) +static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt) { char *estr, buf[MAX_ERR_BUF]; - int ret, retries = count; + int ret, retries = EXPIRE_RETRIES; while (retries--) { struct timespec tm = {0, 100000000}; @@ -733,7 +733,7 @@ static int expire_direct(int ioctlfd, co ret = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &busy); if (ret == -1) { /* Mount has gone away */ - if (errno == EBADF) + if (errno == EBADF || errno == EINVAL) return 1; estr = strerror_r(errno, buf, MAX_ERR_BUF); @@ -751,7 +751,7 @@ static int expire_direct(int ioctlfd, co ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when); if (ret == -1) { /* Mount has gone away */ - if (errno == EBADF) + if (errno == EBADF || errno == EINVAL) return 1; /* Need to wait for the kernel ? */ @@ -766,11 +766,9 @@ static int expire_direct(int ioctlfd, co void *expire_proc_direct(void *arg) { - struct map_source *map; struct mnt_list *mnts, *next; struct expire_args *ea; struct autofs_point *ap; - struct mapent_cache *mc = NULL; struct mapent *me = NULL; unsigned int now; int ioctlfd = -1; @@ -819,35 +817,22 @@ void *expire_proc_direct(void *arg) * All direct mounts must be present in the map * entry cache. */ - master_source_readlock(ap->entry); - map = ap->entry->first; - while (map) { - mc = map->mc; - cache_readlock(mc); - me = cache_lookup_distinct(mc, next->path); - if (me) - break; - cache_unlock(mc); - map = map->next; - } - master_source_unlock(ap->entry); - + me = lookup_source_mapent(ap, next->path, LKP_DISTINCT); if (!me) continue; if (me->ioctlfd >= 0) { /* Real mounts have an open ioctl fd */ ioctlfd = me->ioctlfd; - cache_unlock(mc); + cache_unlock(me->source->mc); } else { - cache_unlock(mc); + cache_unlock(me->source->mc); continue; } debug(ap->logopt, "send expire to trigger %s", next->path); - ret = expire_direct(ioctlfd, next->path, - now, EXPIRE_RETRIES, ap->logopt); + ret = expire_direct(ioctlfd, next->path, now, ap->logopt); if (!ret) { debug(ap->logopt, "failed to expire mount %s", next->path); @@ -926,7 +911,7 @@ static void *do_expire_direct(void *arg) send_fail(mt->ioctlfd, mt->wait_queue_token); else { struct mapent *me; - me = lookup_source_mapent(ap, mt->name); + me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT); me->ioctlfd = -1; cache_unlock(me->source->mc); send_ready(mt->ioctlfd, mt->wait_queue_token); @@ -1225,7 +1210,7 @@ cont: pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); if (status) { struct mapent *me; - me = lookup_source_mapent(ap, mt->name); + me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT); me->ioctlfd = mt->ioctlfd; cache_unlock(me->source->mc); send_ready(mt->ioctlfd, mt->wait_queue_token); diff --git a/daemon/indirect.c b/daemon/indirect.c index af84629..b57bbd1 100644 --- a/daemon/indirect.c +++ b/daemon/indirect.c @@ -294,7 +294,7 @@ int umount_autofs_indirect(struct autofs /* If we are trying to shutdown make sure we can umount */ rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret); - if (rv) { + if (rv == -1) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); error(ap->logopt, "ioctl failed: %s", estr); return 1; @@ -364,7 +364,7 @@ force_umount: return rv; } -static int expire_indirect(int ioctlfd, const char *path, unsigned int when, int count, unsigned int logopt) +static int expire_indirect(int ioctlfd, const char *path, unsigned int when, unsigned int count, unsigned int logopt) { char *estr, buf[MAX_ERR_BUF]; int ret, retries = count; @@ -376,7 +376,7 @@ static int expire_indirect(int ioctlfd, ret = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &busy); if (ret == -1) { /* Mount has gone away */ - if (errno == EBADF) + if (errno == EBADF || errno == EINVAL) return 1; estr = strerror_r(errno, buf, MAX_ERR_BUF); @@ -394,7 +394,7 @@ static int expire_indirect(int ioctlfd, ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when); if (ret == -1) { /* Mount has gone away */ - if (errno == EBADF) + if (errno == EBADF || errno == EINVAL) return 1; /* Need to wait for the kernel ? */ @@ -410,9 +410,7 @@ static int expire_indirect(int ioctlfd, void *expire_proc_indirect(void *arg) { - struct map_source *map; struct autofs_point *ap; - struct mapent_cache *mc = NULL; struct mapent *me = NULL; struct mnt_list *mnts, *next; struct expire_args *ea; @@ -420,6 +418,7 @@ void *expire_proc_indirect(void *arg) int offsets, submnts, count; int ioctlfd, limit; int status, ret; + unsigned int retries = EXPIRE_RETRIES; ea = (struct expire_args *) arg; @@ -473,36 +472,23 @@ void *expire_proc_indirect(void *arg) * Otherwise it's a top level indirect mount (possibly * with offsets in it) and we use the usual ioctlfd. */ - master_source_readlock(ap->entry); - map = ap->entry->first; - while (map) { - mc = map->mc; - cache_readlock(mc); - me = cache_lookup_distinct(mc, next->path); - if (!me) - me = cache_lookup_distinct(mc, ind_key); - if (me) - break; - cache_unlock(mc); - map = map->next; - } - master_source_unlock(ap->entry); - + me = lookup_source_mapent(ap, next->path, LKP_DISTINCT); + if (!me && ind_key) + lookup_source_mapent(ap, ind_key, LKP_NORMAL); if (!me) continue; if (*me->key == '/') { ioctlfd = me->ioctlfd; - cache_unlock(mc); + cache_unlock(me->source->mc); } else { ioctlfd = ap->ioctlfd; - cache_unlock(mc); + cache_unlock(me->source->mc); } debug(ap->logopt, "expire %s", next->path); - ret = expire_indirect(ioctlfd, next->path, - now, EXPIRE_RETRIES, ap->logopt); + ret = expire_indirect(ioctlfd, next->path, now, retries, ap->logopt); if (!ret) { debug(ap->logopt, "failed to expire mount %s", next->path); diff --git a/daemon/lookup.c b/daemon/lookup.c index 6942121..87be647 100644 --- a/daemon/lookup.c +++ b/daemon/lookup.c @@ -931,15 +931,15 @@ int lookup_prune_cache(struct autofs_poi free(path); goto next; } - status = CHE_FAIL; - if (this->ioctlfd == -1) - status = cache_delete(mc, key); - cache_unlock(mc); - if (status != CHE_FAIL) { - if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS)) + if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS)) { + status = CHE_FAIL; + if (this->ioctlfd == -1) + status = cache_delete(mc, key); + if (status != CHE_FAIL) rmdir_path(ap, path); } + cache_unlock(mc); if (!next_key) { free(key); @@ -965,7 +965,7 @@ next: } /* Return with cache readlock held */ -struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key) +struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type) { struct master_mapent *entry = ap->entry; struct map_source *map; @@ -978,7 +978,10 @@ struct mapent *lookup_source_mapent(stru while (map) { mc = map->mc; cache_readlock(mc); - me = cache_lookup_distinct(mc, key); + if (type == LKP_DISTINCT) + me = cache_lookup_distinct(mc, key); + else + me = cache_lookup_distinct(mc, key); if (me) break; cache_unlock(mc); diff --git a/include/automount.h b/include/automount.h index 800e7b0..f7345c5 100644 --- a/include/automount.h +++ b/include/automount.h @@ -95,8 +95,8 @@ #define LKP_WILD 0x0100 #define LKP_LOOKUP 0x0200 #define LKP_GHOST 0x0400 #define LKP_REREAD 0x0800 -#define LKP_EMPTY 0x1000 -#define LKP_ERR_FORMAT 0x2000 +#define LKP_NORMAL 0x1000 +#define LKP_DISTINCT 0x2000 #define LKP_ERR_MOUNT 0x4000 #define LKP_NOTSUP 0x8000 @@ -228,7 +228,7 @@ int lookup_ghost(struct autofs_point *ap int lookup_nss_mount(struct autofs_point *ap, 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_mapent(struct autofs_point *ap, const char *key); +struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type); int lookup_source_close_ioctlfd(struct autofs_point *ap, const char *key); #ifdef MODULE_LOOKUP diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c index 1664afc..f30e9b2 100644 --- a/modules/lookup_hesiod.c +++ b/modules/lookup_hesiod.c @@ -100,15 +100,20 @@ int lookup_read_map(struct autofs_point */ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) { + struct map_source *source; + struct mapent_cache *mc; char **hes_result; struct lookup_context *ctxt = (struct lookup_context *) context; int status, rv; char **record, *best_record = NULL, *p; int priority, lowest_priority = INT_MAX; + source = ap->entry->current; ap->entry->current = NULL; master_source_current_signal(ap->entry); + mc = source->mc; + debug(ap->logopt, MODPREFIX "looking up root=\"%s\", name=\"%s\"", ap->path, name); @@ -148,6 +153,12 @@ int lookup_mount(struct autofs_point *ap } } + cache_writelock(mc); + rv = cache_update(mc, source, name, best_record, time(NULL)); + cache_unlock(mc); + if (rv == CHE_FAIL) + return NSS_STATUS_UNAVAIL; + debug(ap->logopt, MODPREFIX "lookup for \"%s\" gave \"%s\"", name, best_record); diff --git a/modules/lookup_program.c b/modules/lookup_program.c index c589d05..0076596 100644 --- a/modules/lookup_program.c +++ b/modules/lookup_program.c @@ -346,6 +346,12 @@ int lookup_mount(struct autofs_point *ap goto out_free; } + cache_writelock(mc); + ret = cache_update(mc, source, name, mapent, time(NULL)); + cache_unlock(mc); + if (ret == CHE_FAIL) + return NSS_STATUS_UNAVAIL; + debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent); master_source_current_wait(ap->entry); diff --git a/modules/lookup_userhome.c b/modules/lookup_userhome.c index cc0b4fa..efcab0b 100644 --- a/modules/lookup_userhome.c +++ b/modules/lookup_userhome.c @@ -49,11 +49,18 @@ int lookup_read_map(struct autofs_point int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context) { + struct map_source *source; + struct mapent_cache *mc; struct passwd *pw; char buf[MAX_ERR_BUF]; + int ret; + 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); /* Get the equivalent username */ @@ -70,12 +77,23 @@ int lookup_mount(struct autofs_point *ap return NSS_STATUS_UNAVAIL; } + cache_writelock(mc); + ret = cache_update(mc, source, name, NULL, time(NULL)); + cache_unlock(mc); + + if (ret == CHE_FAIL) { + ret = chdir("/"); + return NSS_STATUS_UNAVAIL; + } + if (symlink(pw->pw_dir, name) && errno != EEXIST) { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); error(ap->logopt, MODPREFIX "symlink failed: %s", estr); return NSS_STATUS_UNAVAIL; } + ret = chdir("/"); + return NSS_STATUS_SUCCESS; } diff --git a/modules/parse_sun.c b/modules/parse_sun.c index 0f2c3ab..25d2eda 100644 --- a/modules/parse_sun.c +++ b/modules/parse_sun.c @@ -1215,7 +1215,7 @@ int parse_mount(struct autofs_point *ap, if (ap->submount) oap = ap->parent; - me = lookup_source_mapent(oap, name); + me = lookup_source_mapent(oap, name, LKP_DISTINCT); if (me) { char *m_key; int start;