Blame SOURCES/autofs-5.1.7-make-tree-implementation-data-independent.patch

29d2b9
autofs-5.1.7 - make tree implementation data independent
29d2b9
29d2b9
From: Ian Kent <raven@themaw.net>
29d2b9
29d2b9
Generalise the tree implementation so that it's independent of the
29d2b9
data structure that's used.
29d2b9
29d2b9
Do this by refactoring it into core tree functions and functions
29d2b9
specific to the data structure to be used so that different data
29d2b9
structures can be used when needed by adding an implementation for
29d2b9
the data structure specific functions.
29d2b9
29d2b9
Signed-off-by: Ian Kent <raven@themaw.net>
29d2b9
---
29d2b9
 CHANGELOG        |    1 
29d2b9
 include/mounts.h |   29 +++++++++
29d2b9
 lib/mounts.c     |  174 ++++++++++++++++++++++++++++++++++--------------------
29d2b9
 3 files changed, 140 insertions(+), 64 deletions(-)
29d2b9
29d2b9
diff --git a/CHANGELOG b/CHANGELOG
29d2b9
index 0dae6761..74571570 100644
29d2b9
--- a/CHANGELOG
29d2b9
+++ b/CHANGELOG
29d2b9
@@ -31,6 +31,7 @@
29d2b9
 - add some multi-mount macros.
29d2b9
 - remove unused functions cache_dump_multi() and cache_dump_cache().
29d2b9
 - add a len field to struct autofs_point.
29d2b9
+- make tree implementation data independent.
29d2b9
 
29d2b9
 25/01/2021 autofs-5.1.7
29d2b9
 - make bind mounts propagation slave by default.
29d2b9
diff --git a/include/mounts.h b/include/mounts.h
29d2b9
index ac480c06..71d29566 100644
29d2b9
--- a/include/mounts.h
29d2b9
+++ b/include/mounts.h
29d2b9
@@ -51,10 +51,36 @@ extern const unsigned int t_indirect;
29d2b9
 extern const unsigned int t_direct;
29d2b9
 extern const unsigned int t_offset;
29d2b9
 
29d2b9
+struct mnt_list;
29d2b9
 struct mapent;
29d2b9
 
