]> git.webhop.me Git - bs-cst-neutrino-hd.git/commitdiff
pump version autofs-5.1.7
authorMarkham <markham001@gmx.de>
Tue, 5 Oct 2021 11:40:07 +0000 (13:40 +0200)
committerMarkham <markham001@gmx.de>
Tue, 5 Oct 2021 11:40:07 +0000 (13:40 +0200)
85 files changed:
archive-patches/autofs5/autofs-5.1.7-Fix-option-for-master_read_wait.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-mapent-tree-implementation.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-missing-description-of-null-map-option.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-missing-free-in-handle_mounts.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-mount-and-umount-offsets-functions.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-set_offset_tree_catatonic.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-some-multi-mount-macros.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_add_node.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_delete_offsets.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_traverse_subtree.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-add-xdr_exports.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-check-for-offset-with-no-mount-location.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-cleanup-cache_delete-a-little.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-dont-use-AUTOFS_DEV_IOCTL_CLOSEMOUNT.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-eliminate-some-more-alloca-usage.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-amd-hosts-mount-expire.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-amd-section-mounts-map-reload.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-arg-not-used-in-print.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-concat_options-error-handling.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-dandling-symlink-creation-if-nis-support-is-not-available.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-direct-mount-deadlock.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-double-free-in-parse_mapent.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-double-unlock-in-parse_mount.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-flag-check-in-umount_multi.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-hosts-map-offset-order.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-mount_fullpath.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-offset-entries-order.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-make-tree-implementation-data-independent.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-pass-root-length-to-mount_fullpath.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-refactor-umount_multi_triggers.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-mounts_mutex.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-obsolete-functions.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-redundant-if-check.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-remove-unused-variable-from-get_exports.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-rename-tree-implementation-functions.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-simplify-get_parent.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-simplify-mount_subtree-mount-check.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-use-default-stack-size-for-threads.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch [new file with mode: 0644]
archive-patches/autofs5/autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch [new file with mode: 0644]
archive-patches/autofs5/patch_order_5.1.7 [new file with mode: 0644]
make/applications.mk
make/versions.mk

diff --git a/archive-patches/autofs5/autofs-5.1.7-Fix-option-for-master_read_wait.patch b/archive-patches/autofs5/autofs-5.1.7-Fix-option-for-master_read_wait.patch
new file mode 100644 (file)
index 0000000..2cd873b
--- /dev/null
@@ -0,0 +1,48 @@
+autofs-5.1.7 - Fix option for master read wait
+
+From: Goldwyn Rodrigues <rgoldwyn@suse.de>
+
+The master-wait program option expects a value, and if provided
+automount crashes with the following trace:
+
+#0  __GI_____strtoul_l_internal (nptr=0x0, endptr=0x7fffffffe120, base=0, group=<optimized out>,
+    loc=0x7ffff77a63a0 <_nl_global_locale>) at ../stdlib/strtol_l.c:292
+#1  0x0000555555562c52 in getnumopt ()
+#2  0x0000555555564ec0 in main ()
+
+This is because the options string is not correct and does not expect
+an argument for master-wait (M), which sets optarg to NULL.
+
+Fixes: e68f07f ("autofs-5.1.2 - add master read wait option")
+Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index fe49740e..0b577909 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -4,6 +4,7 @@
+ - dont use realloc in host exports list processing.
+ - use sprintf() when constructing hosts mapent.
+ - fix mnts_remove_amdmount() uses wrong list.
++- Fix option for master read wait.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index e476f6b2..7fa92877 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -2274,7 +2274,7 @@ int main(int argc, char *argv[])
+       time_t timeout;
+       time_t age = monotonic_time(NULL);
+       struct rlimit rlim;
+-      const char *options = "+hp:t:vmdD:SfVrO:l:n:CFUM";
++      const char *options = "+hp:t:vmdD:SfVrO:l:n:CFUM:";
+       static const struct option long_options[] = {
+               {"help", 0, 0, 'h'},
+               {"pid-file", 1, 0, 'p'},
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch b/archive-patches/autofs5/autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch
new file mode 100644 (file)
index 0000000..85c745b
--- /dev/null
@@ -0,0 +1,136 @@
+autofs-5.1.7 - add a len field to struct autofs_point
+
+From: Ian Kent <raven@themaw.net>
+
+Add a path length field to struct autofs_point since the path length
+is needed at various times avoiding additional strlen() calls.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/lookup.c     |    2 +-
+ daemon/master.c     |    1 +
+ include/automount.h |    1 +
+ lib/mounts.c        |    6 +++---
+ modules/parse_amd.c |    4 ++--
+ modules/parse_sun.c |    4 ++--
+ 7 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 60924b3f..0dae6761 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -30,6 +30,7 @@
+ - rename tree implementation functions.
+ - add some multi-mount macros.
+ - remove unused functions cache_dump_multi() and cache_dump_cache().
++- add a len field to struct autofs_point.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/lookup.c b/daemon/lookup.c
+index 8c9a82b5..5116b927 100644
+--- a/daemon/lookup.c
++++ b/daemon/lookup.c
+@@ -843,7 +843,7 @@ static int lookup_amd_instance(struct autofs_point *ap,
+               return NSS_STATUS_UNKNOWN;
+       }
+-      m_key = malloc(strlen(ap->path) + strlen(MM_ROOT(me)->key) + 2);
++      m_key = malloc(ap->len + strlen(MM_ROOT(me)->key) + 2);
+       if (!m_key) {
+               error(ap->logopt,
+                    "failed to allocate storage for search key");
+diff --git a/daemon/master.c b/daemon/master.c
+index da527a61..022fb9dd 100644
+--- a/daemon/master.c
++++ b/daemon/master.c
+@@ -86,6 +86,7 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+               free(ap);
+               return 0;
+       }
++      ap->len = strlen(ap->path);
+       ap->pref = NULL;
+       ap->entry = entry;
+diff --git a/include/automount.h b/include/automount.h
+index e917515b..34485859 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -548,6 +548,7 @@ struct kernel_mod_version {
+ struct autofs_point {
+       pthread_t thid;
+       char *path;                     /* Mount point name */
++      size_t len;                     /* Length of mount point name */
+       mode_t mode;                    /* Mount point mode */
+       char *pref;                     /* amd prefix */
+       int pipefd;                     /* File descriptor for pipe */
+diff --git a/lib/mounts.c b/lib/mounts.c
+index f6f20fc0..b478ecb4 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1158,7 +1158,7 @@ struct mnt_list *mnts_add_mount(struct autofs_point *ap,
+               if (!mp)
+                       goto fail;
+       } else {
+-              int len = strlen(ap->path) + strlen(name) + 2;
++              int len = ap->len + strlen(name) + 2;
+               mp = malloc(len);
+               if (!mp)
+@@ -2495,9 +2495,9 @@ static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+       dir = strdup(oe->key);
+       if (ap->flags & MOUNT_FLAG_GHOST)
+-              split = strlen(ap->path) + strlen(MM_ROOT(oe)->key) + 1;
++              split = ap->len + strlen(MM_ROOT(oe)->key) + 1;
+       else
+-              split = strlen(ap->path);
++              split = ap->len;
+       dir[split] = '\0';
+       path = &dir[split + 1];
+diff --git a/modules/parse_amd.c b/modules/parse_amd.c
+index d3e8a450..5a9079d6 100644
+--- a/modules/parse_amd.c
++++ b/modules/parse_amd.c
+@@ -147,7 +147,7 @@ static struct substvar *add_lookup_vars(struct autofs_point *ap,
+       struct mapent *me;
+       int len;
+-      len = strlen(ap->path) + 1 + key_len + 1;
++      len = ap->len + 1 + key_len + 1;
+       if (len > PATH_MAX) {
+               error(ap->logopt, MODPREFIX
+                     "error: lookup key is greater than PATH_MAX");
+@@ -1319,7 +1319,7 @@ static int do_host_mount(struct autofs_point *ap, const char *name,
+               char *target;
+               size_t len;
+-              len = strlen(ap->path) + strlen(entry->rhost) + 2;
++              len = ap->len + strlen(entry->rhost) + 2;
+               target = malloc(len);
+               if (!target) {
+                       warn(ap->logopt, MODPREFIX
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index b11c6693..b1f64ca0 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1154,7 +1154,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+               mm_root = mm_key;
+               start = strlen(mm_key);
+       } else {
+-              start = strlen(ap->path) + strlen(mm_key) + 1;
++              start = ap->len + strlen(mm_key) + 1;
+               mm_root = alloca(start + 3);
+               strcpy(mm_root, ap->path);
+               strcat(mm_root, "/");
+@@ -1477,7 +1477,7 @@ dont_expand:
+                       }
+                       strcpy(m_root, name);
+               } else {
+-                      m_root_len = strlen(ap->path) + name_len + 1;
++                      m_root_len = ap->len + name_len + 1;
+                       m_root = alloca(m_root_len + 1);
+                       if (!m_root) {
+                               char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch b/archive-patches/autofs5/autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch
new file mode 100644 (file)
index 0000000..ae2b383
--- /dev/null
@@ -0,0 +1,104 @@
+autofs-5.1.7 - add ext_mount_hash_mutex lock helpers
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: check_return: Calling "pthread_mutex_lock" without checking
+         return value.
+
+Well, I use helpers to do this in many places so can't really disagree.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   26 ++++++++++++++++++++------
+ 2 files changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index b1b28888..ff44ac25 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -65,6 +65,7 @@
+ - fix double free in parse_mapent().
+ - refactor lookup_prune_one_cache() a bit.
+ - cater for empty mounts list in mnts_get_expire_list().
++- add ext_mount_hash_mutex lock helpers.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 3996eb5e..c24d1a88 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -788,6 +788,20 @@ char *make_mnt_name_string(char *path)
+       return mnt_name;
+ }
++static void ext_mount_hash_mutex_lock(void)
++{
++      int status = pthread_mutex_lock(&ext_mount_hash_mutex);
++      if (status)
++              fatal(status);
++}
++
++static void ext_mount_hash_mutex_unlock(void)
++{
++      int status = pthread_mutex_unlock(&ext_mount_hash_mutex);
++      if (status)
++              fatal(status);
++}
++
+ static struct ext_mount *ext_mount_lookup(const char *mp)
+ {
+       uint32_t hval = hash(mp, HASH_SIZE(ext_mounts_hash));
+@@ -806,7 +820,7 @@ int ext_mount_add(const char *path, const char *umount)
+       struct ext_mount *em;
+       int ret = 0;
+-      pthread_mutex_lock(&ext_mount_hash_mutex);
++      ext_mount_hash_mutex_lock();
+       em = ext_mount_lookup(path);
+       if (em) {
+@@ -840,7 +854,7 @@ int ext_mount_add(const char *path, const char *umount)
+       ret = 1;
+ done:
+-      pthread_mutex_unlock(&ext_mount_hash_mutex);
++      ext_mount_hash_mutex_unlock();
+       return ret;
+ }
+@@ -849,7 +863,7 @@ int ext_mount_remove(const char *path)
+       struct ext_mount *em;
+       int ret = 0;
+-      pthread_mutex_lock(&ext_mount_hash_mutex);
++      ext_mount_hash_mutex_lock();
+       em = ext_mount_lookup(path);
+       if (!em)
+@@ -867,7 +881,7 @@ int ext_mount_remove(const char *path)
+               ret = 1;
+       }
+ done:
+-      pthread_mutex_unlock(&ext_mount_hash_mutex);
++      ext_mount_hash_mutex_unlock();
+       return ret;
+ }
+@@ -876,13 +890,13 @@ int ext_mount_inuse(const char *path)
+       struct ext_mount *em;
+       int ret = 0;
+-      pthread_mutex_lock(&ext_mount_hash_mutex);
++      ext_mount_hash_mutex_lock();
+       em = ext_mount_lookup(path);
+       if (!em)
+               goto done;
+       ret = em->ref;
+ done:
+-      pthread_mutex_unlock(&ext_mount_hash_mutex);
++      ext_mount_hash_mutex_unlock();
+       return ret;
+ }
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch b/archive-patches/autofs5/autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch
new file mode 100644 (file)
index 0000000..264f83a
--- /dev/null
@@ -0,0 +1,42 @@
+autofs-5.1.7 - add length check in umount_subtree_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: fixed_size_dest: You might overrun the 4097-character
+         fixed-size string "key" by copying "me->key" without
+         checking the length.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    5 +++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 224f58d6..9e385ba9 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -55,6 +55,7 @@
+ - fix possible memory leak in master_parse().
+ - fix possible memory leak in mnts_add_amdmount().
+ - fix double unlock in parse_mount().
++- add length check in umount_subtree_mounts().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 48472d5f..70506d83 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -562,6 +562,11 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+                       left++;
+               }
++              if (me->len > PATH_MAX) {
++                      crit(ap->logopt, "me->key too long for buffer");
++                      return 1;
++              }
++
+               strcpy(key, me->key);
+               cache_unlock(mc);
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-mapent-tree-implementation.patch b/archive-patches/autofs5/autofs-5.1.7-add-mapent-tree-implementation.patch
new file mode 100644 (file)
index 0000000..26ea375
--- /dev/null
@@ -0,0 +1,177 @@
+autofs-5.1.7 - add mapent tree implementation
+
+From: Ian Kent <raven@themaw.net>
+
+Add a struct mapent basic tree implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    4 ++++
+ include/mounts.h    |    8 ++++++++
+ lib/cache.c         |    9 ++++++++-
+ lib/mounts.c        |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 71 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 74571570..8841f72f 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -32,6 +32,7 @@
+ - remove unused functions cache_dump_multi() and cache_dump_cache().
+ - add a len field to struct autofs_point.
+ - make tree implementation data independent.
++- add mapent tree implementation.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/automount.h b/include/automount.h
+index 34485859..ebc2007f 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -166,10 +166,14 @@ struct mapent {
+       struct mapent_cache *mc;
+       struct map_source *source;
+       /* Need to know owner if we're a multi-mount */
++      struct tree_node *mm_root;
++      struct tree_node *mm_parent;
++      struct tree_node node;
+       struct mapent *multi;
+       /* Parent nesting point within multi-mount */
+       struct mapent *parent;
+       char *key;
++      size_t len;
+       char *mapent;
+       struct stack *stack;
+       time_t age;
+diff --git a/include/mounts.h b/include/mounts.h
+index 71d29566..fd7c6183 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -66,6 +66,13 @@ struct tree_node {
+ #define MNT_LIST(n)           (container_of(n, struct mnt_list, node))
+ #define MNT_LIST_NODE(ptr)    ((struct tree_node *) &((struct mnt_list *) ptr)->node)
++#define MAPENT(n)             (container_of(n, struct mapent, node))
++#define MAPENT_NODE(p)                ((struct tree_node *) &((struct mapent *) p)->node)
++#define MAPENT_ROOT(p)                ((struct tree_node *) ((struct mapent *) p)->mm_root)
++#define MAPENT_PARENT(p)      ((struct tree_node *) ((struct mapent *) p)->mm_parent)
++#define MAPENT_SET_ROOT(p, r) { (((struct mapent *) p)->mm_root = (struct tree_node *) r); }
++#define MAPENT_SET_PARENT(p, n)       { (((struct mapent *) p)->mm_parent = (struct tree_node *) n); }
++
+ typedef struct tree_node *(*tree_new_t) (void *ptr);
+ typedef int  (*tree_cmp_t) (struct tree_node *n, void *ptr);
+ typedef void (*tree_free_t) (struct tree_node *n);
+@@ -161,6 +168,7 @@ unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
++struct tree_node *tree_mapent_root(struct mapent *me);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+diff --git a/lib/cache.c b/lib/cache.c
+index 629c4d0a..6dfaeff5 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -546,17 +546,21 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+       struct mapent *me, *existing = NULL;
+       char *pkey, *pent;
+       u_int32_t hashval = hash(key, mc->size);
++      size_t len;
+       me = (struct mapent *) malloc(sizeof(struct mapent));
+       if (!me)
+               return CHE_FAIL;
+-      pkey = malloc(strlen(key) + 1);
++      len = strlen(key);
++
++      pkey = malloc(len + 1);
+       if (!pkey) {
+               free(me);
+               return CHE_FAIL;
+       }
+       me->key = strcpy(pkey, key);
++      me->len = len;
+       if (mapent) {
+               pent = malloc(strlen(mapent) + 1);
+@@ -575,6 +579,9 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+       me->status = 0;
+       me->mc = mc;
+       me->source = ms;
++      me->mm_root = NULL;
++      me->mm_parent = NULL;
++      INIT_TREE_NODE(&me->node);
+       INIT_LIST_HEAD(&me->ino_index);
+       INIT_LIST_HEAD(&me->multi_list);
+       me->multi = NULL;
+diff --git a/lib/mounts.c b/lib/mounts.c
+index a6d1c5a7..40ebf9cf 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -79,6 +79,17 @@ static struct tree_ops mnt_ops = {
+ };
+ static struct tree_ops *tree_mnt_ops = &mnt_ops;
++static struct tree_node *tree_mapent_new(void *ptr);
++static int tree_mapent_cmp(struct tree_node *n, void *ptr);
++static void tree_mapent_free(struct tree_node *n);
++
++static struct tree_ops mapent_ops = {
++      .new = tree_mapent_new,
++      .cmp = tree_mapent_cmp,
++      .free = tree_mapent_free,
++};
++static struct tree_ops *tree_mapent_ops = &mapent_ops;
++
+ unsigned int linux_version_code(void)
+ {
+       struct utsname my_utsname;
+@@ -1431,6 +1442,45 @@ void mnts_put_expire_list(struct list_head *mnts)
+       mnts_hash_mutex_unlock();
+ }
++struct tree_node *tree_mapent_root(struct mapent *me)
++{
++      return tree_root(tree_mapent_ops, me);
++}
++
++static struct tree_node *tree_mapent_new(void *ptr)
++{
++      struct tree_node *n = MAPENT_NODE(ptr);
++
++      n->ops = tree_mapent_ops;
++      n->left = NULL;
++      n->right = NULL;
++
++      return n;
++}
++
++static int tree_mapent_cmp(struct tree_node *n, void *ptr)
++{
++      struct mapent *n_me = MAPENT(n);
++      size_t n_me_len = n_me->len;
++      struct mapent *me = ptr;
++      size_t me_len = me->len;
++
++      if (strncmp(me->key, n_me->key, n_me_len) == 0) {
++              if (me_len < n_me_len)
++                      return -1;
++              else if (me_len > n_me_len)
++                      return 1;
++      }
++      return strcmp(me->key, n_me->key);
++}
++
++static void tree_mapent_free(struct tree_node *n)
++{
++      n->ops = NULL;
++      n->left = NULL;
++      n->right = NULL;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-missing-description-of-null-map-option.patch b/archive-patches/autofs5/autofs-5.1.7-add-missing-description-of-null-map-option.patch
new file mode 100644 (file)
index 0000000..93c7cdb
--- /dev/null
@@ -0,0 +1,55 @@
+autofs-5.1.7 - add missing desciption of null map option
+
+From: Ian Kent <raven@themaw.net>
+
+The description of how the -null master map option behaves is
+mising from auto.master(5).
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG            |    1 +
+ man/auto.master.5.in |   19 +++++++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index b29d2ed8..f5f0da76 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -76,6 +76,7 @@
+ - eliminate redundant cache lookup in tree_mapent_add_node().
+ - fix hosts map offset order.
+ - fix direct mount deadlock.
++- add missing description of null map option.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/man/auto.master.5.in b/man/auto.master.5.in
+index 72fbfd23..16717015 100644
+--- a/man/auto.master.5.in
++++ b/man/auto.master.5.in
+@@ -265,6 +265,25 @@ accessing /net/myserver will mount exports from myserver on directories below
+ NOTE: mounts done from a hosts map will be mounted with the "nosuid,nodev" options
+ unless overridden by explicitly specifying the "suid", "dev" options in the
+ master map entry.
++.SH BUILTIN MAP \-null
++If "\-null" is given as the map it is used to tell automount(8) to ignore a subsequent
++master map entry with the given path.
++.P
++It can only be used for paths that appear in the master map (or in direct mount maps).
++.P
++An indirect mount map top level mount point path can be nulled. If so no mounts from
++the nulled mount are performed (essentially it isn't mounted).
++.P
++Direct mount map path entries can be nulled. Since they must be present at startup
++they are (notionally) part of the master map.
++.P
++A nulled master map entry path will ignore a single subsequent matching entry. Any
++matching entry following that will be treated as it normally would be. An example
++use of this is allowing local master map entries to override remote ones.
++.P
++NOTE: If a duplicate master map entry path is seen (excluding paths of null entries)
++it will be ignored and noted in the log, that is the first encountered master map
++entry is used unless there is a corresponding null entry.
+ .SH LDAP MAPS
+ If the map type \fBldap\fP is specified the mapname is of the form
+ \fB[//servername/]dn\fP, where the optional \fBservername\fP is
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-missing-free-in-handle_mounts.patch b/archive-patches/autofs5/autofs-5.1.7-add-missing-free-in-handle_mounts.patch
new file mode 100644 (file)
index 0000000..288e200
--- /dev/null
@@ -0,0 +1,42 @@
+autofs-5.1.7 - add missing free in handle_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: error[doubleFree]: Memory pointed to by 'root' is freed twice
+
+No it's not, but root isn't freed before the fatal call which crashes
+automount so add a free() before the fatal() call.
+
+It appears Coverity doesn't recognise pthread_exit() as an exit condition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    2 ++
+ 2 files changed, 3 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 9c3ede45..62a918a9 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -50,6 +50,7 @@
+ - check for offset with no mount location.
+ - remove mounts_mutex.
+ - remove unused variable from get_exports().
++- add missing free in handle_mounts().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 28c4d1ee..48472d5f 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -1922,6 +1922,8 @@ void *handle_mounts(void *arg)
+       status = pthread_mutex_lock(&suc->mutex);
+       if (status) {
+               logerr("failed to lock startup condition mutex!");
++              if (root)
++                      free(root);
+               fatal(status);
+       }
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-mount-and-umount-offsets-functions.patch b/archive-patches/autofs5/autofs-5.1.7-add-mount-and-umount-offsets-functions.patch
new file mode 100644 (file)
index 0000000..ffac797
--- /dev/null
@@ -0,0 +1,310 @@
+autofs-5.1.7 - add mount and umount offsets functions
+
+From: Ian Kent <raven@themaw.net>
+
+Add tree_mapent_mount_offsets() and tree_mapent_umount_offsets() to
+the mapent tree handling implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 
+ include/mounts.h |    2 
+ lib/mounts.c     |  260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 263 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 0bd6f181..892f7581 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -39,6 +39,7 @@
+ - fix mount_fullpath().
+ - add tree_mapent_cleanup_offsets().
+ - add set_offset_tree_catatonic().
++- add mount and umount offsets functions.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/mounts.h b/include/mounts.h
+index 5441ee0e..e56f80ba 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -172,6 +172,8 @@ struct tree_node *tree_mapent_root(struct mapent *me);
+ int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ void tree_mapent_cleanup_offsets(struct mapent *oe);
++int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict);
++int tree_mapent_umount_offsets(struct mapent *oe, int nonstrict);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index f075a27e..f7c29475 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1692,6 +1692,266 @@ void tree_mapent_cleanup_offsets(struct mapent *oe)
+       }
+ }
++static int tree_mapent_rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
++{
++      struct mapent *mm_root = MAPENT(MAPENT_ROOT(oe));
++      char *dir, *path;
++      unsigned int split;
++      int ret;
++
++      if (ap->type == LKP_DIRECT)
++              return rmdir_path(ap, oe->key, mm_root->dev);
++
++      dir = strdup(oe->key);
++
++      if (ap->flags & MOUNT_FLAG_GHOST)
++              split = ap->len + mm_root->len + 1;
++      else
++              split = ap->len;
++
++      dir[split] = '\0';
++      path = &dir[split + 1];
++
++      if (chdir(dir) == -1) {
++              error(ap->logopt, "failed to chdir to %s", dir);
++              free(dir);
++              return -1;
++      }
++
++      ret = rmdir_path(ap, path, ap->dev);
++
++      free(dir);
++
++      if (chdir("/") == -1)
++              error(ap->logopt, "failed to chdir to /");
++
++      return ret;
++}
++
++static int tree_mapent_mount_offset(struct mapent *oe, void *ptr)
++{
++      struct traverse_subtree_context *ctxt = ptr;
++      struct autofs_point *ap = ctxt->ap;
++      int ret;
++
++      debug(ap->logopt, "mount offset %s", oe->key);
++
++      ret = mount_autofs_offset(ap, oe);
++      if (ret < MOUNT_OFFSET_OK) {
++              if (ret != MOUNT_OFFSET_IGNORE) {
++                      warn(ap->logopt, "failed to mount offset");
++                      return 0;
++              } else {
++                      debug(ap->logopt,
++                            "ignoring \"nohide\" trigger %s", oe->key);
++                      /*
++                       * Ok, so we shouldn't modify the mapent but
++                       * mount requests are blocked at a point above
++                       * this and expire only uses the mapent key or
++                       * holds the cache write lock.
++                       */
++                      free(oe->mapent);
++                      oe->mapent = NULL;
++              }
++      }
++
++      return 1;
++}
++
++static int tree_mapent_umount_offset(struct mapent *oe, void *ptr)
++{
++      struct traverse_subtree_context *ctxt = ptr;
++      struct autofs_point *ap = ctxt->ap;
++      int ret = 1;
++
++      /*
++       * Check for and umount subtree offsets resulting from
++       * nonstrict mount fail.
++       */
++      ret = tree_mapent_umount_offsets(oe, ctxt->strict);
++      if (!ret)
++              return 0;
++
++      /*
++       * If an offset that has an active mount has been removed
++       * from the multi-mount we don't want to attempt to trigger
++       * mounts for it. Obviously this is because it has been
++       * removed, but less obvious is the potential strange
++       * behaviour that can result if we do try and mount it
++       * again after it's been expired. For example, if an NFS
++       * file system is no longer exported and is later umounted
++       * it can be mounted again without any error message but
++       * shows as an empty directory. That's going to confuse
++       * people for sure.
++       *
++       * If the mount cannot be umounted (the process is now
++       * using a stale mount) the offset needs to be invalidated
++       * so no further mounts will be attempted but the offset
++       * cache entry must remain so expires can continue to
++       * attempt to umount it. If the mount can be umounted and
++       * the offset is removed, at least for NFS we will get
++       * ESTALE errors when attempting list the directory.
++       */
++      if (oe->ioctlfd != -1 ||
++          is_mounted(oe->key, MNTS_REAL)) {
++              if (umount_ent(ap, oe->key) &&
++                  is_mounted(oe->key, MNTS_REAL)) {
++                      debug(ap->logopt,
++                            "offset %s has active mount, invalidate",
++                            oe->key);
++                      /*
++                       * Ok, so we shouldn't modify the mapent but
++                       * mount requests are blocked at a point above
++                       * this and expire only uses the mapent key or
++                       * holds the cache write lock.
++                       */
++                      if (oe->mapent) {
++                              free(oe->mapent);
++                              oe->mapent = NULL;
++                      }
++                      return 0;
++              }
++      }
++
++      /* Don't bother if there's noting to umount. */
++      if (!is_mounted(oe->key, MNTS_AUTOFS))
++              goto done;
++
++      debug(ap->logopt, "umount offset %s", oe->key);
++
++      if (umount_autofs_offset(ap, oe)) {
++              warn(ap->logopt, "failed to umount offset");
++              ret = 0;
++      } else {
++              struct stat st;
++              int ret;
++
++              if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
++                      goto done;
++
++              /*
++               * An error due to partial directory removal is
++               * ok so only try and remount the offset if the
++               * actual mount point still exists.
++               */
++              ret = tree_mapent_rmdir_path_offset(ap, oe);
++              if (ret == -1 && !stat(oe->key, &st)) {
++                      ret = tree_mapent_mount_offset(oe, ctxt);
++                      /* But we did origianlly create this */
++                      oe->flags |= MOUNT_FLAG_DIR_CREATED;
++              }
++      }
++done:
++      return ret;
++}
++
++static int tree_mapent_mount_offsets_work(struct tree_node *n, void *ptr)
++{
++      struct traverse_subtree_context *ctxt = ptr;
++      struct mapent *oe = MAPENT(n);
++      struct mapent *mm_root = MAPENT(MAPENT_ROOT(oe));
++      struct autofs_point *ap = ctxt->ap;
++      int ret;
++
++      if (!oe->mapent)
++              return 1;
++
++      /* Stale offset, no longer present in the mapent */
++      if (oe->age != mm_root->age) {
++              /* Best effort */
++              tree_mapent_umount_offset(oe, ctxt);
++              return 1;
++      }
++
++      ret = tree_mapent_mount_offset(oe, ctxt);
++
++      /*
++       * If re-constructing a multi-mount it's necessary to walk
++       * into nested mounts, unlike the usual "mount only what's
++       * needed as you go" behavior.
++       */
++      if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
++              if (oe->ioctlfd != -1 ||
++                  is_mounted(oe->key, MNTS_REAL))
++                      /* Best effort */
++                      tree_mapent_mount_offsets(oe, !ctxt->strict);
++      }
++
++      return ret;
++}
++
++int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict)
++{
++      struct tree_node *base = MAPENT_NODE(oe);
++      struct traverse_subtree_context ctxt = {
++              .ap = oe->mc->ap,
++              .base = base,
++              .strict = !nonstrict,
++      };
++
++      return tree_mapent_traverse_subtree(base,
++                              tree_mapent_mount_offsets_work, &ctxt);
++}
++
++static int tree_mapent_umount_offsets_work(struct tree_node *n, void *ptr)
++{
++      struct mapent *oe = MAPENT(n);
++
++      return tree_mapent_umount_offset(oe, ptr);
++}
++
++int tree_mapent_umount_offsets(struct mapent *oe, int nonstrict)
++{
++      struct tree_node *base = MAPENT_NODE(oe);
++      struct autofs_point *ap = oe->mc->ap;
++      struct traverse_subtree_context ctxt = {
++              .ap = ap,
++              .base = base,
++              .strict = !nonstrict,
++      };
++      int ret;
++
++      ret = tree_mapent_traverse_subtree(base,
++                              tree_mapent_umount_offsets_work, &ctxt);
++      if (ret && tree_mapent_is_root(oe)) {
++              char mp[PATH_MAX + 1];
++
++              /*
++               * The map entry cache stores mapent keys. For indirect
++               * mount maps they are single direcory components so when
++               * one of these keys is the root of a multi-mount the mount
++               * path must be constructed.
++               */
++              if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key)) {
++                      error(ap->logopt, "mount path is too long");
++                      return 0;
++              }
++
++              /*
++               * Special case.
++               * If we can't umount the root container then we can't
++               * delete the offsets from the cache and we need to put
++               * the offset triggers back.
++               */
++              if (is_mounted(mp, MNTS_REAL)) {
++                      info(ap->logopt, "unmounting dir = %s", mp);
++                      if (umount_ent(ap, mp) &&
++                          is_mounted(mp, MNTS_REAL)) {
++                              if (!tree_mapent_mount_offsets(oe, 1))
++                                      warn(ap->logopt,
++                                           "failed to remount offset triggers");
++                              return 0;
++                      }
++              }
++
++              /* check for mounted mount entry and remove it if found */
++              mnts_remove_mount(mp, MNTS_MOUNTED);
++
++      }
++
++      return ret;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-set_offset_tree_catatonic.patch b/archive-patches/autofs5/autofs-5.1.7-add-set_offset_tree_catatonic.patch
new file mode 100644 (file)
index 0000000..f243d5a
--- /dev/null
@@ -0,0 +1,50 @@
+autofs-5.1.7 - add set_offset_tree_catatonic()
+
+From: Ian Kent <raven@themaw.net>
+
+Add tree mapent support function set_offset_tree_catatonic().
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   15 +++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 89d4cfa0..0bd6f181 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -38,6 +38,7 @@
+ - add tree_mapent_traverse_subtree().
+ - fix mount_fullpath().
+ - add tree_mapent_cleanup_offsets().
++- add set_offset_tree_catatonic().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index ba573b9a..f075a27e 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2578,6 +2578,21 @@ static int set_mount_catatonic(struct autofs_point *ap, struct mapent *me, int i
+       return 0;
+ }
++static int set_offset_tree_catatonic_work(struct tree_node *n, void *ptr)
++{
++      struct mapent *me = MAPENT(n);
++      struct autofs_point *ap = me->mc->ap;
++
++      set_mount_catatonic(ap, me, me->ioctlfd);
++
++      return 1;
++}
++
++static void set_offset_tree_catatonic(struct autofs_point *ap, struct mapent *me)
++{
++      tree_traverse_inorder(MAPENT_ROOT(me), set_offset_tree_catatonic_work, NULL);
++}
++
+ static void set_multi_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+ {
+       if (!list_empty(&me->multi_list)) {
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-some-multi-mount-macros.patch b/archive-patches/autofs5/autofs-5.1.7-add-some-multi-mount-macros.patch
new file mode 100644 (file)
index 0000000..a0f152e
--- /dev/null
@@ -0,0 +1,552 @@
+autofs-5.1.7 - add some multi-mount macros
+
+From: Ian Kent <raven@themaw.net>
+
+Add convienience macros IS_MM() to check is a mapent is part of a
+multi-mount, IS_MM_ROOT() to check if a mapent is the root of a
+multi-mount tree and MM_ROOT() to return the multi-mount root mapent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                |    1 +
+ daemon/automount.c       |   14 +++++++-------
+ daemon/direct.c          |    6 +++---
+ daemon/lookup.c          |   10 +++++-----
+ include/automount.h      |    5 +++++
+ lib/cache.c              |   30 +++++++++++++++---------------
+ lib/mounts.c             |   14 +++++++-------
+ modules/lookup_file.c    |    4 ++--
+ modules/lookup_hosts.c   |    4 ++--
+ modules/lookup_ldap.c    |    4 ++--
+ modules/lookup_nisplus.c |    4 ++--
+ modules/lookup_program.c |    4 ++--
+ modules/lookup_sss.c     |    4 ++--
+ modules/lookup_yp.c      |    4 ++--
+ modules/parse_sun.c      |   12 ++++++------
+ 15 files changed, 63 insertions(+), 57 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 1bf20699..3ba748d7 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -28,6 +28,7 @@
+ - rename path to m_offset in update_offset_entry().
+ - don't pass root to do_mount_autofs_offset().
+ - rename tree implementation functions.
++- add some multi-mount macros.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 62530b6b..f4608fc9 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -545,27 +545,27 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+       if (me) {
+               mc = me->mc;
+-              is_mm_root = (me->multi == me);
++              is_mm_root = IS_MM_ROOT(me);
+       }
+       left = 0;
+-      if (me && me->multi) {
++      if (me && IS_MM(me)) {
+               char root[PATH_MAX + 1];
+               char key[PATH_MAX + 1];
+               struct mapent *tmp;
+               int status;
+               char *base;
+-              if (!strchr(me->multi->key, '/'))
++              if (!strchr(MM_ROOT(me)->key, '/'))
+                       /* Indirect multi-mount root */
+                       /* sprintf okay - if it's mounted, it's
+                        * PATH_MAX or less bytes */
+-                      sprintf(root, "%s/%s", ap->path, me->multi->key);
++                      sprintf(root, "%s/%s", ap->path, MM_ROOT(me)->key);
+               else
+-                      strcpy(root, me->multi->key);
++                      strcpy(root, MM_ROOT(me)->key);
+-              if (is_mm_root)
++              if (IS_MM_ROOT(me))
+                       base = NULL;
+               else
+                       base = me->key + strlen(root);
+@@ -588,7 +588,7 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+                       return 0;
+               }
+-              if (!left && is_mm_root) {
++              if (!left && IS_MM_ROOT(me)) {
+                       status = cache_delete_offset_list(mc, me->key);
+                       if (status != CHE_OK) {
+                               warn(ap->logopt, "couldn't delete offset list");
+diff --git a/daemon/direct.c b/daemon/direct.c
+index 5c1146a7..3f4f5704 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -686,7 +686,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
+                        * a mount that has been automatically mounted by
+                        * the kernel NFS client.
+                        */
+-                      if (me->multi != me &&
++                      if (!IS_MM_ROOT(me) &&
+                           is_mounted(me->key, MNTS_REAL))
+                               return MOUNT_OFFSET_IGNORE;
+@@ -1220,11 +1220,11 @@ static void *do_mount_direct(void *arg)
+                        * for direct mount multi-mounts with no real mount at
+                        * their base so they will be expired.
+                        */
+-                      if (close_fd && me == me->multi)
++                      if (close_fd && IS_MM_ROOT(me))
+                               close_fd = 0;
+                       if (!close_fd)
+                               me->ioctlfd = mt.ioctlfd;
+-                      if (me->multi && me->multi != me)
++                      if (IS_MM(me) && !IS_MM_ROOT(me))
+                               flags |= MNTS_OFFSET;
+               }
+               ops->send_ready(ap->logopt, mt.ioctlfd, mt.wait_queue_token);
+diff --git a/daemon/lookup.c b/daemon/lookup.c
+index 2fea0c0b..8c9a82b5 100644
+--- a/daemon/lookup.c
++++ b/daemon/lookup.c
+@@ -748,7 +748,7 @@ int lookup_ghost(struct autofs_point *ap, const char *root)
+                                       goto next;
+                               /* It's a busy multi-mount - leave till next time */
+-                              if (list_empty(&me->multi_list))
++                              if (IS_MM(me))
+                                       error(ap->logopt,
+                                             "invalid key %s", me->key);
+                               goto next;
+@@ -838,12 +838,12 @@ static int lookup_amd_instance(struct autofs_point *ap,
+       char *m_key;
+       me = cache_lookup_distinct(map->mc, name);
+-      if (!me || !me->multi) {
++      if (!me || !IS_MM(me)) {
+               error(ap->logopt, "expected multi mount entry not found");
+               return NSS_STATUS_UNKNOWN;
+       }
+-      m_key = malloc(strlen(ap->path) + strlen(me->multi->key) + 2);
++      m_key = malloc(strlen(ap->path) + strlen(MM_ROOT(me)->key) + 2);
+       if (!m_key) {
+               error(ap->logopt,
+                    "failed to allocate storage for search key");
+@@ -852,7 +852,7 @@ static int lookup_amd_instance(struct autofs_point *ap,
+       strcpy(m_key, ap->path);
+       strcat(m_key, "/");
+-      strcat(m_key, me->multi->key);
++      strcat(m_key, MM_ROOT(me)->key);
+       mnt = mnts_find_amdmount(m_key);
+       free(m_key);
+@@ -1355,7 +1355,7 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti
+                        * created on demand and managed by expire and don't
+                        * prune the multi-map owner map entry.
+                        */
+-                      if (*me->key == '/' || me->multi == me) {
++                      if (*me->key == '/' || IS_MM_ROOT(me)) {
+                               me = cache_enumerate(mc, me);
+                               continue;
+                       }
+diff --git a/include/automount.h b/include/automount.h
+index fa6f5d63..e917515b 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -183,6 +183,11 @@ struct mapent {
+       ino_t ino;
+ };
++#define IS_MM(me)     (me->multi)
++#define IS_MM_ROOT(me)        (me->multi == me)
++#define MM_ROOT(me)   (me->multi)
++#define MM_PARENT(me) (me->parent)
++
+ void cache_lock_cleanup(void *arg);
+ void cache_readlock(struct mapent_cache *mc);
+ void cache_writelock(struct mapent_cache *mc);
+diff --git a/lib/cache.c b/lib/cache.c
+index a90bbb1d..1d9f5cc7 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -374,7 +374,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
+               while (me) {
+                       /* Multi mount entries are not primary */
+-                      if (me->multi && me->multi != me) {
++                      if (IS_MM(me) && !IS_MM_ROOT(me)) {
+                               me = me->next;
+                               continue;
+                       }
+@@ -397,7 +397,7 @@ struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
+       this = me->next;
+       while (this) {
+               /* Multi mount entries are not primary */
+-              if (this->multi && this->multi != this) {
++              if (IS_MM(this) && !IS_MM_ROOT(this)) {
+                       this = this->next;
+                       continue;
+               }
+@@ -413,7 +413,7 @@ struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
+                       while (this) {
+                               /* Multi mount entries are not primary */
+-                              if (this->multi && this->multi != this) {
++                              if (IS_MM(this) && !IS_MM_ROOT(this)) {
+                                       this = this->next;
+                                       continue;
+                               }
+@@ -435,7 +435,7 @@ struct mapent *cache_lookup_key_next(struct mapent *me)
+       next = me->next;
+       while (next) {
+               /* Multi mount entries are not primary */
+-              if (me->multi && me->multi != me)
++              if (IS_MM(me) && !IS_MM_ROOT(me))
+                       continue;
+               if (!strcmp(me->key, next->key))
+                       return next;
+@@ -706,7 +706,7 @@ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *k
+       me = cache_lookup_distinct(mc, key);
+       if (me) {
+               cache_add_ordered_offset(me, &owner->multi_list);
+-              me->multi = owner;
++              MM_ROOT(me) = owner;
+               goto done;
+       }
+       ret = CHE_FAIL;
+@@ -814,14 +814,14 @@ int cache_set_offset_parent(struct mapent_cache *mc, const char *offset)
+       this = cache_lookup_distinct(mc, offset);
+       if (!this)
+               return 0;
+-      if (!this->multi)
++      if (!IS_MM(this))
+               return 0;
+       parent = get_offset_parent(mc, offset);
+       if (parent)
+               this->parent = parent;
+       else
+-              this->parent = this->multi;
++              this->parent = MM_ROOT(this);
+       return 1;
+ }
+@@ -879,7 +879,7 @@ int cache_delete_offset(struct mapent_cache *mc, const char *key)
+               return CHE_FAIL;
+       if (strcmp(key, me->key) == 0) {
+-              if (me->multi && me->multi == me)
++              if (IS_MM(me) && IS_MM_ROOT(me))
+                       return CHE_FAIL;
+               mc->hash[hashval] = me->next;
+               goto delete;
+@@ -889,7 +889,7 @@ int cache_delete_offset(struct mapent_cache *mc, const char *key)
+               pred = me;
+               me = me->next;
+               if (strcmp(key, me->key) == 0) {
+-                      if (me->multi && me->multi == me)
++                      if (IS_MM(me) && IS_MM_ROOT(me))
+                               return CHE_FAIL;
+                       pred->next = me->next;
+                       goto delete;
+@@ -927,7 +927,7 @@ int cache_delete(struct mapent_cache *mc, const char *key)
+               me = me->next;
+               if (strcmp(key, me->key) == 0) {
+                       struct stack *s = me->stack;
+-                      if (me->multi && !list_empty(&me->multi_list)) {
++                      if (IS_MM(me)) {
+                               ret = CHE_FAIL;
+                               goto done;
+                       }
+@@ -956,7 +956,7 @@ int cache_delete(struct mapent_cache *mc, const char *key)
+       if (strcmp(key, me->key) == 0) {
+               struct stack *s = me->stack;
+-              if (me->multi && !list_empty(&me->multi_list)) {
++              if (IS_MM(me)) {
+                       ret = CHE_FAIL;
+                       goto done;
+               }
+@@ -995,7 +995,7 @@ int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
+               return CHE_FAIL;
+       /* Not offset list owner */
+-      if (me->multi != me)
++      if (!IS_MM_ROOT(me))
+               return CHE_FAIL;
+       head = &me->multi_list;
+@@ -1016,13 +1016,13 @@ int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
+               this = list_entry(next, struct mapent, multi_list);
+               next = next->next;
+               list_del_init(&this->multi_list);
+-              this->multi = NULL;
++              MM_ROOT(this) = NULL;
+               debug(logopt, "deleting offset key %s", this->key);
+               status = cache_delete(mc, this->key);
+               if (status == CHE_FAIL) {
+                       warn(logopt,
+                            "failed to delete offset %s", this->key);
+-                      this->multi = me;
++                      MM_ROOT(this) = me;
+                       /* TODO: add list back in */
+                       remain++;
+               }
+@@ -1030,7 +1030,7 @@ int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
+       if (!remain) {
+               list_del_init(&me->multi_list);
+-              me->multi = NULL;
++              MM_ROOT(me) = NULL;
+       }
+       if (remain)
+diff --git a/lib/mounts.c b/lib/mounts.c
+index f5b905a6..f6f20fc0 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2163,7 +2163,7 @@ int try_remount(struct autofs_point *ap, struct mapent *me, unsigned int type)
+       } else {
+               me->flags &= ~MOUNT_FLAG_DIR_CREATED;
+               if (type == t_offset) {
+-                      if (!is_mounted(me->parent->key, MNTS_REAL))
++                      if (!is_mounted(MM_PARENT(me)->key, MNTS_REAL))
+                               me->flags |= MOUNT_FLAG_DIR_CREATED;
+               }
+       }
+@@ -2310,7 +2310,7 @@ void set_indirect_mount_tree_catatonic(struct autofs_point *ap)
+                               goto next;
+                       /* Only need to set offset mounts catatonic */
+-                      if (me->multi && me->multi == me)
++                      if (IS_MM(me) && IS_MM_ROOT(me))
+                               set_multi_mount_tree_catatonic(ap, me);
+ next:
+                       me = cache_enumerate(mc, me);
+@@ -2330,7 +2330,7 @@ next:
+ void set_direct_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+ {
+       /* Set offset mounts catatonic for this mapent */
+-      if (me->multi && me->multi == me)
++      if (IS_MM(me) && IS_MM_ROOT(me))
+               set_multi_mount_tree_catatonic(ap, me);
+       set_mount_catatonic(ap, me, me->ioctlfd);
+ }
+@@ -2490,12 +2490,12 @@ static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+       int ret;
+       if (ap->type == LKP_DIRECT)
+-              return rmdir_path(ap, oe->key, oe->multi->dev);
++              return rmdir_path(ap, oe->key, MM_ROOT(oe)->dev);
+       dir = strdup(oe->key);
+       if (ap->flags & MOUNT_FLAG_GHOST)
+-              split = strlen(ap->path) + strlen(oe->multi->key) + 1;
++              split = strlen(ap->path) + strlen(MM_ROOT(oe)->key) + 1;
+       else
+               split = strlen(ap->path);
+@@ -2690,7 +2690,7 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+               oe = cache_lookup_distinct(me->mc, key);
+               if (!oe || !oe->mapent)
+                       goto cont;
+-              if (oe->age != me->multi->age) {
++              if (oe->age != MM_ROOT(me)->age) {
+                       /* Best effort */
+                       do_umount_offset(ap, oe, root, start);
+                       goto cont;
+@@ -2724,7 +2724,7 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+       left = do_umount_multi_triggers(ap, me, root, start, base);
+-      if (!left && me->multi == me) {
++      if (!left && IS_MM_ROOT(me)) {
+               /*
+                * Special case.
+                * If we can't umount the root container then we can't
+diff --git a/modules/lookup_file.c b/modules/lookup_file.c
+index f46a04f0..6afc5587 100644
+--- a/modules/lookup_file.c
++++ b/modules/lookup_file.c
+@@ -1199,8 +1199,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+               cache_readlock(mc);
+               me = cache_lookup_distinct(mc, key);
+-              if (me && me->multi)
+-                      lkp_key = strdup(me->multi->key);
++              if (me && IS_MM(me))
++                      lkp_key = strdup(MM_ROOT(me)->key);
+               else if (!ap->pref)
+                       lkp_key = strdup(key);
+               else {
+diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
+index c1ebb7f6..7e101ddb 100644
+--- a/modules/lookup_hosts.c
++++ b/modules/lookup_hosts.c
+@@ -177,7 +177,7 @@ static void update_hosts_mounts(struct autofs_point *ap,
+       me = cache_lookup_first(mc);
+       while (me) {
+               /* Hosts map entry not yet expanded or already expired */
+-              if (!me->multi)
++              if (!IS_MM(me))
+                       goto next;
+               debug(ap->logopt, MODPREFIX "get list of exports for %s", me->key);
+@@ -200,7 +200,7 @@ next:
+                * Hosts map entry not yet expanded, already expired
+                * or not the base of the tree
+                */
+-              if (!me->multi || me->multi != me)
++              if (!IS_MM(me) || !IS_MM_ROOT(me))
+                       goto cont;
+               debug(ap->logopt, MODPREFIX
+diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
+index 3624dd86..3e43fc01 100644
+--- a/modules/lookup_ldap.c
++++ b/modules/lookup_ldap.c
+@@ -3700,8 +3700,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+       if (ap->type == LKP_INDIRECT && *key != '/') {
+               cache_readlock(mc);
+               me = cache_lookup_distinct(mc, key);
+-              if (me && me->multi)
+-                      lkp_key = strdup(me->multi->key);
++              if (me && IS_MM(me))
++                      lkp_key = strdup(MM_ROOT(me)->key);
+               else if (!ap->pref)
+                       lkp_key = strdup(key);
+               else {
+diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
+index cbd03cdb..6e9a85d1 100644
+--- a/modules/lookup_nisplus.c
++++ b/modules/lookup_nisplus.c
+@@ -722,8 +722,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+       if (ap->type == LKP_INDIRECT && *key != '/') {
+               cache_readlock(mc);
+               me = cache_lookup_distinct(mc, key);
+-              if (me && me->multi)
+-                      lkp_key = strdup(me->multi->key);
++              if (me && IS_MM(me))
++                      lkp_key = strdup(MM_ROOT(me)->key);
+               else if (!ap->pref)
+                       lkp_key = strdup(key);
+               else {
+diff --git a/modules/lookup_program.c b/modules/lookup_program.c
+index ca209488..70f27545 100644
+--- a/modules/lookup_program.c
++++ b/modules/lookup_program.c
+@@ -646,7 +646,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+                                name_len, ent, ctxt->parse->context);
+                       goto out_free;
+               } else {
+-                      if (me->multi && me->multi != me) {
++                      if (IS_MM(me) && !IS_MM_ROOT(me)) {
+                               cache_unlock(mc);
+                               warn(ap->logopt, MODPREFIX
+                                    "unexpected lookup for active multi-mount"
+@@ -657,7 +657,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+                       cache_writelock(mc);
+                       me = cache_lookup_distinct(mc, name);
+                       if (me) {
+-                              if (me->multi)
++                              if (IS_MM(me))
+                                       cache_delete_offset_list(mc, name);
+                               cache_delete(mc, name);
+                       }
+diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c
+index ccd605af..ad834626 100644
+--- a/modules/lookup_sss.c
++++ b/modules/lookup_sss.c
+@@ -1055,8 +1055,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+               cache_readlock(mc);
+               me = cache_lookup_distinct(mc, key);
+-              if (me && me->multi)
+-                      lkp_key = strdup(me->multi->key);
++              if (me && IS_MM(me))
++                      lkp_key = strdup(MM_ROOT(me)->key);
+               else
+                       lkp_key = strdup(key);
+               cache_unlock(mc);
+diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
+index 38f75497..8bccb72f 100644
+--- a/modules/lookup_yp.c
++++ b/modules/lookup_yp.c
+@@ -826,8 +826,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+         if (ap->type == LKP_INDIRECT && *key != '/') {
+               cache_readlock(mc);
+               me = cache_lookup_distinct(mc, key);
+-              if (me && me->multi)
+-                      lkp_key = strdup(me->multi->key);
++              if (me && IS_MM(me))
++                      lkp_key = strdup(MM_ROOT(me)->key);
+               else if (!ap->pref)
+                       lkp_key = strdup(key);
+               else {
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 34d4441e..b11c6693 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1148,7 +1148,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+       rv = 0;
+-      mm_key = me->multi->key;
++      mm_key = MM_ROOT(me)->key;
+       if (*mm_key == '/') {
+               mm_root = mm_key;
+@@ -1162,7 +1162,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+       }
+       mm_root_len = strlen(mm_root);
+-      if (me == me->multi) {
++      if (IS_MM_ROOT(me)) {
+               char key[PATH_MAX + 1];
+               if (mm_root_len + 1 > PATH_MAX) {
+@@ -1179,7 +1179,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+               /* Mount root offset if it exists */
+               ro = cache_lookup_distinct(me->mc, key);
+-              if (ro && ro->age == me->multi->age) {
++              if (ro && ro->age == MM_ROOT(me)->age) {
+                       char *myoptions, *ro_loc;
+                       int namelen = name ? strlen(name) : 0;
+                       int ro_len;
+@@ -1350,7 +1350,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
+       if (*name == '/') {
+               cache_readlock(mc);
+               me = cache_lookup_distinct(mc, name);
+-              if (me && me->multi && me->multi != me) {
++              if (me && IS_MM(me) && !IS_MM_ROOT(me)) {
+                       cache_unlock(mc);
+                       mapent_len = strlen(mapent) + 1;
+                       pmapent = malloc(mapent_len + 1);
+@@ -1505,7 +1505,7 @@ dont_expand:
+               }
+               /* So we know we're the multi-mount root */
+-              if (!me->multi)
++              if (!IS_MM(me))
+                       me->multi = me;
+               else {
+                       /*
+@@ -1630,7 +1630,7 @@ dont_expand:
+                */
+               cache_readlock(mc);
+               if (*name == '/' &&
+-                 (me = cache_lookup_distinct(mc, name)) && me->multi) {
++                 (me = cache_lookup_distinct(mc, name)) && IS_MM(me)) {
+                       cache_unlock(mc);
+                       loc = strdup(p);
+                       if (!loc) {
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_add_node.patch b/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_add_node.patch
new file mode 100644 (file)
index 0000000..11f598c
--- /dev/null
@@ -0,0 +1,133 @@
+autofs-5.1.7 - add tree_mapent_add_node()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_add_node() to the mapent tree handling
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    1 +
+ include/mounts.h    |    1 +
+ lib/cache.c         |    5 ++---
+ lib/mounts.c        |   47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 52 insertions(+), 3 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 8841f72f..85730eda 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -33,6 +33,7 @@
+ - add a len field to struct autofs_point.
+ - make tree implementation data independent.
+ - add mapent tree implementation.
++- add tree_mapent_add_node().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/automount.h b/include/automount.h
+index ebc2007f..f6023e27 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -216,6 +216,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age);
+ int cache_lookup_negative(struct mapent *me, const char *key);
+ void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout);
++struct mapent *cache_get_offset_parent(struct mapent_cache *mc, const char *key);
+ int cache_set_offset_parent(struct mapent_cache *mc, const char *offset);
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+diff --git a/include/mounts.h b/include/mounts.h
+index fd7c6183..a0e60e24 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -169,6 +169,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
++int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+diff --git a/lib/cache.c b/lib/cache.c
+index 6dfaeff5..7c409a56 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -749,8 +749,7 @@ void cache_update_negative(struct mapent_cache *mc,
+ }
+-static struct mapent *get_offset_parent(struct mapent_cache *mc,
+-                                      const char *key)
++struct mapent *cache_get_offset_parent(struct mapent_cache *mc, const char *key)
+ {
+       struct mapent *me;
+       char *parent, *tail;
+@@ -796,7 +795,7 @@ int cache_set_offset_parent(struct mapent_cache *mc, const char *offset)
+       if (!IS_MM(this))
+               return 0;
+-      parent = get_offset_parent(mc, offset);
++      parent = cache_get_offset_parent(mc, offset);
+       if (parent)
+               this->parent = parent;
+       else
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 40ebf9cf..a0bf3d52 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1481,6 +1481,53 @@ static void tree_mapent_free(struct tree_node *n)
+       n->right = NULL;
+ }
++int tree_mapent_add_node(struct mapent_cache *mc,
++                       const char *root, const char *key)
++{
++      unsigned int logopt = mc->ap->logopt;
++      struct tree_node *tree, *n;
++      struct mapent *base;
++      struct mapent *parent;
++      struct mapent *me;
++
++      base = cache_lookup_distinct(mc, root);
++      if (!base) {
++              error(logopt,
++                   "failed to find multi-mount root for key %s", key);
++              return 0;
++      }
++
++      if (MAPENT_ROOT(base) != MAPENT_NODE(base)) {
++              error(logopt,
++                   "failed to find multi-mount root of offset tree",
++                   key);
++              return 0;
++      }
++      tree = MAPENT_ROOT(base);
++
++      me = cache_lookup_distinct(mc, key);
++      if (!me) {
++              error(logopt,
++                   "failed to find key %s of multi-mount", key);
++              return 0;
++      }
++
++      n = tree_add_node(tree, me);
++      if (!n)
++              return 0;
++
++      MAPENT_SET_ROOT(me, tree)
++
++      /* Set the subtree parent */
++      parent = cache_get_offset_parent(mc, key);
++      if (!parent)
++              MAPENT_SET_PARENT(me, tree)
++      else
++              MAPENT_SET_PARENT(me, MAPENT_NODE(parent))
++
++      return 1;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch b/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch
new file mode 100644 (file)
index 0000000..2a57e9f
--- /dev/null
@@ -0,0 +1,94 @@
+autofs-5.1.7 - add tree_mapent_cleanup_offsets()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_cleanup_offsets() to the mapent tree handling
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ include/mounts.h |    1 +
+ lib/mounts.c     |   45 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 47 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index e2fd532c..89d4cfa0 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -37,6 +37,7 @@
+ - add tree_mapent_delete_offsets().
+ - add tree_mapent_traverse_subtree().
+ - fix mount_fullpath().
++- add tree_mapent_cleanup_offsets().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/mounts.h b/include/mounts.h
+index b5a1193b..5441ee0e 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -171,6 +171,7 @@ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned
+ struct tree_node *tree_mapent_root(struct mapent *me);
+ int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
++void tree_mapent_cleanup_offsets(struct mapent *oe);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 497c28c9..ba573b9a 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1647,6 +1647,51 @@ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key)
+       return 1;
+ }
++static void tree_mapent_umount_mount(struct autofs_point *ap, const char *mp)
++{
++      if (is_mounted(mp, MNTS_ALL)) {
++              if (umount(mp)) {
++                      error(ap->logopt, "error recovering from mount fail");
++                      error(ap->logopt, "cannot umount %s", mp);
++              }
++      }
++}
++
++static int tree_mapent_cleanup_offsets_work(struct tree_node *n, void *ptr)
++{
++      struct mapent *oe = MAPENT(n);
++      struct traverse_subtree_context *ctxt = ptr;
++
++      tree_mapent_umount_mount(ctxt->ap, oe->key);
++
++      return 1;
++}
++
++void tree_mapent_cleanup_offsets(struct mapent *oe)
++{
++      struct tree_node *base = MAPENT_NODE(oe);
++      struct traverse_subtree_context ctxt = {
++              .ap = oe->mc->ap,
++              .base = base,
++              .strict = 0,
++      };
++      struct autofs_point *ap = oe->mc->ap;
++
++      tree_mapent_traverse_subtree(base, tree_mapent_cleanup_offsets_work, &ctxt);
++
++      /* Cleanup base mount after offsets have been cleaned up */
++      if (*oe->key == '/')
++              tree_mapent_umount_mount(ap, oe->key);
++      else {
++              char mp[PATH_MAX + 1];
++
++              if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key))
++                      error(ap->logopt, "mount path is too long");
++              else
++                      tree_mapent_umount_mount(ap, mp);
++      }
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_delete_offsets.patch b/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_delete_offsets.patch
new file mode 100644 (file)
index 0000000..6d228ec
--- /dev/null
@@ -0,0 +1,119 @@
+autofs-5.1.7 - add tree_mapent_delete_offsets()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_delete_offsets() to the mapent tree handling
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ include/mounts.h |    1 +
+ lib/mounts.c     |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 72 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 85730eda..488b4996 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -34,6 +34,7 @@
+ - make tree implementation data independent.
+ - add mapent tree implementation.
+ - add tree_mapent_add_node().
++- add tree_mapent_delete_offsets().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/mounts.h b/include/mounts.h
+index a0e60e24..b5a1193b 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -170,6 +170,7 @@ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+ int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
++int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index a0bf3d52..eb700c79 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1528,6 +1528,76 @@ int tree_mapent_add_node(struct mapent_cache *mc,
+       return 1;
+ }
++static int tree_mapent_delete_offset_tree(struct tree_node *root)
++{
++      struct mapent *me = MAPENT(root);
++      unsigned int logopt = me->mc->ap->logopt;
++      int ret = CHE_OK;
++
++      if (root->left) {
++              ret = tree_mapent_delete_offset_tree(root->left);
++              if (!ret)
++                      return 0;
++              root->left = NULL;
++      }
++      if (root->right) {
++              ret = tree_mapent_delete_offset_tree(root->right);
++              if (!ret)
++                      return 0;
++              root->right = NULL;
++      }
++
++      /* Keep the owner of the multi-mount offset tree and clear
++       * the root and parent when done.
++       */
++      if (MAPENT_ROOT(me) != MAPENT_NODE(me)) {
++              struct tree_node *root = MAPENT_ROOT(me);
++
++              debug(logopt, "deleting offset key %s", me->key);
++
++              /* cache_delete won't delete an active offset */
++              MAPENT_SET_ROOT(me, NULL);
++              ret = cache_delete(me->mc, me->key);
++              if (ret != CHE_OK) {
++                      MAPENT_SET_ROOT(me, root);
++                      warn(logopt, "failed to delete offset %s", me->key);
++              }
++      } else {
++              MAPENT_SET_ROOT(me, NULL);
++              MAPENT_SET_PARENT(me, NULL);
++      }
++
++      return ret == CHE_OK ? 1 : 0;
++}
++
++int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key)
++{
++      unsigned int logopt = mc->ap->logopt;
++      struct mapent *me;
++
++      me = cache_lookup_distinct(mc, key);
++      if (!me) {
++              error(logopt,
++                   "failed to find multi-mount root for key %s", key);
++              return 0;
++      }
++
++      /* Not offset list owner */
++      if (MAPENT_ROOT(me) != MAPENT_NODE(me)) {
++              error(logopt,
++                   "mapent for key %s is not multi-mount owner", key);
++              return 0;
++      }
++
++      if (!tree_mapent_delete_offset_tree(MAPENT_ROOT(me))) {
++              error(logopt,
++                   "could not delete map entry offsets for key %s", key);
++              return 0;
++      }
++
++      return 1;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_traverse_subtree.patch b/archive-patches/autofs5/autofs-5.1.7-add-tree_mapent_traverse_subtree.patch
new file mode 100644 (file)
index 0000000..1e0ff93
--- /dev/null
@@ -0,0 +1,83 @@
+autofs-5.1.7 - add tree_mapent_traverse_subtree()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_traverse_subtree() that enumerates offsets from
+a given base node bounded by subtree nesting points.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 488b4996..390028ac 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -35,6 +35,7 @@
+ - add mapent tree implementation.
+ - add tree_mapent_add_node().
+ - add tree_mapent_delete_offsets().
++- add tree_mapent_traverse_subtree().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index eb700c79..fded4c09 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1528,6 +1528,53 @@ int tree_mapent_add_node(struct mapent_cache *mc,
+       return 1;
+ }
++static inline int tree_mapent_is_root(struct mapent *oe)
++{
++      /* Offset "/" is a special case, it's looked up and mounted
++       * seperately because the offset tree may or may not have a
++       * real mount at the base and the triggers inside it need to
++       * be mounted in either case. Also the order requires the
++       * offset at the top of the (sub)tree to be handled after
++       * the traversal.
++       */
++      return (oe->key[oe->len - 1] == '/' ||
++              MAPENT_ROOT(oe) == MAPENT_NODE(oe));
++}
++
++struct traverse_subtree_context {
++      struct autofs_point *ap;
++      struct tree_node *base;
++      int strict;
++};
++
++static int tree_mapent_traverse_subtree(struct tree_node *n, tree_work_fn_t work, void *ptr)
++{
++      struct traverse_subtree_context *ctxt = ptr;
++      struct mapent *oe = MAPENT(n);
++      int ret = 1;
++
++      if (n->left) {
++              ret = tree_mapent_traverse_subtree(n->left, work, ctxt);
++              if (!ret && ctxt->strict)
++                      goto done;
++      }
++
++      /* Node is not multi-mount root and is part of current subtree */
++      if (!tree_mapent_is_root(oe) && MAPENT_PARENT(oe) == ctxt->base) {
++              ret = work(n, ctxt);
++              if (!ret && ctxt->strict)
++                      goto done;
++      }
++
++      if (n->right) {
++              ret = tree_mapent_traverse_subtree(n->right, work, ctxt);
++              if (!ret && ctxt->strict)
++                      goto done;
++      }
++done:
++      return ret;
++}
++
+ static int tree_mapent_delete_offset_tree(struct tree_node *root)
+ {
+       struct mapent *me = MAPENT(root);
diff --git a/archive-patches/autofs5/autofs-5.1.7-add-xdr_exports.patch b/archive-patches/autofs5/autofs-5.1.7-add-xdr_exports.patch
new file mode 100644 (file)
index 0000000..80f7c12
--- /dev/null
@@ -0,0 +1,335 @@
+autofs-5.1.7 - add xdr_exports()
+
+From: Ian Kent <raven@themaw.net>
+
+Add an xdr_exports() function to get NFS exports from a server.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    3 +
+ include/rpc_subs.h     |   14 ++++++
+ lib/rpc_subs.c         |  120 +++++++++++++++++++++++++++++++++++-------------
+ modules/lookup_hosts.c |   25 +++-------
+ 4 files changed, 112 insertions(+), 50 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 2c48484b..84050e91 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -1,3 +1,6 @@
++
++- add xdr_exports().
++
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+ - update ldap READMEs and schema definitions.
+diff --git a/include/rpc_subs.h b/include/rpc_subs.h
+index 7ba4b93f..080f19d9 100644
+--- a/include/rpc_subs.h
++++ b/include/rpc_subs.h
+@@ -17,6 +17,7 @@
+ #define _RPC_SUBS_H
+ #include <rpc/rpc.h>
++#include <rpc/types.h>
+ #include <rpc/pmap_prot.h>
+ #include <linux/nfs.h>
+ #include <linux/nfs2.h>
+@@ -47,6 +48,17 @@
+ #define HOST_ENT_BUF_SIZE       2048
++struct hostinfo {
++      char *name;
++      struct hostinfo *next;
++};
++
++struct exportinfo {
++      char *dir;
++      struct hostinfo *hosts;
++      struct exportinfo *next;
++};
++
+ struct conn_info {
+       const char *host;
+       struct sockaddr *addr;
+@@ -71,6 +83,8 @@ int rpc_portmap_getport(struct conn_info *, struct pmap *, unsigned short *);
+ int rpc_ping_proto(struct conn_info *);
+ int rpc_ping(const char *, int, unsigned int, long, long, unsigned int);
+ double monotonic_elapsed(struct timespec, struct timespec);
++struct exportinfo *rpc_get_exports(const char *host, long seconds, long micros, unsigned int option);
++void rpc_exports_free(struct exportinfo *exports);
+ const char *get_addr_string(struct sockaddr *, char *, socklen_t);
+ #endif
+diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
+index 643b7687..7b8162b4 100644
+--- a/lib/rpc_subs.c
++++ b/lib/rpc_subs.c
+@@ -41,7 +41,6 @@ const rpcprog_t rpcb_prog = PMAPPROG;
+ const rpcvers_t rpcb_version = PMAPVERS;
+ #endif
+-#include "mount.h"
+ #include "rpc_subs.h"
+ #include "replicated.h"
+ #include "automount.h"
+@@ -58,6 +57,17 @@ const rpcvers_t rpcb_version = PMAPVERS;
+ #define MAX_NETWORK_LEN               255
++#define EXPPATHLEN 1024
++#define EXPNAMELEN 255
++
++#define MOUNTPROG 100005
++
++#define MOUNTVERS     1
++#define MOUNTVERS_NFSV3 3
++#define MOUNTVERS_POSIX 2
++
++#define MOUNTPROC_EXPORT 5
++
+ /* Get numeric value of the n bits starting at position p */
+ #define getbits(x, p, n)      ((x >> (p + 1 - n)) & ~(~0 << n))
+@@ -1102,7 +1112,55 @@ double monotonic_elapsed(struct timespec start, struct timespec end)
+       return t2 - t1;
+ }
+-static int rpc_get_exports_proto(struct conn_info *info, exports *exp)
++static bool_t xdr_host(XDR *xdrs, struct hostinfo *host)
++{
++      if (!xdr_string(xdrs, &host->name, EXPNAMELEN))
++              return FALSE;
++      return TRUE;
++}
++
++static bool_t xdr_hosts(XDR *xdrs, struct hostinfo **hosts)
++{
++      unsigned int size = sizeof(struct hostinfo);
++      char **host;
++
++      host = (char **) hosts;
++      while (1) {
++              if (!xdr_pointer(xdrs, host, size, (xdrproc_t) xdr_host))
++                      return FALSE;
++              if (!*host)
++                      break;
++              host = (char **) &((struct hostinfo *) *host)->next;
++      }
++      return TRUE;
++}
++
++static bool_t xdr_export(XDR *xdrs, struct exportinfo *export)
++{
++      if (!xdr_string(xdrs, &export->dir, EXPPATHLEN))
++              return FALSE;
++      if (!xdr_hosts(xdrs, &export->hosts))
++              return FALSE;
++      return TRUE;
++}
++
++bool_t xdr_exports(XDR *xdrs, struct exportinfo **exports)
++{
++      unsigned int size = sizeof(struct exportinfo);
++      char **export;
++
++      export = (char **) exports;
++      while (1) {
++              if (!xdr_pointer(xdrs, export, size, (xdrproc_t) xdr_export))
++                      return FALSE;
++              if (!*export)
++                      break;
++              export = (char **) &((struct exportinfo *) *export)->next;
++      }
++      return TRUE;
++}
++
++static int rpc_get_exports_proto(struct conn_info *info, struct exportinfo **exports)
+ {
+       CLIENT *client;
+       enum clnt_stat status;
+@@ -1133,7 +1191,7 @@ static int rpc_get_exports_proto(struct conn_info *info, exports *exp)
+       while (1) {
+               status = clnt_call(client, MOUNTPROC_EXPORT,
+                                (xdrproc_t) xdr_void, NULL,
+-                               (xdrproc_t) xdr_exports, (caddr_t) exp,
++                               (xdrproc_t) xdr_exports, (caddr_t) exports,
+                                info->timeout);
+               if (status == RPC_SUCCESS)
+                       break;
+@@ -1168,41 +1226,43 @@ static int rpc_get_exports_proto(struct conn_info *info, exports *exp)
+       return 1;
+ }
+-static void rpc_export_free(exports item)
++static void rpc_export_free(struct exportinfo *export)
+ {
+-      groups grp;
+-      groups tmp;
+-
+-      if (item->ex_dir)
+-              free(item->ex_dir);
+-
+-      grp = item->ex_groups;
+-      while (grp) {
+-              if (grp->gr_name)
+-                      free(grp->gr_name);
+-              tmp = grp;
+-              grp = grp->gr_next;
++      struct hostinfo *host, *tmp;
++
++      if (export->dir)
++              free(export->dir);
++
++      host = export->hosts;
++      while (host) {
++              if (host->name)
++                      free(host->name);
++              tmp = host;
++              host = host->next;
+               free(tmp);
+       }
+-      free(item);
++      free(export);
+ }
+-void rpc_exports_free(exports list)
++void rpc_exports_free(struct exportinfo *exports)
+ {
+-      exports tmp;
++      struct exportinfo *export, *tmp;
+-      while (list) {
+-              tmp = list;
+-              list = list->ex_next;
++      export = exports;
++      while (export) {
++              tmp = export;
++              export = export->next;
+               rpc_export_free(tmp);
+       }
+       return;
+ }
+-exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option)
++struct exportinfo *rpc_get_exports(const char *host,
++                                 long seconds, long micros,
++                                 unsigned int option)
+ {
+       struct conn_info info;
+-      exports exportlist;
++      struct exportinfo *exports = NULL;
+       struct pmap parms;
+       int status;
+@@ -1231,11 +1291,9 @@ exports rpc_get_exports(const char *host, long seconds, long micros, unsigned in
+       if (status < 0)
+               goto try_tcp;
+-      memset(&exportlist, '\0', sizeof(exportlist));
+-
+-      status = rpc_get_exports_proto(&info, &exportlist);
++      status = rpc_get_exports_proto(&info, &exports);
+       if (status)
+-              return exportlist;
++              return exports;
+ try_tcp:
+       info.proto = IPPROTO_TCP;
+@@ -1246,13 +1304,11 @@ try_tcp:
+       if (status < 0)
+               return NULL;
+-      memset(&exportlist, '\0', sizeof(exportlist));
+-
+-      status = rpc_get_exports_proto(&info, &exportlist);
++      status = rpc_get_exports_proto(&info, &exports);
+       if (!status)
+               return NULL;
+-      return exportlist;
++      return exports;
+ }
+ const char *get_addr_string(struct sockaddr *sa, char *name, socklen_t len)
+diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
+index 744062e2..81a4eb18 100644
+--- a/modules/lookup_hosts.c
++++ b/modules/lookup_hosts.c
+@@ -20,14 +20,6 @@
+ #include <sys/stat.h>
+ #include <netdb.h>
+-/* 
+- * Avoid annoying compiler noise by using an alternate name for
+- * typedef name in mount.h
+- */
+-#define name __dummy_type_name
+-#include "mount.h"
+-#undef name
+-
+ #define MODULE_LOOKUP
+ #include "automount.h"
+ #include "nsswitch.h"
+@@ -43,9 +35,6 @@ struct lookup_context {
+ int lookup_version = AUTOFS_LOOKUP_VERSION;   /* Required by protocol */
+-exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option);
+-void rpc_exports_free(exports list);
+-
+ int lookup_init(const char *mapfmt,
+               int argc, const char *const *argv, void **context)
+ {
+@@ -99,7 +88,7 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+ {
+       char buf[MAX_ERR_BUF];
+       char *mapent;
+-      exports exp, this;
++      struct exportinfo *exp, *this;
+       debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+@@ -111,7 +100,7 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+               if (mapent) {
+                       int len = strlen(mapent) + 1;
+-                      len += strlen(host) + 2*(strlen(this->ex_dir) + 2) + 3;
++                      len += strlen(host) + 2*(strlen(this->dir) + 2) + 3;
+                       mapent = realloc(mapent, len);
+                       if (!mapent) {
+                               char *estr;
+@@ -121,10 +110,10 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+                               return NULL;
+                       }
+                       strcat(mapent, " \"");
+-                      strcat(mapent, this->ex_dir);
++                      strcat(mapent, this->dir);
+                       strcat(mapent, "\"");
+               } else {
+-                      int len = 2*(strlen(this->ex_dir) + 2) + strlen(host) + 3;
++                      int len = 2*(strlen(this->dir) + 2) + strlen(host) + 3;
+                       mapent = malloc(len);
+                       if (!mapent) {
+@@ -135,16 +124,16 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+                               return NULL;
+                       }
+                       strcpy(mapent, "\"");
+-                      strcat(mapent, this->ex_dir);
++                      strcat(mapent, this->dir);
+                       strcat(mapent, "\"");
+               }
+               strcat(mapent, " \"");
+               strcat(mapent, host);
+               strcat(mapent, ":");
+-              strcat(mapent, this->ex_dir);
++              strcat(mapent, this->dir);
+               strcat(mapent, "\"");
+-              this = this->ex_next;
++              this = this->next;
+       }
+       rpc_exports_free(exp);
diff --git a/archive-patches/autofs5/autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch b/archive-patches/autofs5/autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch
new file mode 100644 (file)
index 0000000..062ecdc
--- /dev/null
@@ -0,0 +1,44 @@
+autofs-5.1.7 - cater for empty mounts list in mnts_get_expire_list()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: var_deref_model: Passing null pointer "tree" to
+         "tree_traverse_inorder", which dereferences it.
+
+This obviously can't happen but deal with it anyway to quiet Coverity.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    6 ++++--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index b79aebc8..b1b28888 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -64,6 +64,7 @@
+ - fix missing lock release in mount_subtree().
+ - fix double free in parse_mapent().
+ - refactor lookup_prune_one_cache() a bit.
++- cater for empty mounts list in mnts_get_expire_list().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 883e3743..3996eb5e 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1445,8 +1445,10 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+               }
+       }
+-      tree_traverse_inorder(tree, tree_mnt_expire_list_work, mnts);
+-      tree_free(tree);
++      if (tree) {
++              tree_traverse_inorder(tree, tree_mnt_expire_list_work, mnts);
++              tree_free(tree);
++      }
+ done:
+       mnts_hash_mutex_unlock();
+ }
diff --git a/archive-patches/autofs5/autofs-5.1.7-check-for-offset-with-no-mount-location.patch b/archive-patches/autofs5/autofs-5.1.7-check-for-offset-with-no-mount-location.patch
new file mode 100644 (file)
index 0000000..b2b8566
--- /dev/null
@@ -0,0 +1,50 @@
+autofs-5.1.7 - check for offset with no mount location
+
+From: Ian Kent <raven@themaw.net>
+
+Offsets need to have a mount location, check for it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   15 ++++++++++++++-
+ 2 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index a9209755..42914160 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -47,6 +47,7 @@
+ - pass root length to mount_fullpath().
+ - remove unused function master_submount_list_empty().
+ - move amd mounts removal into lib/mounts.c.
++- check for offset with no mount location.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index b1c2611c..a81d4028 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -801,7 +801,20 @@ update_offset_entry(struct autofs_point *ap,
+       memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+-      /* Internal hosts map may have loc == NULL */
++      if (!loc || !*loc) {
++              const char *type = ap->entry->maps->type;
++
++              /* If it's not the internal hosts map it must have a
++               * mount location.
++               */
++              if (!type || strcmp(type, "hosts")) {
++                      error(ap->logopt,
++                            MODPREFIX "syntax error in offset %s -> %s",
++                            m_offset, loc);
++                      return CHE_FAIL;
++              }
++      }
++
+       if (!*m_offset) {
+               error(ap->logopt,
+                     MODPREFIX "syntax error in offset %s -> %s", m_offset, loc);
diff --git a/archive-patches/autofs5/autofs-5.1.7-cleanup-cache_delete-a-little.patch b/archive-patches/autofs5/autofs-5.1.7-cleanup-cache_delete-a-little.patch
new file mode 100644 (file)
index 0000000..6697ce9
--- /dev/null
@@ -0,0 +1,64 @@
+autofs-5.1.7 - cleanup cache_delete() a little
+
+From: Ian Kent <raven@themaw.net>
+
+There's no reason to use local function storage for the passed in key
+just use the given key.
+
+Also, if there's no hash array entry for the key then there's no cache
+entry so don't return a fail for this case.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG   |    1 +
+ lib/cache.c |   11 +++--------
+ 2 files changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 6419052d..e822efec 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -24,6 +24,7 @@
+ - eliminate some strlen calls in offset handling.
+ - don't add offset mounts to mounted mounts table.
+ - reduce umount EBUSY check delay.
++- cleanup cache_delete() a little.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/cache.c b/lib/cache.c
+index 03d0499a..a90bbb1d 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -917,20 +917,15 @@ int cache_delete(struct mapent_cache *mc, const char *key)
+       struct mapent *me = NULL, *pred;
+       u_int32_t hashval = hash(key, mc->size);
+       int ret = CHE_OK;
+-      char this[PATH_MAX];
+-
+-      strcpy(this, key);
+       me = mc->hash[hashval];
+-      if (!me) {
+-              ret = CHE_FAIL;
++      if (!me)
+               goto done;
+-      }
+       while (me->next != NULL) {
+               pred = me;
+               me = me->next;
+-              if (strcmp(this, me->key) == 0) {
++              if (strcmp(key, me->key) == 0) {
+                       struct stack *s = me->stack;
+                       if (me->multi && !list_empty(&me->multi_list)) {
+                               ret = CHE_FAIL;
+@@ -959,7 +954,7 @@ int cache_delete(struct mapent_cache *mc, const char *key)
+       if (!me)
+               goto done;
+-      if (strcmp(this, me->key) == 0) {
++      if (strcmp(key, me->key) == 0) {
+               struct stack *s = me->stack;
+               if (me->multi && !list_empty(&me->multi_list)) {
+                       ret = CHE_FAIL;
diff --git a/archive-patches/autofs5/autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch b/archive-patches/autofs5/autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch
new file mode 100644 (file)
index 0000000..7e13642
--- /dev/null
@@ -0,0 +1,207 @@
+autofs-5.1.7 - don't add offset mounts to mounted mounts table
+
+From: Ian Kent <raven@themaw.net>
+
+Multi-mount offset mounts are added to the mounted mounts table whether
+they have a real mount or not. If there are a large number of offsets
+this can add unnecessary overhead to the mounted mounts table processing.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG         |    1 +
+ daemon/direct.c   |   14 ++++----------
+ daemon/indirect.c |    4 +++-
+ include/mounts.h  |    2 +-
+ lib/mounts.c      |   43 +++++++++++--------------------------------
+ 5 files changed, 20 insertions(+), 44 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index cb709773..b144f6aa 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -22,6 +22,7 @@
+ - remove unused mount offset list lock functions.
+ - eliminate count_mounts() from expire_proc_indirect().
+ - eliminate some strlen calls in offset handling.
++- don't add offset mounts to mounted mounts table.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/direct.c b/daemon/direct.c
+index 311a98ba..fbfebbdd 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -605,9 +605,6 @@ force_umount:
+       } else
+               info(ap->logopt, "umounted offset mount %s", me->key);
+-      if (!rv)
+-              mnts_remove_mount(me->key, MNTS_OFFSET);
+-
+       return rv;
+ }
+@@ -761,12 +758,6 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
+               notify_mount_result(ap, me->key, timeout, str_offset);
+       ops->close(ap->logopt, ioctlfd);
+-      mnt = mnts_add_mount(ap, me->key, MNTS_OFFSET);
+-      if (!mnt)
+-              error(ap->logopt,
+-                    "failed to add offset mount %s to mounted list",
+-                    me->key);
+-
+       debug(ap->logopt, "mounted trigger %s", me->key);
+       return MOUNT_OFFSET_OK;
+@@ -1214,6 +1205,7 @@ static void *do_mount_direct(void *arg)
+               struct mapent *me;
+               struct statfs fs;
+               unsigned int close_fd = 0;
++              unsigned int flags = MNTS_DIRECT|MNTS_MOUNTED;
+               sbmnt = mnts_find_submount(mt.name);
+               if (statfs(mt.name, &fs) == -1 ||
+@@ -1232,6 +1224,8 @@ static void *do_mount_direct(void *arg)
+                               close_fd = 0;
+                       if (!close_fd)
+                               me->ioctlfd = mt.ioctlfd;
++                      if (me->multi && me->multi != me)
++                              flags |= MNTS_OFFSET;
+               }
+               ops->send_ready(ap->logopt, mt.ioctlfd, mt.wait_queue_token);
+               cache_unlock(mt.mc);
+@@ -1240,7 +1234,7 @@ static void *do_mount_direct(void *arg)
+               info(ap->logopt, "mounted %s", mt.name);
+-              mnts_set_mounted_mount(ap, mt.name);
++              mnts_set_mounted_mount(ap, mt.name, flags);
+               conditional_alarm_add(ap, ap->exp_runfreq);
+       } else {
+diff --git a/daemon/indirect.c b/daemon/indirect.c
+index b259ebdc..eddcfff7 100644
+--- a/daemon/indirect.c
++++ b/daemon/indirect.c
+@@ -747,12 +747,14 @@ static void *do_mount_indirect(void *arg)
+       status = lookup_nss_mount(ap, NULL, mt.name, mt.len);
+       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
+       if (status) {
++              unsigned int flags = MNTS_INDIRECT|MNTS_MOUNTED;
++
+               ops->send_ready(ap->logopt,
+                               ap->ioctlfd, mt.wait_queue_token);
+               info(ap->logopt, "mounted %s", buf);
+-              mnts_set_mounted_mount(ap, mt.name);
++              mnts_set_mounted_mount(ap, mt.name, flags);
+               conditional_alarm_add(ap, ap->exp_runfreq);
+       } else {
+diff --git a/include/mounts.h b/include/mounts.h
+index e3022b23..ac480c06 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -131,7 +131,7 @@ struct mnt_list *get_mnt_list(const char *path, int include);
+ unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+-void mnts_set_mounted_mount(struct autofs_point *ap, const char *name);
++void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 04fe3d00..25ae2e1d 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1172,7 +1172,7 @@ struct mnt_list *mnts_add_mount(struct autofs_point *ap,
+       this = mnts_get_mount(mp);
+       if (this) {
+               this->flags |= flags;
+-              if (list_empty(&this->mount))
++              if ((this->flags & MNTS_MOUNTED) && list_empty(&this->mount))
+                       list_add(&this->mount, &ap->mounts);
+       }
+       mnts_hash_mutex_unlock();
+@@ -1193,42 +1193,23 @@ void mnts_remove_mount(const char *mp, unsigned int flags)
+       this = mnts_lookup(mp);
+       if (this && this->flags & flags) {
+               this->flags &= ~flags;
+-              if (!(this->flags & (MNTS_OFFSET|MNTS_MOUNTED)))
++              if (!(this->flags & MNTS_MOUNTED))
+                       list_del_init(&this->mount);
+               __mnts_put_mount(this);
+       }
+       mnts_hash_mutex_unlock();
+ }
+-void mnts_set_mounted_mount(struct autofs_point *ap, const char *name)
++void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags)
+ {
+       struct mnt_list *mnt;
+-      mnt = mnts_add_mount(ap, name, MNTS_MOUNTED);
++      mnt = mnts_add_mount(ap, name, flags);
+       if (!mnt) {
+               error(ap->logopt,
+                     "failed to add mount %s to mounted list", name);
+               return;
+       }
+-
+-      /* Offset mount failed but non-strict returns success */
+-      if (mnt->flags & MNTS_OFFSET &&
+-          !is_mounted(mnt->mp, MNTS_REAL)) {
+-              mnt->flags &= ~MNTS_MOUNTED;
+-              mnts_put_mount(mnt);
+-      }
+-
+-      /* Housekeeping.
+-       * Set the base type of the mounted mount.
+-       * MNTS_AUTOFS and MNTS_OFFSET are set at mount time and
+-       * are used during expire.
+-       */
+-      if (!(mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET))) {
+-              if (ap->type == LKP_INDIRECT)
+-                      mnt->flags |= MNTS_INDIRECT;
+-              else
+-                      mnt->flags |= MNTS_DIRECT;
+-      }
+ }
+ unsigned int mnts_has_mounted_mounts(struct autofs_point *ap)
+@@ -1947,17 +1928,13 @@ static int do_remount_direct(struct autofs_point *ap,
+       ret = lookup_nss_mount(ap, NULL, path, strlen(path));
+       if (ret) {
+-              struct mnt_list *mnt;
++              unsigned int flags = MNTS_DIRECT|MNTS_MOUNTED;
+               /* If it's an offset mount add a mount reference */
+-              if (type == t_offset) {
+-                      mnt = mnts_add_mount(ap, path, MNTS_OFFSET);
+-                      if (!mnt)
+-                              error(ap->logopt,
+-                                    "failed to add mount %s to mounted list", path);
+-              }
++              if (type == t_offset)
++                      flags |= MNTS_OFFSET;
+-              mnts_set_mounted_mount(ap, path);
++              mnts_set_mounted_mount(ap, path, flags);
+               info(ap->logopt, "re-connected to %s", path);
+@@ -2032,7 +2009,9 @@ static int do_remount_indirect(struct autofs_point *ap, const unsigned int type,
+               ret = lookup_nss_mount(ap, NULL, de[n]->d_name, len);
+               if (ret) {
+-                      mnts_set_mounted_mount(ap, buf);
++                      unsigned int flags = MNTS_INDIRECT|MNTS_MOUNTED;
++
++                      mnts_set_mounted_mount(ap, buf, flags);
+                       info(ap->logopt, "re-connected to %s", buf);
diff --git a/archive-patches/autofs5/autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch b/archive-patches/autofs5/autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch
new file mode 100644 (file)
index 0000000..333b6e4
--- /dev/null
@@ -0,0 +1,64 @@
+autofs-5.1.7 - don't pass root to do_mount_autofs_offset()
+
+From: Ian Kent <raven@themaw.net>
+
+The root parameter of do_mount_autofs_offset() is used only in a
+debug log message. It doesn't really add any value to debugging
+so remove it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    9 ++++-----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 0e9ca94f..2a07bd45 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -26,6 +26,7 @@
+ - reduce umount EBUSY check delay.
+ - cleanup cache_delete() a little.
+ - rename path to m_offset in update_offset_entry().
++- don't pass root to do_mount_autofs_offset().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 25ae2e1d..289500da 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2453,13 +2453,12 @@ out:
+       return rv;
+ }
+-static int do_mount_autofs_offset(struct autofs_point *ap,
+-                                struct mapent *oe, const char *root)
++static int do_mount_autofs_offset(struct autofs_point *ap, struct mapent *oe)
+ {
+       int mounted = 0;
+       int ret;
+-      debug(ap->logopt, "mount offset %s at %s", oe->key, root);
++      debug(ap->logopt, "mount offset %s", oe->key);
+       ret = mount_autofs_offset(ap, oe);
+       if (ret >= MOUNT_OFFSET_OK)
+@@ -2651,7 +2650,7 @@ static int do_umount_offset(struct autofs_point *ap,
+                */
+               ret = rmdir_path_offset(ap, oe);
+               if (ret == -1 && !stat(oe->key, &st)) {
+-                      ret = do_mount_autofs_offset(ap, oe, root);
++                      ret = do_mount_autofs_offset(ap, oe);
+                       if (ret)
+                               left++;
+                       /* But we did origianlly create this */
+@@ -2697,7 +2696,7 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+                       goto cont;
+               }
+-              mounted += do_mount_autofs_offset(ap, oe, root);
++              mounted += do_mount_autofs_offset(ap, oe);
+               /*
+                * If re-constructing a multi-mount it's necessary to walk
diff --git a/archive-patches/autofs5/autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch b/archive-patches/autofs5/autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch
new file mode 100644 (file)
index 0000000..d71cd3e
--- /dev/null
@@ -0,0 +1,45 @@
+autofs-5.1.7 - dont try umount after stat() ENOENT fail
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: Calling function "umount" that uses "me->key" after a check
+         function. This can cause a time-of-check, time-of-use race
+         condition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/direct.c |    6 +++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 7add6c55..c7bc0c39 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -57,6 +57,7 @@
+ - fix double unlock in parse_mount().
+ - add length check in umount_subtree_mounts().
+ - fix flags check in umount_multi().
++- dont try umount after stat() ENOENT fail.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/direct.c b/daemon/direct.c
+index a33f9f91..3bd714e6 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -739,9 +739,13 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
+       ret = stat(me->key, &st);
+       if (ret == -1) {
++              int save_errno = errno;
++
+               error(ap->logopt,
+                    "failed to stat direct mount trigger %s", me->key);
+-              goto out_umount;
++              if (save_errno != ENOENT)
++                      goto out_umount;
++              goto out_err;
+       }
+       ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key);
diff --git a/archive-patches/autofs5/autofs-5.1.7-dont-use-AUTOFS_DEV_IOCTL_CLOSEMOUNT.patch b/archive-patches/autofs5/autofs-5.1.7-dont-use-AUTOFS_DEV_IOCTL_CLOSEMOUNT.patch
new file mode 100644 (file)
index 0000000..aafaed5
--- /dev/null
@@ -0,0 +1,47 @@
+autofs-5.1.7 - dont use AUTOFS_DEV_IOCTL_CLOSEMOUNT
+
+From: Ian Kent <raven@themaw.net>
+
+Using an ioctl (AUTOFS_DEV_IOCTL_CLOSEMOUNT) to close an autofs mount
+file handle can race with copy_to_user() so the file handle needs to
+be closed using close(2) instead.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/dev-ioctl-lib.c |   10 +---------
+ 2 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 06bf24b8..51e7767e 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -68,6 +68,7 @@
+ - add ext_mount_hash_mutex lock helpers.
+ - fix amd section mounts map reload.
+ - fix dandling symlink creation if nis support is not available.
++- dont use AUTOFS_DEV_IOCTL_CLOSEMOUNT.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/dev-ioctl-lib.c b/lib/dev-ioctl-lib.c
+index e7a1b42a..6b549d73 100644
+--- a/lib/dev-ioctl-lib.c
++++ b/lib/dev-ioctl-lib.c
+@@ -404,15 +404,7 @@ err:
+ /* Close */
+ static int dev_ioctl_close(unsigned int logopt, int ioctlfd)
+ {
+-      struct autofs_dev_ioctl param;
+-
+-      init_autofs_dev_ioctl(&param);
+-      param.ioctlfd = ioctlfd;
+-
+-      if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CLOSEMOUNT, &param) == -1)
+-              return -1;
+-
+-      return 0;
++      return close(ioctlfd);
+ }
+ static int ioctl_close(unsigned int logopt, int ioctlfd)
diff --git a/archive-patches/autofs5/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch b/archive-patches/autofs5/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch
new file mode 100644 (file)
index 0000000..ffd8817
--- /dev/null
@@ -0,0 +1,112 @@
+autofs-5.1.7 - dont use realloc in host exports list processing
+
+From: Ian Kent <raven@themaw.net>
+
+If a server exports list is very large calling realloc(3) for each
+export is slow. It's better to traverse the exports list twice, once
+to calculate the length of the mapent then allocate the memory and
+traverse the exports list again to construct the mapent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ modules/lookup_hosts.c |   59 +++++++++++++++++++++---------------------------
+ 2 files changed, 27 insertions(+), 33 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 19af245e..1bd6ac7f 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -1,6 +1,7 @@
+ - add xdr_exports().
+ - remove mount.x and rpcgen dependencies.
++- dont use realloc in host exports list processing.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
+index 81a4eb18..e3ee0ab8 100644
+--- a/modules/lookup_hosts.c
++++ b/modules/lookup_hosts.c
+@@ -89,44 +89,40 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+       char buf[MAX_ERR_BUF];
+       char *mapent;
+       struct exportinfo *exp, *this;
++      size_t hostlen = strlen(host);
++      size_t mapent_len;
+       debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+       exp = rpc_get_exports(host, 10, 0, RPC_CLOSE_NOLINGER);
+-      mapent = NULL;
+       this = exp;
++      mapent_len = 0;
+       while (this) {
+-              if (mapent) {
+-                      int len = strlen(mapent) + 1;
+-
+-                      len += strlen(host) + 2*(strlen(this->dir) + 2) + 3;
+-                      mapent = realloc(mapent, len);
+-                      if (!mapent) {
+-                              char *estr;
+-                              estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-                              error(ap->logopt, MODPREFIX "malloc: %s", estr);
+-                              rpc_exports_free(exp);
+-                              return NULL;
+-                      }
+-                      strcat(mapent, " \"");
+-                      strcat(mapent, this->dir);
+-                      strcat(mapent, "\"");
+-              } else {
+-                      int len = 2*(strlen(this->dir) + 2) + strlen(host) + 3;
+-
+-                      mapent = malloc(len);
+-                      if (!mapent) {
+-                              char *estr;
+-                              estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-                              error(ap->logopt, MODPREFIX "malloc: %s", estr);
+-                              rpc_exports_free(exp);
+-                              return NULL;
+-                      }
++              mapent_len += hostlen + 2*(strlen(this->dir) + 2) + 3;
++              this = this->next;
++      }
++
++      mapent = malloc(mapent_len + 1);
++      if (!mapent) {
++              char *estr;
++              estr = strerror_r(errno, buf, MAX_ERR_BUF);
++              error(ap->logopt, MODPREFIX "malloc: %s", estr);
++              error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
++              rpc_exports_free(exp);
++              return NULL;
++      }
++      *mapent = 0;
++
++      this = exp;
++      while (this) {
++              if (!*mapent)
+                       strcpy(mapent, "\"");
+-                      strcat(mapent, this->dir);
+-                      strcat(mapent, "\"");
+-              }
++              else
++                      strcat(mapent, " \"");
++              strcat(mapent, this->dir);
++              strcat(mapent, "\"");
++
+               strcat(mapent, " \"");
+               strcat(mapent, host);
+               strcat(mapent, ":");
+@@ -137,9 +133,6 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+       }
+       rpc_exports_free(exp);
+-      if (!mapent)
+-              error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
+-
+       return mapent;
+ }
diff --git a/archive-patches/autofs5/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch b/archive-patches/autofs5/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch
new file mode 100644 (file)
index 0000000..ab6524d
--- /dev/null
@@ -0,0 +1,378 @@
+autofs-5.1.7 - eliminate cache_lookup_offset() usage
+
+From: Ian Kent <raven@themaw.net>
+
+The function cache_lookup_offset() will do a linear search when
+looking for an offset. If the number of offsets is large this
+can be a lot of overhead.
+
+But it's possible to use the information already present where
+this is called to to do a hashed lookup instead.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/mounts.c        |   82 +++++++++++++++++++++++++++++++++------------------
+ modules/parse_sun.c |   77 ++++++++++++++++++++++++++++++------------------
+ 3 files changed, 102 insertions(+), 58 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 0b577909..484bd866 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -5,6 +5,7 @@
+ - use sprintf() when constructing hosts mapent.
+ - fix mnts_remove_amdmount() uses wrong list.
+ - Fix option for master read wait.
++- eliminate cache_lookup_offset() usage.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index ccbd52e0..42e8ef07 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2495,24 +2495,27 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+       char *offset = path;
+       struct mapent *oe;
+       struct list_head *pos = NULL;
+-      unsigned int fs_path_len;
++      unsigned int root_len = strlen(root);
+       int mounted;
+-      fs_path_len = start + strlen(base);
+-      if (fs_path_len > PATH_MAX)
+-              return -1;
+-
+       mounted = 0;
+       offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+       while (offset) {
+-              int plen = fs_path_len + strlen(offset);
++              char key[PATH_MAX + 1];
++              int key_len = root_len + strlen(offset);
+-              if (plen > PATH_MAX) {
++              if (key_len > PATH_MAX) {
+                       warn(ap->logopt, "path loo long");
+                       goto cont;
+               }
+-              oe = cache_lookup_offset(base, offset, start, &me->multi_list);
++              /* The root offset is always mounted seperately so the
++               * offset path will always be root + offset.
++               */
++              strcpy(key, root);
++              strcat(key, offset);
++
++              oe = cache_lookup_distinct(me->mc, key);
+               if (!oe || !oe->mapent)
+                       goto cont;
+@@ -2525,12 +2528,8 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+                */
+               if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+                       if (oe->ioctlfd != -1 ||
+-                          is_mounted(oe->key, MNTS_REAL)) {
+-                              char oe_root[PATH_MAX + 1];
+-                              strcpy(oe_root, root);
+-                              strcat(oe_root, offset); 
+-                              mount_multi_triggers(ap, oe, oe_root, strlen(oe_root), base);
+-                      }
++                          is_mounted(oe->key, MNTS_REAL))
++                              mount_multi_triggers(ap, oe, key, strlen(key), base);
+               }
+ cont:
+               offset = cache_get_offset(base,
+@@ -2584,6 +2583,8 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+       const char o_root[] = "/";
+       const char *mm_base;
+       int left, start;
++      unsigned int root_len;
++      unsigned int mm_base_len;
+       left = 0;
+       start = strlen(root);
+@@ -2597,11 +2598,28 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+       pos = NULL;
+       offset = path;
++      root_len = start;
++      mm_base_len = strlen(mm_base);
+       while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
++              char key[PATH_MAX + 1];
++              int key_len = root_len + strlen(offset);
+               char *oe_base;
+-              oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
++              if (mm_base_len > 1)
++                      key_len += mm_base_len;
++
++              if (key_len > PATH_MAX) {
++                      warn(ap->logopt, "path loo long");
++                      continue;
++              }
++
++              strcpy(key, root);
++              if (mm_base_len > 1)
++                      strcat(key, mm_base);
++              strcat(key, offset);
++
++              oe = cache_lookup_distinct(me->mc, key);
+               /* root offset is a special case */
+               if (!oe || (strlen(oe->key) - start) == 1)
+                       continue;
+@@ -2686,13 +2704,14 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+       char *root;
+       char mm_top[PATH_MAX + 1];
+       char path[PATH_MAX + 1];
+-      char buf[MAX_ERR_BUF];
+       char *offset;
+       struct mapent *oe;
+       struct list_head *mm_root, *pos;
+       const char o_root[] = "/";
+       const char *mm_base;
+       int left, start;
++      unsigned int root_len;
++      unsigned int mm_base_len;
+       time_t age;
+       if (top)
+@@ -2720,14 +2739,30 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+       pos = NULL;
+       offset = path;
++      root_len = start;
++      mm_base_len = strlen(mm_base);
+       age = me->multi->age;
+       while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
++              char key[PATH_MAX + 1];
++              int key_len = root_len + strlen(offset);
+               char *oe_base;
+-              char *key;
+               int ret;
+-              oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
++              if (mm_base_len > 1)
++                      key_len += mm_base_len;
++
++              if (key_len > PATH_MAX) {
++                      warn(ap->logopt, "path loo long");
++                      continue;
++              }
++
++              strcpy(key, root);
++              if (mm_base_len > 1)
++                      strcat(key, mm_base);
++              strcat(key, offset);
++
++              oe = cache_lookup_distinct(me->mc, key);
+               /* root offset is a special case */
+               if (!oe || (strlen(oe->key) - start) == 1)
+                       continue;
+@@ -2778,14 +2813,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+                       }
+               }
+-              key = strdup(oe->key);
+-              if (!key) {
+-                      char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-                      error(ap->logopt, "malloc: %s", estr);
+-                      left++;
+-                      continue;
+-              }
+-
+               debug(ap->logopt, "umount offset %s", oe->key);
+               if (umount_autofs_offset(ap, oe)) {
+@@ -2800,7 +2827,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+                               if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
+                                       error(ap->logopt,
+                                            "failed to delete offset key %s", key);
+-                              free(key);
+                               continue;
+                       }
+@@ -2816,7 +2842,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+                                       left++;
+                                       /* But we did origianlly create this */
+                                       oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-                                      free(key);
+                                       continue;
+                               }
+                               /*
+@@ -2834,7 +2859,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+                               error(ap->logopt,
+                                    "failed to delete offset key %s", key);
+               }
+-              free(key);
+       }
+       return left;
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 4b137f99..819d6adc 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1086,6 +1086,8 @@ static void cleanup_multi_triggers(struct autofs_point *ap,
+       struct list_head *mm_root, *pos;
+       const char o_root[] = "/";
+       const char *mm_base;
++      unsigned int root_len;
++      unsigned int mm_base_len;
+       mm_root = &me->multi->multi_list;
+@@ -1095,16 +1097,31 @@ static void cleanup_multi_triggers(struct autofs_point *ap,
+               mm_base = base;
+       pos = NULL;
++      root_len = strlen(root);
++      mm_base_len = strlen(mm_base);
+       /* Make sure "none" of the offsets have an active mount. */
+       while ((poffset = cache_get_offset(mm_base, poffset, start, mm_root, &pos))) {
+-              oe = cache_lookup_offset(mm_base, poffset, start, &me->multi_list);
+-              /* root offset is a special case */
+-              if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
++              unsigned int path_len = root_len + strlen(poffset);
++
++              if (mm_base_len > 1)
++                      path_len += mm_base_len;
++
++              if (path_len > PATH_MAX) {
++                      warn(ap->logopt, "path loo long");
+                       continue;
++              }
+               strcpy(path, root);
++              if (mm_base_len > 1)
++                      strcat(path, mm_base);
+               strcat(path, poffset);
++
++              oe = cache_lookup_distinct(me->mc, path);
++              /* root offset is a special case */
++              if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
++                      continue;
++
+               if (umount(path)) {
+                       error(ap->logopt, "error recovering from mount fail");
+                       error(ap->logopt, "cannot umount offset %s", path);
+@@ -1117,17 +1134,14 @@ static void cleanup_multi_triggers(struct autofs_point *ap,
+ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+                        const char *name, char *loc, char *options, void *ctxt)
+ {
+-      struct mapent *mm;
+       struct mapent *ro;
+       char *mm_root, *mm_base, *mm_key;
+-      const char *mnt_root;
+-      unsigned int mm_root_len, mnt_root_len;
++      unsigned int mm_root_len;
+       int start, ret = 0, rv;
+       rv = 0;
+-      mm = me->multi;
+-      mm_key = mm->key;
++      mm_key = me->multi->key;
+       if (*mm_key == '/') {
+               mm_root = mm_key;
+@@ -1141,20 +1155,26 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+       }
+       mm_root_len = strlen(mm_root);
+-      mnt_root = mm_root;
+-      mnt_root_len = mm_root_len;
+-
+       if (me == me->multi) {
++              char key[PATH_MAX + 1];
++
++              if (mm_root_len + 1 > PATH_MAX) {
++                      warn(ap->logopt, "path loo long");
++                      return 1;
++              }
++
+               /* name = NULL */
+               /* destination = mm_root */
+               mm_base = "/";
++              strcpy(key, mm_root);
++              strcat(key, mm_base);
++
+               /* Mount root offset if it exists */
+-              ro = cache_lookup_offset(mm_base, mm_base, strlen(mm_root), &me->multi_list);
++              ro = cache_lookup_distinct(me->mc, key);
+               if (ro) {
+-                      char *myoptions, *ro_loc, *tmp;
++                      char *myoptions, *ro_loc;
+                       int namelen = name ? strlen(name) : 0;
+-                      const char *root;
+                       int ro_len;
+                       myoptions = NULL;
+@@ -1172,13 +1192,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+                       if (ro_loc)
+                               ro_len = strlen(ro_loc);
+-                      tmp = alloca(mnt_root_len + 2);
+-                      strcpy(tmp, mnt_root);
+-                      tmp[mnt_root_len] = '/';
+-                      tmp[mnt_root_len + 1] = '\0';
+-                      root = tmp;
+-
+-                      rv = sun_mount(ap, root, name, namelen, ro_loc, ro_len, myoptions, ctxt);
++                      rv = sun_mount(ap, key, name, namelen, ro_loc, ro_len, myoptions, ctxt);
+                       free(myoptions);
+                       if (ro_loc)
+@@ -1186,11 +1200,11 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+               }
+               if (ro && rv == 0) {
+-                      ret = mount_multi_triggers(ap, me, mnt_root, start, mm_base);
++                      ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+                       if (ret == -1) {
+                               error(ap->logopt, MODPREFIX
+                                        "failed to mount offset triggers");
+-                              cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
++                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+                               return 1;
+                       }
+               } else if (rv <= 0) {
+@@ -1206,24 +1220,29 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+               int loclen = strlen(loc);
+               int namelen = strlen(name);
+-              mnt_root = name;
+-
+               /* name = mm_root + mm_base */
+               /* destination = mm_root + mm_base = name */
+               mm_base = &me->key[start];
+-              rv = sun_mount(ap, mnt_root, name, namelen, loc, loclen, options, ctxt);
++              rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
+               if (rv == 0) {
+-                      ret = mount_multi_triggers(ap, me->multi, mnt_root, start, mm_base);
++                      ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
+                       if (ret == -1) {
+                               error(ap->logopt, MODPREFIX
+                                        "failed to mount offset triggers");
+-                              cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
++                              cleanup_multi_triggers(ap, me, name, start, mm_base);
+                               return 1;
+                       }
+               } else if (rv < 0) {
+-                      char *mm_root_base = alloca(strlen(mm_root) + strlen(mm_base) + 1);
++                      char mm_root_base[PATH_MAX + 1];
++                      unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
+       
++                      if (mm_root_base_len > PATH_MAX) {
++                              warn(ap->logopt, MODPREFIX "path too long");
++                              cache_delete_offset_list(me->mc, name);
++                              return 1;
++                      }
++
+                       strcpy(mm_root_base, mm_root);
+                       strcat(mm_root_base, mm_base);
diff --git a/archive-patches/autofs5/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch b/archive-patches/autofs5/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch
new file mode 100644 (file)
index 0000000..6c3a66f
--- /dev/null
@@ -0,0 +1,290 @@
+autofs-5.1.7 - eliminate clean_stale_multi_triggers()
+
+From: Ian Kent <raven@themaw.net>
+
+Eliminate clean_stale_multi_triggers() by checking for stale offsets at
+the time mount_subtree() is called.
+
+This should result in the same behaviour but eliminate an additional
+seperate traversal of the offset list.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ lib/mounts.c        |  209 ++++++++++-----------------------------------------
+ modules/parse_sun.c |   10 --
+ 3 files changed, 43 insertions(+), 177 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 5a3bedc1..b1ce7b69 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -12,6 +12,7 @@
+ - remove redundant variables from mount_autofs_offset().
+ - remove unused parameter form do_mount_autofs_offset().
+ - refactor umount_multi_triggers().
++- eliminate clean_stale_multi_triggers().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 5268ba5b..a9abbebf 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2601,10 +2601,44 @@ static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const ch
+       oe_base = oe->key + strlen(root);
+       left += do_umount_multi_triggers(ap, oe, root, oe_base);
++      /*
++       * If an offset that has an active mount has been removed
++       * from the multi-mount we don't want to attempt to trigger
++       * mounts for it. Obviously this is because it has been
++       * removed, but less obvious is the potential strange
++       * behaviour that can result if we do try and mount it
++       * again after it's been expired. For example, if an NFS
++       * file system is no longer exported and is later umounted
++       * it can be mounted again without any error message but
++       * shows as an empty directory. That's going to confuse
++       * people for sure.
++       *
++       * If the mount cannot be umounted (the process is now
++       * using a stale mount) the offset needs to be invalidated
++       * so no further mounts will be attempted but the offset
++       * cache entry must remain so expires can continue to
++       * attempt to umount it. If the mount can be umounted and
++       * the offset is removed, at least for NFS we will get
++       * ESTALE errors when attempting list the directory.
++       */
+       if (oe->ioctlfd != -1 ||
+           is_mounted(oe->key, MNTS_REAL)) {
+-              left++;
+-              return left;
++              if (umount_ent(ap, oe->key) &&
++                  is_mounted(oe->key, MNTS_REAL)) {
++                      debug(ap->logopt,
++                            "offset %s has active mount, invalidate",
++                            oe->key);
++                      /*
++                       * Ok, so we shouldn't modify the mapent but
++                       * mount requests are blocked at a point above
++                       * this and expire only uses the mapent key.
++                       */
++                      if (oe->mapent) {
++                              free(oe->mapent);
++                              oe->mapent = NULL;
++                      }
++                      return ++left;
++              }
+       }
+       debug(ap->logopt, "umount offset %s", oe->key);
+@@ -2666,6 +2700,11 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+               oe = cache_lookup_distinct(me->mc, key);
+               if (!oe || !oe->mapent)
+                       goto cont;
++              if (oe->age != me->multi->age) {
++                      /* Best effort */
++                      do_umount_offset(ap, oe, root);
++                      goto cont;
++              }
+               mounted += do_mount_autofs_offset(ap, oe, root);
+@@ -2725,169 +2764,3 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+       return left;
+ }
+-
+-int clean_stale_multi_triggers(struct autofs_point *ap,
+-                             struct mapent *me, char *top, const char *base)
+-{
+-      char *root;
+-      char mm_top[PATH_MAX + 1];
+-      char path[PATH_MAX + 1];
+-      char *offset;
+-      struct mapent *oe;
+-      struct list_head *mm_root, *pos;
+-      const char o_root[] = "/";
+-      const char *mm_base;
+-      int left, start;
+-      unsigned int root_len;
+-      unsigned int mm_base_len;
+-      time_t age;
+-
+-      if (top)
+-              root = top;
+-      else {
+-              if (!strchr(me->multi->key, '/'))
+-                      /* Indirect multi-mount root */
+-                      /* sprintf okay - if it's mounted, it's
+-                       * PATH_MAX or less bytes */
+-                      sprintf(mm_top, "%s/%s", ap->path, me->multi->key);
+-              else
+-                      strcpy(mm_top, me->multi->key);
+-              root = mm_top;
+-      }
+-
+-      left = 0;
+-      start = strlen(root);
+-
+-      mm_root = &me->multi->multi_list;
+-
+-      if (!base)
+-              mm_base = o_root;
+-      else
+-              mm_base = base;
+-
+-      pos = NULL;
+-      offset = path;
+-      root_len = start;
+-      mm_base_len = strlen(mm_base);
+-      age = me->multi->age;
+-
+-      while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+-              char key[PATH_MAX + 1];
+-              int key_len = root_len + strlen(offset);
+-              char *oe_base;
+-              int ret;
+-
+-              if (mm_base_len > 1)
+-                      key_len += mm_base_len;
+-
+-              if (key_len > PATH_MAX) {
+-                      warn(ap->logopt, "path loo long");
+-                      continue;
+-              }
+-
+-              strcpy(key, root);
+-              if (mm_base_len > 1)
+-                      strcat(key, mm_base);
+-              strcat(key, offset);
+-
+-              oe = cache_lookup_distinct(me->mc, key);
+-              /* root offset is a special case */
+-              if (!oe || (strlen(oe->key) - start) == 1)
+-                      continue;
+-
+-              /* Check for and umount stale subtree offsets */
+-              oe_base = oe->key + strlen(root);
+-              ret = clean_stale_multi_triggers(ap, oe, root, oe_base);
+-              left += ret;
+-              if (ret)
+-                      continue;
+-
+-              if (oe->age == age)
+-                      continue;
+-
+-              /*
+-               * If an offset that has an active mount has been removed
+-               * from the multi-mount we don't want to attempt to trigger
+-               * mounts for it. Obviously this is because it has been
+-               * removed, but less obvious is the potential strange
+-               * behaviour that can result if we do try and mount it
+-               * again after it's been expired. For example, if an NFS
+-               * file system is no longer exported and is later umounted
+-               * it can be mounted again without any error message but
+-               * shows as an empty directory. That's going to confuse
+-               * people for sure.
+-               *
+-               * If the mount cannot be umounted (the process is now
+-               * using a stale mount) the offset needs to be invalidated
+-               * so no further mounts will be attempted but the offset
+-               * cache entry must remain so expires can continue to
+-               * attempt to umount it. If the mount can be umounted and
+-               * the offset is removed, at least for NFS we will get
+-               * ESTALE errors when attempting list the directory.
+-               */
+-              if (oe->ioctlfd != -1 ||
+-                  is_mounted(oe->key, MNTS_REAL)) {
+-                      if (umount_ent(ap, oe->key) &&
+-                          is_mounted(oe->key, MNTS_REAL)) {
+-                              debug(ap->logopt,
+-                                    "offset %s has active mount, invalidate",
+-                                    oe->key);
+-                              if (oe->mapent) {
+-                                      free(oe->mapent);
+-                                      oe->mapent = NULL;
+-                              }
+-                              left++;
+-                              continue;
+-                      }
+-              }
+-
+-              debug(ap->logopt, "umount offset %s", oe->key);
+-
+-              if (umount_autofs_offset(ap, oe)) {
+-                      warn(ap->logopt, "failed to umount offset %s", key);
+-                      left++;
+-              } else {
+-                      struct stat st;
+-
+-                      /* Mount point not ours to delete ? */
+-                      if (!(oe->flags & MOUNT_FLAG_DIR_CREATED)) {
+-                              debug(ap->logopt, "delete offset key %s", key);
+-                              if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
+-                                      error(ap->logopt,
+-                                           "failed to delete offset key %s", key);
+-                              continue;
+-                      }
+-
+-                      /*
+-                       * An error due to partial directory removal is
+-                       * ok so only try and remount the offset if the
+-                       * actual mount point still exists.
+-                       */
+-                      ret = rmdir_path_offset(ap, oe);
+-                      if (ret == -1 && !stat(oe->key, &st)) {
+-                              ret = do_mount_autofs_offset(ap, oe, root);
+-                              if (ret) {
+-                                      left++;
+-                                      /* But we did origianlly create this */
+-                                      oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-                                      continue;
+-                              }
+-                              /*
+-                               * Fall through if the trigger can't be mounted
+-                               * again, since there is no offset there can't
+-                               * be any mount requests so remove the map
+-                               * entry from the cache. There's now a dead
+-                               * offset mount, but what else can we do ....
+-                               */
+-                      }
+-
+-                      debug(ap->logopt, "delete offset key %s", key);
+-
+-                      if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
+-                              error(ap->logopt,
+-                                   "failed to delete offset key %s", key);
+-              }
+-      }
+-
+-      return left;
+-}
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index f42af7b7..f4d5125c 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1176,7 +1176,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+               /* Mount root offset if it exists */
+               ro = cache_lookup_distinct(me->mc, key);
+-              if (ro) {
++              if (ro && ro->age == me->multi->age) {
+                       char *myoptions, *ro_loc;
+                       int namelen = name ? strlen(name) : 0;
+                       int ro_len;
+@@ -1610,14 +1610,6 @@ dont_expand:
+                       free(myoptions);
+               } while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+-              /*
+-               * We've got the ordered list of multi-mount entries so go
+-               * through and remove any stale entries if this is the top
+-               * of the multi-mount and set the parent entry of each.
+-               */
+-              if (me == me->multi)
+-                      clean_stale_multi_triggers(ap, me, NULL, NULL);
+-
+               rv = mount_subtree(ap, me, name, NULL, options, ctxt);
+               cache_multi_unlock(me);
diff --git a/archive-patches/autofs5/autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch b/archive-patches/autofs5/autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch
new file mode 100644 (file)
index 0000000..f39885e
--- /dev/null
@@ -0,0 +1,140 @@
+autofs-5.1.7 - eliminate count_mounts() from expire_proc_indirect()
+
+From: Ian Kent <raven@themaw.net>
+
+The count_mounts() function traverses the directory tree under a given
+automount in order to count the number of mounts.
+
+If there are many directories (such as when there is a very large
+number of offset trigger mounts) this can take a long time.
+
+Eliminate the call in expire_proc_indirect() by changing the expire
+ioctl function to better use the expire return from the kernel.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/direct.c     |    4 ++--
+ daemon/indirect.c   |   10 +++++-----
+ lib/dev-ioctl-lib.c |   21 +++++++++++++--------
+ 4 files changed, 21 insertions(+), 15 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index c5619d2e..0b78eb62 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -20,6 +20,7 @@
+ - pass mapent_cache to update_offset_entry().
+ - fix inconsistent locking in parse_mount().
+ - remove unused mount offset list lock functions.
++- eliminate count_mounts() from expire_proc_indirect().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/direct.c b/daemon/direct.c
+index c41c680f..311a98ba 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -884,7 +884,7 @@ cont:
+                       ioctlfd = me->ioctlfd;
+                       ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+-                      if (ret) {
++                      if (ret == 1) {
+                               left++;
+                               pthread_setcancelstate(cur_state, NULL);
+                               continue;
+@@ -910,7 +910,7 @@ cont:
+               pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+               ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+-              if (ret)
++              if (ret == 1)
+                       left++;
+               pthread_setcancelstate(cur_state, NULL);
+       }
+diff --git a/daemon/indirect.c b/daemon/indirect.c
+index 65cfe4e3..b259ebdc 100644
+--- a/daemon/indirect.c
++++ b/daemon/indirect.c
+@@ -358,7 +358,6 @@ void *expire_proc_indirect(void *arg)
+       struct expire_args ec;
+       unsigned int how;
+       int offsets, submnts, count;
+-      int retries;
+       int ioctlfd, cur_state;
+       int status, ret, left;
+@@ -496,7 +495,7 @@ void *expire_proc_indirect(void *arg)
+               pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+               ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+-              if (ret)
++              if (ret == 1)
+                       left++;
+               pthread_setcancelstate(cur_state, NULL);
+       }
+@@ -507,10 +506,11 @@ void *expire_proc_indirect(void *arg)
+        * so we need to umount or unlink them here.
+        */
+       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-      retries = (count_mounts(ap, ap->path, ap->dev) + 1);
+-      while (retries--) {
++      while (1) {
+               ret = ops->expire(ap->logopt, ap->ioctlfd, ap->path, how);
+-              if (ret)
++              if (ret != 0 && errno == EAGAIN)
++                      break;
++              if (ret == 1)
+                       left++;
+       }
+       pthread_setcancelstate(cur_state, NULL);
+diff --git a/lib/dev-ioctl-lib.c b/lib/dev-ioctl-lib.c
+index 7040c3da..e7a1b42a 100644
+--- a/lib/dev-ioctl-lib.c
++++ b/lib/dev-ioctl-lib.c
+@@ -650,6 +650,7 @@ static int expire(unsigned int logopt,
+ {
+       int ret, retries = EXPIRE_RETRIES;
+       unsigned int may_umount;
++      int save_errno = 0;
+       while (retries--) {
+               struct timespec tm = {0, 100000000};
+@@ -657,9 +658,11 @@ static int expire(unsigned int logopt,
+               /* Ggenerate expire message for the mount. */
+               ret = ioctl(fd, cmd, arg);
+               if (ret == -1) {
++                      save_errno = errno;
++
+                       /* Mount has gone away */
+                       if (errno == EBADF || errno == EINVAL)
+-                              return 0;
++                              break;
+                       /*
+                        * Other than EAGAIN is an expire error so continue.
+@@ -673,14 +676,16 @@ static int expire(unsigned int logopt,
+               nanosleep(&tm, NULL);
+       }
+-      may_umount = 0;
+-      if (ctl.ops->askumount(logopt, ioctlfd, &may_umount))
+-              return -1;
+-
+-      if (!may_umount)
+-              return 1;
++      if (!ret || save_errno == EAGAIN) {
++              may_umount = 0;
++              if (!ctl.ops->askumount(logopt, ioctlfd, &may_umount)) {
++                      if (!may_umount)
++                              ret = 1;
++              }
++      }
++      errno = save_errno;
+-      return 0;
++      return ret;
+ }
+ static int dev_ioctl_expire(unsigned int logopt,
diff --git a/archive-patches/autofs5/autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch b/archive-patches/autofs5/autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch
new file mode 100644 (file)
index 0000000..2d55fd0
--- /dev/null
@@ -0,0 +1,90 @@
+autofs-5.1.7 - eliminate redundant cache lookup in tree_mapent_add_node()
+
+From: Ian Kent <raven@themaw.net>
+
+Since we need to create the offset tree after adding the offset entries
+to the mapent cache (from a list.h list) there's no need to lookup the
+mapent in tree_mapent_add_node() and validate it. Just use it directly
+when calling tree_mapent_add_node() and avoid a cache lookup on every
+node addition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/mounts.h    |    2 +-
+ lib/mounts.c        |   13 ++-----------
+ modules/parse_sun.c |    2 +-
+ 4 files changed, 5 insertions(+), 13 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 5a767360..81b6ce6a 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -73,6 +73,7 @@
+ - fix amd hosts mount expire.
+ - fix offset entries order.
+ - use mapent tree root for tree_mapent_add_node().
++- eliminate redundant cache lookup in tree_mapent_add_node().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/mounts.h b/include/mounts.h
+index f7768ce5..5a7a0b89 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -170,7 +170,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+-int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, const char *key);
++int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, struct mapent *me);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ void tree_mapent_cleanup_offsets(struct mapent *oe);
+ int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 9ec547ea..6b24a6c2 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1519,19 +1519,10 @@ static void tree_mapent_free(struct tree_node *n)
+ }
+ int tree_mapent_add_node(struct mapent_cache *mc,
+-                       struct tree_node *root, const char *key)
++                       struct tree_node *root, struct mapent *me)
+ {
+-      unsigned int logopt = mc->ap->logopt;
+       struct tree_node *n;
+       struct mapent *parent;
+-      struct mapent *me;
+-
+-      me = cache_lookup_distinct(mc, key);
+-      if (!me) {
+-              error(logopt,
+-                   "failed to find key %s of multi-mount", key);
+-              return 0;
+-      }
+       n = tree_add_node(root, me);
+       if (!n)
+@@ -1540,7 +1531,7 @@ int tree_mapent_add_node(struct mapent_cache *mc,
+       MAPENT_SET_ROOT(me, root)
+       /* Set the subtree parent */
+-      parent = cache_get_offset_parent(mc, key);
++      parent = cache_get_offset_parent(mc, me->key);
+       if (!parent)
+               MAPENT_SET_PARENT(me, root)
+       else
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index c75bcc8e..12844a30 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1546,7 +1546,7 @@ dont_expand:
+                       return 1;
+               }
+               list_for_each_entry_safe(oe, tmp, &offsets, work) {
+-                      if (!tree_mapent_add_node(mc, MAPENT_ROOT(me), oe->key))
++                      if (!tree_mapent_add_node(mc, MAPENT_ROOT(me), oe))
+                               error(ap->logopt, "failed to add offset %s to tree", oe->key);
+                       list_del_init(&oe->work);
+               }
diff --git a/archive-patches/autofs5/autofs-5.1.7-eliminate-some-more-alloca-usage.patch b/archive-patches/autofs5/autofs-5.1.7-eliminate-some-more-alloca-usage.patch
new file mode 100644 (file)
index 0000000..e329f65
--- /dev/null
@@ -0,0 +1,216 @@
+autofs-5.1.7 - eliminate some more alloca usage
+
+From: Ian Kent <raven@themaw.net>
+
+Quite a bit of the alloca(3) usage has been eliminated over time.
+Use malloc(3) for some more cases that might need to allocate a largish
+amount of storage.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                |    1 +
+ modules/lookup_program.c |   11 ++++++++++-
+ modules/lookup_yp.c      |   22 +++++++++++++++++++---
+ modules/parse_sun.c      |   18 ++++++++++++++----
+ modules/replicated.c     |   19 ++++++-------------
+ 5 files changed, 50 insertions(+), 21 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 8d050552..2b7cfaa0 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -79,6 +79,7 @@
+ - add missing description of null map option.
+ - fix nonstrict offset mount fail handling.
+ - fix concat_options() error handling.
++- eliminate some more alloca usage.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/lookup_program.c b/modules/lookup_program.c
+index 6cab52c8..028580e5 100644
+--- a/modules/lookup_program.c
++++ b/modules/lookup_program.c
+@@ -636,7 +636,14 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+                       char *ent = NULL;
+                       if (me->mapent) {
+-                              ent = alloca(strlen(me->mapent) + 1);
++                              ent = malloc(strlen(me->mapent) + 1);
++                              if (!ent) {
++                                      char buf[MAX_ERR_BUF];
++                                      char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
++                                      error(ap->logopt, MODPREFIX "malloc: %s", estr);
++                                      cache_unlock(mc);
++                                      goto out_free;
++                              }
+                               strcpy(ent, me->mapent);
+                       }
+                       cache_unlock(mc);
+@@ -644,6 +651,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+                       ap->entry->current = source;
+                       ret = ctxt->parse->parse_mount(ap, name,
+                                name_len, ent, ctxt->parse->context);
++                      if (ent)
++                              free(ent);
+                       goto out_free;
+               } else {
+                       if (IS_MM(me) && !IS_MM_ROOT(me)) {
+diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
+index 8bccb72f..d2a4b5a5 100644
+--- a/modules/lookup_yp.c
++++ b/modules/lookup_yp.c
+@@ -254,7 +254,7 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen,
+       len = ypkeylen + 1 + vallen + 2;
+-      buffer = alloca(len);
++      buffer = malloc(len);
+       if (!buffer) {
+               error(logopt, MODPREFIX "could not malloc parse buffer");
+               return 0;
+@@ -267,6 +267,8 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen,
+       master_parse_entry(buffer, timeout, logging, age);
++      free(buffer);
++
+       return 0;
+ }
+@@ -368,7 +370,12 @@ int yp_all_callback(int status, char *ypkey, int ypkeylen,
+               return 0;
+       }
+-      mapent = alloca(vallen + 1);
++      mapent = malloc(vallen + 1);
++      if (!mapent) {
++              error(logopt, MODPREFIX "could not malloc mapent buffer");
++              free(key);
++              return 0;
++      }
+       strncpy(mapent, val, vallen);
+       *(mapent + vallen) = '\0';
+@@ -377,6 +384,7 @@ int yp_all_callback(int status, char *ypkey, int ypkeylen,
+       cache_unlock(mc);
+       free(key);
++      free(mapent);
+       if (ret == CHE_FAIL)
+               return -1;
+@@ -904,7 +912,14 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+               }
+               if (me && (me->source == source || *me->key == '/')) {
+                       mapent_len = strlen(me->mapent);
+-                      mapent = alloca(mapent_len + 1);
++                      mapent = malloc(mapent_len + 1);
++                      if (!mapent) {
++                              char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
++                              error(ap->logopt, MODPREFIX "malloc: %s", estr);
++                              cache_unlock(mc);
++                              free(lkp_key);
++                              return NSS_STATUS_TRYAGAIN;
++                      }
+                       strcpy(mapent, me->mapent);
+               }
+       }
+@@ -929,6 +944,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+       ret = ctxt->parse->parse_mount(ap, key, key_len,
+                                      mapent, ctxt->parse->context);
++      free(mapent);
+       if (ret) {
+               /* Don't update negative cache when re-connecting */
+               if (ap->flags & MOUNT_FLAG_REMOUNT)
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 9190165d..d9ac0c94 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -668,9 +668,16 @@ static int sun_mount(struct autofs_point *ap, const char *root,
+               }
+       }
++      what = malloc(loclen + 1);
++      if (!what) {
++              char buf[MAX_ERR_BUF];
++              char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
++              error(ap->logopt, MODPREFIX "malloc: %s", estr);
++              return 1;
++      }
++
+       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+       if (!strcmp(fstype, "nfs") || !strcmp(fstype, "nfs4")) {
+-              what = alloca(loclen + 1);
+               memcpy(what, loc, loclen);
+               what[loclen] = '\0';
+@@ -706,10 +713,10 @@ static int sun_mount(struct autofs_point *ap, const char *root,
+               rv = mount_nfs->mount_mount(ap, root, name, namelen,
+                                           what, fstype, options, mount_nfs->context);
+       } else {
+-              if (!loclen)
++              if (!loclen) {
++                      free(what);
+                       what = NULL;
+-              else {
+-                      what = alloca(loclen + 1);
++              } else {
+                       if (*loc == ':') {
+                               loclen--;
+                               memcpy(what, loc + 1, loclen);
+@@ -728,6 +735,9 @@ static int sun_mount(struct autofs_point *ap, const char *root,
+               /* Generic mount routine */
+               rv = do_mount(ap, root, name, namelen, what, fstype, options);
+       }
++      if (what)
++              free(what);
++
+       pthread_setcancelstate(cur_state, NULL);
+       if (nonstrict && rv)
+diff --git a/modules/replicated.c b/modules/replicated.c
+index 03d4ba1e..ffaf519f 100644
+--- a/modules/replicated.c
++++ b/modules/replicated.c
+@@ -1041,25 +1041,18 @@ done:
+       return ret;
+ }
+-static int add_path(struct host *hosts, const char *path, int len)
++static int add_path(struct host *hosts, const char *path)
+ {
+       struct host *this;
+-      char *tmp, *tmp2;
+-
+-      tmp = alloca(len + 1);
+-      if (!tmp)
+-              return 0;
+-
+-      strncpy(tmp, path, len);
+-      tmp[len] = '\0';
++      char *tmp;
+       this = hosts;
+       while (this) {
+               if (!this->path) {
+-                      tmp2 = strdup(tmp);
+-                      if (!tmp2)
++                      tmp = strdup(path);
++                      if (!tmp)
+                               return 0;
+-                      this->path = tmp2;
++                      this->path = tmp;
+               }
+               this = this->next;
+       }
+@@ -1188,7 +1181,7 @@ int parse_location(unsigned logopt, struct host **hosts,
+                                               }
+                                       }
+-                                      if (!add_path(*hosts, path, strlen(path))) {
++                                      if (!add_path(*hosts, path)) {
+                                               free_host_list(hosts);
+                                               free(str);
+                                               return 0;
diff --git a/archive-patches/autofs5/autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch b/archive-patches/autofs5/autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch
new file mode 100644 (file)
index 0000000..29aabc6
--- /dev/null
@@ -0,0 +1,128 @@
+autofs-5.1.7 - eliminate some strlen calls in offset handling
+
+From: Ian Kent <raven@themaw.net>
+
+There are a number of places where strlen() is used to re-calculate
+the length of a string. Eliminate some of those by calculating the
+length once and passing it to the functions that do the re-calculation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   30 +++++++++++++++++-------------
+ 2 files changed, 18 insertions(+), 13 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 0b78eb62..cb709773 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -21,6 +21,7 @@
+ - fix inconsistent locking in parse_mount().
+ - remove unused mount offset list lock functions.
+ - eliminate count_mounts() from expire_proc_indirect().
++- eliminate some strlen calls in offset handling.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 0fcd4087..04fe3d00 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2540,10 +2540,12 @@ static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+       return ret;
+ }
+-static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root);
++static int do_umount_offset(struct autofs_point *ap,
++                          struct mapent *oe, const char *root, int start);
+ static int do_umount_multi_triggers(struct autofs_point *ap,
+-                                  struct mapent *me, const char *root, const char *base)
++                                  struct mapent *me, const char *root,
++                                  int start, const char *base)
+ {
+       char path[PATH_MAX + 1];
+       char *offset;
+@@ -2551,12 +2553,11 @@ static int do_umount_multi_triggers(struct autofs_point *ap,
+       struct list_head *mm_root, *pos;
+       const char o_root[] = "/";
+       const char *mm_base;
+-      int left, start;
++      int left;
+       unsigned int root_len;
+       unsigned int mm_base_len;
+       left = 0;
+-      start = strlen(root);
+       mm_root = &me->multi->multi_list;
+@@ -2592,13 +2593,14 @@ static int do_umount_multi_triggers(struct autofs_point *ap,
+               if (!oe || (strlen(oe->key) - start) == 1)
+                       continue;
+-              left += do_umount_offset(ap, oe, root);
++              left += do_umount_offset(ap, oe, root, start);
+       }
+       return left;
+ }
+-static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root)
++static int do_umount_offset(struct autofs_point *ap,
++                          struct mapent *oe, const char *root, int start)
+ {
+       char *oe_base;
+       int left = 0;
+@@ -2607,8 +2609,8 @@ static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const ch
+        * Check for and umount subtree offsets resulting from
+        * nonstrict mount fail.
+        */
+-      oe_base = oe->key + strlen(root);
+-      left += do_umount_multi_triggers(ap, oe, root, oe_base);
++      oe_base = oe->key + start;
++      left += do_umount_multi_triggers(ap, oe, root, start, oe_base);
+       /*
+        * If an offset that has an active mount has been removed
+@@ -2712,7 +2714,7 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+                       goto cont;
+               if (oe->age != me->multi->age) {
+                       /* Best effort */
+-                      do_umount_offset(ap, oe, root);
++                      do_umount_offset(ap, oe, root, start);
+                       goto cont;
+               }
+@@ -2726,7 +2728,7 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+               if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+                       if (oe->ioctlfd != -1 ||
+                           is_mounted(oe->key, MNTS_REAL))
+-                              mount_multi_triggers(ap, oe, key, strlen(key), base);
++                              mount_multi_triggers(ap, oe, key, key_len, base);
+               }
+ cont:
+               offset = cache_get_offset(base,
+@@ -2738,9 +2740,11 @@ cont:
+ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
+ {
+-      int left;
++      int left, start;
++
++      start = strlen(root);
+-      left = do_umount_multi_triggers(ap, me, root, base);
++      left = do_umount_multi_triggers(ap, me, root, start, base);
+       if (!left && me->multi == me) {
+               /*
+@@ -2753,7 +2757,7 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+                       info(ap->logopt, "unmounting dir = %s", root);
+                       if (umount_ent(ap, root) &&
+                           is_mounted(root, MNTS_REAL)) {
+-                              if (mount_multi_triggers(ap, me, root, strlen(root), "/") < 0)
++                              if (mount_multi_triggers(ap, me, root, start, "/") < 0)
+                                       warn(ap->logopt,
+                                            "failed to remount offset triggers");
+                               return ++left;
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-amd-hosts-mount-expire.patch b/archive-patches/autofs5/autofs-5.1.7-fix-amd-hosts-mount-expire.patch
new file mode 100644 (file)
index 0000000..c82c298
--- /dev/null
@@ -0,0 +1,52 @@
+autofs-5.1.7 - fix amd hosts mount expire
+
+From: Ian Kent <raven@themaw.net>
+
+When swicthing to use the mnt_list to track mounts for expire, if the
+amd hosts map entry name is for the host short name, the amd mount
+entry for the short name gets removed. This causes a subsequent mounts
+for host exports to fail.
+
+What should happen is the short name amd entry not be removed and a
+mounted mount entry for the symlinked FQDN mount added so it expires.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_amd.c |    9 +++++----
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 698cc27a..94eb6a2c 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -70,6 +70,7 @@
+ - fix dandling symlink creation if nis support is not available.
+ - dont use AUTOFS_DEV_IOCTL_CLOSEMOUNT.
+ - fix lookup_prune_one_cache() refactoring change.
++- fix amd hosts mount expire.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_amd.c b/modules/parse_amd.c
+index 64c1ce63..163174cd 100644
+--- a/modules/parse_amd.c
++++ b/modules/parse_amd.c
+@@ -2341,12 +2341,13 @@ int parse_mount(struct autofs_point *ap, const char *name,
+               if (!rv) {
+                       /*
+                        * If entry->path doesn't match the mnt->mp then
+-                       * the mount point path has changed and a new
+-                       * mnt_list entry added for it, so remove the
+-                       * original.
++                       * it's a "host" map and the mount point path is
++                       * different to the lookup name. Add a new mnt_list
++                       * entry so that both the symlinked name and the
++                       * mount expire.
+                        */
+                       if (strcmp(this->path, mnt->mp))
+-                              mnts_remove_amdmount(this->path);
++                              mnts_add_mount(ap, this->rhost, MNTS_INDIRECT|MNTS_MOUNTED);
+                       break;
+               }
+               /* Not mounted, remove the mnt_list entry from amdmount list */
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-amd-section-mounts-map-reload.patch b/archive-patches/autofs5/autofs-5.1.7-fix-amd-section-mounts-map-reload.patch
new file mode 100644 (file)
index 0000000..cbe84ae
--- /dev/null
@@ -0,0 +1,124 @@
+autofs-5.1.7 - fix amd section mounts map reload
+
+From: Ian Kent <raven@themaw.net>
+
+Master map section mounts (amd format mounts) get umounted on reload.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/master.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 81 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index ff44ac25..ddc07912 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -66,6 +66,7 @@
+ - refactor lookup_prune_one_cache() a bit.
+ - cater for empty mounts list in mnts_get_expire_list().
+ - add ext_mount_hash_mutex lock helpers.
++- fix amd section mounts map reload.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/master.c b/daemon/master.c
+index 84743f80..f99359c5 100644
+--- a/daemon/master.c
++++ b/daemon/master.c
+@@ -882,6 +882,83 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int f
+       return master;
+ }
++static void master_update_amd_mount_section_mount(struct master *master,
++                                                const char *path, time_t age)
++{
++      unsigned int m_logopt = master->logopt;
++      struct master_mapent *entry;
++      struct map_source *source;
++      unsigned int loglevel;
++      unsigned int logopt;
++      unsigned int flags;
++      time_t timeout;
++      char *map;
++      char *opts;
++
++      entry = master_find_mapent(master, path);
++      if (!entry)
++              return;
++
++      map = conf_amd_get_map_name(path);
++      if (!map)
++              return;
++
++      /* amd top level mounts have only one map */
++      source = entry->maps;
++      if (strcmp(source->name, map) != 0) {
++              struct map_source *new;
++              char *type;
++              char *argv[2];
++
++              type = conf_amd_get_map_type(path);
++              argv[0] = map;
++              argv[1] = NULL;
++
++              new = master_add_map_source(entry, type, "amd",
++                                          age, 1, (const char **) argv);
++              if (!new) {
++                      error(m_logopt,
++                            "failed to add source for amd section mount %s",
++                            path);
++                      if (type)
++                              free(type);
++                      goto out;
++              }
++              master_free_map_source(source, 0);
++              entry->maps = new;
++              source = new;
++              if (type)
++                      free(type);
++      }
++
++      loglevel = conf_amd_get_log_options();
++      logopt = m_logopt;
++      if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
++              logopt = LOGOPT_DEBUG;
++      else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
++              logopt = LOGOPT_VERBOSE;
++
++      flags = conf_amd_get_flags(path);
++      if (flags & CONF_BROWSABLE_DIRS)
++              entry->ap->flags |= MOUNT_FLAG_GHOST;
++
++      opts = conf_amd_get_map_options(path);
++      if (opts) {
++              if (strstr(opts, "cache:=all"))
++                      entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
++              free(opts);
++      }
++
++      entry->ap->logopt = logopt;
++
++      timeout = conf_amd_get_dismount_interval(path);
++      set_exp_timeout(entry->ap, source, timeout);
++      source->master_line = 0;
++      entry->age = age;
++out:
++      free(map);
++}
++
+ static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
+ {
+       unsigned int m_logopt = master->logopt;
+@@ -916,8 +993,10 @@ static void master_add_amd_mount_section_mounts(struct master *master, time_t ag
+                        * master map it's not a duplicate, don't issue
+                        * an error message.
+                        */
+-                      if (ret == 1)
++                      if (ret == 1) {
++                              master_update_amd_mount_section_mount(master, path, age);
+                               goto next;
++                      }
+                       info(m_logopt,
+                            "amd section mount path conflict, %s ignored",
+                            path);
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-arg-not-used-in-print.patch b/archive-patches/autofs5/autofs-5.1.7-fix-arg-not-used-in-print.patch
new file mode 100644 (file)
index 0000000..52b8a6e
--- /dev/null
@@ -0,0 +1,40 @@
+autofs-5.1.7 - fix arg not used in error print
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: extra_argument: This argument was not used by the format
+         string: "key".
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    4 +---
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index f11aa1c7..1d56c96f 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -60,6 +60,7 @@
+ - dont try umount after stat() ENOENT fail.
+ - remove redundant assignment in master_add_amd_mount_section_mounts().
+ - fix dead code in mnts_add_mount().
++- fix arg not used in error print.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 018b9c80..883e3743 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1519,9 +1519,7 @@ int tree_mapent_add_node(struct mapent_cache *mc,
+       }
+       if (MAPENT_ROOT(base) != MAPENT_NODE(base)) {
+-              error(logopt,
+-                   "failed to find multi-mount root of offset tree",
+-                   key);
++              error(logopt, "key %s is not multi-mount root", root);
+               return 0;
+       }
+       tree = MAPENT_ROOT(base);
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-concat_options-error-handling.patch b/archive-patches/autofs5/autofs-5.1.7-fix-concat_options-error-handling.patch
new file mode 100644 (file)
index 0000000..2b170ba
--- /dev/null
@@ -0,0 +1,124 @@
+autofs-5.1.7 - fix concat_options() error handling
+
+From: Ian Kent <raven@themaw.net>
+
+There's a possibility of a memory leak in the mount options processing
+when calling concat_options() in parse_mount() of the Sun format map
+entry parsing.
+
+There's also a case in do_init() of the Sun map format parsing where
+a previously freed value is used in a logging statement without being
+set to MULL.
+
+So ensure concat_options() always frees it's arguments so that the
+handling can be consistent in all places.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   24 +++++++++++-------------
+ 2 files changed, 12 insertions(+), 13 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index ecffa933..8d050552 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -78,6 +78,7 @@
+ - fix direct mount deadlock.
+ - add missing description of null map option.
+ - fix nonstrict offset mount fail handling.
++- fix concat_options() error handling.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index cdf515c6..9190165d 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -380,7 +380,8 @@ static int do_init(int argc, const char *const *argv, struct parse_context *ctxt
+                       if (!tmp) {
+                               char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+                               logerr(MODPREFIX "concat_options: %s", estr);
+-                              free(gbl_options);
++                              /* freed in concat_options */
++                              ctxt->optstr = NULL;
+                       } else
+                               ctxt->optstr = tmp;
+               } else {
+@@ -492,12 +493,16 @@ static char *concat_options(char *left, char *right)
+       char *ret;
+       if (left == NULL || *left == '\0') {
++              if (!right || *right == '\0')
++                      return NULL;
+               ret = strdup(right);
+               free(right);
+               return ret;
+       }
+       if (right == NULL || *right == '\0') {
++              if (left == NULL || *left == '\0')
++                      return NULL;
+               ret = strdup(left);
+               free(left);
+               return ret;
+@@ -508,6 +513,8 @@ static char *concat_options(char *left, char *right)
+       if (ret == NULL) {
+               char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+               logerr(MODPREFIX "malloc: %s", estr);
++              free(left);
++              free(right);
+               return NULL;
+       }
+@@ -989,14 +996,13 @@ static int parse_mapent(const char *ent, char *g_options, char **options, char *
+                       if (newopt && strstr(newopt, myoptions)) {
+                               free(myoptions);
+                               myoptions = newopt;
+-                      } else {
++                      } else if (newopt) {
+                               tmp = concat_options(myoptions, newopt);
+                               if (!tmp) {
+                                       char *estr;
+                                       estr = strerror_r(errno, buf, MAX_ERR_BUF);
+                                       error(logopt, MODPREFIX
+                                             "concat_options: %s", estr);
+-                                      free(myoptions);
+                                       return 0;
+                               }
+                               myoptions = tmp;
+@@ -1358,16 +1364,12 @@ dont_expand:
+                       if (mnt_options && noptions && strstr(noptions, mnt_options)) {
+                               free(mnt_options);
+                               mnt_options = noptions;
+-                      } else {
++                      } else if (noptions) {
+                               tmp = concat_options(mnt_options, noptions);
+                               if (!tmp) {
+                                       char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+                                       error(ap->logopt,
+                                             MODPREFIX "concat_options: %s", estr);
+-                                      if (noptions)
+-                                              free(noptions);
+-                                      if (mnt_options)
+-                                              free(mnt_options);
+                                       free(options);
+                                       free(pmapent);
+                                       return 1;
+@@ -1387,15 +1389,11 @@ dont_expand:
+                       if (options && mnt_options && strstr(mnt_options, options)) {
+                               free(options);
+                               options = mnt_options;
+-                      } else {
++                      } else if (mnt_options) {
+                               tmp = concat_options(options, mnt_options);
+                               if (!tmp) {
+                                       char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+                                       error(ap->logopt, MODPREFIX "concat_options: %s", estr);
+-                                      if (options)
+-                                              free(options);
+-                                      if (mnt_options)
+-                                              free(mnt_options);
+                                       free(pmapent);
+                                       return 1;
+                               }
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-dandling-symlink-creation-if-nis-support-is-not-available.patch b/archive-patches/autofs5/autofs-5.1.7-fix-dandling-symlink-creation-if-nis-support-is-not-available.patch
new file mode 100644 (file)
index 0000000..6d1149b
--- /dev/null
@@ -0,0 +1,39 @@
+autofs-5.1.7 - fix dandling symlink creation if nis support is not available
+
+From: Ian Kent <raven@themaw.net>
+
+If NIS support is not available a dangling symlink is created pointing
+from lookup_nis.so to (a non-existent) lookup_yp.so.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ modules/Makefile |    2 ++
+ 2 files changed, 3 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index ddc07912..06bf24b8 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -67,6 +67,7 @@
+ - cater for empty mounts list in mnts_get_expire_list().
+ - add ext_mount_hash_mutex lock helpers.
+ - fix amd section mounts map reload.
++- fix dandling symlink creation if nis support is not available.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/Makefile b/modules/Makefile
+index 91dc20ab..6908da06 100644
+--- a/modules/Makefile
++++ b/modules/Makefile
+@@ -77,7 +77,9 @@ install: all
+       install -c $(MODS) -m 755 $(INSTALLROOT)$(autofslibdir)
+       -rm -f $(INSTALLROOT)$(autofslibdir)/mount_smbfs.so
+       ln -fs lookup_file.so $(INSTALLROOT)$(autofslibdir)/lookup_files.so
++ifeq ($(YPCLNT), 1)
+       ln -fs lookup_yp.so $(INSTALLROOT)$(autofslibdir)/lookup_nis.so
++endif
+ ifeq ($(LDAP), 1)
+       ln -fs lookup_ldap.so $(INSTALLROOT)$(autofslibdir)/lookup_ldaps.so
+ endif
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch b/archive-patches/autofs5/autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch
new file mode 100644 (file)
index 0000000..a32bf7b
--- /dev/null
@@ -0,0 +1,55 @@
+autofs-5.1.7 - fix dead code in mnts_add_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: dead_error_line: Execution cannot reach this statement: "free(mp);".
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    8 ++------
+ 2 files changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index f95b1aa6..f11aa1c7 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -59,6 +59,7 @@
+ - fix flags check in umount_multi().
+ - dont try umount after stat() ENOENT fail.
+ - remove redundant assignment in master_add_amd_mount_section_mounts().
++- fix dead code in mnts_add_mount().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index ef69cec1..018b9c80 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1205,13 +1205,13 @@ struct mnt_list *mnts_add_mount(struct autofs_point *ap,
+       if (*name == '/') {
+               mp = strdup(name);
+               if (!mp)
+-                      goto fail;
++                      return NULL;
+       } else {
+               int len = ap->len + strlen(name) + 2;
+               mp = malloc(len);
+               if (!mp)
+-                      goto fail;
++                      return NULL;
+               strcpy(mp, ap->path);
+               strcat(mp, "/");
+               strcat(mp, name);
+@@ -1228,10 +1228,6 @@ struct mnt_list *mnts_add_mount(struct autofs_point *ap,
+       free(mp);
+       return this;
+-fail:
+-      if (mp)
+-              free(mp);
+-      return NULL;
+ }
+ void mnts_remove_mount(const char *mp, unsigned int flags)
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-direct-mount-deadlock.patch b/archive-patches/autofs5/autofs-5.1.7-fix-direct-mount-deadlock.patch
new file mode 100644 (file)
index 0000000..edfb5a1
--- /dev/null
@@ -0,0 +1,135 @@
+autofs-5.1.7 - fix direct mount deadlock
+
+From: Ian Kent <raven@themaw.net>
+
+When umounting direct mounts at exit or when umounting mounts no
+longer in the map on re-load a deadlock can occur.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/direct.c |   22 +++++++++++++++++++++-
+ daemon/state.c  |   14 +++++++++-----
+ 3 files changed, 31 insertions(+), 6 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 9e341e06..b29d2ed8 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -75,6 +75,7 @@
+ - use mapent tree root for tree_mapent_add_node().
+ - eliminate redundant cache lookup in tree_mapent_add_node().
+ - fix hosts map offset order.
++- fix direct mount deadlock.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/direct.c b/daemon/direct.c
+index 3bd714e6..d37dd676 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -84,11 +84,27 @@ static void mnts_cleanup(void *arg)
+ 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;
++      char key[PATH_MAX + 1];
++      struct mapent *tmp;
+       int opened = 0;
+-      left = umount_multi(ap, me->key, 0);
++      if (me->len > PATH_MAX) {
++              error(ap->logopt, "path too long");
++              return 1;
++      }
++      strcpy(key, me->key);
++
++      cache_unlock(mc);
++      left = umount_multi(ap, key, 0);
++      cache_readlock(mc);
++      tmp = cache_lookup_distinct(mc, key);
++      if (tmp != me) {
++              error(ap->logopt, "key %s no longer in mapent cache", key);
++              return -1;
++      }
+       if (left) {
+               warn(ap->logopt, "could not unmount %d dirs under %s",
+                    left, me->key);
+@@ -213,6 +229,7 @@ int umount_autofs_direct(struct autofs_point *ap)
+               mc = map->mc;
+               pthread_cleanup_push(cache_lock_cleanup, mc);
+               cache_readlock(mc);
++restart:
+               me = cache_enumerate(mc, NULL);
+               while (me) {
+                       int error;
+@@ -230,6 +247,9 @@ int umount_autofs_direct(struct autofs_point *ap)
+                        * failed umount.
+                        */
+                       error = do_umount_autofs_direct(ap, me);
++                      /* cache became invalid, restart */
++                      if (error == -1)
++                              goto restart;
+                       if (!error)
+                               goto done;
+diff --git a/daemon/state.c b/daemon/state.c
+index 091210a5..5156bb21 100644
+--- a/daemon/state.c
++++ b/daemon/state.c
+@@ -324,11 +324,12 @@ static void do_readmap_cleanup(void *arg)
+       return;
+ }
+-static void do_readmap_mount(struct autofs_point *ap,
++static int do_readmap_mount(struct autofs_point *ap,
+                            struct map_source *map, struct mapent *me, time_t now)
+ {
+       struct mapent_cache *nc;
+       struct mapent *ne, *nested, *valid;
++      int ret = 0;
+       nc = ap->entry->master->nc;
+@@ -387,7 +388,7 @@ static void do_readmap_mount(struct autofs_point *ap,
+                               cache_unlock(vmc);
+                               error(ap->logopt,
+                                    "failed to find expected existing valid map entry");
+-                              return;
++                              return ret;
+                       }
+                       /* Take over the mount if there is one */
+                       valid->ioctlfd = me->ioctlfd;
+@@ -406,14 +407,14 @@ static void do_readmap_mount(struct autofs_point *ap,
+                                       ap->exp_runfreq = runfreq;
+                       }
+               } else if (!is_mounted(me->key, MNTS_REAL))
+-                      do_umount_autofs_direct(ap, me);
++                      ret = do_umount_autofs_direct(ap, me);
+               else
+                       debug(ap->logopt,
+                             "%s is mounted", me->key);
+       } else
+               do_mount_autofs_direct(ap, me, get_exp_timeout(ap, map));
+-      return;
++      return ret;
+ }
+ static void *do_readmap(void *arg)
+@@ -480,9 +481,12 @@ static void *do_readmap(void *arg)
+                       mc = map->mc;
+                       pthread_cleanup_push(cache_lock_cleanup, mc);
+                       cache_readlock(mc);
++restart:
+                       me = cache_enumerate(mc, NULL);
+                       while (me) {
+-                              do_readmap_mount(ap, map, me, now);
++                              int ret = do_readmap_mount(ap, map, me, now);
++                              if (ret == -1)
++                                      goto restart;
+                               me = cache_enumerate(mc, me);
+                       }
+                       lookup_prune_one_cache(ap, map->mc, now);
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-double-free-in-parse_mapent.patch b/archive-patches/autofs5/autofs-5.1.7-fix-double-free-in-parse_mapent.patch
new file mode 100644 (file)
index 0000000..64ec0c8
--- /dev/null
@@ -0,0 +1,39 @@
+autofs-5.1.7 - fix double free in parse_mapent()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity:
+in parse_mapent(): double_free: Calling "free" frees pointer "newopt"
+                  which has already been freed.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |    2 --
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index ff3d88eb..81461978 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -62,6 +62,7 @@
+ - fix dead code in mnts_add_mount().
+ - fix arg not used in error print.
+ - fix missing lock release in mount_subtree().
++- fix double free in parse_mapent().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 5d15f892..03a63290 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -974,8 +974,6 @@ static int parse_mapent(const char *ent, char *g_options, char **options, char *
+                                       estr = strerror_r(errno, buf, MAX_ERR_BUF);
+                                       error(logopt, MODPREFIX
+                                             "concat_options: %s", estr);
+-                                      if (newopt)
+-                                              free(newopt);
+                                       free(myoptions);
+                                       return 0;
+                               }
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-double-unlock-in-parse_mount.patch b/archive-patches/autofs5/autofs-5.1.7-fix-double-unlock-in-parse_mount.patch
new file mode 100644 (file)
index 0000000..d08b942
--- /dev/null
@@ -0,0 +1,37 @@
+autofs-5.1.7 - fix double unlock in parse_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: double_unlock: "cache_unlock" unlocks "mc->rwlock" while it
+         is unlocked.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |    1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 2e3b9fd7..224f58d6 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -54,6 +54,7 @@
+ - remove redundant if check.
+ - fix possible memory leak in master_parse().
+ - fix possible memory leak in mnts_add_amdmount().
++- fix double unlock in parse_mount().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index a81d4028..05f53fc2 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1526,7 +1526,6 @@ dont_expand:
+                       if (!loc) {
+                               free(options);
+                               free(pmapent);
+-                              cache_unlock(mc);
+                               warn(ap->logopt, MODPREFIX "out of memory");
+                               return 1;
+                       }
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-flag-check-in-umount_multi.patch b/archive-patches/autofs5/autofs-5.1.7-fix-flag-check-in-umount_multi.patch
new file mode 100644 (file)
index 0000000..eaa784c
--- /dev/null
@@ -0,0 +1,38 @@
+autofs-5.1.7 - fix flags check in umount_multi()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: operator_confusion: "ap->flags | 1" is always 1/true
+         regardless of the values of its operand.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 9e385ba9..7add6c55 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -56,6 +56,7 @@
+ - fix possible memory leak in mnts_add_amdmount().
+ - fix double unlock in parse_mount().
+ - add length check in umount_subtree_mounts().
++- fix flags check in umount_multi().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 70506d83..23235a7d 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -662,7 +662,7 @@ int umount_multi(struct autofs_point *ap, const char *path, int incl)
+               /* Check if the autofs mount has browse mode enabled.
+                * If so re-create the directory entry.
+                */
+-              if (ap->flags | MOUNT_FLAG_GHOST) {
++              if (ap->flags & MOUNT_FLAG_GHOST) {
+                       int ret;
+                       /* If the browse directory create fails log an
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-hosts-map-offset-order.patch b/archive-patches/autofs5/autofs-5.1.7-fix-hosts-map-offset-order.patch
new file mode 100644 (file)
index 0000000..4d41c30
--- /dev/null
@@ -0,0 +1,300 @@
+autofs-5.1.7 - fix hosts map offset order
+
+From: Ian Kent <raven@themaw.net>
+
+Map entry offset paths need to be in shortest to longest order but
+exports from a server could come in any order. If there are a large
+number of exports this can result in a lot of overhead when adding
+the offset to the ordered list used to mount the offset during parsing
+since the path length of exports can vary a lot.
+
+So leverage the tree implemention to sort the export offsets into
+shortest to longest order as we go when constructing the mapent from
+the exports list.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ include/automount.h    |    2 +
+ include/mounts.h       |    8 ++++++
+ include/rpc_subs.h     |    3 ++
+ lib/mounts.c           |   57 ++++++++++++++++++++++++++++++++++++++--
+ modules/lookup_hosts.c |   69 ++++++++++++++++++++++++++++++++++++++----------
+ 6 files changed, 123 insertions(+), 17 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 81b6ce6a..9e341e06 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -74,6 +74,7 @@
+ - fix offset entries order.
+ - use mapent tree root for tree_mapent_add_node().
+ - eliminate redundant cache lookup in tree_mapent_add_node().
++- fix hosts map offset order.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/automount.h b/include/automount.h
+index d279744d..947ed16d 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -31,9 +31,9 @@
+ #include "master.h"
+ #include "macros.h"
+ #include "log.h"
++#include "mounts.h"
+ #include "rpc_subs.h"
+ #include "parse_subs.h"
+-#include "mounts.h"
+ #include "dev-ioctl-lib.h"
+ #include "parse_amd.h"
+diff --git a/include/mounts.h b/include/mounts.h
+index 5a7a0b89..ddb7e4c5 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -52,6 +52,7 @@ extern const unsigned int t_direct;
+ extern const unsigned int t_offset;
+ struct mnt_list;
++struct exportinfo;
+ struct mapent;
+ struct tree_ops;
+@@ -66,6 +67,9 @@ struct tree_node {
+ #define MNT_LIST(n)           (container_of(n, struct mnt_list, node))
+ #define MNT_LIST_NODE(ptr)    ((struct tree_node *) &((struct mnt_list *) ptr)->node)
++#define EXPORTINFO(n)         (container_of(n, struct exportinfo, node))
++#define EXPORT_NODE(ptr)      ((struct tree_node *) &((struct exportinfo *) ptr)->node)
++
+ #define MAPENT(n)             (container_of(n, struct mapent, node))
+ #define MAPENT_NODE(p)                ((struct tree_node *) &((struct mapent *) p)->node)
+ #define MAPENT_ROOT(p)                ((struct tree_node *) ((struct mapent *) p)->mm_root)
+@@ -166,9 +170,13 @@ struct mnt_list *mnts_add_mount(struct autofs_point *ap, const char *name, unsig
+ void mnts_remove_mount(const char *mp, unsigned int flags);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+ 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);
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
++struct tree_node *tree_host_root(struct exportinfo *exp);
++struct tree_node *tree_host_add_node(struct tree_node *root, struct exportinfo *exp);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+ int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, struct mapent *me);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+diff --git a/include/rpc_subs.h b/include/rpc_subs.h
+index 080f19d9..debf2df0 100644
+--- a/include/rpc_subs.h
++++ b/include/rpc_subs.h
+@@ -23,6 +23,8 @@
+ #include <linux/nfs2.h>
+ #include <linux/nfs3.h>
++#include "automount.h"
++
+ #define NFS4_VERSION          4
+ /* rpc helper subs */
+@@ -57,6 +59,7 @@ struct exportinfo {
+       char *dir;
+       struct hostinfo *hosts;
+       struct exportinfo *next;
++      struct tree_node node;
+ };
+ struct conn_info {
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 6b24a6c2..5a4602e3 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -79,6 +79,17 @@ static struct tree_ops mnt_ops = {
+ };
+ static struct tree_ops *tree_mnt_ops = &mnt_ops;
++static struct tree_node *tree_host_new(void *ptr);
++static int tree_host_cmp(struct tree_node *n, void *ptr);
++static void tree_host_free(struct tree_node *n);
++
++static struct tree_ops host_ops = {
++      .new = tree_host_new,
++      .cmp = tree_host_cmp,
++      .free = tree_host_free,
++};
++static struct tree_ops *tree_host_ops = &host_ops;
++
+ static struct tree_node *tree_mapent_new(void *ptr);
+ static int tree_mapent_cmp(struct tree_node *n, void *ptr);
+ static void tree_mapent_free(struct tree_node *n);
+@@ -1341,7 +1352,7 @@ static struct tree_node *tree_add_node(struct tree_node *root, void *ptr)
+       return NULL;
+ }
+-static void tree_free(struct tree_node *root)
++void tree_free(struct tree_node *root)
+ {
+       struct tree_ops *ops = root->ops;
+@@ -1352,7 +1363,7 @@ static void tree_free(struct tree_node *root)
+       ops->free(root);
+ }
+-static int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr)
++int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr)
+ {
+       int ret;
+@@ -1479,6 +1490,48 @@ void mnts_put_expire_list(struct list_head *mnts)
+       mnts_hash_mutex_unlock();
+ }
++struct tree_node *tree_host_root(struct exportinfo *exp)
++{
++      return tree_root(tree_host_ops, exp);
++}
++
++static struct tree_node *tree_host_new(void *ptr)
++{
++      struct tree_node *n = EXPORT_NODE(ptr);
++
++      n->ops = tree_host_ops;
++      n->left = NULL;
++      n->right = NULL;
++
++      return n;
++}
++
++static int tree_host_cmp(struct tree_node *n, void *ptr)
++{
++      struct exportinfo *n_exp = EXPORTINFO(n);
++      size_t n_exp_len = strlen(n_exp->dir);
++      struct exportinfo *exp = ptr;
++      size_t exp_len = strlen(exp->dir);
++      int eq;
++
++      eq = strcmp(exp->dir, n_exp->dir);
++      if (!eq)
++              return 0;
++      return (exp_len < n_exp_len) ? -1 : 1;
++}
++
++static void tree_host_free(struct tree_node *n)
++{
++      n->ops = NULL;
++      n->left = NULL;
++      n->right = NULL;
++}
++
++struct tree_node *tree_host_add_node(struct tree_node *root, struct exportinfo *exp)
++{
++      return tree_add_node(root, exp);
++}
++
+ struct tree_node *tree_mapent_root(struct mapent *me)
+ {
+       return tree_root(tree_mapent_ops, me);
+diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
+index 24edf00c..26c224f6 100644
+--- a/modules/lookup_hosts.c
++++ b/modules/lookup_hosts.c
+@@ -84,14 +84,38 @@ int lookup_read_master(struct master *master, time_t age, void *context)
+       return NSS_STATUS_UNKNOWN;
+ }
++struct work_info {
++      char *mapent;
++      const char *host;
++      int pos;
++};
++
++static int tree_host_work(struct tree_node *n, void *ptr)
++{
++      struct exportinfo *exp = EXPORTINFO(n);
++      struct work_info *wi = ptr;
++      int len;
++
++      if (!wi->pos)
++              len = sprintf(wi->mapent, "\"%s\" \"%s:%s\"",
++                              exp->dir, wi->host, exp->dir);
++      else
++              len = sprintf(wi->mapent + wi->pos, " \"%s\" \"%s:%s\"",
++                              exp->dir, wi->host, exp->dir);
++      wi->pos += len;
++
++      return 1;
++}
++
+ static char *get_exports(struct autofs_point *ap, const char *host)
+ {
+       char buf[MAX_ERR_BUF];
+       char *mapent;
+       struct exportinfo *exp, *this;
++      struct tree_node *tree = NULL;
++      struct work_info wi;
+       size_t hostlen = strlen(host);
+       size_t mapent_len;
+-      int len, pos;
+       debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+@@ -100,7 +124,28 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+       this = exp;
+       mapent_len = 0;
+       while (this) {
++              struct tree_node *n;
++
+               mapent_len += hostlen + 2*(strlen(this->dir) + 2) + 3;
++
++              if (!tree) {
++                      tree = tree_host_root(this);
++                      if (!tree) {
++                              error(ap->logopt, "failed to create exports tree root");
++                              rpc_exports_free(exp);
++                              return NULL;
++                      }
++                      goto next;
++              }
++
++              n = tree_host_add_node(tree, this);
++              if (!n) {
++                      error(ap->logopt, "failed to add exports tree node");
++                      tree_free(tree);
++                      rpc_exports_free(exp);
++                      return NULL;
++              }
++next:
+               this = this->next;
+       }
+@@ -115,20 +160,16 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+       }
+       *mapent = 0;
+-      pos = 0;
+-      this = exp;
+-      if (this) {
+-              len = sprintf(mapent, "\"%s\" \"%s:%s\"",
+-                              this->dir, host, this->dir);
+-              pos += len;
+-              this = this->next;
+-      }
++      wi.mapent = mapent;
++      wi.host = host;
++      wi.pos = 0;
+-      while (this) {
+-              len = sprintf(mapent + pos, " \"%s\" \"%s:%s\"",
+-                              this->dir, host, this->dir);
+-              pos += len;
+-              this = this->next;
++      if (!tree) {
++              free(mapent);
++              mapent = NULL;
++      } else {
++              tree_traverse_inorder(tree, tree_host_work, &wi);
++              tree_free(tree);
+       }
+       rpc_exports_free(exp);
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch b/archive-patches/autofs5/autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch
new file mode 100644 (file)
index 0000000..34f3171
--- /dev/null
@@ -0,0 +1,251 @@
+autofs-5.1.7 - fix inconsistent locking in parse_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+Some map entry cache locking inconsistencies have crept in.
+
+In parse_mount() of the sun format parser the cache read lock is too
+heavily used and has too broad a scope. This has lead to some operations
+that should hold the write lock being called with only the read lock.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/mounts.c        |    9 ++++++++-
+ modules/parse_sun.c |   53 ++++++++++++++++++++++++++++++++-------------------
+ 3 files changed, 42 insertions(+), 21 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index c60a9ed3..d25b19c8 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -18,6 +18,7 @@
+ - fix inconsistent locking in umount_subtree_mounts().
+ - fix return from umount_subtree_mounts() on offset list delete.
+ - pass mapent_cache to update_offset_entry().
++- fix inconsistent locking in parse_mount().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 5ebfe5fd..0fcd4087 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2491,6 +2491,12 @@ static int do_mount_autofs_offset(struct autofs_point *ap,
+               else {
+                       debug(ap->logopt, "ignoring \"nohide\" trigger %s",
+                             oe->key);
++                      /*
++                       * Ok, so we shouldn't modify the mapent but
++                       * mount requests are blocked at a point above
++                       * this and expire only uses the mapent key or
++                       * holds the cache write lock.
++                       */
+                       free(oe->mapent);
+                       oe->mapent = NULL;
+               }
+@@ -2634,7 +2640,8 @@ static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const ch
+                       /*
+                        * Ok, so we shouldn't modify the mapent but
+                        * mount requests are blocked at a point above
+-                       * this and expire only uses the mapent key.
++                       * this and expire only uses the mapent key or
++                       * holds the cache write lock.
+                        */
+                       if (oe->mapent) {
+                               free(oe->mapent);
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 95251bee..a6630a76 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -851,10 +851,12 @@ update_offset_entry(struct autofs_point *ap,
+                       strcpy(m_mapent, loc);
+       }
++      cache_writelock(mc);
+       ret = cache_update_offset(mc, name, m_key, m_mapent, age);
+       if (!cache_set_offset_parent(mc, m_key))
+               error(ap->logopt, "failed to set offset parent");
++      cache_unlock(mc);
+       if (ret == CHE_DUPLICATE) {
+               warn(ap->logopt, MODPREFIX
+@@ -1128,14 +1130,22 @@ static void cleanup_multi_triggers(struct autofs_point *ap,
+       return;
+ }
+-static int mount_subtree(struct autofs_point *ap, struct mapent *me,
++static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+                        const char *name, char *loc, char *options, void *ctxt)
+ {
++      struct mapent *me;
+       struct mapent *ro;
+       char *mm_root, *mm_base, *mm_key;
+       unsigned int mm_root_len;
+       int start, ret = 0, rv;
++      cache_readlock(mc);
++      me = cache_lookup_distinct(mc, name);
++      if (!me) {
++              cache_unlock(mc);
++              return 0;
++      }
++
+       rv = 0;
+       mm_key = me->multi->key;
+@@ -1180,9 +1190,12 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+                       rv = parse_mapent(ro->mapent,
+                               options, &myoptions, &ro_loc, ap->logopt);
+                       if (!rv) {
++                              cache_unlock(mc);
+                               warn(ap->logopt,
+                                     MODPREFIX "failed to parse root offset");
+-                              cache_delete_offset_list(me->mc, name);
++                              cache_writelock(mc);
++                              cache_delete_offset_list(mc, name);
++                              cache_unlock(mc);
+                               return 1;
+                       }
+                       ro_len = 0;
+@@ -1199,9 +1212,10 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+               if ((ro && rv == 0) || rv <= 0) {
+                       ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+                       if (ret == -1) {
++                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++                              cache_unlock(mc);
+                               error(ap->logopt, MODPREFIX
+                                        "failed to mount offset triggers");
+-                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+                               return 1;
+                       }
+               }
+@@ -1217,9 +1231,10 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+               if (rv == 0) {
+                       ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
+                       if (ret == -1) {
++                              cleanup_multi_triggers(ap, me, name, start, mm_base);
++                              cache_unlock(mc);
+                               error(ap->logopt, MODPREFIX
+                                        "failed to mount offset triggers");
+-                              cleanup_multi_triggers(ap, me, name, start, mm_base);
+                               return 1;
+                       }
+               } else if (rv < 0) {
+@@ -1227,8 +1242,11 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+                       unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
+       
+                       if (mm_root_base_len > PATH_MAX) {
++                              cache_unlock(mc);
+                               warn(ap->logopt, MODPREFIX "path too long");
+-                              cache_delete_offset_list(me->mc, name);
++                              cache_writelock(mc);
++                              cache_delete_offset_list(mc, name);
++                              cache_unlock(mc);
+                               return 1;
+                       }
+@@ -1237,13 +1255,15 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+                       ret = mount_multi_triggers(ap, me->multi, mm_root_base, start, mm_base);
+                       if (ret == -1) {
++                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++                              cache_unlock(mc);
+                               error(ap->logopt, MODPREFIX
+                                        "failed to mount offset triggers");
+-                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+                               return 1;
+                       }
+               }
+       }
++      cache_unlock(mc);
+       /* Mount for base of tree failed */
+       if (rv > 0)
+@@ -1484,7 +1504,6 @@ dont_expand:
+                       return 1;
+               }
+-              cache_multi_writelock(me);
+               /* So we know we're the multi-mount root */
+               if (!me->multi)
+                       me->multi = me;
+@@ -1509,14 +1528,13 @@ dont_expand:
+                       if (source->flags & MAP_FLAG_FORMAT_AMD) {
+                               free(options);
+                               free(pmapent);
+-                              cache_multi_unlock(me);
+                               cache_unlock(mc);
+                               pthread_setcancelstate(cur_state, NULL);
+                               return 0;
+                       }
+               }
+-
+               age = me->age;
++              cache_unlock(mc);
+               /* It's a multi-mount; deal with it */
+               do {
+@@ -1537,8 +1555,8 @@ dont_expand:
+                       if (!path) {
+                               warn(ap->logopt, MODPREFIX "null path or out of memory");
++                              cache_writelock(mc);
+                               cache_delete_offset_list(mc, name);
+-                              cache_multi_unlock(me);
+                               cache_unlock(mc);
+                               free(options);
+                               free(pmapent);
+@@ -1554,8 +1572,8 @@ dont_expand:
+                       l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
+                       if (!l) {
++                              cache_writelock(mc);
+                               cache_delete_offset_list(mc, name);
+-                              cache_multi_unlock(me);
+                               cache_unlock(mc);
+                               free(path);
+                               free(options);
+@@ -1573,8 +1591,8 @@ dont_expand:
+                       if (status != CHE_OK) {
+                               warn(ap->logopt, MODPREFIX "error adding multi-mount");
++                              cache_writelock(mc);
+                               cache_delete_offset_list(mc, name);
+-                              cache_multi_unlock(me);
+                               cache_unlock(mc);
+                               free(path);
+                               free(options);
+@@ -1592,10 +1610,7 @@ dont_expand:
+                       free(myoptions);
+               } while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+-              rv = mount_subtree(ap, me, name, NULL, options, ctxt);
+-
+-              cache_multi_unlock(me);
+-              cache_unlock(mc);
++              rv = mount_subtree(ap, mc, name, NULL, options, ctxt);
+               free(options);
+               free(pmapent);
+@@ -1616,6 +1631,7 @@ dont_expand:
+               cache_readlock(mc);
+               if (*name == '/' &&
+                  (me = cache_lookup_distinct(mc, name)) && me->multi) {
++                      cache_unlock(mc);
+                       loc = strdup(p);
+                       if (!loc) {
+                               free(options);
+@@ -1624,10 +1640,7 @@ dont_expand:
+                               warn(ap->logopt, MODPREFIX "out of memory");
+                               return 1;
+                       }
+-                      cache_multi_writelock(me);
+-                      rv = mount_subtree(ap, me, name, loc, options, ctxt);
+-                      cache_multi_unlock(me);
+-                      cache_unlock(mc);
++                      rv = mount_subtree(ap, mc, name, loc, options, ctxt);
+                       free(loc);
+                       free(options);
+                       free(pmapent);
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch b/archive-patches/autofs5/autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch
new file mode 100644 (file)
index 0000000..817d7f3
--- /dev/null
@@ -0,0 +1,135 @@
+autofs-5.1.7 - fix inconsistent locking in umount_subtree_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Some map entry cache locking inconsistencies have crept in.
+
+In umount_subtree_mounts() the cache write lock should be held when
+deleting multi-mount cache entries.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |   42 ++++++++++++++++++++++++++++++------------
+ lib/mounts.c       |    8 --------
+ 3 files changed, 31 insertions(+), 20 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 1dded118..64e619ec 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -15,6 +15,7 @@
+ - eliminate clean_stale_multi_triggers().
+ - simplify mount_subtree() mount check.
+ - fix mnts_get_expire_list() expire list construction.
++- fix inconsistent locking in umount_subtree_mounts().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 7fa92877..93bd8556 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -527,8 +527,11 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+       struct mapent_cache *mc;
+       struct mapent *me;
+       unsigned int is_mm_root = 0;
++      int cur_state;
+       int left;
++      pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
++
+       me = lookup_source_mapent(ap, path, LKP_DISTINCT);
+       if (!me) {
+               char *ind_key;
+@@ -548,11 +551,11 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+       left = 0;
+       if (me && me->multi) {
+-              char root[PATH_MAX];
++              char root[PATH_MAX + 1];
++              char key[PATH_MAX + 1];
++              struct mapent *tmp;
++              int status;
+               char *base;
+-              int cur_state;
+-
+-              pthread_cleanup_push(cache_lock_cleanup, mc);
+               if (!strchr(me->multi->key, '/'))
+                       /* Indirect multi-mount root */
+@@ -567,25 +570,40 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+               else
+                       base = me->key + strlen(root);
+-              pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-              /* Lock the closest parent nesting point for umount */
+-              cache_multi_writelock(me->parent);
+-              if (umount_multi_triggers(ap, me, root, base)) {
++              left = umount_multi_triggers(ap, me, root, base);
++              if (left) {
+                       warn(ap->logopt,
+                            "some offset mounts still present under %s", path);
++              }
++
++              strcpy(key, me->key);
++
++              cache_unlock(mc);
++              cache_writelock(mc);
++              tmp = cache_lookup_distinct(mc, key);
++              /* mapent went away while we waited? */
++              if (tmp != me) {
++                      cache_unlock(mc);
++                      pthread_setcancelstate(cur_state, NULL);
++                      return 0;
++              }
++
++              if (!left && is_mm_root) {
++                      status = cache_delete_offset_list(mc, me->key);
++                      if (status != CHE_OK)
++                              warn(ap->logopt, "couldn't delete offset list");
+                       left++;
+               }
+-              cache_multi_unlock(me->parent);
++
+               if (ap->entry->maps &&
+                   (ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD))
+                       cache_pop_mapent(me);
+-              pthread_setcancelstate(cur_state, NULL);
+-              pthread_cleanup_pop(0);
+       }
+-
+       if (me)
+               cache_unlock(mc);
++      pthread_setcancelstate(cur_state, NULL);
++
+       if (left || is_autofs_fs)
+               return left;
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 87813b16..5ebfe5fd 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2736,9 +2736,6 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+       left = do_umount_multi_triggers(ap, me, root, base);
+       if (!left && me->multi == me) {
+-              struct mapent_cache *mc = me->mc;
+-              int status;
+-
+               /*
+                * Special case.
+                * If we can't umount the root container then we can't
+@@ -2756,11 +2753,6 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+                       }
+               }
+-              /* We're done - clean out the offsets */
+-              status = cache_delete_offset_list(mc, me->key);
+-              if (status != CHE_OK)
+-                      warn(ap->logopt, "couldn't delete offset list");
+-
+              /* check for mounted mount entry and remove it if found */
+                mnts_remove_mount(root, MNTS_MOUNTED);
+       }
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch b/archive-patches/autofs5/autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch
new file mode 100644 (file)
index 0000000..8eebf47
--- /dev/null
@@ -0,0 +1,64 @@
+autofs-5.1.7 - fix is mounted check on non existent path
+
+From: Ian Kent <raven@themaw.net>
+
+When checking if a path is a mount point the case of a non-existent path
+was not being handled.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/dev-ioctl-lib.c |    3 +++
+ lib/mounts.c        |   12 +++++++++++-
+ 3 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 484bd866..e55fd66a 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -6,6 +6,7 @@
+ - fix mnts_remove_amdmount() uses wrong list.
+ - Fix option for master read wait.
+ - eliminate cache_lookup_offset() usage.
++- fix is mounted check on non existent path.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/dev-ioctl-lib.c b/lib/dev-ioctl-lib.c
+index e8519236..7040c3da 100644
+--- a/lib/dev-ioctl-lib.c
++++ b/lib/dev-ioctl-lib.c
+@@ -759,6 +759,9 @@ static int dev_ioctl_ismountpoint(unsigned int logopt,
+               int save_errno = errno;
+               free_dev_ioctl_path(param);
+               errno = save_errno;
++              /* Path doesn't exist */
++              if (errno == ENOENT)
++                      return 0;
+               return -1;
+       }
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 42e8ef07..fe931b20 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1649,8 +1649,18 @@ static int table_is_mounted(const char *mp, unsigned int type)
+       struct mntent mnt_wrk;
+       char buf[PATH_MAX * 3];
+       size_t mp_len = strlen(mp);
++      struct stat st;
+       FILE *tab;
+-      int ret = 0;
++      int ret;
++
++      ret = stat(mp, &st);
++      if (ret == -1) {
++              if (errno == ENOENT) {
++                      /* Path does not exist */
++                      return 0;
++              }
++              ret = 0;
++      }
+       if (!mp || !mp_len || mp_len >= PATH_MAX)
+               return 0;
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch b/archive-patches/autofs5/autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch
new file mode 100644 (file)
index 0000000..f157755
--- /dev/null
@@ -0,0 +1,60 @@
+autofs-5.1.7 - fix lookup_prune_one_cache() refactoring change
+
+From: Ian Kent <raven@themaw.net>
+
+Commit 256963d6b (autofs-5.1.7 - refactor lookup_prune_one_cache() a bit)
+changed the position of the getting the next enumeration map entry but
+failed to update a couple of other locations that assume the next map
+entry has been set. Under certain fairly common conditions this leads
+to an infinite loop.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/lookup.c |    5 ++++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 51e7767e..698cc27a 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -69,6 +69,7 @@
+ - fix amd section mounts map reload.
+ - fix dandling symlink creation if nis support is not available.
+ - dont use AUTOFS_DEV_IOCTL_CLOSEMOUNT.
++- fix lookup_prune_one_cache() refactoring change.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/lookup.c b/daemon/lookup.c
+index 3e9722e4..0b281f83 100644
+--- a/daemon/lookup.c
++++ b/daemon/lookup.c
+@@ -1379,6 +1379,7 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti
+               if (!key || strchr(key, '*')) {
+                       if (key)
+                               free(key);
++                      me = cache_enumerate(mc, me);
+                       continue;
+               }
+@@ -1386,6 +1387,7 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti
+               if (!path) {
+                       warn(ap->logopt, "can't malloc storage for path");
+                       free(key);
++                      me = cache_enumerate(mc, me);
+                       continue;
+               }
+@@ -1413,9 +1415,10 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti
+               }
+               if (!valid &&
+                   is_mounted(path, MNTS_REAL)) {
+-                      debug(ap->logopt, "prune posponed, %s mounted", path);
++                      debug(ap->logopt, "prune postponed, %s mounted", path);
+                       free(key);
+                       free(path);
++                      me = cache_enumerate(mc, me);
+                       continue;
+               }
+               if (valid)
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch b/archive-patches/autofs5/autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch
new file mode 100644 (file)
index 0000000..8b1d211
--- /dev/null
@@ -0,0 +1,36 @@
+autofs-5.1.7 - fix missing lock release in mount_subtree()
+
+From: Ian Kent <raven@themaw.net>
+
+Covarity: missing_unlock: Returning without unlocking "mc->rwlock".
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |    1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 1d56c96f..ff3d88eb 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -61,6 +61,7 @@
+ - remove redundant assignment in master_add_amd_mount_section_mounts().
+ - fix dead code in mnts_add_mount().
+ - fix arg not used in error print.
++- fix missing lock release in mount_subtree().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 05f53fc2..5d15f892 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1105,6 +1105,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+               len = mount_fullpath(key, PATH_MAX, ap->path, ap->len, me->key);
+               if (!len) {
+                       warn(ap->logopt, "path loo long");
++                      cache_unlock(mc);
+                       return 1;
+               }
+               key[len] = '/';
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch b/archive-patches/autofs5/autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch
new file mode 100644 (file)
index 0000000..b09b045
--- /dev/null
@@ -0,0 +1,40 @@
+autofs-5.1.7 - fix mnts_get_expire_list() expire list construction
+
+From: Ian Kent <raven@themaw.net>
+
+The mnts_get_expire_list() function is supposed to return an ordered
+list of expire candidates but it is not checking the mounted status
+of list entries and is returning a larger list than is needed.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    3 +++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index f5c5641a..1dded118 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -14,6 +14,7 @@
+ - refactor umount_multi_triggers().
+ - eliminate clean_stale_multi_triggers().
+ - simplify mount_subtree() mount check.
++- fix mnts_get_expire_list() expire list construction.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index a9abbebf..87813b16 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1364,6 +1364,9 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+       list_for_each_entry(mnt, &ap->mounts, mount) {
+               struct node *n;
++              if (!(mnt->flags & MNTS_MOUNTED))
++                      continue;
++
+               __mnts_get_mount(mnt);
+               if (!tree) {
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch b/archive-patches/autofs5/autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch
new file mode 100644 (file)
index 0000000..b1eb16e
--- /dev/null
@@ -0,0 +1,38 @@
+autofs-5.1.7 - fix mnts_remove_amdmount() uses wrong list
+
+From: Ian Kent <raven@themaw.net>
+
+Function mnts_remove_amdmount() uses the wrong list when removing an
+amd mount.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index d613e5ca..fe49740e 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -3,6 +3,7 @@
+ - remove mount.x and rpcgen dependencies.
+ - dont use realloc in host exports list processing.
+ - use sprintf() when constructing hosts mapent.
++- fix mnts_remove_amdmount() uses wrong list.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index dbeb77b5..ccbd52e0 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1124,7 +1124,7 @@ void mnts_remove_amdmount(const char *mp)
+       if (!(this && this->flags & MNTS_AMD_MOUNT))
+               goto done;
+       this->flags &= ~MNTS_AMD_MOUNT;
+-      list_del_init(&this->submount);
++      list_del_init(&this->amdmount);
+       if (this->ext_mp) {
+               free(this->ext_mp);
+               this->ext_mp = NULL;
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-mount_fullpath.patch b/archive-patches/autofs5/autofs-5.1.7-fix-mount_fullpath.patch
new file mode 100644 (file)
index 0000000..e573692
--- /dev/null
@@ -0,0 +1,67 @@
+autofs-5.1.7 - fix mount_fullpath()
+
+From: Ian Kent <raven@themaw.net>
+
+mount_fullpath() incorrecly fills fullpath with the contents of root
+when name[0] == '/'. The cases root[last] == '/' and name[0] == '/'
+need to be handled seperately.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/mounts.c        |    4 +++-
+ modules/parse_amd.c |    6 ++++--
+ 3 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 390028ac..e2fd532c 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -36,6 +36,7 @@
+ - add tree_mapent_add_node().
+ - add tree_mapent_delete_offsets().
+ - add tree_mapent_traverse_subtree().
++- fix mount_fullpath().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index fded4c09..497c28c9 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -371,8 +371,10 @@ int mount_fullpath(char *fullpath, size_t max_len,
+       /* Root offset of multi-mount or direct or offset mount.
+        * Direct or offset mount, name (or root) is absolute path.
+        */
+-      if (root[last] == '/' || *name == '/')
++      if (root[last] == '/')
+               len = snprintf(fullpath, max_len, "%s", root);
++      else if (*name == '/')
++              len = snprintf(fullpath, max_len, "%s", name);
+       else
+               len = snprintf(fullpath, max_len, "%s/%s", root, name);
+diff --git a/modules/parse_amd.c b/modules/parse_amd.c
+index 5a9079d6..64c1ce63 100644
+--- a/modules/parse_amd.c
++++ b/modules/parse_amd.c
+@@ -1177,7 +1177,8 @@ static int do_generic_mount(struct autofs_point *ap, const char *name,
+                * the automount filesystem.
+                */
+               if (!is_mounted(entry->fs, MNTS_REAL)) {
+-                      ret = do_mount(ap, entry->fs, "/", 1,
++                      ret = do_mount(ap, entry->fs,
++                                     entry->fs, strlen(entry->fs),
+                                      target, entry->type, opts);
+                       if (ret)
+                               goto out;
+@@ -1227,7 +1228,8 @@ static int do_nfs_mount(struct autofs_point *ap, const char *name,
+                                            mount_nfs->context);
+       } else {
+               if (!is_mounted(entry->fs, MNTS_REAL)) {
+-                      ret = mount_nfs->mount_mount(ap, entry->fs, "/", 1,
++                      ret = mount_nfs->mount_mount(ap, entry->fs,
++                                              entry->fs, strlen(entry->fs),
+                                               target, entry->type, opts,
+                                               mount_nfs->context);
+                       if (ret)
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch b/archive-patches/autofs5/autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch
new file mode 100644 (file)
index 0000000..ebc63af
--- /dev/null
@@ -0,0 +1,60 @@
+autofs-5.1.7 - fix nonstrict offset mount fail handling
+
+From: Ian Kent <raven@themaw.net>
+
+If a triggered offset mount fails automount is not handling nonstrict
+mount failure correctly.
+
+The nonstrict mount failure handling needs to convert an offset mount
+failure to a success if the offset subtree below the failed mount is not
+empty otherwise it must return the failure. The previous implementation
+used -1 to indicate the subtree was empty and that was used to detect
+when the mount should fail instead of converting the fail to a success.
+
+Make the new implementation do the same.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/mounts.c        |    2 +-
+ modules/parse_sun.c |    2 +-
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index f5f0da76..ecffa933 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -77,6 +77,7 @@
+ - fix hosts map offset order.
+ - fix direct mount deadlock.
+ - add missing description of null map option.
++- fix nonstrict offset mount fail handling.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 5a4602e3..4c866885 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1616,7 +1616,7 @@ static int tree_mapent_traverse_subtree(struct tree_node *n, tree_work_fn_t work
+ {
+       struct traverse_subtree_context *ctxt = ptr;
+       struct mapent *oe = MAPENT(n);
+-      int ret = 1;
++      int ret = -1;
+       if (n->left) {
+               ret = tree_mapent_traverse_subtree(n->left, work, ctxt);
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 12844a30..cdf515c6 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1181,7 +1181,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+                * offsets to be mounted.
+                */
+               rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
+-              if (rv == 0) {
++              if (rv <= 0) {
+                       ret = tree_mapent_mount_offsets(me, 1);
+                       if (!ret) {
+                               tree_mapent_cleanup_offsets(me);
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-offset-entries-order.patch b/archive-patches/autofs5/autofs-5.1.7-fix-offset-entries-order.patch
new file mode 100644 (file)
index 0000000..ff216b4
--- /dev/null
@@ -0,0 +1,207 @@
+autofs-5.1.7 - fix offset entries order
+
+From: Ian Kent <raven@themaw.net>
+
+While it's rare it's possible that a mapent entry might not have
+it's offsets in shortest to longest path order.
+
+If this happens adding an entry to the mapent tree can result in
+an incorrect tree topology that doesn't work. That's because adding
+tree entries ensures that nodes in a sub-tree are placed below the
+containing node so the containing node must be present for that to
+work. This topology is critical to the performance of map entries
+that have a very large number of offsets such as an NFS server with
+many exports.
+
+There's no other choice but make a traversal after the offset entries
+have all been added to create the mapent tree.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    1 +
+ lib/cache.c         |    1 +
+ modules/parse_sun.c |   74 +++++++++++++++++++++++++++++++++++++++++----------
+ 4 files changed, 62 insertions(+), 15 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 94eb6a2c..7b360f52 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -71,6 +71,7 @@
+ - dont use AUTOFS_DEV_IOCTL_CLOSEMOUNT.
+ - fix lookup_prune_one_cache() refactoring change.
+ - fix amd hosts mount expire.
++- fix offset entries order.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/automount.h b/include/automount.h
+index 51a0bf0e..d279744d 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -169,6 +169,7 @@ struct mapent {
+       /* Parent nesting point within multi-mount */
+       struct tree_node *mm_parent;
+       struct tree_node node;
++      struct list_head work;
+       char *key;
+       size_t len;
+       char *mapent;
+diff --git a/lib/cache.c b/lib/cache.c
+index ef761739..66dda5d9 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -559,6 +559,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+       me->mm_parent = NULL;
+       INIT_TREE_NODE(&me->node);
+       INIT_LIST_HEAD(&me->ino_index);
++      INIT_LIST_HEAD(&me->work);
+       me->ioctlfd = -1;
+       me->dev = (dev_t) -1;
+       me->ino = (ino_t) -1;
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 03a63290..b206a326 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -789,14 +789,15 @@ static int check_is_multi(const char *mapent)
+ static int
+ update_offset_entry(struct autofs_point *ap,
+-                  struct mapent_cache *mc, const char *name,
+-                  const char *m_root, int m_root_len,
++                  struct mapent_cache *mc, struct list_head *offsets,
++                  const char *name, const char *m_root, int m_root_len,
+                   const char *m_offset, const char *myoptions,
+                   const char *loc, time_t age)
+ {
+       char m_key[PATH_MAX + 1];
+       char m_mapent[MAPENT_MAX_LEN + 1];
+       int o_len, m_key_len, m_options_len, m_mapent_len;
++      struct mapent *me;
+       int ret;
+       memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+@@ -862,8 +863,29 @@ update_offset_entry(struct autofs_point *ap,
+       cache_writelock(mc);
+       ret = cache_update_offset(mc, name, m_key, m_mapent, age);
+-      if (!tree_mapent_add_node(mc, name, m_key))
+-              error(ap->logopt, "failed to add offset %s to tree", m_key);
++      me = cache_lookup_distinct(mc, m_key);
++      if (me && list_empty(&me->work)) {
++              struct list_head *last;
++
++              /* Offset entries really need to be in shortest to
++               * longest path order. If not and the list of offsets
++               * is large there will be a performace hit.
++               */
++              list_for_each_prev(last, offsets) {
++                      struct mapent *this;
++
++                      this = list_entry(last, struct mapent, work);
++                      if (me->len >= this->len) {
++                              if (last->next == offsets)
++                                      list_add_tail(&me->work, offsets);
++                              else
++                                      list_add_tail(&me->work, last);
++                              break;
++                      }
++              }
++              if (list_empty(&me->work))
++                      list_add(&me->work, offsets);
++      }
+       cache_unlock(mc);
+       if (ret == CHE_DUPLICATE) {
+@@ -1209,6 +1231,25 @@ static char *do_expandsunent(const char *src, const char *key,
+       return mapent;
+ }
++static void cleanup_offset_entries(struct autofs_point *ap,
++                                 struct mapent_cache *mc,
++                                 struct list_head *offsets)
++{
++      struct mapent *me, *tmp;
++      int ret;
++
++      if (list_empty(offsets))
++              return;
++      cache_writelock(mc);
++      list_for_each_entry_safe(me, tmp, offsets, work) {
++              list_del(&me->work);
++              ret = cache_delete(mc, me->key);
++              if (ret != CHE_OK)
++                      crit(ap->logopt, "failed to delete offset %s", me->key);
++      }
++      cache_unlock(mc);
++}
++
+ /*
+  * syntax is:
+  *    [-options] location [location] ...
+@@ -1228,7 +1269,8 @@ int parse_mount(struct autofs_point *ap, const char *name,
+       char buf[MAX_ERR_BUF];
+       struct map_source *source;
+       struct mapent_cache *mc;
+-      struct mapent *me;
++      struct mapent *me, *oe, *tmp;
++      LIST_HEAD(offsets);
+       char *pmapent, *options;
+       const char *p;
+       int mapent_len, rv = 0;
+@@ -1444,9 +1486,7 @@ dont_expand:
+                       if (!m_offset) {
+                               warn(ap->logopt, MODPREFIX "null path or out of memory");
+-                              cache_writelock(mc);
+-                              tree_mapent_delete_offsets(mc, name);
+-                              cache_unlock(mc);
++                              cleanup_offset_entries(ap, mc, &offsets);
+                               free(options);
+                               free(pmapent);
+                               pthread_setcancelstate(cur_state, NULL);
+@@ -1461,9 +1501,7 @@ dont_expand:
+                       l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
+                       if (!l) {
+-                              cache_writelock(mc);
+-                              tree_mapent_delete_offsets(mc, name);
+-                              cache_unlock(mc);
++                              cleanup_offset_entries(ap, mc, &offsets);
+                               free(m_offset);
+                               free(options);
+                               free(pmapent);
+@@ -1474,15 +1512,13 @@ dont_expand:
+                       p += l;
+                       p = skipspace(p);
+-                      status = update_offset_entry(ap, mc,
++                      status = update_offset_entry(ap, mc, &offsets,
+                                                    name, m_root, m_root_len,
+                                                    m_offset, myoptions, loc, age);
+                       if (status != CHE_OK) {
+                               warn(ap->logopt, MODPREFIX "error adding multi-mount");
+-                              cache_writelock(mc);
+-                              tree_mapent_delete_offsets(mc, name);
+-                              cache_unlock(mc);
++                              cleanup_offset_entries(ap, mc, &offsets);
+                               free(m_offset);
+                               free(options);
+                               free(pmapent);
+@@ -1499,6 +1535,14 @@ dont_expand:
+                       free(myoptions);
+               } while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
++              cache_writelock(mc);
++              list_for_each_entry_safe(oe, tmp, &offsets, work) {
++                      if (!tree_mapent_add_node(mc, name, oe->key))
++                              error(ap->logopt, "failed to add offset %s to tree", oe->key);
++                      list_del_init(&oe->work);
++              }
++              cache_unlock(mc);
++
+               rv = mount_subtree(ap, mc, name, NULL, options, ctxt);
+               free(options);
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch b/archive-patches/autofs5/autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch
new file mode 100644 (file)
index 0000000..c2ea9df
--- /dev/null
@@ -0,0 +1,38 @@
+autofs-5.1.7 - fix possible memory leak in master_parse()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: Overwriting "path" in "path = master_strdup(yyvsp[-1].strtype)"
+         leaks the storage that "path" points to.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG             |    1 +
+ daemon/master_parse.y |    2 ++
+ 2 files changed, 3 insertions(+)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 2186cbe3..b797f6dc 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -52,6 +52,7 @@
+ - remove unused variable from get_exports().
+ - add missing free in handle_mounts().
+ - remove redundant if check.
++- fix possible memory leak in master_parse().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/master_parse.y b/daemon/master_parse.y
+index 08e44b57..7480c36a 100644
+--- a/daemon/master_parse.y
++++ b/daemon/master_parse.y
+@@ -155,6 +155,8 @@ file: {
+ line:
+       | PATH mapspec
+       {
++              if (path)
++                      free(path);
+               path = master_strdup($1);
+               if (!path) {
+                       local_free_vars();
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch b/archive-patches/autofs5/autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch
new file mode 100644 (file)
index 0000000..5b7c9cc
--- /dev/null
@@ -0,0 +1,58 @@
+autofs-5.1.7 - fix possible memory leak in mnts_add_amdmount()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: leaked_storage: Variable "ext_mp" going out of scope leaks
+         the storage it points to.
+
+Same applies to the other duped fields destined for the mnt_list struct.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   20 ++++++++++----------
+ 2 files changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index b797f6dc..2e3b9fd7 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -53,6 +53,7 @@
+ - add missing free in handle_mounts().
+ - remove redundant if check.
+ - fix possible memory leak in master_parse().
++- fix possible memory leak in mnts_add_amdmount().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index c8a7bf00..ef69cec1 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1119,16 +1119,16 @@ struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *en
+       mnts_hash_mutex_lock();
+       this = mnts_get_mount(entry->path);
+-      if (this) {
+-              this->ext_mp = ext_mp;
+-              this->amd_pref = pref;
+-              this->amd_type = type;
+-              this->amd_opts = opts;
+-              this->amd_cache_opts = entry->cache_opts;
+-              this->flags |= MNTS_AMD_MOUNT;
+-              if (list_empty(&this->amdmount))
+-                      list_add_tail(&this->amdmount, &ap->amdmounts);
+-      }
++      if (!this)
++              goto fail;
++      this->ext_mp = ext_mp;
++      this->amd_pref = pref;
++      this->amd_type = type;
++      this->amd_opts = opts;
++      this->amd_cache_opts = entry->cache_opts;
++      this->flags |= MNTS_AMD_MOUNT;
++      if (list_empty(&this->amdmount))
++              list_add_tail(&this->amdmount, &ap->amdmounts);
+       mnts_hash_mutex_unlock();
+       return this;
diff --git a/archive-patches/autofs5/autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch b/archive-patches/autofs5/autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch
new file mode 100644 (file)
index 0000000..7ea2f2f
--- /dev/null
@@ -0,0 +1,44 @@
+autofs-5.1.7 - fix return from umount_subtree_mounts() on offset list delete
+
+From: Ian Kent <raven@themaw.net>
+
+When there are no mounts left in a subtree of offset mounts the offset
+list is deleted. If all goes well deleting the list this shouldn't cause
+a positive return from umount_subtree_mounts() (essentially saying that
+the umount of the subtree has not succeeded).
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    5 +++--
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 64e619ec..6e0edd74 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -16,6 +16,7 @@
+ - simplify mount_subtree() mount check.
+ - fix mnts_get_expire_list() expire list construction.
+ - fix inconsistent locking in umount_subtree_mounts().
++- fix return from umount_subtree_mounts() on offset list delete.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 93bd8556..62530b6b 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -590,9 +590,10 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+               if (!left && is_mm_root) {
+                       status = cache_delete_offset_list(mc, me->key);
+-                      if (status != CHE_OK)
++                      if (status != CHE_OK) {
+                               warn(ap->logopt, "couldn't delete offset list");
+-                      left++;
++                              left++;
++                      }
+               }
+               if (ap->entry->maps &&
diff --git a/archive-patches/autofs5/autofs-5.1.7-make-tree-implementation-data-independent.patch b/archive-patches/autofs5/autofs-5.1.7-make-tree-implementation-data-independent.patch
new file mode 100644 (file)
index 0000000..31a0d60
--- /dev/null
@@ -0,0 +1,352 @@
+autofs-5.1.7 - make tree implementation data independent
+
+From: Ian Kent <raven@themaw.net>
+
+Generalise the tree implementation so that it's independent of the
+data structure that's used.
+
+Do this by refactoring it into core tree functions and functions
+specific to the data structure to be used so that different data
+structures can be used when needed by adding an implementation for
+the data structure specific functions.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 
+ include/mounts.h |   29 +++++++++
+ lib/mounts.c     |  174 ++++++++++++++++++++++++++++++++++--------------------
+ 3 files changed, 140 insertions(+), 64 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 0dae6761..74571570 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -31,6 +31,7 @@
+ - add some multi-mount macros.
+ - remove unused functions cache_dump_multi() and cache_dump_cache().
+ - add a len field to struct autofs_point.
++- make tree implementation data independent.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/mounts.h b/include/mounts.h
+index ac480c06..71d29566 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -51,10 +51,36 @@ extern const unsigned int t_indirect;
+ extern const unsigned int t_direct;
+ extern const unsigned int t_offset;
++struct mnt_list;
+ struct mapent;
++struct tree_ops;
++
++struct tree_node {
++      struct tree_ops *ops;
++      struct tree_node *left;
++      struct tree_node *right;
++};
++#define INIT_TREE_NODE(ptr)   ((ptr)->ops = NULL, (ptr)->left = NULL, (ptr)->right = NULL)
++
++#define MNT_LIST(n)           (container_of(n, struct mnt_list, node))
++#define MNT_LIST_NODE(ptr)    ((struct tree_node *) &((struct mnt_list *) ptr)->node)
++
++typedef struct tree_node *(*tree_new_t) (void *ptr);
++typedef int  (*tree_cmp_t) (struct tree_node *n, void *ptr);
++typedef void (*tree_free_t) (struct tree_node *n);
++
++struct tree_ops {
++      tree_new_t new;
++      tree_cmp_t cmp;
++      tree_free_t free;
++};
++
++typedef int (*tree_work_fn_t) (struct tree_node *n, void *ptr);
++
+ struct mnt_list {
+       char *mp;
++      size_t len;
+       unsigned int flags;
+       /* Hash of all mounts */
+@@ -79,6 +105,9 @@ struct mnt_list {
+       unsigned int amd_cache_opts;
+       struct list_head amdmount;
++      /* Tree operations */
++      struct tree_node node;
++
+       /*
+        * List operations ie. get_mnt_list.
+        */
+diff --git a/lib/mounts.c b/lib/mounts.c
+index b478ecb4..a6d1c5a7 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -68,6 +68,17 @@ static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static DEFINE_HASHTABLE(mnts_hash, MNTS_HASH_BITS);
+ static pthread_mutex_t mnts_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
++static struct tree_node *tree_mnt_new(void *ptr);
++static int tree_mnt_cmp(struct tree_node *n, void *ptr);
++static void tree_mnt_free(struct tree_node *n);
++
++static struct tree_ops mnt_ops = {
++      .new = tree_mnt_new,
++      .cmp = tree_mnt_cmp,
++      .free = tree_mnt_free,
++};
++static struct tree_ops *tree_mnt_ops = &mnt_ops;
++
+ unsigned int linux_version_code(void)
+ {
+       struct utsname my_utsname;
+@@ -904,6 +915,7 @@ static struct mnt_list *mnts_alloc_mount(const char *mp)
+               this = NULL;
+               goto done;
+       }
++      this->len = strlen(mp);
+       this->ref = 1;
+       INIT_HLIST_NODE(&this->hash);
+@@ -912,6 +924,7 @@ static struct mnt_list *mnts_alloc_mount(const char *mp)
+       INIT_LIST_HEAD(&this->submount_work);
+       INIT_LIST_HEAD(&this->amdmount);
+       INIT_LIST_HEAD(&this->expire);
++      INIT_TREE_NODE(&this->node);
+ done:
+       return this;
+ }
+@@ -1225,91 +1238,58 @@ done:
+       return has_mounted_mounts;
+ }
+-struct tree_node {
+-      struct mnt_list *mnt;
+-      struct tree_node *left;
+-      struct tree_node *right;
+-};
+-
+-static struct tree_node *tree_new(struct mnt_list *mnt)
++static inline struct tree_node *tree_root(struct tree_ops *ops, void *ptr)
+ {
+-      struct tree_node *n;
+-
+-      n = malloc(sizeof(struct tree_node));
+-      if (!n)
+-              return NULL;
+-      memset(n, 0, sizeof(struct tree_node));
+-      n->mnt = mnt;
+-
+-      return n;
+-}
+-
+-static struct tree_node *tree_root(struct mnt_list *mnt)
+-{
+-      struct tree_node *n;
+-
+-      n = tree_new(mnt);
+-      if (!n) {
+-              error(LOGOPT_ANY, "failed to allcate tree root");
+-              return NULL;
+-      }
+-
+-      return n;
++      return ops->new(ptr);
+ }
+-static struct tree_node *tree_add_left(struct tree_node *n, struct mnt_list *mnt)
++static struct tree_node *tree_add_left(struct tree_node *n, void *ptr)
+ {
+       struct tree_node *new;
+-      new = tree_new(mnt);
+-      if (!new) {
+-              error(LOGOPT_ANY, "failed to allcate tree node");
+-              return NULL;
+-      }
++      new = n->ops->new(ptr);
+       n->left = new;
+-      return n;
++      return new;
+ }
+-static struct tree_node *tree_add_right(struct tree_node *n, struct mnt_list *mnt)
++static struct tree_node *tree_add_right(struct tree_node *n, void *ptr)
+ {
+       struct tree_node *new;
+-      new = tree_new(mnt);
+-      if (!new) {
+-              error(LOGOPT_ANY, "failed to allcate tree node");
+-              return NULL;
+-      }
++      new = n->ops->new(ptr);
+       n->right = new;
+-      return n;
++      return new;
+ }
+-static struct tree_node *tree_add_node(struct tree_node *root, struct mnt_list *mnt)
++static struct tree_node *tree_add_node(struct tree_node *root, void *ptr)
+ {
+       struct tree_node *p, *q;
+-      unsigned int mp_len;
+-
+-      mp_len = strlen(mnt->mp);
++      struct tree_ops *ops = root->ops;
++      int eq;
+       q = root;
+       p = root;
+-      while (q && strcmp(mnt->mp, p->mnt->mp)) {
++      while (q) {
+               p = q;
+-              if (mp_len < strlen(p->mnt->mp))
++              eq = ops->cmp(p, ptr);
++              if (!eq)
++                      break;
++              if (eq < 0)
+                       q = p->left;
+               else
+                       q = p->right;
+       }
+-      if (strcmp(mnt->mp, p->mnt->mp) == 0)
+-              error(LOGOPT_ANY, "duplicate entry in mounts list");
++      if (!eq)
++              error(LOGOPT_ANY, "cannot add duplicate entry to tree");
+       else {
+-              if (mp_len < strlen(p->mnt->mp))
+-                      return tree_add_left(p, mnt);
++              if (eq < 0)
++                      return tree_add_left(p, ptr);
+               else
+-                      return tree_add_right(p, mnt);
++                      return tree_add_right(p, ptr);
+       }
+       return NULL;
+@@ -1317,26 +1297,92 @@ static struct tree_node *tree_add_node(struct tree_node *root, struct mnt_list *
+ static void tree_free(struct tree_node *root)
+ {
++      struct tree_ops *ops = root->ops;
++
+       if (root->right)
+               tree_free(root->right);
+       if (root->left)
+               tree_free(root->left);
+-      free(root);
++      ops->free(root);
+ }
+-static void tree_traverse(struct tree_node *n, struct list_head *mnts)
++static int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr)
+ {
+-      if (n->right)
+-              tree_traverse(n->right, mnts);
+-      list_add_tail(&n->mnt->expire, mnts);
+-      if (n->left)
+-              tree_traverse(n->left, mnts);
++      int ret;
++
++      if (n->left) {
++              ret = tree_traverse_inorder(n->left, work, ptr);
++              if (!ret)
++                      goto done;
++      }
++      ret = work(n, ptr);
++      if (!ret)
++              goto done;
++      if (n->right) {
++              ret = tree_traverse_inorder(n->right, work, ptr);
++              if (!ret)
++                      goto done;
++      }
++done:
++      return ret;
++}
++
++static struct tree_node *tree_mnt_root(struct mnt_list *mnt)
++{
++      return tree_root(tree_mnt_ops, mnt);
++}
++
++static struct tree_node *tree_mnt_new(void *ptr)
++{
++      struct tree_node *n = MNT_LIST_NODE(ptr);
++
++      n->ops = tree_mnt_ops;
++      n->left = NULL;
++      n->right = NULL;
++
++      return n;
++}
++
++static int tree_mnt_cmp(struct tree_node *n, void *ptr)
++{
++      struct mnt_list *n_mnt = MNT_LIST(n);
++      size_t n_mnt_len = n_mnt->len;
++      struct mnt_list *mnt = ptr;
++      size_t mnt_len = mnt->len;
++      int eq;
++
++      eq = strcmp(mnt->mp, n_mnt->mp);
++      if (!eq)
++              return 0;
++      return (mnt_len < n_mnt_len) ? -1 : 1;
++}
++
++static void tree_mnt_free(struct tree_node *n)
++{
++      n->ops = NULL;
++      n->left = NULL;
++      n->right = NULL;
++}
++
++static int tree_mnt_expire_list_work(struct tree_node *n, void *ptr)
++{
++      struct mnt_list *mnt = MNT_LIST(n);
++      struct list_head *mnts = ptr;
++
++      /* The expire of the root offset of an offset tree is the same
++       * as expiring the offset tree root itself (if theree is a root
++       * offset).
++       */
++      if (mnt->mp[mnt->len - 1] != '/')
++              list_add(&mnt->expire, mnts);
++
++      return 1;
+ }
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+ {
+-      struct mnt_list *mnt;
+       struct tree_node *tree = NULL;
++      struct mnt_list *mnt;
+       mnts_hash_mutex_lock();
+       if (list_empty(&ap->mounts))
+@@ -1351,7 +1397,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+               __mnts_get_mount(mnt);
+               if (!tree) {
+-                      tree = tree_root(mnt);
++                      tree = tree_mnt_root(mnt);
+                       if (!tree) {
+                               error(LOGOPT_ANY, "failed to create expire tree root");
+                               goto done;
+@@ -1367,7 +1413,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+               }
+       }
+-      tree_traverse(tree, mnts);
++      tree_traverse_inorder(tree, tree_mnt_expire_list_work, mnts);
+       tree_free(tree);
+ done:
+       mnts_hash_mutex_unlock();
diff --git a/archive-patches/autofs5/autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch b/archive-patches/autofs5/autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch
new file mode 100644 (file)
index 0000000..bb158e2
--- /dev/null
@@ -0,0 +1,118 @@
+autofs-5.1.7 - move amd mounts removal into lib/mounts.c
+
+From: Ian Kent <raven@themaw.net>
+
+Move the amd mounts removal from master_free_autofs_point() into
+lib/mounts.c along with the rest of the amd mount handling.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ daemon/master.c  |   12 +-----------
+ include/mounts.h |    1 +
+ lib/mounts.c     |   28 ++++++++++++++++++++++++----
+ 4 files changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 002da042..a9209755 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -46,6 +46,7 @@
+ - use mount_fullpath() in one spot in parse_mount().
+ - pass root length to mount_fullpath().
+ - remove unused function master_submount_list_empty().
++- move amd mounts removal into lib/mounts.c.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/master.c b/daemon/master.c
+index af9cd79f..b288e070 100644
+--- a/daemon/master.c
++++ b/daemon/master.c
+@@ -143,22 +143,12 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+ void master_free_autofs_point(struct autofs_point *ap)
+ {
+-      struct list_head *p, *head;
+       int status;
+       if (!ap)
+               return;
+-      mounts_mutex_lock(ap);
+-      head = &ap->amdmounts;
+-      p = head->next;
+-      while (p != head) {
+-              struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
+-              p = p->next;
+-              ext_mount_remove(mnt->ext_mp);
+-              mnts_remove_amdmount(mnt->mp);
+-      }
+-      mounts_mutex_unlock(ap);
++      mnts_remove_amdmounts(ap);
+       status = pthread_mutex_destroy(&ap->mounts_mutex);
+       if (status)
+diff --git a/include/mounts.h b/include/mounts.h
+index d7980976..1b376b3d 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -161,6 +161,7 @@ void mnts_remove_submount(const char *mp);
+ struct mnt_list *mnts_find_amdmount(const char *path);
+ struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *entry);
+ void mnts_remove_amdmount(const char *mp);
++void mnts_remove_amdmounts(struct autofs_point *ap);
+ 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);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 6b8e4c92..c8a7bf00 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1144,14 +1144,13 @@ fail:
+       return NULL;
+ }
+-void mnts_remove_amdmount(const char *mp)
++static void __mnts_remove_amdmount(const char *mp)
+ {
+       struct mnt_list *this;
+-      mnts_hash_mutex_lock();
+       this = mnts_lookup(mp);
+       if (!(this && this->flags & MNTS_AMD_MOUNT))
+-              goto done;
++              return;
+       this->flags &= ~MNTS_AMD_MOUNT;
+       list_del_init(&this->amdmount);
+       if (this->ext_mp) {
+@@ -1172,7 +1171,28 @@ void mnts_remove_amdmount(const char *mp)
+       }
+       this->amd_cache_opts = 0;
+       __mnts_put_mount(this);
+-done:
++}
++
++void mnts_remove_amdmount(const char *mp)
++{
++      mnts_hash_mutex_lock();
++      __mnts_remove_amdmount(mp);
++      mnts_hash_mutex_unlock();
++}
++
++void mnts_remove_amdmounts(struct autofs_point *ap)
++{
++      struct list_head *head, *p;
++
++      mnts_hash_mutex_lock();
++      head = &ap->amdmounts;
++      p = head->next;
++      while (p != head) {
++              struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
++              p = p->next;
++              ext_mount_remove(mnt->ext_mp);
++              __mnts_remove_amdmount(mnt->mp);
++      }
+       mnts_hash_mutex_unlock();
+ }
diff --git a/archive-patches/autofs5/autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch b/archive-patches/autofs5/autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch
new file mode 100644 (file)
index 0000000..1dffc83
--- /dev/null
@@ -0,0 +1,72 @@
+autofs-5.1.7 - pass mapent_cache to update_offset_entry()
+
+From: Ian Kent <raven@themaw.net>
+
+Pass mapent_cache to update_offset_entry() rather than use the wait/signal
+mechanism, it isn't needed here.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   22 ++++++----------------
+ 2 files changed, 7 insertions(+), 16 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 6e0edd74..c60a9ed3 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -17,6 +17,7 @@
+ - fix mnts_get_expire_list() expire list construction.
+ - fix inconsistent locking in umount_subtree_mounts().
+ - fix return from umount_subtree_mounts() on offset list delete.
++- pass mapent_cache to update_offset_entry().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 1142e8a3..95251bee 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -793,24 +793,17 @@ static int check_is_multi(const char *mapent)
+ }
+ static int
+-update_offset_entry(struct autofs_point *ap, const char *name,
++update_offset_entry(struct autofs_point *ap,
++                  struct mapent_cache *mc, const char *name,
+                   const char *m_root, int m_root_len,
+-                  const char *path, const char *myoptions, const char *loc,
+-                  time_t age)
++                  const char *path, const char *myoptions,
++                  const char *loc, time_t age)
+ {
+-      struct map_source *source;
+-      struct mapent_cache *mc;
+       char m_key[PATH_MAX + 1];
+       char m_mapent[MAPENT_MAX_LEN + 1];
+       int p_len, m_key_len, m_options_len, m_mapent_len;
+       int ret;
+-      source = ap->entry->current;
+-      ap->entry->current = NULL;
+-      master_source_current_signal(ap->entry);
+-
+-      mc = source->mc;
+-
+       memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+       /* Internal hosts map may have loc == NULL */
+@@ -1574,11 +1567,8 @@ dont_expand:
+                       p += l;
+                       p = skipspace(p);
+-                      master_source_current_wait(ap->entry);
+-                      ap->entry->current = source;
+-
+-                      status = update_offset_entry(ap, name,
+-                                                   m_root, m_root_len,
++                      status = update_offset_entry(ap, mc,
++                                                   name, m_root, m_root_len,
+                                                    path, myoptions, loc, age);
+                       if (status != CHE_OK) {
diff --git a/archive-patches/autofs5/autofs-5.1.7-pass-root-length-to-mount_fullpath.patch b/archive-patches/autofs5/autofs-5.1.7-pass-root-length-to-mount_fullpath.patch
new file mode 100644 (file)
index 0000000..56180c1
--- /dev/null
@@ -0,0 +1,171 @@
+autofs-5.1.7 - pass root length to mount_fullpath()
+
+From: Ian Kent <raven@themaw.net>
+
+The length of root may already be known, add a parameter to allow
+passing it to mount_fullpath() so a strlen() call can be avoided.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG               |    1 +
+ include/mounts.h        |    2 +-
+ lib/mounts.c            |   11 +++++++----
+ modules/mount_bind.c    |    2 +-
+ modules/mount_changer.c |    2 +-
+ modules/mount_ext2.c    |    2 +-
+ modules/mount_generic.c |    2 +-
+ modules/mount_nfs.c     |    2 +-
+ modules/parse_sun.c     |    4 ++--
+ 9 files changed, 16 insertions(+), 12 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 8494f0dc..1c9e2a2d 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -44,6 +44,7 @@
+ - remove obsolete functions.
+ - remove redundant local var from sun_mount().
+ - use mount_fullpath() in one spot in parse_mount().
++- pass root length to mount_fullpath().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/mounts.h b/include/mounts.h
+index ec895e1c..d7980976 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -131,7 +131,7 @@ int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *);
+ extern unsigned int nfs_mount_uses_string_options;
+ int mount_fullpath(char *fullpath, size_t max_len,
+-                 const char *root, const char *name);
++                 const char *root, size_t root_len, const char *name);
+ struct amd_entry;
+diff --git a/lib/mounts.c b/lib/mounts.c
+index c120d2a8..6b8e4c92 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -362,11 +362,14 @@ int check_nfs_mount_version(struct nfs_mount_vers *vers,
+ #endif
+ int mount_fullpath(char *fullpath, size_t max_len,
+-                 const char *root, const char *name)
++                 const char *root, size_t root_len, const char *name)
+ {
+       int last, len;
+-      last = strlen(root) - 1;
++      if (root_len)
++              last = root_len - 1;
++      else
++              last = strlen(root) - 1;
+       /* Root offset of multi-mount or direct or offset mount.
+        * Direct or offset mount, name (or root) is absolute path.
+@@ -1685,7 +1688,7 @@ void tree_mapent_cleanup_offsets(struct mapent *oe)
+       else {
+               char mp[PATH_MAX + 1];
+-              if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key))
++              if (!mount_fullpath(mp, PATH_MAX, ap->path, ap->len, oe->key))
+                       error(ap->logopt, "mount path is too long");
+               else
+                       tree_mapent_umount_mount(ap, mp);
+@@ -1922,7 +1925,7 @@ int tree_mapent_umount_offsets(struct mapent *oe, int nonstrict)
+                * one of these keys is the root of a multi-mount the mount
+                * path must be constructed.
+                */
+-              if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key)) {
++              if (!mount_fullpath(mp, PATH_MAX, ap->path, ap->len, oe->key)) {
+                       error(ap->logopt, "mount path is too long");
+                       return 0;
+               }
+diff --git a/modules/mount_bind.c b/modules/mount_bind.c
+index c17c6f18..7f64332b 100644
+--- a/modules/mount_bind.c
++++ b/modules/mount_bind.c
+@@ -122,7 +122,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
+               }
+       }
+-      len = mount_fullpath(fullpath, PATH_MAX, root, name);
++      len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+       if (!len) {
+               error(ap->logopt,
+                     MODPREFIX "mount point path too long");
+diff --git a/modules/mount_changer.c b/modules/mount_changer.c
+index d02b5f45..8adb9f9a 100644
+--- a/modules/mount_changer.c
++++ b/modules/mount_changer.c
+@@ -59,7 +59,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
+       fstype = "iso9660";
+-      len = mount_fullpath(fullpath, PATH_MAX, root, name);
++      len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+       if (!len) {
+               error(ap->logopt,
+                     MODPREFIX "mount point path too long");
+diff --git a/modules/mount_ext2.c b/modules/mount_ext2.c
+index 53e6ee10..f4002e58 100644
+--- a/modules/mount_ext2.c
++++ b/modules/mount_ext2.c
+@@ -55,7 +55,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
+       if (defaults_get_mount_verbose())
+               mountlog = &log_info;
+-      len = mount_fullpath(fullpath, PATH_MAX, root, name);
++      len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+       if (!len) {
+               error(ap->logopt,
+                     MODPREFIX "mount point path too long");
+diff --git a/modules/mount_generic.c b/modules/mount_generic.c
+index c9deb7ae..8cd0f4ab 100644
+--- a/modules/mount_generic.c
++++ b/modules/mount_generic.c
+@@ -54,7 +54,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
+       if (defaults_get_mount_verbose())
+               mountlog = &log_info;
+-      len = mount_fullpath(fullpath, PATH_MAX, root, name);
++      len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+       if (!len) {
+               error(ap->logopt,
+                     MODPREFIX "mount point path too long");
+diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
+index c70210f4..0314a78f 100644
+--- a/modules/mount_nfs.c
++++ b/modules/mount_nfs.c
+@@ -213,7 +213,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
+       }
+       /* Construct mount point directory */
+-      len = mount_fullpath(fullpath, PATH_MAX, root, name);
++      len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+       if (!len) {
+               error(ap->logopt,
+                     MODPREFIX "mount point path too long");
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index d3fc6c7f..b1c2611c 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1089,7 +1089,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+               struct mapent *ro;
+               size_t len;
+-              len = mount_fullpath(key, PATH_MAX, ap->path, me->key);
++              len = mount_fullpath(key, PATH_MAX, ap->path, ap->len, me->key);
+               if (!len) {
+                       warn(ap->logopt, "path loo long");
+                       return 1;
+@@ -1359,7 +1359,7 @@ dont_expand:
+               time_t age;
+               int l;
+-              m_root_len = mount_fullpath(m_root, PATH_MAX, ap->path, name);
++              m_root_len = mount_fullpath(m_root, PATH_MAX, ap->path, ap->len, name);
+               if (!m_root_len) {
+                       error(ap->logopt,
+                             MODPREFIX "multi-mount root path too long");
diff --git a/archive-patches/autofs5/autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch b/archive-patches/autofs5/autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch
new file mode 100644 (file)
index 0000000..54c0a50
--- /dev/null
@@ -0,0 +1,83 @@
+autofs-5.1.7 - reduce umount EBUSY check delay
+
+From: Ian Kent <raven@themaw.net>
+
+Some time ago I had to wait and retry umount() for autofs mounts
+becuase I found EBUSY would be returned for a time after the call
+causing false negative umount returns.
+
+I think that problem has been resolved but removing the retry is
+probably a little risky.
+
+But the wait time is quite long at one fifth of a second so reduce
+that to one twentieth of a second and increase the retries to make
+it more resposive.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/direct.c     |    4 ++--
+ daemon/indirect.c   |    2 +-
+ include/automount.h |    2 +-
+ 4 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index b144f6aa..6419052d 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -23,6 +23,7 @@
+ - eliminate count_mounts() from expire_proc_indirect().
+ - eliminate some strlen calls in offset handling.
+ - don't add offset mounts to mounted mounts table.
++- reduce umount EBUSY check delay.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/direct.c b/daemon/direct.c
+index fbfebbdd..5c1146a7 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -150,7 +150,7 @@ int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me)
+       retries = UMOUNT_RETRIES;
+       while ((rv = umount(me->key)) == -1 && retries--) {
+-              struct timespec tm = {0, 200000000};
++              struct timespec tm = {0, 50000000};
+               if (errno != EBUSY)
+                       break;
+               nanosleep(&tm, NULL);
+@@ -573,7 +573,7 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
+       retries = UMOUNT_RETRIES;
+       while ((rv = umount(me->key)) == -1 && retries--) {
+-              struct timespec tm = {0, 200000000};
++              struct timespec tm = {0, 50000000};
+               if (errno != EBUSY)
+                       break;
+               nanosleep(&tm, NULL);
+diff --git a/daemon/indirect.c b/daemon/indirect.c
+index eddcfff7..9f2ca6a0 100644
+--- a/daemon/indirect.c
++++ b/daemon/indirect.c
+@@ -265,7 +265,7 @@ int umount_autofs_indirect(struct autofs_point *ap, const char *root)
+       retries = UMOUNT_RETRIES;
+       while ((rv = umount(mountpoint)) == -1 && retries--) {
+-              struct timespec tm = {0, 200000000};
++              struct timespec tm = {0, 50000000};
+               if (errno != EBUSY)
+                       break;
+               nanosleep(&tm, NULL);
+diff --git a/include/automount.h b/include/automount.h
+index 69445b92..fa6f5d63 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -140,7 +140,7 @@ struct autofs_point;
+ #define NULL_MAP_HASHSIZE     64
+ #define NEGATIVE_TIMEOUT      10
+ #define POSITIVE_TIMEOUT      120
+-#define UMOUNT_RETRIES                8
++#define UMOUNT_RETRIES                16
+ #define EXPIRE_RETRIES                3
+ struct mapent_cache {
diff --git a/archive-patches/autofs5/autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch b/archive-patches/autofs5/autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch
new file mode 100644 (file)
index 0000000..e013a52
--- /dev/null
@@ -0,0 +1,75 @@
+autofs-5.1.7 - refactor lookup_prune_one_cache() a bit
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: use: Using an unreliable value of "me" inside the second locked
+         section.
+
+Change lookup_prune_one_cache() a little, move the location the next
+key is set (before releasing the lock) and add a comment explaining
+why we don't care about the side effects of the read lock release/
+write lock aquire/write lock release/read lock reaquire.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/lookup.c |   20 +++++++++++++++++++-
+ 2 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 81461978..b79aebc8 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -63,6 +63,7 @@
+ - fix arg not used in error print.
+ - fix missing lock release in mount_subtree().
+ - fix double free in parse_mapent().
++- refactor lookup_prune_one_cache() a bit.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/lookup.c b/daemon/lookup.c
+index 32dbc24d..3e9722e4 100644
+--- a/daemon/lookup.c
++++ b/daemon/lookup.c
+@@ -1375,7 +1375,6 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti
+               }
+               key = strdup(me->key);
+-              me = cache_enumerate(mc, me);
+               /* Don't consider any entries with a wildcard */
+               if (!key || strchr(key, '*')) {
+                       if (key)
+@@ -1422,6 +1421,7 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti
+               if (valid)
+                       cache_unlock(valid->mc);
++              me = cache_enumerate(mc, me);
+               if (me)
+                       next_key = strdup(me->key);
+@@ -1456,6 +1456,24 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti
+ next:
+               cache_readlock(mc);
+               if (next_key) {
++                      /* The lock release and reaquire above can mean
++                       * a number of things could happen.
++                       *
++                       * First, mapents could be added between the
++                       * current mapent and the mapent of next_key.
++                       * Don't care about that because there's no
++                       * need to prune newly added entries.
++                       *
++                       * Second, the next mapent data could have
++                       * changed. Don't care about that either since
++                       * we are looking to prune stale map entries
++                       * and don't care when they become stale.
++                       *
++                       * Finally, the mapent of next_key could have
++                       * gone away. Again don't care about this either,
++                       * the loop will exit prematurely so just wait
++                       * until the next prune and try again.
++                       */
+                       me = cache_lookup_distinct(mc, next_key);
+                       free(next_key);
+               }
diff --git a/archive-patches/autofs5/autofs-5.1.7-refactor-umount_multi_triggers.patch b/archive-patches/autofs5/autofs-5.1.7-refactor-umount_multi_triggers.patch
new file mode 100644 (file)
index 0000000..39b7e10
--- /dev/null
@@ -0,0 +1,259 @@
+autofs-5.1.7 - refactor umount_multi_triggers()
+
+From: Ian Kent <raven@themaw.net>
+
+Refactor umount_multi_triggers() to try the umount of an offset subtree
+in a seperate function.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 
+ lib/mounts.c |  187 ++++++++++++++++++++++++++++++++--------------------------
+ 2 files changed, 104 insertions(+), 84 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 3eda995c..5a3bedc1 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -11,6 +11,7 @@
+ - set offset parent in update_offset_entry().
+ - remove redundant variables from mount_autofs_offset().
+ - remove unused parameter form do_mount_autofs_offset().
++- refactor umount_multi_triggers().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 8e88182f..5268ba5b 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2496,57 +2496,6 @@ static int do_mount_autofs_offset(struct autofs_point *ap,
+       return mounted;
+ }
+-int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+-                       const char *root, unsigned int start, const char *base)
+-{
+-      char path[PATH_MAX + 1];
+-      char *offset = path;
+-      struct mapent *oe;
+-      struct list_head *pos = NULL;
+-      unsigned int root_len = strlen(root);
+-      int mounted;
+-
+-      mounted = 0;
+-      offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+-      while (offset) {
+-              char key[PATH_MAX + 1];
+-              int key_len = root_len + strlen(offset);
+-
+-              if (key_len > PATH_MAX) {
+-                      warn(ap->logopt, "path loo long");
+-                      goto cont;
+-              }
+-
+-              /* The root offset is always mounted seperately so the
+-               * offset path will always be root + offset.
+-               */
+-              strcpy(key, root);
+-              strcat(key, offset);
+-
+-              oe = cache_lookup_distinct(me->mc, key);
+-              if (!oe || !oe->mapent)
+-                      goto cont;
+-
+-              mounted += do_mount_autofs_offset(ap, oe, root);
+-
+-              /*
+-               * If re-constructing a multi-mount it's necessary to walk
+-               * into nested mounts, unlike the usual "mount only what's
+-               * needed as you go" behavior.
+-               */
+-              if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+-                      if (oe->ioctlfd != -1 ||
+-                          is_mounted(oe->key, MNTS_REAL))
+-                              mount_multi_triggers(ap, oe, key, strlen(key), base);
+-              }
+-cont:
+-              offset = cache_get_offset(base,
+-                              offset, start, &me->multi_list, &pos);
+-      }
+-
+-      return mounted;
+-}
+-
+ static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+ {
+       char *dir, *path;
+@@ -2582,7 +2531,10 @@ static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+       return ret;
+ }
+-int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
++static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root);
++
++static int do_umount_multi_triggers(struct autofs_point *ap,
++                                  struct mapent *me, const char *root, const char *base)
+ {
+       char path[PATH_MAX + 1];
+       char *offset;
+@@ -2612,7 +2564,6 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+       while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+               char key[PATH_MAX + 1];
+               int key_len = root_len + strlen(offset);
+-              char *oe_base;
+               if (mm_base_len > 1)
+                       key_len += mm_base_len;
+@@ -2632,47 +2583,116 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+               if (!oe || (strlen(oe->key) - start) == 1)
+                       continue;
++              left += do_umount_offset(ap, oe, root);
++      }
++
++      return left;
++}
++
++static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root)
++{
++      char *oe_base;
++      int left = 0;
++
++      /*
++       * Check for and umount subtree offsets resulting from
++       * nonstrict mount fail.
++       */
++      oe_base = oe->key + strlen(root);
++      left += do_umount_multi_triggers(ap, oe, root, oe_base);
++
++      if (oe->ioctlfd != -1 ||
++          is_mounted(oe->key, MNTS_REAL)) {
++              left++;
++              return left;
++      }
++
++      debug(ap->logopt, "umount offset %s", oe->key);
++
++      if (umount_autofs_offset(ap, oe)) {
++              warn(ap->logopt, "failed to umount offset");
++              left++;
++      } else {
++              struct stat st;
++              int ret;
++
++              if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
++                      return left;
++
+               /*
+-               * Check for and umount subtree offsets resulting from
+-               * nonstrict mount fail.
++               * An error due to partial directory removal is
++               * ok so only try and remount the offset if the
++               * actual mount point still exists.
+                */
+-              oe_base = oe->key + strlen(root);
+-              left += umount_multi_triggers(ap, oe, root, oe_base);
++              ret = rmdir_path_offset(ap, oe);
++              if (ret == -1 && !stat(oe->key, &st)) {
++                      ret = do_mount_autofs_offset(ap, oe, root);
++                      if (ret)
++                              left++;
++                      /* But we did origianlly create this */
++                      oe->flags |= MOUNT_FLAG_DIR_CREATED;
++              }
++      }
++      return left;
++}
+-              if (oe->ioctlfd != -1 ||
+-                  is_mounted(oe->key, MNTS_REAL)) {
+-                      left++;
+-                      continue;
++int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
++                       const char *root, unsigned int start, const char *base)
++{
++      char path[PATH_MAX + 1];
++      char *offset = path;
++      struct mapent *oe;
++      struct list_head *pos = NULL;
++      unsigned int root_len = strlen(root);
++      int mounted;
++
++      mounted = 0;
++      offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
++      while (offset) {
++              char key[PATH_MAX + 1];
++              int key_len = root_len + strlen(offset);
++
++              if (key_len > PATH_MAX) {
++                      warn(ap->logopt, "path loo long");
++                      goto cont;
+               }
+-              debug(ap->logopt, "umount offset %s", oe->key);
++              /* The root offset is always mounted seperately so the
++               * offset path will always be root + offset.
++               */
++              strcpy(key, root);
++              strcat(key, offset);
+-              if (umount_autofs_offset(ap, oe)) {
+-                      warn(ap->logopt, "failed to umount offset");
+-                      left++;
+-              } else {
+-                      struct stat st;
+-                      int ret;
++              oe = cache_lookup_distinct(me->mc, key);
++              if (!oe || !oe->mapent)
++                      goto cont;
+-                      if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
+-                              continue;
++              mounted += do_mount_autofs_offset(ap, oe, root);
+-                      /*
+-                       * An error due to partial directory removal is
+-                       * ok so only try and remount the offset if the
+-                       * actual mount point still exists.
+-                       */
+-                      ret = rmdir_path_offset(ap, oe);
+-                      if (ret == -1 && !stat(oe->key, &st)) {
+-                              ret = do_mount_autofs_offset(ap, oe, root);
+-                              if (ret)
+-                                      left++;
+-                              /* But we did origianlly create this */
+-                              oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-                      }
++              /*
++               * If re-constructing a multi-mount it's necessary to walk
++               * into nested mounts, unlike the usual "mount only what's
++               * needed as you go" behavior.
++               */
++              if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
++                      if (oe->ioctlfd != -1 ||
++                          is_mounted(oe->key, MNTS_REAL))
++                              mount_multi_triggers(ap, oe, key, strlen(key), base);
+               }
++cont:
++              offset = cache_get_offset(base,
++                              offset, start, &me->multi_list, &pos);
+       }
++      return mounted;
++}
++
++int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
++{
++      int left;
++
++      left = do_umount_multi_triggers(ap, me, root, base);
++
+       if (!left && me->multi == me) {
+               struct mapent_cache *mc = me->mc;
+               int status;
+@@ -2871,4 +2891,3 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+       return left;
+ }
+-
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch b/archive-patches/autofs5/autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch
new file mode 100644 (file)
index 0000000..4c837dc
--- /dev/null
@@ -0,0 +1,574 @@
+autofs-5.1.7 - remove mount.x and rpcgen dependencies
+
+From: Ian Kent <raven@themaw.net>
+
+Adding a local implementation to get the exports list from a server
+means the the rpcgen generataed code is no longer needed so remove
+mount.x and the build dependencies.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ Makefile.conf.in    |    1 
+ autofs.spec         |    2 
+ configure           |   58 ---------
+ configure.in        |    1 
+ include/automount.h |    1 
+ include/config.h.in |    3 
+ lib/Makefile        |   26 ----
+ lib/mount.x         |  345 ---------------------------------------------------
+ 9 files changed, 5 insertions(+), 433 deletions(-)
+ delete mode 100644 lib/mount.x
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 84050e91..19af245e 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -1,5 +1,6 @@
+ - add xdr_exports().
++- remove mount.x and rpcgen dependencies.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/Makefile.conf.in b/Makefile.conf.in
+index df678eec..12f26eb8 100644
+--- a/Makefile.conf.in
++++ b/Makefile.conf.in
+@@ -65,7 +65,6 @@ FEDFS = @ENABLE_FEDFS@
+ LEX = @PATH_LEX@
+ YACC = @PATH_YACC@
+-RPCGEN = @PATH_RPCGEN@
+ RANLIB = @PATH_RANLIB@
+ # Use libtirpc if requested and available
+diff --git a/autofs.spec b/autofs.spec
+index 3c2b144a..823735a3 100644
+--- a/autofs.spec
++++ b/autofs.spec
+@@ -39,7 +39,7 @@ BuildRequires: libtirpc-devel
+ %endif
+ BuildRequires: autoconf, openldap-devel, bison, flex, libxml2-devel
+ BuildRequires: cyrus-sasl-devel, openssl-devel, util-linux
+-BuildRequires: libtirpc-devel, rpcgen, libnsl2-devel, krb5-devel
++BuildRequires: libtirpc-devel, libnsl2-devel, krb5-devel
+ Requires: chkconfig
+ Requires: /bin/bash sed grep /bin/ps
+ %if %{with_systemd}
+diff --git a/configure b/configure
+index de968f0e..3c5fe78b 100755
+--- a/configure
++++ b/configure
+@@ -650,8 +650,6 @@ XML_CFLAGS
+ ENABLE_FEDFS
+ sssldir
+ HAVE_SSS_AUTOFS
+-PATH_RPCGEN
+-RPCGEN
+ PATH_RANLIB
+ RANLIB
+ PATH_YACC
+@@ -4205,62 +4203,6 @@ else
+   as_fn_error $? "required program RANLIB not found" "$LINENO" 5
+ fi
+-for ac_prog in rpcgen
+-do
+-  # Extract the first word of "$ac_prog", so it can be a program name with args.
+-set dummy $ac_prog; ac_word=$2
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-$as_echo_n "checking for $ac_word... " >&6; }
+-if ${ac_cv_path_RPCGEN+:} false; then :
+-  $as_echo_n "(cached) " >&6
+-else
+-  case $RPCGEN in
+-  [\\/]* | ?:[\\/]*)
+-  ac_cv_path_RPCGEN="$RPCGEN" # Let the user override the test with a path.
+-  ;;
+-  *)
+-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $searchpath
+-do
+-  IFS=$as_save_IFS
+-  test -z "$as_dir" && as_dir=.
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+-    ac_cv_path_RPCGEN="$as_dir/$ac_word$ac_exec_ext"
+-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-  ;;
+-esac
+-fi
+-RPCGEN=$ac_cv_path_RPCGEN
+-if test -n "$RPCGEN"; then
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RPCGEN" >&5
+-$as_echo "$RPCGEN" >&6; }
+-else
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-fi
+-
+-
+-  test -n "$RPCGEN" && break
+-done
+-
+-if test -n "$RPCGEN"; then
+-
+-cat >>confdefs.h <<_ACEOF
+-#define PATH_RPCGEN "$RPCGEN"
+-_ACEOF
+-
+-  PATH_RPCGEN="$RPCGEN"
+-else
+-  as_fn_error $? "required program RPCGEN not found" "$LINENO" 5
+-fi
+-
+ if test -z "$sssldir"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sssd autofs library" >&5
+diff --git a/configure.in b/configure.in
+index a38d6655..e774b4cc 100644
+--- a/configure.in
++++ b/configure.in
+@@ -164,7 +164,6 @@ AF_PATH_INCLUDE(E4FSCK, fsck.ext4 e4fsck, , $searchpath)
+ AF_CHECK_PROG(LEX, flex lex, , $searchpath)
+ AF_CHECK_PROG(YACC, bison, , $searchpath)
+ AF_CHECK_PROG(RANLIB, ranlib, , $searchpath)
+-AF_CHECK_PROG(RPCGEN, rpcgen, , $searchpath)
+ AF_CHECK_SSS_LIB(SSS_AUTOFS, libsss_autofs.so)
+ AC_SUBST(HAVE_SSS_AUTOFS)
+diff --git a/include/automount.h b/include/automount.h
+index 1ae40786..2f09e8e7 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -32,7 +32,6 @@
+ #include "macros.h"
+ #include "log.h"
+ #include "rpc_subs.h"
+-#include "mounts.h"
+ #include "parse_subs.h"
+ #include "mounts.h"
+ #include "dev-ioctl-lib.h"
+diff --git a/include/config.h.in b/include/config.h.in
+index a4879494..4e36b390 100644
+--- a/include/config.h.in
++++ b/include/config.h.in
+@@ -135,9 +135,6 @@
+ /* define if you have RANLIB */
+ #undef PATH_RANLIB
+-/* define if you have RPCGEN */
+-#undef PATH_RPCGEN
+-
+ /* define if you have UMOUNT */
+ #undef PATH_UMOUNT
+diff --git a/lib/Makefile b/lib/Makefile
+index 83a80a1e..d18c67b5 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -8,10 +8,9 @@ include ../Makefile.rules
+ SRCS = cache.c cat_path.c rpc_subs.c mounts.c log.c nsswitch.c \
+       nss_tok.c nss_parse.tab.c args.c alarm.c macros.c defaults.c \
+       parse_subs.c dev-ioctl-lib.c
+-RPCS = mount.h mount_clnt.c mount_xdr.c
+-OBJS = cache.o mount_clnt.o mount_xdr.o cat_path.o rpc_subs.o \
+-      mounts.o log.o nsswitch.o nss_tok.o nss_parse.tab.o args.o \
+-      alarm.o macros.o defaults.o parse_subs.o dev-ioctl-lib.o
++OBJS = cache.o cat_path.o rpc_subs.o mounts.o log.o nsswitch.o \
++      nss_tok.o nss_parse.tab.o args.o alarm.o macros.o defaults.o \
++      parse_subs.o dev-ioctl-lib.o
+ YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h
+@@ -33,23 +32,6 @@ libautofs.so: $(OBJS)
+       $(CC) $(SOLDFLAGS) $(CFLAGS) -o $*.so $^ $(LDFLAGS) $(LIBS)
+       $(STRIP) $*.so
+-mount.h: mount.x
+-      $(RPCGEN) -h -o mount.h mount.x
+-
+-mount_clnt.c: mount.h
+-      $(RPCGEN) -l -o mount_clnt.c mount.x
+-
+-mount_clnt.o: mount_clnt.c
+-      $(CC) $(CFLAGS) -o mount_clnt.o -c mount_clnt.c
+-      $(STRIP) mount_clnt.o
+-
+-mount_xdr.c: mount.h
+-      $(RPCGEN) -c -o mount_xdr.c mount.x
+-
+-mount_xdr.o: mount_xdr.c
+-      $(CC) $(CFLAGS) -Wno-unused-variable -o mount_xdr.o -c mount_xdr.c
+-      $(STRIP) mount_xdr.o
+-
+ nss_tok.c: nss_tok.l
+       $(LEX) -o$@ -Pnss_ $?
+@@ -60,8 +42,6 @@ nss_tok.o: nss_tok.c nss_parse.tab.h
+ nss_parse.tab.o: nss_parse.tab.c nss_parse.tab.h
+-rpc_subs.o: mount.h
+-
+ install: all
+       install -d -m 755 $(INSTALLROOT)$(autofslibdir)
+       install -c $(LIB) -m 755 $(INSTALLROOT)$(sharedlibdir)
+diff --git a/lib/mount.x b/lib/mount.x
+deleted file mode 100644
+index f504e7cf..00000000
+--- a/lib/mount.x
++++ /dev/null
+@@ -1,345 +0,0 @@
+-%/*
+-% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+-% * unrestricted use provided that this legend is included on all tape
+-% * media and as a part of the software program in whole or part.  Users
+-% * may copy or modify Sun RPC without charge, but are not authorized
+-% * to license or distribute it to anyone else except as part of a product or
+-% * program developed by the user or with the express written consent of
+-% * Sun Microsystems, Inc.
+-% *
+-% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+-% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+-% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+-% *
+-% * Sun RPC is provided with no support and without any obligation on the
+-% * part of Sun Microsystems, Inc. to assist in its use, correction,
+-% * modification or enhancement.
+-% *
+-% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+-% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+-% * OR ANY PART THEREOF.
+-% *
+-% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+-% * or profits or other special, indirect and consequential damages, even if
+-% * Sun has been advised of the possibility of such damages.
+-% *
+-% * Sun Microsystems, Inc.
+-% * 2550 Garcia Avenue
+-% * Mountain View, California  94043
+-% */
+-
+-%/*
+-% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+-% */
+-%
+-%/* from @(#)mount.x  1.3 91/03/11 TIRPC 1.0 */
+-
+-/*
+- * Protocol description for the mount program
+- */
+-
+-#ifdef RPC_HDR
+-%#ifndef _rpcsvc_mount_h
+-%#define _rpcsvc_mount_h
+-%#include <memory.h>
+-#endif
+-
+-const MNTPATHLEN = 1024;      /* maximum bytes in a pathname argument */
+-const MNTNAMLEN = 255;                /* maximum bytes in a name argument */
+-const FHSIZE = 32;            /* size in bytes of a file handle */
+-
+-/*
+- * The fhandle is the file handle that the server passes to the client.
+- * All file operations are done using the file handles to refer to a file
+- * or a directory. The file handle can contain whatever information the
+- * server needs to distinguish an individual file.
+- */
+-typedef opaque fhandle[FHSIZE];       
+-
+-/*
+- * If a status of zero is returned, the call completed successfully, and 
+- * a file handle for the directory follows. A non-zero status indicates
+- * some sort of error. The status corresponds with UNIX error numbers.
+- */
+-union fhstatus switch (unsigned fhs_status) {
+-case 0:
+-      fhandle fhs_fhandle;
+-default:
+-      void;
+-};
+-
+-/*
+- * The type dirpath is the pathname of a directory
+- */
+-typedef string dirpath<MNTPATHLEN>;
+-
+-/*
+- * The type name is used for arbitrary names (hostnames, groupnames)
+- */
+-typedef string name<MNTNAMLEN>;
+-
+-/*
+- * A list of who has what mounted
+- */
+-typedef struct mountbody *mountlist;
+-struct mountbody {
+-      name ml_hostname;
+-      dirpath ml_directory;
+-      mountlist ml_next;
+-};
+-
+-/*
+- * A list of netgroups
+- */
+-typedef struct groupnode *groups;
+-struct groupnode {
+-      name gr_name;
+-      groups gr_next;
+-};
+-
+-/*
+- * A list of what is exported and to whom
+- */
+-typedef struct exportnode *exports;
+-struct exportnode {
+-      dirpath ex_dir;
+-      groups ex_groups;
+-      exports ex_next;
+-};
+-
+-/*
+- * POSIX pathconf information
+- */
+-struct ppathcnf {
+-      int     pc_link_max;    /* max links allowed */
+-      short   pc_max_canon;   /* max line len for a tty */
+-      short   pc_max_input;   /* input a tty can eat all at once */
+-      short   pc_name_max;    /* max file name length (dir entry) */
+-      short   pc_path_max;    /* max path name length (/x/y/x/.. ) */
+-      short   pc_pipe_buf;    /* size of a pipe (bytes) */
+-      u_char  pc_vdisable;    /* safe char to turn off c_cc[i] */
+-      char    pc_xxx;         /* alignment padding; cc_t == char */
+-      short   pc_mask[2];     /* validity and boolean bits */
+-};
+-
+-/*
+- * NFSv3 file handle
+- */
+-const FHSIZE3 =       64;             /* max size of NFSv3 file handle in bytes */
+-typedef opaque                fhandle3<FHSIZE3>;
+-
+-/*
+- * NFSv3 mount status
+- */
+-enum mountstat3 {
+-      MNT_OK                  = 0,    /* no error */
+-      MNT3ERR_PERM            = 1,    /* not owner */
+-      MNT3ERR_NOENT           = 2,    /* no such file or directory */
+-      MNT3ERR_IO              = 5,    /* I/O error */
+-      MNT3ERR_ACCES           = 13,   /* Permission denied */
+-      MNT3ERR_NOTDIR          = 20,   /* Not a directory */
+-      MNT3ERR_INVAL           = 22,   /* Invalid argument */
+-      MNT3ERR_NAMETOOLONG     = 63,   /* File name too long */
+-      MNT3ERR_NOTSUPP         = 10004,/* Operation not supported */
+-      MNT3ERR_SERVERFAULT     = 10006 /* A failure on the server */
+-};
+-
+-/*
+- * NFSv3 mount result
+- */
+-struct mountres3_ok {
+-      fhandle3        fhandle;
+-      int             auth_flavors<>;
+-};
+-
+-union mountres3 switch (mountstat3 fhs_status) {
+-case MNT_OK:
+-      mountres3_ok    mountinfo; /* File handle and supported flavors */
+-default:
+-      void;
+-};
+-
+-program MOUNTPROG {
+-      /*
+-       * Version one of the mount protocol communicates with version two
+-       * of the NFS protocol. The only connecting point is the fhandle 
+-       * structure, which is the same for both protocols.
+-       */
+-      version MOUNTVERS {
+-              /*
+-               * Does no work. It is made available in all RPC services
+-               * to allow server reponse testing and timing
+-               */
+-              void
+-              MOUNTPROC_NULL(void) = 0;
+-
+-              /*      
+-               * If fhs_status is 0, then fhs_fhandle contains the
+-               * file handle for the directory. This file handle may
+-               * be used in the NFS protocol. This procedure also adds
+-               * a new entry to the mount list for this client mounting
+-               * the directory.
+-               * Unix authentication required.
+-               */
+-              fhstatus 
+-              MOUNTPROC_MNT(dirpath) = 1;
+-
+-              /*
+-               * Returns the list of remotely mounted filesystems. The 
+-               * mountlist contains one entry for each hostname and 
+-               * directory pair.
+-               */
+-              mountlist
+-              MOUNTPROC_DUMP(void) = 2;
+-
+-              /*
+-               * Removes the mount list entry for the directory
+-               * Unix authentication required.
+-               */
+-              void
+-              MOUNTPROC_UMNT(dirpath) = 3;
+-
+-              /*
+-               * Removes all of the mount list entries for this client
+-               * Unix authentication required.
+-               */
+-              void
+-              MOUNTPROC_UMNTALL(void) = 4;
+-
+-              /*
+-               * Returns a list of all the exported filesystems, and which
+-               * machines are allowed to import it.
+-               */
+-              exports
+-              MOUNTPROC_EXPORT(void)  = 5;
+-
+-              /*
+-               * Identical to MOUNTPROC_EXPORT above
+-               */
+-              exports
+-              MOUNTPROC_EXPORTALL(void) = 6;
+-      } = 1;
+-
+-      /*
+-       * Version two of the mount protocol communicates with version two
+-       * of the NFS protocol.
+-       * The only difference from version one is the addition of a POSIX
+-       * pathconf call.
+-       */
+-      version MOUNTVERS_POSIX {
+-              /*
+-               * Does no work. It is made available in all RPC services
+-               * to allow server reponse testing and timing
+-               */
+-              void
+-              MOUNTPROC_NULL(void) = 0;
+-
+-              /*      
+-               * If fhs_status is 0, then fhs_fhandle contains the
+-               * file handle for the directory. This file handle may
+-               * be used in the NFS protocol. This procedure also adds
+-               * a new entry to the mount list for this client mounting
+-               * the directory.
+-               * Unix authentication required.
+-               */
+-              fhstatus 
+-              MOUNTPROC_MNT(dirpath) = 1;
+-
+-              /*
+-               * Returns the list of remotely mounted filesystems. The 
+-               * mountlist contains one entry for each hostname and 
+-               * directory pair.
+-               */
+-              mountlist
+-              MOUNTPROC_DUMP(void) = 2;
+-
+-              /*
+-               * Removes the mount list entry for the directory
+-               * Unix authentication required.
+-               */
+-              void
+-              MOUNTPROC_UMNT(dirpath) = 3;
+-
+-              /*
+-               * Removes all of the mount list entries for this client
+-               * Unix authentication required.
+-               */
+-              void
+-              MOUNTPROC_UMNTALL(void) = 4;
+-
+-              /*
+-               * Returns a list of all the exported filesystems, and which
+-               * machines are allowed to import it.
+-               */
+-              exports
+-              MOUNTPROC_EXPORT(void)  = 5;
+-
+-              /*
+-               * Identical to MOUNTPROC_EXPORT above
+-               */
+-              exports
+-              MOUNTPROC_EXPORTALL(void) = 6;
+-
+-              /*
+-               * POSIX pathconf info (Sun hack)
+-               */
+-              ppathcnf
+-              MOUNTPROC_PATHCONF(dirpath) = 7;
+-      } = 2;
+-
+-      /*
+-       * Version 3 of the protocol is for NFSv3
+-       */
+-      version MOUNTVERS_NFSV3 {
+-              /*
+-               * Does no work. It is made available in all RPC services
+-               * to allow server reponse testing and timing
+-               */
+-              void
+-              MOUNTPROC3_NULL(void) = 0;
+-
+-              /*      
+-               * If fhs_status is 0, then fhs_fhandle contains the
+-               * file handle for the directory. This file handle may
+-               * be used in the NFS protocol. This procedure also adds
+-               * a new entry to the mount list for this client mounting
+-               * the directory.
+-               * Unix authentication required.
+-               */
+-              mountres3 
+-              MOUNTPROC3_MNT(dirpath) = 1;
+-
+-              /*
+-               * Returns the list of remotely mounted filesystems. The 
+-               * mountlist contains one entry for each hostname and 
+-               * directory pair.
+-               */
+-              mountlist
+-              MOUNTPROC3_DUMP(void) = 2;
+-
+-              /*
+-               * Removes the mount list entry for the directory
+-               * Unix authentication required.
+-               */
+-              void
+-              MOUNTPROC3_UMNT(dirpath) = 3;
+-
+-              /*
+-               * Removes all of the mount list entries for this client
+-               * Unix authentication required.
+-               */
+-              void
+-              MOUNTPROC3_UMNTALL(void) = 4;
+-
+-              /*
+-               * Returns a list of all the exported filesystems, and which
+-               * machines are allowed to import it.
+-               */
+-              exports
+-              MOUNTPROC3_EXPORT(void)  = 5;
+-      } = 3;
+-} = 100005;
+-
+-#ifdef RPC_HDR
+-%#endif /*!_rpcsvc_mount_h*/
+-#endif
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-mounts_mutex.patch b/archive-patches/autofs5/autofs-5.1.7-remove-mounts_mutex.patch
new file mode 100644 (file)
index 0000000..7fdebe7
--- /dev/null
@@ -0,0 +1,178 @@
+autofs-5.1.7 - remove mounts_mutex
+
+From: Ian Kent <raven@themaw.net>
+
+The mounts_mutex is no longer used, remove it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ daemon/automount.c     |    8 +-------
+ daemon/master.c        |   13 -------------
+ include/automount.h    |    1 -
+ modules/mount_autofs.c |    8 --------
+ 5 files changed, 2 insertions(+), 29 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 42914160..9d0f4278 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -48,6 +48,7 @@
+ - remove unused function master_submount_list_empty().
+ - move amd mounts removal into lib/mounts.c.
+ - check for offset with no mount location.
++- remove mounts_mutex.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 7833dfae..28c4d1ee 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -1754,7 +1754,6 @@ static void handle_mounts_cleanup(void *arg)
+        * here.
+        */
+       if (submount) {
+-              mounts_mutex_unlock(ap->parent);
+               master_source_unlock(ap->parent->entry);
+               master_free_mapent_sources(ap->entry, 1);
+               master_free_mapent(ap->entry);
+@@ -1792,13 +1791,9 @@ static int submount_source_writelock_nested(struct autofs_point *ap)
+       if (status)
+               goto done;
+-      mounts_mutex_lock(parent);
+-
+       status = pthread_rwlock_trywrlock(&ap->entry->source_lock);
+-      if (status) {
+-              mounts_mutex_unlock(parent);
++      if (status)
+               master_source_unlock(parent->entry);
+-      }
+ done:
+       if (status && status != EBUSY) {
+@@ -1814,7 +1809,6 @@ static void submount_source_unlock_nested(struct autofs_point *ap)
+       struct autofs_point *parent = ap->parent;
+       master_source_unlock(ap->entry);
+-      mounts_mutex_unlock(parent);
+       master_source_unlock(parent->entry);
+ }
+diff --git a/daemon/master.c b/daemon/master.c
+index b288e070..30d7cf98 100644
+--- a/daemon/master.c
++++ b/daemon/master.c
+@@ -69,7 +69,6 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+                           unsigned nobind, unsigned ghost, int submount)
+ {
+       struct autofs_point *ap;
+-      int status;
+       ap = malloc(sizeof(struct autofs_point));
+       if (!ap)
+@@ -128,12 +127,6 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+       INIT_LIST_HEAD(&ap->amdmounts);
+       ap->shutdown = 0;
+-      status = pthread_mutex_init(&ap->mounts_mutex, NULL);
+-      if (status) {
+-              free(ap->path);
+-              free(ap);
+-              return 0;
+-      }
+       ap->mode = 0;
+       entry->ap = ap;
+@@ -143,17 +136,11 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+ void master_free_autofs_point(struct autofs_point *ap)
+ {
+-      int status;
+-
+       if (!ap)
+               return;
+       mnts_remove_amdmounts(ap);
+-      status = pthread_mutex_destroy(&ap->mounts_mutex);
+-      if (status)
+-              fatal(status);
+-
+       if (ap->pref)
+               free(ap->pref);
+       free(ap->path);
+diff --git a/include/automount.h b/include/automount.h
+index e33ee8d2..51a0bf0e 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -565,7 +565,6 @@ struct autofs_point {
+       enum states state;              /* Current state */
+       int state_pipe[2];              /* State change router pipe */
+       struct autofs_point *parent;    /* Owner of mounts list for submount */
+-      pthread_mutex_t mounts_mutex;   /* Protect mount lists */
+       struct list_head mounts;        /* List of autofs mounts at current level */
+       unsigned int submount;          /* Is this a submount */
+       unsigned int submnt_count;      /* Number of submounts */
+diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
+index 1c40e27a..0bcbb343 100644
+--- a/modules/mount_autofs.c
++++ b/modules/mount_autofs.c
+@@ -283,8 +283,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
+       set_exp_timeout(nap, NULL, timeout);
+       nap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+-      mounts_mutex_lock(ap);
+-
+       if (source->flags & MAP_FLAG_FORMAT_AMD) {
+               struct mnt_list *mnt;
+@@ -305,7 +303,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
+       if (handle_mounts_startup_cond_init(&suc)) {
+               crit(ap->logopt, MODPREFIX
+                    "failed to init startup cond for mount %s", entry->path);
+-              mounts_mutex_unlock(ap);
+               master_free_map_source(source, 1);
+               master_free_mapent(entry);
+               return 1;
+@@ -316,7 +313,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
+               crit(ap->logopt,
+                    MODPREFIX "failed to allocate mount %s", realpath);
+               handle_mounts_startup_cond_destroy(&suc);
+-              mounts_mutex_unlock(ap);
+               master_free_map_source(source, 1);
+               master_free_mapent(entry);
+               return 1;
+@@ -335,7 +331,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
+                    realpath);
+               handle_mounts_startup_cond_destroy(&suc);
+               mnts_remove_submount(nap->path);
+-              mounts_mutex_unlock(ap);
+               master_free_map_source(source, 1);
+               master_free_mapent(entry);
+               return 1;
+@@ -346,7 +341,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
+               if (status) {
+                       handle_mounts_startup_cond_destroy(&suc);
+                       mnts_remove_submount(nap->path);
+-                      mounts_mutex_unlock(ap);
+                       master_free_map_source(source, 1);
+                       master_free_mapent(entry);
+                       fatal(status);
+@@ -358,7 +352,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
+                    MODPREFIX "failed to create submount for %s", realpath);
+               handle_mounts_startup_cond_destroy(&suc);
+               mnts_remove_submount(nap->path);
+-              mounts_mutex_unlock(ap);
+               master_free_map_source(source, 1);
+               master_free_mapent(entry);
+               return 1;
+@@ -368,7 +361,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
+       ap->submnt_count++;
+       handle_mounts_startup_cond_destroy(&suc);
+-      mounts_mutex_unlock(ap);
+       return 0;
+ }
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-obsolete-functions.patch b/archive-patches/autofs5/autofs-5.1.7-remove-obsolete-functions.patch
new file mode 100644 (file)
index 0000000..45c22fb
--- /dev/null
@@ -0,0 +1,752 @@
+autofs-5.1.7 - remove obsolete functions
+
+From: Ian Kent <raven@themaw.net>
+
+Remove the code that's no longer used due to the tree mapent
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ include/automount.h |   10 --
+ include/mounts.h    |    2 
+ lib/cache.c         |  227 -------------------------------------
+ lib/mounts.c        |  311 ---------------------------------------------------
+ modules/parse_sun.c |   56 ---------
+ 6 files changed, 2 insertions(+), 605 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 5ac09f77..76fccf70 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -41,6 +41,7 @@
+ - add set_offset_tree_catatonic().
+ - add mount and umount offsets functions.
+ - switch to use tree implementation for offsets.
++- remove obsolete functions.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/automount.h b/include/automount.h
+index a71b8674..e33ee8d2 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -162,16 +162,13 @@ struct stack {
+ struct mapent {
+       struct mapent *next;
+       struct list_head ino_index;
+-      struct list_head multi_list;
+       struct mapent_cache *mc;
+       struct map_source *source;
+       /* Need to know owner if we're a multi-mount */
+       struct tree_node *mm_root;
++      /* Parent nesting point within multi-mount */
+       struct tree_node *mm_parent;
+       struct tree_node node;
+-      struct mapent *multi;
+-      /* Parent nesting point within multi-mount */
+-      struct mapent *parent;
+       char *key;
+       size_t len;
+       char *mapent;
+@@ -209,7 +206,6 @@ struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me);
+ struct mapent *cache_lookup_key_next(struct mapent *me);
+ struct mapent *cache_lookup(struct mapent_cache *mc, const char *key);
+ struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key);
+-struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int start, struct list_head *head);
+ struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix);
+ struct mapent *cache_partial_match_wild(struct mapent_cache *mc, const char *prefix);
+ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+@@ -217,16 +213,12 @@ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *k
+ int cache_lookup_negative(struct mapent *me, const char *key);
+ void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout);
+ struct mapent *cache_get_offset_parent(struct mapent_cache *mc, const char *key);
+-int cache_set_offset_parent(struct mapent_cache *mc, const char *offset);
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+-int cache_delete_offset(struct mapent_cache *mc, const char *key);
+-int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
+ void cache_release(struct map_source *map);
+ void cache_clean_null_cache(struct mapent_cache *mc);
+ void cache_release_null_cache(struct master *master);
+ struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me);
+-char *cache_get_offset(const char *prefix, char *offset, int start, struct list_head *head, struct list_head **pos);
+ /* Utility functions */
+diff --git a/include/mounts.h b/include/mounts.h
+index e56f80ba..ec895e1c 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -187,8 +187,6 @@ 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 mount_multi_triggers(struct autofs_point *, struct mapent *, const char *, unsigned int, const char *);
+-int umount_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
+ int clean_stale_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
+ #endif
+diff --git a/lib/cache.c b/lib/cache.c
+index 93b02daf..ef761739 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -461,30 +461,6 @@ struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key)
+       return NULL;
+ }
+-/* Lookup an offset within a multi-mount entry */
+-struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int start, struct list_head *head)
+-{
+-      struct list_head *p;
+-      struct mapent *this;
+-      /* Keys for direct maps may be as long as a path name */
+-      char o_key[PATH_MAX];
+-      /* Avoid "//" at the beginning of paths */
+-      const char *path_prefix = strlen(prefix) > 1 ? prefix : "";
+-      size_t size;
+-
+-      /* root offset duplicates "/" */
+-      size = snprintf(o_key, sizeof(o_key), "%s%s", path_prefix, offset);
+-      if (size >= sizeof(o_key))
+-              return NULL;
+-
+-      list_for_each(p, head) {
+-              this = list_entry(p, struct mapent, multi_list);
+-              if (!strcmp(&this->key[start], o_key))
+-                      return this;
+-      }
+-      return NULL;
+-}
+-
+ /* cache must be read locked by caller */
+ static struct mapent *__cache_partial_match(struct mapent_cache *mc,
+                                           const char *prefix,
+@@ -583,9 +559,6 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+       me->mm_parent = NULL;
+       INIT_TREE_NODE(&me->node);
+       INIT_LIST_HEAD(&me->ino_index);
+-      INIT_LIST_HEAD(&me->multi_list);
+-      me->multi = NULL;
+-      me->parent = NULL;
+       me->ioctlfd = -1;
+       me->dev = (dev_t) -1;
+       me->ino = (ino_t) -1;
+@@ -615,33 +588,6 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+       return CHE_OK;
+ }
+-/* cache must be write locked by caller */
+-static void cache_add_ordered_offset(struct mapent *me, struct list_head *head)
+-{
+-      struct list_head *p;
+-      struct mapent *this;
+-
+-      list_for_each(p, head) {
+-              size_t tlen;
+-              int eq;
+-
+-              this = list_entry(p, struct mapent, multi_list);
+-              tlen = strlen(this->key);
+-
+-              eq = strncmp(this->key, me->key, tlen);
+-              if (!eq && tlen == strlen(me->key))
+-                      return;
+-
+-              if (eq > 0) {
+-                      list_add_tail(&me->multi_list, p);
+-                      return;
+-              }
+-      }
+-      list_add_tail(&me->multi_list, p);
+-
+-      return;
+-}
+-
+ /* cache must be write locked by caller */
+ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age)
+ {
+@@ -777,25 +723,6 @@ struct mapent *cache_get_offset_parent(struct mapent_cache *mc, const char *key)
+       return NULL;
+ }
+-int cache_set_offset_parent(struct mapent_cache *mc, const char *offset)
+-{
+-      struct mapent *this, *parent;
+-
+-      this = cache_lookup_distinct(mc, offset);
+-      if (!this)
+-              return 0;
+-      if (!IS_MM(this))
+-              return 0;
+-
+-      parent = cache_get_offset_parent(mc, offset);
+-      if (parent)
+-              this->parent = parent;
+-      else
+-              this->parent = MM_ROOT(this);
+-
+-      return 1;
+-}
+-
+ /* cache must be write locked by caller */
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age)
+ {
+@@ -837,50 +764,6 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
+       return ret;
+ }
+-/* cache write lock of the multi mount owner must be held by caller */
+-int cache_delete_offset(struct mapent_cache *mc, const char *key)
+-{
+-      u_int32_t hashval = hash(key, mc->size);
+-      struct mapent *me = NULL, *pred;
+-      int status;
+-
+-      me = mc->hash[hashval];
+-      if (!me)
+-              return CHE_FAIL;
+-
+-      if (strcmp(key, me->key) == 0) {
+-              if (IS_MM(me) && IS_MM_ROOT(me))
+-                      return CHE_FAIL;
+-              mc->hash[hashval] = me->next;
+-              goto delete;
+-      }
+-
+-      while (me->next != NULL) {
+-              pred = me;
+-              me = me->next;
+-              if (strcmp(key, me->key) == 0) {
+-                      if (IS_MM(me) && IS_MM_ROOT(me))
+-                              return CHE_FAIL;
+-                      pred->next = me->next;
+-                      goto delete;
+-              }
+-      }
+-
+-      return CHE_FAIL;
+-
+-delete:
+-      list_del(&me->multi_list);
+-      ino_index_lock(mc);
+-      list_del(&me->ino_index);
+-      ino_index_unlock(mc);
+-      free(me->key);
+-      if (me->mapent)
+-              free(me->mapent);
+-      free(me);
+-
+-      return CHE_OK;
+-}
+-
+ /* cache must be write locked by caller */
+ int cache_delete(struct mapent_cache *mc, const char *key)
+ {
+@@ -1054,113 +937,3 @@ struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me)
+       return cache_lookup_next(mc, me);
+ }
+-
+-/*
+- * Get each offset from list head under prefix.
+- * Maintain traversal current position in pos for subsequent calls. 
+- * Return each offset into offset.
+- */
+-/* cache must be read locked by caller */
+-char *cache_get_offset(const char *prefix, char *offset, int start,
+-                      struct list_head *head, struct list_head **pos)
+-{
+-      struct list_head *next;
+-      struct mapent *this;
+-      size_t plen = strlen(prefix);
+-      size_t len = 0;
+-
+-      if (*pos == head)
+-              return NULL;
+-
+-      /* Find an offset */
+-      *offset = '\0';
+-      next = *pos ? (*pos)->next : head->next;
+-      while (next != head) {
+-              char *offset_start, *pstart, *pend;
+-
+-              this = list_entry(next, struct mapent, multi_list);
+-              *pos = next;
+-              next = next->next;
+-
+-              offset_start = &this->key[start];
+-              if (strlen(offset_start) <= plen)
+-                      continue;
+-
+-              if (!strncmp(prefix, offset_start, plen)) {
+-                      struct mapent *np = NULL;
+-                      char pe[PATH_MAX + 1];
+-
+-                      /* "/" doesn't count for root offset */
+-                      if (plen == 1)
+-                              pstart = &offset_start[plen - 1];
+-                      else
+-                              pstart = &offset_start[plen];
+-
+-                      /* not part of this sub-tree */
+-                      if (*pstart != '/')
+-                              continue;
+-
+-                      /* get next offset */
+-                      pend = pstart;
+-                      while (*pend++) {
+-                              size_t nest_pt_offset;
+-
+-                              if (*pend != '/')
+-                                      continue;
+-
+-                              nest_pt_offset = start + pend - pstart;
+-                              if (plen > 1)
+-                                      nest_pt_offset += plen;
+-                              strcpy(pe, this->key);
+-                              pe[nest_pt_offset] = '\0';
+-
+-                              np = cache_lookup_distinct(this->mc, pe);
+-                              if (np)
+-                                      break;
+-                      }
+-                      if (np)
+-                              continue;
+-                      len = pend - pstart - 1;
+-                      strncpy(offset, pstart, len);
+-                      offset[len] ='\0';
+-                      break;
+-              }
+-      }
+-
+-      /* Seek to next offset */
+-      while (next != head) {
+-              char *offset_start, *pstart;
+-
+-              this = list_entry(next, struct mapent, multi_list);
+-
+-              offset_start = &this->key[start];
+-              if (strlen(offset_start) <= plen + len)
+-                      break;
+-
+-              /* "/" doesn't count for root offset */
+-              if (plen == 1)
+-                      pstart = &offset_start[plen - 1];
+-              else
+-                      pstart = &offset_start[plen];
+-
+-              /* not part of this sub-tree */
+-              if (*pstart != '/')
+-                      break;
+-
+-              /* new offset */
+-              if (!*(pstart + len + 1))
+-                      break;
+-
+-              /* compare offset */
+-              if (pstart[len] != '/' ||
+-                  strlen(pstart) != len ||
+-                  strncmp(offset, pstart, len))
+-                      break;
+-
+-              *pos = next;
+-              next = next->next;
+-      }
+-
+-      return *offset ? offset : NULL;
+-}
+-
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 6ca7eff1..c120d2a8 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2853,21 +2853,6 @@ static void set_offset_tree_catatonic(struct autofs_point *ap, struct mapent *me
+       tree_traverse_inorder(MAPENT_ROOT(me), set_offset_tree_catatonic_work, NULL);
+ }
+-static void set_multi_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+-{
+-      if (!list_empty(&me->multi_list)) {
+-              struct list_head *head = &me->multi_list;
+-              struct list_head *p;
+-
+-              list_for_each(p, head) {
+-                      struct mapent *this;
+-
+-                      this = list_entry(p, struct mapent, multi_list);
+-                      set_mount_catatonic(ap, this, this->ioctlfd);
+-              }
+-      }
+-}
+-
+ void set_indirect_mount_tree_catatonic(struct autofs_point *ap)
+ {
+       struct master_mapent *entry = ap->entry;
+@@ -3034,299 +3019,3 @@ done:
+ out:
+       return rv;
+ }
+-
+-static int do_mount_autofs_offset(struct autofs_point *ap, struct mapent *oe)
+-{
+-      int mounted = 0;
+-      int ret;
+-
+-      debug(ap->logopt, "mount offset %s", oe->key);
+-
+-      ret = mount_autofs_offset(ap, oe);
+-      if (ret >= MOUNT_OFFSET_OK)
+-              mounted++;
+-      else {
+-              if (ret != MOUNT_OFFSET_IGNORE)
+-                      warn(ap->logopt, "failed to mount offset");
+-              else {
+-                      debug(ap->logopt, "ignoring \"nohide\" trigger %s",
+-                            oe->key);
+-                      /*
+-                       * Ok, so we shouldn't modify the mapent but
+-                       * mount requests are blocked at a point above
+-                       * this and expire only uses the mapent key or
+-                       * holds the cache write lock.
+-                       */
+-                      free(oe->mapent);
+-                      oe->mapent = NULL;
+-              }
+-      }
+-
+-      return mounted;
+-}
+-
+-static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+-{
+-      char *dir, *path;
+-      unsigned int split;
+-      int ret;
+-
+-      if (ap->type == LKP_DIRECT)
+-              return rmdir_path(ap, oe->key, MM_ROOT(oe)->dev);
+-
+-      dir = strdup(oe->key);
+-
+-      if (ap->flags & MOUNT_FLAG_GHOST)
+-              split = ap->len + strlen(MM_ROOT(oe)->key) + 1;
+-      else
+-              split = ap->len;
+-
+-      dir[split] = '\0';
+-      path = &dir[split + 1];
+-
+-      if (chdir(dir) == -1) {
+-              error(ap->logopt, "failed to chdir to %s", dir);
+-              free(dir);
+-              return -1;
+-      }
+-
+-      ret = rmdir_path(ap, path, ap->dev);
+-
+-      free(dir);
+-
+-      if (chdir("/") == -1)
+-              error(ap->logopt, "failed to chdir to /");
+-
+-      return ret;
+-}
+-
+-static int do_umount_offset(struct autofs_point *ap,
+-                          struct mapent *oe, const char *root, int start);
+-
+-static int do_umount_multi_triggers(struct autofs_point *ap,
+-                                  struct mapent *me, const char *root,
+-                                  int start, const char *base)
+-{
+-      char path[PATH_MAX + 1];
+-      char *offset;
+-      struct mapent *oe;
+-      struct list_head *mm_root, *pos;
+-      const char o_root[] = "/";
+-      const char *mm_base;
+-      int left;
+-      unsigned int root_len;
+-      unsigned int mm_base_len;
+-
+-      left = 0;
+-
+-      mm_root = &me->multi->multi_list;
+-
+-      if (!base)
+-              mm_base = o_root;
+-      else
+-              mm_base = base;
+-
+-      pos = NULL;
+-      offset = path;
+-      root_len = start;
+-      mm_base_len = strlen(mm_base);
+-
+-      while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+-              char key[PATH_MAX + 1];
+-              int key_len = root_len + strlen(offset);
+-
+-              if (mm_base_len > 1)
+-                      key_len += mm_base_len;
+-
+-              if (key_len > PATH_MAX) {
+-                      warn(ap->logopt, "path loo long");
+-                      continue;
+-              }
+-
+-              strcpy(key, root);
+-              if (mm_base_len > 1)
+-                      strcat(key, mm_base);
+-              strcat(key, offset);
+-
+-              oe = cache_lookup_distinct(me->mc, key);
+-              /* root offset is a special case */
+-              if (!oe || (strlen(oe->key) - start) == 1)
+-                      continue;
+-
+-              left += do_umount_offset(ap, oe, root, start);
+-      }
+-
+-      return left;
+-}
+-
+-static int do_umount_offset(struct autofs_point *ap,
+-                          struct mapent *oe, const char *root, int start)
+-{
+-      char *oe_base;
+-      int left = 0;
+-
+-      /*
+-       * Check for and umount subtree offsets resulting from
+-       * nonstrict mount fail.
+-       */
+-      oe_base = oe->key + start;
+-      left += do_umount_multi_triggers(ap, oe, root, start, oe_base);
+-
+-      /*
+-       * If an offset that has an active mount has been removed
+-       * from the multi-mount we don't want to attempt to trigger
+-       * mounts for it. Obviously this is because it has been
+-       * removed, but less obvious is the potential strange
+-       * behaviour that can result if we do try and mount it
+-       * again after it's been expired. For example, if an NFS
+-       * file system is no longer exported and is later umounted
+-       * it can be mounted again without any error message but
+-       * shows as an empty directory. That's going to confuse
+-       * people for sure.
+-       *
+-       * If the mount cannot be umounted (the process is now
+-       * using a stale mount) the offset needs to be invalidated
+-       * so no further mounts will be attempted but the offset
+-       * cache entry must remain so expires can continue to
+-       * attempt to umount it. If the mount can be umounted and
+-       * the offset is removed, at least for NFS we will get
+-       * ESTALE errors when attempting list the directory.
+-       */
+-      if (oe->ioctlfd != -1 ||
+-          is_mounted(oe->key, MNTS_REAL)) {
+-              if (umount_ent(ap, oe->key) &&
+-                  is_mounted(oe->key, MNTS_REAL)) {
+-                      debug(ap->logopt,
+-                            "offset %s has active mount, invalidate",
+-                            oe->key);
+-                      /*
+-                       * Ok, so we shouldn't modify the mapent but
+-                       * mount requests are blocked at a point above
+-                       * this and expire only uses the mapent key or
+-                       * holds the cache write lock.
+-                       */
+-                      if (oe->mapent) {
+-                              free(oe->mapent);
+-                              oe->mapent = NULL;
+-                      }
+-                      return ++left;
+-              }
+-      }
+-
+-      debug(ap->logopt, "umount offset %s", oe->key);
+-
+-      if (umount_autofs_offset(ap, oe)) {
+-              warn(ap->logopt, "failed to umount offset");
+-              left++;
+-      } else {
+-              struct stat st;
+-              int ret;
+-
+-              if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
+-                      return left;
+-
+-              /*
+-               * An error due to partial directory removal is
+-               * ok so only try and remount the offset if the
+-               * actual mount point still exists.
+-               */
+-              ret = rmdir_path_offset(ap, oe);
+-              if (ret == -1 && !stat(oe->key, &st)) {
+-                      ret = do_mount_autofs_offset(ap, oe);
+-                      if (ret)
+-                              left++;
+-                      /* But we did origianlly create this */
+-                      oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-              }
+-      }
+-      return left;
+-}
+-
+-int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+-                       const char *root, unsigned int start, const char *base)
+-{
+-      char path[PATH_MAX + 1];
+-      char *offset = path;
+-      struct mapent *oe;
+-      struct list_head *pos = NULL;
+-      unsigned int root_len = strlen(root);
+-      int mounted;
+-
+-      mounted = 0;
+-      offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+-      while (offset) {
+-              char key[PATH_MAX + 1];
+-              int key_len = root_len + strlen(offset);
+-
+-              if (key_len > PATH_MAX) {
+-                      warn(ap->logopt, "path loo long");
+-                      goto cont;
+-              }
+-
+-              /* The root offset is always mounted seperately so the
+-               * offset path will always be root + offset.
+-               */
+-              strcpy(key, root);
+-              strcat(key, offset);
+-
+-              oe = cache_lookup_distinct(me->mc, key);
+-              if (!oe || !oe->mapent)
+-                      goto cont;
+-              if (oe->age != MM_ROOT(me)->age) {
+-                      /* Best effort */
+-                      do_umount_offset(ap, oe, root, start);
+-                      goto cont;
+-              }
+-
+-              mounted += do_mount_autofs_offset(ap, oe);
+-
+-              /*
+-               * If re-constructing a multi-mount it's necessary to walk
+-               * into nested mounts, unlike the usual "mount only what's
+-               * needed as you go" behavior.
+-               */
+-              if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+-                      if (oe->ioctlfd != -1 ||
+-                          is_mounted(oe->key, MNTS_REAL))
+-                              mount_multi_triggers(ap, oe, key, key_len, base);
+-              }
+-cont:
+-              offset = cache_get_offset(base,
+-                              offset, start, &me->multi_list, &pos);
+-      }
+-
+-      return mounted;
+-}
+-
+-int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
+-{
+-      int left, start;
+-
+-      start = strlen(root);
+-
+-      left = do_umount_multi_triggers(ap, me, root, start, base);
+-
+-      if (!left && IS_MM_ROOT(me)) {
+-              /*
+-               * Special case.
+-               * If we can't umount the root container then we can't
+-               * delete the offsets from the cache and we need to put
+-               * the offset triggers back.
+-               */
+-              if (is_mounted(root, MNTS_REAL)) {
+-                      info(ap->logopt, "unmounting dir = %s", root);
+-                      if (umount_ent(ap, root) &&
+-                          is_mounted(root, MNTS_REAL)) {
+-                              if (mount_multi_triggers(ap, me, root, start, "/") < 0)
+-                                      warn(ap->logopt,
+-                                           "failed to remount offset triggers");
+-                              return ++left;
+-                      }
+-              }
+-
+-             /* check for mounted mount entry and remove it if found */
+-               mnts_remove_mount(root, MNTS_MOUNTED);
+-      }
+-
+-      return left;
+-}
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index d6ef48b8..ef74eda9 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1074,62 +1074,6 @@ next:
+       return (p - ent);
+ }
+-static void cleanup_multi_triggers(struct autofs_point *ap,
+-                          struct mapent *me, const char *root, int start,
+-                          const char *base)
+-{
+-      char path[PATH_MAX + 1];
+-      char offset[PATH_MAX + 1];
+-      char *poffset = offset;
+-      struct mapent *oe;
+-      struct list_head *mm_root, *pos;
+-      const char o_root[] = "/";
+-      const char *mm_base;
+-      unsigned int root_len;
+-      unsigned int mm_base_len;
+-
+-      mm_root = &me->multi->multi_list;
+-
+-      if (!base)
+-              mm_base = o_root;
+-      else
+-              mm_base = base;
+-
+-      pos = NULL;
+-      root_len = strlen(root);
+-      mm_base_len = strlen(mm_base);
+-
+-      /* Make sure "none" of the offsets have an active mount. */
+-      while ((poffset = cache_get_offset(mm_base, poffset, start, mm_root, &pos))) {
+-              unsigned int path_len = root_len + strlen(poffset);
+-
+-              if (mm_base_len > 1)
+-                      path_len += mm_base_len;
+-
+-              if (path_len > PATH_MAX) {
+-                      warn(ap->logopt, "path loo long");
+-                      continue;
+-              }
+-
+-              strcpy(path, root);
+-              if (mm_base_len > 1)
+-                      strcat(path, mm_base);
+-              strcat(path, poffset);
+-
+-              oe = cache_lookup_distinct(me->mc, path);
+-              /* root offset is a special case */
+-              if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
+-                      continue;
+-
+-              if (umount(path)) {
+-                      error(ap->logopt, "error recovering from mount fail");
+-                      error(ap->logopt, "cannot umount offset %s", path);
+-              }
+-      }
+-
+-      return;
+-}
+-
+ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+                        const char *name, char *loc, char *options, void *ctxt)
+ {
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch b/archive-patches/autofs5/autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch
new file mode 100644 (file)
index 0000000..44cdc66
--- /dev/null
@@ -0,0 +1,40 @@
+autofs-5.1.7 - remove redundant assignment in master_add_amd_mount_section_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: missing_lock: Accessing "entry->current" without holding lock
+         "master_mapent.current_mutex".
+
+This is initialization not clearing current source. But the field has
+already been initialized in the master_new_mapent() call.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/master.c |    1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index c7bc0c39..f95b1aa6 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -58,6 +58,7 @@
+ - add length check in umount_subtree_mounts().
+ - fix flags check in umount_multi().
+ - dont try umount after stat() ENOENT fail.
++- remove redundant assignment in master_add_amd_mount_section_mounts().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/master.c b/daemon/master.c
+index 30d7cf98..84743f80 100644
+--- a/daemon/master.c
++++ b/daemon/master.c
+@@ -996,7 +996,6 @@ static void master_add_amd_mount_section_mounts(struct master *master, time_t ag
+               source->master_line = 0;
+               entry->age = age;
+-              entry->current = NULL;
+               master_add_mapent(master, entry);
+ next:
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-redundant-if-check.patch b/archive-patches/autofs5/autofs-5.1.7-remove-redundant-if-check.patch
new file mode 100644 (file)
index 0000000..86948ea
--- /dev/null
@@ -0,0 +1,40 @@
+autofs-5.1.7 - remove redundant if check
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: identical code in if condition branches.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/direct.c |    5 +----
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 62a918a9..2186cbe3 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -51,6 +51,7 @@
+ - remove mounts_mutex.
+ - remove unused variable from get_exports().
+ - add missing free in handle_mounts().
++- remove redundant if check.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/direct.c b/daemon/direct.c
+index 3f4f5704..a33f9f91 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -752,10 +752,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
+       ops->timeout(ap->logopt, ioctlfd, timeout);
+       cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
+-      if (ap->logopt & LOGOPT_DEBUG)
+-              notify_mount_result(ap, me->key, timeout, str_offset);
+-      else
+-              notify_mount_result(ap, me->key, timeout, str_offset);
++      notify_mount_result(ap, me->key, timeout, str_offset);
+       ops->close(ap->logopt, ioctlfd);
+       debug(ap->logopt, "mounted trigger %s", me->key);
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch b/archive-patches/autofs5/autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch
new file mode 100644 (file)
index 0000000..849d481
--- /dev/null
@@ -0,0 +1,74 @@
+autofs-5.1.7 - remove redundant local var from sun_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+The local variable mountpoint in sun_mount() is set directly from a
+passed in parameter and never changed and the source isn't changed
+either, so use the variable directly.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   13 ++++---------
+ 2 files changed, 5 insertions(+), 9 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 76fccf70..444ade5b 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -42,6 +42,7 @@
+ - add mount and umount offsets functions.
+ - switch to use tree implementation for offsets.
+ - remove obsolete functions.
++- remove redundant local var from sun_mount().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index ef74eda9..437869b5 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -530,7 +530,6 @@ static int sun_mount(struct autofs_point *ap, const char *root,
+       int nonstrict = 1;
+       int use_weight_only = ap->flags & MOUNT_FLAG_USE_WEIGHT_ONLY;
+       int rv, cur_state;
+-      char *mountpoint;
+       char *what;
+       char *type;
+@@ -624,9 +623,6 @@ static int sun_mount(struct autofs_point *ap, const char *root,
+               }
+       }
+-      mountpoint = alloca(namelen + 1);
+-      sprintf(mountpoint, "%.*s", namelen, name);
+-
+       type = ap->entry->maps->type;
+       if (type && !strcmp(type, "hosts")) {
+               if (options && *options != '\0') {
+@@ -698,9 +694,9 @@ static int sun_mount(struct autofs_point *ap, const char *root,
+               debug(ap->logopt, MODPREFIX
+                     "mounting root %s, mountpoint %s, "
+                     "what %s, fstype %s, options %s",
+-                    root, mountpoint, what, fstype, options);
++                    root, name, what, fstype, options);
+-              rv = mount_nfs->mount_mount(ap, root, mountpoint, strlen(mountpoint),
++              rv = mount_nfs->mount_mount(ap, root, name, namelen,
+                                           what, fstype, options, mount_nfs->context);
+       } else {
+               if (!loclen)
+@@ -720,11 +716,10 @@ static int sun_mount(struct autofs_point *ap, const char *root,
+               debug(ap->logopt, MODPREFIX
+                     "mounting root %s, mountpoint %s, "
+                     "what %s, fstype %s, options %s",
+-                    root, mountpoint, what, fstype, options);
++                    root, name, what, fstype, options);
+               /* Generic mount routine */
+-              rv = do_mount(ap, root, mountpoint, strlen(mountpoint), what, fstype,
+-                            options);
++              rv = do_mount(ap, root, name, namelen, what, fstype, options);
+       }
+       pthread_setcancelstate(cur_state, NULL);
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch b/archive-patches/autofs5/autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch
new file mode 100644 (file)
index 0000000..9e7420d
--- /dev/null
@@ -0,0 +1,182 @@
+autofs-5.1.7 - remove redundant variables from mount_autofs_offset()
+
+From: Ian Kent <raven@themaw.net>
+
+The path to be mounted is the key in the passed in mapent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/direct.c     |   42 +++++++++++++++++++-----------------------
+ include/automount.h |    2 +-
+ lib/mounts.c        |    2 +-
+ 4 files changed, 22 insertions(+), 25 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index c4ebb52f..45be4783 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -9,6 +9,7 @@
+ - fix is mounted check on non existent path.
+ - simplify cache_get_parent().
+ - set offset parent in update_offset_entry().
++- remove redundant variables from mount_autofs_offset().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/direct.c b/daemon/direct.c
+index 9fe4903a..c41c680f 100644
+--- a/daemon/direct.c
++++ b/daemon/direct.c
+@@ -611,7 +611,7 @@ force_umount:
+       return rv;
+ }
+-int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *root, const char *offset)
++int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
+ {
+       const char *str_offset = mount_type_str(t_offset);
+       struct ioctl_ops *ops = get_ioctl_ops();
+@@ -623,7 +623,6 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
+       const char *hosts_map_name = "-hosts";
+       const char *map_name = hosts_map_name;
+       const char *type;
+-      char mountpoint[PATH_MAX];
+       struct mnt_list *mnt;
+       if (ops->version && ap->flags & MOUNT_FLAG_REMOUNT) {
+@@ -681,11 +680,8 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
+                       return MOUNT_OFFSET_OK;
+       }
+-      strcpy(mountpoint, root);
+-      strcat(mountpoint, offset);
+-
+       /* In case the directory doesn't exist, try to mkdir it */
+-      if (mkdir_path(mountpoint, mp_mode) < 0) {
++      if (mkdir_path(me->key, mp_mode) < 0) {
+               if (errno == EEXIST) {
+                       /*
+                        * If the mount point directory is a real mount
+@@ -694,7 +690,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
+                        * the kernel NFS client.
+                        */
+                       if (me->multi != me &&
+-                          is_mounted(mountpoint, MNTS_REAL))
++                          is_mounted(me->key, MNTS_REAL))
+                               return MOUNT_OFFSET_IGNORE;
+                       /* 
+@@ -714,13 +710,13 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
+                       char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+                       debug(ap->logopt,
+                            "can't create mount directory: %s, %s",
+-                           mountpoint, estr);
++                           me->key, estr);
+                       return MOUNT_OFFSET_FAIL;
+               } else {
+                       char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+                       crit(ap->logopt,
+                            "failed to create mount directory: %s, %s",
+-                           mountpoint, estr);
++                           me->key, estr);
+                       return MOUNT_OFFSET_FAIL;
+               }
+       } else {
+@@ -730,56 +726,56 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
+       debug(ap->logopt,
+             "calling mount -t autofs " SLOPPY " -o %s automount %s",
+-            mp->options, mountpoint);
++            mp->options, me->key);
+       type = ap->entry->maps->type;
+       if (!type || strcmp(ap->entry->maps->type, "hosts"))
+               map_name = me->mc->map->argv[0];
+-      ret = mount(map_name, mountpoint, "autofs", MS_MGC_VAL, mp->options);
++      ret = mount(map_name, me->key, "autofs", MS_MGC_VAL, mp->options);
+       if (ret) {
+               crit(ap->logopt,
+                    "failed to mount offset trigger %s at %s",
+-                   me->key, mountpoint);
++                   me->key, me->key);
+               goto out_err;
+       }
+-      ret = stat(mountpoint, &st);
++      ret = stat(me->key, &st);
+       if (ret == -1) {
+               error(ap->logopt,
+-                   "failed to stat direct mount trigger %s", mountpoint);
++                   "failed to stat direct mount trigger %s", me->key);
+               goto out_umount;
+       }
+-      ops->open(ap->logopt, &ioctlfd, st.st_dev, mountpoint);
++      ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key);
+       if (ioctlfd < 0) {
+-              crit(ap->logopt, "failed to create ioctl fd for %s", mountpoint);
++              crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
+               goto out_umount;
+       }
+       ops->timeout(ap->logopt, ioctlfd, timeout);
+       cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
+       if (ap->logopt & LOGOPT_DEBUG)
+-              notify_mount_result(ap, mountpoint, timeout, str_offset);
++              notify_mount_result(ap, me->key, timeout, str_offset);
+       else
+               notify_mount_result(ap, me->key, timeout, str_offset);
+       ops->close(ap->logopt, ioctlfd);
+-      mnt = mnts_add_mount(ap, mountpoint, MNTS_OFFSET);
++      mnt = mnts_add_mount(ap, me->key, MNTS_OFFSET);
+       if (!mnt)
+               error(ap->logopt,
+                     "failed to add offset mount %s to mounted list",
+-                    mountpoint);
++                    me->key);
+-      debug(ap->logopt, "mounted trigger %s at %s", me->key, mountpoint);
++      debug(ap->logopt, "mounted trigger %s", me->key);
+       return MOUNT_OFFSET_OK;
+ out_umount:
+-      umount(mountpoint);
++      umount(me->key);
+ out_err:
+-      if (stat(mountpoint, &st) == 0 && me->flags & MOUNT_FLAG_DIR_CREATED)
+-               rmdir_path(ap, mountpoint, st.st_dev);
++      if (stat(me->key, &st) == 0 && me->flags & MOUNT_FLAG_DIR_CREATED)
++               rmdir_path(ap, me->key, st.st_dev);
+       return MOUNT_OFFSET_FAIL;
+ }
+diff --git a/include/automount.h b/include/automount.h
+index 730be19a..09d84f05 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -596,7 +596,7 @@ int expire_offsets_direct(struct autofs_point *ap, struct mapent *me, int now);
+ int mount_autofs_indirect(struct autofs_point *ap, const char *root);
+ int do_mount_autofs_direct(struct autofs_point *ap, struct mapent *me, time_t timeout);
+ int mount_autofs_direct(struct autofs_point *ap);
+-int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *root, const char *offset);
++int mount_autofs_offset(struct autofs_point *ap, struct mapent *me);
+ void submount_signal_parent(struct autofs_point *ap, unsigned int success);
+ void close_mount_fds(struct autofs_point *ap);
+ int umount_autofs_indirect(struct autofs_point *ap, const char *root);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index fe931b20..12d22023 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2481,7 +2481,7 @@ static int do_mount_autofs_offset(struct autofs_point *ap,
+       debug(ap->logopt, "mount offset %s at %s", oe->key, root);
+-      ret = mount_autofs_offset(ap, oe, root, offset);
++      ret = mount_autofs_offset(ap, oe);
+       if (ret >= MOUNT_OFFSET_OK)
+               mounted++;
+       else {
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch b/archive-patches/autofs5/autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch
new file mode 100644 (file)
index 0000000..1f86438
--- /dev/null
@@ -0,0 +1,60 @@
+autofs-5.1.7 - remove unused function master_submount_list_empty()
+
+From: Ian Kent <raven@themaw.net>
+
+This function is not used anywhere now, remove it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ daemon/master.c  |   12 ------------
+ include/master.h |    1 -
+ 3 files changed, 1 insertion(+), 13 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 1c9e2a2d..002da042 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -45,6 +45,7 @@
+ - remove redundant local var from sun_mount().
+ - use mount_fullpath() in one spot in parse_mount().
+ - pass root length to mount_fullpath().
++- remove unused function master_submount_list_empty().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/master.c b/daemon/master.c
+index 022fb9dd..af9cd79f 100644
+--- a/daemon/master.c
++++ b/daemon/master.c
+@@ -1119,18 +1119,6 @@ int master_read_master(struct master *master, time_t age)
+       return 1;
+ }
+-int master_submount_list_empty(struct autofs_point *ap)
+-{
+-      int res = 0;
+-
+-      mounts_mutex_lock(ap);
+-      if (list_empty(&ap->submounts))
+-              res = 1;
+-      mounts_mutex_unlock(ap);
+-
+-      return res;
+-}
+-
+ int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
+ {
+       struct mnt_list *this, *sbmnt;
+diff --git a/include/master.h b/include/master.h
+index 0806b372..2d727943 100644
+--- a/include/master.h
++++ b/include/master.h
+@@ -116,7 +116,6 @@ void master_free_mapent_sources(struct master_mapent *, unsigned int);
+ void master_free_mapent(struct master_mapent *);
+ struct master *master_new(const char *, unsigned int, unsigned int);
+ int master_read_master(struct master *, time_t);
+-int master_submount_list_empty(struct autofs_point *ap);
+ int master_notify_submount(struct autofs_point *, const char *path, enum states);
+ void master_notify_state_change(struct master *, int);
+ int master_mount_mounts(struct master *, time_t);
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch b/archive-patches/autofs5/autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch
new file mode 100644 (file)
index 0000000..df75fec
--- /dev/null
@@ -0,0 +1,63 @@
+autofs-5.1.7 - remove unused functions cache_dump_multi() and cache_dump_cache()
+
+From: Ian Kent <raven@themaw.net>
+
+Remove debugging functions cache_dump_multi() and cache_dump_cache()
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG   |    1 +
+ lib/cache.c |   28 ----------------------------
+ 2 files changed, 1 insertion(+), 28 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 3ba748d7..60924b3f 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -29,6 +29,7 @@
+ - don't pass root to do_mount_autofs_offset().
+ - rename tree implementation functions.
+ - add some multi-mount macros.
++- remove unused functions cache_dump_multi() and cache_dump_cache().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/cache.c b/lib/cache.c
+index 1d9f5cc7..629c4d0a 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -24,34 +24,6 @@
+ #include "automount.h"
+-void cache_dump_multi(struct list_head *list)
+-{
+-      struct list_head *p;
+-      struct mapent *me;
+-
+-      list_for_each(p, list) {
+-              me = list_entry(p, struct mapent, multi_list);
+-              logmsg("key=%s", me->key);
+-      }
+-}
+-
+-void cache_dump_cache(struct mapent_cache *mc)
+-{
+-      struct mapent *me;
+-      unsigned int i;
+-
+-      for (i = 0; i < mc->size; i++) {
+-              me = mc->hash[i];
+-              if (me == NULL)
+-                      continue;
+-              while (me) {
+-                      logmsg("me->key=%s me->multi=%p dev=%ld ino=%ld",
+-                              me->key, me->multi, me->dev, me->ino);
+-                      me = me->next;
+-              }
+-      }
+-}
+-
+ void cache_readlock(struct mapent_cache *mc)
+ {
+       int status;
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch b/archive-patches/autofs5/autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch
new file mode 100644 (file)
index 0000000..5130c4e
--- /dev/null
@@ -0,0 +1,179 @@
+autofs-5.1.7 - remove unused mount offset list lock functions
+
+From: Ian Kent <raven@themaw.net>
+
+When fixing the locking in parse_mount() it was evident that there was
+no real benefit of having an additional lock for the offset list so its
+use was eliminated.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    4 ---
+ lib/cache.c         |   70 +--------------------------------------------------
+ 3 files changed, 3 insertions(+), 72 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index d25b19c8..c5619d2e 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -19,6 +19,7 @@
+ - fix return from umount_subtree_mounts() on offset list delete.
+ - pass mapent_cache to update_offset_entry().
+ - fix inconsistent locking in parse_mount().
++- remove unused mount offset list lock functions.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/automount.h b/include/automount.h
+index 09d84f05..69445b92 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -162,7 +162,6 @@ struct stack {
+ struct mapent {
+       struct mapent *next;
+       struct list_head ino_index;
+-      pthread_rwlock_t multi_rwlock;
+       struct list_head multi_list;
+       struct mapent_cache *mc;
+       struct map_source *source;
+@@ -212,9 +211,6 @@ int cache_set_offset_parent(struct mapent_cache *mc, const char *offset);
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+ int cache_delete_offset(struct mapent_cache *mc, const char *key);
+-void cache_multi_readlock(struct mapent *me);
+-void cache_multi_writelock(struct mapent *me);
+-void cache_multi_unlock(struct mapent *me);
+ int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
+ void cache_release(struct map_source *map);
+ void cache_clean_null_cache(struct mapent_cache *mc);
+diff --git a/lib/cache.c b/lib/cache.c
+index ce9e9bd2..03d0499a 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -108,58 +108,6 @@ void cache_lock_cleanup(void *arg)
+       return;
+ }
+-void cache_multi_readlock(struct mapent *me)
+-{
+-      int status;
+-
+-      if (!me)
+-              return;
+-
+-      status = pthread_rwlock_rdlock(&me->multi_rwlock);
+-      if (status) {
+-              logmsg("mapent cache multi mutex lock failed");
+-              fatal(status);
+-      }
+-      return;
+-}
+-
+-void cache_multi_writelock(struct mapent *me)
+-{
+-      int status;
+-
+-      if (!me)
+-              return;
+-
+-      status = pthread_rwlock_wrlock(&me->multi_rwlock);
+-      if (status) {
+-              logmsg("mapent cache multi mutex lock failed");
+-              fatal(status);
+-      }
+-      return;
+-}
+-
+-void cache_multi_unlock(struct mapent *me)
+-{
+-      int status;
+-
+-      if (!me)
+-              return;
+-
+-      status = pthread_rwlock_unlock(&me->multi_rwlock);
+-      if (status) {
+-              logmsg("mapent cache multi mutex unlock failed");
+-              fatal(status);
+-      }
+-      return;
+-}
+-
+-void cache_multi_lock_cleanup(void *arg)
+-{
+-      struct mapent *me = (struct mapent *) arg;
+-      cache_multi_unlock(me);
+-      return;
+-}
+-
+ static inline void ino_index_lock(struct mapent_cache *mc)
+ {
+       int status = pthread_mutex_lock(&mc->ino_index_mutex);
+@@ -626,7 +574,6 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+       struct mapent *me, *existing = NULL;
+       char *pkey, *pent;
+       u_int32_t hashval = hash(key, mc->size);
+-      int status;
+       me = (struct mapent *) malloc(sizeof(struct mapent));
+       if (!me)
+@@ -665,10 +612,6 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+       me->ino = (ino_t) -1;
+       me->flags = 0;
+-      status = pthread_rwlock_init(&me->multi_rwlock, NULL);
+-      if (status)
+-              fatal(status);
+-
+       /* 
+        * We need to add to the end if values exist in order to
+        * preserve the order in which the map was read on lookup.
+@@ -924,7 +867,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
+       return ret;
+ }
+-/* cache_multi_lock of the multi mount owner must be held by caller */
++/* cache write lock of the multi mount owner must be held by caller */
+ int cache_delete_offset(struct mapent_cache *mc, const char *key)
+ {
+       u_int32_t hashval = hash(key, mc->size);
+@@ -956,9 +899,6 @@ int cache_delete_offset(struct mapent_cache *mc, const char *key)
+       return CHE_FAIL;
+ delete:
+-      status = pthread_rwlock_destroy(&me->multi_rwlock);
+-      if (status)
+-              fatal(status);
+       list_del(&me->multi_list);
+       ino_index_lock(mc);
+       list_del(&me->ino_index);
+@@ -976,7 +916,7 @@ int cache_delete(struct mapent_cache *mc, const char *key)
+ {
+       struct mapent *me = NULL, *pred;
+       u_int32_t hashval = hash(key, mc->size);
+-      int status, ret = CHE_OK;
++      int ret = CHE_OK;
+       char this[PATH_MAX];
+       strcpy(this, key);
+@@ -997,9 +937,6 @@ int cache_delete(struct mapent_cache *mc, const char *key)
+                               goto done;
+                       }
+                       pred->next = me->next;
+-                      status = pthread_rwlock_destroy(&me->multi_rwlock);
+-                      if (status)
+-                              fatal(status);
+                       ino_index_lock(mc);
+                       list_del(&me->ino_index);
+                       ino_index_unlock(mc);
+@@ -1029,9 +966,6 @@ int cache_delete(struct mapent_cache *mc, const char *key)
+                       goto done;
+               }
+               mc->hash[hashval] = me->next;
+-              status = pthread_rwlock_destroy(&me->multi_rwlock);
+-              if (status)
+-                      fatal(status);
+               ino_index_lock(mc);
+               list_del(&me->ino_index);
+               ino_index_unlock(mc);
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch b/archive-patches/autofs5/autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch
new file mode 100644 (file)
index 0000000..dbbecb7
--- /dev/null
@@ -0,0 +1,66 @@
+autofs-5.1.7 - remove unused parameter form do_mount_autofs_offset()
+
+From: Ian Kent <raven@themaw.net>
+
+The offset parameter of do_mount_autofs_offset() isn't used.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   10 ++++------
+ 2 files changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 45be4783..3eda995c 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -10,6 +10,7 @@
+ - simplify cache_get_parent().
+ - set offset parent in update_offset_entry().
+ - remove redundant variables from mount_autofs_offset().
++- remove unused parameter form do_mount_autofs_offset().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 12d22023..8e88182f 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2472,9 +2472,7 @@ out:
+ }
+ static int do_mount_autofs_offset(struct autofs_point *ap,
+-                                struct mapent *oe, const char *root,
+-                                char *offset)
+-
++                                struct mapent *oe, const char *root)
+ {
+       int mounted = 0;
+       int ret;
+@@ -2529,7 +2527,7 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+               if (!oe || !oe->mapent)
+                       goto cont;
+-              mounted += do_mount_autofs_offset(ap, oe, root, offset);
++              mounted += do_mount_autofs_offset(ap, oe, root);
+               /*
+                * If re-constructing a multi-mount it's necessary to walk
+@@ -2666,7 +2664,7 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
+                        */
+                       ret = rmdir_path_offset(ap, oe);
+                       if (ret == -1 && !stat(oe->key, &st)) {
+-                              ret = do_mount_autofs_offset(ap, oe, root, offset);
++                              ret = do_mount_autofs_offset(ap, oe, root);
+                               if (ret)
+                                       left++;
+                               /* But we did origianlly create this */
+@@ -2847,7 +2845,7 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
+                        */
+                       ret = rmdir_path_offset(ap, oe);
+                       if (ret == -1 && !stat(oe->key, &st)) {
+-                              ret = do_mount_autofs_offset(ap, oe, root, offset);
++                              ret = do_mount_autofs_offset(ap, oe, root);
+                               if (ret) {
+                                       left++;
+                                       /* But we did origianlly create this */
diff --git a/archive-patches/autofs5/autofs-5.1.7-remove-unused-variable-from-get_exports.patch b/archive-patches/autofs5/autofs-5.1.7-remove-unused-variable-from-get_exports.patch
new file mode 100644 (file)
index 0000000..10e56a9
--- /dev/null
@@ -0,0 +1,36 @@
+autofs-5.1.7 - remove unused variable from get_exports()
+
+From: Ian Kent <raven@themaw.net>
+
+Fix complier warning about unused variable entry in get_exports().
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ modules/lookup_hosts.c |    1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 9d0f4278..9c3ede45 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -49,6 +49,7 @@
+ - move amd mounts removal into lib/mounts.c.
+ - check for offset with no mount location.
+ - remove mounts_mutex.
++- remove unused variable from get_exports().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
+index 7e101ddb..24edf00c 100644
+--- a/modules/lookup_hosts.c
++++ b/modules/lookup_hosts.c
+@@ -87,7 +87,6 @@ int lookup_read_master(struct master *master, time_t age, void *context)
+ static char *get_exports(struct autofs_point *ap, const char *host)
+ {
+       char buf[MAX_ERR_BUF];
+-      char entry[PATH_MAX + 1];
+       char *mapent;
+       struct exportinfo *exp, *this;
+       size_t hostlen = strlen(host);
diff --git a/archive-patches/autofs5/autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch b/archive-patches/autofs5/autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch
new file mode 100644 (file)
index 0000000..29b9660
--- /dev/null
@@ -0,0 +1,159 @@
+autofs-5.1.7 - rename path to m_offset in update_offset_entry()
+
+From: Ian Kent <raven@themaw.net>
+
+Rename local variable from path to m_offset in update_offset_entry() to
+make the meaning of this variable clear.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   46 +++++++++++++++++++++++-----------------------
+ 2 files changed, 24 insertions(+), 23 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index e822efec..0e9ca94f 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -25,6 +25,7 @@
+ - don't add offset mounts to mounted mounts table.
+ - reduce umount EBUSY check delay.
+ - cleanup cache_delete() a little.
++- rename path to m_offset in update_offset_entry().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index a6630a76..34d4441e 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -796,36 +796,36 @@ static int
+ update_offset_entry(struct autofs_point *ap,
+                   struct mapent_cache *mc, const char *name,
+                   const char *m_root, int m_root_len,
+-                  const char *path, const char *myoptions,
++                  const char *m_offset, const char *myoptions,
+                   const char *loc, time_t age)
+ {
+       char m_key[PATH_MAX + 1];
+       char m_mapent[MAPENT_MAX_LEN + 1];
+-      int p_len, m_key_len, m_options_len, m_mapent_len;
++      int o_len, m_key_len, m_options_len, m_mapent_len;
+       int ret;
+       memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+       /* Internal hosts map may have loc == NULL */
+-      if (!*path) {
++      if (!*m_offset) {
+               error(ap->logopt,
+-                    MODPREFIX "syntax error in offset %s -> %s", path, loc);
++                    MODPREFIX "syntax error in offset %s -> %s", m_offset, loc);
+               return CHE_FAIL;
+       }
+-      p_len = strlen(path);
++      o_len = strlen(m_offset);
+       /* Trailing '/' causes us pain */
+-      if (p_len > 1) {
+-              while (p_len > 1 && path[p_len - 1] == '/')
+-                      p_len--;
++      if (o_len > 1) {
++              while (o_len > 1 && m_offset[o_len - 1] == '/')
++                      o_len--;
+       }
+-      m_key_len = m_root_len + p_len;
++      m_key_len = m_root_len + o_len;
+       if (m_key_len > PATH_MAX) {
+               error(ap->logopt, MODPREFIX "multi mount key too long");
+               return CHE_FAIL;
+       }
+       strcpy(m_key, m_root);
+-      strncat(m_key, path, p_len);
++      strncat(m_key, m_offset, o_len);
+       m_key[m_key_len] = '\0';
+       m_options_len = 0;
+@@ -860,15 +860,15 @@ update_offset_entry(struct autofs_point *ap,
+       if (ret == CHE_DUPLICATE) {
+               warn(ap->logopt, MODPREFIX
+-                   "syntax error or duplicate offset %s -> %s", path, loc);
++                   "syntax error or duplicate offset %s -> %s", m_offset, loc);
+               ret = CHE_OK;
+       } else if (ret == CHE_FAIL)
+               debug(ap->logopt, MODPREFIX
+-                    "failed to update multi-mount offset %s -> %s", path, m_mapent);
++                    "failed to update multi-mount offset %s -> %s", m_offset, m_mapent);
+       else {
+               ret = CHE_OK;
+               debug(ap->logopt, MODPREFIX
+-                    "updated multi-mount offset %s -> %s", path, m_mapent);
++                    "updated multi-mount offset %s -> %s", m_offset, m_mapent);
+       }
+       return ret;
+@@ -1538,22 +1538,22 @@ dont_expand:
+               /* It's a multi-mount; deal with it */
+               do {
+-                      char *path, *myoptions, *loc;
++                      char *m_offset, *myoptions, *loc;
+                       int status;
+                       if ((*p == '"' && *(p + 1) != '/') || (*p != '"' && *p != '/')) {
+                               l = 0;
+-                              path = dequote("/", 1, ap->logopt);
++                              m_offset = dequote("/", 1, ap->logopt);
+                               debug(ap->logopt,
+-                                    MODPREFIX "dequote(\"/\") -> %s", path);
++                                    MODPREFIX "dequote(\"/\") -> %s", m_offset);
+                       } else {
+                               l = span_space(p, mapent_len - (p - pmapent));
+-                              path = sanitize_path(p, l, LKP_MULTI, ap->logopt);
++                              m_offset = sanitize_path(p, l, LKP_MULTI, ap->logopt);
+                               debug(ap->logopt, MODPREFIX
+-                                    "dequote(\"%.*s\") -> %s", l, p, path);
++                                    "dequote(\"%.*s\") -> %s", l, p, m_offset);
+                       }
+-                      if (!path) {
++                      if (!m_offset) {
+                               warn(ap->logopt, MODPREFIX "null path or out of memory");
+                               cache_writelock(mc);
+                               cache_delete_offset_list(mc, name);
+@@ -1575,7 +1575,7 @@ dont_expand:
+                               cache_writelock(mc);
+                               cache_delete_offset_list(mc, name);
+                               cache_unlock(mc);
+-                              free(path);
++                              free(m_offset);
+                               free(options);
+                               free(pmapent);
+                               pthread_setcancelstate(cur_state, NULL);
+@@ -1587,14 +1587,14 @@ dont_expand:
+                       status = update_offset_entry(ap, mc,
+                                                    name, m_root, m_root_len,
+-                                                   path, myoptions, loc, age);
++                                                   m_offset, myoptions, loc, age);
+                       if (status != CHE_OK) {
+                               warn(ap->logopt, MODPREFIX "error adding multi-mount");
+                               cache_writelock(mc);
+                               cache_delete_offset_list(mc, name);
+                               cache_unlock(mc);
+-                              free(path);
++                              free(m_offset);
+                               free(options);
+                               free(pmapent);
+                               free(myoptions);
+@@ -1606,7 +1606,7 @@ dont_expand:
+                       if (loc)
+                               free(loc);
+-                      free(path);
++                      free(m_offset);
+                       free(myoptions);
+               } while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
diff --git a/archive-patches/autofs5/autofs-5.1.7-rename-tree-implementation-functions.patch b/archive-patches/autofs5/autofs-5.1.7-rename-tree-implementation-functions.patch
new file mode 100644 (file)
index 0000000..57bbc5f
--- /dev/null
@@ -0,0 +1,197 @@
+autofs-5.1.7 - rename tree implementation functions
+
+From: Ian Kent <raven@themaw.net>
+
+Rename the tree struct and functions to make them consistent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   80 +++++++++++++++++++++++++++++-----------------------------
+ 2 files changed, 41 insertions(+), 40 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 2a07bd45..1bf20699 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -27,6 +27,7 @@
+ - cleanup cache_delete() a little.
+ - rename path to m_offset in update_offset_entry().
+ - don't pass root to do_mount_autofs_offset().
++- rename tree implementation functions.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/mounts.c b/lib/mounts.c
+index 289500da..f5b905a6 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1225,30 +1225,30 @@ done:
+       return has_mounted_mounts;
+ }
+-struct node {
++struct tree_node {
+       struct mnt_list *mnt;
+-      struct node *left;
+-      struct node *right;
++      struct tree_node *left;
++      struct tree_node *right;
+ };
+-static struct node *new(struct mnt_list *mnt)
++static struct tree_node *tree_new(struct mnt_list *mnt)
+ {
+-      struct node *n;
++      struct tree_node *n;
+-      n = malloc(sizeof(struct node));
++      n = malloc(sizeof(struct tree_node));
+       if (!n)
+               return NULL;
+-      memset(n, 0, sizeof(struct node));
++      memset(n, 0, sizeof(struct tree_node));
+       n->mnt = mnt;
+       return n;
+ }
+-static struct node *tree_root(struct mnt_list *mnt)
++static struct tree_node *tree_root(struct mnt_list *mnt)
+ {
+-      struct node *n;
++      struct tree_node *n;
+-      n = new(mnt);
++      n = tree_new(mnt);
+       if (!n) {
+               error(LOGOPT_ANY, "failed to allcate tree root");
+               return NULL;
+@@ -1257,37 +1257,37 @@ static struct node *tree_root(struct mnt_list *mnt)
+       return n;
+ }
+-static struct node *add_left(struct node *this, struct mnt_list *mnt)
++static struct tree_node *tree_add_left(struct tree_node *n, struct mnt_list *mnt)
+ {
+-      struct node *n;
++      struct tree_node *new;
+-      n = new(mnt);
+-      if (!n) {
++      new = tree_new(mnt);
++      if (!new) {
+               error(LOGOPT_ANY, "failed to allcate tree node");
+               return NULL;
+       }
+-      this->left = n;
++      n->left = new;
+       return n;
+ }
+-static struct node *add_right(struct node *this, struct mnt_list *mnt)
++static struct tree_node *tree_add_right(struct tree_node *n, struct mnt_list *mnt)
+ {
+-      struct node *n;
++      struct tree_node *new;
+-      n = new(mnt);
+-      if (!n) {
++      new = tree_new(mnt);
++      if (!new) {
+               error(LOGOPT_ANY, "failed to allcate tree node");
+               return NULL;
+       }
+-      this->right = n;
++      n->right = new;
+       return n;
+ }
+-static struct node *add_node(struct node *root, struct mnt_list *mnt)
++static struct tree_node *tree_add_node(struct tree_node *root, struct mnt_list *mnt)
+ {
+-      struct node *p, *q;
++      struct tree_node *p, *q;
+       unsigned int mp_len;
+       mp_len = strlen(mnt->mp);
+@@ -1307,43 +1307,43 @@ static struct node *add_node(struct node *root, struct mnt_list *mnt)
+               error(LOGOPT_ANY, "duplicate entry in mounts list");
+       else {
+               if (mp_len < strlen(p->mnt->mp))
+-                      return add_left(p, mnt);
++                      return tree_add_left(p, mnt);
+               else
+-                      return add_right(p, mnt);
++                      return tree_add_right(p, mnt);
+       }
+       return NULL;
+ }
+-static void tree_free(struct node *tree)
++static void tree_free(struct tree_node *root)
+ {
+-      if (tree->right)
+-              tree_free(tree->right);
+-      if (tree->left)
+-              tree_free(tree->left);
+-      free(tree);
++      if (root->right)
++              tree_free(root->right);
++      if (root->left)
++              tree_free(root->left);
++      free(root);
+ }
+-static void traverse(struct node *node, struct list_head *mnts)
++static void tree_traverse(struct tree_node *n, struct list_head *mnts)
+ {
+-      if (node->right)
+-              traverse(node->right, mnts);
+-      list_add_tail(&node->mnt->expire, mnts);
+-      if (node->left)
+-              traverse(node->left, mnts);
++      if (n->right)
++              tree_traverse(n->right, mnts);
++      list_add_tail(&n->mnt->expire, mnts);
++      if (n->left)
++              tree_traverse(n->left, mnts);
+ }
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+ {
+       struct mnt_list *mnt;
+-      struct node *tree = NULL;
++      struct tree_node *tree = NULL;
+       mnts_hash_mutex_lock();
+       if (list_empty(&ap->mounts))
+               goto done;
+       list_for_each_entry(mnt, &ap->mounts, mount) {
+-              struct node *n;
++              struct tree_node *n;
+               if (!(mnt->flags & MNTS_MOUNTED))
+                       continue;
+@@ -1359,7 +1359,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+                       continue;
+               }
+-              n = add_node(tree, mnt);
++              n = tree_add_node(tree, mnt);
+               if (!n) {
+                       error(LOGOPT_ANY, "failed to add expire tree node");
+                       tree_free(tree);
+@@ -1367,7 +1367,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+               }
+       }
+-      traverse(tree, mnts);
++      tree_traverse(tree, mnts);
+       tree_free(tree);
+ done:
+       mnts_hash_mutex_unlock();
diff --git a/archive-patches/autofs5/autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch b/archive-patches/autofs5/autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch
new file mode 100644 (file)
index 0000000..5f5a518
--- /dev/null
@@ -0,0 +1,104 @@
+autofs-5.1.7 - set offset parent in update_offset_entry()
+
+From: Ian Kent <raven@themaw.net>
+
+Avoid the list traversal in cache_set_parents() by setting the
+offset parent when updating the offset.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    2 +-
+ lib/cache.c         |   26 +++++++++++---------------
+ modules/parse_sun.c |    5 ++++-
+ 4 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index ee746277..c4ebb52f 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -8,6 +8,7 @@
+ - eliminate cache_lookup_offset() usage.
+ - fix is mounted check on non existent path.
+ - simplify cache_get_parent().
++- set offset parent in update_offset_entry().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/automount.h b/include/automount.h
+index 2f09e8e7..730be19a 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -208,7 +208,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
+ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age);
+ int cache_lookup_negative(struct mapent *me, const char *key);
+ void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout);
+-int cache_set_parents(struct mapent *mm);
++int cache_set_offset_parent(struct mapent_cache *mc, const char *offset);
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+ int cache_delete_offset(struct mapent_cache *mc, const char *key);
+diff --git a/lib/cache.c b/lib/cache.c
+index 53f290cd..ce9e9bd2 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -864,25 +864,21 @@ static struct mapent *get_offset_parent(struct mapent_cache *mc,
+       return NULL;
+ }
+-int cache_set_parents(struct mapent *mm)
++int cache_set_offset_parent(struct mapent_cache *mc, const char *offset)
+ {
+-      struct list_head *multi_head, *p;
+-      struct mapent *this;
++      struct mapent *this, *parent;
+-      if (!mm->multi)
++      this = cache_lookup_distinct(mc, offset);
++      if (!this)
++              return 0;
++      if (!this->multi)
+               return 0;
+-      multi_head = &mm->multi->multi_list;
+-
+-      list_for_each(p, multi_head) {
+-              struct mapent *parent;
+-              this = list_entry(p, struct mapent, multi_list);
+-              parent = get_offset_parent(mm->mc, this->key);
+-              if (parent)
+-                      this->parent = parent;
+-              else
+-                      this->parent = mm->multi;
+-      }
++      parent = get_offset_parent(mc, offset);
++      if (parent)
++              this->parent = parent;
++      else
++              this->parent = this->multi;
+       return 1;
+ }
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 819d6adc..f42af7b7 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -859,6 +859,10 @@ update_offset_entry(struct autofs_point *ap, const char *name,
+       }
+       ret = cache_update_offset(mc, name, m_key, m_mapent, age);
++
++      if (!cache_set_offset_parent(mc, m_key))
++              error(ap->logopt, "failed to set offset parent");
++
+       if (ret == CHE_DUPLICATE) {
+               warn(ap->logopt, MODPREFIX
+                    "syntax error or duplicate offset %s -> %s", path, loc);
+@@ -1613,7 +1617,6 @@ dont_expand:
+                */
+               if (me == me->multi)
+                       clean_stale_multi_triggers(ap, me, NULL, NULL);
+-              cache_set_parents(me);
+               rv = mount_subtree(ap, me, name, NULL, options, ctxt);
diff --git a/archive-patches/autofs5/autofs-5.1.7-simplify-get_parent.patch b/archive-patches/autofs5/autofs-5.1.7-simplify-get_parent.patch
new file mode 100644 (file)
index 0000000..85a1306
--- /dev/null
@@ -0,0 +1,105 @@
+autofs-5.1.7 - simplify cache_get_parent()
+
+From: Ian Kent <raven@themaw.net>
+
+Eliminate the list traversal from get_parent() and rename it to
+get_offset_parent() to better describe it's usage.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG   |    1 +
+ lib/cache.c |   46 ++++++++++++++++++++++++++++------------------
+ 2 files changed, 29 insertions(+), 18 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index e55fd66a..ee746277 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -7,6 +7,7 @@
+ - Fix option for master read wait.
+ - eliminate cache_lookup_offset() usage.
+ - fix is mounted check on non existent path.
++- simplify cache_get_parent().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/lib/cache.c b/lib/cache.c
+index d3b6642b..53f290cd 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -827,47 +827,57 @@ void cache_update_negative(struct mapent_cache *mc,
+ }
+-static struct mapent *get_parent(const char *key, struct list_head *head, struct list_head **pos)
++static struct mapent *get_offset_parent(struct mapent_cache *mc,
++                                      const char *key)
+ {
+-      struct list_head *next;
+-      struct mapent *this, *last;
+-      int eq;
++      struct mapent *me;
++      char *parent, *tail;
++      int key_len;
+-      last = NULL;
+-      next = *pos ? (*pos)->next : head->next;
++      key_len = strlen(key);
+-      list_for_each(next, head) {
+-              this = list_entry(next, struct mapent, multi_list);
++      /* Check if this is the root offset */
++      if (key[key_len - 1] == '/')
++              return NULL;
++
++      parent = strdup(key);
++      tail = &parent[key_len - 1];
+-              if (!strcmp(this->key, key))
++      while (*tail) {
++              while (*tail != '/')
++                      tail--;
++
++              *tail = 0;
++
++              tail--;
++              if (tail == parent)
+                       break;
+-              eq = strncmp(this->key, key, strlen(this->key));
+-              if (eq == 0) {
+-                      *pos = next;
+-                      last = this;
+-                      continue;
++              me = cache_lookup_distinct(mc, parent);
++              if (me) {
++                      free(parent);
++                      return me;
+               }
+       }
++      free(parent);
+-      return last;
++      return NULL;
+ }
+ int cache_set_parents(struct mapent *mm)
+ {
+-      struct list_head *multi_head, *p, *pos;
++      struct list_head *multi_head, *p;
+       struct mapent *this;
+       if (!mm->multi)
+               return 0;
+-      pos = NULL;
+       multi_head = &mm->multi->multi_list;
+       list_for_each(p, multi_head) {
+               struct mapent *parent;
+               this = list_entry(p, struct mapent, multi_list);
+-              parent = get_parent(this->key, multi_head, &pos);
++              parent = get_offset_parent(mm->mc, this->key);
+               if (parent)
+                       this->parent = parent;
+               else
diff --git a/archive-patches/autofs5/autofs-5.1.7-simplify-mount_subtree-mount-check.patch b/archive-patches/autofs5/autofs-5.1.7-simplify-mount_subtree-mount-check.patch
new file mode 100644 (file)
index 0000000..01b2071
--- /dev/null
@@ -0,0 +1,46 @@
+autofs-5.1.7 - simplify mount_subtree() mount check
+
+From: Ian Kent <raven@themaw.net>
+
+The check of the return from sun_mount() following the possible mount
+of the root offset in mount_subtree() can be simpler.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   10 +---------
+ 2 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index b1ce7b69..f5c5641a 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -13,6 +13,7 @@
+ - remove unused parameter form do_mount_autofs_offset().
+ - refactor umount_multi_triggers().
+ - eliminate clean_stale_multi_triggers().
++- simplify mount_subtree() mount check.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index f4d5125c..1142e8a3 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1203,15 +1203,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+                               free(ro_loc);
+               }
+-              if (ro && rv == 0) {
+-                      ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+-                      if (ret == -1) {
+-                              error(ap->logopt, MODPREFIX
+-                                       "failed to mount offset triggers");
+-                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+-                              return 1;
+-                      }
+-              } else if (rv <= 0) {
++              if ((ro && rv == 0) || rv <= 0) {
+                       ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+                       if (ret == -1) {
+                               error(ap->logopt, MODPREFIX
diff --git a/archive-patches/autofs5/autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch b/archive-patches/autofs5/autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch
new file mode 100644 (file)
index 0000000..4335ed1
--- /dev/null
@@ -0,0 +1,414 @@
+autofs-5.1.7 - switch to use tree implementation for offsets
+
+From: Ian Kent <raven@themaw.net>
+
+Change to use the tree mapent implementation for the handling
+of offset mounts.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                |    1 
+ daemon/automount.c       |   25 ++----------
+ daemon/lookup.c          |    2 -
+ include/automount.h      |    8 ++--
+ lib/cache.c              |   67 ---------------------------------
+ lib/mounts.c             |    4 +-
+ modules/lookup_program.c |    2 -
+ modules/parse_sun.c      |   94 ++++++++++++----------------------------------
+ 8 files changed, 39 insertions(+), 164 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 892f7581..5ac09f77 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -40,6 +40,7 @@
+ - add tree_mapent_cleanup_offsets().
+ - add set_offset_tree_catatonic().
+ - add mount and umount offsets functions.
++- switch to use tree implementation for offsets.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index f4608fc9..7833dfae 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -551,29 +551,15 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+       left = 0;
+       if (me && IS_MM(me)) {
+-              char root[PATH_MAX + 1];
+               char key[PATH_MAX + 1];
+               struct mapent *tmp;
+-              int status;
+-              char *base;
+-
+-              if (!strchr(MM_ROOT(me)->key, '/'))
+-                      /* Indirect multi-mount root */
+-                      /* sprintf okay - if it's mounted, it's
+-                       * PATH_MAX or less bytes */
+-                      sprintf(root, "%s/%s", ap->path, MM_ROOT(me)->key);
+-              else
+-                      strcpy(root, MM_ROOT(me)->key);
+-
+-              if (IS_MM_ROOT(me))
+-                      base = NULL;
+-              else
+-                      base = me->key + strlen(root);
++              int ret;
+-              left = umount_multi_triggers(ap, me, root, base);
+-              if (left) {
++              ret = tree_mapent_umount_offsets(me, 1);
++              if (!ret) {
+                       warn(ap->logopt,
+                            "some offset mounts still present under %s", path);
++                      left++;
+               }
+               strcpy(key, me->key);
+@@ -589,8 +575,7 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
+               }
+               if (!left && IS_MM_ROOT(me)) {
+-                      status = cache_delete_offset_list(mc, me->key);
+-                      if (status != CHE_OK) {
++                      if (!tree_mapent_delete_offsets(mc, me->key)) {
+                               warn(ap->logopt, "couldn't delete offset list");
+                               left++;
+                       }
+diff --git a/daemon/lookup.c b/daemon/lookup.c
+index 5116b927..32dbc24d 100644
+--- a/daemon/lookup.c
++++ b/daemon/lookup.c
+@@ -843,7 +843,7 @@ static int lookup_amd_instance(struct autofs_point *ap,
+               return NSS_STATUS_UNKNOWN;
+       }
+-      m_key = malloc(ap->len + strlen(MM_ROOT(me)->key) + 2);
++      m_key = malloc(ap->len + MM_ROOT(me)->len + 2);
+       if (!m_key) {
+               error(ap->logopt,
+                    "failed to allocate storage for search key");
+diff --git a/include/automount.h b/include/automount.h
+index f6023e27..a71b8674 100644
+--- a/include/automount.h
++++ b/include/automount.h
+@@ -187,10 +187,10 @@ struct mapent {
+       ino_t ino;
+ };
+-#define IS_MM(me)     (me->multi)
+-#define IS_MM_ROOT(me)        (me->multi == me)
+-#define MM_ROOT(me)   (me->multi)
+-#define MM_PARENT(me) (me->parent)
++#define IS_MM(me)     (me->mm_root)
++#define IS_MM_ROOT(me)        (me->mm_root == &me->node)
++#define MM_ROOT(me)   (MAPENT(me->mm_root))
++#define MM_PARENT(me) (MAPENT(me->mm_parent))
+ void cache_lock_cleanup(void *arg);
+ void cache_readlock(struct mapent_cache *mc);
+diff --git a/lib/cache.c b/lib/cache.c
+index 7c409a56..93b02daf 100644
+--- a/lib/cache.c
++++ b/lib/cache.c
+@@ -682,14 +682,6 @@ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *k
+               return CHE_FAIL;
+       }
+-      me = cache_lookup_distinct(mc, key);
+-      if (me) {
+-              cache_add_ordered_offset(me, &owner->multi_list);
+-              MM_ROOT(me) = owner;
+-              goto done;
+-      }
+-      ret = CHE_FAIL;
+-done:
+       return ret; 
+ }
+@@ -958,65 +950,6 @@ done:
+       return ret;
+ }
+-/* cache must be write locked by caller */
+-int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
+-{
+-      unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt();
+-      struct mapent *me;
+-      struct mapent *this;
+-      struct list_head *head, *next;
+-      int remain = 0;
+-      int status;
+-
+-      me = cache_lookup_distinct(mc, key);
+-      if (!me)
+-              return CHE_FAIL;
+-
+-      /* Not offset list owner */
+-      if (!IS_MM_ROOT(me))
+-              return CHE_FAIL;
+-
+-      head = &me->multi_list;
+-      next = head->next;
+-      while (next != head) {
+-              this = list_entry(next, struct mapent, multi_list);
+-              next = next->next;
+-              if (this->ioctlfd != -1) {
+-                      error(logopt,
+-                            "active offset mount key %s", this->key);
+-                      return CHE_FAIL;
+-              }
+-      }
+-
+-      head = &me->multi_list;
+-      next = head->next;
+-      while (next != head) {
+-              this = list_entry(next, struct mapent, multi_list);
+-              next = next->next;
+-              list_del_init(&this->multi_list);
+-              MM_ROOT(this) = NULL;
+-              debug(logopt, "deleting offset key %s", this->key);
+-              status = cache_delete(mc, this->key);
+-              if (status == CHE_FAIL) {
+-                      warn(logopt,
+-                           "failed to delete offset %s", this->key);
+-                      MM_ROOT(this) = me;
+-                      /* TODO: add list back in */
+-                      remain++;
+-              }
+-      }
+-
+-      if (!remain) {
+-              list_del_init(&me->multi_list);
+-              MM_ROOT(me) = NULL;
+-      }
+-
+-      if (remain)
+-              return CHE_FAIL;
+-
+-      return CHE_OK;
+-}
+-
+ void cache_release(struct map_source *map)
+ {
+       struct mapent_cache *mc;
+diff --git a/lib/mounts.c b/lib/mounts.c
+index f7c29475..6ca7eff1 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -2893,7 +2893,7 @@ void set_indirect_mount_tree_catatonic(struct autofs_point *ap)
+                       /* Only need to set offset mounts catatonic */
+                       if (IS_MM(me) && IS_MM_ROOT(me))
+-                              set_multi_mount_tree_catatonic(ap, me);
++                              set_offset_tree_catatonic(ap, me);
+ next:
+                       me = cache_enumerate(mc, me);
+               }
+@@ -2913,7 +2913,7 @@ void set_direct_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+ {
+       /* Set offset mounts catatonic for this mapent */
+       if (IS_MM(me) && IS_MM_ROOT(me))
+-              set_multi_mount_tree_catatonic(ap, me);
++              set_offset_tree_catatonic(ap, me);
+       set_mount_catatonic(ap, me, me->ioctlfd);
+ }
+diff --git a/modules/lookup_program.c b/modules/lookup_program.c
+index 70f27545..6cab52c8 100644
+--- a/modules/lookup_program.c
++++ b/modules/lookup_program.c
+@@ -658,7 +658,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
+                       me = cache_lookup_distinct(mc, name);
+                       if (me) {
+                               if (IS_MM(me))
+-                                      cache_delete_offset_list(mc, name);
++                                      tree_mapent_delete_offsets(mc, name);
+                               cache_delete(mc, name);
+                       }
+                       cache_unlock(mc);
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index b1f64ca0..d6ef48b8 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -854,8 +854,8 @@ update_offset_entry(struct autofs_point *ap,
+       cache_writelock(mc);
+       ret = cache_update_offset(mc, name, m_key, m_mapent, age);
+-      if (!cache_set_offset_parent(mc, m_key))
+-              error(ap->logopt, "failed to set offset parent");
++      if (!tree_mapent_add_node(mc, name, m_key))
++              error(ap->logopt, "failed to add offset %s to tree", m_key);
+       cache_unlock(mc);
+       if (ret == CHE_DUPLICATE) {
+@@ -1134,10 +1134,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+                        const char *name, char *loc, char *options, void *ctxt)
+ {
+       struct mapent *me;
+-      struct mapent *ro;
+-      char *mm_root, *mm_base, *mm_key;
+-      unsigned int mm_root_len;
+-      int start, ret = 0, rv;
++      int ret = 0, rv;
+       cache_readlock(mc);
+       me = cache_lookup_distinct(mc, name);
+@@ -1148,34 +1145,18 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+       rv = 0;
+-      mm_key = MM_ROOT(me)->key;
+-
+-      if (*mm_key == '/') {
+-              mm_root = mm_key;
+-              start = strlen(mm_key);
+-      } else {
+-              start = ap->len + strlen(mm_key) + 1;
+-              mm_root = alloca(start + 3);
+-              strcpy(mm_root, ap->path);
+-              strcat(mm_root, "/");
+-              strcat(mm_root, mm_key);
+-      }
+-      mm_root_len = strlen(mm_root);
+-
+       if (IS_MM_ROOT(me)) {
+               char key[PATH_MAX + 1];
++              struct mapent *ro;
++              size_t len;
+-              if (mm_root_len + 1 > PATH_MAX) {
++              len = mount_fullpath(key, PATH_MAX, ap->path, me->key);
++              if (!len) {
+                       warn(ap->logopt, "path loo long");
+                       return 1;
+               }
+-
+-              /* name = NULL */
+-              /* destination = mm_root */
+-              mm_base = "/";
+-
+-              strcpy(key, mm_root);
+-              strcat(key, mm_base);
++              key[len] = '/';
++              key[len + 1] = 0;
+               /* Mount root offset if it exists */
+               ro = cache_lookup_distinct(me->mc, key);
+@@ -1194,7 +1175,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+                               warn(ap->logopt,
+                                     MODPREFIX "failed to parse root offset");
+                               cache_writelock(mc);
+-                              cache_delete_offset_list(mc, name);
++                              tree_mapent_delete_offsets(mc, name);
+                               cache_unlock(mc);
+                               return 1;
+                       }
+@@ -1209,10 +1190,10 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+                               free(ro_loc);
+               }
+-              if ((ro && rv == 0) || rv <= 0) {
+-                      ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+-                      if (ret == -1) {
+-                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++              if (rv <= 0) {
++                      ret = tree_mapent_mount_offsets(me, 1);
++                      if (!ret) {
++                              tree_mapent_cleanup_offsets(me);
+                               cache_unlock(mc);
+                               error(ap->logopt, MODPREFIX
+                                        "failed to mount offset triggers");
+@@ -1223,39 +1204,14 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+               int loclen = strlen(loc);
+               int namelen = strlen(name);
+-              /* name = mm_root + mm_base */
+-              /* destination = mm_root + mm_base = name */
+-              mm_base = &me->key[start];
+-
++              /* Mounts at nesting points must succeed for subtree
++               * offsets to be mounted.
++               */
+               rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
+               if (rv == 0) {
+-                      ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
+-                      if (ret == -1) {
+-                              cleanup_multi_triggers(ap, me, name, start, mm_base);
+-                              cache_unlock(mc);
+-                              error(ap->logopt, MODPREFIX
+-                                       "failed to mount offset triggers");
+-                              return 1;
+-                      }
+-              } else if (rv < 0) {
+-                      char mm_root_base[PATH_MAX + 1];
+-                      unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
+-      
+-                      if (mm_root_base_len > PATH_MAX) {
+-                              cache_unlock(mc);
+-                              warn(ap->logopt, MODPREFIX "path too long");
+-                              cache_writelock(mc);
+-                              cache_delete_offset_list(mc, name);
+-                              cache_unlock(mc);
+-                              return 1;
+-                      }
+-
+-                      strcpy(mm_root_base, mm_root);
+-                      strcat(mm_root_base, mm_base);
+-
+-                      ret = mount_multi_triggers(ap, me->multi, mm_root_base, start, mm_base);
+-                      if (ret == -1) {
+-                              cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++                      ret = tree_mapent_mount_offsets(me, 1);
++                      if (!ret) {
++                              tree_mapent_cleanup_offsets(me);
+                               cache_unlock(mc);
+                               error(ap->logopt, MODPREFIX
+                                        "failed to mount offset triggers");
+@@ -1265,7 +1221,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+       }
+       cache_unlock(mc);
+-      /* Mount for base of tree failed */
++      /* strict mount failed */
+       if (rv > 0)
+               return rv;
+@@ -1506,7 +1462,7 @@ dont_expand:
+               /* So we know we're the multi-mount root */
+               if (!IS_MM(me))
+-                      me->multi = me;
++                      MAPENT_SET_ROOT(me, tree_mapent_root(me))
+               else {
+                       /*
+                        * The amd host mount type assumes the lookup name
+@@ -1556,7 +1512,7 @@ dont_expand:
+                       if (!m_offset) {
+                               warn(ap->logopt, MODPREFIX "null path or out of memory");
+                               cache_writelock(mc);
+-                              cache_delete_offset_list(mc, name);
++                              tree_mapent_delete_offsets(mc, name);
+                               cache_unlock(mc);
+                               free(options);
+                               free(pmapent);
+@@ -1573,7 +1529,7 @@ dont_expand:
+                       l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
+                       if (!l) {
+                               cache_writelock(mc);
+-                              cache_delete_offset_list(mc, name);
++                              tree_mapent_delete_offsets(mc, name);
+                               cache_unlock(mc);
+                               free(m_offset);
+                               free(options);
+@@ -1592,7 +1548,7 @@ dont_expand:
+                       if (status != CHE_OK) {
+                               warn(ap->logopt, MODPREFIX "error adding multi-mount");
+                               cache_writelock(mc);
+-                              cache_delete_offset_list(mc, name);
++                              tree_mapent_delete_offsets(mc, name);
+                               cache_unlock(mc);
+                               free(m_offset);
+                               free(options);
diff --git a/archive-patches/autofs5/autofs-5.1.7-use-default-stack-size-for-threads.patch b/archive-patches/autofs5/autofs-5.1.7-use-default-stack-size-for-threads.patch
new file mode 100644 (file)
index 0000000..09b776a
--- /dev/null
@@ -0,0 +1,128 @@
+autofs-5.1.7 - use default stack size for threads
+
+From: Ian Kent <raven@themaw.net>
+
+autofs uses PTHREAD_STACK_MIN to set the stack size for threads it
+creates.
+
+In two cases it is used to reduce the stack size for long running
+service threads while it's used to allocate a larger stack for worker
+threads that can have larger memory requirements.
+
+In recent glibc releases PTHREAD_STACK_MIN is no longer a constant
+which can lead to unexpectedly different stack sizes on different
+architectures and the autofs assumption it's a constant causes a
+compile failure.
+
+The need to alter the stack size was due to observed stack overflow
+which was thought to be due the thread stack being too small for autofs
+and glibc alloca(3) usage.
+
+Quite a bit of that alloca(3) usage has been eliminated from autofs now,
+particularly those that might be allocating largish amounts of storage,
+and there has been a lot of change in glibc too so using the thread
+default stack should be ok.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |   29 -----------------------------
+ daemon/state.c     |    6 +-----
+ lib/alarm.c        |    6 +-----
+ 4 files changed, 3 insertions(+), 39 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 2b7cfaa0..61f3547a 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -80,6 +80,7 @@
+ - fix nonstrict offset mount fail handling.
+ - fix concat_options() error handling.
+ - eliminate some more alloca usage.
++- use default stack size for threads.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/daemon/automount.c b/daemon/automount.c
+index 23235a7d..d7432350 100644
+--- a/daemon/automount.c
++++ b/daemon/automount.c
+@@ -84,7 +84,6 @@ static size_t kpkt_len;
+ /* Attributes for creating detached and joinable threads */
+ pthread_attr_t th_attr;
+ pthread_attr_t th_attr_detached;
+-size_t detached_thread_stack_size = PTHREAD_STACK_MIN * 144;
+ struct master_readmap_cond mrc = {
+       PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0};
+@@ -2620,34 +2619,6 @@ int main(int argc, char *argv[])
+               exit(1);
+       }
+-#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+-      if (pthread_attr_setstacksize(
+-                      &th_attr_detached, detached_thread_stack_size)) {
+-              logerr("%s: failed to set stack size thread attribute!",
+-                     program);
+-              if (start_pipefd[1] != -1) {
+-                      res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
+-                      close(start_pipefd[1]);
+-              }
+-              release_flag_file();
+-              macro_free_global_table();
+-              exit(1);
+-      }
+-#endif
+-
+-      if (pthread_attr_getstacksize(
+-                      &th_attr_detached, &detached_thread_stack_size)) {
+-              logerr("%s: failed to get detached thread stack size!",
+-                     program);
+-              if (start_pipefd[1] != -1) {
+-                      res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
+-                      close(start_pipefd[1]);
+-              }
+-              release_flag_file();
+-              macro_free_global_table();
+-              exit(1);
+-      }
+-
+       info(logging, "Starting automounter version %s, master map %s",
+               version, master_list->name);
+       info(logging, "using kernel protocol version %d.%02d",
+diff --git a/daemon/state.c b/daemon/state.c
+index 5156bb21..5df05619 100644
+--- a/daemon/state.c
++++ b/daemon/state.c
+@@ -1177,12 +1177,8 @@ int st_start_handler(void)
+       status = pthread_attr_init(pattrs);
+       if (status)
+               pattrs = NULL;
+-      else {
++      else
+               pthread_attr_setdetachstate(pattrs, PTHREAD_CREATE_DETACHED);
+-#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+-              pthread_attr_setstacksize(pattrs, PTHREAD_STACK_MIN*4);
+-#endif
+-      }
+       status = pthread_create(&thid, pattrs, st_queue_handler, NULL);
+diff --git a/lib/alarm.c b/lib/alarm.c
+index f27e13c4..1631a9bc 100755
+--- a/lib/alarm.c
++++ b/lib/alarm.c
+@@ -270,12 +270,8 @@ int alarm_start_handler(void)
+       status = pthread_attr_init(pattrs);
+       if (status)
+               pattrs = NULL;
+-      else {
++      else
+               pthread_attr_setdetachstate(pattrs, PTHREAD_CREATE_DETACHED);
+-#ifdef _POSIX_THREAD_ATTR_STACKSIZE
+-              pthread_attr_setstacksize(pattrs, PTHREAD_STACK_MIN*4);
+-#endif
+-      }
+       status = pthread_condattr_init(&condattrs);
+       if (status)
diff --git a/archive-patches/autofs5/autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch b/archive-patches/autofs5/autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch
new file mode 100644 (file)
index 0000000..0b83d8e
--- /dev/null
@@ -0,0 +1,119 @@
+autofs-5.1.7 - use mapent tree root for tree_mapent_add_node()
+
+From: Ian Kent <raven@themaw.net>
+
+Since we need to create the offset tree after adding the offset entries
+to the mapent cache lookup the root mapent once and use it when calling
+tree_mapent_add_node() instread of doing a cache lookup on every node
+addition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/mounts.h    |    2 +-
+ lib/mounts.c        |   24 +++++-------------------
+ modules/parse_sun.c |   11 ++++++++++-
+ 4 files changed, 17 insertions(+), 21 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 7b360f52..5a767360 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -72,6 +72,7 @@
+ - fix lookup_prune_one_cache() refactoring change.
+ - fix amd hosts mount expire.
+ - fix offset entries order.
++- use mapent tree root for tree_mapent_add_node().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/include/mounts.h b/include/mounts.h
+index 1b376b3d..f7768ce5 100644
+--- a/include/mounts.h
++++ b/include/mounts.h
+@@ -170,7 +170,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+-int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
++int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, const char *key);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ void tree_mapent_cleanup_offsets(struct mapent *oe);
+ int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict);
+diff --git a/lib/mounts.c b/lib/mounts.c
+index c24d1a88..9ec547ea 100644
+--- a/lib/mounts.c
++++ b/lib/mounts.c
+@@ -1519,27 +1519,13 @@ static void tree_mapent_free(struct tree_node *n)
+ }
+ int tree_mapent_add_node(struct mapent_cache *mc,
+-                       const char *root, const char *key)
++                       struct tree_node *root, const char *key)
+ {
+       unsigned int logopt = mc->ap->logopt;
+-      struct tree_node *tree, *n;
+-      struct mapent *base;
++      struct tree_node *n;
+       struct mapent *parent;
+       struct mapent *me;
+-      base = cache_lookup_distinct(mc, root);
+-      if (!base) {
+-              error(logopt,
+-                   "failed to find multi-mount root for key %s", key);
+-              return 0;
+-      }
+-
+-      if (MAPENT_ROOT(base) != MAPENT_NODE(base)) {
+-              error(logopt, "key %s is not multi-mount root", root);
+-              return 0;
+-      }
+-      tree = MAPENT_ROOT(base);
+-
+       me = cache_lookup_distinct(mc, key);
+       if (!me) {
+               error(logopt,
+@@ -1547,16 +1533,16 @@ int tree_mapent_add_node(struct mapent_cache *mc,
+               return 0;
+       }
+-      n = tree_add_node(tree, me);
++      n = tree_add_node(root, me);
+       if (!n)
+               return 0;
+-      MAPENT_SET_ROOT(me, tree)
++      MAPENT_SET_ROOT(me, root)
+       /* Set the subtree parent */
+       parent = cache_get_offset_parent(mc, key);
+       if (!parent)
+-              MAPENT_SET_PARENT(me, tree)
++              MAPENT_SET_PARENT(me, root)
+       else
+               MAPENT_SET_PARENT(me, MAPENT_NODE(parent))
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index b206a326..c75bcc8e 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1536,8 +1536,17 @@ dont_expand:
+               } while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+               cache_writelock(mc);
++              me = cache_lookup_distinct(mc, name);
++              if (!me) {
++                      cache_unlock(mc);
++                      free(options);
++                      free(pmapent);
++                      cleanup_offset_entries(ap, mc, &offsets);
++                      pthread_setcancelstate(cur_state, NULL);
++                      return 1;
++              }
+               list_for_each_entry_safe(oe, tmp, &offsets, work) {
+-                      if (!tree_mapent_add_node(mc, name, oe->key))
++                      if (!tree_mapent_add_node(mc, MAPENT_ROOT(me), oe->key))
+                               error(ap->logopt, "failed to add offset %s to tree", oe->key);
+                       list_del_init(&oe->work);
+               }
diff --git a/archive-patches/autofs5/autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch b/archive-patches/autofs5/autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch
new file mode 100644 (file)
index 0000000..d72ba0b
--- /dev/null
@@ -0,0 +1,74 @@
+autofs-5.1.7 - use mount_fullpath() in one spot in parse_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+mount_fullpath() is meant to be used for this type of path construction
+so use it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   34 ++++++++--------------------------
+ 2 files changed, 9 insertions(+), 26 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 444ade5b..8494f0dc 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -43,6 +43,7 @@
+ - switch to use tree implementation for offsets.
+ - remove obsolete functions.
+ - remove redundant local var from sun_mount().
++- use mount_fullpath() in one spot in parse_mount().
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/parse_sun.c b/modules/parse_sun.c
+index 437869b5..d3fc6c7f 100644
+--- a/modules/parse_sun.c
++++ b/modules/parse_sun.c
+@@ -1354,36 +1354,18 @@ dont_expand:
+       debug(ap->logopt, MODPREFIX "gathered options: %s", options);
+       if (check_is_multi(p)) {
+-              char *m_root = NULL;
++              char m_root[PATH_MAX + 1];
+               int m_root_len;
+               time_t age;
+               int l;
+-              /* If name starts with "/" it's a direct mount */
+-              if (*name == '/') {
+-                      m_root_len = name_len;
+-                      m_root = alloca(m_root_len + 1);
+-                      if (!m_root) {
+-                              char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-                              free(options);
+-                              free(pmapent);
+-                              logerr(MODPREFIX "alloca: %s", estr);
+-                              return 1;
+-                      }
+-                      strcpy(m_root, name);
+-              } else {
+-                      m_root_len = ap->len + name_len + 1;
+-                      m_root = alloca(m_root_len + 1);
+-                      if (!m_root) {
+-                              char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-                              free(options);
+-                              free(pmapent);
+-                              logerr(MODPREFIX "alloca: %s", estr);
+-                              return 1;
+-                      }
+-                      strcpy(m_root, ap->path);
+-                      strcat(m_root, "/");
+-                      strcat(m_root, name);
++              m_root_len = mount_fullpath(m_root, PATH_MAX, ap->path, name);
++              if (!m_root_len) {
++                      error(ap->logopt,
++                            MODPREFIX "multi-mount root path too long");
++                      free(options);
++                      free(pmapent);
++                      return 1;
+               }
+               pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
diff --git a/archive-patches/autofs5/autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch b/archive-patches/autofs5/autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch
new file mode 100644 (file)
index 0000000..64ab994
--- /dev/null
@@ -0,0 +1,76 @@
+autofs-5.1.7 - use snprintf() when constructing hosts mapent
+
+From: Ian Kent <raven@themaw.net>
+
+Using multiple strcpy() and strcat() functions when constructing the
+hosts map offset for each export is much slower than using a single
+sprintf() for each.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ modules/lookup_hosts.c |   26 +++++++++++++-------------
+ 2 files changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/CHANGELOG b/CHANGELOG
+index 1bd6ac7f..d613e5ca 100644
+--- a/CHANGELOG
++++ b/CHANGELOG
+@@ -2,6 +2,7 @@
+ - add xdr_exports().
+ - remove mount.x and rpcgen dependencies.
+ - dont use realloc in host exports list processing.
++- use sprintf() when constructing hosts mapent.
+ 25/01/2021 autofs-5.1.7
+ - make bind mounts propagation slave by default.
+diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
+index e3ee0ab8..c1ebb7f6 100644
+--- a/modules/lookup_hosts.c
++++ b/modules/lookup_hosts.c
+@@ -87,10 +87,12 @@ int lookup_read_master(struct master *master, time_t age, void *context)
+ static char *get_exports(struct autofs_point *ap, const char *host)
+ {
+       char buf[MAX_ERR_BUF];
++      char entry[PATH_MAX + 1];
+       char *mapent;
+       struct exportinfo *exp, *this;
+       size_t hostlen = strlen(host);
+       size_t mapent_len;
++      int len, pos;
+       debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+@@ -114,21 +116,19 @@ static char *get_exports(struct autofs_point *ap, const char *host)
+       }
+       *mapent = 0;
++      pos = 0;
+       this = exp;
+-      while (this) {
+-              if (!*mapent)
+-                      strcpy(mapent, "\"");
+-              else
+-                      strcat(mapent, " \"");
+-              strcat(mapent, this->dir);
+-              strcat(mapent, "\"");
+-
+-              strcat(mapent, " \"");
+-              strcat(mapent, host);
+-              strcat(mapent, ":");
+-              strcat(mapent, this->dir);
+-              strcat(mapent, "\"");
++      if (this) {
++              len = sprintf(mapent, "\"%s\" \"%s:%s\"",
++                              this->dir, host, this->dir);
++              pos += len;
++              this = this->next;
++      }
++      while (this) {
++              len = sprintf(mapent + pos, " \"%s\" \"%s:%s\"",
++                              this->dir, host, this->dir);
++              pos += len;
+               this = this->next;
+       }
+       rpc_exports_free(exp);
diff --git a/archive-patches/autofs5/patch_order_5.1.7 b/archive-patches/autofs5/patch_order_5.1.7
new file mode 100644 (file)
index 0000000..35e99b8
--- /dev/null
@@ -0,0 +1,82 @@
+autofs5/autofs-5.1.7-add-xdr_exports.patch
+autofs5/autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch
+autofs5/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch
+autofs5/autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch
+autofs5/autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch
+autofs5/autofs-5.1.7-Fix-option-for-master_read_wait.patch
+autofs5/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch
+autofs5/autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch
+autofs5/autofs-5.1.7-simplify-get_parent.patch
+autofs5/autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch
+autofs5/autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch
+autofs5/autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch
+autofs5/autofs-5.1.7-refactor-umount_multi_triggers.patch
+autofs5/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch
+autofs5/autofs-5.1.7-simplify-mount_subtree-mount-check.patch
+autofs5/autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch
+autofs5/autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch
+autofs5/autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch
+autofs5/autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch
+autofs5/autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch
+autofs5/autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch
+autofs5/autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch
+autofs5/autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch
+autofs5/autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch
+autofs5/autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch
+autofs5/autofs-5.1.7-cleanup-cache_delete-a-little.patch
+autofs5/autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch
+autofs5/autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch
+autofs5/autofs-5.1.7-rename-tree-implementation-functions.patch
+autofs5/autofs-5.1.7-add-some-multi-mount-macros.patch
+autofs5/autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch
+autofs5/autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch
+autofs5/autofs-5.1.7-make-tree-implementation-data-independent.patch
+autofs5/autofs-5.1.7-add-mapent-tree-implementation.patch
+autofs5/autofs-5.1.7-add-tree_mapent_add_node.patch
+autofs5/autofs-5.1.7-add-tree_mapent_delete_offsets.patch
+autofs5/autofs-5.1.7-add-tree_mapent_traverse_subtree.patch
+autofs5/autofs-5.1.7-fix-mount_fullpath.patch
+autofs5/autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch
+autofs5/autofs-5.1.7-add-set_offset_tree_catatonic.patch
+autofs5/autofs-5.1.7-add-mount-and-umount-offsets-functions.patch
+autofs5/autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch
+autofs5/autofs-5.1.7-remove-obsolete-functions.patch
+autofs5/autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch
+autofs5/autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch
+autofs5/autofs-5.1.7-pass-root-length-to-mount_fullpath.patch
+autofs5/autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch
+autofs5/autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch
+autofs5/autofs-5.1.7-check-for-offset-with-no-mount-location.patch
+autofs5/autofs-5.1.7-remove-mounts_mutex.patch
+autofs5/autofs-5.1.7-remove-unused-variable-from-get_exports.patch
+autofs5/autofs-5.1.7-add-missing-free-in-handle_mounts.patch
+autofs5/autofs-5.1.7-remove-redundant-if-check.patch
+autofs5/autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch
+autofs5/autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch
+autofs5/autofs-5.1.7-fix-double-unlock-in-parse_mount.patch
+autofs5/autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch
+autofs5/autofs-5.1.7-fix-flag-check-in-umount_multi.patch
+autofs5/autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch
+autofs5/autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch
+autofs5/autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch
+autofs5/autofs-5.1.7-fix-arg-not-used-in-print.patch
+autofs5/autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch
+autofs5/autofs-5.1.7-fix-double-free-in-parse_mapent.patch
+autofs5/autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch
+autofs5/autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch
+autofs5/autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch
+autofs5/autofs-5.1.7-fix-amd-section-mounts-map-reload.patch
+autofs5/autofs-5.1.7-fix-dandling-symlink-creation-if-nis-support-is-not-available.patch
+autofs5/autofs-5.1.7-dont-use-AUTOFS_DEV_IOCTL_CLOSEMOUNT.patch
+autofs5/autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch
+autofs5/autofs-5.1.7-fix-amd-hosts-mount-expire.patch
+autofs5/autofs-5.1.7-fix-offset-entries-order.patch
+autofs5/autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch
+autofs5/autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch
+autofs5/autofs-5.1.7-fix-hosts-map-offset-order.patch
+autofs5/autofs-5.1.7-fix-direct-mount-deadlock.patch
+autofs5/autofs-5.1.7-add-missing-description-of-null-map-option.patch
+autofs5/autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch
+autofs5/autofs-5.1.7-fix-concat_options-error-handling.patch
+autofs5/autofs-5.1.7-eliminate-some-more-alloca-usage.patch
+autofs5/autofs-5.1.7-use-default-stack-size-for-threads.patch
index f6bcbb3394571a9d2cdab4ab2c16facd676fad83..6f12f640c626778b36276c4ad08fc96df90b78ef 100755 (executable)
@@ -322,8 +322,12 @@ $(D)/autofs4: $(ARCHIVE)/autofs-$(AUTOFS4_VER).tar.gz | $(TARGETPREFIX)
        $(REMOVE)/autofs-$(AUTOFS4_VER)
        $(TOUCH)
 
-AUTOFS5_PATCH  = autofs-include-linux-nfs.h-directly-in-rpc_sub.patch
-AUTOFS5_PATCH += autofs-force-STRIP-to-empty.patch
+# cd package/autofs/patches
+# wget -N https://mirrors.edge.kernel.org/pub/linux/daemons/autofs/v5/patches-5.1.8/patch_order_5.1.7
+# for p in $(cat patch_order_5.1.7); do test -f $p || wget https://mirrors.edge.kernel.org/pub/linux/daemons/autofs/v5/patches-5.1.8/$p; done
+
+AUTOFS5_PATCH  = autofs-force-STRIP-to-empty.patch
+AUTOFS5_PATCH += $(shell cat $(PATCHES)/autofs5/patch_order_$(AUTOFS5_VER))
 
 $(D)/autofs5: $(D)/libtirpc $(ARCHIVE)/autofs-$(AUTOFS5_VER).tar.gz | $(TARGETPREFIX)
        $(START_BUILD)
@@ -331,27 +335,32 @@ $(D)/autofs5: $(D)/libtirpc $(ARCHIVE)/autofs-$(AUTOFS5_VER).tar.gz | $(TARGETPR
        $(UNTAR)/autofs-$(AUTOFS5_VER).tar.gz
        set -e; cd  $(BUILD_TMP)/autofs-$(AUTOFS5_VER); \
                $(call apply_patches, $(AUTOFS5_PATCH)); \
-               export ac_cv_linux_procfs=yes; \
+               export ac_cv_path_E2FSCK=/sbin/fsck; \
+               export ac_cv_path_E3FSCK=no; \
+               export ac_cv_path_E4FSCK=no; \
                export ac_cv_path_KRB5_CONFIG=no; \
                export ac_cv_path_MODPROBE=/sbin/modprobe; \
-               export ac_cv_path_RANLIB=$(TARGET)-ranlib; \
+               export ac_cv_path_MOUNT=/bin/mount; \
+               export ac_cv_path_MOUNT_NFS=/sbin/mount.nfs; \
+               export ac_cv_path_UMOUNT=/bin/umount; \
+               export ac_cv_linux_procfs=yes; \
                autoreconf -fi; \
                $(CONFIGURE) \
-                       --prefix= \
                        --datarootdir=/.remove \
                        --disable-mount-locking \
+                       --enable-ignore-busy \
                        --without-openldap \
                        --without-sasl \
-                       --with-path=$(PATH) \
-                       --with-libtirpc \
+                       --with-path="$(PATH)" \
                        --with-hesiod=no \
+                       --with-libtirpc \
                        --with-confdir=/var/etc \
                        --with-mapdir=/var/etc \
                        --with-fifodir=/var/run \
                        --with-flagdir=/var/run \
                        ; \
-               $(MAKE) SUBDIRS="lib daemon modules" DONTSTRIP=1; \
-               $(MAKE) SUBDIRS="lib daemon modules" install DESTDIR=$(TARGETPREFIX)
+               $(MAKE) DONTSTRIP=1; \
+               $(MAKE) install DESTDIR=$(TARGETPREFIX)
        $(REMOVE)/autofs-$(AUTOFS5_VER)
        $(TOUCH)
 
index 0a1c0a54c1275bc32d27c997e006923f428bfd57..899c452381005c2145e5138ffe8f41b537769bff 100644 (file)
@@ -7,7 +7,7 @@ AUTOFS4_VER = 4.1.4
 
 AUTOFS5_MAJOR = 5
 AUTOFS5_MINOR = 1
-AUTOFS5_MICRO = 6
+AUTOFS5_MICRO = 7
 AUTOFS5_VER = $(AUTOFS5_MAJOR).$(AUTOFS5_MINOR).$(AUTOFS5_MICRO)
 
 BUSYBOX_VER = 1.32.1