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.
362 lines
11 KiB
362 lines
11 KiB
7 years ago
|
autofs-5.0.9 - amd lookup add handling of amd maps in the master map
|
||
|
|
||
|
From: Ian Kent <raven@themaw.net>
|
||
|
|
||
|
|
||
|
---
|
||
|
daemon/automount.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++-
|
||
|
include/automount.h | 1 +
|
||
|
include/master.h | 2 +
|
||
|
lib/master.c | 44 +++++++++++++++++++++++++++
|
||
|
lib/master_parse.y | 23 ++++++++++++--
|
||
|
lib/master_tok.l | 2 +
|
||
|
lib/parse_subs.c | 1 +
|
||
|
modules/mount_autofs.c | 24 +++++++++++++++
|
||
|
modules/parse_amd.c | 12 +++++++
|
||
|
9 files changed, 182 insertions(+), 6 deletions(-)
|
||
|
|
||
|
diff --git a/daemon/automount.c b/daemon/automount.c
|
||
|
index fd5a19b..0ba3580 100644
|
||
|
--- a/daemon/automount.c
|
||
|
+++ b/daemon/automount.c
|
||
|
@@ -512,6 +512,9 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
|
||
|
left++;
|
||
|
}
|
||
|
cache_multi_unlock(me->parent);
|
||
|
+ if (ap->entry->maps &&
|
||
|
+ (ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD))
|
||
|
+ cache_pop_mapent(me);
|
||
|
pthread_setcancelstate(cur_state, NULL);
|
||
|
}
|
||
|
|
||
|
@@ -525,13 +528,36 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
|
||
|
* it already to ensure it's ok to remove any offset triggers.
|
||
|
*/
|
||
|
if (!is_mm_root && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
|
||
|
+ struct amd_entry *entry;
|
||
|
debug(ap->logopt, "unmounting dir = %s", path);
|
||
|
if (umount_ent(ap, path)) {
|
||
|
warn(ap->logopt, "could not umount dir %s", path);
|
||
|
left++;
|
||
|
+ goto done;
|
||
|
}
|
||
|
- }
|
||
|
|
||
|
+ /* Check for an external mount and umount if possible */
|
||
|
+ mounts_mutex_lock(ap);
|
||
|
+ entry = __master_find_amdmount(ap, path);
|
||
|
+ if (!entry) {
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ list_del(&entry->entries);
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
+ if (ext_mount_remove(&entry->ext_mount, entry->fs)) {
|
||
|
+ if (umount_ent(ap, entry->fs))
|
||
|
+ debug(ap->logopt,
|
||
|
+ "failed to umount external mount %s",
|
||
|
+ entry->fs);
|
||
|
+ else
|
||
|
+ debug(ap->logopt,
|
||
|
+ "umounted external mount %s",
|
||
|
+ entry->fs);
|
||
|
+ }
|
||
|
+ free_amd_entry(entry);
|
||
|
+ }
|
||
|
+done:
|
||
|
return left;
|
||
|
}
|
||
|
|
||
|
@@ -540,10 +566,55 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
|
||
|
int umount_multi(struct autofs_point *ap, const char *path, int incl)
|
||
|
{
|
||
|
int is_autofs_fs;
|
||
|
+ struct stat st;
|
||
|
int left;
|
||
|
|
||
|
debug(ap->logopt, "path %s incl %d", path, incl);
|
||
|
|
||
|
+ if (lstat(path, &st)) {
|
||
|
+ warn(ap->logopt,
|
||
|
+ "failed to stat mount point directory %s", path);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* if this is a symlink we can handle it now */
|
||
|
+ if (S_ISLNK(st.st_mode)) {
|
||
|
+ struct amd_entry *entry;
|
||
|
+ if (st.st_dev != ap->dev) {
|
||
|
+ crit(ap->logopt,
|
||
|
+ "symlink %s has the wrong device, "
|
||
|
+ "possible race condition", path);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+ debug(ap->logopt, "removing symlink %s", path);
|
||
|
+ if (unlink(path)) {
|
||
|
+ error(ap->logopt,
|
||
|
+ "failed to remove symlink %s", path);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+ /* Check for an external mount and attempt umount if needed */
|
||
|
+ mounts_mutex_lock(ap);
|
||
|
+ entry = __master_find_amdmount(ap, path);
|
||
|
+ if (!entry) {
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ list_del(&entry->entries);
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
+ if (ext_mount_remove(&entry->ext_mount, entry->fs)) {
|
||
|
+ if (umount_ent(ap, entry->fs))
|
||
|
+ debug(ap->logopt,
|
||
|
+ "failed to umount external mount %s",
|
||
|
+ entry->fs);
|
||
|
+ else
|
||
|
+ debug(ap->logopt,
|
||
|
+ "umounted external mount %s",
|
||
|
+ entry->fs);
|
||
|
+ }
|
||
|
+ free_amd_entry(entry);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
is_autofs_fs = 0;
|
||
|
if (master_find_submount(ap, path))
|
||
|
is_autofs_fs = 1;
|
||
|
@@ -1475,9 +1546,15 @@ static void handle_mounts_cleanup(void *arg)
|
||
|
clean = 1;
|
||
|
|
||
|
if (submount) {
|
||
|
+ struct amd_entry *am;
|
||
|
/* We are finishing up */
|
||
|
ap->parent->submnt_count--;
|
||
|
list_del_init(&ap->mounts);
|
||
|
+ am = __master_find_amdmount(ap->parent, ap->path);
|
||
|
+ if (am) {
|
||
|
+ list_del_init(&am->entries);
|
||
|
+ free_amd_entry(am);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
/* Don't signal the handler if we have already done so */
|
||
|
diff --git a/include/automount.h b/include/automount.h
|
||
|
index 615efcc..37133fe 100644
|
||
|
--- a/include/automount.h
|
||
|
+++ b/include/automount.h
|
||
|
@@ -510,6 +510,7 @@ struct autofs_point {
|
||
|
struct autofs_point *parent; /* Owner of mounts list for submount */
|
||
|
pthread_mutex_t mounts_mutex; /* Protect mount lists */
|
||
|
struct list_head mounts; /* List of autofs mounts at current level */
|
||
|
+ struct list_head amdmounts; /* List of non submount amd mounts */
|
||
|
unsigned int submount; /* Is this a submount */
|
||
|
unsigned int shutdown; /* Shutdown notification */
|
||
|
unsigned int submnt_count; /* Number of submounts */
|
||
|
diff --git a/include/master.h b/include/master.h
|
||
|
index 8833ddf..bcc8eeb 100644
|
||
|
--- a/include/master.h
|
||
|
+++ b/include/master.h
|
||
|
@@ -104,6 +104,8 @@ void master_source_current_signal(struct master_mapent *);
|
||
|
struct master_mapent *master_find_mapent(struct master *, const char *);
|
||
|
struct autofs_point *__master_find_submount(struct autofs_point *, const char *);
|
||
|
struct autofs_point *master_find_submount(struct autofs_point *, const char *);
|
||
|
+struct amd_entry *__master_find_amdmount(struct autofs_point *, const char *);
|
||
|
+struct amd_entry *master_find_amdmount(struct autofs_point *, const char *);
|
||
|
struct master_mapent *master_new_mapent(struct master *, const char *, time_t);
|
||
|
void master_add_mapent(struct master *, struct master_mapent *);
|
||
|
void master_remove_mapent(struct master_mapent *);
|
||
|
diff --git a/lib/master.c b/lib/master.c
|
||
|
index df4aef6..5e4ab51 100644
|
||
|
--- a/lib/master.c
|
||
|
+++ b/lib/master.c
|
||
|
@@ -120,6 +120,7 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
|
||
|
ap->submount = submount;
|
||
|
INIT_LIST_HEAD(&ap->mounts);
|
||
|
INIT_LIST_HEAD(&ap->submounts);
|
||
|
+ INIT_LIST_HEAD(&ap->amdmounts);
|
||
|
ap->shutdown = 0;
|
||
|
|
||
|
status = pthread_mutex_init(&ap->mounts_mutex, NULL);
|
||
|
@@ -136,11 +137,26 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
|
||
|
|
||
|
void master_free_autofs_point(struct autofs_point *ap)
|
||
|
{
|
||
|
+ struct list_head *p, *head;
|
||
|
int status;
|
||
|
|
||
|
if (!ap)
|
||
|
return;
|
||
|
|
||
|
+ mounts_mutex_lock(ap);
|
||
|
+ head = &ap->amdmounts;
|
||
|
+ p = head->next;
|
||
|
+ while (p != head) {
|
||
|
+ struct amd_entry *entry = list_entry(p, struct amd_entry, entries);
|
||
|
+ p = p->next;
|
||
|
+ if (!list_empty(&entry->ext_mount))
|
||
|
+ ext_mount_remove(&entry->ext_mount, entry->fs);
|
||
|
+ if (!list_empty(&entry->entries))
|
||
|
+ list_del(&entry->entries);
|
||
|
+ free(entry);
|
||
|
+ }
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
+
|
||
|
status = pthread_mutex_destroy(&ap->mounts_mutex);
|
||
|
if (status)
|
||
|
fatal(status);
|
||
|
@@ -694,6 +710,34 @@ struct autofs_point *master_find_submount(struct autofs_point *ap, const char *p
|
||
|
return submount;
|
||
|
}
|
||
|
|
||
|
+struct amd_entry *__master_find_amdmount(struct autofs_point *ap, const char *path)
|
||
|
+{
|
||
|
+ struct list_head *head, *p;
|
||
|
+
|
||
|
+ head = &ap->amdmounts;
|
||
|
+ list_for_each(p, head) {
|
||
|
+ struct amd_entry *entry;
|
||
|
+
|
||
|
+ entry = list_entry(p, struct amd_entry, entries);
|
||
|
+
|
||
|
+ if (!strcmp(entry->path, path))
|
||
|
+ return entry;
|
||
|
+ }
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+struct amd_entry *master_find_amdmount(struct autofs_point *ap, const char *path)
|
||
|
+{
|
||
|
+ struct amd_entry *entry;
|
||
|
+
|
||
|
+ mounts_mutex_lock(ap);
|
||
|
+ entry = __master_find_amdmount(ap, path);
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
+
|
||
|
+ return entry;
|
||
|
+}
|
||
|
+
|
||
|
struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
|
||
|
{
|
||
|
struct master_mapent *entry;
|
||
|
diff --git a/lib/master_parse.y b/lib/master_parse.y
|
||
|
index 11caf5b..03aedf7 100644
|
||
|
--- a/lib/master_parse.y
|
||
|
+++ b/lib/master_parse.y
|
||
|
@@ -790,12 +790,29 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ if (!format) {
|
||
|
+ if (conf_amd_mount_section_exists(path))
|
||
|
+ format = strdup("amd");
|
||
|
+ }
|
||
|
+
|
||
|
+ if (format && !strcmp(format, "amd")) {
|
||
|
+ unsigned int loglevel = conf_amd_get_log_options();
|
||
|
+ if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
|
||
|
+ logopt = LOGOPT_DEBUG;
|
||
|
+ else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
|
||
|
+ logopt = LOGOPT_VERBOSE;
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
if (timeout < 0) {
|
||
|
/*
|
||
|
- * If no timeout is given get the timout from first
|
||
|
- * map (if it exists).
|
||
|
+ * If no timeout is given get the timout from the
|
||
|
+ * first map (if it exists) or the config for amd
|
||
|
+ * maps.
|
||
|
*/
|
||
|
- if (entry->maps)
|
||
|
+ if (format && !strcmp(format, "amd"))
|
||
|
+ timeout = conf_amd_get_dismount_interval(path);
|
||
|
+ else if (entry->maps)
|
||
|
timeout = entry->maps->exp_timeout;
|
||
|
else
|
||
|
timeout = default_timeout;
|
||
|
diff --git a/lib/master_tok.l b/lib/master_tok.l
|
||
|
index a55cc76..d43c1dd 100644
|
||
|
--- a/lib/master_tok.l
|
||
|
+++ b/lib/master_tok.l
|
||
|
@@ -119,7 +119,7 @@ DNNAMESTR2 ([[:alnum:]_.\-]+)
|
||
|
INTMAP (-hosts|-null)
|
||
|
MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
|
||
|
MULTISEP ([\-]{2}[[:blank:]]+)
|
||
|
-MTYPE ((file|program|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?(:{OPTWS}|{WS}))
|
||
|
+MTYPE ((file|program|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
|
||
|
|
||
|
|
||
|
OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
|
||
|
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
|
||
|
index de5319f..421d18c 100644
|
||
|
--- a/lib/parse_subs.c
|
||
|
+++ b/lib/parse_subs.c
|
||
|
@@ -109,6 +109,7 @@ static unsigned int map_type_count = sizeof(map_type)/sizeof(struct types);
|
||
|
static struct types format_type[] = {
|
||
|
{ "sun", 3 },
|
||
|
{ "hesiod", 6 },
|
||
|
+ { "amd", 3},
|
||
|
};
|
||
|
static unsigned int format_type_count = sizeof(format_type)/sizeof(struct types);
|
||
|
|
||
|
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
|
||
|
index 61aec70..ab5a8e3 100644
|
||
|
--- a/modules/mount_autofs.c
|
||
|
+++ b/modules/mount_autofs.c
|
||
|
@@ -203,6 +203,30 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
|
||
|
}
|
||
|
if (info->map)
|
||
|
argv[0] = info->map;
|
||
|
+ /*
|
||
|
+ * If the parent map format is amd and the format isn't
|
||
|
+ * specified in the map entry set it from the parent map
|
||
|
+ * source.
|
||
|
+ */
|
||
|
+ if (!info->format && ap->entry->maps) {
|
||
|
+ struct map_source *s = ap->entry->maps;
|
||
|
+ /*
|
||
|
+ * For amd maps, if the format and source type aren't
|
||
|
+ * specified try and set them from the parent.
|
||
|
+ */
|
||
|
+ if (s->flags & MAP_FLAG_FORMAT_AMD) {
|
||
|
+ info->format = strdup("amd");
|
||
|
+ if (!info->format)
|
||
|
+ warn(ap->logopt, MODPREFIX
|
||
|
+ "failed to set amd map format");
|
||
|
+ if (!info->type && s->type) {
|
||
|
+ info->type = strdup(s->type);
|
||
|
+ if (!info->type)
|
||
|
+ warn(ap->logopt, MODPREFIX
|
||
|
+ "failed to set amd map type");
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
|
||
|
if (options) {
|
||
|
p = options;
|
||
|
diff --git a/modules/parse_amd.c b/modules/parse_amd.c
|
||
|
index 5d8617e..4322479 100644
|
||
|
--- a/modules/parse_amd.c
|
||
|
+++ b/modules/parse_amd.c
|
||
|
@@ -1563,8 +1563,18 @@ int parse_mount(struct autofs_point *ap, const char *name,
|
||
|
dequote_entry(ap, this);
|
||
|
|
||
|
rv = amd_mount(ap, name, this, source, sv, flags, ctxt);
|
||
|
- if (!rv)
|
||
|
+ mounts_mutex_lock(ap);
|
||
|
+ if (!rv) {
|
||
|
+ /* Add to the parent list of mounts */
|
||
|
+ list_add_tail(&this->entries, &ap->amdmounts);
|
||
|
+ /* Mounted, leave it on the parent list */
|
||
|
+ list_del_init(&this->list);
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
break;
|
||
|
+ }
|
||
|
+ /* Not mounted, remove it from the parent list */
|
||
|
+ list_del_init(&this->entries);
|
||
|
+ mounts_mutex_unlock(ap);
|
||
|
}
|
||
|
free_amd_entry(cur_defaults);
|
||
|
|