Compare commits

...

No commits in common. 'c9' and 'i10c-beta' have entirely different histories.

@ -1 +1 @@
086c327711a7f76692c582264c0742842f3570ba SOURCES/autofs-5.1.7-2.tar.gz 38be847c4d3ca27696d9e8d87b3aabdb6e9d1398 SOURCES/autofs-5.1.9.tar.gz

2
.gitignore vendored

@ -1 +1 @@
SOURCES/autofs-5.1.7-2.tar.gz SOURCES/autofs-5.1.9.tar.gz

@ -1,48 +0,0 @@
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'},

@ -1,136 +0,0 @@
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);

@ -1,104 +0,0 @@
autofs-5.1.7 - add buffer length checks to autofs mount_mount()
From: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
modules/mount_autofs.c | 59 +++++++++++++++++++++++++++++++++----------------
2 files changed, 41 insertions(+), 19 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -138,6 +138,7 @@
- fix amd selector function matching.
- get rid entry thid field.
- continue expire immediately after submount check.
+- add buffer length checks to autofs mount_mount().
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/mount_autofs.c
+++ autofs-5.1.7/modules/mount_autofs.c
@@ -50,8 +50,8 @@ int mount_mount(struct autofs_point *ap,
{
struct startup_cond suc;
pthread_t thid;
- char realpath[PATH_MAX];
- char mountpoint[PATH_MAX];
+ char realpath[PATH_MAX + 1];
+ char mountpoint[PATH_MAX + 1];
const char **argv;
int argc, status;
int nobind = ap->flags & MOUNT_FLAG_NOBIND;
@@ -68,32 +68,53 @@ int mount_mount(struct autofs_point *ap,
struct mnt_list *mnt;
char buf[MAX_ERR_BUF];
char *options, *p;
- int len, ret;
+ int err, ret;
int hosts = 0;
/* Root offset of multi-mount */
- len = strlen(root);
- if (root[len - 1] == '/') {
- strcpy(realpath, ap->path);
- strcat(realpath, "/");
- strcat(realpath, name);
- len--;
- strncpy(mountpoint, root, len);
- mountpoint[len] = '\0';
+ if (root[strlen(root) - 1] == '/') {
+ err = snprintf(realpath, PATH_MAX + 1, "%s/%s", ap->path, name);
+ if (err > PATH_MAX) {
+ error(ap->logopt, MODPREFIX "string too long for realpath");
+ return 1;
+ }
+ err = snprintf(mountpoint, PATH_MAX + 1, "%s", root);
+ if (err > PATH_MAX) {
+ error(ap->logopt, MODPREFIX "string too long for mountpoint");
+ return 1;
+ }
+ mountpoint[err - 1] = 0;
} else if (*name == '/') {
if (ap->flags & MOUNT_FLAG_REMOUNT) {
- strcpy(mountpoint, name);
- strcpy(realpath, name);
+ err = snprintf(mountpoint, PATH_MAX + 1, "%s", name);
+ if (err > PATH_MAX) {
+ error(ap->logopt, MODPREFIX "string too long for mountpoint");
+ return 1;
+ }
+ err = snprintf(realpath, PATH_MAX + 1, "%s", name);
+ if (err > PATH_MAX) {
+ error(ap->logopt, MODPREFIX "string too long for realpath");
+ return 1;
+ }
} else {
- strcpy(mountpoint, root);
- strcpy(realpath, name);
+ err = snprintf(mountpoint, PATH_MAX + 1, "%s", root);
+ if (err > PATH_MAX) {
+ error(ap->logopt, MODPREFIX "string too long for mountpoint");
+ return 1;
+ }
+ err = snprintf(realpath, PATH_MAX + 1, "%s", name);
+ if (err > PATH_MAX) {
+ error(ap->logopt, MODPREFIX "string too long for realpath");
+ return 1;
+ }
}
} else {
- strcpy(mountpoint, root);
- strcat(mountpoint, "/");
+ err = snprintf(mountpoint, PATH_MAX + 1, "%s/%s", root, name);
+ if (err > PATH_MAX) {
+ error(ap->logopt, MODPREFIX "string too long for mountpoint");
+ return 1;
+ }
strcpy(realpath, mountpoint);
- strcat(mountpoint, name);
- strcat(realpath, name);
}
options = NULL;

@ -1,104 +0,0 @@
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;
}

@ -1,42 +0,0 @@
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);

@ -1,177 +0,0 @@
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

@ -1,51 +0,0 @@
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(+)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -75,6 +75,7 @@
- fix hosts map offset order.
- fix direct mount deadlock.
- fix lookup_prune_one_cache() refactoring change.
+- add missing description of null map option.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/man/auto.master.5.in
+++ autofs-5.1.7/man/auto.master.5.in
@@ -265,6 +265,25 @@ accessing /net/myserver will mount expor
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

@ -1,42 +0,0 @@
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);
}

@ -1,310 +0,0 @@
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

@ -1,50 +0,0 @@
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)) {

@ -1,552 +0,0 @@
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) {

@ -1,133 +0,0 @@
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

@ -1,94 +0,0 @@
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

@ -1,119 +0,0 @@
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

@ -1,83 +0,0 @@
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);

@ -1,34 +0,0 @@
autofs-5.1.7 - also require TCP_REQUESTED when setting NFS port
From: Ian Kent <raven@themaw.net>
Set the NFS service port to the default (2049) only if tcp protocol is
being used and not alternate port has been given.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/replicated.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -98,6 +98,7 @@
- fix handling of incorrect return from umount_ent().
- make NFS version check flags consistent.
- refactor get_nfs_info().
+- also require TCP_REQUESTED when setting NFS port.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/replicated.c
+++ autofs-5.1.7/modules/replicated.c
@@ -291,7 +291,7 @@ static unsigned int get_nfs_info(unsigne
rpc_info->proto = proto;
if (port < 0) {
- if (version & NFS4_REQUESTED)
+ if ((version & NFS4_REQUESTED) && (version & TCP_REQUESTED))
rpc_info->port = NFS_PORT;
else
port = 0;

@ -1,44 +0,0 @@
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();
}

@ -1,50 +0,0 @@
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);

@ -1,64 +0,0 @@
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;

@ -1,207 +0,0 @@
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);

@ -1,64 +0,0 @@
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

@ -1,45 +0,0 @@
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);

@ -1,112 +0,0 @@
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;
}

