|
|
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();
|