From b58878d9ddd54a00a6acf778b5e8ed7bde783777 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Tue, 17 Dec 2024 11:04:01 +0800 Subject: [PATCH] Add Add fixes for Jiras RHEL-69485 RHEL-71359 and RHEL-57466 This MR adds fixes for several Jiras. - RHEL-57466 - autofs crashes on startup after IDM client configuration We have had several different reports caused by this bug which leads to a SEGV with very little information about the cuase. - Resolves: RHEL-57466 - RHEL-69485 - Sporadic mount failures with amd program maps on RHEL8. This bug causes AMD-style program map mounts to sporadically not work. - Resolves: RHEL-69485 - RHEL-71359 - RFE: autofs: add handling for AMD 'nounmount' option This Jira adds support for a map option that was deferred in the original implementtion. One of our customers needs this so it has been implemented. - Resolves: RHEL-71359 Signed-off-by: Ian Kent --- ...7-clear-per-mount-timeout-if-not-set.patch | 72 ++++++ ...ags-argument-to-amd-do_program_mount.patch | 60 +++++ ...d-some-unimplemented-amd-map-options.patch | 221 ++++++++++++++++ ...5.1.9-dont-free-ext-mount-if-mounted.patch | 53 ++++ ...1.9-fix-amd-cache-options-not-copied.patch | 35 +++ ...ix-amd-external-mount-error-handling.patch | 55 ++++ ...ix-amd-external-mount-mount-handling.patch | 71 +++++ ...search-type-in-umount_subtree_mounts.patch | 34 +++ ...active_mount-not-remounting-symlinks.patch | 53 ++++ autofs-5.1.9-fix-submount-shutdown-race.patch | 89 +++++++ ...g-when-setting-amd-per-mount-timeout.patch | 51 ++++ ...ops-timeout-handle-per-dentry-expire.patch | 192 ++++++++++++++ ...factor-amd-function-do_program_mount.patch | 138 ++++++++++ ...or-amd-function-umount_amd_ext_mount.patch | 242 ++++++++++++++++++ ...-refactor-amd-mount-options-handling.patch | 121 +++++++++ ...9-seperate-amd-mount-and-entry-flags.patch | 133 ++++++++++ ...-per-mount-expire-timeout-on-readmap.patch | 225 ++++++++++++++++ autofs.spec | 73 +++++- 18 files changed, 1917 insertions(+), 1 deletion(-) create mode 100644 autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch create mode 100644 autofs-5.1.9-add-flags-argument-to-amd-do_program_mount.patch create mode 100644 autofs-5.1.9-add-some-unimplemented-amd-map-options.patch create mode 100644 autofs-5.1.9-dont-free-ext-mount-if-mounted.patch create mode 100644 autofs-5.1.9-fix-amd-cache-options-not-copied.patch create mode 100644 autofs-5.1.9-fix-amd-external-mount-error-handling.patch create mode 100644 autofs-5.1.9-fix-amd-external-mount-mount-handling.patch create mode 100644 autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch create mode 100644 autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch create mode 100644 autofs-5.1.9-fix-submount-shutdown-race.patch create mode 100644 autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch create mode 100644 autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch create mode 100644 autofs-5.1.9-refactor-amd-function-do_program_mount.patch create mode 100644 autofs-5.1.9-refactor-amd-function-umount_amd_ext_mount.patch create mode 100644 autofs-5.1.9-refactor-amd-mount-options-handling.patch create mode 100644 autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch create mode 100644 autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch diff --git a/autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch b/autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch new file mode 100644 index 0000000..1fe0d8a --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -177,6 +177,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. + + 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 +@@ -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.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/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/autofs-5.1.9-add-flags-argument-to-amd-do_program_mount.patch b/autofs-5.1.9-add-flags-argument-to-amd-do_program_mount.patch new file mode 100644 index 0000000..d638cbd --- /dev/null +++ b/autofs-5.1.9-add-flags-argument-to-amd-do_program_mount.patch @@ -0,0 +1,60 @@ +autofs-5.1.9 - add flags argument to amd do_program_mount() + +From: Ian Kent + +Most of the amd mount functions take a flags argument that allows them +to alter their function based on configuration. + +For example the amd option autofs_use_lofs will use bind mounts instead +of symlinks in some cases which might be preferred. + +The program mount function was not being passed this parameter but the +design of all the amd mount functions is quite similar and adding the +flag works as expected.. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/parse_amd.c | 7 ++++--- + 2 files changed, 5 insertions(+), 3 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -166,6 +166,7 @@ + - don't free ext mount if mounted. + - refactor amd function do_program_mount(). + - refactor umount_amd_ext_mount(). ++- add flags argument to amd do_program_mount(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -1405,7 +1405,8 @@ out: + } + + static int do_program_mount(struct autofs_point *ap, +- struct amd_entry *entry, const char *name) ++ struct amd_entry *entry, const char *name, ++ unsigned int flags) + { + int rv = 1; + +@@ -1479,7 +1480,7 @@ static int do_program_mount(struct autof + goto out; + } + done: +- rv = do_link_mount(ap, name, entry, 0); ++ rv = do_link_mount(ap, name, entry, flags); + if (rv) { + if (!umount_amd_ext_mount(ap, entry->fs, 1)) { + debug(ap->logopt, MODPREFIX +@@ -1708,7 +1709,7 @@ static int amd_mount(struct autofs_point + case AMD_MOUNT_TYPE_PROGRAM: + if (!validate_program_options(ap->logopt, entry)) + return 1; +- ret = do_program_mount(ap, entry, name); ++ ret = do_program_mount(ap, entry, name, flags); + break; + + default: diff --git a/autofs-5.1.9-add-some-unimplemented-amd-map-options.patch b/autofs-5.1.9-add-some-unimplemented-amd-map-options.patch new file mode 100644 index 0000000..f799ab8 --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/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. + + 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 +@@ -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.7.orig/include/parse_amd.h ++++ autofs-5.1.7/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.7.orig/lib/mounts.c ++++ autofs-5.1.7/lib/mounts.c +@@ -1210,6 +1210,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)) +@@ -1254,6 +1256,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.7.orig/modules/amd_parse.y ++++ autofs-5.1.7/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.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/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/autofs-5.1.9-dont-free-ext-mount-if-mounted.patch b/autofs-5.1.9-dont-free-ext-mount-if-mounted.patch new file mode 100644 index 0000000..0614a5c --- /dev/null +++ b/autofs-5.1.9-dont-free-ext-mount-if-mounted.patch @@ -0,0 +1,53 @@ +autofs-5.1.9 - don't free ext mount if mounted + +From: Ian Kent + +If an external mount is in use when a umount is attempted don't free +it just let the reference count go to zero. + +This will leave the mount in place and it won't get umounted. But if +another automount uses it it's reference count will become no zero +allowing for it to be umounted as normal if it isn't in use during +automount expire. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + lib/mounts.c | 8 ++++---- + 2 files changed, 5 insertions(+), 4 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -163,6 +163,7 @@ + - fix deadlock in remount. + - fix amd external mount error handling. + - fix amd external mount mount handling. ++- don't free ext mount if mounted. + + 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 +@@ -906,10 +906,10 @@ int ext_mount_remove(const char *path) + if (!em) + goto done; + +- em->ref--; + if (em->ref) +- goto done; +- else { ++ em->ref--; ++ ++ if (!em->ref && !is_mounted(path, MNTS_REAL)) { + hlist_del_init(&em->mount); + free(em->mp); + if (em->umount) +@@ -931,7 +931,7 @@ int ext_mount_inuse(const char *path) + em = ext_mount_lookup(path); + if (!em) + goto done; +- ret = em->ref; ++ ret = 1; + done: + ext_mount_hash_mutex_unlock(); + return ret; diff --git a/autofs-5.1.9-fix-amd-cache-options-not-copied.patch b/autofs-5.1.9-fix-amd-cache-options-not-copied.patch new file mode 100644 index 0000000..2405ea5 --- /dev/null +++ b/autofs-5.1.9-fix-amd-cache-options-not-copied.patch @@ -0,0 +1,35 @@ +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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -167,6 +167,7 @@ + - refactor amd function do_program_mount(). + - refactor umount_amd_ext_mount(). + - add flags argument to amd do_program_mount(). ++- fix amd cache options not copied. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/amd_parse.y ++++ autofs-5.1.7/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/autofs-5.1.9-fix-amd-external-mount-error-handling.patch b/autofs-5.1.9-fix-amd-external-mount-error-handling.patch new file mode 100644 index 0000000..f08d9f2 --- /dev/null +++ b/autofs-5.1.9-fix-amd-external-mount-error-handling.patch @@ -0,0 +1,55 @@ +autofs-5.1.9 - fix amd external mount error handling + +From: Ian Kent + +An amd program mount might have defined its own umount program to be used +for external mounts. + +In mount failure cases where the mount needs to be umounted be sure to +use the custom umount if there is one. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/parse_amd.c | 6 +++--- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -161,6 +161,7 @@ + - fix multi-mount check. + - fix get parent multi-mount check in try_remount(). + - fix deadlock in remount. ++- fix amd external mount error handling. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -1183,7 +1183,7 @@ static int do_generic_mount(struct autof + } + /* If we have an external mount add it to the list */ + if (umount && !ext_mount_add(entry->fs, entry->umount)) { +- umount_ent(ap, entry->fs); ++ umount_amd_ext_mount(ap, entry->fs); + error(ap->logopt, MODPREFIX + "error: could not add external mount %s", + entry->fs); +@@ -1233,7 +1233,7 @@ static int do_nfs_mount(struct autofs_po + } + /* We might be using an external mount */ + if (umount && !ext_mount_add(entry->fs, entry->umount)) { +- umount_ent(ap, entry->fs); ++ umount_amd_ext_mount(ap, entry->fs); + error(ap->logopt, MODPREFIX + "error: could not add external mount %s", entry->fs); + ret = 1; +@@ -1462,7 +1462,7 @@ static int do_program_mount(struct autof + "%s: mounted %s", entry->type, entry->fs); + goto do_free; + } +- umount_ent(ap, entry->fs); ++ umount_amd_ext_mount(ap, entry->fs); + } + + if (!ext_mount_inuse(entry->fs)) diff --git a/autofs-5.1.9-fix-amd-external-mount-mount-handling.patch b/autofs-5.1.9-fix-amd-external-mount-mount-handling.patch new file mode 100644 index 0000000..c3397cd --- /dev/null +++ b/autofs-5.1.9-fix-amd-external-mount-mount-handling.patch @@ -0,0 +1,71 @@ +autofs-5.1.9 - fix amd external mount mount handling + +From: Ian Kent + +Amd external mounts exist outside of the autofs file system and need +extra effort to try and keep track of them so they are mounted and +umounted when they should be. + +Cleanup cases where an external mount is already mounted. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/parse_amd.c | 21 ++++++++++++--------- + 2 files changed, 13 insertions(+), 9 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -162,6 +162,7 @@ + - fix get parent multi-mount check in try_remount(). + - fix deadlock in remount. + - fix amd external mount error handling. ++- fix amd external mount mount handling. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -1182,8 +1182,9 @@ static int do_generic_mount(struct autof + umount = 1; + } + /* If we have an external mount add it to the list */ +- if (umount && !ext_mount_add(entry->fs, entry->umount)) { +- umount_amd_ext_mount(ap, entry->fs); ++ if (!ext_mount_add(entry->fs, entry->umount)) { ++ if (umount) ++ umount_amd_ext_mount(ap, entry->fs); + error(ap->logopt, MODPREFIX + "error: could not add external mount %s", + entry->fs); +@@ -1232,8 +1233,9 @@ static int do_nfs_mount(struct autofs_po + umount = 1; + } + /* We might be using an external mount */ +- if (umount && !ext_mount_add(entry->fs, entry->umount)) { +- umount_amd_ext_mount(ap, entry->fs); ++ if (!ext_mount_add(entry->fs, entry->umount)) { ++ if (umount) ++ umount_amd_ext_mount(ap, entry->fs); + error(ap->logopt, MODPREFIX + "error: could not add external mount %s", entry->fs); + ret = 1; +@@ -1435,12 +1437,13 @@ static int do_program_mount(struct autof + * before executing the mount command and removing it at + * umount. + */ +- if (ext_mount_inuse(entry->fs)) { ++ if (is_mounted(entry->fs, MNTS_REAL)) { ++ if (!ext_mount_add(entry->fs, entry->umount)) { ++ error(ap->logopt, MODPREFIX ++ "error: could not add external mount %s", entry->fs); ++ goto out; ++ } + rv = 0; +- /* An external mount with path entry->fs exists +- * so ext_mount_add() won't fail. +- */ +- ext_mount_add(entry->fs, entry->umount); + } else { + rv = mkdir_path(entry->fs, mp_mode); + if (rv && errno != EEXIST) { diff --git a/autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch b/autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch new file mode 100644 index 0000000..93513eb --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -173,6 +173,7 @@ + - refactor amd mount options handling. + - add some unimplemented amd map options. + - fix submount shutdown race. ++- fix lookup search type in umount_subtree_mounts(). + + 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 +@@ -543,7 +543,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/autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch b/autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch new file mode 100644 index 0000000..23b7fec --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -174,6 +174,7 @@ + - add some unimplemented amd map options. + - fix submount shutdown race. + - fix lookup search type in umount_subtree_mounts(). ++- fix remount_active_mount() not remounting symlinks. + + 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 +@@ -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/autofs-5.1.9-fix-submount-shutdown-race.patch b/autofs-5.1.9-fix-submount-shutdown-race.patch new file mode 100644 index 0000000..50eaebc --- /dev/null +++ b/autofs-5.1.9-fix-submount-shutdown-race.patch @@ -0,0 +1,89 @@ +autofs-5.1.9 - fix submount shutdown race + +From: Ian Kent + +In function master_notify_submount() an expire notification is sent to +existing submounts. automount wait for the task to complete then, if +the submount is exiting, waits for the submount to reach a completion +state. + +But the submount can go away during these checks resulting in the +autofs mount point structure field of the mount list structure to be +set to NULL. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/master.c | 23 +++++++++++++---------- + lib/mounts.c | 2 ++ + 3 files changed, 16 insertions(+), 10 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/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 submount shutdown race. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/master.c ++++ autofs-5.1.7/daemon/master.c +@@ -1213,22 +1213,24 @@ int master_notify_submount(struct autofs + + this = mnts_find_submount(path); + if (this) { ++ struct autofs_point *found; ++ + /* We have found a submount to expire */ + st_mutex_lock(); +- +- if (this->ap->state == ST_SHUTDOWN) { ++ found = this->ap; ++ if (!found || found->state == ST_SHUTDOWN) { + this = NULL; + st_mutex_unlock(); + goto done; + } +- +- this->ap->shutdown = ap->shutdown; +- +- __st_add_task(this->ap, state); +- ++ found->shutdown = ap->shutdown; ++ __st_add_task(found, state); + st_mutex_unlock(); + +- st_wait_task(this->ap, state, 0); ++ /* This is ok because found isn't dereferenced during ++ * the wait checks. ++ */ ++ st_wait_task(found, state, 0); + + /* + * If our submount gets to state ST_SHUTDOWN_PENDING or +@@ -1240,8 +1242,9 @@ int master_notify_submount(struct autofs + struct timespec t = { 0, 300000000 }; + struct timespec r; + +- if (sbmnt->ap->state != ST_SHUTDOWN_PENDING && +- sbmnt->ap->state != ST_SHUTDOWN_FORCE) { ++ if (!sbmnt->ap || ++ (sbmnt->ap->state != ST_SHUTDOWN_PENDING && ++ sbmnt->ap->state != ST_SHUTDOWN_FORCE)) { + ret = 0; + mnts_put_mount(sbmnt); + break; +--- autofs-5.1.7.orig/lib/mounts.c ++++ autofs-5.1.7/lib/mounts.c +@@ -1153,7 +1153,9 @@ void mnts_remove_submount(const char *mp + this = mnts_lookup(mp); + if (this && this->flags & MNTS_AUTOFS) { + this->flags &= ~MNTS_AUTOFS; ++ st_mutex_lock(); + this->ap = NULL; ++ st_mutex_unlock(); + list_del_init(&this->submount); + __mnts_put_mount(this); + } diff --git a/autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch b/autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch new file mode 100644 index 0000000..872667c --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -175,6 +175,7 @@ + - fix submount shutdown race. + - fix lookup search type in umount_subtree_mounts(). + - fix remount_active_mount() not remounting symlinks. ++- log when setting amd per-mount timeout. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/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/autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch b/autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch new file mode 100644 index 0000000..0be68f1 --- /dev/null +++ b/autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch @@ -0,0 +1,192 @@ +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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -169,6 +169,7 @@ + - add flags argument to amd do_program_mount(). + - fix amd cache options not copied. + - seperate amd mount and entry flags. ++- make iocl ops ->timeout() handle per-dentry expire. + + 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 +@@ -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.7.orig/daemon/indirect.c ++++ autofs-5.1.7/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.7.orig/daemon/state.c ++++ autofs-5.1.7/daemon/state.c +@@ -366,7 +366,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) +@@ -427,7 +427,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.7.orig/include/dev-ioctl-lib.h ++++ autofs-5.1.7/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.7.orig/lib/dev-ioctl-lib.c ++++ autofs-5.1.7/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.7.orig/lib/mounts.c ++++ autofs-5.1.7/lib/mounts.c +@@ -2757,7 +2757,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; + } +@@ -2779,7 +2779,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/autofs-5.1.9-refactor-amd-function-do_program_mount.patch b/autofs-5.1.9-refactor-amd-function-do_program_mount.patch new file mode 100644 index 0000000..a6f09b8 --- /dev/null +++ b/autofs-5.1.9-refactor-amd-function-do_program_mount.patch @@ -0,0 +1,138 @@ +autofs-5.1.9 - refactor amd function do_program_mount() + +From: Ian Kent + +The amd mounts function do_program_mount() is particularly untidy. + +Refactor it to make it a little simpler and to take advantage of the +coming refactoring of the funtion umount_amd_ext_mount(). + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + modules/parse_amd.c | 74 ++++++++++++++++++++++++---------------------------- + 2 files changed, 36 insertions(+), 39 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -164,6 +164,7 @@ + - fix amd external mount error handling. + - fix amd external mount mount handling. + - don't free ext mount if mounted. ++- refactor amd function do_program_mount(). + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -1407,26 +1407,8 @@ out: + static int do_program_mount(struct autofs_point *ap, + struct amd_entry *entry, const char *name) + { +- char *prog, *str; +- char **argv; +- int argc = -1; + int rv = 1; + +- str = strdup(entry->mount); +- if (!str) +- goto out; +- +- prog = NULL; +- argv = NULL; +- +- argc = construct_argv(str, &prog, &argv); +- if (argc == -1) { +- error(ap->logopt, MODPREFIX +- "%s: error creating mount arguments", entry->type); +- free(str); +- goto out; +- } +- + /* The am-utils documentation doesn't actually say that the + * mount (and umount, if given) command need to use ${fs} as + * the mount point in the command. +@@ -1445,6 +1427,25 @@ static int do_program_mount(struct autof + } + rv = 0; + } else { ++ char *prog, *str; ++ char **argv; ++ int argc = -1; ++ ++ str = strdup(entry->mount); ++ if (!str) ++ goto out; ++ ++ prog = NULL; ++ argv = NULL; ++ ++ argc = construct_argv(str, &prog, &argv); ++ if (argc == -1) { ++ error(ap->logopt, MODPREFIX ++ "%s: error creating mount arguments", entry->type); ++ free(str); ++ goto out; ++ } ++ + rv = mkdir_path(entry->fs, mp_mode); + if (rv && errno != EEXIST) { + char buf[MAX_ERR_BUF]; +@@ -1454,7 +1455,9 @@ static int do_program_mount(struct autof + error(ap->logopt, + MODPREFIX "%s: mkdir_path %s failed: %s", + entry->type, entry->fs, estr); +- goto do_free; ++ free_argv(argc, (const char **) argv); ++ free(str); ++ goto out; + } + + rv = spawnv(ap->logopt, prog, (const char * const *) argv); +@@ -1463,33 +1466,26 @@ static int do_program_mount(struct autof + rv = 0; + debug(ap->logopt, MODPREFIX + "%s: mounted %s", entry->type, entry->fs); +- goto do_free; ++ free_argv(argc, (const char **) argv); ++ free(str); ++ goto done; + } + umount_amd_ext_mount(ap, entry->fs); + } +- +- if (!ext_mount_inuse(entry->fs)) +- rmdir_path(ap, entry->fs, ap->dev); + error(ap->logopt, MODPREFIX + "%s: failed to mount using %s", entry->type, entry->mount); +- } +-do_free: +- free_argv(argc, (const char **) argv); +- free(str); +- +- if (rv) ++ free_argv(argc, (const char **) argv); ++ free(str); + goto out; +- ++ } ++done: + rv = do_link_mount(ap, name, entry, 0); +- if (!rv) +- goto out; +- +- if (umount_amd_ext_mount(ap, entry->fs)) { +- if (!ext_mount_inuse(entry->fs)) +- rmdir_path(ap, entry->fs, ap->dev); +- debug(ap->logopt, MODPREFIX +- "%s: failed to umount external mount at %s", +- entry->type, entry->fs); ++ if (rv) { ++ if (umount_amd_ext_mount(ap, entry->fs)) { ++ debug(ap->logopt, MODPREFIX ++ "%s: failed to cleanup external mount at %s", ++ entry->type, entry->fs); ++ } + } + out: + return rv; diff --git a/autofs-5.1.9-refactor-amd-function-umount_amd_ext_mount.patch b/autofs-5.1.9-refactor-amd-function-umount_amd_ext_mount.patch new file mode 100644 index 0000000..322352a --- /dev/null +++ b/autofs-5.1.9-refactor-amd-function-umount_amd_ext_mount.patch @@ -0,0 +1,242 @@ +autofs-5.1.9 - refactor amd function umount_amd_ext_mount() + +From: Ian Kent + +The amd mounts function umount_amd_ext_mount() needs some improvement. + +Make sure the function returns true for success and false for failure +and add a parameter to control if the expternal mount reference should +be decremented on successful umount. + +If the reference count of the external mount is greater than 1 there's +some other mount using (symlink pointing to) it so don't try to umount +it just return success. + +Also check for the case where the mount is already mounted. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + daemon/automount.c | 4 +- + include/mounts.h | 2 - + lib/mounts.c | 80 ++++++++++++++++++++++++++++++---------------------- + modules/parse_amd.c | 10 +++--- + 5 files changed, 56 insertions(+), 41 deletions(-) + +--- autofs-5.1.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -165,6 +165,7 @@ + - fix amd external mount mount handling. + - don't free ext mount if mounted. + - refactor amd function do_program_mount(). ++- refactor umount_amd_ext_mount(). + + 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 +@@ -618,7 +618,7 @@ static int umount_subtree_mounts(struct + /* Check for an external mount and umount if possible */ + mnt = mnts_find_amdmount(path); + if (mnt) { +- umount_amd_ext_mount(ap, mnt->ext_mp); ++ umount_amd_ext_mount(ap, mnt->ext_mp, 1); + mnts_remove_amdmount(path); + mnts_put_mount(mnt); + } +@@ -684,7 +684,7 @@ int umount_multi(struct autofs_point *ap + /* Check for an external mount and attempt umount if needed */ + mnt = mnts_find_amdmount(path); + if (mnt) { +- umount_amd_ext_mount(ap, mnt->ext_mp); ++ umount_amd_ext_mount(ap, mnt->ext_mp, 1); + mnts_remove_amdmount(path); + mnts_put_mount(mnt); + } +--- autofs-5.1.7.orig/include/mounts.h ++++ autofs-5.1.7/include/mounts.h +@@ -199,7 +199,7 @@ int try_remount(struct autofs_point *, s + void set_indirect_mount_tree_catatonic(struct autofs_point *); + void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *); + int umount_ent(struct autofs_point *, const char *); +-int umount_amd_ext_mount(struct autofs_point *, const char *); ++int umount_amd_ext_mount(struct autofs_point *, const char *, int remove); + int clean_stale_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *); + + #endif +--- autofs-5.1.7.orig/lib/mounts.c ++++ autofs-5.1.7/lib/mounts.c +@@ -3095,37 +3095,62 @@ int umount_ent(struct autofs_point *ap, + return mounted; + } + +-int umount_amd_ext_mount(struct autofs_point *ap, const char *path) ++int umount_amd_ext_mount(struct autofs_point *ap, const char *path, int remove) + { + struct ext_mount *em; + char *umount = NULL; +- char *mp; ++ char *mp = NULL; + int rv = 1; ++ int ret; + + pthread_mutex_lock(&ext_mount_hash_mutex); +- + em = ext_mount_lookup(path); + if (!em) { + pthread_mutex_unlock(&ext_mount_hash_mutex); ++ rv = 0; + goto out; + } + mp = strdup(em->mp); + if (!mp) { + pthread_mutex_unlock(&ext_mount_hash_mutex); ++ rv = 0; + goto out; + } + if (em->umount) { + umount = strdup(em->umount); + if (!umount) { + pthread_mutex_unlock(&ext_mount_hash_mutex); +- free(mp); ++ rv = 0; + goto out; + } + } +- ++ /* Don't try and umount if there's more than one ++ * user of the external mount. ++ */ ++ if (em->ref > 1) { ++ pthread_mutex_unlock(&ext_mount_hash_mutex); ++ if (!remove) ++ error(ap->logopt, ++ "reference count mismatch, called with remove false"); ++ else ++ ext_mount_remove(mp); ++ goto out; ++ } ++ /* This shouldn't happen ... */ ++ if (!is_mounted(mp, MNTS_REAL)) { ++ pthread_mutex_unlock(&ext_mount_hash_mutex); ++ error(ap->logopt, "failed to umount program mount at %s", mp); ++ if (remove) ++ ext_mount_remove(mp); ++ goto out; ++ } + pthread_mutex_unlock(&ext_mount_hash_mutex); + +- if (umount) { ++ if (!umount) { ++ ret = umount_ent(ap, mp); ++ if (ret) ++ rv = 0; ++ } else { + char *prog; + char **argv; + int argc = -1; +@@ -3134,41 +3159,30 @@ int umount_amd_ext_mount(struct autofs_p + argv = NULL; + + argc = construct_argv(umount, &prog, &argv); +- if (argc == -1) +- goto done; +- +- if (!ext_mount_remove(mp)) { +- rv =0; +- goto out_free; +- } +- +- rv = spawnv(ap->logopt, prog, (const char * const *) argv); +- if (rv == -1 || (WIFEXITED(rv) && WEXITSTATUS(rv))) ++ if (argc == -1) { + error(ap->logopt, +- "failed to umount program mount at %s", mp); +- else { ++ "failed to allocate args for umount of %s", mp); + rv = 0; +- debug(ap->logopt, "umounted program mount at %s", mp); +- rmdir_path(ap, mp, ap->dev); ++ goto out; + } +-out_free: ++ ret = spawnv(ap->logopt, prog, (const char * const *) argv); ++ rv = WIFEXITED(ret) && !WEXITSTATUS(ret); + free_argv(argc, (const char **) argv); +- +- goto done; + } + +- if (ext_mount_remove(mp)) { +- rv = umount_ent(ap, mp); +- if (rv) +- error(ap->logopt, +- "failed to umount external mount %s", mp); +- else +- debug(ap->logopt, "umounted external mount %s", mp); ++ if (is_mounted(mp, MNTS_REAL)) ++ error(ap->logopt, ++ "failed to umount external mount %s", mp); ++ else { ++ info(ap->logopt, "umounted external mount %s", mp); ++ rmdir_path(ap, mp, ap->dev); + } +-done: ++ if (remove) ++ ext_mount_remove(mp); ++out: + if (umount) + free(umount); +- free(mp); +-out: ++ if (mp) ++ free(mp); + return rv; + } +--- autofs-5.1.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/modules/parse_amd.c +@@ -1133,7 +1133,7 @@ symlink: + + if (entry->sublink) { + /* failed to complete sublink mount */ +- umount_amd_ext_mount(ap, entry->fs); ++ umount_amd_ext_mount(ap, entry->fs, 1); + } + out: + return ret; +@@ -1184,7 +1184,7 @@ static int do_generic_mount(struct autof + /* If we have an external mount add it to the list */ + if (!ext_mount_add(entry->fs, entry->umount)) { + if (umount) +- umount_amd_ext_mount(ap, entry->fs); ++ umount_amd_ext_mount(ap, entry->fs, 0); + error(ap->logopt, MODPREFIX + "error: could not add external mount %s", + entry->fs); +@@ -1235,7 +1235,7 @@ static int do_nfs_mount(struct autofs_po + /* We might be using an external mount */ + if (!ext_mount_add(entry->fs, entry->umount)) { + if (umount) +- umount_amd_ext_mount(ap, entry->fs); ++ umount_amd_ext_mount(ap, entry->fs, 0); + error(ap->logopt, MODPREFIX + "error: could not add external mount %s", entry->fs); + ret = 1; +@@ -1470,7 +1470,7 @@ static int do_program_mount(struct autof + free(str); + goto done; + } +- umount_amd_ext_mount(ap, entry->fs); ++ umount_amd_ext_mount(ap, entry->fs, 0); + } + error(ap->logopt, MODPREFIX + "%s: failed to mount using %s", entry->type, entry->mount); +@@ -1481,7 +1481,7 @@ static int do_program_mount(struct autof + done: + rv = do_link_mount(ap, name, entry, 0); + if (rv) { +- if (umount_amd_ext_mount(ap, entry->fs)) { ++ if (!umount_amd_ext_mount(ap, entry->fs, 1)) { + debug(ap->logopt, MODPREFIX + "%s: failed to cleanup external mount at %s", + entry->type, entry->fs); diff --git a/autofs-5.1.9-refactor-amd-mount-options-handling.patch b/autofs-5.1.9-refactor-amd-mount-options-handling.patch new file mode 100644 index 0000000..9d32f17 --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/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. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/modules/amd_parse.y ++++ autofs-5.1.7/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/autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch b/autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch new file mode 100644 index 0000000..3cebb02 --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -168,6 +168,7 @@ + - refactor umount_amd_ext_mount(). + - add flags argument to amd do_program_mount(). + - fix amd cache options not copied. ++- seperate amd mount and entry flags. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/include/parse_amd.h ++++ autofs-5.1.7/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.7.orig/modules/amd_parse.y ++++ autofs-5.1.7/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.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/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/autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch b/autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch new file mode 100644 index 0000000..213e598 --- /dev/null +++ b/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.7.orig/CHANGELOG ++++ autofs-5.1.7/CHANGELOG +@@ -176,6 +176,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. + + 25/01/2021 autofs-5.1.7 + - make bind mounts propagation slave by default. +--- autofs-5.1.7.orig/daemon/master.c ++++ autofs-5.1.7/daemon/master.c +@@ -1379,7 +1379,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.7.orig/daemon/state.c ++++ autofs-5.1.7/daemon/state.c +@@ -428,6 +428,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.7.orig/include/master.h ++++ autofs-5.1.7/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.7.orig/include/mounts.h ++++ autofs-5.1.7/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.7.orig/lib/mounts.c ++++ autofs-5.1.7/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.7.orig/modules/parse_amd.c ++++ autofs-5.1.7/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/autofs.spec b/autofs.spec index 010e788..9408518 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: 58%{?dist} +Release: 59%{?dist} Epoch: 1 License: GPLv2+ Source: https://www.kernel.org/pub/linux/daemons/autofs/v5/autofs-%{version}-2.tar.gz @@ -192,6 +192,31 @@ Patch177: autofs-5.1.8-fix-multi-mount-check.patch Patch178: autofs-5.1.9-fix-get-parent-multi-mount-check-in-try_remount.patch Patch179: autofs-5.1.9-fix-deadlock-in-remount.patch +# JIRA: RHEL-69485 +Patch180: autofs-5.1.9-fix-amd-external-mount-error-handling.patch +Patch181: autofs-5.1.9-fix-amd-external-mount-mount-handling.patch +Patch182: autofs-5.1.9-dont-free-ext-mount-if-mounted.patch +Patch183: autofs-5.1.9-refactor-amd-function-do_program_mount.patch +Patch184: autofs-5.1.9-refactor-amd-function-umount_amd_ext_mount.patch +Patch185: autofs-5.1.9-add-flags-argument-to-amd-do_program_mount.patch + +# JIRA: RHEL-71359 +Patch186: autofs-5.1.9-fix-amd-cache-options-not-copied.patch +Patch187: autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch +Patch188: autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch +Patch189: autofs-5.1.9-refactor-amd-mount-options-handling.patch +Patch190: autofs-5.1.9-add-some-unimplemented-amd-map-options.patch + +# JIRA: RHEL-57466 +Patch200: autofs-5.1.9-fix-submount-shutdown-race.patch + +# JIRA: RHEL-71359 updates and fixes +Patch201: autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch +Patch202: autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch +Patch203: autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch +Patch204: autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch +Patch205: autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch + %if %{with_systemd} BuildRequires: systemd-units BuildRequires: systemd-devel @@ -427,6 +452,27 @@ echo %{version}-%{release} > .version %patch178 -p1 %patch179 -p1 +%patch180 -p1 +%patch181 -p1 +%patch182 -p1 +%patch183 -p1 +%patch184 -p1 +%patch185 -p1 + +%patch186 -p1 +%patch187 -p1 +%patch188 -p1 +%patch189 -p1 +%patch190 -p1 + +%patch200 -p1 + +%patch201 -p1 +%patch202 -p1 +%patch203 -p1 +%patch204 -p1 +%patch205 -p1 + %build LDFLAGS=-Wl,-z,now %configure \ @@ -534,6 +580,31 @@ fi %dir /etc/auto.master.d %changelog +* Mon Dec 16 2024 Ian Kent - 1:5.1.7-59 +- RHEL-69485 - Sporadic mount failures with amd program maps on RHEL8 + - fix amd external mount error handling. + - fix amd external mount mount handling. + - don't free ext mount if mounted. + - refactor amd function do_program_mount(). + - refactor umount_amd_ext_mount(). + - add flags argument to amd do_program_mount(). +- Resolves: RHEL-69485 +- RHEL-71359 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. +- Resolves: RHEL-71359 +- RHEL-57466 - RHEL9.4 - autofs crashes on startup after IDM client configuration + - fix submount shutdown race. +- Resolves: RHEL-57466 + * Fri Dec 22 2023 Ian Kent - 1:5.1.7-58 - RHEL-19731 - SIGSEGV using hierarchical map entries on reload with autofs-5.1.4-109