You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
autofs/SOURCES/autofs-5.1.9-add-some-unimp...

222 lines
6.8 KiB

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.9.orig/CHANGELOG
+++ autofs-5.1.9/CHANGELOG
@@ -16,6 +16,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.
02/11/2023 autofs-5.1.9
- fix kernel mount status notification.
--- autofs-5.1.9.orig/include/mounts.h
+++ autofs-5.1.9/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.9.orig/include/parse_amd.h
+++ autofs-5.1.9/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.9.orig/lib/mounts.c
+++ autofs-5.1.9/lib/mounts.c
@@ -1193,6 +1193,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))
@@ -1237,6 +1239,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.9.orig/modules/amd_parse.y
+++ autofs-5.1.9/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.9.orig/modules/parse_amd.c
+++ autofs-5.1.9/modules/parse_amd.c
@@ -1654,6 +1654,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) {
@@ -1725,6 +1726,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;
}