autofs-5.1.6 - add a hash index to mnt_list From: Ian Kent Add a hash index (and utility functions) to struct mnt_list. Signed-off-by: Ian Kent --- CHANGELOG | 1 include/mounts.h | 8 +++ lib/mounts.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index e62aacbc..f91f2f29 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -55,6 +55,7 @@ xx/xx/2020 autofs-5.1.7 - change mountpoint to mp in struct ext_mount. - make external mounts independent of amd_entry. - make external mounts use simpler hashtable. +- add a hash index to mnt_list. 07/10/2019 autofs-5.1.6 - support strictexpire mount option. diff --git a/include/mounts.h b/include/mounts.h index 4e01f697..a5a46f19 100644 --- a/include/mounts.h +++ b/include/mounts.h @@ -54,10 +54,16 @@ struct mapent; struct mnt_list { char *mp; unsigned int flags; + + /* Hash of all mounts */ + struct hlist_node hash; + unsigned int ref; + /* * List operations ie. get_mnt_list. */ struct mnt_list *next; + /* * Tree operations ie. tree_make_tree, * tree_get_mnt_list etc. @@ -100,6 +106,8 @@ char *make_mnt_name_string(char *path); int ext_mount_add(const char *, const char *); int ext_mount_remove(const char *); int ext_mount_inuse(const char *); +struct mnt_list *mnts_lookup_mount(const char *mp); +void mnts_put_mount(struct mnt_list *mnt); struct mnt_list *get_mnt_list(const char *path, int include); int unlink_mount_tree(struct autofs_point *ap, const char *mp); void free_mnt_list(struct mnt_list *list); diff --git a/lib/mounts.c b/lib/mounts.c index a2bb99c3..79915d34 100644 --- a/lib/mounts.c +++ b/lib/mounts.c @@ -63,6 +63,11 @@ struct ext_mount { static DEFINE_HASHTABLE(ext_mounts_hash, EXT_MOUNTS_HASH_BITS); static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER; +#define MNTS_HASH_BITS 7 + +static DEFINE_HASHTABLE(mnts_hash, MNTS_HASH_BITS); +static pthread_mutex_t mnts_hash_mutex = PTHREAD_MUTEX_INITIALIZER; + unsigned int linux_version_code(void) { struct utsname my_utsname; @@ -832,6 +837,136 @@ done: return ret; } +static void mnts_hash_mutex_lock(void) +{ + int status = pthread_mutex_lock(&mnts_hash_mutex); + if (status) + fatal(status); +} + +static void mnts_hash_mutex_unlock(void) +{ + int status = pthread_mutex_unlock(&mnts_hash_mutex); + if (status) + fatal(status); +} + +static struct mnt_list *mnts_lookup(const char *mp) +{ + uint32_t hval = hash(mp, HASH_SIZE(mnts_hash)); + struct mnt_list *this; + + if (hlist_empty(&mnts_hash[hval])) + return NULL; + + hlist_for_each_entry(this, &mnts_hash[hval], hash) { + if (!strcmp(this->mp, mp) && this->ref) + return this; + } + + return NULL; +} + +static struct mnt_list *mnts_alloc_mount(const char *mp) +{ + struct mnt_list *this; + + this = malloc(sizeof(*this)); + if (!this) + goto done; + memset(this, 0, sizeof(*this)); + + this->mp = strdup(mp); + if (!this->mp) { + free(this); + this = NULL; + goto done; + } + + this->ref = 1; + INIT_HLIST_NODE(&this->hash); +done: + return this; +} + +static void __mnts_get_mount(struct mnt_list *mnt) +{ + mnt->ref++; +} + +static void __mnts_put_mount(struct mnt_list *mnt) +{ + mnt->ref--; + if (!mnt->ref) { + hash_del(&mnt->hash); + free(mnt->mp); + free(mnt); + } +} + +static struct mnt_list *mnts_new_mount(const char *mp) +{ + struct mnt_list *this; + + this = mnts_lookup(mp); + if (this) { + __mnts_get_mount(this); + goto done; + } + + this = mnts_alloc_mount(mp); + if (!this) + goto done; + + hash_add_str(mnts_hash, &this->hash, this->mp); +done: + return this; +} + +static struct mnt_list *mnts_get_mount(const char *mp) +{ + struct mnt_list *this; + + this = mnts_lookup(mp); + if (this) { + __mnts_get_mount(this); + return this; + } + + return mnts_new_mount(mp); +} + +static struct mnt_list *__mnts_lookup_mount(const char *mp) +{ + struct mnt_list *this; + + this = mnts_lookup(mp); + if (this) + __mnts_get_mount(this); + + return this; +} + +struct mnt_list *mnts_lookup_mount(const char *mp) +{ + struct mnt_list *this; + + mnts_hash_mutex_lock(); + this = __mnts_lookup_mount(mp); + mnts_hash_mutex_unlock(); + + return this; +} + +void mnts_put_mount(struct mnt_list *mnt) +{ + if (!mnt) + return; + mnts_hash_mutex_lock(); + __mnts_put_mount(mnt); + mnts_hash_mutex_unlock(); +} + /* 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