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.4.orig/CHANGELOG
+++ autofs-5.1.4/CHANGELOG
@@ -71,6 +71,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.
xx/xx/2018 autofs-5.1.5
- fix flag file permission.
--- autofs-5.1.4.orig/include/automount.h
+++ autofs-5.1.4/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.4.orig/include/mounts.h
+++ autofs-5.1.4/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.4.orig/include/rpc_subs.h
+++ autofs-5.1.4/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.4.orig/lib/mounts.c
+++ autofs-5.1.4/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.4.orig/modules/lookup_hosts.c
+++ autofs-5.1.4/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);