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