@ -1,82 +0,0 @@
autofs-5.1.7 - eliminate buffer usage from handle_mounts_cleanup()
From: Ian Kent <raven@themaw.net>
This buffer was originally added because a SEGV was seen accessing
the ap->path field on shutdown.
But this was actually caused by calling master_remove_mapent() too
early which adds the map entry to the master map join list that leads
to freeing the autofs_point (ap in the code) which also frees ap->path.
But the master map join list is protected by the master map mutex which
is held until after all the accesses are completed. So whatever the
problem was it doesn't appear to be present any more.
Nevertheless, to be sure, delay the call to master_remove_mapent() until
after all accesses to ap->path are completed.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/automount.c | 13 ++++++-------
2 files changed, 7 insertions(+), 7 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -148,6 +148,7 @@
- change to use printf functions in amd parser.
- dont call umount_subtree_mounts() on parent at umount.
- dont take parent source lock at mount shutdown.
+- eliminate buffer usage from handle_mounts_cleanup().
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
@@ -1724,7 +1724,6 @@ void handle_mounts_startup_cond_destroy(
static void handle_mounts_cleanup(void *arg)
{
struct autofs_point *ap;
- char path[PATH_MAX + 1];
char buf[MAX_ERR_BUF];
unsigned int clean = 0, submount, logopt;
unsigned int pending = 0;
@@ -1734,7 +1733,6 @@ static void handle_mounts_cleanup(void *
logopt = ap->logopt;
submount = ap->submount;
- strcpy(path, ap->path);
if (!submount && strcmp(ap->path, "/-") &&
ap->flags & MOUNT_FLAG_DIR_CREATED)
clean = 1;
@@ -1756,8 +1754,8 @@ static void handle_mounts_cleanup(void *
/* Don't signal the handler if we have already done so */
if (!list_empty(&master_list->completed))
pending = 1;
- master_remove_mapent(ap->entry);
- master_source_unlock(ap->entry);
+
+ info(logopt, "shut down path %s", ap->path);
/*
* Submounts are detached threads and don't belong to the
@@ -1770,14 +1768,15 @@ static void handle_mounts_cleanup(void *
}
if (clean) {
- if (rmdir(path) == -1) {
+ if (rmdir(ap->path) == -1) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
warn(logopt, "failed to remove dir %s: %s",
- path, estr);
+ ap->path, estr);
}
}
- info(logopt, "shut down path %s", path);
+ master_remove_mapent(ap->entry);
+ master_source_unlock(ap->entry);
/*
* If we are not a submount send a signal to the signal handler

@ -1,378 +0,0 @@
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);

@ -1,290 +0,0 @@
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);

@ -1,140 +0,0 @@
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,

@ -1,82 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -71,6 +71,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.
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/include/mounts.h
@@ -170,7 +170,7 @@ void mnts_get_expire_list(struct list_he
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);
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -1519,19 +1519,10 @@ static void tree_mapent_free(struct tree
}
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_c
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
--- autofs-5.1.7.orig/modules/parse_sun.c
+++ autofs-5.1.7/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);
}

@ -1,217 +0,0 @@
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>
---
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -78,6 +78,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.
--- autofs-5.1.7.orig/modules/lookup_program.c
+++ autofs-5.1.7/modules/lookup_program.c
@@ -636,7 +636,14 @@ int lookup_mount(struct autofs_point *ap
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
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)) {
--- autofs-5.1.7.orig/modules/lookup_yp.c
+++ autofs-5.1.7/modules/lookup_yp.c
@@ -254,7 +254,7 @@ int yp_all_master_callback(int status, c
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, c
master_parse_entry(buffer, timeout, logging, age);
+ free(buffer);
+
return 0;
}
@@ -368,7 +370,12 @@ int yp_all_callback(int status, char *yp
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 *yp
cache_unlock(mc);
free(key);
+ free(mapent);
if (ret == CHE_FAIL)
return -1;
@@ -904,7 +912,14 @@ int lookup_mount(struct autofs_point *ap
}
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
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)
--- autofs-5.1.7.orig/modules/parse_sun.c
+++ autofs-5.1.7/modules/parse_sun.c
@@ -668,9 +668,16 @@ static int sun_mount(struct autofs_point
}
}
+ 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
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
/* 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)
--- autofs-5.1.7.orig/modules/replicated.c
+++ autofs-5.1.7/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, stru
}
}
- if (!add_path(*hosts, path, strlen(path))) {
+ if (!add_path(*hosts, path)) {
free_host_list(hosts);
free(str);
return 0;

@ -1,128 +0,0 @@
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;

@ -1,48 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -68,6 +68,7 @@
- add ext_mount_hash_mutex lock helpers.
- fix dangling symlink creation if nis support is not available.
- fix amd section mounts map reload.
+- fix amd hosts mount expire.
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
@@ -2341,12 +2341,13 @@ int parse_mount(struct autofs_point *ap,
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 */

@ -1,120 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -67,6 +67,7 @@
- cater for empty mounts list in mnts_get_expire_list().
- add ext_mount_hash_mutex lock helpers.
- fix dangling symlink creation if nis support is not available.
+- fix amd section mounts map reload.
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
@@ -882,6 +882,83 @@ struct master *master_new(const char *na
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
* 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);

@ -1,40 +0,0 @@
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);

@ -1,120 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -77,6 +77,7 @@
- fix lookup_prune_one_cache() refactoring change.
- 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.
--- autofs-5.1.7.orig/modules/parse_sun.c
+++ autofs-5.1.7/modules/parse_sun.c
@@ -380,7 +380,8 @@ static int do_init(int argc, const char
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 *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,
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,
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;
}

@ -1,35 +0,0 @@
autofs-5.1.7 - fix dangling 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(+)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/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 dangling symlink creation if nis support is not available.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/Makefile
+++ autofs-5.1.7/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

@ -1,55 +0,0 @@
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)

@ -1,129 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -73,6 +73,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.
--- autofs-5.1.7.orig/daemon/direct.c
+++ autofs-5.1.7/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_p
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_p
* failed umount.
*/
error = do_umount_autofs_direct(ap, me);
+ /* cache became invalid, restart */
+ if (error == -1)
+ goto restart;
if (!error)
goto done;
--- autofs-5.1.7.orig/daemon/state.c
+++ autofs-5.1.7/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 auto
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 auto
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);

@ -1,39 +0,0 @@
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;
}

@ -1,37 +0,0 @@
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;
}

@ -1,38 +0,0 @@
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

@ -1,289 +0,0 @@
autofs-5.1.7 - fix hosts map offset order
From: Ian Kent <raven@themaw.net>
Map entry offset paths 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 use to mount the offset during parsing since the
path length of exports can cary 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 | 71 ++++++++++++++++++++++++++++++++++++++-----------
6 files changed, 124 insertions(+), 18 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -72,6 +72,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.
--- autofs-5.1.7.orig/include/automount.h
+++ autofs-5.1.7/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"
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/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 a
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);
--- autofs-5.1.7.orig/include/rpc_subs.h
+++ autofs-5.1.7/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 {
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/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(s
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 *
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_he
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);
--- autofs-5.1.7.orig/modules/lookup_hosts.c
+++ autofs-5.1.7/modules/lookup_hosts.c
@@ -84,14 +84,38 @@ int lookup_read_master(struct master *ma
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_p
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_p
}
*mapent = 0;
- pos = 0;
- this = exp;
- 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;
+ wi.mapent = mapent;
+ wi.host = host;
+ wi.pos = 0;
+
+ if (!tree) {
+ free(mapent);
+ mapent = NULL;
+ } else {
+ tree_traverse_inorder(tree, tree_host_work, &wi);
+ tree_free(tree);
}
rpc_exports_free(exp);

@ -1,251 +0,0 @@
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);

@ -1,135 +0,0 @@
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);
}

@ -1,40 +0,0 @@
autofs-5.1.7 - fix incorrect print format specifiers in get_pkt()
From: Ian Kent <raven@themaw.net>
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/automount.c | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -122,6 +122,7 @@
- make amd mapent search function name clear.
- rename statemachine() to signal_handler().
- make signal handling consistent.
+- fix incorrect print format specifiers in get_pkt().
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
@@ -1105,7 +1105,7 @@ static int get_pkt(struct autofs_point *
estr = strerror_r(errno, buf, MAX_ERR_BUF);
error(ap->logopt,
"read error on state pipe, "
- "read %u, error %s",
+ "read %lu, error %s",
read, estr);
st_mutex_unlock();
continue;
@@ -1123,7 +1123,7 @@ static int get_pkt(struct autofs_point *
estr = strerror_r(errno, buf, MAX_ERR_BUF);
error(ap->logopt,
"read error on request pipe, "
- "read %u, expected %u error %s",
+ "read %lu, expected %lu error %s",
read, kpkt_len, estr);
}
return read;

@ -1,64 +0,0 @@
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;

@ -1,56 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -74,6 +74,7 @@
- eliminate redundant cache lookup in tree_mapent_add_node().
- fix hosts map offset order.
- fix direct mount deadlock.
+- fix lookup_prune_one_cache() refactoring change.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/daemon/lookup.c
+++ autofs-5.1.7/daemon/lookup.c
@@ -1379,6 +1379,7 @@ void lookup_prune_one_cache(struct autof
if (!key || strchr(key, '*')) {
if (key)
free(key);
+ me = cache_enumerate(mc, me);
continue;
}
@@ -1386,6 +1387,7 @@ void lookup_prune_one_cache(struct autof
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 autof
}
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)

@ -1,36 +0,0 @@
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] = '/';

@ -1,40 +0,0 @@
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) {

@ -1,38 +0,0 @@
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;

@ -1,67 +0,0 @@
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)

