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

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