|
|
29d2b9 |
autofs-5.1.7 - fix offset entries order
|
|
|
29d2b9 |
|
|
|
29d2b9 |
From: Ian Kent <raven@themaw.net>
|
|
|
29d2b9 |
|
|
|
29d2b9 |
While it's rare it's possible that a mapent entry might not have
|
|
|
29d2b9 |
it's offsets in shortest to longest path order.
|
|
|
29d2b9 |
|
|
|
29d2b9 |
If this happens adding an entry to the mapent tree can result in
|
|
|
29d2b9 |
an incorrect tree topology that doesn't work. That's because adding
|
|
|
29d2b9 |
tree entries ensures that nodes in a sub-tree are placed below the
|
|
|
29d2b9 |
containing node so the containing node must be present for that to
|
|
|
29d2b9 |
work. This topology is critical to the performance of map entries
|
|
|
29d2b9 |
that have a very large number of offsets such as an NFS server with
|
|
|
29d2b9 |
many exports.
|
|
|
29d2b9 |
|
|
|
29d2b9 |
There's no other choice but make a traversal after the offset entries
|
|
|
29d2b9 |
have all been added to create the mapent tree.
|
|
|
29d2b9 |
|
|
|
29d2b9 |
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
|
29d2b9 |
---
|
|
|
29d2b9 |
CHANGELOG | 1
|
|
|
29d2b9 |
include/automount.h | 1
|
|
|
29d2b9 |
lib/cache.c | 1
|
|
|
29d2b9 |
modules/parse_sun.c | 74 +++++++++++++++++++++++++++++++++++++++++-----------
|
|
|
29d2b9 |
4 files changed, 62 insertions(+), 15 deletions(-)
|
|
|
29d2b9 |
|
|
|
29d2b9 |
--- autofs-5.1.7.orig/CHANGELOG
|
|
|
29d2b9 |
+++ autofs-5.1.7/CHANGELOG
|
|
|
29d2b9 |
@@ -69,6 +69,7 @@
|
|
|
29d2b9 |
- fix dangling symlink creation if nis support is not available.
|
|
|
29d2b9 |
- fix amd section mounts map reload.
|
|
|
29d2b9 |
- fix amd hosts mount expire.
|
|
|
29d2b9 |
+- fix offset entries order.
|
|
|
29d2b9 |
|
|
|
29d2b9 |
25/01/2021 autofs-5.1.7
|
|
|
29d2b9 |
- make bind mounts propagation slave by default.
|
|
|
29d2b9 |
--- autofs-5.1.7.orig/include/automount.h
|
|
|
29d2b9 |
+++ autofs-5.1.7/include/automount.h
|
|
|
29d2b9 |
@@ -169,6 +169,7 @@ struct mapent {
|
|
|
29d2b9 |
/* Parent nesting point within multi-mount */
|
|
|
29d2b9 |
struct tree_node *mm_parent;
|
|
|
29d2b9 |
struct tree_node node;
|
|
|
29d2b9 |
+ struct list_head work;
|
|
|
29d2b9 |
char *key;
|
|
|
29d2b9 |
size_t len;
|
|
|
29d2b9 |
char *mapent;
|
|
|
29d2b9 |
--- autofs-5.1.7.orig/lib/cache.c
|
|
|
29d2b9 |
+++ autofs-5.1.7/lib/cache.c
|
|
|
29d2b9 |
@@ -559,6 +559,7 @@ int cache_add(struct mapent_cache *mc, s
|
|
|
29d2b9 |
me->mm_parent = NULL;
|
|
|
29d2b9 |
INIT_TREE_NODE(&me->node);
|
|
|
29d2b9 |
INIT_LIST_HEAD(&me->ino_index);
|
|
|
29d2b9 |
+ INIT_LIST_HEAD(&me->work);
|
|
|
29d2b9 |
me->ioctlfd = -1;
|
|
|
29d2b9 |
me->dev = (dev_t) -1;
|
|
|
29d2b9 |
me->ino = (ino_t) -1;
|
|
|
29d2b9 |
--- autofs-5.1.7.orig/modules/parse_sun.c
|
|
|
29d2b9 |
+++ autofs-5.1.7/modules/parse_sun.c
|
|
|
29d2b9 |
@@ -789,14 +789,15 @@ static int check_is_multi(const char *ma
|
|
|
29d2b9 |
|
|
|
29d2b9 |
static int
|
|
|
29d2b9 |
update_offset_entry(struct autofs_point *ap,
|
|
|
29d2b9 |
- struct mapent_cache *mc, const char *name,
|
|
|
29d2b9 |
- const char *m_root, int m_root_len,
|
|
|
29d2b9 |
+ struct mapent_cache *mc, struct list_head *offsets,
|
|
|
29d2b9 |
+ const char *name, const char *m_root, int m_root_len,
|
|
|
29d2b9 |
const char *m_offset, const char *myoptions,
|
|
|
29d2b9 |
const char *loc, time_t age)
|
|
|
29d2b9 |
{
|
|
|
29d2b9 |
char m_key[PATH_MAX + 1];
|
|
|
29d2b9 |
char m_mapent[MAPENT_MAX_LEN + 1];
|
|
|
29d2b9 |
int o_len, m_key_len, m_options_len, m_mapent_len;
|
|
|
29d2b9 |
+ struct mapent *me;
|
|
|
29d2b9 |
int ret;
|
|
|
29d2b9 |
|
|
|
29d2b9 |
memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
|
|
|
29d2b9 |
@@ -862,8 +863,29 @@ update_offset_entry(struct autofs_point
|
|
|
29d2b9 |
cache_writelock(mc);
|
|
|
29d2b9 |
ret = cache_update_offset(mc, name, m_key, m_mapent, age);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
- if (!tree_mapent_add_node(mc, name, m_key))
|
|
|
29d2b9 |
- error(ap->logopt, "failed to add offset %s to tree", m_key);
|
|
|
29d2b9 |
+ me = cache_lookup_distinct(mc, m_key);
|
|
|
29d2b9 |
+ if (me && list_empty(&me->work)) {
|
|
|
29d2b9 |
+ struct list_head *last;
|
|
|
29d2b9 |
+
|
|
|
29d2b9 |
+ /* Offset entries really need to be in shortest to
|
|
|
29d2b9 |
+ * longest path order. If not and the list of offsets
|
|
|
29d2b9 |
+ * is large there will be a performace hit.
|
|
|
29d2b9 |
+ */
|
|
|
29d2b9 |
+ list_for_each_prev(last, offsets) {
|
|
|
29d2b9 |
+ struct mapent *this;
|
|
|
29d2b9 |
+
|
|
|
29d2b9 |
+ this = list_entry(last, struct mapent, work);
|
|
|
29d2b9 |
+ if (me->len >= this->len) {
|
|
|
29d2b9 |
+ if (last->next == offsets)
|
|
|
29d2b9 |
+ list_add_tail(&me->work, offsets);
|
|
|
29d2b9 |
+ else
|
|
|
29d2b9 |
+ list_add_tail(&me->work, last);
|
|
|
29d2b9 |
+ break;
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
+ if (list_empty(&me->work))
|
|
|
29d2b9 |
+ list_add(&me->work, offsets);
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
cache_unlock(mc);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
if (ret == CHE_DUPLICATE) {
|
|
|
29d2b9 |
@@ -1209,6 +1231,25 @@ static char *do_expandsunent(const char
|
|
|
29d2b9 |
return mapent;
|
|
|
29d2b9 |
}
|
|
|
29d2b9 |
|
|
|
29d2b9 |
+static void cleanup_offset_entries(struct autofs_point *ap,
|
|
|
29d2b9 |
+ struct mapent_cache *mc,
|
|
|
29d2b9 |
+ struct list_head *offsets)
|
|
|
29d2b9 |
+{
|
|
|
29d2b9 |
+ struct mapent *me, *tmp;
|
|
|
29d2b9 |
+ int ret;
|
|
|
29d2b9 |
+
|
|
|
29d2b9 |
+ if (list_empty(offsets))
|
|
|
29d2b9 |
+ return;
|
|
|
29d2b9 |
+ cache_writelock(mc);
|
|
|
29d2b9 |
+ list_for_each_entry_safe(me, tmp, offsets, work) {
|
|
|
29d2b9 |
+ list_del(&me->work);
|
|
|
29d2b9 |
+ ret = cache_delete(mc, me->key);
|
|
|
29d2b9 |
+ if (ret != CHE_OK)
|
|
|
29d2b9 |
+ crit(ap->logopt, "failed to delete offset %s", me->key);
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
+ cache_unlock(mc);
|
|
|
29d2b9 |
+}
|
|
|
29d2b9 |
+
|
|
|
29d2b9 |
/*
|
|
|
29d2b9 |
* syntax is:
|
|
|
29d2b9 |
* [-options] location [location] ...
|
|
|
29d2b9 |
@@ -1228,7 +1269,8 @@ int parse_mount(struct autofs_point *ap,
|
|
|
29d2b9 |
char buf[MAX_ERR_BUF];
|
|
|
29d2b9 |
struct map_source *source;
|
|
|
29d2b9 |
struct mapent_cache *mc;
|
|
|
29d2b9 |
- struct mapent *me;
|
|
|
29d2b9 |
+ struct mapent *me, *oe, *tmp;
|
|
|
29d2b9 |
+ LIST_HEAD(offsets);
|
|
|
29d2b9 |
char *pmapent, *options;
|
|
|
29d2b9 |
const char *p;
|
|
|
29d2b9 |
int mapent_len, rv = 0;
|
|
|
29d2b9 |
@@ -1444,9 +1486,7 @@ dont_expand:
|
|
|
29d2b9 |
|
|
|
29d2b9 |
if (!m_offset) {
|
|
|
29d2b9 |
warn(ap->logopt, MODPREFIX "null path or out of memory");
|
|
|
29d2b9 |
- cache_writelock(mc);
|
|
|
29d2b9 |
- tree_mapent_delete_offsets(mc, name);
|
|
|
29d2b9 |
- cache_unlock(mc);
|
|
|
29d2b9 |
+ cleanup_offset_entries(ap, mc, &offsets);
|
|
|
29d2b9 |
free(options);
|
|
|
29d2b9 |
free(pmapent);
|
|
|
29d2b9 |
pthread_setcancelstate(cur_state, NULL);
|
|
|
29d2b9 |
@@ -1461,9 +1501,7 @@ dont_expand:
|
|
|
29d2b9 |
|
|
|
29d2b9 |
l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
|
|
|
29d2b9 |
if (!l) {
|
|
|
29d2b9 |
- cache_writelock(mc);
|
|
|
29d2b9 |
- tree_mapent_delete_offsets(mc, name);
|
|
|
29d2b9 |
- cache_unlock(mc);
|
|
|
29d2b9 |
+ cleanup_offset_entries(ap, mc, &offsets);
|
|
|
29d2b9 |
free(m_offset);
|
|
|
29d2b9 |
free(options);
|
|
|
29d2b9 |
free(pmapent);
|
|
|
29d2b9 |
@@ -1474,15 +1512,13 @@ dont_expand:
|
|
|
29d2b9 |
p += l;
|
|
|
29d2b9 |
p = skipspace(p);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
- status = update_offset_entry(ap, mc,
|
|
|
29d2b9 |
+ status = update_offset_entry(ap, mc, &offsets,
|
|
|
29d2b9 |
name, m_root, m_root_len,
|
|
|
29d2b9 |
m_offset, myoptions, loc, age);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
if (status != CHE_OK) {
|
|
|
29d2b9 |
warn(ap->logopt, MODPREFIX "error adding multi-mount");
|
|
|
29d2b9 |
- cache_writelock(mc);
|
|
|
29d2b9 |
- tree_mapent_delete_offsets(mc, name);
|
|
|
29d2b9 |
- cache_unlock(mc);
|
|
|
29d2b9 |
+ cleanup_offset_entries(ap, mc, &offsets);
|
|
|
29d2b9 |
free(m_offset);
|
|
|
29d2b9 |
free(options);
|
|
|
29d2b9 |
free(pmapent);
|
|
|
29d2b9 |
@@ -1499,6 +1535,14 @@ dont_expand:
|
|
|
29d2b9 |
free(myoptions);
|
|
|
29d2b9 |
} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
|
|
|
29d2b9 |
|
|
|
29d2b9 |
+ cache_writelock(mc);
|
|
|
29d2b9 |
+ list_for_each_entry_safe(oe, tmp, &offsets, work) {
|
|
|
29d2b9 |
+ if (!tree_mapent_add_node(mc, name, oe->key))
|
|
|
29d2b9 |
+ error(ap->logopt, "failed to add offset %s to tree", oe->key);
|
|
|
29d2b9 |
+ list_del_init(&oe->work);
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
+ cache_unlock(mc);
|
|
|
29d2b9 |
+
|
|
|
29d2b9 |
rv = mount_subtree(ap, mc, name, NULL, options, ctxt);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
free(options);
|