diff --git a/SOURCES/autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch b/SOURCES/autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch new file mode 100644 index 0000000..a821819 --- /dev/null +++ b/SOURCES/autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch @@ -0,0 +1,72 @@ +autofs-5.1.7 - clear per-mount timeout if not set + +From: Ian Kent + +If the per-mount timeout isn't set in the amd map entry clear it so +that updates that remove the setting are seen. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + lib/mounts.c | 8 +++++++- + modules/parse_amd.c | 12 ++++++++---- + 3 files changed, 16 insertions(+), 5 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -176,6 +176,7 @@ + - fix remount_active_mount() not remounting symlinks. + - log when setting amd per-mount timeout. + - update per-mount expire timeout on readmap. ++- clear per-mount timeout if not set. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -2696,8 +2696,14 @@ void update_mounted_mounts_timeout(struc + goto next; + + /* No per-mount timeout set? */ +- if (!(mnt->amd_flags & AMD_MOUNT_OPT_MASK)) ++ if (!(mnt->amd_flags & AMD_MOUNT_OPT_MASK)) { ++ /* Per-mount timeout setting isn't present, reset to ++ * be sure updates are seen. ++ */ ++ if (ops) ++ ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, -1); + goto next; ++ } + + /* The default in autofs is to always expire mounts according to + * a timeout set in the autofs mount super block information +--- autofs-5.1.4.orig/modules/parse_amd.c ++++ autofs-5.1.4/modules/parse_amd.c +@@ -1720,10 +1720,16 @@ static int amd_mount(struct autofs_point + } + + if (!ret) { +- struct ioctl_ops *ops; ++ struct ioctl_ops *ops = get_ioctl_ops(); + +- if (!(per_mnt_flags & AMD_MOUNT_OPT_MASK)) ++ if (!(per_mnt_flags & AMD_MOUNT_OPT_MASK)) { ++ /* Per-mount timeout setting isn't present, reset to ++ * be sure updates are seen. ++ */ ++ if (ops) ++ ops->timeout(ap->logopt, ap->ioctlfd, name, -1); + goto done; ++ } + + /* The mount succeeded, make sure there's no path component + * seperator in "name" as it must be the last component of +@@ -1734,8 +1740,6 @@ static int amd_mount(struct autofs_point + goto done; + } + +- ops = get_ioctl_ops(); +- + /* The default in autofs is to always expire mounts according to + * a timeout set in the autofs mount super block information + * structure. But amd allows for differing expire timeouts on a diff --git a/SOURCES/autofs-5.1.9-add-function-table_lookup_ino.patch b/SOURCES/autofs-5.1.9-add-function-table_lookup_ino.patch new file mode 100644 index 0000000..3d657e4 --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -188,6 +188,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(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/include/mounts.h ++++ autofs-5.1.4/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.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -2330,6 +2330,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/SOURCES/autofs-5.1.9-add-some-unimplemented-amd-map-options.patch b/SOURCES/autofs-5.1.9-add-some-unimplemented-amd-map-options.patch new file mode 100644 index 0000000..10f8227 --- /dev/null +++ b/SOURCES/autofs-5.1.9-add-some-unimplemented-amd-map-options.patch @@ -0,0 +1,221 @@ +commit 6cbb6e9a3b8b223babf723e0f56cdd7b7eb90455 +Author: Ian Kent +Date: Mon Jul 8 11:04:11 2024 +0800 + + autofs-5.1.9 - add some unimplemented amd map options + + Add handling for amd per-mount options "utimeout", "unmount" and "nounmount" + if the kernel supports it. + + Signed-off-by: Ian Kent + +--- + CHANGELOG | 1 + + include/mounts.h | 2 ++ + include/parse_amd.h | 6 ++++++ + lib/mounts.c | 4 ++++ + modules/amd_parse.y | 38 +++++++++++++++++++++++++++++++------- + modules/parse_amd.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 94 insertions(+), 7 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -171,6 +171,7 @@ + - seperate amd mount and entry flags. + - make iocl ops ->timeout() handle per-dentry expire. + - refactor amd mount options handling. ++- add some unimplemented amd map options. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/include/mounts.h ++++ autofs-5.1.4/include/mounts.h +@@ -113,6 +113,8 @@ struct mnt_list { + char *amd_pref; + char *amd_type; + char *amd_opts; ++ unsigned long amd_flags; ++ unsigned int amd_utimeout; + unsigned int amd_cache_opts; + struct list_head amdmount; + +--- autofs-5.1.4.orig/include/parse_amd.h ++++ autofs-5.1.4/include/parse_amd.h +@@ -33,6 +33,11 @@ + #define AMD_MOUNT_TYPE_PROGRAM 0x00004000 + #define AMD_MOUNT_TYPE_MASK 0x0000ffff + ++#define AMD_MOUNT_OPT_UNMOUNT 0x00010000 ++#define AMD_MOUNT_OPT_NOUNMOUNT 0x00020000 ++#define AMD_MOUNT_OPT_UTIMEOUT 0x00040000 ++#define AMD_MOUNT_OPT_MASK 0x00ff0000 ++ + #define AMD_DEFAULTS_MERGE 0x0001 + #define AMD_DEFAULTS_RESET 0x0002 + #define AMD_DEFAULTS_MASK 0x00ff +@@ -49,6 +54,7 @@ + struct amd_entry { + char *path; + unsigned long flags; ++ unsigned int utimeout; + unsigned int cache_opts; + unsigned int entry_flags; + char *type; +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -1212,6 +1212,8 @@ struct mnt_list *mnts_add_amdmount(struc + this->amd_pref = pref; + this->amd_type = type; + this->amd_opts = opts; ++ this->amd_flags = entry->flags; ++ this->amd_utimeout = entry->utimeout; + this->amd_cache_opts = entry->cache_opts; + this->flags |= MNTS_AMD_MOUNT; + if (list_empty(&this->amdmount)) +@@ -1256,6 +1258,8 @@ static void __mnts_remove_amdmount(const + free(this->amd_opts); + this->amd_opts = NULL; + } ++ this->amd_flags = AMD_MOUNT_OPT_UNMOUNT; ++ this->amd_utimeout = -1; + this->amd_cache_opts = 0; + __mnts_put_mount(this); + } +--- autofs-5.1.4.orig/modules/amd_parse.y ++++ autofs-5.1.4/modules/amd_parse.y +@@ -647,8 +647,7 @@ static int match_mnt_option(char *option + { + int ret = 0; + +- if (!strcmp(option, "fullybrowsable") || +- !strcmp(option, "nounmount")) { ++ if (!strcmp(option, "fullybrowsable")) { + sprintf(msg_buf, "option %s is not currently " + "implemented, ignored", option); + amd_info(msg_buf); +@@ -660,15 +659,37 @@ static int match_mnt_option(char *option + sprintf(msg_buf, "option %s is not used by " + "autofs, ignored", option); + amd_info(msg_buf); ++ } else if (!strcmp(option, "umount")) { ++ entry.flags &= ~AMD_MOUNT_OPT_NOUNMOUNT; ++ entry.flags |= AMD_MOUNT_OPT_UNMOUNT; ++ } else if (!strcmp(option, "nounmount")) { ++ if (entry.flags & AMD_MOUNT_TYPE_AUTO) ++ prepend_opt(opts, "timeout=0"); ++ else { ++ entry.flags &= ~AMD_MOUNT_OPT_UNMOUNT; ++ entry.flags |= AMD_MOUNT_OPT_NOUNMOUNT; ++ entry.utimeout = 0; ++ } + } else if (!strncmp(option, "utimeout=", 9)) { ++ /* ++ * amd type "auto" mounts map to autofs fstype=autofs ++ * mounts so a distinct autofs mount is present at the ++ * the root so there's no need for special handling, ++ * just pass the timeout= autofs option. ++ */ + if (entry.flags & AMD_MOUNT_TYPE_AUTO) + prepend_opt(options, ++option); + else { +- sprintf(msg_buf, "umount timeout can't be " +- "used for other than type " +- "\"auto\" with autofs, " +- "ignored"); +- amd_info(msg_buf); ++ if (strchr(option, '=')) { ++ unsigned long tout; ++ int ret; ++ ++ ret = sscanf(option, "utimeout=%lu", &tout); ++ if (ret) { ++ entry.flags |= AMD_MOUNT_OPT_UTIMEOUT; ++ entry.utimeout = tout; ++ } ++ } + } + } else + ret = 1; +@@ -791,6 +812,8 @@ static void local_init_vars(void) + { + memset(&entry, 0, sizeof(entry)); + entry.cache_opts = AMD_CACHE_OPTION_NONE; ++ entry.flags = AMD_MOUNT_OPT_UNMOUNT; ++ entry.utimeout = -1; + memset(opts, 0, sizeof(opts)); + } + +@@ -900,6 +923,7 @@ static int add_location(void) + new->path = entry.path; + } + new->flags = entry.flags; ++ new->utimeout = entry.utimeout; + new->cache_opts = entry.cache_opts; + new->entry_flags = entry.entry_flags; + new->type = entry.type; +--- autofs-5.1.4.orig/modules/parse_amd.c ++++ autofs-5.1.4/modules/parse_amd.c +@@ -1647,6 +1647,7 @@ static int amd_mount(struct autofs_point + struct parse_context *ctxt) + { + unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK; ++ unsigned long per_mnt_flags = entry->flags & AMD_MOUNT_OPT_MASK; + int ret = 1; + + switch (fstype) { +@@ -1718,6 +1719,55 @@ static int amd_mount(struct autofs_point + break; + } + ++ if (!ret) { ++ struct ioctl_ops *ops; ++ ++ if (!(per_mnt_flags & AMD_MOUNT_OPT_MASK)) ++ goto done; ++ ++ /* The mount succeeded, make sure there's no path component ++ * seperator in "name" as it must be the last component of ++ * the mount point alone for the per-mount options. ++ */ ++ if (strchr(name, '/')) { ++ warn(ap->logopt, "path component seperator not valid here"); ++ goto done; ++ } ++ ++ ops = get_ioctl_ops(); ++ ++ /* The default in autofs is to always expire mounts according to ++ * a timeout set in the autofs mount super block information ++ * structure. But amd allows for differing expire timeouts on a ++ * per-mount basis. It also has (context sensitive) options "unmount" ++ * to say expire this mount and "nounmount" to say don't expire this ++ * mount. In amd mounts these options are set by default according ++ * to whether a mount should expire or not, for example a cd mount ++ * is set "nounmount". Setting defaults like this is not used in the ++ * autofs amd implementation because there's only one, little used, ++ * removable file system available. ++ * ++ * But the "nounmount" and "utimeout" options can be useful. ++ */ ++ if (per_mnt_flags & AMD_MOUNT_OPT_NOUNMOUNT) { ++ if (entry->utimeout) ++ warn(ap->logopt, ++ "non-zero timeout set, possible conflicting options"); ++ ++ /* "nounmount" option, don't expire this mount. */ ++ if (ops) ++ ops->timeout(ap->logopt, ap->ioctlfd, name, 0); ++ } else if (per_mnt_flags & AMD_MOUNT_OPT_UTIMEOUT) { ++ if (!entry->utimeout) ++ warn(ap->logopt, ++ "zero timeout set, possible conflicting options"); ++ ++ /* "utimeout" option, expire this mount according to a timeout. */ ++ if (ops) ++ ops->timeout(ap->logopt, ap->ioctlfd, name, entry->utimeout); ++ } ++ } ++done: + return ret; + } + diff --git a/SOURCES/autofs-5.1.9-fix-amd-cache-options-not-copied.patch b/SOURCES/autofs-5.1.9-fix-amd-cache-options-not-copied.patch new file mode 100644 index 0000000..5faea4e --- /dev/null +++ b/SOURCES/autofs-5.1.9-fix-amd-cache-options-not-copied.patch @@ -0,0 +1,36 @@ +commit abf2030556dfe694dc19ed2d73f84f7e5046b660 +Author: Ian Kent +Date: Thu Jul 11 13:56:15 2024 +0800 + + autofs-5.1.9 - fix amd cache options not copied + + The cache options set when parsing the amd map entry are not copied to + the list entry that gets processed by the caller. + + Signed-off-by: Ian Kent + +--- + CHANGELOG | 1 + + modules/amd_parse.y | 1 + + 2 files changed, 2 insertions(+) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -167,6 +167,7 @@ + - fix always recreate credential cache. + - fix missing unlock in sasl_do_kinit_ext_cc(). + - handle sss special case getautomntbyname() error. ++- fix amd cache options not copied. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/modules/amd_parse.y ++++ autofs-5.1.4/modules/amd_parse.y +@@ -888,6 +888,7 @@ static int add_location(void) + new->path = entry.path; + } + new->flags = entry.flags; ++ new->cache_opts = entry.cache_opts; + new->type = entry.type; + new->map_type = entry.map_type; + new->pref = entry.pref; diff --git a/SOURCES/autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch b/SOURCES/autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch new file mode 100644 index 0000000..cd9d9c7 --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -181,6 +181,7 @@ + - skip expire check for amd nounmount mounts. + - quiet possibly noisy log message. + - fix devid update on reload. ++- fix cache writelock must be taken in update_map_cache(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -512,13 +512,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/SOURCES/autofs-5.1.9-fix-devid-update-on-reload.patch b/SOURCES/autofs-5.1.9-fix-devid-update-on-reload.patch new file mode 100644 index 0000000..fe28b95 --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -180,6 +180,7 @@ + - fix incorrect flags update in update_with_defaults(). + - skip expire check for amd nounmount mounts. + - quiet possibly noisy log message. ++- fix devid update on reload. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/lookup.c ++++ autofs-5.1.4/daemon/lookup.c +@@ -1354,6 +1354,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; + +@@ -1411,6 +1412,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, +@@ -1418,37 +1420,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); +@@ -1461,10 +1446,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) { +@@ -1538,7 +1520,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; +@@ -1562,8 +1544,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.4.orig/daemon/state.c ++++ autofs-5.1.4/daemon/state.c +@@ -357,17 +357,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(); +@@ -389,8 +379,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.4.orig/include/automount.h ++++ autofs-5.1.4/include/automount.h +@@ -273,7 +273,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/SOURCES/autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch b/SOURCES/autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch new file mode 100644 index 0000000..1aa553c --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -185,6 +185,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. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/direct.c ++++ autofs-5.1.4/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/SOURCES/autofs-5.1.9-fix-incorrect-flags-update-in-update_with_defaults.patch b/SOURCES/autofs-5.1.9-fix-incorrect-flags-update-in-update_with_defaults.patch new file mode 100644 index 0000000..26e0e5e --- /dev/null +++ b/SOURCES/autofs-5.1.9-fix-incorrect-flags-update-in-update_with_defaults.patch @@ -0,0 +1,41 @@ +autofs-5.1.9 - fix incorrect flags update in update_with_defaults() + +From: Ian Kent + +After adding support for some additional am-utils map entry options at +least one of them, "nounmount", and probably others don't work in some +cases. + +This is because some of them are is implemented using a flag in the map +entry which was incorrectly being cleared during updating the entry with +current defaults. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/parse_amd.c | 4 +++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -177,6 +177,7 @@ + - log when setting amd per-mount timeout. + - update per-mount expire timeout on readmap. + - clear per-mount timeout if not set. ++- fix incorrect flags update in update_with_defaults(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/modules/parse_amd.c ++++ autofs-5.1.4/modules/parse_amd.c +@@ -654,7 +654,9 @@ static void update_with_defaults(struct + if (deftype != AMD_MOUNT_TYPE_NONE) + entry->flags |= (defaults->flags & AMD_MOUNT_TYPE_MASK); + else { +- entry->flags = AMD_MOUNT_TYPE_NFS; ++ unsigned long per_mnt_flags = entry->flags & AMD_MOUNT_OPT_MASK; ++ ++ entry->flags = AMD_MOUNT_TYPE_NFS | per_mnt_flags; + tmp = strdup("nfs"); + if (tmp) + entry->type = tmp; diff --git a/SOURCES/autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch b/SOURCES/autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch new file mode 100644 index 0000000..8fd03e2 --- /dev/null +++ b/SOURCES/autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch @@ -0,0 +1,34 @@ +autofs-5.1.9 - fix lookup search type in umount_subtree_mounts() + +From: Ian Kent + +The lookup type used in umount_subtree_mounts() should be LKP_DISTINCT +because we're looking for existing cache entries. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -172,6 +172,7 @@ + - make iocl ops ->timeout() handle per-dentry expire. + - refactor amd mount options handling. + - add some unimplemented amd map options. ++- fix lookup search type in umount_subtree_mounts(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -544,7 +544,7 @@ static int umount_subtree_mounts(struct + if (ind_key) + ind_key++; + +- me = lookup_source_mapent(ap, ind_key, LKP_NORMAL); ++ me = lookup_source_mapent(ap, ind_key, LKP_DISTINCT); + } + + if (me) { diff --git a/SOURCES/autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch b/SOURCES/autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch new file mode 100644 index 0000000..296e0e7 --- /dev/null +++ b/SOURCES/autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch @@ -0,0 +1,53 @@ +autofs-5.1.9 - fix remount_active_mount() not remounting symlinks + +From: Ian Kent + +In remount_active_mount() there's a check if the path has an active +mount (ie. covered). This is meant to check if the mount is a direct +mount with an active mount to decide if the file descriptor needs to +be retained or not. + +But this check gets it worng if the path is an indirect mount that +contains symlinks and causes them to not be properly expired after +the re-mount. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + lib/mounts.c | 12 +++++------- + 2 files changed, 6 insertions(+), 7 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -173,6 +173,7 @@ + - refactor amd mount options handling. + - add some unimplemented amd map options. + - fix lookup search type in umount_subtree_mounts(). ++- fix remount_active_mount() not remounting symlinks. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -2819,16 +2819,14 @@ static int remount_active_mount(struct a + ops->close(ap->logopt, fd); + return REMOUNT_FAIL; + } +- if (!mounted) { ++ if (!mounted && type != t_indirect) { + /* + * If we're an indirect mount we pass back the fd. +- * But if were a direct or offset mount with no active +- * mount we don't retain an open file descriptor. ++ * But if we're a direct or offset mount with no active ++ * mount we don't retain the open file descriptor. + */ +- if (type != t_indirect) { +- ops->close(ap->logopt, fd); +- *ioctlfd = -1; +- } ++ ops->close(ap->logopt, fd); ++ *ioctlfd = -1; + } else { + /* + * What can I do if we can't remount the existing diff --git a/SOURCES/autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch b/SOURCES/autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch new file mode 100644 index 0000000..daf0e09 --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -182,6 +182,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. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/daemon/automount.c +@@ -505,16 +505,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/SOURCES/autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch b/SOURCES/autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch new file mode 100644 index 0000000..d561470 --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -187,6 +187,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. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/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.4.orig/daemon/direct.c ++++ autofs-5.1.4/daemon/direct.c +@@ -1000,10 +1000,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/SOURCES/autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch b/SOURCES/autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch new file mode 100644 index 0000000..cb3b8f7 --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -189,6 +189,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. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/direct.c ++++ autofs-5.1.4/daemon/direct.c +@@ -1365,12 +1365,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); +@@ -1389,7 +1431,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/SOURCES/autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch b/SOURCES/autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch new file mode 100644 index 0000000..35f690e --- /dev/null +++ b/SOURCES/autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch @@ -0,0 +1,51 @@ +autofs-5.1.9 - log when setting amd per-mount timeout + +From: Ian Kent + +Log action when setting amd per-mount expire timeout. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/parse_amd.c | 12 ++++++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -174,6 +174,7 @@ + - add some unimplemented amd map options. + - fix lookup search type in umount_subtree_mounts(). + - fix remount_active_mount() not remounting symlinks. ++- log when setting amd per-mount timeout. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/modules/parse_amd.c ++++ autofs-5.1.4/modules/parse_amd.c +@@ -1755,16 +1755,24 @@ static int amd_mount(struct autofs_point + "non-zero timeout set, possible conflicting options"); + + /* "nounmount" option, don't expire this mount. */ +- if (ops) ++ if (ops) { ++ info(ap->logopt, ++ "set amd per-mount expire timeout to 0 for %s", ++ name); + ops->timeout(ap->logopt, ap->ioctlfd, name, 0); ++ } + } else if (per_mnt_flags & AMD_MOUNT_OPT_UTIMEOUT) { + if (!entry->utimeout) + warn(ap->logopt, + "zero timeout set, possible conflicting options"); + + /* "utimeout" option, expire this mount according to a timeout. */ +- if (ops) ++ if (ops) { ++ info(ap->logopt, ++ "set amd per-dentry expire timeout to %d for %s", ++ entry->utimeout, name); + ops->timeout(ap->logopt, ap->ioctlfd, name, entry->utimeout); ++ } + } + } + done: diff --git a/SOURCES/autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch b/SOURCES/autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch new file mode 100644 index 0000000..75597a2 --- /dev/null +++ b/SOURCES/autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch @@ -0,0 +1,193 @@ +commit 6fdfbcd65fd845e968a68cbdf475a6dd0ee0ee66 +Author: Ian Kent +Date: Tue Jul 9 16:18:19 2024 +0800 + + autofs-5.1.9 - make ioctl ops ->timeout() handle per-dentry expire + + Update the ioctl ops ->timeout() function to handle setting of per-dentry + expire timeout if the kernel supports it. + + Signed-off-by: Ian Kent + +--- + CHANGELOG | 1 + + daemon/direct.c | 6 +++--- + daemon/indirect.c | 2 +- + daemon/state.c | 4 ++-- + include/dev-ioctl-lib.h | 2 +- + lib/dev-ioctl-lib.c | 42 +++++++++++++++++++++++++++++++----------- + lib/mounts.c | 4 ++-- + 7 files changed, 41 insertions(+), 20 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -169,6 +169,7 @@ + - handle sss special case getautomntbyname() error. + - fix amd cache options not copied. + - seperate amd mount and entry flags. ++- make iocl ops ->timeout() handle per-dentry expire. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/direct.c ++++ autofs-5.1.4/daemon/direct.c +@@ -328,7 +328,7 @@ int do_mount_autofs_direct(struct autofs + return 0; + } + +- ops->timeout(ap->logopt, ioctlfd, tout); ++ ops->timeout(ap->logopt, ioctlfd, NULL, tout); + + if (save_ioctlfd == -1) + ops->close(ap->logopt, ioctlfd); +@@ -423,7 +423,7 @@ int do_mount_autofs_direct(struct autofs + goto out_umount; + } + +- ops->timeout(ap->logopt, ioctlfd, timeout); ++ ops->timeout(ap->logopt, ioctlfd, NULL, timeout); + notify_mount_result(ap, me->key, timeout, str_direct); + cache_set_ino_index(me->mc, me); + ops->close(ap->logopt, ioctlfd); +@@ -777,7 +777,7 @@ int mount_autofs_offset(struct autofs_po + if (ioctlfd < 0) + goto out_umount; + +- ops->timeout(ap->logopt, ioctlfd, timeout); ++ ops->timeout(ap->logopt, ioctlfd, NULL, timeout); + cache_set_ino_index(me->mc, me); + notify_mount_result(ap, me->key, timeout, str_offset); + ops->close(ap->logopt, ioctlfd); +--- autofs-5.1.4.orig/daemon/indirect.c ++++ autofs-5.1.4/daemon/indirect.c +@@ -136,7 +136,7 @@ static int do_mount_autofs_indirect(stru + goto out_umount; + } + +- ops->timeout(ap->logopt, ap->ioctlfd, timeout); ++ ops->timeout(ap->logopt, ap->ioctlfd, NULL, timeout); + notify_mount_result(ap, ap->path, timeout, str_indirect); + + return 0; +--- autofs-5.1.4.orig/daemon/state.c ++++ autofs-5.1.4/daemon/state.c +@@ -394,7 +394,7 @@ static int do_readmap_mount(struct autof + cache_unlock(vmc); + /* Set timeout and calculate the expire run frequency */ + timeout = get_exp_timeout(ap, map); +- ops->timeout(ap->logopt, valid->ioctlfd, timeout); ++ ops->timeout(ap->logopt, valid->ioctlfd, NULL, timeout); + if (timeout) { + runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; + if (ap->exp_runfreq) +@@ -455,7 +455,7 @@ static void *do_readmap(void *arg) + struct ioctl_ops *ops = get_ioctl_ops(); + time_t timeout = get_exp_timeout(ap, ap->entry->maps); + ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; +- ops->timeout(ap->logopt, ap->ioctlfd, timeout); ++ ops->timeout(ap->logopt, ap->ioctlfd, NULL, timeout); + lookup_prune_cache(ap, now); + status = lookup_ghost(ap); + } else { +--- autofs-5.1.4.orig/include/dev-ioctl-lib.h ++++ autofs-5.1.4/include/dev-ioctl-lib.h +@@ -45,7 +45,7 @@ struct ioctl_ops { + int (*send_fail)(unsigned int, int, unsigned int, int); + int (*setpipefd)(unsigned int, int, int); + int (*catatonic)(unsigned int, int); +- int (*timeout)(unsigned int, int, time_t); ++ int (*timeout)(unsigned int, int, const char *, time_t); + int (*requester)(unsigned int, int, const char *, uid_t *, gid_t *); + int (*expire)(unsigned int, int, const char *, unsigned int); + int (*askumount)(unsigned int, int, unsigned int *); +--- autofs-5.1.4.orig/lib/dev-ioctl-lib.c ++++ autofs-5.1.4/lib/dev-ioctl-lib.c +@@ -55,7 +55,7 @@ static int dev_ioctl_send_ready(unsigned + static int dev_ioctl_send_fail(unsigned int, int, unsigned int, int); + static int dev_ioctl_setpipefd(unsigned int, int, int); + static int dev_ioctl_catatonic(unsigned int, int); +-static int dev_ioctl_timeout(unsigned int, int, time_t); ++static int dev_ioctl_timeout(unsigned int, int, const char *, time_t); + static int dev_ioctl_requester(unsigned int, int, const char *, uid_t *, gid_t *); + static int dev_ioctl_expire(unsigned int, int, const char *, unsigned int); + static int dev_ioctl_askumount(unsigned int, int, unsigned int *); +@@ -69,7 +69,7 @@ static int ioctl_close(unsigned int, int + static int ioctl_send_ready(unsigned int, int, unsigned int); + static int ioctl_send_fail(unsigned int, int, unsigned int, int); + static int ioctl_catatonic(unsigned int, int); +-static int ioctl_timeout(unsigned int, int, time_t); ++static int ioctl_timeout(unsigned int, int, const char *, time_t); + static int ioctl_expire(unsigned int, int, const char *, unsigned int); + static int ioctl_askumount(unsigned int, int, unsigned int *); + +@@ -579,21 +579,41 @@ static int ioctl_catatonic(unsigned int + } + + /* Set the autofs mount timeout */ +-static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout) ++static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, const char *mp, time_t timeout) + { +- struct autofs_dev_ioctl param; +- +- init_autofs_dev_ioctl(¶m); +- param.ioctlfd = ioctlfd; +- param.timeout.timeout = timeout; ++ if (!mp) { ++ struct autofs_dev_ioctl param; + +- if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, ¶m) == -1) +- return -1; ++ init_autofs_dev_ioctl(¶m); ++ param.ioctlfd = ioctlfd; ++ param.timeout.timeout = timeout; ++ if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, ¶m) == -1) ++ return -1; ++ } else { ++ unsigned int kver_major = get_kver_major(); ++ unsigned int kver_minor = get_kver_minor(); ++ struct autofs_dev_ioctl *param; ++ ++ if (kver_major < 5 || ++ (kver_major == 5 && kver_minor < 6)) { ++ error(logopt, "per-mount expire timeout not supported by kernel."); ++ return -1; ++ } + ++ param = alloc_dev_ioctl_path(ioctlfd, mp); ++ if (!param) ++ return -1; ++ param->timeout.timeout = timeout; ++ if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, param) == -1) { ++ free_dev_ioctl_path(param); ++ return -1; ++ } ++ free_dev_ioctl_path(param); ++ } + return 0; + } + +-static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout) ++static int ioctl_timeout(unsigned int logopt, int ioctlfd, const char *mp, time_t timeout) + { + time_t tout = timeout; + return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout); +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -2759,7 +2759,7 @@ 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, timeout); ++ ops->timeout(ap->logopt, fd, NULL, timeout); + ops->close(ap->logopt, fd); + return REMOUNT_READ_MAP; + } +@@ -2781,7 +2781,7 @@ static int remount_active_mount(struct a + ops->close(ap->logopt, fd); + return REMOUNT_OPEN_FAIL; + } +- ops->timeout(ap->logopt, fd, timeout); ++ ops->timeout(ap->logopt, fd, NULL, timeout); + if (fstat(fd, &st) == -1) { + error(ap->logopt, + "failed to stat %s mount %s", str_type, path); diff --git a/SOURCES/autofs-5.1.9-quiet-possibly-noisy-log-message.patch b/SOURCES/autofs-5.1.9-quiet-possibly-noisy-log-message.patch new file mode 100644 index 0000000..655adde --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -179,6 +179,7 @@ + - clear per-mount timeout if not set. + - fix incorrect flags update in update_with_defaults(). + - skip expire check for amd nounmount mounts. ++- quiet possibly noisy log message. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -2890,7 +2890,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/SOURCES/autofs-5.1.9-refactor-amd-mount-options-handling.patch b/SOURCES/autofs-5.1.9-refactor-amd-mount-options-handling.patch new file mode 100644 index 0000000..760038d --- /dev/null +++ b/SOURCES/autofs-5.1.9-refactor-amd-mount-options-handling.patch @@ -0,0 +1,121 @@ +commit b48aab92dd3f47411a8ccd67ff4370cbfee64581 +Author: Ian Kent +Date: Thu Jul 11 13:35:04 2024 +0800 + + autofs-5.1.9 - refactor amd mount options handling + + Refactor handling of entry options opts, addopts, remopts. + + Signed-off-by: Ian Kent + +--- + CHANGELOG | 1 + modules/amd_parse.y | 66 ++++++++++++++++++++++++++++++---------------------- + 2 files changed, 40 insertions(+), 27 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -170,6 +170,7 @@ + - fix amd cache options not copied. + - seperate amd mount and entry flags. + - make iocl ops ->timeout() handle per-dentry expire. ++- refactor amd mount options handling. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/modules/amd_parse.y ++++ autofs-5.1.4/modules/amd_parse.y +@@ -60,6 +60,7 @@ static int match_map_option_fs_type(char + static int match_map_option_map_type(char *map_option, char *type); + static int match_map_option_cache_option(char *type); + static int match_mnt_option_options(char *mnt_option, char *options); ++static int match_mnt_option(char *option, char *options); + + static struct amd_entry entry; + static struct list_head *entries; +@@ -437,40 +438,18 @@ option_assignment: MAP_OPTION OPTION_ASS + + options: OPTION + { +- if (!strcmp($1, "fullybrowsable") || +- !strcmp($1, "nounmount")) { +- sprintf(msg_buf, "option %s is not currently " +- "implemented, ignored", $1); +- amd_info(msg_buf); +- } else if (!strncmp($1, "ping=", 5) || +- !strncmp($1, "retry=", 6) || +- !strcmp($1, "public") || +- !strcmp($1, "softlookup") || +- !strcmp($1, "xlatecookie")) { +- sprintf(msg_buf, "option %s is not used by " +- "autofs, ignored", $1); +- amd_info(msg_buf); +- } else if (!strncmp($1, "utimeout=", 9)) { +- if (entry.flags & AMD_MOUNT_TYPE_AUTO) { +- char *opt = $1; +- prepend_opt(opts, ++opt); +- } else { +- sprintf(msg_buf, "umount timeout can't be " +- "used for other than type " +- "\"auto\" with autofs, " +- "ignored"); +- amd_info(msg_buf); +- } +- } else ++ if (match_mnt_option($1, opts)) + prepend_opt(opts, $1); + } + | OPTION COMMA options + { +- prepend_opt(opts, $1); ++ if (match_mnt_option($1, opts)) ++ prepend_opt(opts, $1); + } + | OPTION COMMA + { +- prepend_opt(opts, $1); ++ if (match_mnt_option($1, opts)) ++ prepend_opt(opts, $1); + } + ; + +@@ -664,6 +643,39 @@ static int match_mnt_option_options(char + return 1; + } + ++static int match_mnt_option(char *option, char *options) ++{ ++ int ret = 0; ++ ++ if (!strcmp(option, "fullybrowsable") || ++ !strcmp(option, "nounmount")) { ++ sprintf(msg_buf, "option %s is not currently " ++ "implemented, ignored", option); ++ amd_info(msg_buf); ++ } else if (!strncmp(option, "ping=", 5) || ++ !strncmp(option, "retry=", 6) || ++ !strcmp(option, "public") || ++ !strcmp(option, "softlookup") || ++ !strcmp(option, "xlatecookie")) { ++ sprintf(msg_buf, "option %s is not used by " ++ "autofs, ignored", option); ++ amd_info(msg_buf); ++ } else if (!strncmp(option, "utimeout=", 9)) { ++ if (entry.flags & AMD_MOUNT_TYPE_AUTO) ++ prepend_opt(options, ++option); ++ else { ++ sprintf(msg_buf, "umount timeout can't be " ++ "used for other than type " ++ "\"auto\" with autofs, " ++ "ignored"); ++ amd_info(msg_buf); ++ } ++ } else ++ ret = 1; ++ ++ return ret; ++} ++ + static void prepend_opt(char *dest, char *opt) + { + char new[MAX_OPTS_LEN]; diff --git a/SOURCES/autofs-5.1.9-refactor-do_umount_autofs_direct.patch b/SOURCES/autofs-5.1.9-refactor-do_umount_autofs_direct.patch new file mode 100644 index 0000000..309bde3 --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -186,6 +186,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(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/direct.c ++++ autofs-5.1.4/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/SOURCES/autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch b/SOURCES/autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch new file mode 100644 index 0000000..13e72ad --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -184,6 +184,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(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/automount.c ++++ autofs-5.1.4/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/SOURCES/autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch b/SOURCES/autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch new file mode 100644 index 0000000..ea39ade --- /dev/null +++ b/SOURCES/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.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -183,6 +183,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(). + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/direct.c ++++ autofs-5.1.4/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/SOURCES/autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch b/SOURCES/autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch new file mode 100644 index 0000000..45d7d9c --- /dev/null +++ b/SOURCES/autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch @@ -0,0 +1,133 @@ +commit a2002247e16ef60efe049e04119a9c92694cbfe1 +Author: Ian Kent +Date: Tue Jul 9 14:59:40 2024 +0800 + + autofs-5.1.9 - seperate amd mount and entry flags + + We are running out of flags for amd mounts, seperate the mount flags + from the defaults and entry flags and add a new amd entry flags field. + + Signed-off-by: Ian Kent + +--- + CHANGELOG | 1 + + include/parse_amd.h | 11 ++++++----- + modules/amd_parse.y | 7 ++++--- + modules/parse_amd.c | 10 +++++----- + 4 files changed, 16 insertions(+), 13 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -168,6 +168,7 @@ + - fix missing unlock in sasl_do_kinit_ext_cc(). + - handle sss special case getautomntbyname() error. + - fix amd cache options not copied. ++- seperate amd mount and entry flags. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/include/parse_amd.h ++++ autofs-5.1.4/include/parse_amd.h +@@ -33,12 +33,12 @@ + #define AMD_MOUNT_TYPE_PROGRAM 0x00004000 + #define AMD_MOUNT_TYPE_MASK 0x0000ffff + +-#define AMD_ENTRY_CUT 0x00010000 +-#define AMD_ENTRY_MASK 0x00ff0000 ++#define AMD_DEFAULTS_MERGE 0x0001 ++#define AMD_DEFAULTS_RESET 0x0002 ++#define AMD_DEFAULTS_MASK 0x00ff + +-#define AMD_DEFAULTS_MERGE 0x01000000 +-#define AMD_DEFAULTS_RESET 0x02000000 +-#define AMD_DEFAULTS_MASK 0xff000000 ++#define AMD_ENTRY_CUT 0x0100 ++#define AMD_ENTRY_MASK 0xff00 + + #define AMD_CACHE_OPTION_NONE 0x0000 + #define AMD_CACHE_OPTION_INC 0x0001 +@@ -50,6 +50,7 @@ struct amd_entry { + char *path; + unsigned long flags; + unsigned int cache_opts; ++ unsigned int entry_flags; + char *type; + char *map_type; + char *pref; +--- autofs-5.1.4.orig/modules/amd_parse.y ++++ autofs-5.1.4/modules/amd_parse.y +@@ -155,7 +155,7 @@ location_selection_list: location + } + | location_selection_list SPACE CUT SPACE location + { +- entry.flags |= AMD_ENTRY_CUT; ++ entry.entry_flags |= AMD_ENTRY_CUT; + if (!add_location()) { + amd_msg("failed to allocate new location"); + YYABORT; +@@ -168,11 +168,11 @@ location: location_entry + } + | HYPHEN location_entry + { +- entry.flags |= AMD_DEFAULTS_MERGE; ++ entry.entry_flags |= AMD_DEFAULTS_MERGE; + } + | HYPHEN + { +- entry.flags |= AMD_DEFAULTS_RESET; ++ entry.entry_flags |= AMD_DEFAULTS_RESET; + } + ; + +@@ -889,6 +889,7 @@ static int add_location(void) + } + new->flags = entry.flags; + new->cache_opts = entry.cache_opts; ++ new->entry_flags = entry.entry_flags; + new->type = entry.type; + new->map_type = entry.map_type; + new->pref = entry.pref; +--- autofs-5.1.4.orig/modules/parse_amd.c ++++ autofs-5.1.4/modules/parse_amd.c +@@ -2022,13 +2022,13 @@ static struct amd_entry *select_default_ + + p = p->next; + +- if (this->flags & AMD_DEFAULTS_MERGE) { ++ if (this->entry_flags & AMD_DEFAULTS_MERGE) { + if (entry_default) + free_amd_entry(entry_default); + list_del_init(&this->list); + entry_default = this; + continue; +- } else if (this->flags & AMD_DEFAULTS_RESET) { ++ } else if (this->entry_flags & AMD_DEFAULTS_RESET) { + struct amd_entry *new; + new = dup_defaults_entry(defaults_entry); + if (new) { +@@ -2259,14 +2259,14 @@ int parse_mount(struct autofs_point *ap, + struct amd_entry *this = list_entry(p, struct amd_entry, list); + p = p->next; + +- if (this->flags & AMD_DEFAULTS_MERGE) { ++ if (this->entry_flags & AMD_DEFAULTS_MERGE) { + free_amd_entry(cur_defaults); + list_del_init(&this->list); + cur_defaults = this; + update_with_defaults(defaults_entry, cur_defaults, sv); + debug(ap->logopt, "merged /defaults entry with defaults"); + continue; +- } else if (this->flags & AMD_DEFAULTS_RESET) { ++ } else if (this->entry_flags & AMD_DEFAULTS_RESET) { + struct amd_entry *nd, *new; + struct substvar *nsv = NULL; + +@@ -2291,7 +2291,7 @@ int parse_mount(struct autofs_point *ap, + debug(ap->logopt, "expand defaults entry"); + sv = expand_entry(ap, cur_defaults, flags, sv); + +- if (this->flags & AMD_ENTRY_CUT && at_least_one) { ++ if (this->entry_flags & AMD_ENTRY_CUT && at_least_one) { + info(ap->logopt, MODPREFIX + "at least one entry tried before cut selector, " + "not continuing"); diff --git a/SOURCES/autofs-5.1.9-skip-expire-check-for-amd-nounmount-mounts.patch b/SOURCES/autofs-5.1.9-skip-expire-check-for-amd-nounmount-mounts.patch new file mode 100644 index 0000000..9c78257 --- /dev/null +++ b/SOURCES/autofs-5.1.9-skip-expire-check-for-amd-nounmount-mounts.patch @@ -0,0 +1,36 @@ +autofs-5.1.9 - skip expire check for amd nounmount mounts + +From: Ian Kent + +There's no need to check amd mounts with the "nounmount" option set. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/indirect.c | 5 +++++ + 2 files changed, 6 insertions(+) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -178,6 +178,7 @@ + - update per-mount expire timeout on readmap. + - clear per-mount timeout if not set. + - fix incorrect flags update in update_with_defaults(). ++- skip expire check for amd nounmount mounts. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/indirect.c ++++ autofs-5.1.4/daemon/indirect.c +@@ -377,6 +377,11 @@ void *expire_proc_indirect(void *arg) + char *ind_key; + int ret; + ++ /* No need to check "nounmount" amd mounts */ ++ if (mnt->flags & MNTS_AMD_MOUNT && ++ mnt->amd_flags & AMD_MOUNT_OPT_NOUNMOUNT) ++ continue; ++ + if (mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET)) { + /* + * If we have submounts check if this path lives below diff --git a/SOURCES/autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch b/SOURCES/autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch new file mode 100644 index 0000000..fca7abf --- /dev/null +++ b/SOURCES/autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch @@ -0,0 +1,225 @@ +autofs-5.1.9 - update per-mount expire timeout on readmap + +From: Ian Kent + +Ensure read map requests are propagated to child submounts and update +the amd per-mount timeout. + +Also update the logging text to remove the use of the word dentry as +it might not make sense to users. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/master.c | 2 + daemon/state.c | 1 + include/master.h | 1 + include/mounts.h | 1 + lib/mounts.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + modules/parse_amd.c | 6 +- + 7 files changed, 130 insertions(+), 4 deletions(-) + +--- autofs-5.1.4.orig/CHANGELOG ++++ autofs-5.1.4/CHANGELOG +@@ -175,6 +175,7 @@ + - fix lookup search type in umount_subtree_mounts(). + - fix remount_active_mount() not remounting symlinks. + - log when setting amd per-mount timeout. ++- update per-mount expire timeout on readmap. + + xx/xx/2018 autofs-5.1.5 + - fix flag file permission. +--- autofs-5.1.4.orig/daemon/master.c ++++ autofs-5.1.4/daemon/master.c +@@ -1378,7 +1378,7 @@ static int master_do_mount(struct master + return 1; + } + +-static void check_update_map_sources(struct master_mapent *entry, int readall) ++void check_update_map_sources(struct master_mapent *entry, int readall) + { + struct map_source *source, *last; + struct autofs_point *ap; +--- autofs-5.1.4.orig/daemon/state.c ++++ autofs-5.1.4/daemon/state.c +@@ -456,6 +456,7 @@ static void *do_readmap(void *arg) + time_t timeout = get_exp_timeout(ap, ap->entry->maps); + ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; + ops->timeout(ap->logopt, ap->ioctlfd, NULL, timeout); ++ update_mounted_mounts_timeout(ap, ap->path); + lookup_prune_cache(ap, now); + status = lookup_ghost(ap); + } else { +--- autofs-5.1.4.orig/include/master.h ++++ autofs-5.1.4/include/master.h +@@ -115,6 +115,7 @@ struct master *master_new(const char *, + int master_read_master(struct master *, time_t); + int master_notify_submount(struct autofs_point *, const char *path, enum states); + void master_notify_state_change(struct master *, int); ++void check_update_map_sources(struct master_mapent *, int); + int master_mount_mounts(struct master *, time_t); + int dump_map(struct master *, const char *, const char *); + int master_show_mounts(struct master *); +--- autofs-5.1.4.orig/include/mounts.h ++++ autofs-5.1.4/include/mounts.h +@@ -197,6 +197,7 @@ const char *mount_type_str(unsigned int) + void set_exp_timeout(struct autofs_point *ap, struct map_source *source, time_t timeout); + time_t get_exp_timeout(struct autofs_point *ap, struct map_source *source); + void notify_mount_result(struct autofs_point *, const char *, time_t, const char *); ++void update_mounted_mounts_timeout(struct autofs_point *, const char *); + int try_remount(struct autofs_point *, struct mapent *, unsigned int); + void set_indirect_mount_tree_catatonic(struct autofs_point *); + void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *); +--- autofs-5.1.4.orig/lib/mounts.c ++++ autofs-5.1.4/lib/mounts.c +@@ -2622,6 +2622,128 @@ void notify_mount_result(struct autofs_p + return; + } + ++void update_mounted_mounts_timeout(struct autofs_point *ap, const char *path) ++{ ++ struct ioctl_ops *ops = get_ioctl_ops(); ++ struct dirent **de; ++ char buf[PATH_MAX + 1]; ++ int n, size; ++ ++ n = scandir(path, &de, 0, alphasort); ++ if (n < 0) ++ return; ++ ++ size = sizeof(buf); ++ ++ while (n--) { ++ unsigned int mounted = 0; ++ struct mnt_list *mnt; ++ int ret; ++ ++ if (strcmp(de[n]->d_name, ".") == 0 || ++ strcmp(de[n]->d_name, "..") == 0) { ++ free(de[n]); ++ continue; ++ } ++ ++ ret = cat_path(buf, size, path, de[n]->d_name); ++ if (!ret) { ++ do { ++ free(de[n]); ++ } while (n--); ++ free(de); ++ return; ++ } ++ ++ ops->ismountpoint(ap->logopt, -1, buf, &mounted); ++ if (!mounted) { ++ struct dirent **de2; ++ int i, j; ++ ++ i = j = scandir(buf, &de2, 0, alphasort); ++ if (i < 0) { ++ free(de[n]); ++ continue; ++ } ++ while (i--) ++ free(de2[i]); ++ free(de2); ++ if (j <= 2) { ++ free(de[n]); ++ continue; ++ } ++ } ++ ++ /* For submounts we need to propogate the read map ++ * request. ++ */ ++ mnt = mnts_find_submount(buf); ++ if (mnt) { ++ check_update_map_sources(mnt->ap->entry, 1); ++ mnts_put_mount(mnt); ++ } ++ ++ mnt = mnts_find_amdmount(buf); ++ if (!mnt) { ++ free(de[n]); ++ continue; ++ } ++ ++ /* For amd type auto mounts the timeout is the per-mount ++ * timeout. ++ */ ++ if (mnt->amd_flags & AMD_MOUNT_TYPE_AUTO) ++ goto next; ++ ++ /* No per-mount timeout set? */ ++ if (!(mnt->amd_flags & AMD_MOUNT_OPT_MASK)) ++ goto next; ++ ++ /* The default in autofs is to always expire mounts according to ++ * a timeout set in the autofs mount super block information ++ * structure. But amd allows for differing expire timeouts on a ++ * per-mount basis. It also has (context sensitive) options "unmount" ++ * to say expire this mount and "nounmount" to say don't expire this ++ * mount. In amd mounts these options are set by default according ++ * to whether a mount should expire or not, for example a cd mount ++ * is set "nounmount". Setting defaults like this is not used in the ++ * autofs amd implementation because there's only one, little used, ++ * removable file system available. ++ * ++ * But the "nounmount" and "utimeout" options can be useful. ++ */ ++ if (mnt->amd_flags & AMD_MOUNT_OPT_NOUNMOUNT) { ++ if (mnt->amd_utimeout) ++ warn(ap->logopt, ++ "non-zero timeout set, possible conflicting options"); ++ ++ /* "nounmount" option, don't expire this mount. */ ++ if (ops) { ++ info(ap->logopt, ++ "set amd per-mount expire timeout to 0 for %s", ++ buf); ++ ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, 0); ++ } ++ } else if (mnt->amd_flags & AMD_MOUNT_OPT_UTIMEOUT) { ++ if (!mnt->amd_utimeout) ++ warn(ap->logopt, ++ "zero timeout set, possible conflicting options"); ++ ++ /* "utimeout" option, expire this mount according to a timeout. */ ++ if (ops) { ++ info(ap->logopt, ++ "set amd per-mount expire timeout to %d for %s", ++ mnt->amd_utimeout, buf); ++ ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, mnt->amd_utimeout); ++ } ++ } ++next: ++ mnts_put_mount(mnt); ++ free(de[n]); ++ } ++ free(de); ++} ++ + static int do_remount_direct(struct autofs_point *ap, + const unsigned int type, int fd, const char *path) + { +--- autofs-5.1.4.orig/modules/parse_amd.c ++++ autofs-5.1.4/modules/parse_amd.c +@@ -1758,7 +1758,7 @@ static int amd_mount(struct autofs_point + if (ops) { + info(ap->logopt, + "set amd per-mount expire timeout to 0 for %s", +- name); ++ entry->path); + ops->timeout(ap->logopt, ap->ioctlfd, name, 0); + } + } else if (per_mnt_flags & AMD_MOUNT_OPT_UTIMEOUT) { +@@ -1769,8 +1769,8 @@ static int amd_mount(struct autofs_point + /* "utimeout" option, expire this mount according to a timeout. */ + if (ops) { + info(ap->logopt, +- "set amd per-dentry expire timeout to %d for %s", +- entry->utimeout, name); ++ "set amd per-mount expire timeout to %d for %s", ++ entry->utimeout, entry->path); + ops->timeout(ap->logopt, ap->ioctlfd, name, entry->utimeout); + } + } diff --git a/SPECS/autofs.spec b/SPECS/autofs.spec index 2e2d114..c2fbb02 100644 --- a/SPECS/autofs.spec +++ b/SPECS/autofs.spec @@ -8,7 +8,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.1.4 -Release: 114%{?dist}.6 +Release: 114%{?dist}.8 Epoch: 1 License: GPLv2+ Group: System Environment/Daemons @@ -356,6 +356,33 @@ Patch343: autofs-5.1.8-fix-missing-unlock-in-sasl_do_kinit_ext_cc.patch # JIRA: RHEL-127179 Patch344: autofs-5.1.9-handle-sss-special-case-getautomntbyname-error.patch +# JIRA: RHEL-46409 +Patch350: autofs-5.1.9-fix-amd-cache-options-not-copied.patch +Patch351: autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch +Patch352: autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch +Patch353: autofs-5.1.9-refactor-amd-mount-options-handling.patch +Patch354: autofs-5.1.9-add-some-unimplemented-amd-map-options.patch +Patch355: autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch +Patch356: autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch +Patch357: autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch +Patch358: autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch +Patch359: autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch +Patch360: autofs-5.1.9-fix-incorrect-flags-update-in-update_with_defaults.patch +Patch361: autofs-5.1.9-skip-expire-check-for-amd-nounmount-mounts.patch + +# JIRA: RHEL-RHEL-97546 +Patch370: autofs-5.1.9-quiet-possibly-noisy-log-message.patch +Patch371: autofs-5.1.9-fix-devid-update-on-reload.patch +Patch372: autofs-5.1.9-fix-cache-writelock-must-be-taken-in-update_map_cache.patch +Patch373: autofs-5.1.9-fix-skip-valid-map-entries-on-expire-cleanup.patch +Patch374: autofs-5.1.9-remove-unnecessary-call-to-set_direct_mount_tree_catatonic.patch +Patch375: autofs-5.1.9-remove-unnecessary-assignment-in-umount_multi.patch +Patch376: autofs-5.1.9-fix-direct-mount-trigger-umount-failure-case.patch +Patch377: autofs-5.1.9-refactor-do_umount_autofs_direct.patch +Patch378: autofs-5.1.9-fix-stale-direct-mount-trigger-not-umounted-on-expire.patch +Patch379: autofs-5.1.9-add-function-table_lookup_ino.patch +Patch380: autofs-5.1.9-improve-handling-of-missing-map-entry-for-mount-request.patch + %if %{with_systemd} BuildRequires: systemd-units BuildRequires: systemd-devel @@ -749,6 +776,31 @@ echo %{version}-%{release} > .version %patch -P 344 -p1 +%patch -P 350 -p1 +%patch -P 351 -p1 +%patch -P 352 -p1 +%patch -P 353 -p1 +%patch -P 354 -p1 +%patch -P 355 -p1 +%patch -P 356 -p1 +%patch -P 357 -p1 +%patch -P 358 -p1 +%patch -P 359 -p1 +%patch -P 360 -p1 +%patch -P 361 -p1 + +%patch -P 370 -p1 +%patch -P 371 -p1 +%patch -P 372 -p1 +%patch -P 373 -p1 +%patch -P 374 -p1 +%patch -P 375 -p1 +%patch -P 376 -p1 +%patch -P 377 -p1 +%patch -P 378 -p1 +%patch -P 379 -p1 +%patch -P 380 -p1 + %build LDFLAGS=-Wl,-z,now %configure --disable-mount-locking --enable-ignore-busy --with-libtirpc --without-hesiod %{?systemd_configure_arg:} @@ -843,6 +895,37 @@ fi %dir /etc/auto.master.d %changelog +* Fri Feb 27 2026 Ian Kent - 5.1.4-114.el8_10.8 +- RHEL-97546 - hung tasks after autofs reload + - 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-97546 + +* Fri Jan 30 2026 Ian Kent - 5.1.4-114.el8_10.7 +- RHEL-46409 - RFE: autofs: add handling for AMD 'nounmount' option + - fix amd cache options not copied. + - seperate amd mount and entry flags. + - make iocl ops ->timeout() handle per-dentry expire. + - refactor amd mount options handling. + - add some unimplemented amd map options. + - fix lookup search type in umount_subtree_mounts(). + - fix remount_active_mount() not remounting symlinks. + - log when setting amd per-mount timeout. + - update per-mount expire timeout on readmap. + - clear per-mount timeout if not set. + - fix incorrect flags update in update_with_defaults(). + - skip expire check for amd nounmount mounts. +- Resolves: RHEL-46409 + * Tue Nov 25 2025 Ian Kent - 5.1.4-114.el8_10.6 - RHEL-127179 - sssd autofs fails to get correct EHOSTDOWN if requested incorrect mount after upgrade to sssd-2.9.1-4.el8_9.5.x86_64