Blob Blame History Raw
autofs-5.1.6 - add a hash index to mnt_list

From: Ian Kent <raven@themaw.net>

Add a hash index (and utility functions) to struct mnt_list.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG        |    1 
 include/mounts.h |    8 +++
 lib/mounts.c     |  135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 144 insertions(+)

--- autofs-5.1.4.orig/CHANGELOG
+++ autofs-5.1.4/CHANGELOG
@@ -121,6 +121,7 @@ xx/xx/2018 autofs-5.1.5
 - 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.
 
 19/12/2017 autofs-5.1.4
 - fix spec file url.
--- autofs-5.1.4.orig/include/mounts.h
+++ autofs-5.1.4/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);
--- autofs-5.1.4.orig/lib/mounts.c
+++ autofs-5.1.4/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