29d2b9
+struct tree_ops;
29d2b9
+
29d2b9
+struct tree_node {
29d2b9
+	struct tree_ops *ops;
29d2b9
+	struct tree_node *left;
29d2b9
+	struct tree_node *right;
29d2b9
+};
29d2b9
+#define INIT_TREE_NODE(ptr)	((ptr)->ops = NULL, (ptr)->left = NULL, (ptr)->right = NULL)
29d2b9
+
29d2b9
+#define MNT_LIST(n)		(container_of(n, struct mnt_list, node))
29d2b9
+#define MNT_LIST_NODE(ptr)	((struct tree_node *) &((struct mnt_list *) ptr)->node)
29d2b9
+
29d2b9
+typedef struct tree_node *(*tree_new_t) (void *ptr);
29d2b9
+typedef int  (*tree_cmp_t) (struct tree_node *n, void *ptr);
29d2b9
+typedef void (*tree_free_t) (struct tree_node *n);
29d2b9
+
29d2b9
+struct tree_ops {
29d2b9
+	tree_new_t new;
29d2b9
+	tree_cmp_t cmp;
29d2b9
+	tree_free_t free;
29d2b9
+};
29d2b9
+
29d2b9
+typedef int (*tree_work_fn_t) (struct tree_node *n, void *ptr);
29d2b9
+
29d2b9
 struct mnt_list {
29d2b9
 	char *mp;
29d2b9
+	size_t len;
29d2b9
 	unsigned int flags;
29d2b9
 
29d2b9
 	/* Hash of all mounts */
29d2b9
@@ -79,6 +105,9 @@ struct mnt_list {
29d2b9
 	unsigned int amd_cache_opts;
29d2b9
 	struct list_head amdmount;
29d2b9
 
29d2b9
+	/* Tree operations */
29d2b9
+	struct tree_node node;
29d2b9
+
29d2b9
 	/*
29d2b9
 	 * List operations ie. get_mnt_list.
29d2b9
 	 */
29d2b9
diff --git a/lib/mounts.c b/lib/mounts.c
29d2b9
index b478ecb4..a6d1c5a7 100644
29d2b9
--- a/lib/mounts.c
29d2b9
+++ b/lib/mounts.c
29d2b9
@@ -68,6 +68,17 @@ static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
29d2b9
 static DEFINE_HASHTABLE(mnts_hash, MNTS_HASH_BITS);
29d2b9
 static pthread_mutex_t mnts_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
29d2b9
 
29d2b9
+static struct tree_node *tree_mnt_new(void *ptr);
29d2b9
+static int tree_mnt_cmp(struct tree_node *n, void *ptr);
29d2b9
+static void tree_mnt_free(struct tree_node *n);
29d2b9
+
29d2b9
+static struct tree_ops mnt_ops = {
29d2b9
+	.new = tree_mnt_new,
29d2b9
+	.cmp = tree_mnt_cmp,
29d2b9
+	.free = tree_mnt_free,
29d2b9
+};
29d2b9
+static struct tree_ops *tree_mnt_ops = &mnt_ops;
29d2b9
+
29d2b9
 unsigned int linux_version_code(void)
29d2b9
 {
29d2b9
 	struct utsname my_utsname;
29d2b9
@@ -904,6 +915,7 @@ static struct mnt_list *mnts_alloc_mount(const char *mp)
29d2b9
 		this = NULL;
29d2b9
 		goto done;
29d2b9
 	}
29d2b9
+	this->len = strlen(mp);
29d2b9
 
29d2b9
 	this->ref = 1;
29d2b9
 	INIT_HLIST_NODE(&this->hash);
29d2b9
@@ -912,6 +924,7 @@ static struct mnt_list *mnts_alloc_mount(const char *mp)
29d2b9
 	INIT_LIST_HEAD(&this->submount_work);
29d2b9
 	INIT_LIST_HEAD(&this->amdmount);
29d2b9
 	INIT_LIST_HEAD(&this->expire);
29d2b9
+	INIT_TREE_NODE(&this->node);
29d2b9
 done:
29d2b9
 	return this;
29d2b9
 }
29d2b9
@@ -1225,91 +1238,58 @@ done:
29d2b9
 	return has_mounted_mounts;
29d2b9
 }
29d2b9
 
29d2b9
-struct tree_node {
29d2b9
-	struct mnt_list *mnt;
29d2b9
-	struct tree_node *left;
29d2b9
-	struct tree_node *right;
29d2b9
-};
29d2b9
-
29d2b9
-static struct tree_node *tree_new(struct mnt_list *mnt)
29d2b9
+static inline struct tree_node *tree_root(struct tree_ops *ops, void *ptr)
29d2b9
 {
29d2b9
-	struct tree_node *n;
29d2b9
-
29d2b9
-	n = malloc(sizeof(struct tree_node));
29d2b9
-	if (!n)
29d2b9
-		return NULL;
29d2b9
-	memset(n, 0, sizeof(struct tree_node));
29d2b9
-	n->mnt = mnt;
29d2b9
-
29d2b9
-	return n;
29d2b9
-}
29d2b9
-
29d2b9
-static struct tree_node *tree_root(struct mnt_list *mnt)
29d2b9
-{
29d2b9
-	struct tree_node *n;
29d2b9
-
29d2b9
-	n = tree_new(mnt);
29d2b9
-	if (!n) {
29d2b9
-		error(LOGOPT_ANY, "failed to allcate tree root");
29d2b9
-		return NULL;
29d2b9
-	}
29d2b9
-
29d2b9
-	return n;
29d2b9
+	return ops->new(ptr);
29d2b9
 }
29d2b9
 
29d2b9
-static struct tree_node *tree_add_left(struct tree_node *n, struct mnt_list *mnt)
29d2b9
+static struct tree_node *tree_add_left(struct tree_node *n, void *ptr)
29d2b9
 {
29d2b9
 	struct tree_node *new;
29d2b9
 
29d2b9
-	new = tree_new(mnt);
29d2b9
-	if (!new) {
29d2b9
-		error(LOGOPT_ANY, "failed to allcate tree node");
29d2b9
-		return NULL;
29d2b9
-	}
29d2b9
+	new = n->ops->new(ptr);
29d2b9
 	n->left = new;
29d2b9
 
29d2b9
-	return n;
29d2b9
+	return new;
29d2b9
 }
