From 7f03cb7b09017d8052d73f27f7f2d45cc4e2b551 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Wed, 4 Mar 2026 09:56:18 +0800 Subject: [PATCH] - Add fix for Jira RHEL-113623. --- ...-5.1.9-add-function-table_lookup_ino.patch | 122 ++++++++++++ ...ck-must-be-taken-in-update_map_cache.patch | 48 +++++ autofs-5.1.9-fix-devid-update-on-reload.patch | 180 ++++++++++++++++++ ...ct-mount-trigger-umount-failure-case.patch | 39 ++++ ...-valid-map-entries-on-expire-cleanup.patch | 51 +++++ ...mount-trigger-not-umounted-on-expire.patch | 90 +++++++++ ...-missing-map-entry-for-mount-request.patch | 98 ++++++++++ ...1.9-quiet-possibly-noisy-log-message.patch | 35 ++++ ...1.9-refactor-do_umount_autofs_direct.patch | 158 +++++++++++++++ ...necessary-assignment-in-umount_multi.patch | 36 ++++ ...l-to-set_direct_mount_tree_catatonic.patch | 44 +++++ autofs.spec | 43 ++++- 12 files changed, 943 insertions(+), 1 deletion(-) create mode 100644 autofs-5.1.9-add-function-table_lookup_ino.patch create mode 100644 autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch create mode 100644 autofs-5.1.9-fix-devid-update-on-reload.patch create mode 100644 autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch create mode 100644 autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch create mode 100644 autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch create mode 100644 autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch create mode 100644 autofs-5.1.9-quiet-possibly-noisy-log-message.patch create mode 100644 autofs-5.1.9-refactor-do_umount_autofs_direct.patch create mode 100644 autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch create mode 100644 autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch diff --git a/autofs-5.1.9-add-function-table_lookup_ino.patch b/autofs-5.1.9-add-function-table_lookup_ino.patch new file mode 100644 index 0000000..c59b8ba --- /dev/null +++ b/autofs-5.1.9-add-function-table_lookup_ino.patch @@ -0,0 +1,122 @@ +autofs-5.1.9 - add function table_lookup_ino() + +From: Ian Kent + +Add function table_lookup_ino() to try and locate a mount for a given +device, open a file handle for it, and return it's path in the provided +buffer. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + include/mounts.h | 1 + lib/mounts.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 80 insertions(+) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -195,6 +195,7 @@ + - fix direct mount trigger umount failure case. + - refactor do_umount_autofs_direct(). + - fix stale direct mount trigger not umounted on expire. ++- add function table_lookup_ino(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/include/mounts.h ++++ autofs-5.1.7/include/mounts.h +@@ -175,6 +175,7 @@ void mnts_remove_amdmounts(struct autofs + struct mnt_list *mnts_add_mount(struct autofs_point *ap, const char *name, unsigned int flags); + void mnts_remove_mount(const char *mp, unsigned int flags); + struct mnt_list *get_mnt_list(const char *path, int include); ++char *table_lookup_ino(struct autofs_point *ap, dev_t dev, ino_t ino, char *buf, size_t len, int *fd); + unsigned int mnts_has_mounted_mounts(struct autofs_point *ap); + int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr); + void tree_free(struct tree_node *root); +--- autofs-5.1.7.orig/lib/mounts.c ++++ autofs-5.1.7/lib/mounts.c +@@ -2335,6 +2335,84 @@ void free_mnt_list(struct mnt_list *list + } + } + ++char *table_lookup_ino(struct autofs_point *ap, ++ dev_t dev, ino_t ino, ++ char *buf, size_t len, int *fd) ++{ ++ struct ioctl_ops *ops; ++ struct mntent *mnt; ++ struct mntent mnt_wrk; ++ char tmp[PATH_MAX * 3]; ++ char *path = NULL; ++ FILE *tab; ++ int ret = 0; ++ ++ ops = get_ioctl_ops(); ++ if (!ops) { ++ errno = EINVAL; ++ return NULL; ++ } ++ ++ tab = open_fopen_r(_PROC_MOUNTS); ++ if (!tab) { ++ errno = EINVAL; ++ return NULL; ++ } ++ ++ while ((mnt = local_getmntent_r(tab, &mnt_wrk, tmp, PATH_MAX * 3))) { ++ unsigned int type; ++ int ioctlfd; ++ dev_t devid; ++ ++ if (strcmp(mnt->mnt_type, "autofs")) ++ continue; ++ ++ type = t_direct; ++ if (strstr(mnt->mnt_opts, "indirect")) ++ type = t_indirect; ++ else if (strstr(mnt->mnt_opts, "offset")) ++ type = t_offset; ++ ++ ret = ops->mount_device(ap->logopt, mnt->mnt_dir, type, &devid); ++ if (ret == -1 || ret == 0) ++ continue; ++ ++ /* Our should be unique so there can only ++ * be one. ++ */ ++ ioctlfd = open_ioctlfd(ap, mnt->mnt_dir, devid); ++ /* errno will be set on fail */ ++ if (ioctlfd == -1) ++ break; ++ if (fd > 0) { ++ struct stat st; ++ ++ if (fstat(ioctlfd, &st) == -1) { ++ ops->close(ap->logopt, ioctlfd); ++ break; ++ } ++ ++ if (strlen(mnt->mnt_dir) >= len) { ++ ops->close(ap->logopt, ioctlfd); ++ errno = ENAMETOOLONG; ++ break; ++ } ++ ++ if (st.st_dev == dev && st.st_ino == ino) { ++ strcpy(buf, mnt->mnt_dir); ++ path = buf; ++ *fd = ioctlfd; ++ break; ++ } ++ ops->close(ap->logopt, ioctlfd); ++ break; ++ } ++ } ++ fclose(tab); ++ ++ return path; ++} ++ + static int table_is_mounted(const char *mp, unsigned int type) + { + struct mntent *mnt; diff --git a/autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch b/autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch new file mode 100644 index 0000000..0c97fcf --- /dev/null +++ b/autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch @@ -0,0 +1,48 @@ +autofs-5.1.9 - fix cache writelock must be taken in update_map_cache() + +From: Ian Kent + +In update_map_cache() the cache writelock must be taken because we need +to clean up the map entry as it will be a problem later if we don't. + +It's possible that some other process has taken the lock temporarily but +when this function is called the thread does not hold any cache locks so +it should be ok to aquire it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 12 +++++------- + 2 files changed, 6 insertions(+), 7 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -188,6 +188,7 @@ + - fix always recreate credential cache. + - quiet possibly noisy log message. + - fix devid update on reload. ++- fix cache writelock must be taken in update_map_cache(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/automount.c ++++ autofs-5.1.7/daemon/automount.c +@@ -511,13 +511,11 @@ static void update_map_cache(struct auto + } + + mc = map->mc; +- /* If the lock is busy try later */ +- if (cache_try_writelock(mc)) { +- me = cache_lookup_distinct(mc, key); +- if (me && me->ioctlfd == -1) +- cache_delete(mc, key); +- cache_unlock(mc); +- } ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, key); ++ if (me && me->ioctlfd == -1) ++ cache_delete(mc, key); ++ cache_unlock(mc); + + map = map->next; + } diff --git a/autofs-5.1.9-fix-devid-update-on-reload.patch b/autofs-5.1.9-fix-devid-update-on-reload.patch new file mode 100644 index 0000000..20cb0f9 --- /dev/null +++ b/autofs-5.1.9-fix-devid-update-on-reload.patch @@ -0,0 +1,180 @@ +autofs-5.1.9 - fix devid update on reload + +From: Ian Kent + +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 +--- + CHANGELOG | 1 + + daemon/lookup.c | 38 ++++++++++++-------------------------- + daemon/state.c | 17 +++++------------ + include/automount.h | 2 +- + 4 files changed, 19 insertions(+), 39 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -187,6 +187,7 @@ + - always recreate credential cache. + - fix always recreate credential cache. + - quiet possibly noisy log message. ++- fix devid update on reload. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/lookup.c ++++ autofs-5.1.7/daemon/lookup.c +@@ -1346,6 +1346,7 @@ void lookup_prune_one_cache(struct autof + + me = cache_enumerate(mc, NULL); + while (me) { ++ dev_t devid; + struct mapent *valid; + char *key = NULL, *next_key = NULL; + +@@ -1403,6 +1404,7 @@ void lookup_prune_one_cache(struct autof + me = cache_enumerate(mc, me); + continue; + } ++ devid = ap->type == LKP_INDIRECT ? ap->dev : me->dev; + + /* + * If this key has another valid entry we want to prune it, +@@ -1410,37 +1412,20 @@ void lookup_prune_one_cache(struct autof + * 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); +@@ -1453,10 +1438,7 @@ void lookup_prune_one_cache(struct autof + if (valid) + cache_delete(mc, key); + else if (!is_mounted(path, MNTS_AUTOFS)) { +- dev_t devid = ap->dev; + status = CHE_FAIL; +- if (ap->type == LKP_DIRECT) +- devid = this->dev; + if (this->ioctlfd == -1) + status = cache_delete(mc, key); + if (status != CHE_FAIL) { +@@ -1530,7 +1512,7 @@ int lookup_prune_cache(struct autofs_poi + } + + /* 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; +@@ -1554,8 +1536,12 @@ struct mapent *lookup_source_valid_mapen + 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; + } +--- autofs-5.1.7.orig/daemon/state.c ++++ autofs-5.1.7/daemon/state.c +@@ -333,17 +333,7 @@ static int do_readmap_mount(struct autof + * 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(); +@@ -365,8 +355,11 @@ static int do_readmap_mount(struct autof + /* 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); +--- autofs-5.1.7.orig/include/automount.h ++++ autofs-5.1.7/include/automount.h +@@ -274,7 +274,7 @@ int lookup_nss_mount(struct autofs_point + 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); + diff --git a/autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch b/autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch new file mode 100644 index 0000000..06338a5 --- /dev/null +++ b/autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch @@ -0,0 +1,39 @@ +autofs-5.1.9 - fix direct mount trigger umount failure case + +From: Ian Kent + +In function do_umount_autofs_direct() for the case where the trigger +mount is found to be in use we should be detaching the mount so it gets +umounted but the process can continue using it while it has an open file +handle for it. + +This is because direct mount triggers are only umounted when the map +entry is removed from a map or automount(8) is shutdown which in both +cases the trigger mount needs to go away. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/direct.c | 1 + + 2 files changed, 2 insertions(+) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -192,6 +192,7 @@ + - fix skip valid map entries on expire cleanup. + - remove unnecessary call to set_direct_mount_tree_catatonic(). + - remove unnecessary assignment in umount_multi(). ++- fix direct mount trigger umount failure case. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/direct.c ++++ autofs-5.1.7/daemon/direct.c +@@ -153,6 +153,7 @@ int do_umount_autofs_direct(struct autof + } else { + me->ioctlfd = -1; + ops->close(ap->logopt, ioctlfd); ++ rv = -1; + goto force_umount; + } + } diff --git a/autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch b/autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch new file mode 100644 index 0000000..871185b --- /dev/null +++ b/autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch @@ -0,0 +1,51 @@ +autofs-5.1.9 - fix skip valid map entries on expire cleanup + +From: Ian Kent + +After an expire if the current map entry is stale because it could not +be cleaned up during the map entry prune (due to the presence of a real +mount) it needs to be cleaned up after a successful expire. + +Currently this is done by update_map_cache() if the entry is contained +in an invalid map but it should be doing it if the entry is no longer +valid. In addition, if update_map_cache() gets called the umount has +been successful so the ioctlfd does not need to be checked (and is in +fact updated later in the expire process). + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 9 ++------- + 2 files changed, 3 insertions(+), 7 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -189,6 +189,7 @@ + - quiet possibly noisy log message. + - fix devid update on reload. + - fix cache writelock must be taken in update_map_cache(). ++- fix skip valid map entries on expire cleanup. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/automount.c ++++ autofs-5.1.7/daemon/automount.c +@@ -504,16 +504,11 @@ static void update_map_cache(struct auto + while (map) { + struct mapent *me = NULL; + +- /* Skip current, in-use cache */ +- if (ap->entry->age <= map->age) { +- map = map->next; +- continue; +- } +- + mc = map->mc; + cache_writelock(mc); + me = cache_lookup_distinct(mc, key); +- if (me && me->ioctlfd == -1) ++ /* Only for invalid map entries */ ++ if (me && map->age > me->age) + cache_delete(mc, key); + cache_unlock(mc); + diff --git a/autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch b/autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch new file mode 100644 index 0000000..068a643 --- /dev/null +++ b/autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch @@ -0,0 +1,90 @@ +autofs-5.1.9 - fix stale direct mount trigger not umounted on expire + +From: Ian Kent + +If a direct mount map entry is removed but has an active real mount the +mount trigger needs to be unmounted during the expire cleanup. + +If the direct mount map entry has been re-added the map entry age will +have been updated so the entry won't be seen as stale so the umount +won't be done. + +Also in function umount_multi() update_map_cache() and check_rm_dirs() +are not called for direct mounts because count_mounts() always returns +1 or more for top level direct mounts. Make this clear by using ap->type +in the logical check and rely on the left == 0 check to verify there are +no remaining mounts for indirect mounts since count_mounts() will be +more expensive. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 12 ++++++++---- + daemon/direct.c | 22 +++++++++++++++++++++- + 3 files changed, 30 insertions(+), 5 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -194,6 +194,7 @@ + - remove unnecessary assignment in umount_multi(). + - fix direct mount trigger umount failure case. + - refactor do_umount_autofs_direct(). ++- fix stale direct mount trigger not umounted on expire. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/automount.c ++++ autofs-5.1.7/daemon/automount.c +@@ -697,10 +697,14 @@ int umount_multi(struct autofs_point *ap + + left = umount_subtree_mounts(ap, path, is_autofs_fs); + +- /* Delete detritus like unwanted mountpoints and symlinks */ +- if (left == 0 && +- ap->state != ST_READMAP && +- !count_mounts(ap, path, ap->dev)) { ++ /* Delete detritus like unwanted mountpoints and symlinks ++ * for indirect mounts. This can't be done for direct mounts ++ * here because there's an ioctl file handle open on the ++ * autofs trigger mount for them so it must be done after ++ * the expire. ++ */ ++ if (ap->type == LKP_INDIRECT && ++ ap->state != ST_READMAP && left == 0) { + update_map_cache(ap, path); + check_rm_dirs(ap, path, incl); + } +--- autofs-5.1.7.orig/daemon/direct.c ++++ autofs-5.1.7/daemon/direct.c +@@ -1003,10 +1003,30 @@ static void *do_expire_direct(void *arg) + mt.ioctlfd, mt.wait_queue_token, -ENOENT); + else { + struct mapent *me; ++ + cache_writelock(mt.mc); + me = cache_lookup_distinct(mt.mc, mt.name); +- if (me) ++ if (me) { ++ /* If the direct mount map entry is no longer ++ * valid but there is an autofs mount trigger ++ * for the mount the mount trigger needs to be ++ * umounted, the map entry deleted and the mount ++ * point directory removed (if it was created by ++ * us). ++ */ + me->ioctlfd = -1; ++ if (me->mc->map->age > me->age && ++ is_mounted(mt.name, MNTS_AUTOFS)) { ++ /* We must detach the mount becuase the ++ * umount must be completed before ++ * notifying status to the kernel but ++ * there's an ioctlfd open on the ++ * trigger. ++ */ ++ if (!finish_umount(ap, me, -1)) ++ cache_delete(me->mc, me->key); ++ } ++ } + cache_unlock(mt.mc); + ops->send_ready(ap->logopt, mt.ioctlfd, mt.wait_queue_token); + ops->close(ap->logopt, mt.ioctlfd); diff --git a/autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch b/autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch new file mode 100644 index 0000000..79fc60a --- /dev/null +++ b/autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch @@ -0,0 +1,98 @@ +autofs-5.1.9 - improve handling of missing map entry for mount request + +From: Ian Kent + +If the map entry isn't found it must have been deleted from the map but +a trigger mount is still mounted because it has sent us this request. +Use the mount table for a brute force lookup to get the path and open a +file handle for it so we can send a failure status to the kernel. + +Also remove the crit() log message following open_ioctlfd() as it already +issues an appropriate error message on failure. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/direct.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 48 insertions(+), 6 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -196,6 +196,7 @@ + - refactor do_umount_autofs_direct(). + - fix stale direct mount trigger not umounted on expire. + - add function table_lookup_ino(). ++- improve handling of missing map entry for mount request. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/direct.c ++++ autofs-5.1.7/daemon/direct.c +@@ -1368,12 +1368,54 @@ int handle_packet_missing_direct(struct + } + + if (!me) { +- /* +- * Shouldn't happen as the kernel is telling us +- * someone has walked on our mount point. ++ char tmp[PATH_MAX + 1]; ++ char *path; ++ ++ /* If the map entry wasn't found it must have been deleted ++ * from the map but a trigger mount is still mounted because ++ * it has sent us this request. So use the mount table for a ++ * brute force lookup to get the path and open a file handle ++ * for it so we can return a not found status to the kernel. + */ +- logerr("can't find map entry for (%lu,%lu)", +- (unsigned long) pkt->dev, (unsigned long) pkt->ino); ++ path = table_lookup_ino(ap, pkt->dev, pkt->ino, tmp, PATH_MAX + 1, &ioctlfd); ++ if (!path) { ++ /* This could be cuased by an inability to open a file ++ * handle but generally that doesn't happen. The mount ++ * has to exist and be pinned becuase we got this request ++ * so it can't be umounted. Therefore it's very unlikely ++ * this case will happen. If it does happen it's fatal, ++ * the waiter will hang and there's nothing we can do ++ * about it. ++ */ ++ logerr("can't find mount for (%lu,%lu)", ++ (unsigned long) pkt->dev, (unsigned long) pkt->ino); ++ /* TODO: how do we clear wait q in kernel ?? */ ++ } else { ++ char buf[MAX_ERR_BUF]; ++ ++ /* Try and recover from this unexpecyedly missing map ++ * entry by detaching the direct mount trigger that ++ * sent the request so it's no longer visible to the ++ * VFS. ++ */ ++ info(ap->logopt, "forcing umount of direct mount %s", path); ++ if (umount2(path, MNT_DETACH) == -1) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ warn(ap->logopt, "failed to force umount %s: %s", ++ path, estr); ++ } ++ if (rmdir(path) == -1) { ++ char buf[MAX_ERR_BUF]; ++ char *estr; ++ ++ estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ warn(ap->logopt, ++ "failed to remove dir %s: %s", path, estr); ++ } ++ ops->send_fail(ap->logopt, ++ ioctlfd, pkt->wait_queue_token, -EINVAL); ++ ops->close(ap->logopt, ioctlfd); ++ } + master_source_unlock(ap->entry); + master_mutex_unlock(); + pthread_setcancelstate(state, NULL); +@@ -1392,7 +1434,6 @@ int handle_packet_missing_direct(struct + master_source_unlock(ap->entry); + master_mutex_unlock(); + pthread_setcancelstate(state, NULL); +- crit(ap->logopt, "failed to create ioctl fd for %s", me->key); + /* TODO: how do we clear wait q in kernel ?? */ + return 1; + } diff --git a/autofs-5.1.9-quiet-possibly-noisy-log-message.patch b/autofs-5.1.9-quiet-possibly-noisy-log-message.patch new file mode 100644 index 0000000..c4dd9c6 --- /dev/null +++ b/autofs-5.1.9-quiet-possibly-noisy-log-message.patch @@ -0,0 +1,35 @@ +autofs-5.1.9 - quiet possibly noisy log message + +From: Ian Kent + +The message that logs when a mount is already mounted and only the +timeout will be updated on map re-read can create a lot of noise in +the log for direct mount maps. But this is normal operation and is of +limited value for both direct and indirect maps, so remove it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + lib/mounts.c | 1 - + 2 files changed, 1 insertion(+), 1 deletion(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -186,6 +186,7 @@ + - fix invalidated map entry handling in hosts module. + - always recreate credential cache. + - fix always recreate credential cache. ++- quiet possibly noisy log message. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/lib/mounts.c ++++ autofs-5.1.7/lib/mounts.c +@@ -2895,7 +2895,6 @@ static int remount_active_mount(struct a + + /* Re-reading the map, set timeout and return */ + if (ap->state == ST_READMAP) { +- debug(ap->logopt, "already mounted, update timeout"); + ops->timeout(ap->logopt, fd, NULL, timeout); + ops->close(ap->logopt, fd); + return REMOUNT_READ_MAP; diff --git a/autofs-5.1.9-refactor-do_umount_autofs_direct.patch b/autofs-5.1.9-refactor-do_umount_autofs_direct.patch new file mode 100644 index 0000000..3cd2292 --- /dev/null +++ b/autofs-5.1.9-refactor-do_umount_autofs_direct.patch @@ -0,0 +1,158 @@ +autofs-5.1.9 - refactor do_umount_autofs_direct() + +From: Ian Kent + +Refactor functon do_umount_autofs_direct() so that it can be called from +do_expire_direct() to clean up stale direct mounts that couldn't be +cleaned up at map re-load. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/direct.c | 106 ++++++++++++++++++++++++++++++-------------------------- + 2 files changed, 58 insertions(+), 49 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -193,6 +193,7 @@ + - remove unnecessary call to set_direct_mount_tree_catatonic(). + - remove unnecessary assignment in umount_multi(). + - fix direct mount trigger umount failure case. ++- refactor do_umount_autofs_direct(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/direct.c ++++ autofs-5.1.7/daemon/direct.c +@@ -81,12 +81,66 @@ static void mnts_cleanup(void *arg) + mnts_put_expire_list(mnts); + } + ++static int finish_umount(struct autofs_point *ap, struct mapent *me, int rv) ++{ ++ char buf[MAX_ERR_BUF]; ++ ++ if (rv != 0) { ++ info(ap->logopt, "forcing umount of direct mount %s", me->key); ++ rv = umount2(me->key, MNT_DETACH); ++ } else ++ info(ap->logopt, "umounted direct mount %s", me->key); ++ ++ if (!rv && me->flags & MOUNT_FLAG_DIR_CREATED) { ++ if (rmdir(me->key) == -1) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ warn(ap->logopt, "failed to remove dir %s: %s", ++ me->key, estr); ++ } ++ } ++ return rv; ++} ++ ++static int do_umount_direct(struct autofs_point *ap, struct mapent *me) ++{ ++ int rv, retries = UMOUNT_RETRIES; ++ ++ while ((rv = umount(me->key)) == -1 && retries--) { ++ struct timespec tm = {0, 50000000}; ++ if (errno != EBUSY) ++ break; ++ nanosleep(&tm, NULL); ++ } ++ ++ if (rv == -1) { ++ switch (errno) { ++ case ENOENT: ++ case EINVAL: ++ warn(ap->logopt, "mount point %s does not exist", ++ me->key); ++ return 0; ++ case EBUSY: ++ warn(ap->logopt, "mount point %s is in use", me->key); ++ if (ap->state == ST_SHUTDOWN_FORCE) ++ goto out; ++ else ++ return 0; ++ case ENOTDIR: ++ error(ap->logopt, "mount point is not a directory"); ++ return 0; ++ } ++ return 1; ++ } ++out: ++ return finish_umount(ap, me, rv); ++} ++ + int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me) + { + struct ioctl_ops *ops = get_ioctl_ops(); + struct mapent_cache *mc = me->mc; + char buf[MAX_ERR_BUF]; +- int ioctlfd = -1, rv, left, retries; ++ int ioctlfd = -1, rv, left; + char key[PATH_MAX + 1]; + struct mapent *tmp; + int opened = 0; +@@ -153,8 +207,7 @@ int do_umount_autofs_direct(struct autof + } else { + me->ioctlfd = -1; + ops->close(ap->logopt, ioctlfd); +- rv = -1; +- goto force_umount; ++ return finish_umount(ap, me, -1); + } + } + me->ioctlfd = -1; +@@ -167,52 +220,7 @@ int do_umount_autofs_direct(struct autof + + sched_yield(); + +- retries = UMOUNT_RETRIES; +- while ((rv = umount(me->key)) == -1 && retries--) { +- struct timespec tm = {0, 50000000}; +- if (errno != EBUSY) +- break; +- nanosleep(&tm, NULL); +- } +- +- if (rv == -1) { +- switch (errno) { +- case ENOENT: +- case EINVAL: +- warn(ap->logopt, "mount point %s does not exist", +- me->key); +- return 0; +- break; +- case EBUSY: +- warn(ap->logopt, "mount point %s is in use", me->key); +- if (ap->state == ST_SHUTDOWN_FORCE) +- goto force_umount; +- else +- return 0; +- break; +- case ENOTDIR: +- error(ap->logopt, "mount point is not a directory"); +- return 0; +- break; +- } +- return 1; +- } +- +-force_umount: +- if (rv != 0) { +- info(ap->logopt, "forcing umount of direct mount %s", me->key); +- rv = umount2(me->key, MNT_DETACH); +- } else +- info(ap->logopt, "umounted direct mount %s", me->key); +- +- if (!rv && me->flags & MOUNT_FLAG_DIR_CREATED) { +- if (rmdir(me->key) == -1) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(ap->logopt, "failed to remove dir %s: %s", +- me->key, estr); +- } +- } +- return rv; ++ return do_umount_direct(ap, me); + } + + int umount_autofs_direct(struct autofs_point *ap) diff --git a/autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch b/autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch new file mode 100644 index 0000000..2b4be33 --- /dev/null +++ b/autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch @@ -0,0 +1,36 @@ +autofs-5.1.9 - remove unnecessary assignment in umount_multi() + +From: Ian Kent + +Remove the leftover initialisation of left from when there were multiple +calls to umount_subtree_mounts(). + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 4 +--- + 2 files changed, 2 insertions(+), 3 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -191,6 +191,7 @@ + - fix cache writelock must be taken in update_map_cache(). + - fix skip valid map entries on expire cleanup. + - remove unnecessary call to set_direct_mount_tree_catatonic(). ++- remove unnecessary assignment in umount_multi(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/automount.c ++++ autofs-5.1.7/daemon/automount.c +@@ -695,9 +695,7 @@ int umount_multi(struct autofs_point *ap + mnts_put_mount(sbmnt); + } + +- left = 0; +- +- left += umount_subtree_mounts(ap, path, is_autofs_fs); ++ left = umount_subtree_mounts(ap, path, is_autofs_fs); + + /* Delete detritus like unwanted mountpoints and symlinks */ + if (left == 0 && diff --git a/autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch b/autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch new file mode 100644 index 0000000..4199f60 --- /dev/null +++ b/autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch @@ -0,0 +1,44 @@ +autofs-5.1.9 - remove unnecessary call to set_direct_mount_tree_catatonic() + +From: Ian Kent + +Function do_umount_autofs_direct() is called in two cases, during a +readmap and when umounting top level direct mounts. + +During a readmap, mounts should not be set catatonic so the call to +set_direct_mount_tree_catatonic() is not needed. If it's called for a +top level direct mount the caller, umount_autofs_direct(), calls +set_direct_mount_tree_catatonic() itself already. So remove this +unnecessary call. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/direct.c | 5 +---- + 2 files changed, 2 insertions(+), 4 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -190,6 +190,7 @@ + - fix devid update on reload. + - fix cache writelock must be taken in update_map_cache(). + - fix skip valid map entries on expire cleanup. ++- remove unnecessary call to set_direct_mount_tree_catatonic(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/direct.c ++++ autofs-5.1.7/daemon/direct.c +@@ -186,11 +186,8 @@ int do_umount_autofs_direct(struct autof + warn(ap->logopt, "mount point %s is in use", me->key); + if (ap->state == ST_SHUTDOWN_FORCE) + goto force_umount; +- else { +- if (ap->state != ST_READMAP) +- set_direct_mount_tree_catatonic(ap, me); ++ else + return 0; +- } + break; + case ENOTDIR: + error(ap->logopt, "mount point is not a directory"); diff --git a/autofs.spec b/autofs.spec index 206d4f9..d0546cc 100644 --- a/autofs.spec +++ b/autofs.spec @@ -12,7 +12,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.1.7 -Release: 65%{?dist} +Release: 66%{?dist} Epoch: 1 License: GPLv2+ Source: https://www.kernel.org/pub/linux/daemons/autofs/v5/autofs-%{version}-2.tar.gz @@ -233,6 +233,19 @@ Patch211: autofs-5.1.9-fix-invalidated-map-entry-handling-in-hosts-module.patch Patch212: autofs-5.1.8-always-recreate-credential-cache.patch Patch213: autofs-5.1.9-fix-always-recreate-credential-cache.patch +# JIRA: RHEL-113623 +Patch214: autofs-5.1.9-quiet-possibly-noisy-log-message.patch +Patch215: autofs-5.1.9-fix-devid-update-on-reload.patch +Patch216: autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch +Patch217: autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch +Patch218: autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch +Patch219: autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch +Patch220: autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch +Patch221: autofs-5.1.9-refactor-do_umount_autofs_direct.patch +Patch222: autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch +Patch223: autofs-5.1.9-add-function-table_lookup_ino.patch +Patch224: autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch + %if %{with_systemd} BuildRequires: systemd-units BuildRequires: systemd-devel @@ -496,6 +509,18 @@ echo %{version}-%{release} > .version %patch -P 212 -p1 %patch -P 213 -p1 +%patch -P 214 -p1 +%patch -P 215 -p1 +%patch -P 216 -p1 +%patch -P 217 -p1 +%patch -P 218 -p1 +%patch -P 219 -p1 +%patch -P 220 -p1 +%patch -P 221 -p1 +%patch -P 222 -p1 +%patch -P 223 -p1 +%patch -P 224 -p1 + %build LDFLAGS=-Wl,-z,now %configure \ @@ -603,6 +628,22 @@ fi %dir /etc/auto.master.d %changelog +* Wed Mar 04 2026 Ian Kent - 1:5.1.7-66 +- RHEL-113623 - Wrong oz_pgrp in autofs_sb_info causes automount to wait + on automount. + - quiet possibly noisy log message. + - fix devid update on reload. + - fix cache writelock must be taken in update_map_cache(). + - fix skip valid map entries on expire cleanup. + - remove unnecessary call to set_direct_mount_tree_catatonic(). + - remove unnecessary assignment in umount_multi(). + - fix direct mount trigger umount failure case. + - refactor do_umount_autofs_direct(). + - fix stale direct mount trigger not umounted on expire. + - add function table_lookup_ino(). + - improve handling of missing map entry for mount request. +- Resolves: RHEL-113623 + * Tue May 13 2025 Ian Kent - 1:5.1.7-65 - RHEL-85615 - autofs fails to mount shares when using kerberised LDAP - always recreate credential cache.