On map update if there's a direct mount in the master map it may be associated with multiple maps. If there's an entry that's been removed but is present in another map and the removed entry has a real mount associated with it special case handling is needed. Currently the function that looks for these newly valid map entries doesn't do it properly. It's meant to look for the first "valid" map entry but doesn't check if the entry is valid. So if a valid entry follows the an invalid entry it isn't found, the invalid entry is returned instead. Once this is fixed the handling of a removed direct mount entry that's covered by a real mount can be done. Basically, the newly valid map entry needs to take over the mount (which wasn't being done quite right either) and the removed map entry deleted so that the covering mount can expire. From this point onward the newly valid map entry will be used. Signed-off-by: Ian Kent <raven@xxxxxxxxxx> --- CHANGELOG | 1 + daemon/lookup.c | 33 ++++++++++----------------------- daemon/state.c | 17 +++++------------ include/automount.h | 2 +- 4 files changed, 17 insertions(+), 36 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 37a0d25c5..e18666399 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -33,6 +33,7 @@ - fix handling of ignored offsets. - fix invalidated map entry handling in hosts module. - quiet possibly noisy log message. +- fix devid update on reload. 02/11/2023 autofs-5.1.9 - fix kernel mount status notification. diff --git a/daemon/lookup.c b/daemon/lookup.c index dc7794806..c7bf76273 100644 --- a/daemon/lookup.c +++ b/daemon/lookup.c @@ -1412,37 +1412,20 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti * mount if it is a direct mount or it's just a stale indirect * cache entry. */ - valid = lookup_source_valid_mapent(ap, key, LKP_DISTINCT); - if (valid && valid->mc == mc) { - /* - * We've found a map entry that has been removed from - * the current cache so it isn't really valid. Set the - * mapent negative to prevent further mount requests - * using the cache entry. - */ - debug(ap->logopt, "removed map entry detected, mark negative"); - if (valid->mapent) { - free(valid->mapent); - valid->mapent = NULL; - } + valid = lookup_source_valid_mapent(ap, key, LKP_DISTINCT, age); + if (valid) cache_unlock(valid->mc); - valid = NULL; - } - if (!valid && - is_mounted(path, MNTS_REAL)) { + else if (is_mounted(path, MNTS_REAL)) { debug(ap->logopt, "prune postponed, %s mounted", path); free(key); free(path); me = cache_enumerate(mc, me); continue; } - if (valid) - cache_unlock(valid->mc); me = cache_enumerate(mc, me); if (me) next_key = strdup(me->key); - cache_unlock(mc); cache_writelock(mc); @@ -1532,7 +1515,7 @@ int lookup_prune_cache(struct autofs_point *ap, time_t age) } /* Return with cache readlock held */ -struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type) +struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type, time_t age) { struct master_mapent *entry = ap->entry; struct map_source *map; @@ -1556,8 +1539,12 @@ struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *k me = cache_lookup_distinct(mc, key); else me = cache_lookup(mc, key); - if (me) - break; + if (me) { + /* Valid? */ + if (me->age >= age) + break; + me = NULL; + } cache_unlock(mc); map = map->next; } diff --git a/daemon/state.c b/daemon/state.c index dbd22be61..3760fef9e 100644 --- a/daemon/state.c +++ b/daemon/state.c @@ -337,17 +337,7 @@ static int do_readmap_mount(struct autofs_point *ap, * This is becuase of the requirement to continue running with * an empty cache awaiting a map re-load. */ - valid = lookup_source_valid_mapent(ap, me->key, LKP_DISTINCT); - if (valid && valid->mc == me->mc) { - /* - * We've found a map entry that has been removed from - * the current cache so there is no need to update it. - * The stale entry will be dealt with when we prune the - * cache later. - */ - cache_unlock(valid->mc); - valid = NULL; - } + valid = lookup_source_valid_mapent(ap, me->key, LKP_DISTINCT, now); if (valid) { struct mapent_cache *vmc = valid->mc; struct ioctl_ops *ops = get_ioctl_ops(); @@ -369,8 +359,11 @@ static int do_readmap_mount(struct autofs_point *ap, /* Take over the mount if there is one */ valid->ioctlfd = me->ioctlfd; me->ioctlfd = -1; + /* Same path */ + valid->dev = me->dev; + valid->ino = me->ino; /* Set device and inode number of the new mapent */ - cache_set_ino_index(vmc, me); + cache_set_ino_index(vmc, valid); cache_unlock(vmc); /* Set timeout and calculate the expire run frequency */ timeout = get_exp_timeout(ap, map); diff --git a/include/automount.h b/include/automount.h index 79a375512..955f5928c 100644 --- a/include/automount.h +++ b/include/automount.h @@ -279,7 +279,7 @@ int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const c void lookup_close_lookup(struct autofs_point *ap); void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, time_t age); 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); +struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type, time_t age); 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); -- 2.50.1