Blame SOURCES/autofs-5.0.9-amd-lookup-add-handling-of-amd-maps-in-the-master-map.patch

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