autofs-5.1.7 - add mapent tree implementation From: Ian Kent Add a struct mapent basic tree implementation. Signed-off-by: Ian Kent --- CHANGELOG | 1 + include/automount.h | 4 ++++ include/mounts.h | 8 ++++++++ lib/cache.c | 9 ++++++++- lib/mounts.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 74571570..8841f72f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -32,6 +32,7 @@ - remove unused functions cache_dump_multi() and cache_dump_cache(). - add a len field to struct autofs_point. - make tree implementation data independent. +- add mapent tree implementation. 25/01/2021 autofs-5.1.7 - make bind mounts propagation slave by default. diff --git a/include/automount.h b/include/automount.h index 34485859..ebc2007f 100644 --- a/include/automount.h +++ b/include/automount.h @@ -166,10 +166,14 @@ struct mapent { struct mapent_cache *mc; struct map_source *source; /* Need to know owner if we're a multi-mount */ + struct tree_node *mm_root; + struct tree_node *mm_parent; + struct tree_node node; struct mapent *multi; /* Parent nesting point within multi-mount */ struct mapent *parent; char *key; + size_t len; char *mapent; struct stack *stack; time_t age; diff --git a/include/mounts.h b/include/mounts.h index 71d29566..fd7c6183 100644 --- a/include/mounts.h +++ b/include/mounts.h @@ -66,6 +66,13 @@ 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 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) +#define MAPENT_PARENT(p) ((struct tree_node *) ((struct mapent *) p)->mm_parent) +#define MAPENT_SET_ROOT(p, r) { (((struct mapent *) p)->mm_root = (struct tree_node *) r); } +#define MAPENT_SET_PARENT(p, n) { (((struct mapent *) p)->mm_parent = (struct tree_node *) n); } + typedef struct tree_node *(*tree_new_t) (void *ptr); typedef int (*tree_cmp_t) (struct tree_node *n, void *ptr); typedef void (*tree_free_t) (struct tree_node *n); @@ -161,6 +168,7 @@ unsigned int mnts_has_mounted_mounts(struct autofs_point *ap); 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_mapent_root(struct mapent *me); int unlink_mount_tree(struct autofs_point *ap, const char *mp); void free_mnt_list(struct mnt_list *list); int is_mounted(const char *mp, unsigned int type); diff --git a/lib/cache.c b/lib/cache.c index 629c4d0a..6dfaeff5 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -546,17 +546,21 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c struct mapent *me, *existing = NULL; char *pkey, *pent; u_int32_t hashval = hash(key, mc->size); + size_t len; me = (struct mapent *) malloc(sizeof(struct mapent)); if (!me) return CHE_FAIL; - pkey = malloc(strlen(key) + 1); + len = strlen(key); + + pkey = malloc(len + 1); if (!pkey) { free(me); return CHE_FAIL; } me->key = strcpy(pkey, key); + me->len = len; if (mapent) { pent = malloc(strlen(mapent) + 1); @@ -575,6 +579,9 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c me->status = 0; me->mc = mc; me->source = ms; + me->mm_root = NULL; + me->mm_parent = NULL; + INIT_TREE_NODE(&me->node); INIT_LIST_HEAD(&me->ino_index); INIT_LIST_HEAD(&me->multi_list); me->multi = NULL; diff --git a/lib/mounts.c b/lib/mounts.c index a6d1c5a7..40ebf9cf 100644 --- a/lib/mounts.c +++ b/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_mapent_new(void *ptr); +static int tree_mapent_cmp(struct tree_node *n, void *ptr); +static void tree_mapent_free(struct tree_node *n); + +static struct tree_ops mapent_ops = { + .new = tree_mapent_new, + .cmp = tree_mapent_cmp, + .free = tree_mapent_free, +}; +static struct tree_ops *tree_mapent_ops = &mapent_ops; + unsigned int linux_version_code(void) { struct utsname my_utsname; @@ -1431,6 +1442,45 @@ void mnts_put_expire_list(struct list_head *mnts) mnts_hash_mutex_unlock(); } +struct tree_node *tree_mapent_root(struct mapent *me) +{ + return tree_root(tree_mapent_ops, me); +} + +static struct tree_node *tree_mapent_new(void *ptr) +{ + struct tree_node *n = MAPENT_NODE(ptr); + + n->ops = tree_mapent_ops; + n->left = NULL; + n->right = NULL; + + return n; +} + +static int tree_mapent_cmp(struct tree_node *n, void *ptr) +{ + struct mapent *n_me = MAPENT(n); + size_t n_me_len = n_me->len; + struct mapent *me = ptr; + size_t me_len = me->len; + + if (strncmp(me->key, n_me->key, n_me_len) == 0) { + if (me_len < n_me_len) + return -1; + else if (me_len > n_me_len) + return 1; + } + return strcmp(me->key, n_me->key); +} + +static void tree_mapent_free(struct tree_node *n) +{ + n->ops = NULL; + n->left = NULL; + n->right = NULL; +} + /* From glibc decode_name() */ /* Since the values in a line are separated by spaces, a name cannot * contain a space. Therefore some programs encode spaces in names