Add Add fixes for Jiras RHEL-69485 RHEL-71359 and RHEL-57466

This MR adds fixes for several Jiras.

- RHEL-57466 - autofs crashes on startup after IDM client configuration
We have had several different reports caused by this bug which leads to a
SEGV with very little information about the cuase.

- Resolves: RHEL-57466

- RHEL-69485 - Sporadic mount failures with amd program maps on RHEL8.
This bug causes AMD-style program map mounts to sporadically not work.

- Resolves: RHEL-69485

- RHEL-71359 - RFE: autofs: add handling for AMD 'nounmount' option
This Jira adds support for a map option that was deferred in the original
implementtion. One of our customers needs this so it has been implemented.

- Resolves: RHEL-71359

Signed-off-by: Ian Kent <ikent@redhat.com>
This commit is contained in:
Ian Kent 2024-12-17 11:04:01 +08:00
parent 60c7c495a0
commit b58878d9dd
18 changed files with 1917 additions and 1 deletions

View File

@ -0,0 +1,72 @@
autofs-5.1.7 - clear per-mount timeout if not set
From: Ian Kent <raven@themaw.net>
If the per-mount timeout isn't set in the amd map entry clear it so
that updates that remove the setting are seen.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
lib/mounts.c | 8 +++++++-
modules/parse_amd.c | 12 ++++++++----
3 files changed, 16 insertions(+), 5 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -177,6 +177,7 @@
- fix remount_active_mount() not remounting symlinks.
- log when setting amd per-mount timeout.
- update per-mount expire timeout on readmap.
+- clear per-mount timeout if not set.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -2696,8 +2696,14 @@ void update_mounted_mounts_timeout(struc
goto next;
/* No per-mount timeout set? */
- if (!(mnt->amd_flags & AMD_MOUNT_OPT_MASK))
+ if (!(mnt->amd_flags & AMD_MOUNT_OPT_MASK)) {
+ /* Per-mount timeout setting isn't present, reset to
+ * be sure updates are seen.
+ */
+ if (ops)
+ ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, -1);
goto next;
+ }
/* The default in autofs is to always expire mounts according to
* a timeout set in the autofs mount super block information
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1720,10 +1720,16 @@ static int amd_mount(struct autofs_point
}
if (!ret) {
- struct ioctl_ops *ops;
+ struct ioctl_ops *ops = get_ioctl_ops();
- if (!(per_mnt_flags & AMD_MOUNT_OPT_MASK))
+ if (!(per_mnt_flags & AMD_MOUNT_OPT_MASK)) {
+ /* Per-mount timeout setting isn't present, reset to
+ * be sure updates are seen.
+ */
+ if (ops)
+ ops->timeout(ap->logopt, ap->ioctlfd, name, -1);
goto done;
+ }
/* The mount succeeded, make sure there's no path component
* seperator in "name" as it must be the last component of
@@ -1734,8 +1740,6 @@ static int amd_mount(struct autofs_point
goto done;
}
- ops = get_ioctl_ops();
-
/* The default in autofs is to always expire mounts according to
* a timeout set in the autofs mount super block information
* structure. But amd allows for differing expire timeouts on a

View File

@ -0,0 +1,60 @@
autofs-5.1.9 - add flags argument to amd do_program_mount()
From: Ian Kent <raven@themaw.net>
Most of the amd mount functions take a flags argument that allows them
to alter their function based on configuration.
For example the amd option autofs_use_lofs will use bind mounts instead
of symlinks in some cases which might be preferred.
The program mount function was not being passed this parameter but the
design of all the amd mount functions is quite similar and adding the
flag works as expected..
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/parse_amd.c | 7 ++++---
2 files changed, 5 insertions(+), 3 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -166,6 +166,7 @@
- don't free ext mount if mounted.
- refactor amd function do_program_mount().
- refactor umount_amd_ext_mount().
+- add flags argument to amd do_program_mount().
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1405,7 +1405,8 @@ out:
}
static int do_program_mount(struct autofs_point *ap,
- struct amd_entry *entry, const char *name)
+ struct amd_entry *entry, const char *name,
+ unsigned int flags)
{
int rv = 1;
@@ -1479,7 +1480,7 @@ static int do_program_mount(struct autof
goto out;
}
done:
- rv = do_link_mount(ap, name, entry, 0);
+ rv = do_link_mount(ap, name, entry, flags);
if (rv) {
if (!umount_amd_ext_mount(ap, entry->fs, 1)) {
debug(ap->logopt, MODPREFIX
@@ -1708,7 +1709,7 @@ static int amd_mount(struct autofs_point
case AMD_MOUNT_TYPE_PROGRAM:
if (!validate_program_options(ap->logopt, entry))
return 1;
- ret = do_program_mount(ap, entry, name);
+ ret = do_program_mount(ap, entry, name, flags);
break;
default:

View File

@ -0,0 +1,221 @@
commit 6cbb6e9a3b8b223babf723e0f56cdd7b7eb90455
Author: Ian Kent <raven@themaw.net>
Date: Mon Jul 8 11:04:11 2024 +0800
autofs-5.1.9 - add some unimplemented amd map options
Add handling for amd per-mount options "utimeout", "unmount" and "nounmount"
if the kernel supports it.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
include/mounts.h | 2 ++
include/parse_amd.h | 6 ++++++
lib/mounts.c | 4 ++++
modules/amd_parse.y | 38 +++++++++++++++++++++++++++++++-------
modules/parse_amd.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 94 insertions(+), 7 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -171,6 +171,7 @@
- seperate amd mount and entry flags.
- make iocl ops ->timeout() handle per-dentry expire.
- refactor amd mount options handling.
+- add some unimplemented amd map options.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/include/mounts.h
@@ -113,6 +113,8 @@ struct mnt_list {
char *amd_pref;
char *amd_type;
char *amd_opts;
+ unsigned long amd_flags;
+ unsigned int amd_utimeout;
unsigned int amd_cache_opts;
struct list_head amdmount;
--- autofs-5.1.7.orig/include/parse_amd.h
+++ autofs-5.1.7/include/parse_amd.h
@@ -33,6 +33,11 @@
#define AMD_MOUNT_TYPE_PROGRAM 0x00004000
#define AMD_MOUNT_TYPE_MASK 0x0000ffff
+#define AMD_MOUNT_OPT_UNMOUNT 0x00010000
+#define AMD_MOUNT_OPT_NOUNMOUNT 0x00020000
+#define AMD_MOUNT_OPT_UTIMEOUT 0x00040000
+#define AMD_MOUNT_OPT_MASK 0x00ff0000
+
#define AMD_DEFAULTS_MERGE 0x0001
#define AMD_DEFAULTS_RESET 0x0002
#define AMD_DEFAULTS_MASK 0x00ff
@@ -49,6 +54,7 @@
struct amd_entry {
char *path;
unsigned long flags;
+ unsigned int utimeout;
unsigned int cache_opts;
unsigned int entry_flags;
char *type;
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -1210,6 +1210,8 @@ struct mnt_list *mnts_add_amdmount(struc
this->amd_pref = pref;
this->amd_type = type;
this->amd_opts = opts;
+ this->amd_flags = entry->flags;
+ this->amd_utimeout = entry->utimeout;
this->amd_cache_opts = entry->cache_opts;
this->flags |= MNTS_AMD_MOUNT;
if (list_empty(&this->amdmount))
@@ -1254,6 +1256,8 @@ static void __mnts_remove_amdmount(const
free(this->amd_opts);
this->amd_opts = NULL;
}
+ this->amd_flags = AMD_MOUNT_OPT_UNMOUNT;
+ this->amd_utimeout = -1;
this->amd_cache_opts = 0;
__mnts_put_mount(this);
}
--- autofs-5.1.7.orig/modules/amd_parse.y
+++ autofs-5.1.7/modules/amd_parse.y
@@ -647,8 +647,7 @@ static int match_mnt_option(char *option
{
int ret = 0;
- if (!strcmp(option, "fullybrowsable") ||
- !strcmp(option, "nounmount")) {
+ if (!strcmp(option, "fullybrowsable")) {
sprintf(msg_buf, "option %s is not currently "
"implemented, ignored", option);
amd_info(msg_buf);
@@ -660,15 +659,37 @@ static int match_mnt_option(char *option
sprintf(msg_buf, "option %s is not used by "
"autofs, ignored", option);
amd_info(msg_buf);
+ } else if (!strcmp(option, "umount")) {
+ entry.flags &= ~AMD_MOUNT_OPT_NOUNMOUNT;
+ entry.flags |= AMD_MOUNT_OPT_UNMOUNT;
+ } else if (!strcmp(option, "nounmount")) {
+ if (entry.flags & AMD_MOUNT_TYPE_AUTO)
+ prepend_opt(opts, "timeout=0");
+ else {
+ entry.flags &= ~AMD_MOUNT_OPT_UNMOUNT;
+ entry.flags |= AMD_MOUNT_OPT_NOUNMOUNT;
+ entry.utimeout = 0;
+ }
} else if (!strncmp(option, "utimeout=", 9)) {
+ /*
+ * amd type "auto" mounts map to autofs fstype=autofs
+ * mounts so a distinct autofs mount is present at the
+ * the root so there's no need for special handling,
+ * just pass the timeout=<seconds> autofs option.
+ */
if (entry.flags & AMD_MOUNT_TYPE_AUTO)
prepend_opt(options, ++option);
else {
- sprintf(msg_buf, "umount timeout can't be "
- "used for other than type "
- "\"auto\" with autofs, "
- "ignored");
- amd_info(msg_buf);
+ if (strchr(option, '=')) {
+ unsigned long tout;
+ int ret;
+
+ ret = sscanf(option, "utimeout=%lu", &tout);
+ if (ret) {
+ entry.flags |= AMD_MOUNT_OPT_UTIMEOUT;
+ entry.utimeout = tout;
+ }
+ }
}
} else
ret = 1;
@@ -791,6 +812,8 @@ static void local_init_vars(void)
{
memset(&entry, 0, sizeof(entry));
entry.cache_opts = AMD_CACHE_OPTION_NONE;
+ entry.flags = AMD_MOUNT_OPT_UNMOUNT;
+ entry.utimeout = -1;
memset(opts, 0, sizeof(opts));
}
@@ -900,6 +923,7 @@ static int add_location(void)
new->path = entry.path;
}
new->flags = entry.flags;
+ new->utimeout = entry.utimeout;
new->cache_opts = entry.cache_opts;
new->entry_flags = entry.entry_flags;
new->type = entry.type;
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1647,6 +1647,7 @@ static int amd_mount(struct autofs_point
struct parse_context *ctxt)
{
unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK;
+ unsigned long per_mnt_flags = entry->flags & AMD_MOUNT_OPT_MASK;
int ret = 1;
switch (fstype) {
@@ -1718,6 +1719,55 @@ static int amd_mount(struct autofs_point
break;
}
+ if (!ret) {
+ struct ioctl_ops *ops;
+
+ if (!(per_mnt_flags & AMD_MOUNT_OPT_MASK))
+ goto done;
+
+ /* The mount succeeded, make sure there's no path component
+ * seperator in "name" as it must be the last component of
+ * the mount point alone for the per-mount options.
+ */
+ if (strchr(name, '/')) {
+ warn(ap->logopt, "path component seperator not valid here");
+ goto done;
+ }
+
+ ops = get_ioctl_ops();
+
+ /* The default in autofs is to always expire mounts according to
+ * a timeout set in the autofs mount super block information
+ * structure. But amd allows for differing expire timeouts on a
+ * per-mount basis. It also has (context sensitive) options "unmount"
+ * to say expire this mount and "nounmount" to say don't expire this
+ * mount. In amd mounts these options are set by default according
+ * to whether a mount should expire or not, for example a cd mount
+ * is set "nounmount". Setting defaults like this is not used in the
+ * autofs amd implementation because there's only one, little used,
+ * removable file system available.
+ *
+ * But the "nounmount" and "utimeout" options can be useful.
+ */
+ if (per_mnt_flags & AMD_MOUNT_OPT_NOUNMOUNT) {
+ if (entry->utimeout)
+ warn(ap->logopt,
+ "non-zero timeout set, possible conflicting options");
+
+ /* "nounmount" option, don't expire this mount. */
+ if (ops)
+ ops->timeout(ap->logopt, ap->ioctlfd, name, 0);
+ } else if (per_mnt_flags & AMD_MOUNT_OPT_UTIMEOUT) {
+ if (!entry->utimeout)
+ warn(ap->logopt,
+ "zero timeout set, possible conflicting options");
+
+ /* "utimeout" option, expire this mount according to a timeout. */
+ if (ops)
+ ops->timeout(ap->logopt, ap->ioctlfd, name, entry->utimeout);
+ }
+ }
+done:
return ret;
}

View File

@ -0,0 +1,53 @@
autofs-5.1.9 - don't free ext mount if mounted
From: Ian Kent <raven@themaw.net>
If an external mount is in use when a umount is attempted don't free
it just let the reference count go to zero.
This will leave the mount in place and it won't get umounted. But if
another automount uses it it's reference count will become no zero
allowing for it to be umounted as normal if it isn't in use during
automount expire.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
lib/mounts.c | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -163,6 +163,7 @@
- fix deadlock in remount.
- fix amd external mount error handling.
- fix amd external mount mount handling.
+- don't free ext mount if mounted.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -906,10 +906,10 @@ int ext_mount_remove(const char *path)
if (!em)
goto done;
- em->ref--;
if (em->ref)
- goto done;
- else {
+ em->ref--;
+
+ if (!em->ref && !is_mounted(path, MNTS_REAL)) {
hlist_del_init(&em->mount);
free(em->mp);
if (em->umount)
@@ -931,7 +931,7 @@ int ext_mount_inuse(const char *path)
em = ext_mount_lookup(path);
if (!em)
goto done;
- ret = em->ref;
+ ret = 1;
done:
ext_mount_hash_mutex_unlock();
return ret;

View File

@ -0,0 +1,35 @@
commit abf2030556dfe694dc19ed2d73f84f7e5046b660
Author: Ian Kent <raven@themaw.net>
Date: Thu Jul 11 13:56:15 2024 +0800
autofs-5.1.9 - fix amd cache options not copied
The cache options set when parsing the amd map entry are not copied to
the list entry that gets processed by the caller.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/amd_parse.y | 1 +
2 files changed, 2 insertions(+)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -167,6 +167,7 @@
- refactor amd function do_program_mount().
- refactor umount_amd_ext_mount().
- add flags argument to amd do_program_mount().
+- fix amd cache options not copied.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/amd_parse.y
+++ autofs-5.1.7/modules/amd_parse.y
@@ -888,6 +888,7 @@ static int add_location(void)
new->path = entry.path;
}
new->flags = entry.flags;
+ new->cache_opts = entry.cache_opts;
new->type = entry.type;
new->map_type = entry.map_type;
new->pref = entry.pref;

View File

@ -0,0 +1,55 @@
autofs-5.1.9 - fix amd external mount error handling
From: Ian Kent <raven@themaw.net>
An amd program mount might have defined its own umount program to be used
for external mounts.
In mount failure cases where the mount needs to be umounted be sure to
use the custom umount if there is one.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/parse_amd.c | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -161,6 +161,7 @@
- fix multi-mount check.
- fix get parent multi-mount check in try_remount().
- fix deadlock in remount.
+- fix amd external mount error handling.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1183,7 +1183,7 @@ static int do_generic_mount(struct autof
}
/* If we have an external mount add it to the list */
if (umount && !ext_mount_add(entry->fs, entry->umount)) {
- umount_ent(ap, entry->fs);
+ umount_amd_ext_mount(ap, entry->fs);
error(ap->logopt, MODPREFIX
"error: could not add external mount %s",
entry->fs);
@@ -1233,7 +1233,7 @@ static int do_nfs_mount(struct autofs_po
}
/* We might be using an external mount */
if (umount && !ext_mount_add(entry->fs, entry->umount)) {
- umount_ent(ap, entry->fs);
+ umount_amd_ext_mount(ap, entry->fs);
error(ap->logopt, MODPREFIX
"error: could not add external mount %s", entry->fs);
ret = 1;
@@ -1462,7 +1462,7 @@ static int do_program_mount(struct autof
"%s: mounted %s", entry->type, entry->fs);
goto do_free;
}
- umount_ent(ap, entry->fs);
+ umount_amd_ext_mount(ap, entry->fs);
}
if (!ext_mount_inuse(entry->fs))

View File

@ -0,0 +1,71 @@
autofs-5.1.9 - fix amd external mount mount handling
From: Ian Kent <raven@themaw.net>
Amd external mounts exist outside of the autofs file system and need
extra effort to try and keep track of them so they are mounted and
umounted when they should be.
Cleanup cases where an external mount is already mounted.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/parse_amd.c | 21 ++++++++++++---------
2 files changed, 13 insertions(+), 9 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -162,6 +162,7 @@
- fix get parent multi-mount check in try_remount().
- fix deadlock in remount.
- fix amd external mount error handling.
+- fix amd external mount mount handling.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1182,8 +1182,9 @@ static int do_generic_mount(struct autof
umount = 1;
}
/* If we have an external mount add it to the list */
- if (umount && !ext_mount_add(entry->fs, entry->umount)) {
- umount_amd_ext_mount(ap, entry->fs);
+ if (!ext_mount_add(entry->fs, entry->umount)) {
+ if (umount)
+ umount_amd_ext_mount(ap, entry->fs);
error(ap->logopt, MODPREFIX
"error: could not add external mount %s",
entry->fs);
@@ -1232,8 +1233,9 @@ static int do_nfs_mount(struct autofs_po
umount = 1;
}
/* We might be using an external mount */
- if (umount && !ext_mount_add(entry->fs, entry->umount)) {
- umount_amd_ext_mount(ap, entry->fs);
+ if (!ext_mount_add(entry->fs, entry->umount)) {
+ if (umount)
+ umount_amd_ext_mount(ap, entry->fs);
error(ap->logopt, MODPREFIX
"error: could not add external mount %s", entry->fs);
ret = 1;
@@ -1435,12 +1437,13 @@ static int do_program_mount(struct autof
* before executing the mount command and removing it at
* umount.
*/
- if (ext_mount_inuse(entry->fs)) {
+ if (is_mounted(entry->fs, MNTS_REAL)) {
+ if (!ext_mount_add(entry->fs, entry->umount)) {
+ error(ap->logopt, MODPREFIX
+ "error: could not add external mount %s", entry->fs);
+ goto out;
+ }
rv = 0;
- /* An external mount with path entry->fs exists
- * so ext_mount_add() won't fail.
- */
- ext_mount_add(entry->fs, entry->umount);
} else {
rv = mkdir_path(entry->fs, mp_mode);
if (rv && errno != EEXIST) {

View File

@ -0,0 +1,34 @@
autofs-5.1.9 - fix lookup search type in umount_subtree_mounts()
From: Ian Kent <raven@themaw.net>
The lookup type used in umount_subtree_mounts() should be LKP_DISTINCT
because we're looking for existing cache entries.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/automount.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -173,6 +173,7 @@
- refactor amd mount options handling.
- add some unimplemented amd map options.
- fix submount shutdown race.
+- fix lookup search type in umount_subtree_mounts().
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/daemon/automount.c
+++ autofs-5.1.7/daemon/automount.c
@@ -543,7 +543,7 @@ static int umount_subtree_mounts(struct
if (ind_key)
ind_key++;
- me = lookup_source_mapent(ap, ind_key, LKP_NORMAL);
+ me = lookup_source_mapent(ap, ind_key, LKP_DISTINCT);
}
if (me) {

View File

@ -0,0 +1,53 @@
autofs-5.1.9 - fix remount_active_mount() not remounting symlinks
From: Ian Kent <raven@themaw.net>
In remount_active_mount() there's a check if the path has an active
mount (ie. covered). This is meant to check if the mount is a direct
mount with an active mount to decide if the file descriptor needs to
be retained or not.
But this check gets it worng if the path is an indirect mount that
contains symlinks and causes them to not be properly expired after
the re-mount.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
lib/mounts.c | 12 +++++-------
2 files changed, 6 insertions(+), 7 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -174,6 +174,7 @@
- add some unimplemented amd map options.
- fix submount shutdown race.
- fix lookup search type in umount_subtree_mounts().
+- fix remount_active_mount() not remounting symlinks.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -2819,16 +2819,14 @@ static int remount_active_mount(struct a
ops->close(ap->logopt, fd);
return REMOUNT_FAIL;
}
- if (!mounted) {
+ if (!mounted && type != t_indirect) {
/*
* If we're an indirect mount we pass back the fd.
- * But if were a direct or offset mount with no active
- * mount we don't retain an open file descriptor.
+ * But if we're a direct or offset mount with no active
+ * mount we don't retain the open file descriptor.
*/
- if (type != t_indirect) {
- ops->close(ap->logopt, fd);
- *ioctlfd = -1;
- }
+ ops->close(ap->logopt, fd);
+ *ioctlfd = -1;
} else {
/*
* What can I do if we can't remount the existing

View File

@ -0,0 +1,89 @@
autofs-5.1.9 - fix submount shutdown race
From: Ian Kent <raven@themaw.net>
In function master_notify_submount() an expire notification is sent to
existing submounts. automount wait for the task to complete then, if
the submount is exiting, waits for the submount to reach a completion
state.
But the submount can go away during these checks resulting in the
autofs mount point structure field of the mount list structure to be
set to NULL.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/master.c | 23 +++++++++++++----------
lib/mounts.c | 2 ++
3 files changed, 16 insertions(+), 10 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -172,6 +172,7 @@
- make iocl ops ->timeout() handle per-dentry expire.
- refactor amd mount options handling.
- add some unimplemented amd map options.
+- fix submount shutdown race.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/daemon/master.c
+++ autofs-5.1.7/daemon/master.c
@@ -1213,22 +1213,24 @@ int master_notify_submount(struct autofs
this = mnts_find_submount(path);
if (this) {
+ struct autofs_point *found;
+
/* We have found a submount to expire */
st_mutex_lock();
-
- if (this->ap->state == ST_SHUTDOWN) {
+ found = this->ap;
+ if (!found || found->state == ST_SHUTDOWN) {
this = NULL;
st_mutex_unlock();
goto done;
}
-
- this->ap->shutdown = ap->shutdown;
-
- __st_add_task(this->ap, state);
-
+ found->shutdown = ap->shutdown;
+ __st_add_task(found, state);
st_mutex_unlock();
- st_wait_task(this->ap, state, 0);
+ /* This is ok because found isn't dereferenced during
+ * the wait checks.
+ */
+ st_wait_task(found, state, 0);
/*
* If our submount gets to state ST_SHUTDOWN_PENDING or
@@ -1240,8 +1242,9 @@ int master_notify_submount(struct autofs
struct timespec t = { 0, 300000000 };
struct timespec r;
- if (sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
- sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
+ if (!sbmnt->ap ||
+ (sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
+ sbmnt->ap->state != ST_SHUTDOWN_FORCE)) {
ret = 0;
mnts_put_mount(sbmnt);
break;
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -1153,7 +1153,9 @@ void mnts_remove_submount(const char *mp
this = mnts_lookup(mp);
if (this && this->flags & MNTS_AUTOFS) {
this->flags &= ~MNTS_AUTOFS;
+ st_mutex_lock();
this->ap = NULL;
+ st_mutex_unlock();
list_del_init(&this->submount);
__mnts_put_mount(this);
}

View File

@ -0,0 +1,51 @@
autofs-5.1.9 - log when setting amd per-mount timeout
From: Ian Kent <raven@themaw.net>
Log action when setting amd per-mount expire timeout.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/parse_amd.c | 12 ++++++++++--
2 files changed, 11 insertions(+), 2 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -175,6 +175,7 @@
- fix submount shutdown race.
- fix lookup search type in umount_subtree_mounts().
- fix remount_active_mount() not remounting symlinks.
+- log when setting amd per-mount timeout.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1755,16 +1755,24 @@ static int amd_mount(struct autofs_point
"non-zero timeout set, possible conflicting options");
/* "nounmount" option, don't expire this mount. */
- if (ops)
+ if (ops) {
+ info(ap->logopt,
+ "set amd per-mount expire timeout to 0 for %s",
+ name);
ops->timeout(ap->logopt, ap->ioctlfd, name, 0);
+ }
} else if (per_mnt_flags & AMD_MOUNT_OPT_UTIMEOUT) {
if (!entry->utimeout)
warn(ap->logopt,
"zero timeout set, possible conflicting options");
/* "utimeout" option, expire this mount according to a timeout. */
- if (ops)
+ if (ops) {
+ info(ap->logopt,
+ "set amd per-dentry expire timeout to %d for %s",
+ entry->utimeout, name);
ops->timeout(ap->logopt, ap->ioctlfd, name, entry->utimeout);
+ }
}
}
done:

View File

@ -0,0 +1,192 @@
commit 6fdfbcd65fd845e968a68cbdf475a6dd0ee0ee66
Author: Ian Kent <raven@themaw.net>
Date: Tue Jul 9 16:18:19 2024 +0800
autofs-5.1.9 - make ioctl ops ->timeout() handle per-dentry expire
Update the ioctl ops ->timeout() function to handle setting of per-dentry
expire timeout if the kernel supports it.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/direct.c | 6 +++---
daemon/indirect.c | 2 +-
daemon/state.c | 4 ++--
include/dev-ioctl-lib.h | 2 +-
lib/dev-ioctl-lib.c | 42 +++++++++++++++++++++++++++++++-----------
lib/mounts.c | 4 ++--
7 files changed, 41 insertions(+), 20 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -169,6 +169,7 @@
- add flags argument to amd do_program_mount().
- fix amd cache options not copied.
- seperate amd mount and entry flags.
+- make iocl ops ->timeout() handle per-dentry expire.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/daemon/direct.c
+++ autofs-5.1.7/daemon/direct.c
@@ -328,7 +328,7 @@ int do_mount_autofs_direct(struct autofs
return 0;
}
- ops->timeout(ap->logopt, ioctlfd, tout);
+ ops->timeout(ap->logopt, ioctlfd, NULL, tout);
if (save_ioctlfd == -1)
ops->close(ap->logopt, ioctlfd);
@@ -423,7 +423,7 @@ int do_mount_autofs_direct(struct autofs
goto out_umount;
}
- ops->timeout(ap->logopt, ioctlfd, timeout);
+ ops->timeout(ap->logopt, ioctlfd, NULL, timeout);
notify_mount_result(ap, me->key, timeout, str_direct);
cache_set_ino_index(me->mc, me);
ops->close(ap->logopt, ioctlfd);
@@ -777,7 +777,7 @@ int mount_autofs_offset(struct autofs_po
if (ioctlfd < 0)
goto out_umount;
- ops->timeout(ap->logopt, ioctlfd, timeout);
+ ops->timeout(ap->logopt, ioctlfd, NULL, timeout);
cache_set_ino_index(me->mc, me);
notify_mount_result(ap, me->key, timeout, str_offset);
ops->close(ap->logopt, ioctlfd);
--- autofs-5.1.7.orig/daemon/indirect.c
+++ autofs-5.1.7/daemon/indirect.c
@@ -136,7 +136,7 @@ static int do_mount_autofs_indirect(stru
goto out_umount;
}
- ops->timeout(ap->logopt, ap->ioctlfd, timeout);
+ ops->timeout(ap->logopt, ap->ioctlfd, NULL, timeout);
notify_mount_result(ap, ap->path, timeout, str_indirect);
return 0;
--- autofs-5.1.7.orig/daemon/state.c
+++ autofs-5.1.7/daemon/state.c
@@ -366,7 +366,7 @@ static int do_readmap_mount(struct autof
cache_unlock(vmc);
/* Set timeout and calculate the expire run frequency */
timeout = get_exp_timeout(ap, map);
- ops->timeout(ap->logopt, valid->ioctlfd, timeout);
+ ops->timeout(ap->logopt, valid->ioctlfd, NULL, timeout);
if (timeout) {
runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
if (ap->exp_runfreq)
@@ -427,7 +427,7 @@ static void *do_readmap(void *arg)
struct ioctl_ops *ops = get_ioctl_ops();
time_t timeout = get_exp_timeout(ap, ap->entry->maps);
ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
- ops->timeout(ap->logopt, ap->ioctlfd, timeout);
+ ops->timeout(ap->logopt, ap->ioctlfd, NULL, timeout);
lookup_prune_cache(ap, now);
status = lookup_ghost(ap);
} else {
--- autofs-5.1.7.orig/include/dev-ioctl-lib.h
+++ autofs-5.1.7/include/dev-ioctl-lib.h
@@ -45,7 +45,7 @@ struct ioctl_ops {
int (*send_fail)(unsigned int, int, unsigned int, int);
int (*setpipefd)(unsigned int, int, int);
int (*catatonic)(unsigned int, int);
- int (*timeout)(unsigned int, int, time_t);
+ int (*timeout)(unsigned int, int, const char *, time_t);
int (*requester)(unsigned int, int, const char *, uid_t *, gid_t *);
int (*expire)(unsigned int, int, const char *, unsigned int);
int (*askumount)(unsigned int, int, unsigned int *);
--- autofs-5.1.7.orig/lib/dev-ioctl-lib.c
+++ autofs-5.1.7/lib/dev-ioctl-lib.c
@@ -55,7 +55,7 @@ static int dev_ioctl_send_ready(unsigned
static int dev_ioctl_send_fail(unsigned int, int, unsigned int, int);
static int dev_ioctl_setpipefd(unsigned int, int, int);
static int dev_ioctl_catatonic(unsigned int, int);
-static int dev_ioctl_timeout(unsigned int, int, time_t);
+static int dev_ioctl_timeout(unsigned int, int, const char *, time_t);
static int dev_ioctl_requester(unsigned int, int, const char *, uid_t *, gid_t *);
static int dev_ioctl_expire(unsigned int, int, const char *, unsigned int);
static int dev_ioctl_askumount(unsigned int, int, unsigned int *);
@@ -69,7 +69,7 @@ static int ioctl_close(unsigned int, int
static int ioctl_send_ready(unsigned int, int, unsigned int);
static int ioctl_send_fail(unsigned int, int, unsigned int, int);
static int ioctl_catatonic(unsigned int, int);
-static int ioctl_timeout(unsigned int, int, time_t);
+static int ioctl_timeout(unsigned int, int, const char *, time_t);
static int ioctl_expire(unsigned int, int, const char *, unsigned int);
static int ioctl_askumount(unsigned int, int, unsigned int *);
@@ -579,21 +579,41 @@ static int ioctl_catatonic(unsigned int
}
/* Set the autofs mount timeout */
-static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout)
+static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, const char *mp, time_t timeout)
{
- struct autofs_dev_ioctl param;
-
- init_autofs_dev_ioctl(&param);
- param.ioctlfd = ioctlfd;
- param.timeout.timeout = timeout;
+ if (!mp) {
+ struct autofs_dev_ioctl param;
- if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) == -1)
- return -1;
+ init_autofs_dev_ioctl(&param);
+ param.ioctlfd = ioctlfd;
+ param.timeout.timeout = timeout;
+ if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) == -1)
+ return -1;
+ } else {
+ unsigned int kver_major = get_kver_major();
+ unsigned int kver_minor = get_kver_minor();
+ struct autofs_dev_ioctl *param;
+
+ if (kver_major < 5 ||
+ (kver_major == 5 && kver_minor < 6)) {
+ error(logopt, "per-mount expire timeout not supported by kernel.");
+ return -1;
+ }
+ param = alloc_dev_ioctl_path(ioctlfd, mp);
+ if (!param)
+ return -1;
+ param->timeout.timeout = timeout;
+ if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, param) == -1) {
+ free_dev_ioctl_path(param);
+ return -1;
+ }
+ free_dev_ioctl_path(param);
+ }
return 0;
}
-static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout)
+static int ioctl_timeout(unsigned int logopt, int ioctlfd, const char *mp, time_t timeout)
{
time_t tout = timeout;
return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout);
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -2757,7 +2757,7 @@ static int remount_active_mount(struct a
/* Re-reading the map, set timeout and return */
if (ap->state == ST_READMAP) {
debug(ap->logopt, "already mounted, update timeout");
- ops->timeout(ap->logopt, fd, timeout);
+ ops->timeout(ap->logopt, fd, NULL, timeout);
ops->close(ap->logopt, fd);
return REMOUNT_READ_MAP;
}
@@ -2779,7 +2779,7 @@ static int remount_active_mount(struct a
ops->close(ap->logopt, fd);
return REMOUNT_OPEN_FAIL;
}
- ops->timeout(ap->logopt, fd, timeout);
+ ops->timeout(ap->logopt, fd, NULL, timeout);
if (fstat(fd, &st) == -1) {
error(ap->logopt,
"failed to stat %s mount %s", str_type, path);

View File

@ -0,0 +1,138 @@
autofs-5.1.9 - refactor amd function do_program_mount()
From: Ian Kent <raven@themaw.net>
The amd mounts function do_program_mount() is particularly untidy.
Refactor it to make it a little simpler and to take advantage of the
coming refactoring of the funtion umount_amd_ext_mount().
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
modules/parse_amd.c | 74 ++++++++++++++++++++++++----------------------------
2 files changed, 36 insertions(+), 39 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -164,6 +164,7 @@
- fix amd external mount error handling.
- fix amd external mount mount handling.
- don't free ext mount if mounted.
+- refactor amd function do_program_mount().
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1407,26 +1407,8 @@ out:
static int do_program_mount(struct autofs_point *ap,
struct amd_entry *entry, const char *name)
{
- char *prog, *str;
- char **argv;
- int argc = -1;
int rv = 1;
- str = strdup(entry->mount);
- if (!str)
- goto out;
-
- prog = NULL;
- argv = NULL;
-
- argc = construct_argv(str, &prog, &argv);
- if (argc == -1) {
- error(ap->logopt, MODPREFIX
- "%s: error creating mount arguments", entry->type);
- free(str);
- goto out;
- }
-
/* The am-utils documentation doesn't actually say that the
* mount (and umount, if given) command need to use ${fs} as
* the mount point in the command.
@@ -1445,6 +1427,25 @@ static int do_program_mount(struct autof
}
rv = 0;
} else {
+ char *prog, *str;
+ char **argv;
+ int argc = -1;
+
+ str = strdup(entry->mount);
+ if (!str)
+ goto out;
+
+ prog = NULL;
+ argv = NULL;
+
+ argc = construct_argv(str, &prog, &argv);
+ if (argc == -1) {
+ error(ap->logopt, MODPREFIX
+ "%s: error creating mount arguments", entry->type);
+ free(str);
+ goto out;
+ }
+
rv = mkdir_path(entry->fs, mp_mode);
if (rv && errno != EEXIST) {
char buf[MAX_ERR_BUF];
@@ -1454,7 +1455,9 @@ static int do_program_mount(struct autof
error(ap->logopt,
MODPREFIX "%s: mkdir_path %s failed: %s",
entry->type, entry->fs, estr);
- goto do_free;
+ free_argv(argc, (const char **) argv);
+ free(str);
+ goto out;
}
rv = spawnv(ap->logopt, prog, (const char * const *) argv);
@@ -1463,33 +1466,26 @@ static int do_program_mount(struct autof
rv = 0;
debug(ap->logopt, MODPREFIX
"%s: mounted %s", entry->type, entry->fs);
- goto do_free;
+ free_argv(argc, (const char **) argv);
+ free(str);
+ goto done;
}
umount_amd_ext_mount(ap, entry->fs);
}
-
- if (!ext_mount_inuse(entry->fs))
- rmdir_path(ap, entry->fs, ap->dev);
error(ap->logopt, MODPREFIX
"%s: failed to mount using %s", entry->type, entry->mount);
- }
-do_free:
- free_argv(argc, (const char **) argv);
- free(str);
-
- if (rv)
+ free_argv(argc, (const char **) argv);
+ free(str);
goto out;
-
+ }
+done:
rv = do_link_mount(ap, name, entry, 0);
- if (!rv)
- goto out;
-
- if (umount_amd_ext_mount(ap, entry->fs)) {
- if (!ext_mount_inuse(entry->fs))
- rmdir_path(ap, entry->fs, ap->dev);
- debug(ap->logopt, MODPREFIX
- "%s: failed to umount external mount at %s",
- entry->type, entry->fs);
+ if (rv) {
+ if (umount_amd_ext_mount(ap, entry->fs)) {
+ debug(ap->logopt, MODPREFIX
+ "%s: failed to cleanup external mount at %s",
+ entry->type, entry->fs);
+ }
}
out:
return rv;

View File

@ -0,0 +1,242 @@
autofs-5.1.9 - refactor amd function umount_amd_ext_mount()
From: Ian Kent <raven@themaw.net>
The amd mounts function umount_amd_ext_mount() needs some improvement.
Make sure the function returns true for success and false for failure
and add a parameter to control if the expternal mount reference should
be decremented on successful umount.
If the reference count of the external mount is greater than 1 there's
some other mount using (symlink pointing to) it so don't try to umount
it just return success.
Also check for the case where the mount is already mounted.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
daemon/automount.c | 4 +-
include/mounts.h | 2 -
lib/mounts.c | 80 ++++++++++++++++++++++++++++++----------------------
modules/parse_amd.c | 10 +++---
5 files changed, 56 insertions(+), 41 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -165,6 +165,7 @@
- fix amd external mount mount handling.
- don't free ext mount if mounted.
- refactor amd function do_program_mount().
+- refactor umount_amd_ext_mount().
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/daemon/automount.c
+++ autofs-5.1.7/daemon/automount.c
@@ -618,7 +618,7 @@ static int umount_subtree_mounts(struct
/* Check for an external mount and umount if possible */
mnt = mnts_find_amdmount(path);
if (mnt) {
- umount_amd_ext_mount(ap, mnt->ext_mp);
+ umount_amd_ext_mount(ap, mnt->ext_mp, 1);
mnts_remove_amdmount(path);
mnts_put_mount(mnt);
}
@@ -684,7 +684,7 @@ int umount_multi(struct autofs_point *ap
/* Check for an external mount and attempt umount if needed */
mnt = mnts_find_amdmount(path);
if (mnt) {
- umount_amd_ext_mount(ap, mnt->ext_mp);
+ umount_amd_ext_mount(ap, mnt->ext_mp, 1);
mnts_remove_amdmount(path);
mnts_put_mount(mnt);
}
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/include/mounts.h
@@ -199,7 +199,7 @@ int try_remount(struct autofs_point *, s
void set_indirect_mount_tree_catatonic(struct autofs_point *);
void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *);
int umount_ent(struct autofs_point *, const char *);
-int umount_amd_ext_mount(struct autofs_point *, const char *);
+int umount_amd_ext_mount(struct autofs_point *, const char *, int remove);
int clean_stale_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
#endif
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -3095,37 +3095,62 @@ int umount_ent(struct autofs_point *ap,
return mounted;
}
-int umount_amd_ext_mount(struct autofs_point *ap, const char *path)
+int umount_amd_ext_mount(struct autofs_point *ap, const char *path, int remove)
{
struct ext_mount *em;
char *umount = NULL;
- char *mp;
+ char *mp = NULL;
int rv = 1;
+ int ret;
pthread_mutex_lock(&ext_mount_hash_mutex);
-
em = ext_mount_lookup(path);
if (!em) {
pthread_mutex_unlock(&ext_mount_hash_mutex);
+ rv = 0;
goto out;
}
mp = strdup(em->mp);
if (!mp) {
pthread_mutex_unlock(&ext_mount_hash_mutex);
+ rv = 0;
goto out;
}
if (em->umount) {
umount = strdup(em->umount);
if (!umount) {
pthread_mutex_unlock(&ext_mount_hash_mutex);
- free(mp);
+ rv = 0;
goto out;
}
}
-
+ /* Don't try and umount if there's more than one
+ * user of the external mount.
+ */
+ if (em->ref > 1) {
+ pthread_mutex_unlock(&ext_mount_hash_mutex);
+ if (!remove)
+ error(ap->logopt,
+ "reference count mismatch, called with remove false");
+ else
+ ext_mount_remove(mp);
+ goto out;
+ }
+ /* This shouldn't happen ... */
+ if (!is_mounted(mp, MNTS_REAL)) {
+ pthread_mutex_unlock(&ext_mount_hash_mutex);
+ error(ap->logopt, "failed to umount program mount at %s", mp);
+ if (remove)
+ ext_mount_remove(mp);
+ goto out;
+ }
pthread_mutex_unlock(&ext_mount_hash_mutex);
- if (umount) {
+ if (!umount) {
+ ret = umount_ent(ap, mp);
+ if (ret)
+ rv = 0;
+ } else {
char *prog;
char **argv;
int argc = -1;
@@ -3134,41 +3159,30 @@ int umount_amd_ext_mount(struct autofs_p
argv = NULL;
argc = construct_argv(umount, &prog, &argv);
- if (argc == -1)
- goto done;
-
- if (!ext_mount_remove(mp)) {
- rv =0;
- goto out_free;
- }
-
- rv = spawnv(ap->logopt, prog, (const char * const *) argv);
- if (rv == -1 || (WIFEXITED(rv) && WEXITSTATUS(rv)))
+ if (argc == -1) {
error(ap->logopt,
- "failed to umount program mount at %s", mp);
- else {
+ "failed to allocate args for umount of %s", mp);
rv = 0;
- debug(ap->logopt, "umounted program mount at %s", mp);
- rmdir_path(ap, mp, ap->dev);
+ goto out;
}
-out_free:
+ ret = spawnv(ap->logopt, prog, (const char * const *) argv);
+ rv = WIFEXITED(ret) && !WEXITSTATUS(ret);
free_argv(argc, (const char **) argv);
-
- goto done;
}
- if (ext_mount_remove(mp)) {
- rv = umount_ent(ap, mp);
- if (rv)
- error(ap->logopt,
- "failed to umount external mount %s", mp);
- else
- debug(ap->logopt, "umounted external mount %s", mp);
+ if (is_mounted(mp, MNTS_REAL))
+ error(ap->logopt,
+ "failed to umount external mount %s", mp);
+ else {
+ info(ap->logopt, "umounted external mount %s", mp);
+ rmdir_path(ap, mp, ap->dev);
}
-done:
+ if (remove)
+ ext_mount_remove(mp);
+out:
if (umount)
free(umount);
- free(mp);
-out:
+ if (mp)
+ free(mp);
return rv;
}
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1133,7 +1133,7 @@ symlink:
if (entry->sublink) {
/* failed to complete sublink mount */
- umount_amd_ext_mount(ap, entry->fs);
+ umount_amd_ext_mount(ap, entry->fs, 1);
}
out:
return ret;
@@ -1184,7 +1184,7 @@ static int do_generic_mount(struct autof
/* If we have an external mount add it to the list */
if (!ext_mount_add(entry->fs, entry->umount)) {
if (umount)
- umount_amd_ext_mount(ap, entry->fs);
+ umount_amd_ext_mount(ap, entry->fs, 0);
error(ap->logopt, MODPREFIX
"error: could not add external mount %s",
entry->fs);
@@ -1235,7 +1235,7 @@ static int do_nfs_mount(struct autofs_po
/* We might be using an external mount */
if (!ext_mount_add(entry->fs, entry->umount)) {
if (umount)
- umount_amd_ext_mount(ap, entry->fs);
+ umount_amd_ext_mount(ap, entry->fs, 0);
error(ap->logopt, MODPREFIX
"error: could not add external mount %s", entry->fs);
ret = 1;
@@ -1470,7 +1470,7 @@ static int do_program_mount(struct autof
free(str);
goto done;
}
- umount_amd_ext_mount(ap, entry->fs);
+ umount_amd_ext_mount(ap, entry->fs, 0);
}
error(ap->logopt, MODPREFIX
"%s: failed to mount using %s", entry->type, entry->mount);
@@ -1481,7 +1481,7 @@ static int do_program_mount(struct autof
done:
rv = do_link_mount(ap, name, entry, 0);
if (rv) {
- if (umount_amd_ext_mount(ap, entry->fs)) {
+ if (!umount_amd_ext_mount(ap, entry->fs, 1)) {
debug(ap->logopt, MODPREFIX
"%s: failed to cleanup external mount at %s",
entry->type, entry->fs);

View File

@ -0,0 +1,121 @@
commit b48aab92dd3f47411a8ccd67ff4370cbfee64581
Author: Ian Kent <raven@themaw.net>
Date: Thu Jul 11 13:35:04 2024 +0800
autofs-5.1.9 - refactor amd mount options handling
Refactor handling of entry options opts, addopts, remopts.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
modules/amd_parse.y | 66 ++++++++++++++++++++++++++++++----------------------
2 files changed, 40 insertions(+), 27 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -170,6 +170,7 @@
- fix amd cache options not copied.
- seperate amd mount and entry flags.
- make iocl ops ->timeout() handle per-dentry expire.
+- refactor amd mount options handling.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/amd_parse.y
+++ autofs-5.1.7/modules/amd_parse.y
@@ -60,6 +60,7 @@ static int match_map_option_fs_type(char
static int match_map_option_map_type(char *map_option, char *type);
static int match_map_option_cache_option(char *type);
static int match_mnt_option_options(char *mnt_option, char *options);
+static int match_mnt_option(char *option, char *options);
static struct amd_entry entry;
static struct list_head *entries;
@@ -437,40 +438,18 @@ option_assignment: MAP_OPTION OPTION_ASS
options: OPTION
{
- if (!strcmp($1, "fullybrowsable") ||
- !strcmp($1, "nounmount")) {
- sprintf(msg_buf, "option %s is not currently "
- "implemented, ignored", $1);
- amd_info(msg_buf);
- } else if (!strncmp($1, "ping=", 5) ||
- !strncmp($1, "retry=", 6) ||
- !strcmp($1, "public") ||
- !strcmp($1, "softlookup") ||
- !strcmp($1, "xlatecookie")) {
- sprintf(msg_buf, "option %s is not used by "
- "autofs, ignored", $1);
- amd_info(msg_buf);
- } else if (!strncmp($1, "utimeout=", 9)) {
- if (entry.flags & AMD_MOUNT_TYPE_AUTO) {
- char *opt = $1;
- prepend_opt(opts, ++opt);
- } else {
- sprintf(msg_buf, "umount timeout can't be "
- "used for other than type "
- "\"auto\" with autofs, "
- "ignored");
- amd_info(msg_buf);
- }
- } else
+ if (match_mnt_option($1, opts))
prepend_opt(opts, $1);
}
| OPTION COMMA options
{
- prepend_opt(opts, $1);
+ if (match_mnt_option($1, opts))
+ prepend_opt(opts, $1);
}
| OPTION COMMA
{
- prepend_opt(opts, $1);
+ if (match_mnt_option($1, opts))
+ prepend_opt(opts, $1);
}
;
@@ -664,6 +643,39 @@ static int match_mnt_option_options(char
return 1;
}
+static int match_mnt_option(char *option, char *options)
+{
+ int ret = 0;
+
+ if (!strcmp(option, "fullybrowsable") ||
+ !strcmp(option, "nounmount")) {
+ sprintf(msg_buf, "option %s is not currently "
+ "implemented, ignored", option);
+ amd_info(msg_buf);
+ } else if (!strncmp(option, "ping=", 5) ||
+ !strncmp(option, "retry=", 6) ||
+ !strcmp(option, "public") ||
+ !strcmp(option, "softlookup") ||
+ !strcmp(option, "xlatecookie")) {
+ sprintf(msg_buf, "option %s is not used by "
+ "autofs, ignored", option);
+ amd_info(msg_buf);
+ } else if (!strncmp(option, "utimeout=", 9)) {
+ if (entry.flags & AMD_MOUNT_TYPE_AUTO)
+ prepend_opt(options, ++option);
+ else {
+ sprintf(msg_buf, "umount timeout can't be "
+ "used for other than type "
+ "\"auto\" with autofs, "
+ "ignored");
+ amd_info(msg_buf);
+ }
+ } else
+ ret = 1;
+
+ return ret;
+}
+
static void prepend_opt(char *dest, char *opt)
{
char new[MAX_OPTS_LEN];

View File

@ -0,0 +1,133 @@
commit a2002247e16ef60efe049e04119a9c92694cbfe1
Author: Ian Kent <raven@themaw.net>
Date: Tue Jul 9 14:59:40 2024 +0800
autofs-5.1.9 - seperate amd mount and entry flags
We are running out of flags for amd mounts, seperate the mount flags
from the defaults and entry flags and add a new amd entry flags field.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
include/parse_amd.h | 11 ++++++-----
modules/amd_parse.y | 7 ++++---
modules/parse_amd.c | 10 +++++-----
4 files changed, 16 insertions(+), 13 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -168,6 +168,7 @@
- refactor umount_amd_ext_mount().
- add flags argument to amd do_program_mount().
- fix amd cache options not copied.
+- seperate amd mount and entry flags.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/include/parse_amd.h
+++ autofs-5.1.7/include/parse_amd.h
@@ -33,12 +33,12 @@
#define AMD_MOUNT_TYPE_PROGRAM 0x00004000
#define AMD_MOUNT_TYPE_MASK 0x0000ffff
-#define AMD_ENTRY_CUT 0x00010000
-#define AMD_ENTRY_MASK 0x00ff0000
+#define AMD_DEFAULTS_MERGE 0x0001
+#define AMD_DEFAULTS_RESET 0x0002
+#define AMD_DEFAULTS_MASK 0x00ff
-#define AMD_DEFAULTS_MERGE 0x01000000
-#define AMD_DEFAULTS_RESET 0x02000000
-#define AMD_DEFAULTS_MASK 0xff000000
+#define AMD_ENTRY_CUT 0x0100
+#define AMD_ENTRY_MASK 0xff00
#define AMD_CACHE_OPTION_NONE 0x0000
#define AMD_CACHE_OPTION_INC 0x0001
@@ -50,6 +50,7 @@ struct amd_entry {
char *path;
unsigned long flags;
unsigned int cache_opts;
+ unsigned int entry_flags;
char *type;
char *map_type;
char *pref;
--- autofs-5.1.7.orig/modules/amd_parse.y
+++ autofs-5.1.7/modules/amd_parse.y
@@ -155,7 +155,7 @@ location_selection_list: location
}
| location_selection_list SPACE CUT SPACE location
{
- entry.flags |= AMD_ENTRY_CUT;
+ entry.entry_flags |= AMD_ENTRY_CUT;
if (!add_location()) {
amd_msg("failed to allocate new location");
YYABORT;
@@ -168,11 +168,11 @@ location: location_entry
}
| HYPHEN location_entry
{
- entry.flags |= AMD_DEFAULTS_MERGE;
+ entry.entry_flags |= AMD_DEFAULTS_MERGE;
}
| HYPHEN
{
- entry.flags |= AMD_DEFAULTS_RESET;
+ entry.entry_flags |= AMD_DEFAULTS_RESET;
}
;
@@ -889,6 +889,7 @@ static int add_location(void)
}
new->flags = entry.flags;
new->cache_opts = entry.cache_opts;
+ new->entry_flags = entry.entry_flags;
new->type = entry.type;
new->map_type = entry.map_type;
new->pref = entry.pref;
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -2022,13 +2022,13 @@ static struct amd_entry *select_default_
p = p->next;
- if (this->flags & AMD_DEFAULTS_MERGE) {
+ if (this->entry_flags & AMD_DEFAULTS_MERGE) {
if (entry_default)
free_amd_entry(entry_default);
list_del_init(&this->list);
entry_default = this;
continue;
- } else if (this->flags & AMD_DEFAULTS_RESET) {
+ } else if (this->entry_flags & AMD_DEFAULTS_RESET) {
struct amd_entry *new;
new = dup_defaults_entry(defaults_entry);
if (new) {
@@ -2259,14 +2259,14 @@ int parse_mount(struct autofs_point *ap,
struct amd_entry *this = list_entry(p, struct amd_entry, list);
p = p->next;
- if (this->flags & AMD_DEFAULTS_MERGE) {
+ if (this->entry_flags & AMD_DEFAULTS_MERGE) {
free_amd_entry(cur_defaults);
list_del_init(&this->list);
cur_defaults = this;
update_with_defaults(defaults_entry, cur_defaults, sv);
debug(ap->logopt, "merged /defaults entry with defaults");
continue;
- } else if (this->flags & AMD_DEFAULTS_RESET) {
+ } else if (this->entry_flags & AMD_DEFAULTS_RESET) {
struct amd_entry *nd, *new;
struct substvar *nsv = NULL;
@@ -2291,7 +2291,7 @@ int parse_mount(struct autofs_point *ap,
debug(ap->logopt, "expand defaults entry");
sv = expand_entry(ap, cur_defaults, flags, sv);
- if (this->flags & AMD_ENTRY_CUT && at_least_one) {
+ if (this->entry_flags & AMD_ENTRY_CUT && at_least_one) {
info(ap->logopt, MODPREFIX
"at least one entry tried before cut selector, "
"not continuing");

View File

@ -0,0 +1,225 @@
autofs-5.1.9 - update per-mount expire timeout on readmap
From: Ian Kent <raven@themaw.net>
Ensure read map requests are propagated to child submounts and update
the amd per-mount timeout.
Also update the logging text to remove the use of the word dentry as
it might not make sense to users.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
daemon/master.c | 2
daemon/state.c | 1
include/master.h | 1
include/mounts.h | 1
lib/mounts.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/parse_amd.c | 6 +-
7 files changed, 130 insertions(+), 4 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -176,6 +176,7 @@
- fix lookup search type in umount_subtree_mounts().
- fix remount_active_mount() not remounting symlinks.
- log when setting amd per-mount timeout.
+- update per-mount expire timeout on readmap.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/daemon/master.c
+++ autofs-5.1.7/daemon/master.c
@@ -1379,7 +1379,7 @@ static int master_do_mount(struct master
return 1;
}
-static void check_update_map_sources(struct master_mapent *entry, int readall)
+void check_update_map_sources(struct master_mapent *entry, int readall)
{
struct map_source *source, *last;
struct autofs_point *ap;
--- autofs-5.1.7.orig/daemon/state.c
+++ autofs-5.1.7/daemon/state.c
@@ -428,6 +428,7 @@ static void *do_readmap(void *arg)
time_t timeout = get_exp_timeout(ap, ap->entry->maps);
ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
ops->timeout(ap->logopt, ap->ioctlfd, NULL, timeout);
+ update_mounted_mounts_timeout(ap, ap->path);
lookup_prune_cache(ap, now);
status = lookup_ghost(ap);
} else {
--- autofs-5.1.7.orig/include/master.h
+++ autofs-5.1.7/include/master.h
@@ -115,6 +115,7 @@ struct master *master_new(const char *,
int master_read_master(struct master *, time_t);
int master_notify_submount(struct autofs_point *, const char *path, enum states);
void master_notify_state_change(struct master *, int);
+void check_update_map_sources(struct master_mapent *, int);
int master_mount_mounts(struct master *, time_t);
int dump_map(struct master *, const char *, const char *);
int master_show_mounts(struct master *);
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/include/mounts.h
@@ -197,6 +197,7 @@ const char *mount_type_str(unsigned int)
void set_exp_timeout(struct autofs_point *ap, struct map_source *source, time_t timeout);
time_t get_exp_timeout(struct autofs_point *ap, struct map_source *source);
void notify_mount_result(struct autofs_point *, const char *, time_t, const char *);
+void update_mounted_mounts_timeout(struct autofs_point *, const char *);
int try_remount(struct autofs_point *, struct mapent *, unsigned int);
void set_indirect_mount_tree_catatonic(struct autofs_point *);
void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *);
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -2622,6 +2622,128 @@ void notify_mount_result(struct autofs_p
return;
}
+void update_mounted_mounts_timeout(struct autofs_point *ap, const char *path)
+{
+ struct ioctl_ops *ops = get_ioctl_ops();
+ struct dirent **de;
+ char buf[PATH_MAX + 1];
+ int n, size;
+
+ n = scandir(path, &de, 0, alphasort);
+ if (n < 0)
+ return;
+
+ size = sizeof(buf);
+
+ while (n--) {
+ unsigned int mounted = 0;
+ struct mnt_list *mnt;
+ int ret;
+
+ if (strcmp(de[n]->d_name, ".") == 0 ||
+ strcmp(de[n]->d_name, "..") == 0) {
+ free(de[n]);
+ continue;
+ }
+
+ ret = cat_path(buf, size, path, de[n]->d_name);
+ if (!ret) {
+ do {
+ free(de[n]);
+ } while (n--);
+ free(de);
+ return;
+ }
+
+ ops->ismountpoint(ap->logopt, -1, buf, &mounted);
+ if (!mounted) {
+ struct dirent **de2;
+ int i, j;
+
+ i = j = scandir(buf, &de2, 0, alphasort);
+ if (i < 0) {
+ free(de[n]);
+ continue;
+ }
+ while (i--)
+ free(de2[i]);
+ free(de2);
+ if (j <= 2) {
+ free(de[n]);
+ continue;
+ }
+ }
+
+ /* For submounts we need to propogate the read map
+ * request.
+ */
+ mnt = mnts_find_submount(buf);
+ if (mnt) {
+ check_update_map_sources(mnt->ap->entry, 1);
+ mnts_put_mount(mnt);
+ }
+
+ mnt = mnts_find_amdmount(buf);
+ if (!mnt) {
+ free(de[n]);
+ continue;
+ }
+
+ /* For amd type auto mounts the timeout is the per-mount
+ * timeout.
+ */
+ if (mnt->amd_flags & AMD_MOUNT_TYPE_AUTO)
+ goto next;
+
+ /* No per-mount timeout set? */
+ if (!(mnt->amd_flags & AMD_MOUNT_OPT_MASK))
+ goto next;
+
+ /* The default in autofs is to always expire mounts according to
+ * a timeout set in the autofs mount super block information
+ * structure. But amd allows for differing expire timeouts on a
+ * per-mount basis. It also has (context sensitive) options "unmount"
+ * to say expire this mount and "nounmount" to say don't expire this
+ * mount. In amd mounts these options are set by default according
+ * to whether a mount should expire or not, for example a cd mount
+ * is set "nounmount". Setting defaults like this is not used in the
+ * autofs amd implementation because there's only one, little used,
+ * removable file system available.
+ *
+ * But the "nounmount" and "utimeout" options can be useful.
+ */
+ if (mnt->amd_flags & AMD_MOUNT_OPT_NOUNMOUNT) {
+ if (mnt->amd_utimeout)
+ warn(ap->logopt,
+ "non-zero timeout set, possible conflicting options");
+
+ /* "nounmount" option, don't expire this mount. */
+ if (ops) {
+ info(ap->logopt,
+ "set amd per-mount expire timeout to 0 for %s",
+ buf);
+ ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, 0);
+ }
+ } else if (mnt->amd_flags & AMD_MOUNT_OPT_UTIMEOUT) {
+ if (!mnt->amd_utimeout)
+ warn(ap->logopt,
+ "zero timeout set, possible conflicting options");
+
+ /* "utimeout" option, expire this mount according to a timeout. */
+ if (ops) {
+ info(ap->logopt,
+ "set amd per-mount expire timeout to %d for %s",
+ mnt->amd_utimeout, buf);
+ ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, mnt->amd_utimeout);
+ }
+ }
+next:
+ mnts_put_mount(mnt);
+ free(de[n]);
+ }
+ free(de);
+}
+
static int do_remount_direct(struct autofs_point *ap,
const unsigned int type, int fd, const char *path)
{
--- autofs-5.1.7.orig/modules/parse_amd.c
+++ autofs-5.1.7/modules/parse_amd.c
@@ -1758,7 +1758,7 @@ static int amd_mount(struct autofs_point
if (ops) {
info(ap->logopt,
"set amd per-mount expire timeout to 0 for %s",
- name);
+ entry->path);
ops->timeout(ap->logopt, ap->ioctlfd, name, 0);
}
} else if (per_mnt_flags & AMD_MOUNT_OPT_UTIMEOUT) {
@@ -1769,8 +1769,8 @@ static int amd_mount(struct autofs_point
/* "utimeout" option, expire this mount according to a timeout. */
if (ops) {
info(ap->logopt,
- "set amd per-dentry expire timeout to %d for %s",
- entry->utimeout, name);
+ "set amd per-mount expire timeout to %d for %s",
+ entry->utimeout, entry->path);
ops->timeout(ap->logopt, ap->ioctlfd, name, entry->utimeout);
}
}

View File

@ -12,7 +12,7 @@
Summary: A tool for automatically mounting and unmounting filesystems
Name: autofs
Version: 5.1.7
Release: 58%{?dist}
Release: 59%{?dist}
Epoch: 1
License: GPLv2+
Source: https://www.kernel.org/pub/linux/daemons/autofs/v5/autofs-%{version}-2.tar.gz
@ -192,6 +192,31 @@ Patch177: autofs-5.1.8-fix-multi-mount-check.patch
Patch178: autofs-5.1.9-fix-get-parent-multi-mount-check-in-try_remount.patch
Patch179: autofs-5.1.9-fix-deadlock-in-remount.patch
# JIRA: RHEL-69485
Patch180: autofs-5.1.9-fix-amd-external-mount-error-handling.patch
Patch181: autofs-5.1.9-fix-amd-external-mount-mount-handling.patch
Patch182: autofs-5.1.9-dont-free-ext-mount-if-mounted.patch
Patch183: autofs-5.1.9-refactor-amd-function-do_program_mount.patch
Patch184: autofs-5.1.9-refactor-amd-function-umount_amd_ext_mount.patch
Patch185: autofs-5.1.9-add-flags-argument-to-amd-do_program_mount.patch
# JIRA: RHEL-71359
Patch186: autofs-5.1.9-fix-amd-cache-options-not-copied.patch
Patch187: autofs-5.1.9-seperate-amd-mount-and-entry-flags.patch
Patch188: autofs-5.1.9-make-ioctl-ops-timeout-handle-per-dentry-expire.patch
Patch189: autofs-5.1.9-refactor-amd-mount-options-handling.patch
Patch190: autofs-5.1.9-add-some-unimplemented-amd-map-options.patch
# JIRA: RHEL-57466
Patch200: autofs-5.1.9-fix-submount-shutdown-race.patch
# JIRA: RHEL-71359 updates and fixes
Patch201: autofs-5.1.9-fix-lookup-search-type-in-umount_subtree_mounts.patch
Patch202: autofs-5.1.9-fix-remount_active_mount-not-remounting-symlinks.patch
Patch203: autofs-5.1.9-log-when-setting-amd-per-mount-timeout.patch
Patch204: autofs-5.1.9-update-per-mount-expire-timeout-on-readmap.patch
Patch205: autofs-5.1.7-clear-per-mount-timeout-if-not-set.patch
%if %{with_systemd}
BuildRequires: systemd-units
BuildRequires: systemd-devel
@ -427,6 +452,27 @@ echo %{version}-%{release} > .version
%patch178 -p1
%patch179 -p1
%patch180 -p1
%patch181 -p1
%patch182 -p1
%patch183 -p1
%patch184 -p1
%patch185 -p1
%patch186 -p1
%patch187 -p1
%patch188 -p1
%patch189 -p1
%patch190 -p1
%patch200 -p1
%patch201 -p1
%patch202 -p1
%patch203 -p1
%patch204 -p1
%patch205 -p1
%build
LDFLAGS=-Wl,-z,now
%configure \
@ -534,6 +580,31 @@ fi
%dir /etc/auto.master.d
%changelog
* Mon Dec 16 2024 Ian Kent <ikent@redhat.com> - 1:5.1.7-59
- RHEL-69485 - Sporadic mount failures with amd program maps on RHEL8
- fix amd external mount error handling.
- fix amd external mount mount handling.
- don't free ext mount if mounted.
- refactor amd function do_program_mount().
- refactor umount_amd_ext_mount().
- add flags argument to amd do_program_mount().
- Resolves: RHEL-69485
- RHEL-71359 RFE: autofs: add handling for AMD 'nounmount' option
- fix amd cache options not copied.
- seperate amd mount and entry flags.
- make iocl ops ->timeout() handle per-dentry expire.
- refactor amd mount options handling.
- add some unimplemented amd map options.
- fix lookup search type in umount_subtree_mounts().
- fix remount_active_mount() not remounting symlinks.
- log when setting amd per-mount timeout.
- update per-mount expire timeout on readmap.
- clear per-mount timeout if not set.
- Resolves: RHEL-71359
- RHEL-57466 - RHEL9.4 - autofs crashes on startup after IDM client configuration
- fix submount shutdown race.
- Resolves: RHEL-57466
* Fri Dec 22 2023 Ian Kent <ikent@redhat.com> - 1:5.1.7-58
- RHEL-19731 - SIGSEGV using hierarchical map entries on reload with
autofs-5.1.4-109