|
|
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 |
*/
|