@ -1,54 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -76,6 +76,7 @@
- fix direct mount deadlock.
- fix lookup_prune_one_cache() refactoring change.
- 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.
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -1616,7 +1616,7 @@ static int tree_mapent_traverse_subtree(
{
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);
--- autofs-5.1.7.orig/modules/parse_sun.c
+++ autofs-5.1.7/modules/parse_sun.c
@@ -1181,7 +1181,7 @@ static int mount_subtree(struct autofs_p
* 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);

@ -1,199 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -69,6 +69,7 @@
- fix dangling symlink creation if nis support is not available.
- fix amd section mounts map reload.
- fix amd hosts mount expire.
+- fix offset entries order.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/include/automount.h
+++ autofs-5.1.7/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;
--- autofs-5.1.7.orig/lib/cache.c
+++ autofs-5.1.7/lib/cache.c
@@ -559,6 +559,7 @@ int cache_add(struct mapent_cache *mc, s
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;
--- autofs-5.1.7.orig/modules/parse_sun.c
+++ autofs-5.1.7/modules/parse_sun.c
@@ -789,14 +789,15 @@ static int check_is_multi(const char *ma
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
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
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,
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);

@ -1,38 +0,0 @@
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();

@ -1,58 +0,0 @@
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;

@ -1,44 +0,0 @@
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 &&

@ -1,65 +0,0 @@
autofs-5.1.7 - make NFS version check flags consistent
From: Ian Kent <raven@themaw.net>
Several of the NFS connection macros have the same value so that they
can be used as internal code documentation of what is being done.
Adjust the protocol macro naming to be consistent in a few places.
Also make sure the correct flags are set for the function they indicate.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/mount_nfs.c | 16 +++++++++-------
2 files changed, 10 insertions(+), 7 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -96,6 +96,7 @@
- fix sysconf(3) return handling.
- remove nonstrict parameter from tree_mapent_umount_offsets().
- fix handling of incorrect return from umount_ent().
+- make NFS version check flags consistent.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/mount_nfs.c
+++ autofs-5.1.7/modules/mount_nfs.c
@@ -178,18 +178,20 @@ int mount_mount(struct autofs_point *ap,
port = 0;
} else if (_strncmp("proto=udp", cp, o_len) == 0 ||
_strncmp("udp", cp, o_len) == 0) {
- vers &= ~TCP_SUPPORTED;
+ vers &= ~TCP_REQUESTED;
+ vers |= UDP_REQUESTED;
} else if (_strncmp("proto=udp6", cp, o_len) == 0 ||
_strncmp("udp6", cp, o_len) == 0) {
- vers &= ~TCP_SUPPORTED;
- vers |= UDP6_REQUESTED;
+ vers &= ~(TCP_REQUESTED|TCP6_REQUESTED);
+ vers |= (UDP_REQUESTED|UDP6_REQUESTED);
} else if (_strncmp("proto=tcp", cp, o_len) == 0 ||
_strncmp("tcp", cp, o_len) == 0) {
- vers &= ~UDP_SUPPORTED;
+ vers &= ~UDP_REQUESTED;
+ vers |= TCP_REQUESTED;
} else if (_strncmp("proto=tcp6", cp, o_len) == 0 ||
_strncmp("tcp6", cp, o_len) == 0) {
- vers &= ~UDP_SUPPORTED;
- vers |= TCP6_REQUESTED;
+ vers &= ~(UDP_REQUESTED|UDP6_REQUESTED);
+ vers |= TCP_REQUESTED|TCP6_REQUESTED;
}
/* Check for options that also make sense
with bind mounts */
@@ -246,7 +248,7 @@ int mount_mount(struct autofs_point *ap,
mount_default_proto == 4 &&
(vers & NFS_VERS_MASK) != 0 &&
(vers & NFS4_VERS_MASK) != 0 &&
- !(vers & UDP6_REQUESTED)) {
+ !(vers & (UDP_REQUESTED|UDP6_REQUESTED))) {
unsigned int v4_probe_ok = 0;
struct host *tmp = new_host(hosts->name, 0,
hosts->addr, hosts->addr_len,

@ -1,352 +0,0 @@
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();

@ -1,118 +0,0 @@
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();
}

@ -1,72 +0,0 @@
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) {

@ -1,171 +0,0 @@
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");

@ -1,83 +0,0 @@
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 {

@ -1,202 +0,0 @@
autofs-5.1.7 - refactor get_nfs_info()
From: Ian Kent <raven@themaw.net>
Make getting a portmap client and getting a service port from portmap
helper functions and simplify the return handling.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
modules/replicated.c | 135 ++++++++++++++++++++++++++++-----------------------
2 files changed, 76 insertions(+), 60 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -97,6 +97,7 @@
- remove nonstrict parameter from tree_mapent_umount_offsets().
- fix handling of incorrect return from umount_ent().
- make NFS version check flags consistent.
+- refactor get_nfs_info().
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/modules/replicated.c
+++ autofs-5.1.7/modules/replicated.c
@@ -223,6 +223,49 @@ void free_host_list(struct host **list)
*list = NULL;
}
+static unsigned int get_portmap_client(unsigned logopt,
+ struct conn_info *pm_info, struct host *host,
+ int proto)
+{
+ unsigned int status;
+
+ /* On success client is stored in pm_info->client */
+ status = rpc_portmap_getclient(pm_info,
+ host->name, host->addr, host->addr_len,
+ proto, RPC_CLOSE_DEFAULT);
+ if (status == -EHOSTUNREACH)
+ debug(logopt,
+ "host not reachable getting portmap client");
+ else if (status)
+ debug(logopt, "error 0x%d getting portmap client");
+
+ return status;
+}
+
+static unsigned int get_portmap_port(unsigned logopt,
+ struct conn_info *pm_info, struct pmap *parms,
+ unsigned long vers, unsigned int version,
+ short unsigned int *port)
+{
+ unsigned int status;
+ short unsigned int nfs_port;
+
+ parms->pm_vers = vers;
+ status = rpc_portmap_getport(pm_info, parms, &nfs_port);
+ if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
+ debug(logopt,
+ "host not reachable or timed out getting service port");
+ } else if (status < 0) {
+ if (!(version & NFS_VERS_MASK))
+ debug(logopt, "error 0x%d getting service port");
+ }
+
+ if (!status)
+ *port = nfs_port;
+
+ return status;
+}
+
static unsigned int get_nfs_info(unsigned logopt, struct host *host,
struct conn_info *pm_info, struct conn_info *rpc_info,
int proto, unsigned int version, int port)
@@ -263,33 +306,20 @@ static unsigned int get_nfs_info(unsigne
goto v3_ver;
if (!port) {
- status = rpc_portmap_getclient(pm_info,
- host->name, host->addr, host->addr_len,
- proto, RPC_CLOSE_DEFAULT);
- if (status == -EHOSTUNREACH) {
- debug(logopt,
- "host not reachable getting portmap client");
- supported = status;
- goto done_ver;
- } else if (status) {
- debug(logopt, "error 0x%d getting portmap client");
+ status = get_portmap_client(logopt, pm_info, host, proto);
+ if (status) {
+ if (status == -EHOSTUNREACH)
+ supported = status;
goto done_ver;
}
- parms.pm_vers = NFS4_VERSION;
- status = rpc_portmap_getport(pm_info, &parms, &rpc_info->port);
- if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
- debug(logopt,
- "host not reachable or timed out getting service port");
- supported = status;
- goto done_ver;
- } else if (status < 0) {
- if (version & NFS_VERS_MASK)
+ status = get_portmap_port(logopt, pm_info, &parms,
+ NFS4_VERSION, version, &rpc_info->port);
+ if (status) {
+ if (status == -EHOSTUNREACH || status == -ETIMEDOUT)
+ supported = status;
+ if (status < 0 && version & NFS_VERS_MASK)
goto v3_ver; /* MOUNT_NFS_DEFAULT_PROTOCOL=4 */
- else {
- debug(logopt,
- "error 0x%d getting service port");
- goto done_ver;
- }
+ goto done_ver;
}
}
@@ -334,31 +364,22 @@ v3_ver:
goto v2_ver;
if (!port && !pm_info->client) {
- status = rpc_portmap_getclient(pm_info,
- host->name, host->addr, host->addr_len,
- proto, RPC_CLOSE_DEFAULT);
- if (status == -EHOSTUNREACH) {
- debug(logopt,
- "host not reachable getting portmap client");
- supported = status;
- goto done_ver;
- } else if (status) {
- debug(logopt,
- "error 0x%d getting getting portmap client");
+ status = get_portmap_client(logopt, pm_info, host, proto);
+ if (status) {
+ if (status == -EHOSTUNREACH)
+ supported = status;
goto done_ver;
}
}
if (!port) {
- parms.pm_vers = NFS3_VERSION;
- status = rpc_portmap_getport(pm_info, &parms, &rpc_info->port);
- if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
- debug(logopt,
- "host not reachable or timed out getting service port");
- supported = status;
+ status = get_portmap_port(logopt, pm_info, &parms,
+ NFS3_VERSION, version, &rpc_info->port);
+ if (status) {
+ if (status == -EHOSTUNREACH || status == -ETIMEDOUT)
+ supported = status;
goto done_ver;
- } else if (status < 0)
- goto v2_ver;
+ }
}
if (rpc_info->proto == IPPROTO_UDP)
@@ -399,28 +420,22 @@ v2_ver:
goto done_ver;
if (!port && !pm_info->client) {
- status = rpc_portmap_getclient(pm_info,
- host->name, host->addr, host->addr_len,
- proto, RPC_CLOSE_DEFAULT);
- if (status == -EHOSTUNREACH) {
- debug(logopt,
- "host not reachable getting portmap client");
- supported = status;
- goto done_ver;
- } else if (status)
+ status = get_portmap_client(logopt, pm_info, host, proto);
+ if (status) {
+ if (status == -EHOSTUNREACH)
+ supported = status;
goto done_ver;
+ }
}
if (!port) {
- parms.pm_vers = NFS2_VERSION;
- status = rpc_portmap_getport(pm_info, &parms, &rpc_info->port);
- if (status == -EHOSTUNREACH || status == -ETIMEDOUT) {
- debug(logopt,
- "host not reachable or timed out getting service port");
- supported = status;
- goto done_ver;
- } else if (status < 0)
+ status = get_portmap_port(logopt, pm_info, &parms,
+ NFS2_VERSION, version, &rpc_info->port);
+ if (status) {
+ if (status == -EHOSTUNREACH || status == -ETIMEDOUT)
+ supported = status;
goto done_ver;
+ }
}
if (rpc_info->proto == IPPROTO_UDP)

@ -1,75 +0,0 @@
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);
}

@ -1,259 +0,0 @@
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;
}
-

@ -1,178 +0,0 @@
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;
}

