Blob Blame History Raw
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);