29d2b9
 
29d2b9
-static struct tree_node *tree_add_right(struct tree_node *n, struct mnt_list *mnt)
29d2b9
+static struct tree_node *tree_add_right(struct tree_node *n, void *ptr)
29d2b9
 {
29d2b9
 	struct tree_node *new;
29d2b9
 
29d2b9
-	new = tree_new(mnt);
29d2b9
-	if (!new) {
29d2b9
-		error(LOGOPT_ANY, "failed to allcate tree node");
29d2b9
-		return NULL;
29d2b9
-	}
29d2b9
+	new = n->ops->new(ptr);
29d2b9
 	n->right = new;
29d2b9
 
29d2b9
-	return n;
29d2b9
+	return new;
29d2b9
 }
29d2b9
 
29d2b9
-static struct tree_node *tree_add_node(struct tree_node *root, struct mnt_list *mnt)
29d2b9
+static struct tree_node *tree_add_node(struct tree_node *root, void *ptr)
29d2b9
 {
29d2b9
 	struct tree_node *p, *q;
29d2b9
-	unsigned int mp_len;
29d2b9
-
29d2b9
-	mp_len = strlen(mnt->mp);
29d2b9
+	struct tree_ops *ops = root->ops;
29d2b9
+	int eq;
29d2b9
 
29d2b9
 	q = root;
29d2b9
 	p = root;
29d2b9
 
29d2b9
-	while (q && strcmp(mnt->mp, p->mnt->mp)) {
29d2b9
+	while (q) {
29d2b9
 		p = q;
29d2b9
-		if (mp_len < strlen(p->mnt->mp))
29d2b9
+		eq = ops->cmp(p, ptr);
29d2b9
+		if (!eq)
29d2b9
+			break;
29d2b9
+		if (eq < 0)
29d2b9
 			q = p->left;
29d2b9
 		else
29d2b9
 			q = p->right;
29d2b9
 	}
29d2b9
 
29d2b9
-	if (strcmp(mnt->mp, p->mnt->mp) == 0)
29d2b9
-		error(LOGOPT_ANY, "duplicate entry in mounts list");
29d2b9
+	if (!eq)
29d2b9
+		error(LOGOPT_ANY, "cannot add duplicate entry to tree");
29d2b9
 	else {
29d2b9
-		if (mp_len < strlen(p->mnt->mp))
29d2b9
-			return tree_add_left(p, mnt);
29d2b9
+		if (eq < 0)
29d2b9
+			return tree_add_left(p, ptr);
29d2b9
 		else
29d2b9
-			return tree_add_right(p, mnt);
29d2b9
+			return tree_add_right(p, ptr);
29d2b9
 	}
29d2b9
 
29d2b9
 	return NULL;
29d2b9
@@ -1317,26 +1297,92 @@ static struct tree_node *tree_add_node(struct tree_node *root, struct mnt_list *
29d2b9
 
29d2b9
 static void tree_free(struct tree_node *root)
29d2b9
 {
29d2b9
+	struct tree_ops *ops = root->ops;
29d2b9
+
29d2b9
 	if (root->right)
29d2b9
 		tree_free(root->right);
29d2b9
 	if (root->left)
29d2b9
 		tree_free(root->left);
29d2b9
-	free(root);
29d2b9
+	ops->free(root);
29d2b9
 }
29d2b9
 
29d2b9
-static void tree_traverse(struct tree_node *n, struct list_head *mnts)
29d2b9
+static int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr)
29d2b9
 {
29d2b9
-	if (n->right)
29d2b9
-		tree_traverse(n->right, mnts);
29d2b9
-	list_add_tail(&n->mnt->expire, mnts);
29d2b9
-	if (n->left)
29d2b9
-		tree_traverse(n->left, mnts);
29d2b9
+	int ret;
29d2b9
+
29d2b9
+	if (n->left) {
29d2b9
+		ret = tree_traverse_inorder(n->left, work, ptr);
29d2b9
+		if (!ret)
29d2b9
+			goto done;
29d2b9
+	}
29d2b9
+	ret = work(n, ptr);
29d2b9
+	if (!ret)
29d2b9
+		goto done;
29d2b9
+	if (n->right) {
29d2b9
+		ret = tree_traverse_inorder(n->right, work, ptr);
29d2b9
+		if (!ret)
29d2b9
+			goto done;
29d2b9
+	}
29d2b9
+done:
29d2b9
+	return ret;
29d2b9
+}
29d2b9
+
29d2b9
+static struct tree_node *tree_mnt_root(struct mnt_list *mnt)
29d2b9
+{
29d2b9
+	return tree_root(tree_mnt_ops, mnt);
29d2b9
+}
29d2b9
+
29d2b9
+static struct tree_node *tree_mnt_new(void *ptr)
29d2b9
+{
29d2b9
+	struct tree_node *n = MNT_LIST_NODE(ptr);
29d2b9
+
29d2b9
+	n->ops = tree_mnt_ops;
29d2b9
+	n->left = NULL;
29d2b9
+	n->right = NULL;
29d2b9
+
29d2b9
+	return n;
29d2b9
+}
29d2b9
+
29d2b9
+static int tree_mnt_cmp(struct tree_node *n, void *ptr)
29d2b9
+{
29d2b9
+	struct mnt_list *n_mnt = MNT_LIST(n);
29d2b9
+	size_t n_mnt_len = n_mnt->len;
29d2b9
+	struct mnt_list *mnt = ptr;
29d2b9
+	size_t mnt_len = mnt->len;
29d2b9
+	int eq;
29d2b9
+
29d2b9
+	eq = strcmp(mnt->mp, n_mnt->mp);
29d2b9
+	if (!eq)
29d2b9
+		return 0;
29d2b9
+	return (mnt_len < n_mnt_len) ? -1 : 1;
29d2b9
+}
29d2b9
+
29d2b9
+static void tree_mnt_free(struct tree_node *n)
29d2b9
+{
29d2b9
+	n->ops = NULL;
29d2b9
+	n->left = NULL;
29d2b9
+	n->right = NULL;
29d2b9
+}
29d2b9
+
29d2b9
+static int tree_mnt_expire_list_work(struct tree_node *n, void *ptr)
29d2b9
+{
29d2b9
+	struct mnt_list *mnt = MNT_LIST(n);
29d2b9
+	struct list_head *mnts = ptr;
29d2b9
+
29d2b9
+	/* The expire of the root offset of an offset tree is the same
29d2b9
+	 * as expiring the offset tree root itself (if theree is a root
29d2b9
+	 * offset).
29d2b9
+	 */
29d2b9
+	if (mnt->mp[mnt->len - 1] != '/')
29d2b9
+		list_add(&mnt->expire, mnts);
29d2b9
+
29d2b9
+	return 1;
29d2b9
 }
29d2b9
 
29d2b9
 void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
29d2b9
 {
29d2b9
-	struct mnt_list *mnt;
29d2b9
 	struct tree_node *tree = NULL;
29d2b9
+	struct mnt_list *mnt;
29d2b9
 
29d2b9
 	mnts_hash_mutex_lock();
29d2b9
 	if (list_empty(&ap->mounts))
29d2b9
@@ -1351,7 +1397,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
29d2b9
 		__mnts_get_mount(mnt);
29d2b9
 
29d2b9
 		if (!tree) {
29d2b9
-			tree = tree_root(mnt);
29d2b9
+			tree = tree_mnt_root(mnt);
29d2b9
 			if (!tree) {
29d2b9
 				error(LOGOPT_ANY, "failed to create expire tree root");
29d2b9
 				goto done;
29d2b9
@@ -1367,7 +1413,7 @@ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
29d2b9
 		}
29d2b9
 	}
29d2b9
 
29d2b9
-	tree_traverse(tree, mnts);
29d2b9
+	tree_traverse_inorder(tree, tree_mnt_expire_list_work, mnts);
29d2b9
 	tree_free(tree);
29d2b9
 done:
29d2b9
 	mnts_hash_mutex_unlock();