Blame SOURCES/autofs-5.0.9-amd-lookup-add-external-mounts-tracking-functions.patch

4d476f
autofs-5.0.9 - amd lookup add external mounts tracking functions
4d476f
4d476f
From: Ian Kent <raven@themaw.net>
4d476f
4d476f
Amd automounts can use what's called a sublink option. Using this
4d476f
option a single containing mount can be specified and symlinks
4d476f
that point to directories within the mount created instead of a
4d476f
mount for every directory.
4d476f
4d476f
In some cases this can greatly reduce the number of mounts needed
4d476f
for a map but complicates automounting when using an "in-place"
4d476f
automounter such as autofs.
4d476f
4d476f
Clearly we can't perform the mount and create symlinks within it
4d476f
so we must us a mount lookaside directory like amd. Those external
4d476f
mounts also need to be managed.
4d476f
4d476f
This patch adds functions to maintain a list of these mounts (much
4d476f
like a reference counter) so we know if an external mount is present
4d476f
and if it's time to umount it.
4d476f
---
4d476f
 include/mounts.h |    2 +
4d476f
 lib/mounts.c     |  132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4d476f
 2 files changed, 134 insertions(+)
4d476f
4d476f
diff --git a/include/mounts.h b/include/mounts.h
4d476f
index c2f92ec..3bef086 100644
4d476f
--- a/include/mounts.h
4d476f
+++ b/include/mounts.h
4d476f
@@ -93,6 +93,8 @@ unsigned int get_kver_major(void);
4d476f
 unsigned int get_kver_minor(void);
4d476f
 char *make_options_string(char *path, int kernel_pipefd, const char *extra);
4d476f
 char *make_mnt_name_string(char *path);
4d476f
+int ext_mount_add(struct list_head *, const char *);
4d476f
+int ext_mount_remove(struct list_head *, const char *);
4d476f
 struct mnt_list *get_mnt_list(const char *table, const char *path, int include);
4d476f
 struct mnt_list *reverse_mnt_list(struct mnt_list *list);
4d476f
 void free_mnt_list(struct mnt_list *list);
4d476f
diff --git a/lib/mounts.c b/lib/mounts.c
4d476f
index 868dcb1..aea6691 100644
4d476f
--- a/lib/mounts.c
4d476f
+++ b/lib/mounts.c
4d476f
@@ -46,6 +46,17 @@ static const char mnt_name_template[]      = "automount(pid%u)";
4d476f
 static struct kernel_mod_version kver = {0, 0};
4d476f
 static const char kver_options_template[]  = "fd=%d,pgrp=%u,minproto=3,maxproto=5";
4d476f
 
4d476f
+#define EXT_MOUNTS_HASH_SIZE    50
4d476f
+
4d476f
+struct ext_mount {
4d476f
+	char *mountpoint;
4d476f
+	struct list_head mount;
4d476f
+	struct list_head mounts;
4d476f
+};
4d476f
+static struct list_head ext_mounts_hash[EXT_MOUNTS_HASH_SIZE];
4d476f
+static unsigned int ext_mounts_hash_init_done = 0;
4d476f
+static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
4d476f
+
4d476f
 unsigned int linux_version_code(void)
4d476f
 {
4d476f
 	struct utsname my_utsname;
4d476f
@@ -422,6 +433,127 @@ char *make_mnt_name_string(char *path)
4d476f
 	return mnt_name;
4d476f
 }
4d476f
 