@ -1,752 +0,0 @@
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)
{

@ -1,40 +0,0 @@
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:

@ -1,40 +0,0 @@
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);

@ -1,74 +0,0 @@
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);

@ -1,182 +0,0 @@
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 {

@ -1,60 +0,0 @@
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);

@ -1,63 +0,0 @@
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;

@ -1,179 +0,0 @@
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);

@ -1,66 +0,0 @@
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 */

@ -1,32 +0,0 @@
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(-)
--- autofs-5.1.7.orig/modules/lookup_hosts.c
+++ autofs-5.1.7/modules/lookup_hosts.c
@@ -87,7 +87,6 @@ int lookup_read_master(struct master *ma
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);
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/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.

@ -1,159 +0,0 @@
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) == '/'));

@ -1,197 +0,0 @@
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();

@ -1,104 +0,0 @@
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);

@ -1,105 +0,0 @@
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

@ -1,46 +0,0 @@
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

@ -1,414 +0,0 @@
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);

@ -1,120 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -79,6 +79,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.
--- autofs-5.1.7.orig/daemon/automount.c
+++ autofs-5.1.7/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};
@@ -2614,34 +2613,6 @@ int main(int argc, char *argv[])
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);
- }
-
-#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();
--- autofs-5.1.7.orig/daemon/state.c
+++ autofs-5.1.7/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);
--- autofs-5.1.7.orig/lib/alarm.c
+++ autofs-5.1.7/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)

@ -1,111 +0,0 @@
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(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -70,6 +70,7 @@
- fix amd section mounts map reload.
- 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.
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/include/mounts.h
@@ -170,7 +170,7 @@ void mnts_get_expire_list(struct list_he
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);
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -1519,27 +1519,13 @@ static void tree_mapent_free(struct tree
}
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_c
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))
--- autofs-5.1.7.orig/modules/parse_sun.c
+++ autofs-5.1.7/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);
}

@ -1,74 +0,0 @@
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);

@ -1,76 +0,0 @@
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);

