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

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