4d476f
+static void ext_mounts_hash_init(void)
4d476f
+{
4d476f
+	int i;
4d476f
+	for (i = 0; i < EXT_MOUNTS_HASH_SIZE; i++)
4d476f
+		INIT_LIST_HEAD(&ext_mounts_hash[i]);
4d476f
+	ext_mounts_hash_init_done = 1;
4d476f
+}
4d476f
+
4d476f
+static struct ext_mount *ext_mount_lookup(const char *mountpoint)
4d476f
+{
4d476f
+	u_int32_t hval = hash(mountpoint, EXT_MOUNTS_HASH_SIZE);
4d476f
+	struct list_head *p, *head;
4d476f
+
4d476f
+	if (!ext_mounts_hash_init_done)
4d476f
+		ext_mounts_hash_init();
4d476f
+
4d476f
+	if (list_empty(&ext_mounts_hash[hval]))
4d476f
+		return NULL;
4d476f
+
4d476f
+	head = &ext_mounts_hash[hval];
4d476f
+	list_for_each(p, head) {
4d476f
+		struct ext_mount *this = list_entry(p, struct ext_mount, mount);
4d476f
+		if (!strcmp(this->mountpoint, mountpoint))
4d476f
+			return this;
4d476f
+	}
4d476f
+	return NULL;
4d476f
+}
4d476f
+
4d476f
+int ext_mount_add(struct list_head *entry, const char *path)
4d476f
+{
4d476f
+	struct ext_mount *em;
4d476f
+	char *auto_dir;
4d476f
+	u_int32_t hval;
4d476f
+	int ret = 0;
4d476f
+
4d476f
+	/* Not a mount in the external mount directory */
4d476f
+	auto_dir = conf_amd_get_auto_dir();
4d476f
+	if (strncmp(path, auto_dir, strlen(auto_dir))) {
4d476f
+		free(auto_dir);
4d476f
+		return 0;
4d476f
+	}
4d476f
+	free(auto_dir);
4d476f
+
4d476f
+	pthread_mutex_lock(&ext_mount_hash_mutex);
4d476f
+
4d476f
+	em = ext_mount_lookup(path);
4d476f
+	if (em) {
4d476f
+		struct list_head *p, *head;
4d476f
+		head = &em->mounts;
4d476f
+		list_for_each(p, head) {
4d476f
+			if (p == entry)
4d476f
+				goto done;
4d476f
+		}
4d476f
+		list_add_tail(entry, &em->mounts);
4d476f
+		ret = 1;
4d476f
+		goto done;
4d476f
+	}
4d476f
+
4d476f
+	em = malloc(sizeof(struct ext_mount));
4d476f
+	if (!em) {
4d476f
+		ret = -1;
4d476f
+		goto done;
4d476f
+	}
4d476f
+
4d476f
+	em->mountpoint = strdup(path);
4d476f
+	if (!em->mountpoint) {
4d476f
+		free(em);
4d476f
+		ret = -1;
4d476f
+		goto done;
4d476f
+	}
4d476f
+	INIT_LIST_HEAD(&em->mount);
4d476f
+	INIT_LIST_HEAD(&em->mounts);
4d476f
+
4d476f
+	hval = hash(path, EXT_MOUNTS_HASH_SIZE);
4d476f
+	list_add_tail(&em->mount, &ext_mounts_hash[hval]);
4d476f
+
4d476f
+	list_add_tail(entry, &em->mounts);
4d476f
+
4d476f
+	ret = 1;
4d476f
+done:
4d476f
+	pthread_mutex_unlock(&ext_mount_hash_mutex);
4d476f
+	return ret;
4d476f
+}
4d476f
+
4d476f
+int ext_mount_remove(struct list_head *entry, const char *path)
4d476f
+{
4d476f
+	struct ext_mount *em;
4d476f
+	char *auto_dir;
4d476f
+	int ret = 0;
4d476f
+
4d476f
+	/* Not a mount in the external mount directory */
4d476f
+	auto_dir = conf_amd_get_auto_dir();
4d476f
+	if (strncmp(path, auto_dir, strlen(auto_dir))) {
4d476f
+		free(auto_dir);
4d476f
+		return 0;
4d476f
+	}
4d476f
+	free(auto_dir);
4d476f
+
4d476f
+	pthread_mutex_lock(&ext_mount_hash_mutex);
4d476f
+
4d476f
+	em = ext_mount_lookup(path);
4d476f
+	if (!em)
4d476f
+		goto done;
4d476f
+
4d476f
+	list_del_init(entry);
4d476f
+
4d476f
+	if (!list_empty(&em->mounts))
4d476f
+		goto done;
4d476f
+	else {
4d476f
+		list_del_init(&em->mount);
4d476f
+		if (list_empty(&em->mount)) {
4d476f
+			free(em->mountpoint);
4d476f
+			free(em);
4d476f
+		}
4d476f
+		ret = 1;
4d476f
+	}
4d476f
+done:
4d476f
+	pthread_mutex_unlock(&ext_mount_hash_mutex);
4d476f
+	return ret;
4d476f
+}
4d476f
+
4d476f
 /*
4d476f
  * Get list of mounts under path in longest->shortest order
4d476f
  */