@ -1,310 +0,0 @@
autofs-5.1.8 - add command pipe handling functions
From: Ian Kent <raven@themaw.net>
In order to use a single file handle for a command pipe the pipe needs
to be independent of the kernel message packet handling function.
Add most of the functions needed for this as preperation.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
daemon/automount.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 270 insertions(+)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -126,6 +126,7 @@
- eliminate last remaining state_pipe usage.
- add function master_find_mapent_by_devid().
- use device id to locate autofs_point when setting log priotity.
+- add command pipe handling functions.
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
@@ -60,6 +60,14 @@ unsigned int nfs_mount_uses_string_optio
static struct nfs_mount_vers vers, check = {1, 1, 1};
#define FIFO_BUF_SIZE 25
+static int cmd_pipe_fifo = -1;
+
+/* autofs cmd fifo name */
+#define FIFO_NAME "autofs.cmd.fifo"
+const char *cmd_pipe_name = AUTOFS_FIFO_DIR "/" FIFO_NAME;
+
+int start_cmd_pipe_handler(void);
+void finish_cmd_pipe_handler(void);
/* autofs fifo name prefix */
#define FIFO_NAME_PREFIX "autofs.fifo"
@@ -1654,6 +1662,267 @@ static void *signal_handler(void *arg)
}
}
+static pthread_mutex_t cmd_pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int done = 0;
+static pthread_t cmd_pipe_thid;
+
+void cmd_pipe_mutex_lock(void)
+{
+ int status = pthread_mutex_lock(&cmd_pipe_mutex);
+ if (status)
+ fatal(status);
+}
+
+void cmd_pipe_mutex_unlock(void)
+{
+ int status = pthread_mutex_unlock(&cmd_pipe_mutex);
+ if (status)
+ fatal(status);
+}
+
+static int create_cmd_pipe_fifo(void)
+{
+ char buf[MAX_ERR_BUF];
+ int ret = -1;
+ int fd;
+
+ if (cmd_pipe_fifo != -1)
+ return 0;
+
+ ret = unlink(cmd_pipe_name);
+ if (ret != 0 && errno != ENOENT) {
+ fprintf(stderr,
+ "%s: failed to unlink command pipe. Is the "
+ "automount daemon already running?", program);
+ return ret;
+ }
+
+ ret = mkfifo(cmd_pipe_name, S_IRUSR|S_IWUSR);
+ if (ret != 0 && errno != EEXIST) {
+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ fprintf(stderr, "%s: mkfifo for %s failed: %s",
+ program, cmd_pipe_name, estr);
+ return ret;
+ }
+
+ fd = open_fd(cmd_pipe_name, O_RDWR|O_NONBLOCK);
+ if (fd < 0) {
+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ unlink(cmd_pipe_name);
+ fprintf(stderr, "%s: failed to open cwcommand pipe %s: %s",
+ program, cmd_pipe_name, estr);
+ return -1;
+ }
+
+ cmd_pipe_fifo = fd;
+
+ return 0;
+}
+
+static int destroy_cmd_pipe_fifo(void)
+{
+ char buf[MAX_ERR_BUF];
+ int ret = -1;
+
+ if (cmd_pipe_fifo == -1)
+ return 0;
+
+ ret = close(cmd_pipe_fifo);
+ if (ret != 0) {
+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ warn(LOGOPT_ANY,
+ "close for command pipe %s: %s", cmd_pipe_name, estr);
+ }
+
+ cmd_pipe_fifo = -1;
+
+ ret = unlink(cmd_pipe_name);
+ if (ret != 0) {
+ warn(LOGOPT_ANY,
+ "failed to unlink FIFO. Was the fifo created OK?");
+ }
+
+ return 0;
+}
+
+static void handle_cmd_pipe_fifo_message(int fd)
+{
+ struct autofs_point *ap;
+ char buffer[PIPE_BUF];
+ char *end, *sep;
+ char buf[MAX_ERR_BUF];
+ dev_t devid;
+ int ret;
+ long pri;
+
+ memset(buffer, 0, sizeof(buffer));
+ ret = read(fd, &buffer, sizeof(buffer));
+ if (ret < 0) {
+ char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ warn(LOGOPT_ANY,
+ "read on command pipe returned error: %s", estr);
+ return;
+ }
+
+ sep = strrchr(buffer, ' ');
+ if (!sep) {
+ error(LOGOPT_ANY,
+ "incorrect command pipe message format %s.", buffer);
+ return;
+ }
+ sep++;
+
+ errno = 0;
+ devid = strtol(buffer, &end, 10);
+ if ((devid == LONG_MIN || devid == LONG_MAX) && errno == ERANGE) {
+ debug(LOGOPT_ANY, "strtol reported a range error.");
+ error(LOGOPT_ANY, "invalid command pipe message format %s.", buffer);
+ return;
+ }
+
+ if ((devid == 0 && errno == EINVAL) || end == buffer) {
+ debug(LOGOPT_ANY, "devid id is expected to be a integer.");
+ return;
+ }
+
+ ap = master_find_mapent_by_devid(master_list, devid);
+ if (!ap) {
+ error(LOGOPT_ANY, "can't locate autofs_point for device id %ld.", devid);
+ return;
+ }
+
+ errno = 0;
+ pri = strtol(sep, &end, 10);
+ if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) {
+ error(ap->logopt, "failed to set log priority.");
+ error(ap->logopt, "strtol reported an %s.",
+ pri == LONG_MIN ? "underflow" : "overflow");
+ return;
+ }
+
+ if ((pri == 0 && errno == EINVAL) || end == sep) {
+ debug(ap->logopt, "priority is expected to be an integer "
+ "in the range 0-7 inclusive.");
+ return;
+ }
+
+ if (pri > LOG_DEBUG || pri < LOG_EMERG) {
+ debug(ap->logopt,
+ "invalid log priority (%ld) received on fifo", pri);
+ return;
+ }
+
+ /*
+ * OK, the message passed all of the sanity checks. The
+ * automounter actually only supports three log priorities.
+ * Everything is logged at log level debug, deamon messages
+ * and everything except debug messages are logged with the
+ * verbose setting and only error and critical messages are
+ * logged when debugging isn't enabled.
+ */
+ if (pri >= LOG_WARNING) {
+ if (pri == LOG_DEBUG) {
+ set_log_debug_ap(ap);
+ info(ap->logopt, "debug logging set for %s", ap->path);
+ } else {
+ set_log_verbose_ap(ap);
+ info(ap->logopt, "verbose logging set for %s", ap->path);
+ }
+ } else {
+ if (ap->logopt & LOGOPT_ANY)
+ info(ap->logopt, "basic logging set for %s", ap->path);
+ set_log_norm_ap(ap);
+ }
+}
+
+static void cmd_pipe_dummy(int sig)
+{
+}
+
+static void *cmd_pipe_handler(void *arg)
+{
+ struct sigaction sa;
+ sigset_t signalset;
+ struct pollfd fds[1];
+ int pollfds = 1;
+ char buf[MAX_ERR_BUF];
+ char *estr;
+
+ if (create_cmd_pipe_fifo())
+ return NULL;
+
+ fds[0].fd = cmd_pipe_fifo;
+ fds[0].events = POLLIN;
+
+ sa.sa_handler = cmd_pipe_dummy;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction(SIGPIPE, &sa, NULL) == -1) {
+ error(LOGOPT_ANY, "failed to set signal handler %d", errno);
+ return NULL;
+ }
+
+ sigfillset(&signalset);
+ sigdelset(&signalset, SIGPIPE);
+
+ while (1) {
+ cmd_pipe_mutex_lock();
+ if (done) {
+ cmd_pipe_mutex_unlock();
+ break;
+ }
+ cmd_pipe_mutex_unlock();
+
+ errno = 0;
+ if (ppoll(fds, pollfds, NULL, &signalset) == -1) {
+ if (errno == EINTR)
+ continue;
+ estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ logerr("poll failed: %s", estr);
+ return NULL;
+ }
+
+ if (fds[0].revents & POLLIN) {
+ debug(LOGOPT_ANY, "message pending on control fifo.");
+ handle_cmd_pipe_fifo_message(fds[0].fd);
+ }
+ }
+ destroy_cmd_pipe_fifo();
+ return NULL;
+}
+
+int start_cmd_pipe_handler(void)
+{
+ pthread_t thid;
+ pthread_attr_t attrs;
+ pthread_attr_t *pattrs = &attrs;
+ int status;
+
+ status = pthread_attr_init(pattrs);
+ if (status)
+ pattrs = NULL;
+ else
+ pthread_attr_setdetachstate(pattrs, PTHREAD_CREATE_DETACHED);
+
+ status = pthread_create(&thid, pattrs, cmd_pipe_handler, NULL);
+
+ if (pattrs)
+ pthread_attr_destroy(pattrs);
+
+ if (!status)
+ cmd_pipe_thid = thid;
+
+ return !status;
+}
+
+void finish_cmd_pipe_handler(void)
+{
+ cmd_pipe_mutex_lock();
+ done = 1;
+ pthread_kill(cmd_pipe_thid, SIGPIPE);
+ cmd_pipe_mutex_unlock();
+}
+
static void return_start_status(void *arg)
{
struct startup_cond *sc;

@ -1,125 +0,0 @@
autofs-5.1.8 - add function master_find_mapent_by_devid()
From: Ian Kent <raven@themaw.net>
Add a helper function that can locate an automount given its device id.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/master.c | 28 ++++++++++++++++++++++++++++
include/master.h | 1 +
include/mounts.h | 1 +
lib/mounts.c | 34 ++++++++++++++++++++++++++++++++++
5 files changed, 65 insertions(+)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -124,6 +124,7 @@
- make signal handling consistent.
- fix incorrect print format specifiers in get_pkt().
- eliminate last remaining state_pipe usage.
+- add function master_find_mapent_by_devid().
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
@@ -739,6 +739,34 @@ struct master_mapent *master_find_mapent
return NULL;
}
+struct autofs_point *master_find_mapent_by_devid(struct master *master, dev_t devid)
+{
+ struct autofs_point *ap = NULL;
+ struct list_head *head, *p;
+
+ master_mutex_lock();
+
+ head = &master->mounts;
+ list_for_each(p, head) {
+ struct master_mapent *entry;
+
+ entry = list_entry(p, struct master_mapent, list);
+
+ if (entry->ap->dev == devid) {
+ ap = entry->ap;
+ break;
+ }
+
+ ap = mnt_find_submount_by_devid(&entry->ap->submounts, devid);
+ if (ap)
+ break;
+ }
+
+ master_mutex_unlock();
+
+ return ap;
+}
+
static unsigned int master_partial_match_amd_mapent(struct master *master, const char *path)
{
struct list_head *head, *p;
--- autofs-5.1.7.orig/include/master.h
+++ autofs-5.1.7/include/master.h
@@ -110,6 +110,7 @@ void master_source_lock_cleanup(void *);
void master_source_current_wait(struct master_mapent *);
void master_source_current_signal(struct master_mapent *);
struct master_mapent *master_find_mapent(struct master *, const char *);
+struct autofs_point *master_find_mapent_by_devid(struct master *master, dev_t devid);
struct master_mapent *master_new_mapent(struct master *, const char *, time_t);
void master_add_mapent(struct master *, struct master_mapent *);
void master_remove_mapent(struct master_mapent *);
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/include/mounts.h
@@ -160,6 +160,7 @@ int ext_mount_inuse(const char *);
struct mnt_list *mnts_lookup_mount(const char *mp);
void mnts_put_mount(struct mnt_list *mnt);
struct mnt_list *mnts_find_submount(const char *path);
+struct autofs_point *mnt_find_submount_by_devid(struct list_head *submounts, dev_t devid);
struct mnt_list *mnts_add_submount(struct autofs_point *ap);
void mnts_remove_submount(const char *mp);
struct mnt_list *mnts_find_amdmount(const char *path);
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -1059,6 +1059,40 @@ struct mnt_list *mnts_find_submount(cons
return NULL;
}
+static struct autofs_point *__mnt_find_submount_by_devid(struct list_head *submounts, dev_t devid)
+{
+ struct autofs_point *ap = NULL;
+ struct list_head *p;
+
+ list_for_each(p, submounts) {
+ struct mnt_list *this;
+
+ this = list_entry(p, struct mnt_list, submount);
+
+ if (this->ap->dev == devid) {
+ ap = this->ap;
+ break;
+ }
+
+ ap = mnt_find_submount_by_devid(&this->ap->submounts, devid);
+ if (ap)
+ break;
+ }
+
+ return ap;
+}
+
+struct autofs_point *mnt_find_submount_by_devid(struct list_head *submounts, dev_t devid)
+{
+ struct autofs_point *ap = NULL;
+
+ mnts_hash_mutex_lock();
+ ap = __mnt_find_submount_by_devid(submounts, devid);
+ mnts_hash_mutex_unlock();
+
+ return ap;
+}
+
struct mnt_list *mnts_add_submount(struct autofs_point *ap)
{
struct mnt_list *this;

@ -1,270 +0,0 @@
autofs-5.1.8 - add ioctlfd open helper
From: Ian Kent <raven@themaw.net>
Add an ioctl fd open helper, it simplifies the code in some areas.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1
daemon/direct.c | 25 ++++++++--------
daemon/indirect.c | 9 ++---
include/mounts.h | 3 +
lib/mounts.c | 82 ++++++++++++++++++++++++++++++------------------------
5 files changed, 68 insertions(+), 52 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -152,6 +152,7 @@
- fix possible use after free in handle_mounts_exit().
- make submount cleanup the same as top level mounts.
- add soucre parameter to module functions.
+- add ioctlfd open helper.
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
@@ -121,7 +121,9 @@ int do_umount_autofs_direct(struct autof
}
ioctlfd = me->ioctlfd;
} else {
- ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
+ ioctlfd = open_ioctlfd(ap, me->key, me->dev);
+ if (ioctlfd == -1)
+ return 1;
opened = 1;
}
@@ -317,8 +319,7 @@ int do_mount_autofs_direct(struct autofs
save_ioctlfd = ioctlfd = me->ioctlfd;
if (ioctlfd == -1)
- ops->open(ap->logopt,
- &ioctlfd, me->dev, me->key);
+ ioctlfd = open_ioctlfd(ap, me->key, me->dev);
if (ioctlfd < 0) {
error(ap->logopt,
@@ -416,7 +417,7 @@ int do_mount_autofs_direct(struct autofs
if (ap->mode && (err = chmod(me->key, ap->mode)))
warn(ap->logopt, "failed to change mode of %s", me->key);
- ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key);
+ ioctlfd = open_ioctlfd(ap, me->key, me->dev);
if (ioctlfd < 0) {
crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
goto out_umount;
@@ -540,7 +541,9 @@ int umount_autofs_offset(struct autofs_p
me->key);
return 0;
}
- ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
+ ioctlfd = open_ioctlfd(ap, me->key, me->dev);
+ if (ioctlfd == -1)
+ return 1;
opened = 1;
}
@@ -770,11 +773,9 @@ int mount_autofs_offset(struct autofs_po
me->dev = st.st_dev;
me->ino = st.st_ino;
- ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key);
- if (ioctlfd < 0) {
- crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
+ ioctlfd = open_ioctlfd(ap, me->key, me->dev);
+ if (ioctlfd < 0)
goto out_umount;
- }
ops->timeout(ap->logopt, ioctlfd, timeout);
cache_set_ino_index(me->mc, me);
@@ -1059,9 +1060,9 @@ int handle_packet_expire_direct(struct a
/* Can't expire it if it isn't mounted */
if (me->ioctlfd == -1) {
int ioctlfd;
- ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
+
+ ioctlfd = open_ioctlfd(ap, me->key, me->dev);
if (ioctlfd == -1) {
- crit(ap->logopt, "can't open ioctlfd for %s", me->key);
cache_unlock(mc);
master_source_unlock(ap->entry);
pthread_setcancelstate(state, NULL);
@@ -1355,8 +1356,8 @@ int handle_packet_missing_direct(struct
close(me->ioctlfd);
me->ioctlfd = -1;
}
- ops->open(ap->logopt, &ioctlfd, me->dev, me->key);
+ ioctlfd = open_ioctlfd(ap, me->key, me->dev);
if (ioctlfd == -1) {
cache_unlock(mc);
master_source_unlock(ap->entry);
--- autofs-5.1.7.orig/daemon/indirect.c
+++ autofs-5.1.7/daemon/indirect.c
@@ -124,18 +124,18 @@ static int do_mount_autofs_indirect(stru
"failed to stat mount for autofs path %s", ap->path);
goto out_umount;
}
+ ap->dev = st.st_dev; /* Device number for mount point checks */
if (ap->mode && (err = chmod(ap->path, ap->mode)))
warn(ap->logopt, "failed to change mode of %s", ap->path);
- if (ops->open(ap->logopt, &ap->ioctlfd, st.st_dev, ap->path)) {
+ ap->ioctlfd = open_ioctlfd(ap, ap->path, ap->dev);
+ if (ap->ioctlfd == -1) {
crit(ap->logopt,
"failed to create ioctl fd for autofs path %s", ap->path);
goto out_umount;
}
- ap->dev = st.st_dev; /* Device number for mount point checks */
-
ops->timeout(ap->logopt, ap->ioctlfd, timeout);
notify_mount_result(ap, ap->path, timeout, str_indirect);
@@ -284,8 +284,7 @@ int umount_autofs_indirect(struct autofs
return 0;
}
#endif
- ops->open(ap->logopt,
- &ap->ioctlfd, ap->dev, ap->path);
+ ap->ioctlfd = open_ioctlfd(ap, ap->path, ap->dev);
if (ap->ioctlfd < 0) {
warn(ap->logopt,
"could not recover autofs path %s",
--- autofs-5.1.7.orig/include/mounts.h
+++ autofs-5.1.7/include/mounts.h
@@ -151,6 +151,9 @@ void free_amd_entry_list(struct list_hea
unsigned int query_kproto_ver(void);
unsigned int get_kver_major(void);
unsigned int get_kver_minor(void);
+
+int open_ioctlfd(struct autofs_point *ap, const char *path, dev_t dev);
+
char *make_options_string(char *path, int pipefd,
const char *type, unsigned int flags);
char *make_mnt_name_string(char *path);
--- autofs-5.1.7.orig/lib/mounts.c
+++ autofs-5.1.7/lib/mounts.c
@@ -231,6 +231,32 @@ unsigned int get_kver_minor(void)
return kver.minor;
}
+int open_ioctlfd(struct autofs_point *ap, const char *path, dev_t dev)
+{
+ struct ioctl_ops *ops = get_ioctl_ops();
+ int fd = -1;
+ int error;
+
+ error = ops->open(ap->logopt, &fd, dev, path);
+ if (error == -1) {
+ char buf[MAX_ERR_BUF];
+ int err = errno;
+ char *estr;
+
+ if (errno == ENOENT)
+ return -1;
+
+ estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ error(ap->logopt,
+ "failed to open ioctlfd for %s, error: %s",
+ path, estr);
+ errno = err;
+ return -1;
+ }
+
+ return fd;
+}
+
#ifdef HAVE_MOUNT_NFS
static int extract_version(char *start, struct nfs_mount_vers *vers)
{
@@ -2719,7 +2745,7 @@ static int remount_active_mount(struct a
*ioctlfd = -1;
/* Open failed, no mount present */
- ops->open(ap->logopt, &fd, devid, path);
+ fd = open_ioctlfd(ap, path, devid);
if (fd == -1)
return REMOUNT_OPEN_FAIL;
@@ -2918,10 +2944,9 @@ static int set_mount_catatonic(struct au
{
struct ioctl_ops *ops = get_ioctl_ops();
unsigned int opened = 0;
- char buf[MAX_ERR_BUF];
- char *path;
- int fd = -1;
- int error;
+ const char *path;
+ int fd;
+ int err;
dev_t dev;
path = ap->path;
@@ -2936,44 +2961,31 @@ static int set_mount_catatonic(struct au
else if (me && me->ioctlfd >= 0)
fd = me->ioctlfd;
else {
- error = ops->open(ap->logopt, &fd, dev, path);
- if (error == -1) {
- int err = errno;
- char *estr;
-
- if (errno == ENOENT)
- return 0;
-
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
- error(ap->logopt,
- "failed to open ioctlfd for %s, error: %s",
- path, estr);
- return err;
- }
+ fd = open_ioctlfd(ap, path, dev);
+ if (fd == -1)
+ return (errno == ENOENT ? 0 : errno);
opened = 1;
}
- if (fd >= 0) {
- error = ops->catatonic(ap->logopt, fd);
- if (error == -1) {
- int err = errno;
- char *estr;
+ err = ops->catatonic(ap->logopt, fd);
+ if (err == -1) {
+ char buf[MAX_ERR_BUF];
+ char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
- error(ap->logopt,
- "failed to set %s catatonic, error: %s",
- path, estr);
- if (opened)
- ops->close(ap->logopt, fd);
- return err;
- }
- if (opened)
- ops->close(ap->logopt, fd);
+ err = errno;
+ estr = strerror_r(err, buf, MAX_ERR_BUF);
+ error(ap->logopt,
+ "failed to set %s catatonic, error: %s",
+ path, estr);
+ goto out;
}
debug(ap->logopt, "set %s catatonic", path);
+out:
+ if (opened)
+ ops->close(ap->logopt, fd);
- return 0;
+ return err;
}
static int set_offset_tree_catatonic_work(struct tree_node *n, void *ptr)

@ -1,35 +0,0 @@
autofs-5.1.8 - avoid calling pthread_getspecific() with NULL key_thread_attempt_id
From: Ian Kent <raven@themaw.net>
Don't call pthread_getspecific() if key_thread_attempt_id is NULL in
case the pthread_getspecific() implementation doesn't check for this.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
lib/log.c | 3 +++
2 files changed, 4 insertions(+)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -92,6 +92,7 @@
- simplify cache_add() a little.
- fix use after free in tree_mapent_delete_offset_tree().
- fix memory leak in xdr_exports().
+- avoid calling pthread_getspecific() with NULL key_thread_attempt_id.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/lib/log.c
+++ autofs-5.1.7/lib/log.c
@@ -38,6 +38,9 @@ static char *prepare_attempt_prefix(cons
char buffer[ATTEMPT_ID_SIZE + 1];
char *prefixed_msg = NULL;
+ if (!key_thread_attempt_id)
+ return NULL;
+
attempt_id = pthread_getspecific(key_thread_attempt_id);
if (attempt_id) {
int len = sizeof(buffer) + 1 + strlen(msg) + 1;

@ -1,34 +0,0 @@
autofs-5.1.8 - bailout on rpc systemerror
From: Ian Kent <raven@themaw.net>
If there's a system error (eg. oversize packet received) just give up
since redoing the call would likely end up with the same error.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
lib/rpc_subs.c | 2 ++
2 files changed, 3 insertions(+)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -99,6 +99,7 @@
- make NFS version check flags consistent.
- refactor get_nfs_info().
- also require TCP_REQUESTED when setting NFS port.
+- bailout on rpc systemerror.
25/01/2021 autofs-5.1.7
- make bind mounts propagation slave by default.
--- autofs-5.1.7.orig/lib/rpc_subs.c
+++ autofs-5.1.7/lib/rpc_subs.c
@@ -1200,6 +1200,8 @@ static int rpc_get_exports_proto(struct
info->timeout);
if (status == RPC_SUCCESS)
break;
+ if (status == RPC_SYSTEMERROR)
+ break;
if (++vers_entry > 2)
break;
CLNT_CONTROL(client, CLSET_VERS,

@ -1,144 +0,0 @@
autofs-5.1.8 - change to use printf functions in amd parser
From: Ian Kent <raven@themaw.net>
Change to use the printf(3) functions in the amd parser rather than
string functions. These functions seem to have less overhead and they
are a little more compact.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/parse_amd.c | 45 +++++++++++++++++----------------------------
2 files changed, 18 insertions(+), 28 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -145,6 +145,7 @@
- get rid of strlen call in handle_packet_missing_direct().
- remove redundant stat call in lookup_ghost().
- set mapent dev and ino before adding to index.
+- change to use printf functions in amd parser.
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
@@ -170,11 +170,9 @@ static struct substvar *add_lookup_vars(
if (*key == '/')
strcpy(path, key);
- else {
- strcpy(path, ap->path);
- strcat(path, "/");
- strcat(path, key);
- }
+ else
+ sprintf(path, "%s/%s", ap->path, key);
+
list = macro_addvar(list, "path", 4, path);
me = cache_lookup_distinct(source->mc, lkp_key);
@@ -1067,24 +1065,23 @@ static int do_auto_mount(struct autofs_p
struct amd_entry *entry, unsigned int flags)
{
char target[PATH_MAX + 1];
+ int len;
if (!entry->map_type) {
- if (strlen(entry->fs) > PATH_MAX) {
+ len = snprintf(target, PATH_MAX, "%s", entry->fs);
+ if (len > PATH_MAX) {
error(ap->logopt, MODPREFIX
"error: fs option length is too long");
return 0;
}
- strcpy(target, entry->fs);
} else {
- if (strlen(entry->fs) +
- strlen(entry->map_type) + 5 > PATH_MAX) {
+ len = snprintf(target, PATH_MAX,
+ "%s,amd:%s", entry->map_type, entry->fs);
+ if (len > PATH_MAX) {
error(ap->logopt, MODPREFIX
"error: fs + maptype options length is too long");
return 0;
}
- strcpy(target, entry->map_type);
- strcat(target, ",amd:");
- strcat(target, entry->fs);
}
return do_mount(ap, ap->path,
@@ -1207,17 +1204,15 @@ static int do_nfs_mount(struct autofs_po
char *opts = (entry->opts && *entry->opts) ? entry->opts : NULL;
unsigned int umount = 0;
int ret = 0;
+ int len;
- if (strlen(entry->rhost) + strlen(entry->rfs) + 1 > PATH_MAX) {
+ len = snprintf(target, PATH_MAX, "%s:%s", entry->rhost, entry->rfs);
+ if (len > PATH_MAX) {
error(ap->logopt, MODPREFIX
"error: rhost + rfs options length is too long");
return 1;
}
- strcpy(target, entry->rhost);
- strcat(target, ":");
- strcat(target, entry->rfs);
-
proximity = get_network_proximity(entry->rhost);
if (proximity == PROXIMITY_OTHER && entry->remopts && *entry->remopts)
opts = entry->remopts;
@@ -1319,7 +1314,7 @@ static int do_host_mount(struct autofs_p
*/
if (strcmp(name, entry->rhost)) {
char *target;
- size_t len;
+ int len;
len = ap->len + strlen(entry->rhost) + 2;
target = malloc(len);
@@ -1328,9 +1323,7 @@ static int do_host_mount(struct autofs_p
"failed to alloc target to hosts mount base");
goto out;
}
- strcpy(target, ap->path);
- strcat(target, "/");
- strcat(target, entry->rhost);
+ sprintf(target, "%s/%s", ap->path, entry->rhost);
if (entry->path)
free(entry->path);
entry->path = target;
@@ -1819,7 +1812,7 @@ static void normalize_sublink(unsigned i
struct amd_entry *entry, struct substvar *sv)
{
char *new;
- size_t len;
+ int len;
/* Normalizing sublink requires a non-blank fs option */
if (!*entry->fs)
@@ -1833,9 +1826,7 @@ static void normalize_sublink(unsigned i
"error: couldn't allocate storage for sublink");
return;
}
- strcpy(new, entry->fs);
- strcat(new, "/");
- strcat(new, entry->sublink);
+ sprintf(new, "%s/%s", entry->fs, entry->sublink);
debug(logopt, MODPREFIX
"rfs dequote(\"%.*s\") -> %s",
strlen(entry->sublink), entry->sublink, new);
@@ -1866,9 +1857,7 @@ static void update_prefix(struct autofs_
len = strlen(ap->pref) + strlen(name) + 2;
new = malloc(len);
if (new) {
- strcpy(new, ap->pref);
- strcat(new, name);
- strcat(new, "/");
+ sprintf(new, "%s%s/", ap->pref, name);
entry->pref = new;
}
}

@ -1,56 +0,0 @@
autofs-5.1.8 - continue expire immediately after submount check
From: Ian Kent <raven@themaw.net>
The expire proc for both direct and indirect mounts doesn't immediately
continue after seeing an autofs submount and sending it a notification.
Add the "continue" to avoid some wasted overhead.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/direct.c | 5 ++++-
daemon/indirect.c | 5 ++++-
3 files changed, 9 insertions(+), 2 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -137,6 +137,7 @@
- include addtional log info for mounts.
- fix amd selector function matching.
- get rid entry thid field.
+- continue expire immediately after submount check.
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
@@ -854,8 +854,11 @@ void *expire_proc_direct(void *arg)
* one of them and pass on state change.
*/
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- if (mnt->flags & MNTS_AUTOFS)
+ if (mnt->flags & MNTS_AUTOFS) {
master_notify_submount(ap, mnt->mp, ap->state);
+ pthread_setcancelstate(cur_state, NULL);
+ continue;
+ }
if (me->ioctlfd == -1) {
pthread_setcancelstate(cur_state, NULL);
--- autofs-5.1.7.orig/daemon/indirect.c
+++ autofs-5.1.7/daemon/indirect.c
@@ -392,8 +392,11 @@ void *expire_proc_indirect(void *arg)
* one of them and pass on the state change.
*/
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- if (mnt->flags & MNTS_AUTOFS)
+ if (mnt->flags & MNTS_AUTOFS) {
master_notify_submount(ap, mnt->mp, ap->state);
+ pthread_setcancelstate(cur_state, NULL);
+ continue;
+ }
/* An offset without a real mount, check for manual umount */
if (mnt->flags & MNTS_OFFSET &&

@ -1,32 +0,0 @@
autofs-5.1.8 - coverity fix for invalid access
From: Ian Kent <raven@themaw.net>
Fix invalid access in modules/parse_amd.c:do_host_mount().
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
modules/parse_amd.c | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -106,6 +106,7 @@
- fix missing unlock in sasl_do_kinit_ext_cc().
- fix parse module instance mutex naming.
- serialise lookup module open and reinit.
+- coverity fix for invalid access.
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
@@ -1366,7 +1366,6 @@ static int do_host_mount(struct autofs_p
if (!instance) {
error(ap->logopt, MODPREFIX
"failed to create source instance for hosts map");
- close_lookup(lookup);
goto out;
}
}

@ -1,40 +0,0 @@
autofs-5.1.8 - dont call umount_subtree_mounts() on parent at umount
From: Ian Kent <raven@themaw.net>
There shouldn't be any multi-mount offsets mounted within a submount
because the submount will be a nesting point and offsets will be mounted
within it when it gets mounted and expired before it's umounted.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/automount.c | 7 -------
2 files changed, 1 insertion(+), 7 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -146,6 +146,7 @@
- remove redundant stat call in lookup_ghost().
- set mapent dev and ino before adding to index.
- change to use printf functions in amd parser.
+- dont call umount_subtree_mounts() on parent at umount.
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
@@ -706,13 +706,6 @@ int umount_multi(struct autofs_point *ap
left = 0;
- /*
- * If we are a submount we need to umount any offsets our
- * parent may have mounted over top of us.
- */
- if (ap->submount)
- left += umount_subtree_mounts(ap->parent, path, 1);
-
left += umount_subtree_mounts(ap, path, is_autofs_fs);
/* Delete detritus like unwanted mountpoints and symlinks */

@ -1,47 +0,0 @@
autofs-5.1.8 - don't close lookup at umount
From: Ian Kent <raven@themaw.net>
Since map sources are reference counted they persist beyond autofs
submounts.
Now the map source moudule lookup gets closed at submount umount and
if we are unlucky enough to be using the same map in other submounts
and a lookup is underway at the time of the umount a crash can occur.
To resolve this it's much better to just not close the lookup at
submount umount and rely on the map source free to close the module
lookup and instances when the map source is no longer referenced.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/automount.c | 7 -------
2 files changed, 1 insertion(+), 7 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -116,6 +116,7 @@
- improve handling of ENOENT in sss setautomntent().
- don't immediately call function when waiting.
- fix return status of mount_autofs().
+- don't close lookup at umount.
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
@@ -737,13 +737,6 @@ static int umount_autofs(struct autofs_p
if (ap->state == ST_INIT)
return -1;
- /*
- * Since lookup.c is lazy about closing lookup modules
- * to prevent unneeded opens, we need to clean them up
- * before umount.
- */
- lookup_close_lookup(ap);
-
if (ap->type == LKP_INDIRECT) {
umount_all(ap);
ret = umount_autofs_indirect(ap, root);

@ -1,94 +0,0 @@
autofs-5.1.8 - dont delay expire
From: Ian Kent <raven@themaw.net>
There's a delay on expire of submounts that can be as much as the
expire timeout. This was originally an attempt to reduce re-reading
the map but it can cause very long delays on expire.
So get rid of the delay and allow submounts to expire normally.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
daemon/master.c | 9 ++++-----
daemon/state.c | 30 ++++--------------------------
3 files changed, 9 insertions(+), 31 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -118,6 +118,7 @@
- fix return status of mount_autofs().
- don't close lookup at umount.
- fix deadlock in lookups.
+- dont delay expire.
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
@@ -1250,17 +1250,16 @@ int master_notify_submount(struct autofs
st_wait_task(this->ap, state, 0);
/*
- * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
- * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
- * to ST_READY.
+ * If our submount gets to state ST_SHUTDOWN_PENDING or
+ * ST_SHUTDOWN_FORCE we need to wait until it goes away
+ * or changes to state ST_SHUTDOWN or ST_READY.
*/
st_mutex_lock();
while ((sbmnt = mnts_find_submount(path))) {
struct timespec t = { 0, 300000000 };
struct timespec r;
- if (sbmnt->ap->state != ST_SHUTDOWN &&
- sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
+ if (sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
ret = 0;
mnts_put_mount(sbmnt);
--- autofs-5.1.7.orig/daemon/state.c
+++ autofs-5.1.7/daemon/state.c
@@ -99,36 +99,14 @@ void expire_cleanup(void *arg)
/*
* If we're a submount and we've just pruned or
* expired everything away, try to shut down.
- *
- * Since we use the the fact that a mount will not
- * expire for at least ap->exp_timeout to avoid a
- * mount <-> expire race we need to wait before
- * letting a submount expire away. We also need
- * them to go away fairly quickly so the owner
- * mount expires in a reasonable time. Just skip
- * one expire check after it's no longer busy before
- * allowing it to shutdown.
- *
- * But if this mount point is an amd format map it
- * is better to keep the mount around longer. This
- * is because of the common heavy reuse of maps in
- * amd maps and we want to try and avoid constantly
- * re-reading large maps.
*/
if (ap->submount && !success) {
rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
- if (!rv && idle && ap->submount > 1) {
- struct map_source *map = ap->entry->maps;
-
- if (ap->submount > 4 ||
- !(map->flags & MAP_FLAG_FORMAT_AMD)) {
- next = ST_SHUTDOWN_PENDING;
- break;
- }
+ if (!rv && idle) {
+ next = ST_SHUTDOWN_PENDING;
+ break;
}
- ap->submount++;
- } else if (ap->submount > 1)
- ap->submount = 1;
+ }
if (ap->state == ST_EXPIRE)
conditional_alarm_add(ap, ap->exp_runfreq);

@ -1,46 +0,0 @@
autofs-5.1.8 - dont fail on duplicate host export entry
From: Ian Kent <raven@themaw.net>
If we encounter a duplicate host export entry don't fail, just ignore
it and return the duplicate.
Signed-off-by: Ian Kent <raven@themaw.net>
---
CHANGELOG | 1 +
lib/mounts.c | 6 ++++--
2 files changed, 5 insertions(+), 2 deletions(-)
--- autofs-5.1.7.orig/CHANGELOG
+++ autofs-5.1.7/CHANGELOG
@@ -87,6 +87,7 @@
- fix root offset error handling.
- fix fix root offset error handling.
- fix nonstrict fail handling of last offset mount.
+- dont fail on duplicate offset entry tree add.
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
@@ -1341,7 +1341,7 @@ static struct tree_node *tree_add_node(s
}
if (!eq)
- error(LOGOPT_ANY, "cannot add duplicate entry to tree");
+ return p;
else {
if (eq < 0)
return tree_add_left(p, ptr);
@@ -1515,8 +1515,10 @@ static int tree_host_cmp(struct tree_nod
int eq;
eq = strcmp(exp->dir, n_exp->dir);
- if (!eq)
+ if (!eq) {
+ error(LOGOPT_ANY, "duplicate entry %s ignored", exp->dir);
return 0;
+ }
return (exp_len < n_exp_len) ? -1 : 1;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save