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);