- add changes for bugs 1965870, 1965863 and 1966380.

This commit is contained in:
Ian Kent 2021-06-14 18:51:16 +08:00
parent 059c556a9d
commit 36b0802122
8 changed files with 946 additions and 1 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@
Summary: A tool for automatically mounting and unmounting filesystems
Name: autofs
Version: 5.1.7
Release: 15%{?dist}
Release: 16%{?dist}
Epoch: 1
License: GPLv2+
Source: https://www.kernel.org/pub/linux/daemons/autofs/v5/autofs-%{version}-2.tar.gz
@ -90,6 +90,14 @@ Patch68: autofs-5.1.7-fix-dangling-symlink-creation-if-nis-support-is-not-availa
Patch69: autofs-5.1.7-fix-amd-section-mounts-map-reload.patch
Patch70: autofs-5.1.7-fix-amd-hosts-mount-expire.patch
Patch71: autofs-5.1.7-fix-offset-entries-order.patch
Patch72: autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch
Patch73: autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch
Patch74: autofs-5.1.7-fix-hosts-map-offset-order.patch
Patch75: autofs-5.1.7-fix-direct-mount-deadlock.patch
Patch76: autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch
Patch77: autofs-5.1.7-add-missing-description-of-null-map-option.patch
%if %{with_systemd}
BuildRequires: systemd-units
BuildRequires: systemd-devel
@ -225,6 +233,13 @@ echo %{version}-%{release} > .version
%patch68 -p1
%patch69 -p1
%patch70 -p1
%patch71 -p1
%patch72 -p1
%patch73 -p1
%patch74 -p1
%patch75 -p1
%patch76 -p1
%patch77 -p1
%build
LDFLAGS=-Wl,-z,now
@ -333,6 +348,19 @@ fi
%dir /etc/auto.master.d
%changelog
* Mon Jun 14 2021 Ian Kent <ikent@redhat.com> - 1:5.1.7-16
- bz1965870 - autofs: regression in offset ordering
- 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.
- fix direct mount deadlock.
- bz1965863 - A recent Coverity change can cause an infinit loop on map reload
- fix lookup_prune_one_cache() refactoring change.
- bz1966380 - auto.master manpage doesn't mention -null or other built-in maps
- add missing desciption of null map option.
- Resolves: rhbz#1965870 rhbz#1965863 rhbz#1966380
* Tue May 11 2021 Ian Kent <ikent@redhat.com> - 1:5.1.7-15
- bz1942371 - Drop nis support from autofs
- fix dangling symlink creation if nis support is not available