diff --git a/SOURCES/autofs-5.1.4-remove-unused-function-dump_master.patch b/SOURCES/autofs-5.1.4-remove-unused-function-dump_master.patch
new file mode 100644
index 0000000..17e7c78
--- /dev/null
+++ b/SOURCES/autofs-5.1.4-remove-unused-function-dump_master.patch
@@ -0,0 +1,37 @@
+autofs-5.1.4 - remove unused function dump_master()
+
+From: Ian Kent <raven@themaw.net>
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/master.c |   11 -----------
+ 2 files changed, 1 insertion(+), 11 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -112,6 +112,7 @@ xx/xx/2018 autofs-5.1.5
+ - dont prune offset map entries.
+ - simplify sss source stale check.
+ - use defines for expire type.
++- remove unused function dump_master().
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/lib/master.c
++++ autofs-5.1.4/lib/master.c
+@@ -1971,14 +1971,3 @@ int master_kill(struct master *master)
+ 
+ 	return 1;
+ }
+-
+-void dump_master(struct master *master)
+-{
+-	struct list_head *p, *head;
+-
+-	head = &master->mounts;
+-	list_for_each(p, head) {
+-		struct master_mapent *this = list_entry(p, struct master_mapent, list);
+-		logmsg("path %s", this->path);
+-	}
+-}
diff --git a/SOURCES/autofs-5.1.4-use-defines-for-expire-type.patch b/SOURCES/autofs-5.1.4-use-defines-for-expire-type.patch
new file mode 100644
index 0000000..6592ac4
--- /dev/null
+++ b/SOURCES/autofs-5.1.4-use-defines-for-expire-type.patch
@@ -0,0 +1,100 @@
+autofs-5.1.4 - use defines for expire type
+
+From: Ian Kent <raven@themaw.net>
+
+The kernel defines for expire type such as an immediate expire
+shoule be used to clearify what is being requested.
+
+AUTOFS_EXP_IMMEDIATE corresponds to a SIGUSR1 prune operation.
+
+AUTOFS_EXP_FORCE corresponds to an expire type not yet implemented in
+the kernel, a SIGUSR2 forced expire. Define it in our internal autofs
+kernel include file, the kernel will ignore it if it doesn't support it.
+
+AUTOFS_EXP_LEAVES is no longer used in autofs version 5.
+
+Finally add a define AUTOFS_EXP_NORMAL to indicate we're perfoming a
+normal expire.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                |    1 +
+ daemon/state.c           |    8 ++++----
+ include/linux/auto_fs4.h |    6 ++++--
+ include/state.h          |    2 +-
+ 4 files changed, 10 insertions(+), 7 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -111,6 +111,7 @@ xx/xx/2018 autofs-5.1.5
+ - use a valid timeout in lookup_prune_one_cache().
+ - dont prune offset map entries.
+ - simplify sss source stale check.
++- use defines for expire type.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/state.c
++++ autofs-5.1.4/daemon/state.c
+@@ -634,7 +634,7 @@ static unsigned int st_prepare_shutdown(
+ 	ap->state = ST_SHUTDOWN_PENDING;
+ 
+ 	/* Unmount everything */
+-	exp = expire_proc(ap, 1);
++	exp = expire_proc(ap, AUTOFS_EXP_IMMEDIATE);
+ 	switch (exp) {
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+@@ -660,7 +660,7 @@ static unsigned int st_force_shutdown(st
+ 	ap->state = ST_SHUTDOWN_FORCE;
+ 
+ 	/* Unmount everything */
+-	exp = expire_proc(ap, 1);
++	exp = expire_proc(ap, AUTOFS_EXP_FORCE | AUTOFS_EXP_IMMEDIATE);
+ 	switch (exp) {
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+@@ -695,7 +695,7 @@ static unsigned int st_prune(struct auto
+ 	assert(ap->state == ST_READY);
+ 	ap->state = ST_PRUNE;
+ 
+-	switch (expire_proc(ap, 1)) {
++	switch (expire_proc(ap, AUTOFS_EXP_IMMEDIATE)) {
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+ 		if (!ap->submount)
+@@ -716,7 +716,7 @@ static unsigned int st_expire(struct aut
+ 	assert(ap->state == ST_READY);
+ 	ap->state = ST_EXPIRE;
+ 
+-	switch (expire_proc(ap, 0)) {
++	switch (expire_proc(ap, AUTOFS_EXP_NORMAL)) {
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+ 		if (!ap->submount)
+--- autofs-5.1.4.orig/include/linux/auto_fs4.h
++++ autofs-5.1.4/include/linux/auto_fs4.h
+@@ -27,8 +27,10 @@
+ #define AUTOFS_PROTO_SUBVERSION		2
+ 
+ /* Mask for expire behaviour */
+-#define AUTOFS_EXP_IMMEDIATE		1
+-#define AUTOFS_EXP_LEAVES		2
++#define AUTOFS_EXP_NORMAL		0x00
++#define AUTOFS_EXP_IMMEDIATE		0x01
++#define AUTOFS_EXP_LEAVES		0x02
++#define AUTOFS_EXP_FORCE		0x04
+ 
+ #define AUTOFS_TYPE_ANY			0U
+ #define AUTOFS_TYPE_INDIRECT		1U
+--- autofs-5.1.4.orig/include/state.h
++++ autofs-5.1.4/include/state.h
+@@ -55,7 +55,7 @@ struct expire_args {
+ 	unsigned int signaled;
+ 	struct autofs_point *ap; /* autofs mount we are working on */
+ 	enum states state;	 /* State prune or expire */
+-	unsigned int how;	 /* Normal, immediate expire ? */
++	unsigned int how;	 /* Normal, immediate, forced expire ? */
+ 	int status;		 /* Return status */
+ };
+ 
diff --git a/SOURCES/autofs-5.1.5-fix-additional-typing-errors.patch b/SOURCES/autofs-5.1.5-fix-additional-typing-errors.patch
new file mode 100644
index 0000000..c1669c4
--- /dev/null
+++ b/SOURCES/autofs-5.1.5-fix-additional-typing-errors.patch
@@ -0,0 +1,383 @@
+autofs-5.1.5 - fix additional typing errors
+
+From: Andreas P <nurgrak@gmail.com>
+
+Fix some more typing errors.
+imk: added changes discussed on mailing list.
+
+Signed-off-by: Andreas P <nurgrak@gmail.com>
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                      |    1 +
+ INSTALL                        |    2 +-
+ README.replicated-server       |    2 +-
+ man/auto.master.5.in           |   14 +++++++-------
+ man/autofs.5                   |    9 ++++-----
+ man/autofs.conf.5.in           |   29 ++++++++++++++---------------
+ man/autofs_ldap_auth.conf.5.in |    2 +-
+ man/automount.8                |    2 +-
+ modules/lookup_ldap.c          |    4 ++--
+ modules/replicated.c           |    4 ++--
+ redhat/autofs.conf.default.in  |   14 +++++++-------
+ redhat/autofs.sysconfig        |    2 +-
+ samples/autofs.conf.default.in |   10 +++++-----
+ 13 files changed, 47 insertions(+), 48 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -113,6 +113,7 @@ xx/xx/2018 autofs-5.1.5
+ - simplify sss source stale check.
+ - use defines for expire type.
+ - remove unused function dump_master().
++- fix additional typing errors.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/INSTALL
++++ autofs-5.1.4/INSTALL
+@@ -119,7 +119,7 @@ For example, Fedora Core 4 kernel packag
+ would use the 2.6.12 patch because it applies the 2.6.12 release
+ candidate revision 6 patch. But the autofs patch doesn't apply
+ because the rpm also applies a patch somewhere that changes one
+-area the the patch also changes but this change is not present
++area the patch also changes but this change is not present
+ in the 2.6.12 release kernel.
+ 
+ On the other hand, Fedora Core 3 kernel 2.6.12-1.1381_FC3
+--- autofs-5.1.4.orig/README.replicated-server
++++ autofs-5.1.4/README.replicated-server
+@@ -34,7 +34,7 @@ the following selection rules.
+      - PROXIMITY_OTHER, host is on a network not directlty
+        reachable through a local interface.
+   
+-2) NFS version and protocol is selected by caclculating the largest
++2) NFS version and protocol is selected by calculating the largest
+    number of hosts supporting an NFS version and protocol that
+    have the closest proximity. These hosts are added to the list
+    in response time order. Hosts may have a corresponding weight
+--- autofs-5.1.4.orig/man/auto.master.5.in
++++ autofs-5.1.4/man/auto.master.5.in
+@@ -211,12 +211,12 @@ due to application accesses triggered by
+ This option allows mount propagation of bind mounts to be set to
+ either \fIslave\fP or \fIprivate\fP. This option may be needed when using
+ multi-mounts that have bind mounts that bind to a file system that is
+-propagation shared. This is becuase the bind mount will have the same
++propagation shared. This is because the bind mount will have the same
+ properties as its target which causes problems for offset mounts. When
+ this happens an unwanted offset mount is propagated back to the target
+ file system resulting in a deadlock when attempting to access the offset.
+-This option is a an autofs pseudo mount option that can be used in the
+-master map only. By default bind mounts will inherit the mount propagation
++This option is an autofs pseudo mount option that can be used in the
++master map only. By default, bind mounts will inherit the mount propagation
+ of the target file system.
+ .TP
+ .I "\-r, \-\-random-multimount-selection"
+@@ -261,7 +261,7 @@ accessing /net/myserver will mount expor
+ /net/myserver.
+ .P
+ NOTE: mounts done from a hosts map will be mounted with the "nosuid,nodev,intr" options
+-unless overridden by explicily specifying the "suid", "dev" or "nointr" options in the
++unless overridden by explicitly specifying the "suid", "dev" or "nointr" options in the
+ master map entry.
+ .SH LDAP MAPS
+ If the map type \fBldap\fP is specified the mapname is of the form
+@@ -277,7 +277,7 @@ configuration, in which case the map nam
+ .P
+ If no schema is set in the autofs configuration then autofs will check
+ each of the commonly used schema for a valid entry and if one is found
+-it will used for subsequent lookups.
++it will be used for subsequent lookups.
+ .P
+ There are three common schemas in use:
+ .TP
+@@ -351,7 +351,7 @@ connection is to be used then the client
+ locations must also be configured within the LDAP client.
+ .P
+ In OpenLDAP these may be configured in the \fBldap.conf\fP file or in the
+-per-user configuration. For example it may be sensible to use the system
++per-user configuration. For example, it may be sensible to use the system
+ wide configuration for the location of the Certificate Authority certificate
+ and set the location of the client certificate and private key
+ in the per-user configuration. The location of these files and the configuration
+@@ -399,5 +399,5 @@ configuration will be used to locate the
+ .BR autofs_ldap_auth.conf (5).
+ .SH AUTHOR
+ This manual page was written by Christoph Lameter <chris@waterf.org>,
+-for the Debian GNU/Linux system.  Edited by <hpa@transmeta.com> and
++for the Debian GNU/Linux system. Edited by <hpa@transmeta.com> and
+ Ian Kent <raven@themaw.net> .
+--- autofs-5.1.4.orig/man/autofs.5
++++ autofs-5.1.4/man/autofs.5
+@@ -64,7 +64,6 @@ can't be mounted.
+ .br
+ is used to make the weight the sole factor in selecting a server when multiple
+ servers are present in a map entry.
+-and
+ .TP
+ .B \-no-use-weight-only
+ .br
+@@ -192,7 +191,7 @@ SHOST	Short hostname (domain part remove
+ .sp
+ If a program map is used these standard environment variables will have
+ a prefix of "AUTOFS_" to prevent interpreted languages like python from
+-being able to load and execute arbitray code from a user home directory.
++being able to load and execute arbitrary code from a user home directory.
+ .RE
+ .sp
+ Additional entries can be defined with the \-Dvariable=Value map-option to
+@@ -293,10 +292,10 @@ may be negated with the \fB!\fP.
+ For a \fBlocation\fP to be selected for a mount attempt all of its \fBselectors\fP
+ must evaluate to true. If a \fBlocation\fP is selected for a mount attempt
+ and succeeds the lookup is completed and returns success. If the mount
+-attempt fails the proceedure continues with the next \fBlocation\fP until
++attempt fails the procedure continues with the next \fBlocation\fP until
+ they have all been tried.
+ 
+-In addition some \fBselectors\fP take no argumenets, some one argument
++In addition, some \fBselectors\fP take no arguments, some one argument
+ and others optionally take two arguments.
+ 
+ The \fBselectors\fP that take no arguments are:
+@@ -584,7 +583,7 @@ In the first line we have an NFS remote
+ another nfs mount for the exported directory /work/util from host zeus.
+ This would be mounted on /test/util.
+ 
+-Finally we have an example of the use of the \fBsublink\fP option. In
++Finally, we have an example of the use of the \fBsublink\fP option. In
+ this case the filesystem bilbo:/shared would be mounted on a path
+ external the automount directory (under the direcory given by
+ configuration option auto_dir) and the path /test/local either
+--- autofs-5.1.4.orig/man/autofs.conf.5.in
++++ autofs-5.1.4/man/autofs.conf.5.in
+@@ -91,7 +91,7 @@ set default log level "none", "verbose"
+ .B force_standard_program_map_env
+ .br
+ override the use of a prefix with standard environment variables when a
+-program map is executed. Since program maps are run as the privileded
++program map is executed. Since program maps are run as the privileged
+ user setting these standard environment variables opens automount(8) to
+ potential user privilege escalation when the program map is written in a
+ language that can load components from, for example, a user home directory
+@@ -110,16 +110,15 @@ and a direct map with 8000 entries would
+ containing an average of 8 entries, which should be acceptable.
+ 
+ However, if excessive CPU usage is observed during automount lookups
+-increasing this option can reduce the CPU overhead considerably becuase
++increasing this option can reduce the CPU overhead considerably because
+ it reduces the length of the search chains.
+ 
+ Note that the number of entries in a map doesn't necessarily relate
+ to the number of entries used in the map entry cache.
+ 
+-There are three distinct cases, direct maps and indirect maps that
+-use the "browse" option must be read in their entirity at program
+-start so, in these two cases the map size does retate directly to
+-the map entry cache size.
++There are two distinct cases where the map hash table can make a
++significant difference, direct maps and indirect maps that use the
++"browse" option.
+ 
+ For indirect maps that do not use the "browse" option entries are
+ added to the map entry cache at lookup so the number of active cache
+@@ -174,7 +173,7 @@ by the number of retries that would be u
+ .B use_mount_request_log_id
+ .br
+ Set whether to use a mount request log id so that log entries for specific
+-mount requests can be easily identified in logs that have multiple conncurrent
++mount requests can be easily identified in logs that have multiple concurrent
+ requests. Default is don't use mount request log ids.
+ .SS LDAP Configuration
+ .P
+@@ -183,7 +182,7 @@ Configuration settings available are:
+ .B ldap_timeout
+ .br
+ Set the network response timeout (default 8).
+-Set timeout value for the synchronous API  calls. The default is the LDAP
++Set timeout value for the synchronous API calls. The default is the LDAP
+ library default of an infinite timeout.
+ .TP
+ .B ldap_network_timeout
+@@ -323,7 +322,7 @@ cleaned on re-load, which is done when m
+ so these configuration entries are not used by autofs. An
+ exception to this is the case where the map is large. In this
+ case it may be necessary to read the whole map at startup even if
+-browsing is is not enabled. Adding the cache:=all option to
++browsing is not enabled. Adding the cache:=all option to
+ map_options can be used to for this.
+ .TP
+ .B localhost_address
+@@ -390,14 +389,14 @@ and that will be done.
+ Allow map keys to be shown in directory listings. This option
+ can have values of "yes" or "no". The default is "no". A variation
+ of this option, "browsable", can be used as a pseudo mount option
+-in type "auto" map entries to provide provide browsing funtionality
++in type "auto" map entries to provide browsing functionality
+ in sub-mounts. The amd "browsable_dirs = full" option cannot be
+ implemented within the current autofs framework and is not supported.
+ .TP
+ .B exec_map_timeout
+ .br
+-A timeout is not currently used for for program maps, might be
+-implemented.
++A timeout is not currently used for program maps but this might be
++implemented in the future.
+ .TP
+ .B tag
+ .br
+@@ -473,7 +472,7 @@ its official host name.
+ .TP
+ .B domain_strip
+ .br
+-If set to "yes" the domain name part of the host is strippped
++If set to "yes" the domain name part of the host is stripped
+ when normalizing hostnames. This can be useful when using of
+ the same maps in a multiple domain environment.
+ .TP
+@@ -497,8 +496,8 @@ that is used for queries if ldap is to b
+ .B ldap_hostports
+ .br
+ This option has no default value set. It must be set to the URI
+-of the LDAP server to be used for lookups wheni ldap is used a
+-map source. It may contain a comma or space separated list of
++of the LDAP server to be used for lookups when ldap is used as
++a map source. It may contain a comma or space separated list of
+ LDAP URIs.
+ .TP
+ .B hesiod_base
+--- autofs-5.1.4.orig/man/autofs_ldap_auth.conf.5.in
++++ autofs-5.1.4/man/autofs_ldap_auth.conf.5.in
+@@ -56,7 +56,7 @@ required in order to perform ldap querie
+ sasl authenticated connections will be allowed. If it is set to no then
+ authentication is not needed for ldap server connections. If it is set to
+ autodetect then the ldap server will be queried to establish a suitable sasl
+-authentication  mechanism. If no suitable mechanism can be found, connections
++authentication mechanism. If no suitable mechanism can be found, connections
+ to the ldap server are made without authentication. Finally, if it is set to
+ simple, then simple authentication will be used instead of SASL.
+ .TP
+--- autofs-5.1.4.orig/man/automount.8
++++ autofs-5.1.4/man/automount.8
+@@ -89,7 +89,7 @@ that would be used by autofs for the who
+ .TP
+ .I "\-O, \-\-global-options"
+ Allows the specification of global mount options used for all master
+-map entries. These options will either replace or be appened to options
++map entries. These options will either replace or be appended to options
+ given in a master map entry depending on the APPEND_OPTIONS configuration
+ setting.
+ .TP
+--- autofs-5.1.4.orig/modules/lookup_ldap.c
++++ autofs-5.1.4/modules/lookup_ldap.c
+@@ -1320,11 +1320,11 @@ auth_fail:
+ 		ret |= get_property(logopt, root, "external_key",  &extern_key);
+ 		/*
+ 		 * For EXTERNAL auth to function we need a client certificate
+-		 * and and certificate key. The ca certificate used to verify
++		 * and certificate key. The ca certificate used to verify
+ 		 * the server certificate must also be set correctly in the
+ 		 * global configuration as the connection must be encrypted
+ 		 * and the server and client certificates must have been
+-		 * verified for the EXTERNAL method to be offerred by the
++		 * verified for the EXTERNAL method to be offered by the
+ 		 * server. If the cert and key have not been set in the autofs
+ 		 * configuration they must be set in the ldap rc file.
+ 		 */
+--- autofs-5.1.4.orig/modules/replicated.c
++++ autofs-5.1.4/modules/replicated.c
+@@ -24,11 +24,11 @@
+  *        - PROXIMITY_OTHER, host is on a network not directlty
+  *          reachable through a local interface.
+  *
+- *   2) NFS version and protocol is selected by caclculating the largest
++ *   2) NFS version and protocol is selected by calculating the largest
+  *      number of hosts supporting an NFS version and protocol that
+  *      have the closest proximity. These hosts are added to the list
+  *      in response time order. Hosts may have a corresponding weight
+- *      which essentially increaes response time and so influences the
++ *      which essentially increases response time and so influences the
+  *      host order.
+  *
+  *   3) Hosts at further proximity that support the selected NFS version
+--- autofs-5.1.4.orig/redhat/autofs.conf.default.in
++++ autofs-5.1.4/redhat/autofs.conf.default.in
+@@ -79,7 +79,7 @@ mount_nfs_default_protocol = 4
+ #			are run as the privileded user this opens
+ #			automount(8) to potential user privilege
+ #			escalation when the program map is written
+-#			in a language that  can load components from,
++#			in a language that can load components from,
+ #			for example, a user home directory.
+ #
+ # force_standard_program_map_env = no
+@@ -87,7 +87,7 @@ mount_nfs_default_protocol = 4
+ # use_mount_request_log_id - Set whether to use a mount request log
+ #			id so that log entries for specific mount
+ #			requests can be easily identified in logs
+-#			that have multiple conncurrent requests.
++#			that have multiple concurrent requests.
+ #
+ #use_mount_request_log_id = no
+ #
+@@ -419,10 +419,10 @@ dismount_interval = 300
+ # appears to work reasonably well most of the time without the
+ # update).
+ #
+-# autofs_use_lofs = yes
++#autofs_use_lofs = yes
+ #
+ # Several configuration options can be set per mount point.
+-# In particulr map_type, map_name, map_defaults, search_path,
++# In particular map_type, map_name, map_defaults, search_path,
+ # browsable_dirs, dismount_interval and selectors_in_defaults
+ # (not all of which are currently implemented, see above).
+ #
+@@ -431,6 +431,6 @@ dismount_interval = 300
+ # master map entry and the format will be inherited for type
+ # "auto" mounts.
+ #
+-# [ /expamle/mount ]
+-# dismount_interval = 60
+-# map_type = nis
++#[ /example/mount ]
++#dismount_interval = 60
++#map_type = nis
+--- autofs-5.1.4.orig/redhat/autofs.sysconfig
++++ autofs-5.1.4/redhat/autofs.sysconfig
+@@ -1,5 +1,5 @@
+ #
+-# Init syatem options
++# Init system options
+ #
+ # If the kernel supports using the autofs miscellanous device
+ # and you wish to use it you must set this configuration option
+--- autofs-5.1.4.orig/samples/autofs.conf.default.in
++++ autofs-5.1.4/samples/autofs.conf.default.in
+@@ -78,7 +78,7 @@ browse_mode = no
+ #			are run as the privileded user this opens
+ #			automount(8) to potential user privilege
+ #			escalation when the program map is written
+-#			in a language that  can load components from,
++#			in a language that can load components from,
+ #			for example, a user home directory.
+ #
+ # force_standard_program_map_env = no
+@@ -86,7 +86,7 @@ browse_mode = no
+ # use_mount_request_log_id - Set whether to use a mount request log
+ #			id so that log entries for specific mount
+ #			requests can be easily identified in logs
+-#			that have multiple conncurrent requests.
++#			that have multiple concurrent requests.
+ #
+ #use_mount_request_log_id = no
+ #
+@@ -430,6 +430,6 @@ dismount_interval = 300
+ # master map entry and the format will be inherited for type
+ # "auto" mounts.
+ #
+-# [ /expamle/mount ]
+-# dismount_interval = 60
+-# map_type = nis
++#[ /example/mount ]
++#dismount_interval = 60
++#map_type = nis
diff --git a/SOURCES/autofs-5.1.6-add-a-hash-index-to-mnt_list.patch b/SOURCES/autofs-5.1.6-add-a-hash-index-to-mnt_list.patch
new file mode 100644
index 0000000..3291813
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-add-a-hash-index-to-mnt_list.patch
@@ -0,0 +1,202 @@
+autofs-5.1.6 - add a hash index to mnt_list
+
+From: Ian Kent <raven@themaw.net>
+
+Add a hash index (and utility functions) to struct mnt_list.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 
+ include/mounts.h |    8 +++
+ lib/mounts.c     |  135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 144 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -121,6 +121,7 @@ xx/xx/2018 autofs-5.1.5
+ - change mountpoint to mp in struct ext_mount.
+ - make external mounts independent of amd_entry.
+ - make external mounts use simpler hashtable.
++- add a hash index to mnt_list.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -54,10 +54,16 @@ struct mapent;
+ struct mnt_list {
+ 	char *mp;
+ 	unsigned int flags;
++
++	/* Hash of all mounts */
++	struct hlist_node hash;
++	unsigned int ref;
++
+ 	/*
+ 	 * List operations ie. get_mnt_list.
+ 	 */
+ 	struct mnt_list *next;
++
+ 	/*
+ 	 * Tree operations ie. tree_make_tree,
+ 	 * tree_get_mnt_list etc.
+@@ -100,6 +106,8 @@ char *make_mnt_name_string(char *path);
+ int ext_mount_add(const char *, const char *);
+ int ext_mount_remove(const char *);
+ int ext_mount_inuse(const char *);
++struct mnt_list *mnts_lookup_mount(const char *mp);
++void mnts_put_mount(struct mnt_list *mnt);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -63,6 +63,11 @@ struct ext_mount {
+ static DEFINE_HASHTABLE(ext_mounts_hash, EXT_MOUNTS_HASH_BITS);
+ static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
+ 
++#define MNTS_HASH_BITS	7
++
++static DEFINE_HASHTABLE(mnts_hash, MNTS_HASH_BITS);
++static pthread_mutex_t mnts_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
++
+ unsigned int linux_version_code(void)
+ {
+ 	struct utsname my_utsname;
+@@ -832,6 +837,136 @@ done:
+ 	return ret;
+ }
+ 
++static void mnts_hash_mutex_lock(void)
++{
++	int status = pthread_mutex_lock(&mnts_hash_mutex);
++	if (status)
++		fatal(status);
++}
++
++static void mnts_hash_mutex_unlock(void)
++{
++	int status = pthread_mutex_unlock(&mnts_hash_mutex);
++	if (status)
++		fatal(status);
++}
++
++static struct mnt_list *mnts_lookup(const char *mp)
++{
++	uint32_t hval = hash(mp, HASH_SIZE(mnts_hash));
++	struct mnt_list *this;
++
++	if (hlist_empty(&mnts_hash[hval]))
++		return NULL;
++
++	hlist_for_each_entry(this, &mnts_hash[hval], hash) {
++		if (!strcmp(this->mp, mp) && this->ref)
++			return this;
++	}
++
++	return NULL;
++}
++
++static struct mnt_list *mnts_alloc_mount(const char *mp)
++{
++	struct mnt_list *this;
++
++	this = malloc(sizeof(*this));
++	if (!this)
++		goto done;
++	memset(this, 0, sizeof(*this));
++
++	this->mp = strdup(mp);
++	if (!this->mp) {
++		free(this);
++		this = NULL;
++		goto done;
++	}
++
++	this->ref = 1;
++	INIT_HLIST_NODE(&this->hash);
++done:
++	return this;
++}
++
++static void __mnts_get_mount(struct mnt_list *mnt)
++{
++	mnt->ref++;
++}
++
++static void __mnts_put_mount(struct mnt_list *mnt)
++{
++	mnt->ref--;
++	if (!mnt->ref) {
++		hash_del(&mnt->hash);
++		free(mnt->mp);
++		free(mnt);
++	}
++}
++
++static struct mnt_list *mnts_new_mount(const char *mp)
++{
++	struct mnt_list *this;
++
++	this = mnts_lookup(mp);
++	if (this) {
++		__mnts_get_mount(this);
++		goto done;
++	}
++
++	this = mnts_alloc_mount(mp);
++	if (!this)
++		goto done;
++
++	hash_add_str(mnts_hash, &this->hash, this->mp);
++done:
++	return this;
++}
++
++static struct mnt_list *mnts_get_mount(const char *mp)
++{
++	struct mnt_list *this;
++
++	this = mnts_lookup(mp);
++	if (this) {
++		__mnts_get_mount(this);
++		return this;
++	}
++
++	return mnts_new_mount(mp);
++}
++
++static struct mnt_list *__mnts_lookup_mount(const char *mp)
++{
++	struct mnt_list *this;
++
++	this = mnts_lookup(mp);
++	if (this)
++		__mnts_get_mount(this);
++
++	return this;
++}
++
++struct mnt_list *mnts_lookup_mount(const char *mp)
++{
++	struct mnt_list *this;
++
++	mnts_hash_mutex_lock();
++	this = __mnts_lookup_mount(mp);
++	mnts_hash_mutex_unlock();
++
++	return this;
++}
++
++void mnts_put_mount(struct mnt_list *mnt)
++{
++	if (!mnt)
++		return;
++	mnts_hash_mutex_lock();
++	__mnts_put_mount(mnt);
++	mnts_hash_mutex_unlock();
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/SOURCES/autofs-5.1.6-add-hashtable-implementation.patch b/SOURCES/autofs-5.1.6-add-hashtable-implementation.patch
new file mode 100644
index 0000000..23e3c9a
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-add-hashtable-implementation.patch
@@ -0,0 +1,334 @@
+autofs-5.1.6 - add hashtable implementation
+
+From: Ian Kent <raven@themaw.net>
+
+Include the (slightly modified) Linux kernel hashtable implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ include/automount.h |   19 -----
+ include/hash.h      |  101 +++++++++++++++++++++++++++++++
+ include/hashtable.h |  166 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 269 insertions(+), 18 deletions(-)
+ create mode 100644 include/hash.h
+ create mode 100644 include/hashtable.h
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -117,6 +117,7 @@ xx/xx/2018 autofs-5.1.5
+ - make bind mounts propagation slave by default.
+ - fix browse dir not re-created on symlink expire.
+ - update list.h.
++- add hashtable implementation.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -22,6 +22,7 @@
+ #include <mntent.h>
+ #include "config.h"
+ #include "list.h"
++#include "hash.h"
+ 
+ #include <linux/auto_fs4.h>
+ 
+@@ -143,24 +144,6 @@ struct autofs_point;
+ #define UMOUNT_RETRIES		8
+ #define EXPIRE_RETRIES		3
+ 
+-static u_int32_t inline hash(const char *key, unsigned int size)
+-{
+-	u_int32_t hashval;
+-	char *s = (char *) key;
+-
+-	for (hashval = 0; *s != '\0';) {
+-		hashval += (unsigned char) *s++;
+-		hashval += (hashval << 10);
+-		hashval ^= (hashval >> 6);
+-	}
+-
+-	hashval += (hashval << 3);
+-	hashval ^= (hashval >> 11);
+-	hashval += (hashval << 15);
+-
+-	return hashval % size;
+-}
+-
+ struct mapent_cache {
+ 	pthread_rwlock_t rwlock;
+ 	unsigned int size;
+--- /dev/null
++++ autofs-5.1.4/include/hash.h
+@@ -0,0 +1,101 @@
++#ifndef _LINUX_HASH_H
++#define _LINUX_HASH_H
++/* Fast hashing routine for ints,  longs and pointers.
++   (C) 2002 Nadia Yvette Chambers, IBM */
++
++#include <sys/types.h>
++#include <stdint.h>
++
++/*
++ * The "GOLDEN_RATIO_PRIME" is used in ifs/btrfs/brtfs_inode.h and
++ * fs/inode.c.  It's not actually prime any more (the previous primes
++ * were actively bad for hashing), but the name remains.
++ */
++#if __WORDSIZE == 32
++#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
++#define hash_long(val, bits) hash_32(val, bits)
++#elif __WORDSIZE == 64
++#define hash_long(val, bits) hash_64(val, bits)
++#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64
++#else
++#error Wordsize not 32 or 64
++#endif
++
++/* String based hash function */
++static uint32_t inline hash(const char *key, unsigned int size)
++{
++	u_int32_t hashval;
++	char *s = (char *) key;
++
++	for (hashval = 0; *s != '\0';) {
++		hashval += (unsigned char) *s++;
++		hashval += (hashval << 10);
++		hashval ^= (hashval >> 6);
++	}
++
++	hashval += (hashval << 3);
++	hashval ^= (hashval >> 11);
++	hashval += (hashval << 15);
++
++	return hashval % size;
++}
++
++/*
++ * This hash multiplies the input by a large odd number and takes the
++ * high bits.  Since multiplication propagates changes to the most
++ * significant end only, it is essential that the high bits of the
++ * product be used for the hash value.
++ *
++ * Chuck Lever verified the effectiveness of this technique:
++ * http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
++ *
++ * Although a random odd number will do, it turns out that the golden
++ * ratio phi = (sqrt(5)-1)/2, or its negative, has particularly nice
++ * properties.  (See Knuth vol 3, section 6.4, exercise 9.)
++ *
++ * These are the negative, (1 - phi) = phi**2 = (3 - sqrt(5))/2,
++ * which is very slightly easier to multiply by and makes no
++ * difference to the hash distribution.
++ */
++#define GOLDEN_RATIO_32 0x61C88647
++#define GOLDEN_RATIO_64 0x61C8864680B583EBull
++
++static inline uint32_t __hash_32(uint32_t val)
++{
++	return val * GOLDEN_RATIO_32;
++}
++
++static inline uint32_t hash_32(uint32_t val, unsigned int bits)
++{
++	/* High bits are more random, so use them. */
++	return __hash_32(val) >> (32 - bits);
++}
++
++static __always_inline uint32_t hash_64(uint64_t val, unsigned int bits)
++{
++#if __WORDSIZE == 64
++	/* 64x64-bit multiply is efficient on all 64-bit processors */
++	return val * GOLDEN_RATIO_64 >> (64 - bits);
++#else
++	/* Hash 64 bits using only 32x32-bit multiply. */
++	return hash_32((uint32_t) val ^ __hash_32(val >> 32), bits);
++#endif
++}
++
++static inline uint32_t hash_ptr(const void *ptr, unsigned int bits)
++{
++	return hash_long((unsigned long) ptr, bits);
++}
++
++/* This really should be called fold32_ptr; it does no hashing to speak of. */
++static inline uint32_t hash32_ptr(const void *ptr)
++{
++	unsigned long val = (unsigned long) ptr;
++
++#if __WORDSIZE == 64
++	val ^= (val >> 32);
++#endif
++	return (uint32_t) val;
++}
++
++#endif /* _LINUX_HASH_H */
+--- /dev/null
++++ autofs-5.1.4/include/hashtable.h
+@@ -0,0 +1,166 @@
++/*
++ * Statically sized hash table implementation
++ * (C) 2012  Sasha Levin <levinsasha928@gmail.com>
++ */
++
++#ifndef _LINUX_HASHTABLE_H
++#define _LINUX_HASHTABLE_H
++
++#include "list.h"
++#include "hash.h"
++
++#ifndef ARRAY_SIZE
++#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
++#endif
++
++static inline unsigned int ilog2(unsigned long val) {
++	unsigned int ret = -1;
++
++	while (val != 0) {
++		val >>= 1;
++		ret++;
++	}
++	return ret;
++}
++
++#define DEFINE_HASHTABLE(name, bits)						\
++	struct hlist_head name[1 << (bits)] =					\
++			{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
++
++#define DECLARE_HASHTABLE(name, bits)                                   	\
++	struct hlist_head name[1 << (bits)]
++
++#define HASH_SIZE(name) (ARRAY_SIZE(name))
++#define HASH_BITS(name) ilog2(HASH_SIZE(name))
++
++/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
++#define hash_min(val, bits)							\
++	(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
++
++static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
++{
++	unsigned int i;
++
++	for (i = 0; i < sz; i++)
++		INIT_HLIST_HEAD(&ht[i]);
++}
++
++/**
++ * hash_init - initialize a hash table
++ * @hashtable: hashtable to be initialized
++ *
++ * Calculates the size of the hashtable from the given parameter, otherwise
++ * same as hash_init_size.
++ *
++ * This has to be a macro since HASH_BITS() will not work on pointers since
++ * it calculates the size during preprocessing.
++ */
++#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
++
++/**
++ * hash_add - add an object to a hashtable
++ * @hashtable: hashtable to add to
++ * @node: the &struct hlist_node of the object to be added
++ * @key: the key of the object to be added
++ */
++#define hash_add(hashtable, node, key)						\
++	hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
++
++/**
++ * hash_add_str - add a string object to a hashtable
++ * @hashtable: hashtable to add to
++ * @node: the &struct hlist_node of the object to be added
++ * @key: the string key of the object to be added
++ */
++#define hash_add_str(hashtable, node, key)						\
++	hlist_add_head(node, &hashtable[hash(key, HASH_SIZE(hashtable))])
++
++/**
++ * hash_hashed - check whether an object is in any hashtable
++ * @node: the &struct hlist_node of the object to be checked
++ */
++static inline int hash_hashed(struct hlist_node *node)
++{
++	return !hlist_unhashed(node);
++}
++
++static inline int __hash_empty(struct hlist_head *ht, unsigned int sz)
++{
++	unsigned int i;
++
++	for (i = 0; i < sz; i++)
++		if (!hlist_empty(&ht[i]))
++			return 0;
++
++	return 1;
++}
++
++/**
++ * hash_empty - check whether a hashtable is empty
++ * @hashtable: hashtable to check
++ *
++ * This has to be a macro since HASH_BITS() will not work on pointers since
++ * it calculates the size during preprocessing.
++ */
++#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
++
++/**
++ * hash_del - remove an object from a hashtable
++ * @node: &struct hlist_node of the object to remove
++ */
++static inline void hash_del(struct hlist_node *node)
++{
++	hlist_del_init(node);
++}
++
++/**
++ * hash_for_each - iterate over a hashtable
++ * @name: hashtable to iterate
++ * @bkt: integer to use as bucket loop cursor
++ * @obj: the type * to use as a loop cursor for each entry
++ * @member: the name of the hlist_node within the struct
++ */
++#define hash_for_each(name, bkt, obj, member)				\
++	for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
++			(bkt)++)\
++		hlist_for_each_entry(obj, &name[bkt], member)
++
++/**
++ * hash_for_each_safe - iterate over a hashtable safe against removal of
++ * hash entry
++ * @name: hashtable to iterate
++ * @bkt: integer to use as bucket loop cursor
++ * @tmp: a &struct used for temporary storage
++ * @obj: the type * to use as a loop cursor for each entry
++ * @member: the name of the hlist_node within the struct
++ */
++#define hash_for_each_safe(name, bkt, tmp, obj, member)			\
++	for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
++			(bkt)++)\
++		hlist_for_each_entry_safe(obj, tmp, &name[bkt], member)
++
++/**
++ * hash_for_each_possible - iterate over all possible objects hashing to the
++ * same bucket
++ * @name: hashtable to iterate
++ * @obj: the type * to use as a loop cursor for each entry
++ * @member: the name of the hlist_node within the struct
++ * @key: the key of the objects to iterate over
++ */
++#define hash_for_each_possible(name, obj, member, key)			\
++	hlist_for_each_entry(obj, &name[hash_min(key, HASH_BITS(name))], member)
++
++/**
++ * hash_for_each_possible_safe - iterate over all possible objects hashing to the
++ * same bucket safe against removals
++ * @name: hashtable to iterate
++ * @obj: the type * to use as a loop cursor for each entry
++ * @tmp: a &struct used for temporary storage
++ * @member: the name of the hlist_node within the struct
++ * @key: the key of the objects to iterate over
++ */
++#define hash_for_each_possible_safe(name, obj, tmp, member, key)	\
++	hlist_for_each_entry_safe(obj, tmp,\
++		&name[hash_min(key, HASH_BITS(name))], member)
++
++#endif
diff --git a/SOURCES/autofs-5.1.6-add-helper-to-construct-mount-point-path.patch b/SOURCES/autofs-5.1.6-add-helper-to-construct-mount-point-path.patch
new file mode 100644
index 0000000..1cb15cf
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-add-helper-to-construct-mount-point-path.patch
@@ -0,0 +1,225 @@
+autofs-5.1.6 - add helper to construct mount point path
+
+From: Ian Kent <raven@themaw.net>
+
+Add convenience helper to construct mount point path.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG               |    1 +
+ include/mounts.h        |    3 +++
+ lib/mounts.c            |   23 +++++++++++++++++++++++
+ modules/mount_bind.c    |   19 +++++--------------
+ modules/mount_changer.c |   19 +++++--------------
+ modules/mount_ext2.c    |   19 +++++--------------
+ modules/mount_generic.c |   19 +++++--------------
+ modules/mount_nfs.c     |   21 ++++++++-------------
+ 8 files changed, 55 insertions(+), 69 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -135,6 +135,7 @@ xx/xx/2018 autofs-5.1.5
+ - move submount check into conditional_alarm_add().
+ - move lib/master.c to daemon/master.c.
+ - use master_list_empty() for list empty check.
++- add helper to construct mount point path.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -94,6 +94,9 @@ unsigned int linux_version_code(void);
+ int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *);
+ extern unsigned int nfs_mount_uses_string_options;
+ 
++int mount_fullpath(char *fullpath, size_t max_len,
++		   const char *root, const char *name);
++
+ struct amd_entry;
+ 
+ struct substvar *addstdenv(struct substvar *sv, const char *prefix);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -339,6 +339,29 @@ int check_nfs_mount_version(struct nfs_m
+ }
+ #endif
+ 
++int mount_fullpath(char *fullpath, size_t max_len,
++		   const char *root, const char *name)
++{
++	int last, len;
++
++	last = strlen(root) - 1;
++
++	/* Root offset of multi-mount or direct or offset mount.
++	 * Direct or offset mount, name (or root) is absolute path.
++	 */
++	if (root[last] == '/' || *name == '/')
++		len = snprintf(fullpath, max_len, "%s", root);
++	else
++		len = snprintf(fullpath, max_len, "%s/%s", root, name);
++
++	if (len >= max_len)
++		return 0;
++
++	fullpath[len] = '\0';
++
++	return len;
++}
++
+ static char *set_env_name(const char *prefix, const char *name, char *buf)
+ {
+ 	size_t len;
+--- autofs-5.1.4.orig/modules/mount_bind.c
++++ autofs-5.1.4/modules/mount_bind.c
+@@ -122,21 +122,12 @@ int mount_mount(struct autofs_point *ap,
+ 		}
+ 	}
+ 
+-	/* Root offset of multi-mount */
+-	len = strlen(root);
+-	if (root[len - 1] == '/') {
+-		len = snprintf(fullpath, len, "%s", root);
+-	} else if (*name == '/') {
+-		/*
+-		 * Direct or offset mount, name is absolute path so
+-		 * don't use root (but with move mount changes root
+-		 * is now the same as name).
+-		 */
+-		len = sprintf(fullpath, "%s", root);
+-	} else {
+-		len = sprintf(fullpath, "%s/%s", root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	if (!len) {
++		error(ap->logopt,
++		      MODPREFIX "mount point path too long");
++		return 1;
+ 	}
+-	fullpath[len] = '\0';
+ 
+ 	i = len;
+ 	while (--i > 0 && fullpath[i] == '/')
+--- autofs-5.1.4.orig/modules/mount_changer.c
++++ autofs-5.1.4/modules/mount_changer.c
+@@ -59,21 +59,12 @@ int mount_mount(struct autofs_point *ap,
+ 
+ 	fstype = "iso9660";
+ 
+-	/* Root offset of multi-mount */
+-	len = strlen(root);
+-	if (root[len - 1] == '/') {
+-		len = snprintf(fullpath, len, "%s", root);
+-	} else if (*name == '/') {
+-		/*
+-		 * Direct or offset mount, name is absolute path so
+-		 * don't use root (but with move mount changes root
+-		 * is now the same as name).
+-		 */
+-		len = sprintf(fullpath, "%s", root);
+-	} else {
+-		len = sprintf(fullpath, "%s/%s", root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	if (!len) {
++		error(ap->logopt,
++		      MODPREFIX "mount point path too long");
++		return 1;
+ 	}
+-	fullpath[len] = '\0';
+ 
+ 	debug(ap->logopt, MODPREFIX "calling umount %s", what);
+ 
+--- autofs-5.1.4.orig/modules/mount_ext2.c
++++ autofs-5.1.4/modules/mount_ext2.c
+@@ -55,21 +55,12 @@ int mount_mount(struct autofs_point *ap,
+ 	if (defaults_get_mount_verbose())
+ 		mountlog = &log_info;
+ 
+-	/* Root offset of multi-mount */
+-	len = strlen(root);
+-	if (root[len - 1] == '/') {
+-		len = snprintf(fullpath, len, "%s", root);
+-	} else if (*name == '/') {
+-		/*
+-		 * Direct or offset mount, name is absolute path so
+-		 * don't use root (but with move mount changes root
+-		 * is now the same as name).
+-		 */
+-		len = sprintf(fullpath, "%s", root);
+-	} else {
+-		len = sprintf(fullpath, "%s/%s", root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	if (!len) {
++		error(ap->logopt,
++		      MODPREFIX "mount point path too long");
++		return 1;
+ 	}
+-	fullpath[len] = '\0';
+ 
+ 	debug(ap->logopt, MODPREFIX "calling mkdir_path %s", fullpath);
+ 
+--- autofs-5.1.4.orig/modules/mount_generic.c
++++ autofs-5.1.4/modules/mount_generic.c
+@@ -54,21 +54,12 @@ int mount_mount(struct autofs_point *ap,
+ 	if (defaults_get_mount_verbose())
+ 		mountlog = &log_info;
+ 
+-	/* Root offset of multi-mount */
+-	len = strlen(root);
+-	if (root[len - 1] == '/') {
+-		len = snprintf(fullpath, len, "%s", root);
+-	} else if (*name == '/') {
+-		/*
+-		 * Direct or offset mount, name is absolute path so
+-		 * don't use root (but with move mount changes root
+-		 * is now the same as name).
+-		 */
+-		len = sprintf(fullpath, "%s", root);
+-	} else {
+-		len = sprintf(fullpath, "%s/%s", root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	if (!len) {
++		error(ap->logopt,
++		      MODPREFIX "mount point path too long");
++		return 1;
+ 	}
+-	fullpath[len] = '\0';
+ 
+ 	debug(ap->logopt, MODPREFIX "calling mkdir_path %s", fullpath);
+ 
+--- autofs-5.1.4.orig/modules/mount_nfs.c
++++ autofs-5.1.4/modules/mount_nfs.c
+@@ -212,6 +212,14 @@ int mount_mount(struct autofs_point *ap,
+ 			 nfsoptions, nobind, nosymlink, ro);
+ 	}
+ 
++	/* Construct mount point directory */
++	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	if (!len) {
++		error(ap->logopt,
++		      MODPREFIX "mount point path too long");
++		return 1;
++	}
++
+ 	if (!parse_location(ap->logopt, &hosts, what, flags)) {
+ 		info(ap->logopt, MODPREFIX "no hosts available");
+ 		return 1;
+@@ -266,19 +274,6 @@ dont_probe:
+ 		return 1;
+ 	}
+ 
+-	/* Construct and perhaps create mount point directory */
+-
+-	/* Root offset of multi-mount */
+-	len = strlen(root);
+-	if (root[len - 1] == '/') {
+-		len = snprintf(fullpath, len, "%s", root);
+-	} else if (*name == '/') {
+-		len = sprintf(fullpath, "%s", root);
+-	} else {
+-		len = sprintf(fullpath, "%s/%s", root, name);
+-	}
+-	fullpath[len] = '\0';
+-
+ 	debug(ap->logopt, MODPREFIX "calling mkdir_path %s", fullpath);
+ 
+ 	status = mkdir_path(fullpath, mp_mode);
diff --git a/SOURCES/autofs-5.1.6-change-mountpoint-to-mp-in-struct-ext_mount.patch b/SOURCES/autofs-5.1.6-change-mountpoint-to-mp-in-struct-ext_mount.patch
new file mode 100644
index 0000000..65e2800
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-change-mountpoint-to-mp-in-struct-ext_mount.patch
@@ -0,0 +1,74 @@
+autofs-5.1.6 - change mountpoint to mp in struct ext_mount
+
+From: Ian Kent <raven@themaw.net>
+
+Use simple name mp instead of mountpoint in struct ext_mount.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   14 +++++++-------
+ 2 files changed, 8 insertions(+), 7 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -118,6 +118,7 @@ xx/xx/2018 autofs-5.1.5
+ - fix browse dir not re-created on symlink expire.
+ - update list.h.
+ - add hashtable implementation.
++- change mountpoint to mp in struct ext_mount.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -54,7 +54,7 @@ static size_t maxgrpbuf = 0;
+ #define EXT_MOUNTS_HASH_SIZE    50
+ 
+ struct ext_mount {
+-	char *mountpoint;
++	char *mp;
+ 	unsigned int umount;
+ 	struct list_head mount;
+ 	struct list_head mounts;
+@@ -743,9 +743,9 @@ static void ext_mounts_hash_init(void)
+ 	ext_mounts_hash_init_done = 1;
+ }
+ 
+-static struct ext_mount *ext_mount_lookup(const char *mountpoint)
++static struct ext_mount *ext_mount_lookup(const char *mp)
+ {
+-	u_int32_t hval = hash(mountpoint, EXT_MOUNTS_HASH_SIZE);
++	u_int32_t hval = hash(mp, EXT_MOUNTS_HASH_SIZE);
+ 	struct list_head *p, *head;
+ 
+ 	if (!ext_mounts_hash_init_done)
+@@ -757,7 +757,7 @@ static struct ext_mount *ext_mount_looku
+ 	head = &ext_mounts_hash[hval];
+ 	list_for_each(p, head) {
+ 		struct ext_mount *this = list_entry(p, struct ext_mount, mount);
+-		if (!strcmp(this->mountpoint, mountpoint))
++		if (!strcmp(this->mp, mp))
+ 			return this;
+ 	}
+ 	return NULL;
+@@ -788,8 +788,8 @@ int ext_mount_add(struct list_head *entr
+ 	if (!em)
+ 		goto done;
+ 
+-	em->mountpoint = strdup(path);
+-	if (!em->mountpoint) {
++	em->mp = strdup(path);
++	if (!em->mp) {
+ 		free(em);
+ 		goto done;
+ 	}
+@@ -828,7 +828,7 @@ int ext_mount_remove(struct list_head *e
+ 		if (em->umount)
+ 			ret = 1;
+ 		if (list_empty(&em->mount)) {
+-			free(em->mountpoint);
++			free(em->mp);
+ 			free(em);
+ 		}
+ 	}
diff --git a/SOURCES/autofs-5.1.6-fix-browse-dir-not-re-created-on-symlink-expire.patch b/SOURCES/autofs-5.1.6-fix-browse-dir-not-re-created-on-symlink-expire.patch
new file mode 100644
index 0000000..aafc5c4
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-fix-browse-dir-not-re-created-on-symlink-expire.patch
@@ -0,0 +1,52 @@
+autofs-5.1.6 - fix browse dir not re-created on symlink expire
+
+From: Ian Kent <raven@themaw.net>
+
+If symlinks are being used for mounts and the autofs mount has browse mode
+enabled when a symlink is removed at expire the browse mode directory needs
+to be re-created.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |   19 +++++++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -115,6 +115,7 @@ xx/xx/2018 autofs-5.1.5
+ - remove unused function dump_master().
+ - fix additional typing errors.
+ - make bind mounts propagation slave by default.
++- fix browse dir not re-created on symlink expire.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -651,6 +651,25 @@ int umount_multi(struct autofs_point *ap
+ 			      "failed to remove symlink %s", path);
+ 			return 1;
+ 		}
++		/* Check if the autofs mount has browse mode enabled.
++		 * If so re-create the directory entry.
++		 */
++		if (ap->flags | MOUNT_FLAG_GHOST) {
++			int ret;
++
++			/* If the browse directory create fails log an
++			 * error and continue anyway since the expire
++			 * has succeeded.
++			 */
++			ret = mkdir_path(path, mp_mode);
++			if (ret && errno != EEXIST) {
++				char buf[MAX_ERR_BUF];
++				char *estr;
++				estr = strerror_r(errno, buf, MAX_ERR_BUF);
++				warn(ap->logopt,
++				     "mkdir_path %s failed: %s", path, estr);
++			}
++		}
+ 		/* Check for an external mount and attempt umount if needed */
+ 		mounts_mutex_lock(ap);
+ 		entry = __master_find_amdmount(ap, path);
diff --git a/SOURCES/autofs-5.1.6-fix-empty-mounts-list-return-from-unlink_mount_tree.patch b/SOURCES/autofs-5.1.6-fix-empty-mounts-list-return-from-unlink_mount_tree.patch
index 34ffcad..8ab0516 100644
--- a/SOURCES/autofs-5.1.6-fix-empty-mounts-list-return-from-unlink_mount_tree.patch
+++ b/SOURCES/autofs-5.1.6-fix-empty-mounts-list-return-from-unlink_mount_tree.patch
@@ -19,17 +19,17 @@ Signed-off-by: Ian Kent <raven@themaw.net>
 
 --- autofs-5.1.4.orig/CHANGELOG
 +++ autofs-5.1.4/CHANGELOG
-@@ -111,6 +111,7 @@ xx/xx/2018 autofs-5.1.5
- - use a valid timeout in lookup_prune_one_cache().
- - dont prune offset map entries.
- - simplify sss source stale check.
+@@ -75,6 +75,7 @@
+ - fix direct mount deadlock.
+ - fix lookup_prune_one_cache() refactoring change.
+ - add missing description of null map option.
 +- fix empty mounts list return from unlink_mount_tree().
  
- 19/12/2017 autofs-5.1.4
- - fix spec file url.
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
 --- autofs-5.1.4.orig/lib/mounts.c
 +++ autofs-5.1.4/lib/mounts.c
-@@ -954,9 +954,13 @@ int unlink_mount_tree(struct autofs_poin
+@@ -2115,9 +2115,13 @@ int unlink_mount_tree(struct autofs_poin
  	struct mnt_list *mnts, *mnt;
  	int rv, ret = 1;
  
diff --git a/SOURCES/autofs-5.1.6-fix-program-map-multi-mount-lookup-after-mount-fail.patch b/SOURCES/autofs-5.1.6-fix-program-map-multi-mount-lookup-after-mount-fail.patch
new file mode 100644
index 0000000..2fed0c8
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-fix-program-map-multi-mount-lookup-after-mount-fail.patch
@@ -0,0 +1,60 @@
+autofs-5.1.6 - fix program map multi-mount lookup after mount fail
+
+From: Ian Kent <raven@themaw.net>
+
+For the case of a singleton multi-mount program map lookup following
+a mount fail (and the negative timeout has passed) the lookup key is
+what's expected for an indirect map key but the the root offset map
+entry already exists. This causes autofs to think it has an incorrect
+lookup key and it fails the lookup when it should take the opptunity
+to delete and update the cache entry since it's not actually in use
+yet.
+
+If a check is done to see if the lookup is for the root offset,
+deleting the entry fails because it contains an offset. Later when
+parsing is done the offset will get updated and can get out of sync
+with the entry of the multi-mount owner. That's not a problem as the
+offsets would be deleted on eventual expire but it's best to clean
+out the entry and start a fresh so the most up to date map entry
+is being used.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                |    1 +
+ modules/lookup_program.c |    7 +++++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -27,6 +27,7 @@
+ - rename path to m_offset in update_offset_entry().
+ - don't pass root to do_mount_autofs_offset().
+ - rename tree implementation functions.
++- fix program map multi-mount lookup after mount fail.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/lookup_program.c
++++ autofs-5.1.4/modules/lookup_program.c
+@@ -664,7 +664,7 @@ int lookup_mount(struct autofs_point *ap
+ 				 name_len, ent, ctxt->parse->context);
+ 			goto out_free;
+ 		} else {
+-			if (me->multi) {
++			if (me->multi && me->multi != me) {
+ 				cache_unlock(mc);
+ 				warn(ap->logopt, MODPREFIX
+ 				     "unexpected lookup for active multi-mount"
+@@ -674,8 +674,11 @@ int lookup_mount(struct autofs_point *ap
+ 			cache_unlock(mc);
+ 			cache_writelock(mc);
+ 			me = cache_lookup_distinct(mc, name);
+-			if (me)
++			if (me) {
++				if (me->multi)
++					cache_delete_offset_list(mc, name);
+ 				cache_delete(mc, name);
++			}
+ 			cache_unlock(mc);
+ 		}
+ 	}
diff --git a/SOURCES/autofs-5.1.6-fix-remount-expire.patch b/SOURCES/autofs-5.1.6-fix-remount-expire.patch
new file mode 100644
index 0000000..fd9c75f
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-fix-remount-expire.patch
@@ -0,0 +1,48 @@
+autofs-5.1.6 - fix remount expire
+
+From: Ian Kent <raven@themaw.net>
+
+When starting autofs when there are active mounts due to in use
+mounts from a previous shutdown, and a mount entry has offsets,
+and an offset doesn't have a real mount due to a non-strict fail
+returning success for the remount a file handle is incorrectly
+left open.
+
+The file handle gets assingned to the offset entry for expires
+but since there is no mount to expire it never gets closed which
+prevents the multi-mount owner itself from expiring.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    8 +++++++-
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -126,6 +126,7 @@ xx/xx/2018 autofs-5.1.5
+ - use mnt_list for amdmounts.
+ - make umount_autofs() static.
+ - remove force parameter from umount_all().
++- fix remount expire.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2205,8 +2205,14 @@ int try_remount(struct autofs_point *ap,
+ 		if (fd != -1) {
+ 			if (type == t_indirect)
+ 				ap->ioctlfd = fd;
+-			else
++			else {
++				if (type == t_offset &&
++				    !is_mounted(me->key, MNTS_REAL)) {
++					ops->close(ap->logopt, fd);
++					fd = -1;
++				}
+ 				me->ioctlfd = fd;
++			}
+ 			return 1;
+ 		}
+ 
diff --git a/SOURCES/autofs-5.1.6-fix-stale-offset-directories-disable-mount.patch b/SOURCES/autofs-5.1.6-fix-stale-offset-directories-disable-mount.patch
new file mode 100644
index 0000000..1b1b74f
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-fix-stale-offset-directories-disable-mount.patch
@@ -0,0 +1,57 @@
+autofs-5.1.6 - fix stale offset directories disable mount
+
+From: Ian Kent <raven@themaw.net>
+
+When starting autofs when there are active mounts due to in use
+mounts from a previous shutdown, and a mount entry has offsets
+that are within an autofs mount, the mount point directories are
+incorrectly marked as not created by us when re-connecting to the
+mount so they are not removed at expire.
+
+Since the base autofs mount directory needs to be empty for mounts
+to be triggered these directories disable automounting for the mount.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   12 ++++++++++--
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -127,6 +127,7 @@ xx/xx/2018 autofs-5.1.5
+ - make umount_autofs() static.
+ - remove force parameter from umount_all().
+ - fix remount expire.
++- fix stale offset directories disable mount.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2182,15 +2182,23 @@ int try_remount(struct autofs_point *ap,
+ 	 * number for the mount but we can't know if we created
+ 	 * it or not. However, if this is an indirect mount with
+ 	 * the nobrowse option we need to remove the mount point
+-	 * directory at umount anyway.
++	 * directory at umount anyway. Also, if this is an offset
++	 * mount that's not within a real mount then we know we
++	 * created it so we must remove it on expire for the mount
++	 * to function.
+ 	 */
+ 	if (type == t_indirect) {
+ 		if (ap->flags & MOUNT_FLAG_GHOST)
+ 			ap->flags &= ~MOUNT_FLAG_DIR_CREATED;
+ 		else
+ 			ap->flags |= MOUNT_FLAG_DIR_CREATED;
+-	} else
++	} else {
+ 		me->flags &= ~MOUNT_FLAG_DIR_CREATED;
++		if (type == t_offset) {
++			if (!is_mounted(me->parent->key, MNTS_REAL))
++				me->flags |= MOUNT_FLAG_DIR_CREATED;
++		}
++	}
+ 
+ 	/*
+ 	 * Either we opened the mount or we're re-reading the map.
diff --git a/SOURCES/autofs-5.1.6-make-bind-mounts-propagation-slave-by-default.patch b/SOURCES/autofs-5.1.6-make-bind-mounts-propagation-slave-by-default.patch
new file mode 100644
index 0000000..ece835a
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-make-bind-mounts-propagation-slave-by-default.patch
@@ -0,0 +1,220 @@
+autofs-5.1.6 - make bind mounts propagation slave by default
+
+From: Ian Kent <raven@themaw.net>
+
+Make setting mount propagation on bind mounts mandatory with a default
+of propagation slave.
+
+When using multi-mounts that have bind mounts the bind mount will have
+the same properties as its parent which is commonly propagation shared.
+And if the mount target is also propagation shared this can lead to a
+deadlock when attempting to access the offset mounts. When this happens
+an unwanted offset mount is propagated back to the target file system
+resulting in a deadlock since the automount target is itself an
+(unwanted) automount trigger.
+
+This problem has been present much longer than I originally thought,
+perhaps since mount propagation was introduced into the kernel, so
+explicitly setting bind mount propagation is the sensible thing to do.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG            |    1 +
+ include/automount.h  |    9 +++++----
+ lib/master_parse.y   |   29 +++++++++++++++++------------
+ lib/master_tok.l     |    1 +
+ modules/mount_bind.c |   40 ++++++++++++++++++++++------------------
+ 5 files changed, 46 insertions(+), 34 deletions(-)
+
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -551,14 +551,15 @@ struct kernel_mod_version {
+ #define MOUNT_FLAG_AMD_CACHE_ALL	0x0080
+ 
+ /* Set mount propagation for bind mounts */
+-#define MOUNT_FLAG_SLAVE		0x0100
+-#define MOUNT_FLAG_PRIVATE		0x0200
++#define MOUNT_FLAG_SHARED		0x0100
++#define MOUNT_FLAG_SLAVE		0x0200
++#define MOUNT_FLAG_PRIVATE		0x0400
+ 
+ /* Use strict expire semantics if requested and kernel supports it */
+-#define MOUNT_FLAG_STRICTEXPIRE		0x0400
++#define MOUNT_FLAG_STRICTEXPIRE		0x0800
+ 
+ /* Indicator for applications to ignore the mount entry */
+-#define MOUNT_FLAG_IGNORE		0x0800
++#define MOUNT_FLAG_IGNORE		0x1000
+ 
+ struct autofs_point {
+ 	pthread_t thid;
+--- autofs-5.1.4.orig/lib/master_parse.y
++++ autofs-5.1.4/lib/master_parse.y
+@@ -59,8 +59,6 @@ static long timeout;
+ static long negative_timeout;
+ static unsigned symlnk;
+ static unsigned strictexpire;
+-static unsigned slave;
+-static unsigned private;
+ static unsigned nobind;
+ static unsigned ghost;
+ extern unsigned global_selection_options;
+@@ -72,6 +70,14 @@ static int tmp_argc;
+ static char **local_argv;
+ static int local_argc;
+ 
++#define PROPAGATION_SHARED	MOUNT_FLAG_SHARED
++#define PROPAGATION_SLAVE	MOUNT_FLAG_SLAVE
++#define PROPAGATION_PRIVATE	MOUNT_FLAG_PRIVATE
++#define PROPAGATION_MASK	(MOUNT_FLAG_SHARED | \
++				 MOUNT_FLAG_SLAVE  | \
++				 MOUNT_FLAG_PRIVATE)
++static unsigned int propagation;
++
+ static char errstr[MAX_ERR_LEN];
+ 
+ static unsigned int verbose;
+@@ -106,7 +112,7 @@ static int master_fprintf(FILE *, char *
+ %token MAP
+ %token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
+ %token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
+-%token OPT_STRICTEXPIRE OPT_SLAVE OPT_PRIVATE
++%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
+ %token COLON COMMA NL DDASH
+ %type <strtype> map
+ %type <strtype> options
+@@ -208,6 +214,7 @@ line:
+ 	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
+ 	| PATH OPT_SYMLINK { master_notify($1); YYABORT; }
+ 	| PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
++	| PATH OPT_SHARED { master_notify($1); YYABORT; }
+ 	| PATH OPT_SLAVE { master_notify($1); YYABORT; }
+ 	| PATH OPT_PRIVATE { master_notify($1); YYABORT; }
+ 	| PATH OPT_NOBIND { master_notify($1); YYABORT; }
+@@ -622,8 +629,9 @@ daemon_option: OPT_TIMEOUT NUMBER { time
+ 	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
+ 	| OPT_SYMLINK	{ symlnk = 1; }
+ 	| OPT_STRICTEXPIRE { strictexpire = 1; }
+-	| OPT_SLAVE	{ slave = 1; }
+-	| OPT_PRIVATE	{ private = 1; }
++	| OPT_SHARED	{ propagation = PROPAGATION_SHARED; }
++	| OPT_SLAVE	{ propagation = PROPAGATION_SLAVE; }
++	| OPT_PRIVATE	{ propagation = PROPAGATION_PRIVATE; }
+ 	| OPT_NOBIND	{ nobind = 1; }
+ 	| OPT_NOGHOST	{ ghost = 0; }
+ 	| OPT_GHOST	{ ghost = 1; }
+@@ -697,8 +705,7 @@ static void local_init_vars(void)
+ 	negative_timeout = 0;
+ 	symlnk = 0;
+ 	strictexpire = 0;
+-	slave = 0;
+-	private = 0;
++	propagation = PROPAGATION_SLAVE;
+ 	nobind = 0;
+ 	ghost = defaults_get_browse_mode();
+ 	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
+@@ -888,7 +895,6 @@ int master_parse_entry(const char *buffe
+ 			ghost = 1;
+ 	}
+ 
+-
+ 	if (!entry->ap) {
+ 		ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
+ 		if (!ret) {
+@@ -899,6 +905,9 @@ int master_parse_entry(const char *buffe
+ 			return 0;
+ 		}
+ 	}
++	entry->ap->flags &= ~(PROPAGATION_MASK);
++	entry->ap->flags |= propagation;
++
+ 	if (random_selection)
+ 		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
+ 	if (use_weight)
+@@ -907,10 +916,6 @@ int master_parse_entry(const char *buffe
+ 		entry->ap->flags |= MOUNT_FLAG_SYMLINK;
+ 	if (strictexpire)
+ 		entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
+-	if (slave)
+-		entry->ap->flags |= MOUNT_FLAG_SLAVE;
+-	if (private)
+-		entry->ap->flags |= MOUNT_FLAG_PRIVATE;
+ 	if (negative_timeout)
+ 		entry->ap->negative_timeout = negative_timeout;
+ 	if (mode && mode < LONG_MAX)
+--- autofs-5.1.4.orig/lib/master_tok.l
++++ autofs-5.1.4/lib/master_tok.l
+@@ -389,6 +389,7 @@ MODE		(--mode{OPTWS}|--mode{OPTWS}={OPTW
+ 	-?symlink		{ return(OPT_SYMLINK); }
+ 	-?nobind		{ return(OPT_NOBIND); }
+ 	-?nobrowse		{ return(OPT_NOGHOST); }
++	-?shared		{ return(OPT_SHARED); }
+ 	-?slave			{ return(OPT_SLAVE); }
+ 	-?private		{ return(OPT_PRIVATE); }
+ 	-?strictexpire		{ return(OPT_STRICTEXPIRE); }
+--- autofs-5.1.4.orig/modules/mount_bind.c
++++ autofs-5.1.4/modules/mount_bind.c
+@@ -153,6 +153,7 @@ int mount_mount(struct autofs_point *ap,
+ 
+ 	if (!symlnk && bind_works) {
+ 		int status, existed = 1;
++		int flags;
+ 
+ 		debug(ap->logopt, MODPREFIX "calling mkdir_path %s", fullpath);
+ 
+@@ -190,24 +191,27 @@ int mount_mount(struct autofs_point *ap,
+ 			      what, fstype, fullpath);
+ 		}
+ 
+-		if (ap->flags & (MOUNT_FLAG_SLAVE | MOUNT_FLAG_PRIVATE)) {
+-			int flags = MS_SLAVE;
+-
+-			if (ap->flags & MOUNT_FLAG_PRIVATE)
+-				flags = MS_PRIVATE;
+-
+-			/* The bind mount has succeeded but if the target
+-			 * mount is propagation shared propagation of child
+-			 * mounts (autofs offset mounts for example) back to
+-			 * the target of the bind mount must be avoided or
+-			 * autofs trigger mounts will deadlock.
+-			 */
+-			err = mount(NULL, fullpath, NULL, flags, NULL);
+-			if (err) {
+-				warn(ap->logopt,
+-				     "failed to set propagation for %s",
+-				     fullpath, root);
+-			}
++		/* The bind mount has succeeded, now set the mount propagation.
++		 *
++		 * The default is propagation shared, change it if the master
++		 * map entry has a different option specified.
++		 */
++		flags = MS_SLAVE;
++		if (ap->flags & MOUNT_FLAG_PRIVATE)
++			flags = MS_PRIVATE;
++		else if (ap->flags & MOUNT_FLAG_SHARED)
++			flags = MS_SHARED;
++
++		/* Note: If the parent mount is propagation shared propagation
++		 *  of child mounts (autofs offset mounts for example) back to
++		 *  the target of the bind mount can happen in some cases and
++		 *  must be avoided or autofs trigger mounts will deadlock.
++		 */
++		err = mount(NULL, fullpath, NULL, flags, NULL);
++		if (err) {
++			warn(ap->logopt,
++			     "failed to set propagation for %s",
++			     fullpath, root);
+ 		}
+ 
+ 		return 0;
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -114,6 +114,7 @@ xx/xx/2018 autofs-5.1.5
+ - use defines for expire type.
+ - remove unused function dump_master().
+ - fix additional typing errors.
++- make bind mounts propagation slave by default.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
diff --git a/SOURCES/autofs-5.1.6-make-external-mounts-independent-of-amd_entry.patch b/SOURCES/autofs-5.1.6-make-external-mounts-independent-of-amd_entry.patch
new file mode 100644
index 0000000..a4e9482
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-make-external-mounts-independent-of-amd_entry.patch
@@ -0,0 +1,382 @@
+autofs-5.1.6 - make external mounts independent of amd_entry
+
+From: Ian Kent <raven@themaw.net>
+
+The external mounts used by amd map entries should not depend
+on the amd map entry.
+
+The external mounts list is keyed by the external mount path
+and this should be what's used to locate them.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ daemon/automount.c  |    4 -
+ include/mounts.h    |    6 +-
+ include/parse_amd.h |    1 
+ lib/master.c        |    3 -
+ lib/mounts.c        |  114 ++++++++++++++++++++++++++++++----------------------
+ modules/parse_amd.c |   14 +++---
+ 7 files changed, 80 insertions(+), 63 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -119,6 +119,7 @@ xx/xx/2018 autofs-5.1.5
+ - update list.h.
+ - add hashtable implementation.
+ - change mountpoint to mp in struct ext_mount.
++- make external mounts independent of amd_entry.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -613,7 +613,7 @@ static int umount_subtree_mounts(struct
+ 		}
+ 		list_del(&entry->entries);
+ 		mounts_mutex_unlock(ap);
+-		umount_amd_ext_mount(ap, entry);
++		umount_amd_ext_mount(ap, entry->fs);
+ 		free_amd_entry(entry);
+ 	}
+ done:
+@@ -679,7 +679,7 @@ int umount_multi(struct autofs_point *ap
+ 		}
+ 		list_del(&entry->entries);
+ 		mounts_mutex_unlock(ap);
+-		umount_amd_ext_mount(ap, entry);
++		umount_amd_ext_mount(ap, entry->fs);
+ 		free_amd_entry(entry);
+ 		return 0;
+ 	}
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -97,8 +97,8 @@ unsigned int get_kver_minor(void);
+ char *make_options_string(char *path, int pipefd,
+ 			  const char *type, unsigned int flags);
+ char *make_mnt_name_string(char *path);
+-int ext_mount_add(struct list_head *, const char *, unsigned int);
+-int ext_mount_remove(struct list_head *, const char *);
++int ext_mount_add(const char *, const char *);
++int ext_mount_remove(const char *);
+ int ext_mount_inuse(const char *);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+@@ -118,7 +118,7 @@ int try_remount(struct autofs_point *, s
+ void set_indirect_mount_tree_catatonic(struct autofs_point *);
+ void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *);
+ int umount_ent(struct autofs_point *, const char *);
+-int umount_amd_ext_mount(struct autofs_point *, struct amd_entry *);
++int umount_amd_ext_mount(struct autofs_point *, const char *);
+ int mount_multi_triggers(struct autofs_point *, struct mapent *, const char *, unsigned int, const char *);
+ int umount_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
+ int clean_stale_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
+--- autofs-5.1.4.orig/include/parse_amd.h
++++ autofs-5.1.4/include/parse_amd.h
+@@ -66,7 +66,6 @@ struct amd_entry {
+ 	struct selector *selector;
+ 	struct list_head list;
+ 	struct list_head entries;
+-	struct list_head ext_mount;
+ };
+ 
+ int amd_parse_list(struct autofs_point *,
+--- autofs-5.1.4.orig/lib/master.c
++++ autofs-5.1.4/lib/master.c
+@@ -154,10 +154,9 @@ void master_free_autofs_point(struct aut
+ 	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);
++		ext_mount_remove(entry->fs);
+ 		free_amd_entry(entry);
+ 	}
+ 	mounts_mutex_unlock(ap);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -54,10 +54,10 @@ static size_t maxgrpbuf = 0;
+ #define EXT_MOUNTS_HASH_SIZE    50
+ 
+ struct ext_mount {
++	unsigned int ref;
+ 	char *mp;
+-	unsigned int umount;
++	char *umount;
+ 	struct list_head mount;
+-	struct list_head mounts;
+ };
+ static struct list_head ext_mounts_hash[EXT_MOUNTS_HASH_SIZE];
+ static unsigned int ext_mounts_hash_init_done = 0;
+@@ -542,7 +542,6 @@ struct amd_entry *new_amd_entry(const st
+ 	new->path = path;
+ 	INIT_LIST_HEAD(&new->list);
+ 	INIT_LIST_HEAD(&new->entries);
+-	INIT_LIST_HEAD(&new->ext_mount);
+ 
+ 	return new;
+ }
+@@ -763,7 +762,7 @@ static struct ext_mount *ext_mount_looku
+ 	return NULL;
+ }
+ 
+-int ext_mount_add(struct list_head *entry, const char *path, unsigned int umount)
++int ext_mount_add(const char *path, const char *umount)
+ {
+ 	struct ext_mount *em;
+ 	u_int32_t hval;
+@@ -773,13 +772,7 @@ int ext_mount_add(struct list_head *entr
+ 
+ 	em = ext_mount_lookup(path);
+ 	if (em) {
+-		struct list_head *p, *head;
+-		head = &em->mounts;
+-		list_for_each(p, head) {
+-			if (p == entry)
+-				goto done;
+-		}
+-		list_add_tail(entry, &em->mounts);
++		em->ref++;
+ 		ret = 1;
+ 		goto done;
+ 	}
+@@ -787,28 +780,34 @@ int ext_mount_add(struct list_head *entr
+ 	em = malloc(sizeof(struct ext_mount));
+ 	if (!em)
+ 		goto done;
++	memset(em, 0, sizeof(*em));
+ 
+ 	em->mp = strdup(path);
+ 	if (!em->mp) {
+ 		free(em);
+ 		goto done;
+ 	}
+-	em->umount = umount;
++	if (umount) {
++		em->umount = strdup(umount);
++		if (!em->umount) {
++			free(em->mp);
++			free(em);
++			goto done;
++		}
++	}
++	em->ref = 1;
+ 	INIT_LIST_HEAD(&em->mount);
+-	INIT_LIST_HEAD(&em->mounts);
+ 
+ 	hval = hash(path, EXT_MOUNTS_HASH_SIZE);
+ 	list_add_tail(&em->mount, &ext_mounts_hash[hval]);
+ 
+-	list_add_tail(entry, &em->mounts);
+-
+ 	ret = 1;
+ done:
+ 	pthread_mutex_unlock(&ext_mount_hash_mutex);
+ 	return ret;
+ }
+ 
+-int ext_mount_remove(struct list_head *entry, const char *path)
++int ext_mount_remove(const char *path)
+ {
+ 	struct ext_mount *em;
+ 	int ret = 0;
+@@ -819,18 +818,18 @@ int ext_mount_remove(struct list_head *e
+ 	if (!em)
+ 		goto done;
+ 
+-	list_del_init(entry);
+-
+-	if (!list_empty(&em->mounts))
++	em->ref--;
++	if (em->ref)
+ 		goto done;
+ 	else {
+ 		list_del_init(&em->mount);
+-		if (em->umount)
+-			ret = 1;
+ 		if (list_empty(&em->mount)) {
+ 			free(em->mp);
++			if (em->umount)
++				free(em->umount);
+ 			free(em);
+ 		}
++		ret = 1;
+ 	}
+ done:
+ 	pthread_mutex_unlock(&ext_mount_hash_mutex);
+@@ -846,9 +845,7 @@ int ext_mount_inuse(const char *path)
+ 	em = ext_mount_lookup(path);
+ 	if (!em)
+ 		goto done;
+-
+-	if (!list_empty(&em->mounts))
+-		ret = 1;
++	ret = em->ref;
+ done:
+ 	pthread_mutex_unlock(&ext_mount_hash_mutex);
+ 	return ret;
+@@ -2092,29 +2089,49 @@ int umount_ent(struct autofs_point *ap,
+ 	return rv;
+ }
+ 
+-int umount_amd_ext_mount(struct autofs_point *ap, struct amd_entry *entry)
++int umount_amd_ext_mount(struct autofs_point *ap, const char *path)
+ {
++	struct ext_mount *em;
++	char *umount = NULL;
++	char *mp;
+ 	int rv = 1;
+ 
+-	if (entry->umount) {
+-		char *prog, *str;
+-		char **argv;
+-		int argc = -1;
++	pthread_mutex_lock(&ext_mount_hash_mutex);
+ 
+-		str = strdup(entry->umount);
+-		if (!str)
++	em = ext_mount_lookup(path);
++	if (!em) {
++		pthread_mutex_unlock(&ext_mount_hash_mutex);
++		goto out;
++	}
++	mp = strdup(em->mp);
++	if (!mp) {
++		pthread_mutex_unlock(&ext_mount_hash_mutex);
++		goto out;
++	}
++	if (em->umount) {
++		umount = strdup(em->umount);
++		if (!umount) {
++			pthread_mutex_unlock(&ext_mount_hash_mutex);
++			free(mp);
+ 			goto out;
++		}
++	}
++
++	pthread_mutex_unlock(&ext_mount_hash_mutex);
++
++	if (umount) {
++		char *prog;
++		char **argv;
++		int argc = -1;
+ 
+ 		prog = NULL;
+ 		argv = NULL;
+ 
+-		argc = construct_argv(str, &prog, &argv);
+-		if (argc == -1) {
+-			free(str);
+-			goto out;
+-		}
++		argc = construct_argv(umount, &prog, &argv);
++		if (argc == -1)
++			goto done;
+ 
+-		if (!ext_mount_remove(&entry->ext_mount, entry->fs)) {
++		if (!ext_mount_remove(mp)) {
+ 			rv =0;
+ 			goto out_free;
+ 		}
+@@ -2122,29 +2139,30 @@ int umount_amd_ext_mount(struct autofs_p
+ 		rv = spawnv(ap->logopt, prog, (const char * const *) argv);
+ 		if (rv == -1 || (WIFEXITED(rv) && WEXITSTATUS(rv)))
+ 			error(ap->logopt,
+-			     "failed to umount program mount at %s", entry->fs);
++			     "failed to umount program mount at %s", mp);
+ 		else {
+ 			rv = 0;
+-			debug(ap->logopt,
+-			      "umounted program mount at %s", entry->fs);
+-			rmdir_path(ap, entry->fs, ap->dev);
++			debug(ap->logopt, "umounted program mount at %s", mp);
++			rmdir_path(ap, mp, ap->dev);
+ 		}
+ out_free:
+ 		free_argv(argc, (const char **) argv);
+-		free(str);
+ 
+-		goto out;
++		goto done;
+ 	}
+ 
+-	if (ext_mount_remove(&entry->ext_mount, entry->fs)) {
+-		rv = umount_ent(ap, entry->fs);
++	if (ext_mount_remove(mp)) {
++		rv = umount_ent(ap, mp);
+ 		if (rv)
+ 			error(ap->logopt,
+-			      "failed to umount external mount %s", entry->fs);
++			      "failed to umount external mount %s", mp);
+ 		else
+-			debug(ap->logopt,
+-			      "umounted external mount %s", entry->fs);
++			debug(ap->logopt, "umounted external mount %s", mp);
+ 	}
++done:
++	if (umount)
++		free(umount);
++	free(mp);
+ out:
+ 	return rv;
+ }
+--- autofs-5.1.4.orig/modules/parse_amd.c
++++ autofs-5.1.4/modules/parse_amd.c
+@@ -1136,7 +1136,7 @@ symlink:
+ 
+ 	if (entry->sublink) {
+ 		/* failed to complete sublink mount */
+-		umount_amd_ext_mount(ap, entry);
++		umount_amd_ext_mount(ap, entry->fs);
+ 	}
+ out:
+ 	return ret;
+@@ -1183,8 +1183,8 @@ static int do_generic_mount(struct autof
+ 				goto out;
+ 			umount = 1;
+ 		}
+-		/* We have an external mount */
+-		if (!ext_mount_add(&entry->ext_mount, entry->fs, umount)) {
++		/* If we have an external mount add it to the list */
++		if (umount && !ext_mount_add(entry->fs, entry->umount)) {
+ 			umount_ent(ap, entry->fs);
+ 			error(ap->logopt, MODPREFIX
+ 			      "error: could not add external mount %s",
+@@ -1235,7 +1235,7 @@ static int do_nfs_mount(struct autofs_po
+ 			umount = 1;
+ 		}
+ 		/* We might be using an external mount */
+-		if (!ext_mount_add(&entry->ext_mount, entry->fs, umount)) {
++		if (umount && !ext_mount_add(entry->fs, entry->umount)) {
+ 			umount_ent(ap, entry->fs);
+ 			error(ap->logopt, MODPREFIX
+ 			      "error: could not add external mount %s", entry->fs);
+@@ -1429,7 +1429,7 @@ static int do_program_mount(struct autof
+ 		/* An external mount with path entry->fs exists
+ 		 * so ext_mount_add() won't fail.
+ 		 */
+-		ext_mount_add(&entry->ext_mount, entry->fs, 1);
++		ext_mount_add(entry->fs, entry->umount);
+ 	} else {
+ 		rv = mkdir_path(entry->fs, mp_mode);
+ 		if (rv && errno != EEXIST) {
+@@ -1445,7 +1445,7 @@ static int do_program_mount(struct autof
+ 
+ 		rv = spawnv(ap->logopt, prog, (const char * const *) argv);
+ 		if (WIFEXITED(rv) && !WEXITSTATUS(rv)) {
+-			if (ext_mount_add(&entry->ext_mount, entry->fs, 1)) {
++			if (ext_mount_add(entry->fs, entry->umount)) {
+ 				rv = 0;
+ 				debug(ap->logopt, MODPREFIX
+ 				     "%s: mounted %s", entry->type, entry->fs);
+@@ -1470,7 +1470,7 @@ do_free:
+ 	if (!rv)
+ 		goto out;
+ 
+-	if (umount_amd_ext_mount(ap, entry)) {
++	if (umount_amd_ext_mount(ap, entry->fs)) {
+ 		if (!ext_mount_inuse(entry->fs))
+ 			rmdir_path(ap, entry->fs, ap->dev);
+ 		debug(ap->logopt, MODPREFIX
diff --git a/SOURCES/autofs-5.1.6-make-external-mounts-use-simpler-hashtable.patch b/SOURCES/autofs-5.1.6-make-external-mounts-use-simpler-hashtable.patch
new file mode 100644
index 0000000..044f74a
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-make-external-mounts-use-simpler-hashtable.patch
@@ -0,0 +1,128 @@
+autofs-5.1.6 - make external mounts use simpler hashtable
+
+From: Ian Kent <raven@themaw.net>
+
+Use the added hashtable implementation for the external mounts
+hashtable.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   49 +++++++++++++++----------------------------------
+ 2 files changed, 16 insertions(+), 34 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -120,6 +120,7 @@ xx/xx/2018 autofs-5.1.5
+ - add hashtable implementation.
+ - change mountpoint to mp in struct ext_mount.
+ - make external mounts independent of amd_entry.
++- make external mounts use simpler hashtable.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -29,6 +29,7 @@
+ #include <libgen.h>
+ 
+ #include "automount.h"
++#include "hashtable.h"
+ 
+ #define MAX_OPTIONS_LEN		80
+ #define MAX_MNT_NAME_LEN	30
+@@ -51,16 +52,15 @@ static const char kver_options_template[
+ extern size_t detached_thread_stack_size;
+ static size_t maxgrpbuf = 0;
+ 
+-#define EXT_MOUNTS_HASH_SIZE    50
++#define EXT_MOUNTS_HASH_BITS	6
+ 
+ struct ext_mount {
+ 	unsigned int ref;
+ 	char *mp;
+ 	char *umount;
+-	struct list_head mount;
++	struct hlist_node mount;
+ };
+-static struct list_head ext_mounts_hash[EXT_MOUNTS_HASH_SIZE];
+-static unsigned int ext_mounts_hash_init_done = 0;
++static DEFINE_HASHTABLE(ext_mounts_hash, EXT_MOUNTS_HASH_BITS);
+ static pthread_mutex_t ext_mount_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
+ 
+ unsigned int linux_version_code(void)
+@@ -734,38 +734,22 @@ char *make_mnt_name_string(char *path)
+ 	return mnt_name;
+ }
+ 
+-static void ext_mounts_hash_init(void)
+-{
+-	int i;
+-	for (i = 0; i < EXT_MOUNTS_HASH_SIZE; i++)
+-		INIT_LIST_HEAD(&ext_mounts_hash[i]);
+-	ext_mounts_hash_init_done = 1;
+-}
+-
+ static struct ext_mount *ext_mount_lookup(const char *mp)
+ {
+-	u_int32_t hval = hash(mp, EXT_MOUNTS_HASH_SIZE);
+-	struct list_head *p, *head;
+-
+-	if (!ext_mounts_hash_init_done)
+-		ext_mounts_hash_init();
+-
+-	if (list_empty(&ext_mounts_hash[hval]))
+-		return NULL;
++	uint32_t hval = hash(mp, HASH_SIZE(ext_mounts_hash));
++	struct ext_mount *this;
+ 
+-	head = &ext_mounts_hash[hval];
+-	list_for_each(p, head) {
+-		struct ext_mount *this = list_entry(p, struct ext_mount, mount);
++	hlist_for_each_entry(this, &ext_mounts_hash[hval], mount) {
+ 		if (!strcmp(this->mp, mp))
+ 			return this;
+ 	}
++
+ 	return NULL;
+ }
+ 
+ int ext_mount_add(const char *path, const char *umount)
+ {
+ 	struct ext_mount *em;
+-	u_int32_t hval;
+ 	int ret = 0;
+ 
+ 	pthread_mutex_lock(&ext_mount_hash_mutex);
+@@ -796,10 +780,9 @@ int ext_mount_add(const char *path, cons
+ 		}
+ 	}
+ 	em->ref = 1;
+-	INIT_LIST_HEAD(&em->mount);
++	INIT_HLIST_NODE(&em->mount);
+ 
+-	hval = hash(path, EXT_MOUNTS_HASH_SIZE);
+-	list_add_tail(&em->mount, &ext_mounts_hash[hval]);
++	hash_add_str(ext_mounts_hash, &em->mount, em->mp);
+ 
+ 	ret = 1;
+ done:
+@@ -822,13 +805,11 @@ int ext_mount_remove(const char *path)
+ 	if (em->ref)
+ 		goto done;
+ 	else {
+-		list_del_init(&em->mount);
+-		if (list_empty(&em->mount)) {
+-			free(em->mp);
+-			if (em->umount)
+-				free(em->umount);
+-			free(em);
+-		}
++		hlist_del_init(&em->mount);
++		free(em->mp);
++		if (em->umount)
++			free(em->umount);
++		free(em);
+ 		ret = 1;
+ 	}
+ done:
diff --git a/SOURCES/autofs-5.1.6-make-umount_autofs-static.patch b/SOURCES/autofs-5.1.6-make-umount_autofs-static.patch
new file mode 100644
index 0000000..94352b9
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-make-umount_autofs-static.patch
@@ -0,0 +1,86 @@
+autofs-5.1.6 - make umount_autofs() static
+
+From: Ian Kent <raven@themaw.net>
+
+The function umount_autofs() is only called within daemon/automount.c
+so make it static.
+
+Also it's only ever called with it's force parameter true so remove
+it as well and because this parameter is always true the failure case
+when calling umount_all() never happens.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/automount.c  |   11 +++++------
+ include/automount.h |    1 -
+ 3 files changed, 6 insertions(+), 7 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -124,6 +124,7 @@ xx/xx/2018 autofs-5.1.5
+ - add a hash index to mnt_list.
+ - use mnt_list for submounts.
+ - use mnt_list for amdmounts.
++- make umount_autofs() static.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -722,7 +722,7 @@ static int umount_all(struct autofs_poin
+ 	return left;
+ }
+ 
+-int umount_autofs(struct autofs_point *ap, const char *root, int force)
++static int umount_autofs(struct autofs_point *ap, const char *root)
+ {
+ 	int ret = 0;
+ 
+@@ -737,8 +737,7 @@ int umount_autofs(struct autofs_point *a
+ 	lookup_close_lookup(ap);
+ 
+ 	if (ap->type == LKP_INDIRECT) {
+-		if (umount_all(ap, force) && !force)
+-			return -1;
++		umount_all(ap, 1);
+ 		ret = umount_autofs_indirect(ap, root);
+ 	} else
+ 		ret = umount_autofs_direct(ap);
+@@ -1867,7 +1866,7 @@ int handle_mounts_exit(struct autofs_poi
+ 	 * to check for possible recovery.
+ 	 */
+ 	if (ap->type == LKP_DIRECT) {
+-		umount_autofs(ap, NULL, 1);
++		umount_autofs(ap, NULL);
+ 		handle_mounts_cleanup(ap);
+ 		return 1;
+ 	}
+@@ -1878,7 +1877,7 @@ int handle_mounts_exit(struct autofs_poi
+ 	 * so we can continue. This can happen if a lookup
+ 	 * occurs while we're trying to umount.
+ 	 */
+-	ret = umount_autofs(ap, NULL, 1);
++	ret = umount_autofs(ap, NULL);
+ 	if (!ret) {
+ 		set_indirect_mount_tree_catatonic(ap);
+ 		handle_mounts_cleanup(ap);
+@@ -1934,7 +1933,7 @@ void *handle_mounts(void *arg)
+ 		if (!(do_force_unlink & UNLINK_AND_EXIT))
+ 			crit(ap->logopt, "mount of %s failed!", ap->path);
+ 		suc->status = 1;
+-		umount_autofs(ap, root, 1);
++		umount_autofs(ap, root);
+ 		free(root);
+ 		pthread_setcancelstate(cancel_state, NULL);
+ 		pthread_exit(NULL);
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -599,7 +599,6 @@ int mount_autofs_direct(struct autofs_po
+ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *root, const char *offset);
+ void submount_signal_parent(struct autofs_point *ap, unsigned int success);
+ void close_mount_fds(struct autofs_point *ap);
+-int umount_autofs(struct autofs_point *ap, const char *root, int force);
+ int umount_autofs_indirect(struct autofs_point *ap, const char *root);
+ int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me);
+ int umount_autofs_direct(struct autofs_point *ap);
diff --git a/SOURCES/autofs-5.1.6-move-lib_master_c-to-daemon_master_c.patch b/SOURCES/autofs-5.1.6-move-lib_master_c-to-daemon_master_c.patch
new file mode 100644
index 0000000..090a661
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-move-lib_master_c-to-daemon_master_c.patch
@@ -0,0 +1,6877 @@
+autofs-5.1.6 - move lib/master.c to daemon/master.c
+
+From: Ian Kent <raven@themaw.net>
+
+The lib subdirectory isn't really the right place for master.c, move
+it to the deamon subdirectory.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG             |    1 
+ daemon/Makefile       |   19 
+ daemon/master.c       | 1885 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ daemon/master_parse.y |  983 ++++++++++++++++++++++++++
+ daemon/master_tok.l   |  504 +++++++++++++
+ lib/Makefile          |   23 
+ lib/master.c          | 1885 --------------------------------------------------
+ lib/master_parse.y    |  983 --------------------------
+ lib/master_tok.l      |  504 -------------
+ 9 files changed, 3394 insertions(+), 3393 deletions(-)
+ create mode 100644 daemon/master.c
+ create mode 100644 daemon/master_parse.y
+ create mode 100644 daemon/master_tok.l
+ delete mode 100644 lib/master.c
+ delete mode 100644 lib/master_parse.y
+ delete mode 100644 lib/master_tok.l
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -133,6 +133,7 @@ xx/xx/2018 autofs-5.1.5
+ - remove unused function tree_get_mnt_list().
+ - only add expre alarm for active mounts.
+ - move submount check into conditional_alarm_add().
++- move lib/master.c to daemon/master.c.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/Makefile
++++ autofs-5.1.4/daemon/Makefile
+@@ -6,9 +6,12 @@
+ include ../Makefile.rules
+ 
+ SRCS = automount.c indirect.c direct.c spawn.c module.c mount.c \
+-	lookup.c state.c flag.c
++	master.c master_tok.l master_parse.y lookup.c state.c flag.c
+ OBJS = automount.o indirect.o direct.o spawn.o module.o mount.o \
+-	lookup.o state.o flag.o
++	master.o master_tok.o master_parse.tab.o lookup.o state.o \
++	flag.o
++
++YACCSRC = master_tok.c master_parse.tab.c master_parse.tab.h
+ 
+ version := $(shell cat ../.version)
+ 
+@@ -38,8 +41,18 @@ automount: $(OBJS) $(AUTOFS_LIB)
+ 	$(CC) $(DAEMON_LDFLAGS) -o automount $(OBJS) $(LDFLAGS) $(AUTOFS_LIB) $(LIBS)
+ 	$(STRIP) automount
+ 
++master_tok.c: master_tok.l
++	$(LEX) -o$@ -Pmaster_ $?
++
++master_parse.tab.c master_parse.tab.h: master_parse.y
++	$(YACC) -v -d -p master_ -b master_parse $?
++
++master_tok.o: master_tok.c master_parse.tab.h
++
++master_parse.tab.o: master_parse.tab.c master_parse.tab.h
++
+ clean:
+-	rm -f *.o *.s *~ automount
++	rm -f *.o *.s *~ $(YACCSRC) *.output *~ automount
+ 
+ install: all
+ 	install -d -m 755 $(INSTALLROOT)$(sbindir)
+--- /dev/null
++++ autofs-5.1.4/daemon/master.c
+@@ -0,0 +1,1885 @@
++/* ----------------------------------------------------------------------- *
++ *   
++ *  master.c - master map utility routines.
++ *
++ *   Copyright 2006 Ian Kent <raven@themaw.net>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU General Public License as published by
++ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
++ *   USA; either version 2 of the License, or (at your option) any later
++ *   version.
++ *   
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details.
++ *
++ * ----------------------------------------------------------------------- */
++
++#include <stdlib.h>
++#include <string.h>
++#include <memory.h>
++#include <limits.h>
++#include <signal.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <ctype.h>
++#include "automount.h"
++
++/* The root of the map entry tree */
++struct master *master_list = NULL;
++
++extern const char *global_options;
++extern long global_negative_timeout;
++
++/* Attribute to create a joinable thread */
++extern pthread_attr_t th_attr;
++
++extern struct startup_cond suc;
++
++static struct map_source *
++__master_find_map_source(struct master_mapent *,
++			 const char *, const char *, int, const char **);
++
++static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
++static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
++
++void master_mutex_lock(void)
++{
++	int status = pthread_mutex_lock(&master_mutex);
++	if (status)
++		fatal(status);
++}
++
++void master_mutex_unlock(void)
++{
++	int status = pthread_mutex_unlock(&master_mutex);
++	if (status)
++		fatal(status);
++}
++
++void master_mutex_lock_cleanup(void *arg)
++{
++	master_mutex_unlock();
++	return;
++}
++
++int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
++			    unsigned nobind, unsigned ghost, int submount)
++{
++	struct autofs_point *ap;
++	int status;
++
++	ap = malloc(sizeof(struct autofs_point));
++	if (!ap)
++		return 0;
++
++	ap->state = ST_INIT;
++
++	ap->state_pipe[0] = -1;
++	ap->state_pipe[1] = -1;
++	ap->logpri_fifo = -1;
++
++	ap->path = strdup(entry->path);
++	if (!ap->path) {
++		free(ap);
++		return 0;
++	}
++	ap->pref = NULL;
++
++	ap->entry = entry;
++	ap->exp_thread = 0;
++	ap->readmap_thread = 0;
++	/*
++	 * Program command line option overrides config.
++	 * We can't use 0 negative timeout so use default.
++	 */
++	if (global_negative_timeout <= 0)
++		ap->negative_timeout = defaults_get_negative_timeout();
++	else
++		ap->negative_timeout = global_negative_timeout;
++	ap->exp_timeout = defaults_get_timeout();
++	ap->exp_runfreq = 0;
++	ap->flags = 0;
++
++	if (defaults_get_use_ignore_mount_option())
++		ap->flags = MOUNT_FLAG_IGNORE;
++	if (ghost)
++		ap->flags |= MOUNT_FLAG_GHOST;
++
++	if (nobind)
++		ap->flags |= MOUNT_FLAG_NOBIND;
++
++	if (ap->path[1] == '-')
++		ap->type = LKP_DIRECT;
++	else
++		ap->type = LKP_INDIRECT;
++
++	ap->logopt = logopt;
++
++	ap->parent = NULL;
++	ap->thid = 0;
++	ap->submnt_count = 0;
++	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);
++	if (status) {
++		free(ap->path);
++		free(ap);
++		return 0;
++	}
++	ap->mode = 0;
++
++	entry->ap = ap;
++
++	return 1;
++}
++
++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 mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
++		p = p->next;
++		ext_mount_remove(mnt->ext_mp);
++		mnts_remove_amdmount(mnt->mp);
++	}
++	mounts_mutex_unlock(ap);
++
++	status = pthread_mutex_destroy(&ap->mounts_mutex);
++	if (status)
++		fatal(status);
++
++	if (ap->pref)
++		free(ap->pref);
++	free(ap->path);
++	free(ap);
++}
++
++struct map_source *
++master_add_map_source(struct master_mapent *entry,
++		      char *type, char *format, time_t age,
++		      int argc, const char **argv)
++{
++	struct map_source *source;
++	char *ntype, *nformat;
++	const char **tmpargv;
++
++	source = malloc(sizeof(struct map_source));
++	if (!source)
++		return NULL;
++	memset(source, 0, sizeof(struct map_source));
++	source->ref = 1;
++
++	if (type) {
++		ntype = strdup(type);
++		if (!ntype) {
++			master_free_map_source(source, 0);
++			return NULL;
++		}
++		source->type = ntype;
++	}
++
++	if (format) {
++		nformat = strdup(format);
++		if (!nformat) {
++			master_free_map_source(source, 0);
++			return NULL;
++		}
++		source->format = nformat;
++		if (!strcmp(nformat, "amd"))
++			source->flags |= MAP_FLAG_FORMAT_AMD;
++	}
++
++	source->age = age;
++	source->stale = 1;
++
++	tmpargv = copy_argv(argc, argv);
++	if (!tmpargv) {
++		master_free_map_source(source, 0);
++		return NULL;
++	}
++	source->argc = argc;
++	source->argv = tmpargv;
++	if (source->argv[0])
++		source->name = strdup(source->argv[0]);
++
++	master_source_writelock(entry);
++
++	if (!entry->maps) {
++		source->mc = cache_init(entry->ap, source);
++		if (!source->mc) {
++			master_free_map_source(source, 0);
++			master_source_unlock(entry);
++			return NULL;
++		}
++		entry->maps = source;
++	} else {
++		struct map_source *this, *last, *next;
++
++		/* Typically there only a few map sources */
++
++		this = __master_find_map_source(entry, type, format, argc, tmpargv);
++		if (this) {
++			debug(entry->ap->logopt,
++			      "map source used without taking reference");
++			this->age = age;
++			master_free_map_source(source, 0);
++			master_source_unlock(entry);
++			return this;
++		}
++
++		source->mc = cache_init(entry->ap, source);
++		if (!source->mc) {
++			master_free_map_source(source, 0);
++			master_source_unlock(entry);
++			return NULL;
++		}
++
++		last = NULL;
++		next = entry->maps;
++		while (next) {
++			last = next;
++			next = next->next;
++		}
++		if (last)
++			last->next = source;
++		else
++			entry->maps = source;
++	}
++
++	master_source_unlock(entry);
++
++	return source;
++}
++
++static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
++{
++	int res = 0;
++
++	if (type) {
++		if (!map->type)
++			goto done;
++
++		if (strcmp(map->type, type))
++			goto done;
++	} else if (map->type)
++		goto done;
++
++	if (format) {
++		if (!map->format)
++			goto done;
++
++		if (strcmp(map->format, format))
++			goto done;
++	} else if (map->format)
++		goto done;
++
++	res = 1;
++done:
++	return res;
++}
++
++static struct map_source *
++__master_find_map_source(struct master_mapent *entry,
++			 const char *type, const char *format,
++			 int argc, const char **argv)
++{
++	struct map_source *map;
++	struct map_source *source = NULL;
++	int res;
++
++	map = entry->maps;
++	while (map) {
++		res = compare_source_type_and_format(map, type, format);
++		if (!res)
++			goto next;
++
++		res = compare_argv(map->argc, map->argv, argc, argv);
++		if (!res)
++			goto next;
++
++		source = map;
++		break;
++next:
++		map = map->next;
++	}
++
++	return source;
++}
++
++struct map_source *master_find_map_source(struct master_mapent *entry,
++				const char *type, const char *format,
++				int argc, const char **argv)
++{
++	struct map_source *source = NULL;
++
++	master_source_readlock(entry);
++	source = __master_find_map_source(entry, type, format, argc, argv);
++	master_source_unlock(entry);
++
++	return source;
++}
++
++struct map_source *
++master_get_map_source(struct master_mapent *entry,
++		      const char *type, const char *format,
++		      int argc, const char **argv)
++{
++	struct map_source *source = NULL;
++
++	master_source_readlock(entry);
++	source = __master_find_map_source(entry, type, format, argc, argv);
++	if (source)
++		source->ref++;
++	master_source_unlock(entry);
++
++	return source;
++}
++
++static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
++{
++	/* instance map sources are not ref counted */
++	if (source->ref && --source->ref)
++		return;
++	if (source->type)
++		free(source->type);
++	if (source->format)
++		free(source->format);
++	if (source->name)
++		free(source->name);
++	if (free_cache && source->mc)
++		cache_release(source);
++	if (source->lookup) {
++		struct map_source *instance;
++
++		instance = source->instance;
++		while (instance) {
++			if (instance->lookup)
++				close_lookup(instance->lookup);
++			instance = instance->next;
++		}
++		close_lookup(source->lookup);
++	}
++	if (source->argv)
++		free_argv(source->argc, source->argv);
++	if (source->instance) {
++		struct map_source *instance, *next;
++
++		instance = source->instance;
++		while (instance) {
++			next = instance->next;
++			__master_free_map_source(instance, 0);
++			instance = next;
++		}
++	}
++
++	free(source);
++
++	return;
++}
++
++void master_free_map_source(struct map_source *source, unsigned int free_cache)
++{
++	int status;
++
++	status = pthread_mutex_lock(&instance_mutex);
++	if (status)
++		fatal(status);
++
++	__master_free_map_source(source, free_cache);
++
++	status = pthread_mutex_unlock(&instance_mutex);
++	if (status)
++		fatal(status);
++}
++
++struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
++{
++	struct map_source *map;
++	struct map_source *instance = NULL;
++	int status, res;
++
++	status = pthread_mutex_lock(&instance_mutex);
++	if (status)
++		fatal(status);
++
++	map = source->instance;
++	while (map) {
++		res = compare_source_type_and_format(map, type, format);
++		if (!res)
++			goto next;
++
++		if (!argv) {
++			instance = map;
++			break;
++		}
++
++		res = compare_argv(map->argc, map->argv, argc, argv);
++		if (!res)
++			goto next;
++
++		instance = map;
++		break;
++next:
++		map = map->next;
++	}
++
++	status = pthread_mutex_unlock(&instance_mutex);
++	if (status)
++		fatal(status);
++
++	return instance;
++}
++
++struct map_source *
++master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
++{
++	struct map_source *instance;
++	struct map_source *new;
++	char *ntype, *nformat;
++	const char **tmpargv;
++	int status;
++
++	instance = master_find_source_instance(source, type, format, argc, argv);
++	if (instance)
++		return instance;
++
++	new = malloc(sizeof(struct map_source));
++	if (!new)
++		return NULL;
++	memset(new, 0, sizeof(struct map_source));
++
++	if (type) {
++		ntype = strdup(type);
++		if (!ntype) {
++			master_free_map_source(new, 0);
++			return NULL;
++		}
++		new->type = ntype;
++	}
++
++	if (format) {
++		nformat = strdup(format);
++		if (!nformat) {
++			master_free_map_source(new, 0);
++			return NULL;
++		}
++		new->format = nformat;
++		if (!strcmp(nformat, "amd"))
++			new->flags |= MAP_FLAG_FORMAT_AMD;
++	}
++
++	new->age = age;
++	new->master_line = 0;
++	new->mc = source->mc;
++	new->exp_timeout = source->exp_timeout;
++	new->stale = 1;
++
++	tmpargv = copy_argv(argc, argv);
++	if (!tmpargv) {
++		master_free_map_source(new, 0);
++		return NULL;
++	}
++	new->argc = argc;
++	new->argv = tmpargv;
++	if (source->name)
++		new->name = strdup(source->name);
++
++	status = pthread_mutex_lock(&instance_mutex);
++	if (status)
++		fatal(status);
++
++	if (!source->instance)
++		source->instance = new;
++	else {
++		/*
++		 * We know there's no other instance of this
++		 * type so just add to head of list
++		 */
++		new->next = source->instance;
++		source->instance = new;
++	}
++
++	status = pthread_mutex_unlock(&instance_mutex);
++	if (status)
++		fatal(status);
++
++	return new;
++}
++
++int check_stale_instances(struct map_source *source)
++{
++	struct map_source *map;
++
++	if (!source)
++		return 0;
++
++	map = source->instance;
++	while (map) {
++		if (map->stale)
++			return 1;
++		if (check_stale_instances(map))
++			return 1;
++		map = map->next;
++	}
++
++	return 0;
++}
++
++void clear_stale_instances(struct map_source *source)
++{
++	struct map_source *map;
++
++	if (!source)
++		return;
++
++	map = source->instance;
++	while (map) {
++		clear_stale_instances(map);
++		if (map->stale)
++			map->stale = 0;
++		map = map->next;
++	}
++
++	return;
++}
++
++void send_map_update_request(struct autofs_point *ap)
++{
++	struct map_source *map;
++	int status, need_update = 0;
++
++	status = pthread_mutex_lock(&instance_mutex);
++	if (status)
++		fatal(status);
++
++	map = ap->entry->maps;
++	while (map) {
++		if (check_stale_instances(map))
++			map->stale = 1;
++		if (map->stale) {
++			need_update = 1;
++			break;
++		}
++		map = map->next;
++	}
++
++	status = pthread_mutex_unlock(&instance_mutex);
++	if (status)
++		fatal(status);
++
++	if (!need_update)
++		return;
++
++	st_add_task(ap, ST_READMAP);
++
++	return;
++}
++
++void master_source_writelock(struct master_mapent *entry)
++{
++	int status;
++
++	status = pthread_rwlock_wrlock(&entry->source_lock);
++	if (status) {
++		logmsg("master_mapent source write lock failed");
++		fatal(status);
++	}
++	return;
++}
++
++void master_source_readlock(struct master_mapent *entry)
++{
++	int retries = 25;
++	int status;
++
++	while (retries--) {
++		status = pthread_rwlock_rdlock(&entry->source_lock);
++		if (status != EAGAIN && status != EBUSY)
++			break;
++		else {
++                	struct timespec t = { 0, 200000000 };
++	                struct timespec r;
++
++			if (status == EAGAIN)
++				logmsg("master_mapent source too many readers");
++			else
++				logmsg("master_mapent source write lock held");
++
++                	while (nanosleep(&t, &r) == -1 && errno == EINTR)
++                        	memcpy(&t, &r, sizeof(struct timespec));
++		}
++	}
++
++	if (status) {
++		logmsg("master_mapent source read lock failed");
++		fatal(status);
++	}
++
++	return;
++}
++
++void master_source_unlock(struct master_mapent *entry)
++{
++	int status;
++
++	status = pthread_rwlock_unlock(&entry->source_lock);
++	if (status) {
++		logmsg("master_mapent source unlock failed");
++		fatal(status);
++	}
++	return;
++}
++
++void master_source_lock_cleanup(void *arg)
++{
++	struct master_mapent *entry = (struct master_mapent *) arg;
++
++	master_source_unlock(entry);
++
++	return;
++}
++
++void master_source_current_wait(struct master_mapent *entry)
++{
++	int status;
++
++	status = pthread_mutex_lock(&entry->current_mutex);
++	if (status) {
++		logmsg("entry current source lock failed");
++		fatal(status);
++	}
++
++	while (entry->current != NULL) {
++		status = pthread_cond_wait(
++				&entry->current_cond, &entry->current_mutex);
++		if (status) {
++			logmsg("entry current source condition wait failed");
++			fatal(status);
++		}
++	}
++
++	return;
++}
++
++void master_source_current_signal(struct master_mapent *entry)
++{
++	int status;
++
++	status = pthread_cond_signal(&entry->current_cond);
++	if (status) {
++		logmsg("entry current source condition signal failed");
++		fatal(status);
++	}
++
++	status = pthread_mutex_unlock(&entry->current_mutex);
++	if (status) {
++		logmsg("entry current source unlock failed");
++		fatal(status);
++	}
++
++	return;
++}
++
++struct master_mapent *master_find_mapent(struct master *master, const char *path)
++{
++	struct list_head *head, *p;
++
++	head = &master->mounts;
++	list_for_each(p, head) {
++		struct master_mapent *entry;
++
++		entry = list_entry(p, struct master_mapent, list);
++
++		if (!strcmp(entry->path, path))
++			return entry;
++	}
++
++	return NULL;
++}
++
++unsigned int master_partial_match_mapent(struct master *master, const char *path)
++{
++	struct list_head *head, *p;
++	size_t path_len = strlen(path);
++	int ret = 0;
++
++	head = &master->mounts;
++	list_for_each(p, head) {
++		struct master_mapent *entry;
++		size_t entry_len;
++		size_t cmp_len;
++
++		entry = list_entry(p, struct master_mapent, list);
++
++		entry_len = strlen(entry->path);
++		cmp_len = min(entry_len, path_len);
++
++		if (!strncmp(entry->path, path, cmp_len)) {
++			/* paths are equal, matching master map entry ? */
++			if (entry_len == path_len) {
++				if (entry->maps &&
++				    entry->maps->flags & MAP_FLAG_FORMAT_AMD)
++					ret = 1;
++				else
++					ret = -1;
++				break;
++			}
++
++			/* amd mount conflicts with entry mount */
++			if (entry_len > path_len &&
++			    *(entry->path + path_len) == '/') {
++				ret = -1;
++				break;
++			}
++
++			/* entry mount conflicts with amd mount */
++			if (entry_len < path_len &&
++			    *(path + entry_len) == '/') {
++				ret = -1;
++				break;
++			}
++		}
++	}
++
++	return ret;
++}
++
++struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
++{
++	struct master_mapent *entry;
++	int status;
++	char *tmp;
++
++	entry = malloc(sizeof(struct master_mapent));
++	if (!entry)
++		return NULL;
++
++	memset(entry, 0, sizeof(struct master_mapent));
++
++	tmp = strdup(path);
++	if (!tmp) {
++		free(entry);
++		return NULL;
++	}
++	entry->path = tmp;
++
++	entry->thid = 0;
++	entry->age = age;
++	entry->master = master;
++	entry->current = NULL;
++	entry->maps = NULL;
++	entry->ap = NULL;
++
++	status = pthread_rwlock_init(&entry->source_lock, NULL);
++	if (status)
++		fatal(status);
++
++	status = pthread_mutex_init(&entry->current_mutex, NULL);
++	if (status)
++		fatal(status);
++
++	status = pthread_cond_init(&entry->current_cond, NULL);
++	if (status)
++		fatal(status);
++
++	INIT_LIST_HEAD(&entry->list);
++
++	return entry;
++}
++
++void master_add_mapent(struct master *master, struct master_mapent *entry)
++{
++	list_add_tail(&entry->list, &master->mounts);
++	return;
++}
++
++void master_remove_mapent(struct master_mapent *entry)
++{
++	struct master *master = entry->master;
++
++	if (entry->ap->submount)
++		return;
++
++	if (!list_empty(&entry->list)) {
++		list_del_init(&entry->list);
++		list_add(&entry->join, &master->completed);
++	}
++
++	return;
++}
++
++void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
++{
++	if (entry->maps) {
++		struct map_source *m, *n;
++
++		m = entry->maps;
++		while (m) {
++			n = m->next;
++			master_free_map_source(m, free_cache);
++			m = n;
++		}
++		entry->maps = NULL;
++	}
++
++	return;
++}
++
++void master_free_mapent(struct master_mapent *entry)
++{
++	int status;
++
++	if (entry->path)
++		free(entry->path);
++
++	master_free_autofs_point(entry->ap);
++
++	status = pthread_rwlock_destroy(&entry->source_lock);
++	if (status)
++		fatal(status);
++
++	status = pthread_mutex_destroy(&entry->current_mutex);
++	if (status)
++		fatal(status);
++
++	status = pthread_cond_destroy(&entry->current_cond);
++	if (status)
++		fatal(status);
++
++	free(entry);
++
++	return;
++}
++
++struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
++{
++	struct master *master;
++	char *tmp;
++
++	master = malloc(sizeof(struct master));
++	if (!master)
++		return NULL;
++
++	if (!name)
++		tmp = (char *) defaults_get_master_map();
++	else
++		tmp = strdup(name);
++
++	if (!tmp) {
++		free(master);
++		return NULL;
++	}
++
++	master->name = tmp;
++	master->nc = NULL;
++
++	master->recurse = 0;
++	master->depth = 0;
++	master->reading = 0;
++	master->read_fail = 0;
++	master->readall = 0;
++	master->default_ghost = flags & DAEMON_FLAGS_GHOST;
++	master->default_timeout = timeout;
++	master->default_logging = defaults_get_logging();
++	master->logopt = master->default_logging;
++
++	INIT_LIST_HEAD(&master->mounts);
++	INIT_LIST_HEAD(&master->completed);
++
++	return master;
++}
++
++static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
++{
++	unsigned int m_logopt = master->logopt;
++	struct master_mapent *entry;
++	struct map_source *source;
++	unsigned int loglevel;
++	unsigned int logopt;
++	unsigned int flags;
++	char *argv[2];
++	char **paths;
++	int ret;
++	int i;
++
++	loglevel = conf_amd_get_log_options();
++
++	paths = conf_amd_get_mount_paths();
++	if (!paths)
++		return;
++
++	i = 0;
++	while (paths[i]) {
++		const char *path = paths[i];
++		unsigned int ghost = 0;
++		time_t timeout;
++		char *type = NULL;
++		char *map = NULL;
++		char *opts;
++
++		ret = master_partial_match_mapent(master, path);
++		if (ret) {
++			/* If this amd entry is already present in the
++			 * master map it's not a duplicate, don't issue
++			 * an error message.
++			 */
++			if (ret == 1)
++				goto next;
++			info(m_logopt,
++			     "amd section mount path conflict, %s ignored",
++			     path);
++			goto next;
++		}
++
++		map = conf_amd_get_map_name(path);
++		if (!map) {
++			error(m_logopt,
++			      "failed to get map name for amd section mount %s",
++			      path);
++			goto next;
++		}
++
++		entry = master_new_mapent(master, path, age);
++		if (!entry) {
++			error(m_logopt,
++			      "failed to allocate new amd section mount %s",
++			      path);
++			goto next;
++		}
++
++		logopt = m_logopt;
++		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
++			logopt = LOGOPT_DEBUG;
++		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
++			logopt = LOGOPT_VERBOSE;
++
++		/* It isn't possible to provide the fullybrowsable amd
++		 * browsing functionality within the autofs framework.
++		 * This flag will not be set if browsable_dirs = full
++		 * in the configuration or fullybrowsable is present as
++		 * an option.
++		 */
++		flags = conf_amd_get_flags(path);
++		if (flags & CONF_BROWSABLE_DIRS)
++			ghost = 1;
++
++		ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
++		if (!ret) {
++			error(m_logopt, "failed to add autofs_point");
++			master_free_mapent(entry);
++			goto next;
++		}
++
++		opts = conf_amd_get_map_options(path);
++		if (opts) {
++			/* autofs uses the equivalent of cache:=inc,sync
++			 * (except for file maps which use cache:=all,sync)
++			 * but if the map is large then it may be necessary
++			 * to read the whole map at startup even if browsing
++			 * is is not enabled, so look for cache:=all in the
++			 * map_options configuration entry.
++			 */
++			if (strstr(opts, "cache:=all"))
++				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
++			free(opts);
++		}
++
++		type = conf_amd_get_map_type(path);
++		argv[0] = map;
++		argv[1] = NULL;
++
++		source = master_add_map_source(entry, type, "amd",
++					       age, 1, (const char **) argv);
++		if (!source) {
++			error(m_logopt,
++			      "failed to add source for amd section mount %s",
++			      path);
++			master_free_mapent(entry);
++			goto next;
++		}
++
++		timeout = conf_amd_get_dismount_interval(path);
++		set_exp_timeout(entry->ap, source, timeout);
++		source->master_line = 0;
++
++		entry->age = age;
++		entry->current = NULL;
++
++		master_add_mapent(master, entry);
++next:
++		if (type)
++			free(type);
++		if (map)
++			free(map);
++		i++;
++	}
++
++	i = 0;
++	while (paths[i])
++		free(paths[i++]);
++	free(paths);
++}
++
++static void wait_for_lookups_and_lock(struct master *master)
++{
++	struct list_head *p, *head;
++	int status;
++
++again:
++	master_mutex_lock();
++
++	head = &master->mounts;
++	p = head->next;
++	while (p != head) {
++		struct master_mapent *this;
++
++		this = list_entry(p, struct master_mapent, list);
++
++		status = pthread_rwlock_trywrlock(&this->source_lock);
++		if (status) {
++			struct timespec t = { 0, 200000000 };
++			struct timespec r;
++
++			master_mutex_unlock();
++
++			while (nanosleep(&t, &r) == -1 && errno == EINTR)
++				memcpy(&t, &r, sizeof(struct timespec));
++
++			goto again;
++		}
++		master_source_unlock(this);
++
++		p = p->next;
++	}
++}
++
++int master_read_master(struct master *master, time_t age)
++{
++	unsigned int logopt = master->logopt;
++	struct mapent_cache *nc;
++
++	/*
++	 * We need to clear and re-populate the null map entry cache
++	 * before alowing anyone else to use it.
++	 */
++	wait_for_lookups_and_lock(master);
++	if (master->nc) {
++		cache_writelock(master->nc);
++		nc = master->nc;
++		cache_clean_null_cache(nc);
++	} else {
++		nc = cache_init_null_cache(master);
++		if (!nc) {
++			error(logopt,
++			      "failed to init null map cache for %s",
++			      master->name);
++			return 0;
++		}
++		cache_writelock(nc);
++		master->nc = nc;
++	}
++	master_init_scan();
++	lookup_nss_read_master(master, age);
++	cache_unlock(nc);
++	master_add_amd_mount_section_mounts(master, age);
++
++	if (!master->read_fail)
++		master_mount_mounts(master, age);
++	else {
++		master->read_fail = 0;
++		/* HUP signal sets master->readall == 1 only */
++		if (!master->readall) {
++			master_mutex_unlock();
++			return 0;
++		} else
++			master_mount_mounts(master, age);
++	}
++
++	if (list_empty(&master->mounts))
++		warn(logopt, "no mounts in table");
++
++	master_mutex_unlock();
++
++	return 1;
++}
++
++int master_submount_list_empty(struct autofs_point *ap)
++{
++	int res = 0;
++
++	mounts_mutex_lock(ap);
++	if (list_empty(&ap->submounts))
++		res = 1;
++	mounts_mutex_unlock(ap);
++
++	return res;
++}
++
++int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
++{
++	struct mnt_list *this, *sbmnt;
++	int ret = 1;
++
++	this = mnts_find_submount(path);
++	if (this) {
++		/* We have found a submount to expire */
++		st_mutex_lock();
++
++		if (this->ap->state == ST_SHUTDOWN) {
++			this = NULL;
++			st_mutex_unlock();
++			goto done;
++		}
++
++		this->ap->shutdown = ap->shutdown;
++
++		__st_add_task(this->ap, state);
++
++		st_mutex_unlock();
++
++		st_wait_task(this->ap, state, 0);
++
++		/*
++		 * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
++		 * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
++		 * to ST_READY.
++		 */
++		st_mutex_lock();
++		while ((sbmnt = mnts_find_submount(path))) {
++			struct timespec t = { 0, 300000000 };
++			struct timespec r;
++
++			if (sbmnt->ap->state != ST_SHUTDOWN &&
++			    sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
++			    sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
++				ret = 0;
++				mnts_put_mount(sbmnt);
++				break;
++			}
++			mnts_put_mount(sbmnt);
++
++			st_mutex_unlock();
++			while (nanosleep(&t, &r) == -1 && errno == EINTR)
++				memcpy(&t, &r, sizeof(struct timespec));
++			st_mutex_lock();
++		}
++		st_mutex_unlock();
++done:
++		mnts_put_mount(this);
++	}
++
++	return ret;
++}
++
++void master_notify_state_change(struct master *master, int sig)
++{
++	struct master_mapent *entry;
++	struct autofs_point *ap;
++	struct list_head *p;
++	int cur_state;
++	unsigned int logopt;
++
++	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
++	master_mutex_lock();
++
++	list_for_each(p, &master->mounts) {
++		enum states next = ST_INVAL;
++
++		entry = list_entry(p, struct master_mapent, list);
++
++		ap = entry->ap;
++		logopt = ap->logopt;
++
++		st_mutex_lock();
++
++		if (ap->state == ST_SHUTDOWN)
++			goto next;
++
++		switch (sig) {
++		case SIGTERM:
++		case SIGINT:
++			if (ap->state != ST_SHUTDOWN_PENDING &&
++			    ap->state != ST_SHUTDOWN_FORCE) {
++				next = ST_SHUTDOWN_PENDING;
++				ap->shutdown = 1;
++				__st_add_task(ap, next);
++			}
++			break;
++#ifdef ENABLE_FORCED_SHUTDOWN
++		case SIGUSR2:
++			if (ap->state != ST_SHUTDOWN_FORCE &&
++			    ap->state != ST_SHUTDOWN_PENDING) {
++				next = ST_SHUTDOWN_FORCE;
++				ap->shutdown = 1;
++				__st_add_task(ap, next);
++			}
++			break;
++#endif
++		case SIGUSR1:
++			assert(ap->state == ST_READY);
++			next = ST_PRUNE;
++			__st_add_task(ap, next);
++			break;
++		}
++next:
++		if (next != ST_INVAL)
++			debug(logopt,
++			      "sig %d switching %s from %d to %d",
++			      sig, ap->path, ap->state, next);
++
++		st_mutex_unlock();
++	}
++
++	master_mutex_unlock();
++	pthread_setcancelstate(cur_state, NULL);
++
++	return;
++}
++
++static int master_do_mount(struct master_mapent *entry)
++{
++	struct startup_cond suc;
++	struct autofs_point *ap;
++	pthread_t thid;
++	int status;
++
++	ap = entry->ap;
++
++	if (handle_mounts_startup_cond_init(&suc)) {
++		crit(ap->logopt,
++		     "failed to init startup cond for mount %s", entry->path);
++		return 0;
++	}
++
++	suc.ap = ap;
++	suc.root = ap->path;
++	suc.done = 0;
++	suc.status = 0;
++
++	if (!(do_force_unlink & UNLINK_AND_EXIT))
++		debug(ap->logopt, "mounting %s", entry->path);
++
++	status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
++	if (status) {
++		crit(ap->logopt,
++		     "failed to create mount handler thread for %s",
++		     entry->path);
++		handle_mounts_startup_cond_destroy(&suc);
++		return 0;
++	}
++
++	while (!suc.done) {
++		status = pthread_cond_wait(&suc.cond, &suc.mutex);
++		if (status)
++			fatal(status);
++	}
++
++	if (suc.status) {
++		if (!(do_force_unlink & UNLINK_AND_EXIT))
++			error(ap->logopt, "failed to startup mount");
++		handle_mounts_startup_cond_destroy(&suc);
++		return 0;
++	}
++	entry->thid = thid;
++
++	handle_mounts_startup_cond_destroy(&suc);
++
++	return 1;
++}
++
++static void check_update_map_sources(struct master_mapent *entry, int readall)
++{
++	struct map_source *source, *last;
++	struct autofs_point *ap;
++	int map_stale = 0;
++
++	if (readall)
++		map_stale = 1;
++
++	ap = entry->ap;
++
++	master_source_writelock(entry);
++
++	last = NULL;
++	source = entry->maps;
++	while (source) {
++		if (readall)
++			source->stale = 1;
++
++		/*
++		 * If a map source is no longer valid and all it's
++		 * entries have expired away we can get rid of it.
++		 */
++		if (entry->age > source->age) {
++			struct mapent *me;
++			cache_readlock(source->mc);
++			me = cache_lookup_first(source->mc);
++			if (!me) {
++				struct map_source *next = source->next;
++
++				cache_unlock(source->mc);
++
++				if (!last)
++					entry->maps = next;
++				else
++					last->next = next;
++
++				if (entry->maps == source)
++					entry->maps = next;
++
++				master_free_map_source(source, 1);
++
++				source = next;
++				continue;
++			} else {
++				source->stale = 1;
++				map_stale = 1;
++			}
++			cache_unlock(source->mc);
++		}
++		last = source;
++		source = source->next;
++	}
++
++	master_source_unlock(entry);
++
++	/* The map sources have changed */
++	if (map_stale)
++		st_add_task(ap, ST_READMAP);
++
++	return;
++}
++
++int master_mount_mounts(struct master *master, time_t age)
++{
++	struct mapent_cache *nc = master->nc;
++	struct list_head *p, *head;
++	int cur_state;
++
++	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
++
++	head = &master->mounts;
++	p = head->next;
++	while (p != head) {
++		struct master_mapent *this;
++		struct autofs_point *ap;
++		struct mapent *ne, *nested;
++		struct stat st;
++		int state_pipe, save_errno;
++		int ret;
++
++		this = list_entry(p, struct master_mapent, list);
++		p = p->next;
++
++		ap = this->ap;
++
++		/* A master map entry has gone away */
++		if (this->age < age) {
++			st_add_task(ap, ST_SHUTDOWN_PENDING);
++			continue;
++		}
++
++		cache_readlock(nc);
++		ne = cache_lookup_distinct(nc, this->path);
++		/*
++		 * If this path matched a nulled entry the master map entry
++		 * must be an indirect mount so the master map entry line
++		 * number may be obtained from this->maps.
++		 */
++		if (ne) {
++			int lineno = ne->age;
++			cache_unlock(nc);
++
++			/* null entry appears after map entry */
++			if (this->maps->master_line < lineno) {
++				warn(ap->logopt,
++				     "ignoring null entry that appears after "
++				     "existing entry for %s", this->path);
++				goto cont;
++			}
++			if (ap->state != ST_INIT) {
++				st_add_task(ap, ST_SHUTDOWN_PENDING);
++				continue;
++			}
++			/*
++			 * The map entry hasn't been started yet and we've
++			 * seen a preceeding null map entry for it so just
++			 * delete it from the master map entry list so it
++			 * doesn't get in the road.
++			 */
++			list_del_init(&this->list);
++			master_free_mapent_sources(ap->entry, 1);
++			master_free_mapent(ap->entry);
++			continue;
++		}
++		nested = cache_partial_match(nc, this->path);
++		if (nested) {
++			error(ap->logopt,
++			     "removing invalid nested null entry %s",
++			     nested->key);
++			nested = cache_partial_match(nc, this->path);
++			if (nested)
++				cache_delete(nc, nested->key);
++		}
++		cache_unlock(nc);
++cont:
++		st_mutex_lock();
++
++		state_pipe = this->ap->state_pipe[1];
++
++		/* No pipe so mount is needed */
++		ret = fstat(state_pipe, &st);
++		save_errno = errno;
++
++		st_mutex_unlock();
++
++		if (!ret)
++			check_update_map_sources(this, master->readall);
++		else if (ret == -1 && save_errno == EBADF) {
++			if (!master_do_mount(this)) {
++				list_del_init(&this->list);
++				master_free_mapent_sources(ap->entry, 1);
++				master_free_mapent(ap->entry);
++			}
++		}
++	}
++
++	pthread_setcancelstate(cur_state, NULL);
++
++	return 1;
++}
++
++/* The nss source instances end up in reverse order. */
++static void list_source_instances(struct map_source *source, struct map_source *instance)
++{
++	if (!source || !instance) {
++		printf("none");
++		return;
++	}
++
++	if (instance->next)
++		list_source_instances(source, instance->next);
++
++	/*
++	 * For convienience we map nss instance type "files" to "file".
++	 * Check for that and report corrected instance type.
++	 */
++	if (strcmp(instance->type, "file"))
++		printf("%s ", instance->type);
++	else {
++		if (source->argv && *(source->argv[0]) != '/')
++			printf("files ");
++		else
++			printf("%s ", instance->type);
++	}
++
++	return;
++}
++
++static void print_map_info(struct map_source *source)
++{
++	int argc = source->argc;
++	int i, multi, map_num;
++
++	multi = (source->type && !strcmp(source->type, "multi"));
++	map_num = 1;
++	for (i = 0; i < argc; i++) {
++		if (source->argv[i] && *source->argv[i] != '-') {
++			if (!multi)
++				printf("  map: %s\n", source->argv[i]);
++			else
++				printf("  map[%i]: %s\n", map_num, source->argv[i]);
++			i++;
++		}
++
++		if (i >= argc)
++			return;
++
++		if (!strcmp(source->argv[i], "--"))
++			continue;
++
++		if (source->argv[i]) {
++			int need_newline = 0;
++			int j;
++
++			if (!multi)
++				printf("  arguments:");
++			else
++				printf("  arguments[%i]:", map_num);
++
++			for (j = i; j < source->argc; j++) {
++				if (!strcmp(source->argv[j], "--"))
++					break;
++				printf(" %s", source->argv[j]);
++				i++;
++				need_newline = 1;
++			}
++			if (need_newline)
++				printf("\n");
++		}
++		if (multi)
++			map_num++;
++	}
++
++	return;
++}
++
++static int match_type(const char *source, const char *type)
++{
++	if (!strcmp(source, type))
++		return 1;
++	/* Sources file and files are synonymous */
++	if (!strncmp(source, type, 4) && (strlen(source) <= 5))
++		return 1;
++	return 0;
++}
++
++static char *get_map_name(const char *string)
++{
++	char *name, *tmp;
++	char *start, *end, *base;
++
++	tmp = strdup(string);
++	if (!tmp) {
++		printf("error: allocation failure: %s\n", strerror(errno));
++		return NULL;
++	}
++
++	base = basename(tmp);
++	end = strchr(base, ',');
++	if (end)
++		*end = '\0';
++	start = strchr(tmp, '=');
++	if (start)
++		start++;
++	else {
++		char *colon = strrchr(base, ':');
++		if (colon)
++			start = ++colon;
++		else
++			start = base;
++	}
++
++	name = strdup(start);
++	if (!name)
++		printf("error: allocation failure: %s\n", strerror(errno));
++	free(tmp);
++
++	return name;
++}
++
++static int match_name(struct map_source *source, const char *name)
++{
++	int argc = source->argc;
++	int ret = 0;
++	int i;
++
++	/*
++	 * This can't work for old style "multi" type sources since
++	 * there's no way to know from which map the cache entry came
++	 * from and duplicate entries are ignored at map read time.
++	 * All we can really do is list all the entries for the given
++	 * multi map if one of its map names matches.
++	 */
++	for (i = 0; i < argc; i++) {
++		if (i == 0 || !strcmp(source->argv[i], "--")) {
++			if (i != 0) {
++				i++;
++				if (i >= argc)
++					break;
++			}
++
++			if (source->argv[i] && *source->argv[i] != '-') {
++				char *map = get_map_name(source->argv[i]);
++				if (!map)
++					break;
++				if (!strcmp(map, name)) {
++					ret = 1;
++					free(map);
++					break;
++				}
++				free(map);
++			}
++		}
++	}
++
++	return ret;
++}
++
++int dump_map(struct master *master, const char *type, const char *name)
++{
++	struct list_head *p, *head;
++
++	if (list_empty(&master->mounts)) {
++		printf("no master map entries found\n");
++		return 1;
++	}
++
++	head = &master->mounts;
++	p = head->next;
++	while (p != head) {
++		struct map_source *source;
++		struct master_mapent *this;
++		struct autofs_point *ap;
++		time_t now = monotonic_time(NULL);
++
++		this = list_entry(p, struct master_mapent, list);
++		p = p->next;
++
++		ap = this->ap;
++
++		/*
++		 * Ensure we actually read indirect map entries so we can
++		 * list them. The map reads won't read any indirect map
++		 * entries (other than those in a file map) unless the
++		 * browse option is set.
++		 */
++		if (ap->type == LKP_INDIRECT)
++			ap->flags |= MOUNT_FLAG_GHOST;
++
++		/* Read the map content into the cache */
++		if (lookup_nss_read_map(ap, NULL, now))
++			lookup_prune_cache(ap, now);
++		else {
++			printf("failed to read map\n");
++			lookup_close_lookup(ap);
++			continue;
++		}
++
++		if (!this->maps) {
++			printf("no map sources found for %s\n", ap->path);
++			lookup_close_lookup(ap);
++			continue;
++		}
++
++		source = this->maps;
++		while (source) {
++			struct map_source *instance;
++			struct mapent *me;
++
++			instance = NULL;
++			if (source->type) {
++				if (!match_type(source->type, type)) {
++					source = source->next;
++					continue;
++				}
++				if (!match_name(source, name)) {
++					source = source->next;
++					continue;
++				}
++				instance = source;
++			} else {
++				struct map_source *map;
++
++				map = source->instance;
++				while (map) {
++					if (!match_type(map->type, type)) {
++						map = map->next;
++						continue;
++					}
++					if (!match_name(map, name)) {
++						map = map->next;
++						continue;
++					}
++					instance = map;
++					break;
++				}
++			}
++
++			if (!instance) {
++				source = source->next;
++				lookup_close_lookup(ap);
++				continue;
++			}
++
++			me = cache_lookup_first(source->mc);
++			if (!me)
++				printf("no keys found in map\n");
++			else {
++				do {
++					if (me->source == instance)
++						printf("%s\t%s\n", me->key, me->mapent);
++				} while ((me = cache_lookup_next(source->mc, me)));
++			}
++
++			lookup_close_lookup(ap);
++			return 1;
++		}
++		lookup_close_lookup(ap);
++	}
++
++	return 0;
++}
++
++int master_show_mounts(struct master *master)
++{
++	struct list_head *p, *head;
++
++	printf("\nautofs dump map information\n"
++		 "===========================\n\n");
++
++	printf("global options: ");
++	if (!global_options)
++		printf("none configured\n");
++	else {
++		printf("%s\n", global_options);
++		unsigned int append_options = defaults_get_append_options();
++		const char *append = append_options ? "will" : "will not";
++		printf("global options %s be appended to map entries\n", append);
++	}
++
++	if (list_empty(&master->mounts)) {
++		printf("no master map entries found\n\n");
++		return 1;
++	}
++
++	head = &master->mounts;
++	p = head->next;
++	while (p != head) {
++		struct map_source *source;
++		struct master_mapent *this;
++		struct autofs_point *ap;
++		time_t now = monotonic_time(NULL);
++		unsigned int count = 0;
++
++		this = list_entry(p, struct master_mapent, list);
++		p = p->next;
++
++		ap = this->ap;
++
++		printf("\nMount point: %s\n", ap->path);
++
++		printf("\nsource(s):\n");
++
++		/*
++		 * Ensure we actually read indirect map entries so we can
++		 * list them. The map reads won't read any indirect map
++		 * entries (other than those in a file map) unless the
++		 * browse option is set.
++		 */
++		if (ap->type == LKP_INDIRECT)
++			ap->flags |= MOUNT_FLAG_GHOST;
++
++		/* Read the map content into the cache */
++		if (lookup_nss_read_map(ap, NULL, now))
++			lookup_prune_cache(ap, now);
++		else {
++			printf("  failed to read map\n\n");
++			continue;
++		}
++
++		if (!this->maps) {
++			printf("  no map sources found\n\n");
++			continue;
++		}
++
++		source = this->maps;
++		while (source) {
++			struct mapent *me;
++
++			if (source->type)
++				printf("\n  type: %s\n", source->type);
++			else {
++				printf("\n  instance type(s): ");
++				list_source_instances(source, source->instance);
++				printf("\n");
++			}
++
++			if (source->argc >= 1) {
++				print_map_info(source);
++				if (count && ap->type == LKP_INDIRECT)
++					printf("  duplicate indirect map entry"
++					       " will be ignored at run time\n");
++			}
++
++			printf("\n");
++
++			me = cache_lookup_first(source->mc);
++			if (!me)
++				printf("  no keys found in map\n");
++			else {
++				do {
++					printf("  %s | %s\n", me->key, me->mapent);
++				} while ((me = cache_lookup_next(source->mc, me)));
++			}
++
++			count++;
++
++			source = source->next;
++		}
++
++		lookup_close_lookup(ap);
++
++		printf("\n");
++	}
++
++	return 1;
++}
++
++int master_list_empty(struct master *master)
++{
++	int res = 0;
++
++	master_mutex_lock();
++	if (list_empty(&master->mounts))
++		res = 1;
++	master_mutex_unlock();
++
++	return res;
++}
++
++int master_done(struct master *master)
++{
++	struct list_head *head, *p;
++	struct master_mapent *entry;
++	int res = 0;
++
++	head = &master->completed;
++	p = head->next;
++	while (p != head) {
++		entry = list_entry(p, struct master_mapent, join);
++		p = p->next;
++		list_del(&entry->join);
++		pthread_join(entry->thid, NULL);
++		master_free_mapent_sources(entry, 1);
++		master_free_mapent(entry);
++	}
++	if (list_empty(&master->mounts))
++		res = 1;
++
++	return res;
++}
++
++unsigned int master_get_logopt(void)
++{
++	return master_list ? master_list->logopt : LOGOPT_NONE;
++}
++
++int master_kill(struct master *master)
++{
++	if (!list_empty(&master->mounts))
++		return 0;
++
++	if (master->name)
++		free(master->name);
++
++	cache_release_null_cache(master);
++	free(master);
++
++	return 1;
++}
+--- /dev/null
++++ autofs-5.1.4/daemon/master_parse.y
+@@ -0,0 +1,983 @@
++%{
++/* ----------------------------------------------------------------------- *
++ *   
++ *  master_parser.y - master map buffer parser.
++ *
++ *   Copyright 2006 Ian Kent <raven@themaw.net>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU General Public License as published by
++ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
++ *   USA; either version 2 of the License, or (at your option) any later
++ *   version.
++ *   
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details.
++ *
++ * ----------------------------------------------------------------------- */
++
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <ctype.h>
++#include <sys/ioctl.h>
++
++#include "automount.h"
++#include "master.h"
++
++#define MAX_ERR_LEN	512
++
++extern struct master *master_list;
++
++char **add_argv(int, char **, char *);
++const char **copy_argv(int, const char **);
++int free_argv(int, const char **);
++
++extern FILE *master_in;
++extern char *master_text;
++extern int master_lex(void);
++extern int master_lineno;
++extern void master_set_scan_buffer(const char *);
++
++static char *master_strdup(char *);
++static void local_init_vars(void);
++static void local_free_vars(void);
++static void trim_maptype(char *);
++static int add_multi_mapstr(void);
++
++static int master_error(const char *s);
++static int master_notify(const char *s);
++static int master_msg(const char *s);
++ 
++static char *path;
++static char *type;
++static char *format;
++static long timeout;
++static long negative_timeout;
++static unsigned symlnk;
++static unsigned strictexpire;
++static unsigned nobind;
++static unsigned ghost;
++extern unsigned global_selection_options;
++static unsigned random_selection;
++static unsigned use_weight;
++static unsigned long mode;
++static char **tmp_argv;
++static int tmp_argc;
++static char **local_argv;
++static int local_argc;
++
++#define PROPAGATION_SHARED	MOUNT_FLAG_SHARED
++#define PROPAGATION_SLAVE	MOUNT_FLAG_SLAVE
++#define PROPAGATION_PRIVATE	MOUNT_FLAG_PRIVATE
++#define PROPAGATION_MASK	(MOUNT_FLAG_SHARED | \
++				 MOUNT_FLAG_SLAVE  | \
++				 MOUNT_FLAG_PRIVATE)
++static unsigned int propagation;
++
++static char errstr[MAX_ERR_LEN];
++
++static unsigned int verbose;
++static unsigned int debug;
++
++static int lineno;
++
++#define YYDEBUG 0
++
++#ifndef YYENABLE_NLS
++#define YYENABLE_NLS 0
++#endif
++#ifndef YYLTYPE_IS_TRIVIAL
++#define YYLTYPE_IS_TRIVIAL 0
++#endif
++
++#if YYDEBUG
++static int master_fprintf(FILE *, char *, ...);
++#undef YYFPRINTF
++#define YYFPRINTF master_fprintf
++#endif
++
++%}
++
++%union {
++	char strtype[2048];
++	int inttype;
++	long longtype;
++}
++
++%token COMMENT
++%token MAP
++%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
++%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
++%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
++%token COLON COMMA NL DDASH
++%type <strtype> map
++%type <strtype> options
++%type <strtype> dn
++%type <strtype> dnattrs
++%type <strtype> dnattr
++%type <strtype> option
++%type <strtype> daemon_option
++%type <strtype> mount_option
++%token <strtype> PATH
++%token <strtype> QUOTE
++%token <strtype> NILL
++%token <strtype> SPACE
++%token <strtype> EQUAL
++%token <strtype> MULTITYPE
++%token <strtype> MAPTYPE
++%token <strtype> DNSERVER
++%token <strtype> DNATTR
++%token <strtype> DNNAME
++%token <strtype> MAPHOSTS
++%token <strtype> MAPNULL
++%token <strtype> MAPXFN
++%token <strtype> MAPNAME
++%token <longtype> NUMBER
++%token <longtype> OCTALNUMBER
++%token <strtype> OPTION
++
++%start file
++
++%%
++
++file: {
++		master_lineno = 0;
++#if YYDEBUG != 0
++		master_debug = YYDEBUG;
++#endif
++	} line
++	;
++
++line:
++	| PATH mapspec
++	{
++		path = master_strdup($1);
++		if (!path) {
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| PATH MULTITYPE maplist
++	{
++		char *tmp = NULL;
++
++		trim_maptype($2);
++
++		if (path)
++			free(path);
++		path = master_strdup($1);
++		if (!path) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++
++		if ((tmp = strchr($2, ',')))
++			*tmp++ = '\0';
++#ifndef WITH_HESIOD
++		/* Map type or map type parser is hesiod */
++		if (!strcmp($2, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
++			master_error("hesiod support not built in");
++			local_free_vars();
++			YYABORT;
++		}
++#endif
++		if (type)
++			free(type);
++		type = master_strdup($2);
++		if (!type) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++		if (tmp) {
++			if (format)
++				free(format);
++			format = master_strdup(tmp);
++			if (!format) {
++				master_error("memory allocation error");
++				local_free_vars();
++				YYABORT;
++			}
++		}
++	}
++	| PATH COLON { master_notify($1); YYABORT; }
++	| PATH OPTION { master_notify($2); YYABORT; }
++	| PATH NILL { master_notify($2); YYABORT; }
++	| PATH OPT_RANDOM { master_notify($1); YYABORT; }
++	| PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
++	| PATH OPT_DEBUG { master_notify($1); YYABORT; }
++	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
++	| PATH OPT_SYMLINK { master_notify($1); YYABORT; }
++	| PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
++	| PATH OPT_SHARED { master_notify($1); YYABORT; }
++	| PATH OPT_SLAVE { master_notify($1); YYABORT; }
++	| PATH OPT_PRIVATE { master_notify($1); YYABORT; }
++	| PATH OPT_NOBIND { master_notify($1); YYABORT; }
++	| PATH OPT_GHOST { master_notify($1); YYABORT; }
++	| PATH OPT_NOGHOST { master_notify($1); YYABORT; }
++	| PATH OPT_VERBOSE { master_notify($1); YYABORT; }
++	| PATH OPT_MODE { master_notify($1); YYABORT; }
++	| PATH { master_notify($1); YYABORT; }
++	| QUOTE { master_notify($1); YYABORT; }
++	| OPTION { master_notify($1); YYABORT; }
++	| NILL { master_notify($1); YYABORT; }
++	| COMMENT { YYABORT; }
++	;
++
++mapspec: map
++	{
++		if (local_argv)
++			free_argv(local_argc, (const char **) local_argv);
++		local_argc = tmp_argc;
++		local_argv = tmp_argv;
++		tmp_argc = 0;
++		tmp_argv = NULL;
++	}
++	| map options
++	{
++		if (local_argv)
++			free_argv(local_argc, (const char **) local_argv);
++		local_argc = tmp_argc;
++		local_argv = tmp_argv;
++		tmp_argc = 0;
++		tmp_argv = NULL;
++	}
++	;
++
++maplist: map
++	{
++		if (!add_multi_mapstr()) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| map options
++	{
++		if (!add_multi_mapstr()) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| maplist DDASH map
++	{
++		local_argc++;
++		local_argv = add_argv(local_argc, local_argv, "--");
++		if (!local_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++		if (!add_multi_mapstr()) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| maplist DDASH map options
++	{
++		local_argc++;
++		local_argv = add_argv(local_argc, local_argv, "--");
++		if (!local_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++		if (!add_multi_mapstr()) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	;
++
++map:	PATH
++	{
++		tmp_argc++;
++		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
++		if (!tmp_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| MAPNAME
++	{
++		tmp_argc++;
++		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
++		if (!tmp_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| MAPHOSTS
++	{
++		if (type)
++			free(type);
++		type = master_strdup($1 + 1);
++		if (!type) {
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| MAPXFN
++	{
++		master_notify($1);
++		master_msg("X/Open Federated Naming service not supported");
++		YYABORT;
++	}
++	| MAPNULL
++	{
++		if (type)
++			free(type);
++		type = master_strdup($1 + 1);
++		if (!type) {
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| dnattrs
++	{
++		if (type)
++			free(type);
++		type = master_strdup("ldap");
++		if (!type) {
++			local_free_vars();
++			YYABORT;
++		}
++		tmp_argc++;
++		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
++		if (!tmp_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| MAPTYPE PATH
++	{
++		char *tmp = NULL;
++
++		trim_maptype($1);
++
++		if ((tmp = strchr($1, ',')))
++			*tmp++ = '\0';
++#ifndef WITH_HESIOD
++		/* Map type or map type parser is hesiod */
++		if (!strcmp($1, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
++			master_error("hesiod support not built in");
++			local_free_vars();
++			YYABORT;
++		}
++#endif
++		if (type)
++			free(type);
++		if (strcmp($1, "exec"))
++			type = master_strdup($1);
++		else
++			type = master_strdup("program");
++		if (!type) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++		if (tmp) {
++			if (format)
++				free(format);
++			format = master_strdup(tmp);
++			if (!format) {
++				master_error("memory allocation error");
++				local_free_vars();
++				YYABORT;
++			}
++		}
++		tmp_argc++;
++		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
++		if (!tmp_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| MAPTYPE MAPNAME
++	{
++		char *tmp = NULL;
++
++		trim_maptype($1);
++
++		if ((tmp = strchr($1, ',')))
++			*tmp++ = '\0';
++
++		if (type)
++			free(type);
++		if (strcmp($1, "exec"))
++			type = master_strdup($1);
++		else
++			type = master_strdup("program");
++		if (!type) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++		if (tmp) {
++			if (format)
++				free(format);
++			format = master_strdup(tmp);
++			if (!format) {
++				master_error("memory allocation error");
++				local_free_vars();
++				YYABORT;
++			}
++		}
++		tmp_argc++;
++		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
++		if (!tmp_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	| MAPTYPE dn
++	{
++		char *tmp = NULL;
++
++		trim_maptype($1);
++
++		if ((tmp = strchr($1, ',')))
++			*tmp++ = '\0';
++
++		if (type)
++			free(type);
++		if (strcmp($1, "exec"))
++			type = master_strdup($1);
++		else
++			type = master_strdup("program");
++		if (!type) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++		if (tmp) {
++			if (format)
++				free(format);
++			format = master_strdup(tmp);
++			if (!format) {
++				master_error("memory allocation error");
++				local_free_vars();
++				YYABORT;
++			}
++		}
++		tmp_argc++;
++		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
++		if (!tmp_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++		/* Add back the type for lookup_ldap.c to handle ldaps */
++		if (*tmp_argv[0]) {
++			tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
++			if (!tmp) {
++				master_error("memory allocation error");
++				local_free_vars();
++				YYABORT;
++			}
++			strcpy(tmp, type);
++			strcat(tmp, ":");
++			strcat(tmp, tmp_argv[0]);
++			free(tmp_argv[0]);
++			tmp_argv[0] = tmp;
++		}
++	}
++	;
++
++dn:	DNSERVER dnattrs
++	{
++		strcpy($$, $1);
++		strcat($$, $2);
++	}
++	| dnattrs
++	{
++		strcpy($$, $1);
++	}
++	|
++	{
++		master_notify("syntax error in dn");
++		YYABORT;
++	}
++	;
++
++dnattrs: DNATTR EQUAL DNNAME
++	{
++		if (strcasecmp($1, "cn") &&
++		    strcasecmp($1, "ou") &&
++		    strcasecmp($1, "automountMapName") &&
++		    strcasecmp($1, "nisMapName")) {
++			strcpy(errstr, $1);
++			strcat(errstr, "=");
++			strcat(errstr, $3);
++			master_notify(errstr);
++			YYABORT;
++		}
++		strcpy($$, $1);
++		strcat($$, "=");
++		strcat($$, $3);
++	}
++	| DNATTR EQUAL DNNAME COMMA dnattr
++	{
++		if (strcasecmp($1, "cn") &&
++		    strcasecmp($1, "ou") &&
++		    strcasecmp($1, "automountMapName") &&
++		    strcasecmp($1, "nisMapName")) {
++			strcpy(errstr, $1);
++			strcat(errstr, "=");
++			strcat(errstr, $3);
++			master_notify(errstr);
++			YYABORT;
++		}
++		strcpy($$, $1);
++		strcat($$, "=");
++		strcat($$, $3);
++		strcat($$, ",");
++		strcat($$, $5);
++	}
++	| DNNAME
++	{
++		/* Matches map in old style syntax ldap:server:map */
++		strcpy($$, $1);
++	}
++	| DNATTR
++	{
++		master_notify($1);
++		YYABORT;
++	}
++	;
++
++dnattr: DNATTR EQUAL DNNAME
++	{
++		if (!strcasecmp($1, "automountMapName") ||
++		    !strcasecmp($1, "nisMapName")) {
++			strcpy(errstr, $1);
++			strcat(errstr, "=");
++			strcat(errstr, $3);
++			master_notify(errstr);
++			YYABORT;
++		}
++		strcpy($$, $1);
++		strcat($$, "=");
++		strcat($$, $3);
++	}
++	| DNATTR EQUAL DNNAME COMMA dnattr
++	{
++		if (!strcasecmp($1, "automountMapName") ||
++		    !strcasecmp($1, "nisMapName")) {
++			strcpy(errstr, $1);
++			strcat(errstr, "=");
++			strcat(errstr, $3);
++			master_notify(errstr);
++			YYABORT;
++		}
++		strcpy($$, $1);
++		strcat($$, "=");
++		strcat($$, $3);
++		strcat($$, ",");
++		strcat($$, $5);
++	}
++	| DNATTR
++	{
++		master_notify($1);
++		YYABORT;
++	}
++	| DNNAME
++	{
++		master_notify($1);
++		YYABORT;
++	}
++	;
++
++options: option {}
++	| options COMMA option {}
++	| options option {}
++	| options COMMA COMMA option
++	{
++		master_notify($1);
++		YYABORT;
++	}
++	| options EQUAL
++	{
++		master_notify($1);
++		YYABORT;
++	}
++	;
++
++option: daemon_option
++	| mount_option {}
++	| error
++	{
++		master_notify("bogus option");
++		YYABORT;
++	}
++	;
++
++daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
++	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
++	| OPT_SYMLINK	{ symlnk = 1; }
++	| OPT_STRICTEXPIRE { strictexpire = 1; }
++	| OPT_SHARED	{ propagation = PROPAGATION_SHARED; }
++	| OPT_SLAVE	{ propagation = PROPAGATION_SLAVE; }
++	| OPT_PRIVATE	{ propagation = PROPAGATION_PRIVATE; }
++	| OPT_NOBIND	{ nobind = 1; }
++	| OPT_NOGHOST	{ ghost = 0; }
++	| OPT_GHOST	{ ghost = 1; }
++	| OPT_VERBOSE	{ verbose = 1; }
++	| OPT_DEBUG	{ debug = 1; }
++	| OPT_RANDOM	{ random_selection = 1; }
++	| OPT_USE_WEIGHT { use_weight = 1; }
++	| OPT_MODE OCTALNUMBER { mode = $2; }
++	;
++
++mount_option: OPTION
++	{
++		tmp_argc++;
++		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
++		if (!tmp_argv) {
++			master_error("memory allocation error");
++			local_free_vars();
++			YYABORT;
++		}
++	}
++	;
++%%
++
++#if YYDEBUG
++static int master_fprintf(FILE *f, char *msg, ...)
++{
++	va_list ap;
++	va_start(ap, msg);
++	vsyslog(LOG_DEBUG, msg, ap);
++	va_end(ap);
++	return 1;
++}
++#endif
++
++static char *master_strdup(char *str)
++{
++	char *tmp;
++
++	tmp = strdup(str);
++	if (!tmp)
++		master_error("memory allocation error");
++	return tmp;
++}
++
++static int master_error(const char *s)
++{
++	logmsg("%s while parsing map.", s);
++	return 0;
++}
++
++static int master_notify(const char *s)
++{
++	logmsg("syntax error in map near [ %s ]", s);
++	return(0);
++}
++
++static int master_msg(const char *s)
++{
++	logmsg("%s", s);
++	return 0;
++}
++
++static void local_init_vars(void)
++{
++	path = NULL;
++	type = NULL;
++	format = NULL;
++	verbose = 0;
++	debug = 0;
++	timeout = -1;
++	negative_timeout = 0;
++	symlnk = 0;
++	strictexpire = 0;
++	propagation = PROPAGATION_SLAVE;
++	nobind = 0;
++	ghost = defaults_get_browse_mode();
++	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
++	use_weight = 0;
++	mode = 0;
++	tmp_argv = NULL;
++	tmp_argc = 0;
++	local_argv = NULL;
++	local_argc = 0;
++}
++
++static void local_free_vars(void)
++{
++	if (path)
++		free(path);
++
++	if (type)
++		free(type);
++
++	if (format)
++		free(format);
++
++	if (local_argv) {
++		free_argv(local_argc, (const char **) local_argv);
++		local_argv = NULL;
++		local_argc = 0;
++	}
++
++	if (tmp_argv) {
++		free_argv(tmp_argc, (const char **) tmp_argv);
++		tmp_argv = NULL;
++		tmp_argc = 0;
++	}
++}
++
++static void trim_maptype(char *type)
++{
++	char *tmp;
++
++	tmp = strchr(type, ':');
++	if (tmp)
++		*tmp = '\0';
++	else {
++		int len = strlen(type);
++		while (len-- && isblank(type[len]))
++			type[len] = '\0';
++	}
++	return;
++}
++
++static int add_multi_mapstr(void)
++{
++	if (type) {
++		/* If type given and format is non-null add it back */
++		if (format) {
++			int len = strlen(type) + strlen(format) + 2;
++			char *tmp = realloc(type, len);
++			if (!tmp)
++				return 0;
++			type = tmp;
++			strcat(type, ",");
++			strcat(type, format);
++			free(format);
++			format = NULL;
++		}
++
++		local_argc++;
++		local_argv = add_argv(local_argc, local_argv, type);
++		if (!local_argv) {
++			free(type);
++			type = NULL;
++			return 0;
++		}
++
++		free(type);
++		type = NULL;
++	}
++
++	local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv);
++	if (!local_argv) {
++		free(type);
++		type = NULL;
++		return 0;
++	}
++	local_argc += tmp_argc;
++
++	tmp_argc = 0;
++	tmp_argv = NULL;
++
++	return 1;
++}
++
++void master_init_scan(void)
++{
++	lineno = 0;
++}
++
++int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigned int logging, time_t age)
++{
++	struct master *master = master_list;
++	struct mapent_cache *nc;
++	struct master_mapent *entry, *new;
++	struct map_source *source;
++	unsigned int logopt = logging;
++	unsigned int m_logopt = master->logopt;
++	size_t mp_len;
++	int ret;
++
++	local_init_vars();
++
++	lineno++;
++
++	master_set_scan_buffer(buffer);
++
++	ret = master_parse();
++	if (ret != 0) {
++		local_free_vars();
++		return 0;
++	}
++
++	mp_len = strlen(path);
++	while (mp_len && path[--mp_len] == '/')
++		path[mp_len] = 0;
++
++	nc = master->nc;
++
++	/* Add null map entries to the null map cache */
++	if (type && !strcmp(type, "null")) {
++		cache_update(nc, NULL, path, NULL, lineno);
++		local_free_vars();
++		return 1;
++	}
++
++	/* Ignore all subsequent matching nulled entries */
++	if (cache_lookup_distinct(nc, path)) {
++		local_free_vars();
++		return 1;
++	}
++
++	if (debug || verbose) {
++		logopt = (debug ? LOGOPT_DEBUG : 0);
++		logopt |= (verbose ? LOGOPT_VERBOSE : 0);
++	}
++
++	new = NULL;
++	entry = master_find_mapent(master, path);
++	if (!entry) {
++		new = master_new_mapent(master, path, age);
++		if (!new) {
++			local_free_vars();
++			return 0;
++		}
++		entry = new;
++	} else {
++		if (entry->age && entry->age == age) {
++			if (strcmp(path, "/-")) {
++				info(m_logopt,
++				    "ignoring duplicate indirect mount %s",
++				     path);
++				local_free_vars();
++				return 0;
++			}
++		}
++	}
++
++	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();
++		unsigned int flags = conf_amd_get_flags(path);
++
++		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
++			logopt = LOGOPT_DEBUG;
++		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
++			logopt = LOGOPT_VERBOSE;
++
++		/* It isn't possible to provide the fullybrowsable amd
++		 * browsing functionality within the autofs framework.
++		 * This flag will not be set if browsable_dirs = full
++		 * in the configuration or fullybrowsable is present as
++		 * an option.
++		 */
++		if (flags & CONF_BROWSABLE_DIRS)
++			ghost = 1;
++	}
++
++	if (!entry->ap) {
++		ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
++		if (!ret) {
++			error(m_logopt, "failed to add autofs_point");
++			if (new)
++				master_free_mapent(new);
++			local_free_vars();
++			return 0;
++		}
++	}
++	entry->ap->flags &= ~(PROPAGATION_MASK);
++	entry->ap->flags |= propagation;
++
++	if (random_selection)
++		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
++	if (use_weight)
++		entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
++	if (symlnk)
++		entry->ap->flags |= MOUNT_FLAG_SYMLINK;
++	if (strictexpire)
++		entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
++	if (negative_timeout)
++		entry->ap->negative_timeout = negative_timeout;
++	if (mode && mode < LONG_MAX)
++		entry->ap->mode = mode;
++
++	if (timeout < 0) {
++		/*
++		 * If no timeout is given get the timout from the
++		 * autofs point, or the first map, or the config
++		 * for amd maps.
++		 */
++		if (format && !strcmp(format, "amd"))
++			timeout = conf_amd_get_dismount_interval(path);
++		else
++			timeout = get_exp_timeout(entry->ap, entry->maps);
++	}
++
++	if (format && !strcmp(format, "amd")) {
++		char *opts = conf_amd_get_map_options(path);
++		if (opts) {
++			/* autofs uses the equivalent of cache:=inc,sync
++			 * (except for file maps which use cache:=all,sync)
++			 * but if the map is large then it may be necessary
++			 * to read the whole map at startup even if browsing
++			 * is is not enabled, so look for cache:=all in the
++			 * map_options configuration entry.
++			 */
++			if (strstr(opts, "cache:=all"))
++				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
++			free(opts);
++		}
++	}
++
++/*
++	source = master_find_map_source(entry, type, format,
++					local_argc, (const char **) local_argv); 
++	if (!source)
++		source = master_add_map_source(entry, type, format, age, 
++					local_argc, (const char **) local_argv);
++	else
++		source->age = age;
++*/
++	source = master_add_map_source(entry, type, format, age, 
++					local_argc, (const char **) local_argv);
++	if (!source) {
++		error(m_logopt, "failed to add source");
++		if (new)
++			master_free_mapent(new);
++		local_free_vars();
++		return 0;
++	}
++	set_exp_timeout(entry->ap, source, timeout);
++	source->master_line = lineno;
++
++	entry->age = age;
++	entry->current = NULL;
++
++	if (new)
++		master_add_mapent(master, entry);
++
++	local_free_vars();
++
++	return 1;
++}
++
+--- /dev/null
++++ autofs-5.1.4/daemon/master_tok.l
+@@ -0,0 +1,504 @@
++%{
++/* ----------------------------------------------------------------------- *
++ *   
++ *  master_tok.l - master map tokenizer.
++ *
++ *   Copyright 2006 Ian Kent <raven@themaw.net>
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of the GNU General Public License as published by
++ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
++ *   USA; either version 2 of the License, or (at your option) any later
++ *   version.
++ *   
++ *   This program is distributed in the hope that it will be useful,
++ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *   GNU General Public License for more details.
++ *
++ * ----------------------------------------------------------------------- */
++
++#ifdef ECHO
++# undef ECHO
++#endif /* ECHO */
++static void master_echo(void);	/* forward definition */
++#define ECHO master_echo()
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include "master_parse.tab.h"
++
++/*
++ * There are some things that need to be defined only if useing GNU flex.
++ * These must not be defined if using standard lex
++ */
++#ifdef FLEX_SCANNER
++int master_lineno;
++#endif
++
++int master_lex(void);
++int master_wrap(void);
++
++/* no need for yywrap() */
++#define YY_SKIP_YYWRAP
++
++#ifndef YY_STACK_USED
++#define YY_STACK_USED 0
++#endif
++#ifndef YY_ALWAYS_INTERACTIVE
++#define YY_ALWAYS_INTERACTIVE 0
++#endif
++#ifndef YY_NEVER_INTERACTIVE
++#define YY_NEVER_INTERACTIVE 0
++#endif
++#ifndef YY_MAIN
++#define YY_MAIN 0
++#endif
++
++void master_set_scan_buffer(const char *);
++const char *line = NULL;
++
++#ifdef FLEX_SCANNER
++const char *line_pos = NULL;
++const char *line_lim = NULL;
++int my_yyinput(char *, int);
++
++#undef YY_INPUT
++#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
++#else
++#undef input
++#undef unput
++#define input()  (*(char *) line++)
++#define unput(c) (*(char *) --line = c)
++#endif
++
++#define BUFF_LEN	1024
++char buff[BUFF_LEN];
++char *bptr;
++char *optr = buff;
++unsigned int tlen;
++
++%}
++
++%option nounput
++
++%x PATHSTR MAPSTR DNSTR OPTSTR OCTAL
++
++WS		[[:blank:]]+
++OPTWS		[[:blank:]]*
++NL		\r?\n
++CONT		\\\n{OPTWS}
++
++OPTIONSTR	([\-]?([[:alpha:]_]([[:alnum:]_\-])*(=(\"?([[:alnum:]_\-\:\.])+\"?))?)+)
++MACROSTR	(-D{OPTWS}([[:alpha:]_]([[:alnum:]_\-\.])*)=([[:alnum:]_\-\.])+)
++SLASHIFYSTR	(--(no-)?slashify-colons)
++NUMBER		[0-9]+
++OCTALNUMBER	[0-7]+
++
++DNSERVSTR1	([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
++DNSERVSTR2	(\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
++DNSERVSTR3	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
++DNSERVSTR4	(\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
++DNSERVSTR5	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
++DNSERVSTR6	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
++DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
++
++AT_CN		([cC][[nN])
++AT_NMN		([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
++AT_AMN		([aA][uU][tT][oO][mM][oO][uU][nN][tT][Mm][aA][pP][Nn][aA][mM][eE])
++AT_OU		([oO][[uU])
++AT_DC		([dD][[cC])
++AT_O		([oO])
++AT_C		([cC])
++AT_L		([lL])
++DNATTRSTR	({AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}|{AT_L})
++DNNAMESTR1	([[:alnum:]_.\- ]+)
++DNNAMESTR2	([[:alnum:]_.\-]+)
++
++INTMAP		(-hosts|-null)
++MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
++MULTISEP	([\-]{2}[[:blank:]]+)
++MTYPE		((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
++
++
++OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
++OPTNTOUT	(-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
++
++MODE		(--mode{OPTWS}|--mode{OPTWS}={OPTWS})
++
++%%
++
++<INITIAL>{
++	{NL} | 
++	\x00 {
++		if (optr != buff) {
++			*optr = '\0';
++			strcpy(master_lval.strtype, buff);
++			return NILL;
++		}
++	}
++
++	#.*  { return COMMENT; }
++
++	"/" {
++		if (optr != buff) {
++			*optr = '\0';
++			strcpy(master_lval.strtype, buff);
++			return NILL;
++		}
++		BEGIN(PATHSTR);
++		bptr = buff;
++		yyless(0);
++	}
++
++	.    { *optr++ = *master_text; }
++}
++
++<PATHSTR>{
++	\x00 {
++		BEGIN(INITIAL);
++		*bptr++ = *master_text;
++		strcpy(master_lval.strtype, buff);
++		return NILL;
++	}
++
++	\\.  { *bptr++ = *(master_text + 1); }
++	\"   {
++		BEGIN(INITIAL);
++		*bptr++ = *master_text;
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		return QUOTE;
++	}
++
++	{WS} {
++		BEGIN(MAPSTR);
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		bptr = buff;
++		memset(buff, 0, BUFF_LEN);
++		return(PATH);
++	}
++
++	<<EOF>> {
++		BEGIN(INITIAL);
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		return(PATH);
++	}
++
++	{NL} {
++		BEGIN(INITIAL);
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		return PATH;
++	}
++
++	.    { *bptr++ = *master_text; }
++}
++
++<MAPSTR>{
++	{OPTWS}\\\n{OPTWS} {}
++
++	{MULTI} {
++		tlen = master_leng - 1;
++		if (bptr != buff && isblank(master_text[tlen])) {
++			/*
++			 * We can't handle unescaped white space in map names
++			 * so just eat the white space. We always have the
++			 * "multi" at the beginning of the string so the while
++			 * will not fall off the end.
++			 */
++			while (isblank(master_text[tlen - 1]))
++				tlen--;
++			strncat(buff, master_text, tlen);
++			bptr += tlen;
++			yyless(tlen);
++		} else {
++			strcpy(master_lval.strtype, master_text);
++			return(MULTITYPE);
++		}
++	}
++
++	{MTYPE} |
++	{MTYPE}/{DNSERVERSTR}{DNATTRSTR}= |
++	{MTYPE}/{DNATTRSTR}= {
++		tlen = master_leng - 1;
++		if (bptr != buff && isblank(master_text[tlen])) {
++			/*
++			 * We can't handle unescaped white space in map names
++			 * so just eat the white space. We always have the
++			 * maptype keyword at the beginning of the string so
++			 * the while will not fall off the end.
++			 */
++			while (isblank(master_text[tlen - 1]))
++				tlen--;
++			strncat(buff, master_text, tlen);
++			bptr += tlen;
++			yyless(tlen);
++		} else {
++			strcpy(master_lval.strtype, master_text);
++			return(MAPTYPE);
++		}
++	}
++
++	{MULTISEP} { return(DDASH); }
++
++	":"	{ return(COLON); }
++
++	"-hosts" {
++		BEGIN(OPTSTR);
++		strcpy(master_lval.strtype, master_text);
++		return MAPHOSTS;
++	}
++
++	"-null" {
++		BEGIN(OPTSTR);
++		strcpy(master_lval.strtype, master_text);
++		return MAPNULL;
++	}
++
++	"-xfn" {
++		/*
++		 * The X/Open Federated Naming service isn't supported
++		 * and the parser will call YYABORT() when it sees the
++		 * MAPXFN token so we must set the start state to the
++		 * INITIAL state here for the next yylex() call.
++		 */
++		BEGIN(INITIAL);
++		strcpy(master_lval.strtype, master_text);
++		return MAPXFN;
++	}
++
++	"//" {
++		BEGIN(DNSTR);
++		yyless(0);
++	}
++
++	{DNSERVERSTR}{DNATTRSTR}= {
++		BEGIN(DNSTR);
++		yyless(0);
++	}
++
++	{DNATTRSTR}= {
++		BEGIN(DNSTR);
++		yyless(0);
++	}
++
++	{OPTWS}/{NL} {
++		BEGIN(INITIAL);
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		bptr = buff;
++		return(MAPNAME);
++	}
++
++	\\. { *bptr++ = *(master_text + 1); }
++
++	{WS} {
++		BEGIN(OPTSTR);
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		bptr = buff;
++		return(MAPNAME);
++	}
++
++	{NL} |
++	\x00 {
++		BEGIN(INITIAL);
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		return(MAPNAME);
++	}
++
++	<<EOF>> {
++		BEGIN(INITIAL);
++		*bptr = '\0';
++		strcpy(master_lval.strtype, buff);
++		return(MAPNAME);
++	}
++
++	.	{ *bptr++ = *master_text; }
++}
++
++<DNSTR>{
++	{OPTWS}\\\n{OPTWS} {}
++
++	{DNSERVERSTR} {
++		strcpy(master_lval.strtype, master_text);
++		return DNSERVER;
++	}
++
++	{DNATTRSTR}/"=" {
++		strcpy(master_lval.strtype, master_text);
++		return DNATTR;
++	}
++
++	"=" {
++		return EQUAL;
++	}
++
++	{DNNAMESTR1}/","{DNATTRSTR}"=" {
++		strcpy(master_lval.strtype, master_text);
++		return DNNAME;
++	}
++
++	{DNNAMESTR2} {
++		strcpy(master_lval.strtype, master_text);
++		return DNNAME;
++	}
++
++	{OPTWS}","{OPTWS} {
++		return COMMA;
++	}
++
++	{WS}"=" |
++	"="{WS} {
++		BEGIN(INITIAL);
++		strcpy(master_lval.strtype, master_text);
++		return SPACE;
++	}
++
++	{WS}    { BEGIN(OPTSTR); }
++
++	{NL} |
++	\x00	{ BEGIN(INITIAL); }
++
++	<<EOF>> { BEGIN(INITIAL); }
++}
++
++<OPTSTR>{
++	{OPTWS}\\\n{OPTWS} {}
++
++	{MULTISEP} {
++		BEGIN(MAPSTR);
++		return(DDASH);
++	}
++
++	{OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
++
++	{OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
++
++	{NUMBER} {
++		master_lval.longtype = atol(master_text);
++		return(NUMBER);
++	}
++
++	-?symlink		{ return(OPT_SYMLINK); }
++	-?nobind		{ return(OPT_NOBIND); }
++	-?nobrowse		{ return(OPT_NOGHOST); }
++	-?shared		{ return(OPT_SHARED); }
++	-?slave			{ return(OPT_SLAVE); }
++	-?private		{ return(OPT_PRIVATE); }
++	-?strictexpire		{ return(OPT_STRICTEXPIRE); }
++	-g|--ghost|-?browse	{ return(OPT_GHOST); }
++	-v|--verbose		{ return(OPT_VERBOSE); }
++	-d|--debug		{ return(OPT_DEBUG); }
++	-w|--use-weight-only	{ return(OPT_USE_WEIGHT); }
++	-r|--random-multimount-selection { return(OPT_RANDOM); }
++
++	{MODE}/{OCTALNUMBER} {
++		BEGIN(OCTAL);
++		return(OPT_MODE);
++	}
++
++	{OPTWS}","{OPTWS}	{ return(COMMA); }
++
++	{OPTWS} {}
++
++	{SLASHIFYSTR} {
++		strcpy(master_lval.strtype, master_text);
++		return(OPTION);
++	}
++
++	{MACROSTR} {
++		strcpy(master_lval.strtype, master_text);
++		return(OPTION);
++	}
++
++	{OPTIONSTR} {
++		strcpy(master_lval.strtype, master_text);
++		return(OPTION);
++	}
++
++	"="	{
++		strcpy(master_lval.strtype, master_text);
++		return(EQUAL);
++	}
++
++	{WS}	{}
++	{NL} |
++	\x00 { BEGIN(INITIAL); }
++
++	<<EOF>> { BEGIN(INITIAL); }
++}
++
++<OCTAL>{
++	{OCTALNUMBER} {
++		master_lval.longtype = strtoul(master_text, NULL, 8);
++		return(OCTALNUMBER);
++	}
++
++	. { BEGIN(OPTSTR); yyless(0); }
++}
++
++%%
++
++#include "automount.h"
++
++int master_wrap(void)
++{
++	return 1;
++}
++
++static void master_echo(void)
++{
++	logmsg("%s", master_text);
++	return;
++}
++
++#ifdef FLEX_SCANNER
++
++void master_set_scan_buffer(const char *buffer)
++{
++	memset(buff, 0, sizeof(buff));
++	optr = buff;
++
++	YY_FLUSH_BUFFER;
++
++	line = buffer;
++	line_pos = &line[0];
++	/*
++	 * Ensure buffer is 1 greater than string and is zeroed before
++	 * the parse so we can fit the extra NULL which allows us to
++	 * explicitly match an end of line within the buffer (ie. the
++	 * need for 2 NULLS when parsing in memeory buffers).
++	 */
++	line_lim = line + strlen(buffer) + 1;
++}
++
++#ifndef min
++#define min(a,b) (((a) < (b)) ? (a) : (b))
++#endif
++
++int my_yyinput(char *buffer, int max_size)
++{
++	int n = min(max_size, line_lim - line_pos);
++
++	if (n > 0) {
++		memcpy(buffer, line_pos, n);
++		line_pos += n;
++	}
++	return n;
++}
++
++#else
++
++void master_set_scan_buffer(const char *buffer)
++{
++	line = buffer;
++}
++
++#endif
+--- autofs-5.1.4.orig/lib/Makefile
++++ autofs-5.1.4/lib/Makefile
+@@ -6,17 +6,14 @@
+ include ../Makefile.rules
+ 
+ SRCS = cache.c cat_path.c rpc_subs.c mounts.c log.c nsswitch.c \
+-	master_tok.l master_parse.y nss_tok.c nss_parse.tab.c \
+-	args.c alarm.c macros.c master.c defaults.c parse_subs.c \
+-	dev-ioctl-lib.c
++	nss_tok.c nss_parse.tab.c args.c alarm.c macros.c defaults.c \
++	parse_subs.c dev-ioctl-lib.c
+ RPCS = mount.h mount_clnt.c mount_xdr.c
+ OBJS = cache.o mount_clnt.o mount_xdr.o cat_path.o rpc_subs.o \
+-	mounts.o log.o nsswitch.o master_tok.o master_parse.tab.o \
+-	nss_tok.o nss_parse.tab.o args.o alarm.o macros.o master.o \
+-	defaults.o parse_subs.o dev-ioctl-lib.o
++	mounts.o log.o nsswitch.o nss_tok.o nss_parse.tab.o args.o \
++	alarm.o macros.o defaults.o parse_subs.o dev-ioctl-lib.o
+ 
+-YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h \
+-	  master_tok.c master_parse.tab.c master_parse.tab.h
++YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h
+ 
+ LIB = autofs.a
+ 
+@@ -54,16 +51,6 @@ mount_xdr.o: mount_xdr.c
+ 	$(CC) $(CFLAGS) -Wno-unused-variable -o mount_xdr.o -c mount_xdr.c
+ 	$(STRIP) mount_xdr.o
+ 
+-master_tok.c: master_tok.l
+-	$(LEX) -o$@ -Pmaster_ $?
+-
+-master_parse.tab.c master_parse.tab.h: master_parse.y
+-	$(YACC) -v -d -p master_ -b master_parse $?
+-
+-master_tok.o: master_tok.c master_parse.tab.h
+-
+-master_parse.tab.o: master_parse.tab.c master_parse.tab.h
+-
+ nss_tok.c: nss_tok.l
+ 	$(LEX) -o$@ -Pnss_ $?
+ 
+--- autofs-5.1.4.orig/lib/master.c
++++ /dev/null
+@@ -1,1885 +0,0 @@
+-/* ----------------------------------------------------------------------- *
+- *   
+- *  master.c - master map utility routines.
+- *
+- *   Copyright 2006 Ian Kent <raven@themaw.net>
+- *
+- *   This program is free software; you can redistribute it and/or modify
+- *   it under the terms of the GNU General Public License as published by
+- *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+- *   USA; either version 2 of the License, or (at your option) any later
+- *   version.
+- *   
+- *   This program is distributed in the hope that it will be useful,
+- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- *   GNU General Public License for more details.
+- *
+- * ----------------------------------------------------------------------- */
+-
+-#include <stdlib.h>
+-#include <string.h>
+-#include <memory.h>
+-#include <limits.h>
+-#include <signal.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include <ctype.h>
+-#include "automount.h"
+-
+-/* The root of the map entry tree */
+-struct master *master_list = NULL;
+-
+-extern const char *global_options;
+-extern long global_negative_timeout;
+-
+-/* Attribute to create a joinable thread */
+-extern pthread_attr_t th_attr;
+-
+-extern struct startup_cond suc;
+-
+-static struct map_source *
+-__master_find_map_source(struct master_mapent *,
+-			 const char *, const char *, int, const char **);
+-
+-static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
+-static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
+-
+-void master_mutex_lock(void)
+-{
+-	int status = pthread_mutex_lock(&master_mutex);
+-	if (status)
+-		fatal(status);
+-}
+-
+-void master_mutex_unlock(void)
+-{
+-	int status = pthread_mutex_unlock(&master_mutex);
+-	if (status)
+-		fatal(status);
+-}
+-
+-void master_mutex_lock_cleanup(void *arg)
+-{
+-	master_mutex_unlock();
+-	return;
+-}
+-
+-int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+-			    unsigned nobind, unsigned ghost, int submount)
+-{
+-	struct autofs_point *ap;
+-	int status;
+-
+-	ap = malloc(sizeof(struct autofs_point));
+-	if (!ap)
+-		return 0;
+-
+-	ap->state = ST_INIT;
+-
+-	ap->state_pipe[0] = -1;
+-	ap->state_pipe[1] = -1;
+-	ap->logpri_fifo = -1;
+-
+-	ap->path = strdup(entry->path);
+-	if (!ap->path) {
+-		free(ap);
+-		return 0;
+-	}
+-	ap->pref = NULL;
+-
+-	ap->entry = entry;
+-	ap->exp_thread = 0;
+-	ap->readmap_thread = 0;
+-	/*
+-	 * Program command line option overrides config.
+-	 * We can't use 0 negative timeout so use default.
+-	 */
+-	if (global_negative_timeout <= 0)
+-		ap->negative_timeout = defaults_get_negative_timeout();
+-	else
+-		ap->negative_timeout = global_negative_timeout;
+-	ap->exp_timeout = defaults_get_timeout();
+-	ap->exp_runfreq = 0;
+-	ap->flags = 0;
+-
+-	if (defaults_get_use_ignore_mount_option())
+-		ap->flags = MOUNT_FLAG_IGNORE;
+-	if (ghost)
+-		ap->flags |= MOUNT_FLAG_GHOST;
+-
+-	if (nobind)
+-		ap->flags |= MOUNT_FLAG_NOBIND;
+-
+-	if (ap->path[1] == '-')
+-		ap->type = LKP_DIRECT;
+-	else
+-		ap->type = LKP_INDIRECT;
+-
+-	ap->logopt = logopt;
+-
+-	ap->parent = NULL;
+-	ap->thid = 0;
+-	ap->submnt_count = 0;
+-	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);
+-	if (status) {
+-		free(ap->path);
+-		free(ap);
+-		return 0;
+-	}
+-	ap->mode = 0;
+-
+-	entry->ap = ap;
+-
+-	return 1;
+-}
+-
+-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 mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
+-		p = p->next;
+-		ext_mount_remove(mnt->ext_mp);
+-		mnts_remove_amdmount(mnt->mp);
+-	}
+-	mounts_mutex_unlock(ap);
+-
+-	status = pthread_mutex_destroy(&ap->mounts_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	if (ap->pref)
+-		free(ap->pref);
+-	free(ap->path);
+-	free(ap);
+-}
+-
+-struct map_source *
+-master_add_map_source(struct master_mapent *entry,
+-		      char *type, char *format, time_t age,
+-		      int argc, const char **argv)
+-{
+-	struct map_source *source;
+-	char *ntype, *nformat;
+-	const char **tmpargv;
+-
+-	source = malloc(sizeof(struct map_source));
+-	if (!source)
+-		return NULL;
+-	memset(source, 0, sizeof(struct map_source));
+-	source->ref = 1;
+-
+-	if (type) {
+-		ntype = strdup(type);
+-		if (!ntype) {
+-			master_free_map_source(source, 0);
+-			return NULL;
+-		}
+-		source->type = ntype;
+-	}
+-
+-	if (format) {
+-		nformat = strdup(format);
+-		if (!nformat) {
+-			master_free_map_source(source, 0);
+-			return NULL;
+-		}
+-		source->format = nformat;
+-		if (!strcmp(nformat, "amd"))
+-			source->flags |= MAP_FLAG_FORMAT_AMD;
+-	}
+-
+-	source->age = age;
+-	source->stale = 1;
+-
+-	tmpargv = copy_argv(argc, argv);
+-	if (!tmpargv) {
+-		master_free_map_source(source, 0);
+-		return NULL;
+-	}
+-	source->argc = argc;
+-	source->argv = tmpargv;
+-	if (source->argv[0])
+-		source->name = strdup(source->argv[0]);
+-
+-	master_source_writelock(entry);
+-
+-	if (!entry->maps) {
+-		source->mc = cache_init(entry->ap, source);
+-		if (!source->mc) {
+-			master_free_map_source(source, 0);
+-			master_source_unlock(entry);
+-			return NULL;
+-		}
+-		entry->maps = source;
+-	} else {
+-		struct map_source *this, *last, *next;
+-
+-		/* Typically there only a few map sources */
+-
+-		this = __master_find_map_source(entry, type, format, argc, tmpargv);
+-		if (this) {
+-			debug(entry->ap->logopt,
+-			      "map source used without taking reference");
+-			this->age = age;
+-			master_free_map_source(source, 0);
+-			master_source_unlock(entry);
+-			return this;
+-		}
+-
+-		source->mc = cache_init(entry->ap, source);
+-		if (!source->mc) {
+-			master_free_map_source(source, 0);
+-			master_source_unlock(entry);
+-			return NULL;
+-		}
+-
+-		last = NULL;
+-		next = entry->maps;
+-		while (next) {
+-			last = next;
+-			next = next->next;
+-		}
+-		if (last)
+-			last->next = source;
+-		else
+-			entry->maps = source;
+-	}
+-
+-	master_source_unlock(entry);
+-
+-	return source;
+-}
+-
+-static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
+-{
+-	int res = 0;
+-
+-	if (type) {
+-		if (!map->type)
+-			goto done;
+-
+-		if (strcmp(map->type, type))
+-			goto done;
+-	} else if (map->type)
+-		goto done;
+-
+-	if (format) {
+-		if (!map->format)
+-			goto done;
+-
+-		if (strcmp(map->format, format))
+-			goto done;
+-	} else if (map->format)
+-		goto done;
+-
+-	res = 1;
+-done:
+-	return res;
+-}
+-
+-static struct map_source *
+-__master_find_map_source(struct master_mapent *entry,
+-			 const char *type, const char *format,
+-			 int argc, const char **argv)
+-{
+-	struct map_source *map;
+-	struct map_source *source = NULL;
+-	int res;
+-
+-	map = entry->maps;
+-	while (map) {
+-		res = compare_source_type_and_format(map, type, format);
+-		if (!res)
+-			goto next;
+-
+-		res = compare_argv(map->argc, map->argv, argc, argv);
+-		if (!res)
+-			goto next;
+-
+-		source = map;
+-		break;
+-next:
+-		map = map->next;
+-	}
+-
+-	return source;
+-}
+-
+-struct map_source *master_find_map_source(struct master_mapent *entry,
+-				const char *type, const char *format,
+-				int argc, const char **argv)
+-{
+-	struct map_source *source = NULL;
+-
+-	master_source_readlock(entry);
+-	source = __master_find_map_source(entry, type, format, argc, argv);
+-	master_source_unlock(entry);
+-
+-	return source;
+-}
+-
+-struct map_source *
+-master_get_map_source(struct master_mapent *entry,
+-		      const char *type, const char *format,
+-		      int argc, const char **argv)
+-{
+-	struct map_source *source = NULL;
+-
+-	master_source_readlock(entry);
+-	source = __master_find_map_source(entry, type, format, argc, argv);
+-	if (source)
+-		source->ref++;
+-	master_source_unlock(entry);
+-
+-	return source;
+-}
+-
+-static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
+-{
+-	/* instance map sources are not ref counted */
+-	if (source->ref && --source->ref)
+-		return;
+-	if (source->type)
+-		free(source->type);
+-	if (source->format)
+-		free(source->format);
+-	if (source->name)
+-		free(source->name);
+-	if (free_cache && source->mc)
+-		cache_release(source);
+-	if (source->lookup) {
+-		struct map_source *instance;
+-
+-		instance = source->instance;
+-		while (instance) {
+-			if (instance->lookup)
+-				close_lookup(instance->lookup);
+-			instance = instance->next;
+-		}
+-		close_lookup(source->lookup);
+-	}
+-	if (source->argv)
+-		free_argv(source->argc, source->argv);
+-	if (source->instance) {
+-		struct map_source *instance, *next;
+-
+-		instance = source->instance;
+-		while (instance) {
+-			next = instance->next;
+-			__master_free_map_source(instance, 0);
+-			instance = next;
+-		}
+-	}
+-
+-	free(source);
+-
+-	return;
+-}
+-
+-void master_free_map_source(struct map_source *source, unsigned int free_cache)
+-{
+-	int status;
+-
+-	status = pthread_mutex_lock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	__master_free_map_source(source, free_cache);
+-
+-	status = pthread_mutex_unlock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-}
+-
+-struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
+-{
+-	struct map_source *map;
+-	struct map_source *instance = NULL;
+-	int status, res;
+-
+-	status = pthread_mutex_lock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	map = source->instance;
+-	while (map) {
+-		res = compare_source_type_and_format(map, type, format);
+-		if (!res)
+-			goto next;
+-
+-		if (!argv) {
+-			instance = map;
+-			break;
+-		}
+-
+-		res = compare_argv(map->argc, map->argv, argc, argv);
+-		if (!res)
+-			goto next;
+-
+-		instance = map;
+-		break;
+-next:
+-		map = map->next;
+-	}
+-
+-	status = pthread_mutex_unlock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	return instance;
+-}
+-
+-struct map_source *
+-master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
+-{
+-	struct map_source *instance;
+-	struct map_source *new;
+-	char *ntype, *nformat;
+-	const char **tmpargv;
+-	int status;
+-
+-	instance = master_find_source_instance(source, type, format, argc, argv);
+-	if (instance)
+-		return instance;
+-
+-	new = malloc(sizeof(struct map_source));
+-	if (!new)
+-		return NULL;
+-	memset(new, 0, sizeof(struct map_source));
+-
+-	if (type) {
+-		ntype = strdup(type);
+-		if (!ntype) {
+-			master_free_map_source(new, 0);
+-			return NULL;
+-		}
+-		new->type = ntype;
+-	}
+-
+-	if (format) {
+-		nformat = strdup(format);
+-		if (!nformat) {
+-			master_free_map_source(new, 0);
+-			return NULL;
+-		}
+-		new->format = nformat;
+-		if (!strcmp(nformat, "amd"))
+-			new->flags |= MAP_FLAG_FORMAT_AMD;
+-	}
+-
+-	new->age = age;
+-	new->master_line = 0;
+-	new->mc = source->mc;
+-	new->exp_timeout = source->exp_timeout;
+-	new->stale = 1;
+-
+-	tmpargv = copy_argv(argc, argv);
+-	if (!tmpargv) {
+-		master_free_map_source(new, 0);
+-		return NULL;
+-	}
+-	new->argc = argc;
+-	new->argv = tmpargv;
+-	if (source->name)
+-		new->name = strdup(source->name);
+-
+-	status = pthread_mutex_lock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	if (!source->instance)
+-		source->instance = new;
+-	else {
+-		/*
+-		 * We know there's no other instance of this
+-		 * type so just add to head of list
+-		 */
+-		new->next = source->instance;
+-		source->instance = new;
+-	}
+-
+-	status = pthread_mutex_unlock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	return new;
+-}
+-
+-int check_stale_instances(struct map_source *source)
+-{
+-	struct map_source *map;
+-
+-	if (!source)
+-		return 0;
+-
+-	map = source->instance;
+-	while (map) {
+-		if (map->stale)
+-			return 1;
+-		if (check_stale_instances(map))
+-			return 1;
+-		map = map->next;
+-	}
+-
+-	return 0;
+-}
+-
+-void clear_stale_instances(struct map_source *source)
+-{
+-	struct map_source *map;
+-
+-	if (!source)
+-		return;
+-
+-	map = source->instance;
+-	while (map) {
+-		clear_stale_instances(map);
+-		if (map->stale)
+-			map->stale = 0;
+-		map = map->next;
+-	}
+-
+-	return;
+-}
+-
+-void send_map_update_request(struct autofs_point *ap)
+-{
+-	struct map_source *map;
+-	int status, need_update = 0;
+-
+-	status = pthread_mutex_lock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	map = ap->entry->maps;
+-	while (map) {
+-		if (check_stale_instances(map))
+-			map->stale = 1;
+-		if (map->stale) {
+-			need_update = 1;
+-			break;
+-		}
+-		map = map->next;
+-	}
+-
+-	status = pthread_mutex_unlock(&instance_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	if (!need_update)
+-		return;
+-
+-	st_add_task(ap, ST_READMAP);
+-
+-	return;
+-}
+-
+-void master_source_writelock(struct master_mapent *entry)
+-{
+-	int status;
+-
+-	status = pthread_rwlock_wrlock(&entry->source_lock);
+-	if (status) {
+-		logmsg("master_mapent source write lock failed");
+-		fatal(status);
+-	}
+-	return;
+-}
+-
+-void master_source_readlock(struct master_mapent *entry)
+-{
+-	int retries = 25;
+-	int status;
+-
+-	while (retries--) {
+-		status = pthread_rwlock_rdlock(&entry->source_lock);
+-		if (status != EAGAIN && status != EBUSY)
+-			break;
+-		else {
+-                	struct timespec t = { 0, 200000000 };
+-	                struct timespec r;
+-
+-			if (status == EAGAIN)
+-				logmsg("master_mapent source too many readers");
+-			else
+-				logmsg("master_mapent source write lock held");
+-
+-                	while (nanosleep(&t, &r) == -1 && errno == EINTR)
+-                        	memcpy(&t, &r, sizeof(struct timespec));
+-		}
+-	}
+-
+-	if (status) {
+-		logmsg("master_mapent source read lock failed");
+-		fatal(status);
+-	}
+-
+-	return;
+-}
+-
+-void master_source_unlock(struct master_mapent *entry)
+-{
+-	int status;
+-
+-	status = pthread_rwlock_unlock(&entry->source_lock);
+-	if (status) {
+-		logmsg("master_mapent source unlock failed");
+-		fatal(status);
+-	}
+-	return;
+-}
+-
+-void master_source_lock_cleanup(void *arg)
+-{
+-	struct master_mapent *entry = (struct master_mapent *) arg;
+-
+-	master_source_unlock(entry);
+-
+-	return;
+-}
+-
+-void master_source_current_wait(struct master_mapent *entry)
+-{
+-	int status;
+-
+-	status = pthread_mutex_lock(&entry->current_mutex);
+-	if (status) {
+-		logmsg("entry current source lock failed");
+-		fatal(status);
+-	}
+-
+-	while (entry->current != NULL) {
+-		status = pthread_cond_wait(
+-				&entry->current_cond, &entry->current_mutex);
+-		if (status) {
+-			logmsg("entry current source condition wait failed");
+-			fatal(status);
+-		}
+-	}
+-
+-	return;
+-}
+-
+-void master_source_current_signal(struct master_mapent *entry)
+-{
+-	int status;
+-
+-	status = pthread_cond_signal(&entry->current_cond);
+-	if (status) {
+-		logmsg("entry current source condition signal failed");
+-		fatal(status);
+-	}
+-
+-	status = pthread_mutex_unlock(&entry->current_mutex);
+-	if (status) {
+-		logmsg("entry current source unlock failed");
+-		fatal(status);
+-	}
+-
+-	return;
+-}
+-
+-struct master_mapent *master_find_mapent(struct master *master, const char *path)
+-{
+-	struct list_head *head, *p;
+-
+-	head = &master->mounts;
+-	list_for_each(p, head) {
+-		struct master_mapent *entry;
+-
+-		entry = list_entry(p, struct master_mapent, list);
+-
+-		if (!strcmp(entry->path, path))
+-			return entry;
+-	}
+-
+-	return NULL;
+-}
+-
+-unsigned int master_partial_match_mapent(struct master *master, const char *path)
+-{
+-	struct list_head *head, *p;
+-	size_t path_len = strlen(path);
+-	int ret = 0;
+-
+-	head = &master->mounts;
+-	list_for_each(p, head) {
+-		struct master_mapent *entry;
+-		size_t entry_len;
+-		size_t cmp_len;
+-
+-		entry = list_entry(p, struct master_mapent, list);
+-
+-		entry_len = strlen(entry->path);
+-		cmp_len = min(entry_len, path_len);
+-
+-		if (!strncmp(entry->path, path, cmp_len)) {
+-			/* paths are equal, matching master map entry ? */
+-			if (entry_len == path_len) {
+-				if (entry->maps &&
+-				    entry->maps->flags & MAP_FLAG_FORMAT_AMD)
+-					ret = 1;
+-				else
+-					ret = -1;
+-				break;
+-			}
+-
+-			/* amd mount conflicts with entry mount */
+-			if (entry_len > path_len &&
+-			    *(entry->path + path_len) == '/') {
+-				ret = -1;
+-				break;
+-			}
+-
+-			/* entry mount conflicts with amd mount */
+-			if (entry_len < path_len &&
+-			    *(path + entry_len) == '/') {
+-				ret = -1;
+-				break;
+-			}
+-		}
+-	}
+-
+-	return ret;
+-}
+-
+-struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
+-{
+-	struct master_mapent *entry;
+-	int status;
+-	char *tmp;
+-
+-	entry = malloc(sizeof(struct master_mapent));
+-	if (!entry)
+-		return NULL;
+-
+-	memset(entry, 0, sizeof(struct master_mapent));
+-
+-	tmp = strdup(path);
+-	if (!tmp) {
+-		free(entry);
+-		return NULL;
+-	}
+-	entry->path = tmp;
+-
+-	entry->thid = 0;
+-	entry->age = age;
+-	entry->master = master;
+-	entry->current = NULL;
+-	entry->maps = NULL;
+-	entry->ap = NULL;
+-
+-	status = pthread_rwlock_init(&entry->source_lock, NULL);
+-	if (status)
+-		fatal(status);
+-
+-	status = pthread_mutex_init(&entry->current_mutex, NULL);
+-	if (status)
+-		fatal(status);
+-
+-	status = pthread_cond_init(&entry->current_cond, NULL);
+-	if (status)
+-		fatal(status);
+-
+-	INIT_LIST_HEAD(&entry->list);
+-
+-	return entry;
+-}
+-
+-void master_add_mapent(struct master *master, struct master_mapent *entry)
+-{
+-	list_add_tail(&entry->list, &master->mounts);
+-	return;
+-}
+-
+-void master_remove_mapent(struct master_mapent *entry)
+-{
+-	struct master *master = entry->master;
+-
+-	if (entry->ap->submount)
+-		return;
+-
+-	if (!list_empty(&entry->list)) {
+-		list_del_init(&entry->list);
+-		list_add(&entry->join, &master->completed);
+-	}
+-
+-	return;
+-}
+-
+-void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
+-{
+-	if (entry->maps) {
+-		struct map_source *m, *n;
+-
+-		m = entry->maps;
+-		while (m) {
+-			n = m->next;
+-			master_free_map_source(m, free_cache);
+-			m = n;
+-		}
+-		entry->maps = NULL;
+-	}
+-
+-	return;
+-}
+-
+-void master_free_mapent(struct master_mapent *entry)
+-{
+-	int status;
+-
+-	if (entry->path)
+-		free(entry->path);
+-
+-	master_free_autofs_point(entry->ap);
+-
+-	status = pthread_rwlock_destroy(&entry->source_lock);
+-	if (status)
+-		fatal(status);
+-
+-	status = pthread_mutex_destroy(&entry->current_mutex);
+-	if (status)
+-		fatal(status);
+-
+-	status = pthread_cond_destroy(&entry->current_cond);
+-	if (status)
+-		fatal(status);
+-
+-	free(entry);
+-
+-	return;
+-}
+-
+-struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
+-{
+-	struct master *master;
+-	char *tmp;
+-
+-	master = malloc(sizeof(struct master));
+-	if (!master)
+-		return NULL;
+-
+-	if (!name)
+-		tmp = (char *) defaults_get_master_map();
+-	else
+-		tmp = strdup(name);
+-
+-	if (!tmp) {
+-		free(master);
+-		return NULL;
+-	}
+-
+-	master->name = tmp;
+-	master->nc = NULL;
+-
+-	master->recurse = 0;
+-	master->depth = 0;
+-	master->reading = 0;
+-	master->read_fail = 0;
+-	master->readall = 0;
+-	master->default_ghost = flags & DAEMON_FLAGS_GHOST;
+-	master->default_timeout = timeout;
+-	master->default_logging = defaults_get_logging();
+-	master->logopt = master->default_logging;
+-
+-	INIT_LIST_HEAD(&master->mounts);
+-	INIT_LIST_HEAD(&master->completed);
+-
+-	return master;
+-}
+-
+-static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
+-{
+-	unsigned int m_logopt = master->logopt;
+-	struct master_mapent *entry;
+-	struct map_source *source;
+-	unsigned int loglevel;
+-	unsigned int logopt;
+-	unsigned int flags;
+-	char *argv[2];
+-	char **paths;
+-	int ret;
+-	int i;
+-
+-	loglevel = conf_amd_get_log_options();
+-
+-	paths = conf_amd_get_mount_paths();
+-	if (!paths)
+-		return;
+-
+-	i = 0;
+-	while (paths[i]) {
+-		const char *path = paths[i];
+-		unsigned int ghost = 0;
+-		time_t timeout;
+-		char *type = NULL;
+-		char *map = NULL;
+-		char *opts;
+-
+-		ret = master_partial_match_mapent(master, path);
+-		if (ret) {
+-			/* If this amd entry is already present in the
+-			 * master map it's not a duplicate, don't issue
+-			 * an error message.
+-			 */
+-			if (ret == 1)
+-				goto next;
+-			info(m_logopt,
+-			     "amd section mount path conflict, %s ignored",
+-			     path);
+-			goto next;
+-		}
+-
+-		map = conf_amd_get_map_name(path);
+-		if (!map) {
+-			error(m_logopt,
+-			      "failed to get map name for amd section mount %s",
+-			      path);
+-			goto next;
+-		}
+-
+-		entry = master_new_mapent(master, path, age);
+-		if (!entry) {
+-			error(m_logopt,
+-			      "failed to allocate new amd section mount %s",
+-			      path);
+-			goto next;
+-		}
+-
+-		logopt = m_logopt;
+-		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
+-			logopt = LOGOPT_DEBUG;
+-		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
+-			logopt = LOGOPT_VERBOSE;
+-
+-		/* It isn't possible to provide the fullybrowsable amd
+-		 * browsing functionality within the autofs framework.
+-		 * This flag will not be set if browsable_dirs = full
+-		 * in the configuration or fullybrowsable is present as
+-		 * an option.
+-		 */
+-		flags = conf_amd_get_flags(path);
+-		if (flags & CONF_BROWSABLE_DIRS)
+-			ghost = 1;
+-
+-		ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
+-		if (!ret) {
+-			error(m_logopt, "failed to add autofs_point");
+-			master_free_mapent(entry);
+-			goto next;
+-		}
+-
+-		opts = conf_amd_get_map_options(path);
+-		if (opts) {
+-			/* autofs uses the equivalent of cache:=inc,sync
+-			 * (except for file maps which use cache:=all,sync)
+-			 * but if the map is large then it may be necessary
+-			 * to read the whole map at startup even if browsing
+-			 * is is not enabled, so look for cache:=all in the
+-			 * map_options configuration entry.
+-			 */
+-			if (strstr(opts, "cache:=all"))
+-				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
+-			free(opts);
+-		}
+-
+-		type = conf_amd_get_map_type(path);
+-		argv[0] = map;
+-		argv[1] = NULL;
+-
+-		source = master_add_map_source(entry, type, "amd",
+-					       age, 1, (const char **) argv);
+-		if (!source) {
+-			error(m_logopt,
+-			      "failed to add source for amd section mount %s",
+-			      path);
+-			master_free_mapent(entry);
+-			goto next;
+-		}
+-
+-		timeout = conf_amd_get_dismount_interval(path);
+-		set_exp_timeout(entry->ap, source, timeout);
+-		source->master_line = 0;
+-
+-		entry->age = age;
+-		entry->current = NULL;
+-
+-		master_add_mapent(master, entry);
+-next:
+-		if (type)
+-			free(type);
+-		if (map)
+-			free(map);
+-		i++;
+-	}
+-
+-	i = 0;
+-	while (paths[i])
+-		free(paths[i++]);
+-	free(paths);
+-}
+-
+-static void wait_for_lookups_and_lock(struct master *master)
+-{
+-	struct list_head *p, *head;
+-	int status;
+-
+-again:
+-	master_mutex_lock();
+-
+-	head = &master->mounts;
+-	p = head->next;
+-	while (p != head) {
+-		struct master_mapent *this;
+-
+-		this = list_entry(p, struct master_mapent, list);
+-
+-		status = pthread_rwlock_trywrlock(&this->source_lock);
+-		if (status) {
+-			struct timespec t = { 0, 200000000 };
+-			struct timespec r;
+-
+-			master_mutex_unlock();
+-
+-			while (nanosleep(&t, &r) == -1 && errno == EINTR)
+-				memcpy(&t, &r, sizeof(struct timespec));
+-
+-			goto again;
+-		}
+-		master_source_unlock(this);
+-
+-		p = p->next;
+-	}
+-}
+-
+-int master_read_master(struct master *master, time_t age)
+-{
+-	unsigned int logopt = master->logopt;
+-	struct mapent_cache *nc;
+-
+-	/*
+-	 * We need to clear and re-populate the null map entry cache
+-	 * before alowing anyone else to use it.
+-	 */
+-	wait_for_lookups_and_lock(master);
+-	if (master->nc) {
+-		cache_writelock(master->nc);
+-		nc = master->nc;
+-		cache_clean_null_cache(nc);
+-	} else {
+-		nc = cache_init_null_cache(master);
+-		if (!nc) {
+-			error(logopt,
+-			      "failed to init null map cache for %s",
+-			      master->name);
+-			return 0;
+-		}
+-		cache_writelock(nc);
+-		master->nc = nc;
+-	}
+-	master_init_scan();
+-	lookup_nss_read_master(master, age);
+-	cache_unlock(nc);
+-	master_add_amd_mount_section_mounts(master, age);
+-
+-	if (!master->read_fail)
+-		master_mount_mounts(master, age);
+-	else {
+-		master->read_fail = 0;
+-		/* HUP signal sets master->readall == 1 only */
+-		if (!master->readall) {
+-			master_mutex_unlock();
+-			return 0;
+-		} else
+-			master_mount_mounts(master, age);
+-	}
+-
+-	if (list_empty(&master->mounts))
+-		warn(logopt, "no mounts in table");
+-
+-	master_mutex_unlock();
+-
+-	return 1;
+-}
+-
+-int master_submount_list_empty(struct autofs_point *ap)
+-{
+-	int res = 0;
+-
+-	mounts_mutex_lock(ap);
+-	if (list_empty(&ap->submounts))
+-		res = 1;
+-	mounts_mutex_unlock(ap);
+-
+-	return res;
+-}
+-
+-int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
+-{
+-	struct mnt_list *this, *sbmnt;
+-	int ret = 1;
+-
+-	this = mnts_find_submount(path);
+-	if (this) {
+-		/* We have found a submount to expire */
+-		st_mutex_lock();
+-
+-		if (this->ap->state == ST_SHUTDOWN) {
+-			this = NULL;
+-			st_mutex_unlock();
+-			goto done;
+-		}
+-
+-		this->ap->shutdown = ap->shutdown;
+-
+-		__st_add_task(this->ap, state);
+-
+-		st_mutex_unlock();
+-
+-		st_wait_task(this->ap, state, 0);
+-
+-		/*
+-		 * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
+-		 * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
+-		 * to ST_READY.
+-		 */
+-		st_mutex_lock();
+-		while ((sbmnt = mnts_find_submount(path))) {
+-			struct timespec t = { 0, 300000000 };
+-			struct timespec r;
+-
+-			if (sbmnt->ap->state != ST_SHUTDOWN &&
+-			    sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
+-			    sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
+-				ret = 0;
+-				mnts_put_mount(sbmnt);
+-				break;
+-			}
+-			mnts_put_mount(sbmnt);
+-
+-			st_mutex_unlock();
+-			while (nanosleep(&t, &r) == -1 && errno == EINTR)
+-				memcpy(&t, &r, sizeof(struct timespec));
+-			st_mutex_lock();
+-		}
+-		st_mutex_unlock();
+-done:
+-		mnts_put_mount(this);
+-	}
+-
+-	return ret;
+-}
+-
+-void master_notify_state_change(struct master *master, int sig)
+-{
+-	struct master_mapent *entry;
+-	struct autofs_point *ap;
+-	struct list_head *p;
+-	int cur_state;
+-	unsigned int logopt;
+-
+-	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-	master_mutex_lock();
+-
+-	list_for_each(p, &master->mounts) {
+-		enum states next = ST_INVAL;
+-
+-		entry = list_entry(p, struct master_mapent, list);
+-
+-		ap = entry->ap;
+-		logopt = ap->logopt;
+-
+-		st_mutex_lock();
+-
+-		if (ap->state == ST_SHUTDOWN)
+-			goto next;
+-
+-		switch (sig) {
+-		case SIGTERM:
+-		case SIGINT:
+-			if (ap->state != ST_SHUTDOWN_PENDING &&
+-			    ap->state != ST_SHUTDOWN_FORCE) {
+-				next = ST_SHUTDOWN_PENDING;
+-				ap->shutdown = 1;
+-				__st_add_task(ap, next);
+-			}
+-			break;
+-#ifdef ENABLE_FORCED_SHUTDOWN
+-		case SIGUSR2:
+-			if (ap->state != ST_SHUTDOWN_FORCE &&
+-			    ap->state != ST_SHUTDOWN_PENDING) {
+-				next = ST_SHUTDOWN_FORCE;
+-				ap->shutdown = 1;
+-				__st_add_task(ap, next);
+-			}
+-			break;
+-#endif
+-		case SIGUSR1:
+-			assert(ap->state == ST_READY);
+-			next = ST_PRUNE;
+-			__st_add_task(ap, next);
+-			break;
+-		}
+-next:
+-		if (next != ST_INVAL)
+-			debug(logopt,
+-			      "sig %d switching %s from %d to %d",
+-			      sig, ap->path, ap->state, next);
+-
+-		st_mutex_unlock();
+-	}
+-
+-	master_mutex_unlock();
+-	pthread_setcancelstate(cur_state, NULL);
+-
+-	return;
+-}
+-
+-static int master_do_mount(struct master_mapent *entry)
+-{
+-	struct startup_cond suc;
+-	struct autofs_point *ap;
+-	pthread_t thid;
+-	int status;
+-
+-	ap = entry->ap;
+-
+-	if (handle_mounts_startup_cond_init(&suc)) {
+-		crit(ap->logopt,
+-		     "failed to init startup cond for mount %s", entry->path);
+-		return 0;
+-	}
+-
+-	suc.ap = ap;
+-	suc.root = ap->path;
+-	suc.done = 0;
+-	suc.status = 0;
+-
+-	if (!(do_force_unlink & UNLINK_AND_EXIT))
+-		debug(ap->logopt, "mounting %s", entry->path);
+-
+-	status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
+-	if (status) {
+-		crit(ap->logopt,
+-		     "failed to create mount handler thread for %s",
+-		     entry->path);
+-		handle_mounts_startup_cond_destroy(&suc);
+-		return 0;
+-	}
+-
+-	while (!suc.done) {
+-		status = pthread_cond_wait(&suc.cond, &suc.mutex);
+-		if (status)
+-			fatal(status);
+-	}
+-
+-	if (suc.status) {
+-		if (!(do_force_unlink & UNLINK_AND_EXIT))
+-			error(ap->logopt, "failed to startup mount");
+-		handle_mounts_startup_cond_destroy(&suc);
+-		return 0;
+-	}
+-	entry->thid = thid;
+-
+-	handle_mounts_startup_cond_destroy(&suc);
+-
+-	return 1;
+-}
+-
+-static void check_update_map_sources(struct master_mapent *entry, int readall)
+-{
+-	struct map_source *source, *last;
+-	struct autofs_point *ap;
+-	int map_stale = 0;
+-
+-	if (readall)
+-		map_stale = 1;
+-
+-	ap = entry->ap;
+-
+-	master_source_writelock(entry);
+-
+-	last = NULL;
+-	source = entry->maps;
+-	while (source) {
+-		if (readall)
+-			source->stale = 1;
+-
+-		/*
+-		 * If a map source is no longer valid and all it's
+-		 * entries have expired away we can get rid of it.
+-		 */
+-		if (entry->age > source->age) {
+-			struct mapent *me;
+-			cache_readlock(source->mc);
+-			me = cache_lookup_first(source->mc);
+-			if (!me) {
+-				struct map_source *next = source->next;
+-
+-				cache_unlock(source->mc);
+-
+-				if (!last)
+-					entry->maps = next;
+-				else
+-					last->next = next;
+-
+-				if (entry->maps == source)
+-					entry->maps = next;
+-
+-				master_free_map_source(source, 1);
+-
+-				source = next;
+-				continue;
+-			} else {
+-				source->stale = 1;
+-				map_stale = 1;
+-			}
+-			cache_unlock(source->mc);
+-		}
+-		last = source;
+-		source = source->next;
+-	}
+-
+-	master_source_unlock(entry);
+-
+-	/* The map sources have changed */
+-	if (map_stale)
+-		st_add_task(ap, ST_READMAP);
+-
+-	return;
+-}
+-
+-int master_mount_mounts(struct master *master, time_t age)
+-{
+-	struct mapent_cache *nc = master->nc;
+-	struct list_head *p, *head;
+-	int cur_state;
+-
+-	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-
+-	head = &master->mounts;
+-	p = head->next;
+-	while (p != head) {
+-		struct master_mapent *this;
+-		struct autofs_point *ap;
+-		struct mapent *ne, *nested;
+-		struct stat st;
+-		int state_pipe, save_errno;
+-		int ret;
+-
+-		this = list_entry(p, struct master_mapent, list);
+-		p = p->next;
+-
+-		ap = this->ap;
+-
+-		/* A master map entry has gone away */
+-		if (this->age < age) {
+-			st_add_task(ap, ST_SHUTDOWN_PENDING);
+-			continue;
+-		}
+-
+-		cache_readlock(nc);
+-		ne = cache_lookup_distinct(nc, this->path);
+-		/*
+-		 * If this path matched a nulled entry the master map entry
+-		 * must be an indirect mount so the master map entry line
+-		 * number may be obtained from this->maps.
+-		 */
+-		if (ne) {
+-			int lineno = ne->age;
+-			cache_unlock(nc);
+-
+-			/* null entry appears after map entry */
+-			if (this->maps->master_line < lineno) {
+-				warn(ap->logopt,
+-				     "ignoring null entry that appears after "
+-				     "existing entry for %s", this->path);
+-				goto cont;
+-			}
+-			if (ap->state != ST_INIT) {
+-				st_add_task(ap, ST_SHUTDOWN_PENDING);
+-				continue;
+-			}
+-			/*
+-			 * The map entry hasn't been started yet and we've
+-			 * seen a preceeding null map entry for it so just
+-			 * delete it from the master map entry list so it
+-			 * doesn't get in the road.
+-			 */
+-			list_del_init(&this->list);
+-			master_free_mapent_sources(ap->entry, 1);
+-			master_free_mapent(ap->entry);
+-			continue;
+-		}
+-		nested = cache_partial_match(nc, this->path);
+-		if (nested) {
+-			error(ap->logopt,
+-			     "removing invalid nested null entry %s",
+-			     nested->key);
+-			nested = cache_partial_match(nc, this->path);
+-			if (nested)
+-				cache_delete(nc, nested->key);
+-		}
+-		cache_unlock(nc);
+-cont:
+-		st_mutex_lock();
+-
+-		state_pipe = this->ap->state_pipe[1];
+-
+-		/* No pipe so mount is needed */
+-		ret = fstat(state_pipe, &st);
+-		save_errno = errno;
+-
+-		st_mutex_unlock();
+-
+-		if (!ret)
+-			check_update_map_sources(this, master->readall);
+-		else if (ret == -1 && save_errno == EBADF) {
+-			if (!master_do_mount(this)) {
+-				list_del_init(&this->list);
+-				master_free_mapent_sources(ap->entry, 1);
+-				master_free_mapent(ap->entry);
+-			}
+-		}
+-	}
+-
+-	pthread_setcancelstate(cur_state, NULL);
+-
+-	return 1;
+-}
+-
+-/* The nss source instances end up in reverse order. */
+-static void list_source_instances(struct map_source *source, struct map_source *instance)
+-{
+-	if (!source || !instance) {
+-		printf("none");
+-		return;
+-	}
+-
+-	if (instance->next)
+-		list_source_instances(source, instance->next);
+-
+-	/*
+-	 * For convienience we map nss instance type "files" to "file".
+-	 * Check for that and report corrected instance type.
+-	 */
+-	if (strcmp(instance->type, "file"))
+-		printf("%s ", instance->type);
+-	else {
+-		if (source->argv && *(source->argv[0]) != '/')
+-			printf("files ");
+-		else
+-			printf("%s ", instance->type);
+-	}
+-
+-	return;
+-}
+-
+-static void print_map_info(struct map_source *source)
+-{
+-	int argc = source->argc;
+-	int i, multi, map_num;
+-
+-	multi = (source->type && !strcmp(source->type, "multi"));
+-	map_num = 1;
+-	for (i = 0; i < argc; i++) {
+-		if (source->argv[i] && *source->argv[i] != '-') {
+-			if (!multi)
+-				printf("  map: %s\n", source->argv[i]);
+-			else
+-				printf("  map[%i]: %s\n", map_num, source->argv[i]);
+-			i++;
+-		}
+-
+-		if (i >= argc)
+-			return;
+-
+-		if (!strcmp(source->argv[i], "--"))
+-			continue;
+-
+-		if (source->argv[i]) {
+-			int need_newline = 0;
+-			int j;
+-
+-			if (!multi)
+-				printf("  arguments:");
+-			else
+-				printf("  arguments[%i]:", map_num);
+-
+-			for (j = i; j < source->argc; j++) {
+-				if (!strcmp(source->argv[j], "--"))
+-					break;
+-				printf(" %s", source->argv[j]);
+-				i++;
+-				need_newline = 1;
+-			}
+-			if (need_newline)
+-				printf("\n");
+-		}
+-		if (multi)
+-			map_num++;
+-	}
+-
+-	return;
+-}
+-
+-static int match_type(const char *source, const char *type)
+-{
+-	if (!strcmp(source, type))
+-		return 1;
+-	/* Sources file and files are synonymous */
+-	if (!strncmp(source, type, 4) && (strlen(source) <= 5))
+-		return 1;
+-	return 0;
+-}
+-
+-static char *get_map_name(const char *string)
+-{
+-	char *name, *tmp;
+-	char *start, *end, *base;
+-
+-	tmp = strdup(string);
+-	if (!tmp) {
+-		printf("error: allocation failure: %s\n", strerror(errno));
+-		return NULL;
+-	}
+-
+-	base = basename(tmp);
+-	end = strchr(base, ',');
+-	if (end)
+-		*end = '\0';
+-	start = strchr(tmp, '=');
+-	if (start)
+-		start++;
+-	else {
+-		char *colon = strrchr(base, ':');
+-		if (colon)
+-			start = ++colon;
+-		else
+-			start = base;
+-	}
+-
+-	name = strdup(start);
+-	if (!name)
+-		printf("error: allocation failure: %s\n", strerror(errno));
+-	free(tmp);
+-
+-	return name;
+-}
+-
+-static int match_name(struct map_source *source, const char *name)
+-{
+-	int argc = source->argc;
+-	int ret = 0;
+-	int i;
+-
+-	/*
+-	 * This can't work for old style "multi" type sources since
+-	 * there's no way to know from which map the cache entry came
+-	 * from and duplicate entries are ignored at map read time.
+-	 * All we can really do is list all the entries for the given
+-	 * multi map if one of its map names matches.
+-	 */
+-	for (i = 0; i < argc; i++) {
+-		if (i == 0 || !strcmp(source->argv[i], "--")) {
+-			if (i != 0) {
+-				i++;
+-				if (i >= argc)
+-					break;
+-			}
+-
+-			if (source->argv[i] && *source->argv[i] != '-') {
+-				char *map = get_map_name(source->argv[i]);
+-				if (!map)
+-					break;
+-				if (!strcmp(map, name)) {
+-					ret = 1;
+-					free(map);
+-					break;
+-				}
+-				free(map);
+-			}
+-		}
+-	}
+-
+-	return ret;
+-}
+-
+-int dump_map(struct master *master, const char *type, const char *name)
+-{
+-	struct list_head *p, *head;
+-
+-	if (list_empty(&master->mounts)) {
+-		printf("no master map entries found\n");
+-		return 1;
+-	}
+-
+-	head = &master->mounts;
+-	p = head->next;
+-	while (p != head) {
+-		struct map_source *source;
+-		struct master_mapent *this;
+-		struct autofs_point *ap;
+-		time_t now = monotonic_time(NULL);
+-
+-		this = list_entry(p, struct master_mapent, list);
+-		p = p->next;
+-
+-		ap = this->ap;
+-
+-		/*
+-		 * Ensure we actually read indirect map entries so we can
+-		 * list them. The map reads won't read any indirect map
+-		 * entries (other than those in a file map) unless the
+-		 * browse option is set.
+-		 */
+-		if (ap->type == LKP_INDIRECT)
+-			ap->flags |= MOUNT_FLAG_GHOST;
+-
+-		/* Read the map content into the cache */
+-		if (lookup_nss_read_map(ap, NULL, now))
+-			lookup_prune_cache(ap, now);
+-		else {
+-			printf("failed to read map\n");
+-			lookup_close_lookup(ap);
+-			continue;
+-		}
+-
+-		if (!this->maps) {
+-			printf("no map sources found for %s\n", ap->path);
+-			lookup_close_lookup(ap);
+-			continue;
+-		}
+-
+-		source = this->maps;
+-		while (source) {
+-			struct map_source *instance;
+-			struct mapent *me;
+-
+-			instance = NULL;
+-			if (source->type) {
+-				if (!match_type(source->type, type)) {
+-					source = source->next;
+-					continue;
+-				}
+-				if (!match_name(source, name)) {
+-					source = source->next;
+-					continue;
+-				}
+-				instance = source;
+-			} else {
+-				struct map_source *map;
+-
+-				map = source->instance;
+-				while (map) {
+-					if (!match_type(map->type, type)) {
+-						map = map->next;
+-						continue;
+-					}
+-					if (!match_name(map, name)) {
+-						map = map->next;
+-						continue;
+-					}
+-					instance = map;
+-					break;
+-				}
+-			}
+-
+-			if (!instance) {
+-				source = source->next;
+-				lookup_close_lookup(ap);
+-				continue;
+-			}
+-
+-			me = cache_lookup_first(source->mc);
+-			if (!me)
+-				printf("no keys found in map\n");
+-			else {
+-				do {
+-					if (me->source == instance)
+-						printf("%s\t%s\n", me->key, me->mapent);
+-				} while ((me = cache_lookup_next(source->mc, me)));
+-			}
+-
+-			lookup_close_lookup(ap);
+-			return 1;
+-		}
+-		lookup_close_lookup(ap);
+-	}
+-
+-	return 0;
+-}
+-
+-int master_show_mounts(struct master *master)
+-{
+-	struct list_head *p, *head;
+-
+-	printf("\nautofs dump map information\n"
+-		 "===========================\n\n");
+-
+-	printf("global options: ");
+-	if (!global_options)
+-		printf("none configured\n");
+-	else {
+-		printf("%s\n", global_options);
+-		unsigned int append_options = defaults_get_append_options();
+-		const char *append = append_options ? "will" : "will not";
+-		printf("global options %s be appended to map entries\n", append);
+-	}
+-
+-	if (list_empty(&master->mounts)) {
+-		printf("no master map entries found\n\n");
+-		return 1;
+-	}
+-
+-	head = &master->mounts;
+-	p = head->next;
+-	while (p != head) {
+-		struct map_source *source;
+-		struct master_mapent *this;
+-		struct autofs_point *ap;
+-		time_t now = monotonic_time(NULL);
+-		unsigned int count = 0;
+-
+-		this = list_entry(p, struct master_mapent, list);
+-		p = p->next;
+-
+-		ap = this->ap;
+-
+-		printf("\nMount point: %s\n", ap->path);
+-
+-		printf("\nsource(s):\n");
+-
+-		/*
+-		 * Ensure we actually read indirect map entries so we can
+-		 * list them. The map reads won't read any indirect map
+-		 * entries (other than those in a file map) unless the
+-		 * browse option is set.
+-		 */
+-		if (ap->type == LKP_INDIRECT)
+-			ap->flags |= MOUNT_FLAG_GHOST;
+-
+-		/* Read the map content into the cache */
+-		if (lookup_nss_read_map(ap, NULL, now))
+-			lookup_prune_cache(ap, now);
+-		else {
+-			printf("  failed to read map\n\n");
+-			continue;
+-		}
+-
+-		if (!this->maps) {
+-			printf("  no map sources found\n\n");
+-			continue;
+-		}
+-
+-		source = this->maps;
+-		while (source) {
+-			struct mapent *me;
+-
+-			if (source->type)
+-				printf("\n  type: %s\n", source->type);
+-			else {
+-				printf("\n  instance type(s): ");
+-				list_source_instances(source, source->instance);
+-				printf("\n");
+-			}
+-
+-			if (source->argc >= 1) {
+-				print_map_info(source);
+-				if (count && ap->type == LKP_INDIRECT)
+-					printf("  duplicate indirect map entry"
+-					       " will be ignored at run time\n");
+-			}
+-
+-			printf("\n");
+-
+-			me = cache_lookup_first(source->mc);
+-			if (!me)
+-				printf("  no keys found in map\n");
+-			else {
+-				do {
+-					printf("  %s | %s\n", me->key, me->mapent);
+-				} while ((me = cache_lookup_next(source->mc, me)));
+-			}
+-
+-			count++;
+-
+-			source = source->next;
+-		}
+-
+-		lookup_close_lookup(ap);
+-
+-		printf("\n");
+-	}
+-
+-	return 1;
+-}
+-
+-int master_list_empty(struct master *master)
+-{
+-	int res = 0;
+-
+-	master_mutex_lock();
+-	if (list_empty(&master->mounts))
+-		res = 1;
+-	master_mutex_unlock();
+-
+-	return res;
+-}
+-
+-int master_done(struct master *master)
+-{
+-	struct list_head *head, *p;
+-	struct master_mapent *entry;
+-	int res = 0;
+-
+-	head = &master->completed;
+-	p = head->next;
+-	while (p != head) {
+-		entry = list_entry(p, struct master_mapent, join);
+-		p = p->next;
+-		list_del(&entry->join);
+-		pthread_join(entry->thid, NULL);
+-		master_free_mapent_sources(entry, 1);
+-		master_free_mapent(entry);
+-	}
+-	if (list_empty(&master->mounts))
+-		res = 1;
+-
+-	return res;
+-}
+-
+-unsigned int master_get_logopt(void)
+-{
+-	return master_list ? master_list->logopt : LOGOPT_NONE;
+-}
+-
+-int master_kill(struct master *master)
+-{
+-	if (!list_empty(&master->mounts))
+-		return 0;
+-
+-	if (master->name)
+-		free(master->name);
+-
+-	cache_release_null_cache(master);
+-	free(master);
+-
+-	return 1;
+-}
+--- autofs-5.1.4.orig/lib/master_parse.y
++++ /dev/null
+@@ -1,983 +0,0 @@
+-%{
+-/* ----------------------------------------------------------------------- *
+- *   
+- *  master_parser.y - master map buffer parser.
+- *
+- *   Copyright 2006 Ian Kent <raven@themaw.net>
+- *
+- *   This program is free software; you can redistribute it and/or modify
+- *   it under the terms of the GNU General Public License as published by
+- *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+- *   USA; either version 2 of the License, or (at your option) any later
+- *   version.
+- *   
+- *   This program is distributed in the hope that it will be useful,
+- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- *   GNU General Public License for more details.
+- *
+- * ----------------------------------------------------------------------- */
+-
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-#include <stdarg.h>
+-#include <ctype.h>
+-#include <sys/ioctl.h>
+-
+-#include "automount.h"
+-#include "master.h"
+-
+-#define MAX_ERR_LEN	512
+-
+-extern struct master *master_list;
+-
+-char **add_argv(int, char **, char *);
+-const char **copy_argv(int, const char **);
+-int free_argv(int, const char **);
+-
+-extern FILE *master_in;
+-extern char *master_text;
+-extern int master_lex(void);
+-extern int master_lineno;
+-extern void master_set_scan_buffer(const char *);
+-
+-static char *master_strdup(char *);
+-static void local_init_vars(void);
+-static void local_free_vars(void);
+-static void trim_maptype(char *);
+-static int add_multi_mapstr(void);
+-
+-static int master_error(const char *s);
+-static int master_notify(const char *s);
+-static int master_msg(const char *s);
+- 
+-static char *path;
+-static char *type;
+-static char *format;
+-static long timeout;
+-static long negative_timeout;
+-static unsigned symlnk;
+-static unsigned strictexpire;
+-static unsigned nobind;
+-static unsigned ghost;
+-extern unsigned global_selection_options;
+-static unsigned random_selection;
+-static unsigned use_weight;
+-static unsigned long mode;
+-static char **tmp_argv;
+-static int tmp_argc;
+-static char **local_argv;
+-static int local_argc;
+-
+-#define PROPAGATION_SHARED	MOUNT_FLAG_SHARED
+-#define PROPAGATION_SLAVE	MOUNT_FLAG_SLAVE
+-#define PROPAGATION_PRIVATE	MOUNT_FLAG_PRIVATE
+-#define PROPAGATION_MASK	(MOUNT_FLAG_SHARED | \
+-				 MOUNT_FLAG_SLAVE  | \
+-				 MOUNT_FLAG_PRIVATE)
+-static unsigned int propagation;
+-
+-static char errstr[MAX_ERR_LEN];
+-
+-static unsigned int verbose;
+-static unsigned int debug;
+-
+-static int lineno;
+-
+-#define YYDEBUG 0
+-
+-#ifndef YYENABLE_NLS
+-#define YYENABLE_NLS 0
+-#endif
+-#ifndef YYLTYPE_IS_TRIVIAL
+-#define YYLTYPE_IS_TRIVIAL 0
+-#endif
+-
+-#if YYDEBUG
+-static int master_fprintf(FILE *, char *, ...);
+-#undef YYFPRINTF
+-#define YYFPRINTF master_fprintf
+-#endif
+-
+-%}
+-
+-%union {
+-	char strtype[2048];
+-	int inttype;
+-	long longtype;
+-}
+-
+-%token COMMENT
+-%token MAP
+-%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
+-%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
+-%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
+-%token COLON COMMA NL DDASH
+-%type <strtype> map
+-%type <strtype> options
+-%type <strtype> dn
+-%type <strtype> dnattrs
+-%type <strtype> dnattr
+-%type <strtype> option
+-%type <strtype> daemon_option
+-%type <strtype> mount_option
+-%token <strtype> PATH
+-%token <strtype> QUOTE
+-%token <strtype> NILL
+-%token <strtype> SPACE
+-%token <strtype> EQUAL
+-%token <strtype> MULTITYPE
+-%token <strtype> MAPTYPE
+-%token <strtype> DNSERVER
+-%token <strtype> DNATTR
+-%token <strtype> DNNAME
+-%token <strtype> MAPHOSTS
+-%token <strtype> MAPNULL
+-%token <strtype> MAPXFN
+-%token <strtype> MAPNAME
+-%token <longtype> NUMBER
+-%token <longtype> OCTALNUMBER
+-%token <strtype> OPTION
+-
+-%start file
+-
+-%%
+-
+-file: {
+-		master_lineno = 0;
+-#if YYDEBUG != 0
+-		master_debug = YYDEBUG;
+-#endif
+-	} line
+-	;
+-
+-line:
+-	| PATH mapspec
+-	{
+-		path = master_strdup($1);
+-		if (!path) {
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| PATH MULTITYPE maplist
+-	{
+-		char *tmp = NULL;
+-
+-		trim_maptype($2);
+-
+-		if (path)
+-			free(path);
+-		path = master_strdup($1);
+-		if (!path) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-
+-		if ((tmp = strchr($2, ',')))
+-			*tmp++ = '\0';
+-#ifndef WITH_HESIOD
+-		/* Map type or map type parser is hesiod */
+-		if (!strcmp($2, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
+-			master_error("hesiod support not built in");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-#endif
+-		if (type)
+-			free(type);
+-		type = master_strdup($2);
+-		if (!type) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		if (tmp) {
+-			if (format)
+-				free(format);
+-			format = master_strdup(tmp);
+-			if (!format) {
+-				master_error("memory allocation error");
+-				local_free_vars();
+-				YYABORT;
+-			}
+-		}
+-	}
+-	| PATH COLON { master_notify($1); YYABORT; }
+-	| PATH OPTION { master_notify($2); YYABORT; }
+-	| PATH NILL { master_notify($2); YYABORT; }
+-	| PATH OPT_RANDOM { master_notify($1); YYABORT; }
+-	| PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
+-	| PATH OPT_DEBUG { master_notify($1); YYABORT; }
+-	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
+-	| PATH OPT_SYMLINK { master_notify($1); YYABORT; }
+-	| PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
+-	| PATH OPT_SHARED { master_notify($1); YYABORT; }
+-	| PATH OPT_SLAVE { master_notify($1); YYABORT; }
+-	| PATH OPT_PRIVATE { master_notify($1); YYABORT; }
+-	| PATH OPT_NOBIND { master_notify($1); YYABORT; }
+-	| PATH OPT_GHOST { master_notify($1); YYABORT; }
+-	| PATH OPT_NOGHOST { master_notify($1); YYABORT; }
+-	| PATH OPT_VERBOSE { master_notify($1); YYABORT; }
+-	| PATH OPT_MODE { master_notify($1); YYABORT; }
+-	| PATH { master_notify($1); YYABORT; }
+-	| QUOTE { master_notify($1); YYABORT; }
+-	| OPTION { master_notify($1); YYABORT; }
+-	| NILL { master_notify($1); YYABORT; }
+-	| COMMENT { YYABORT; }
+-	;
+-
+-mapspec: map
+-	{
+-		if (local_argv)
+-			free_argv(local_argc, (const char **) local_argv);
+-		local_argc = tmp_argc;
+-		local_argv = tmp_argv;
+-		tmp_argc = 0;
+-		tmp_argv = NULL;
+-	}
+-	| map options
+-	{
+-		if (local_argv)
+-			free_argv(local_argc, (const char **) local_argv);
+-		local_argc = tmp_argc;
+-		local_argv = tmp_argv;
+-		tmp_argc = 0;
+-		tmp_argv = NULL;
+-	}
+-	;
+-
+-maplist: map
+-	{
+-		if (!add_multi_mapstr()) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| map options
+-	{
+-		if (!add_multi_mapstr()) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| maplist DDASH map
+-	{
+-		local_argc++;
+-		local_argv = add_argv(local_argc, local_argv, "--");
+-		if (!local_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		if (!add_multi_mapstr()) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| maplist DDASH map options
+-	{
+-		local_argc++;
+-		local_argv = add_argv(local_argc, local_argv, "--");
+-		if (!local_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		if (!add_multi_mapstr()) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	;
+-
+-map:	PATH
+-	{
+-		tmp_argc++;
+-		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+-		if (!tmp_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| MAPNAME
+-	{
+-		tmp_argc++;
+-		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+-		if (!tmp_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| MAPHOSTS
+-	{
+-		if (type)
+-			free(type);
+-		type = master_strdup($1 + 1);
+-		if (!type) {
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| MAPXFN
+-	{
+-		master_notify($1);
+-		master_msg("X/Open Federated Naming service not supported");
+-		YYABORT;
+-	}
+-	| MAPNULL
+-	{
+-		if (type)
+-			free(type);
+-		type = master_strdup($1 + 1);
+-		if (!type) {
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| dnattrs
+-	{
+-		if (type)
+-			free(type);
+-		type = master_strdup("ldap");
+-		if (!type) {
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		tmp_argc++;
+-		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+-		if (!tmp_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| MAPTYPE PATH
+-	{
+-		char *tmp = NULL;
+-
+-		trim_maptype($1);
+-
+-		if ((tmp = strchr($1, ',')))
+-			*tmp++ = '\0';
+-#ifndef WITH_HESIOD
+-		/* Map type or map type parser is hesiod */
+-		if (!strcmp($1, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
+-			master_error("hesiod support not built in");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-#endif
+-		if (type)
+-			free(type);
+-		if (strcmp($1, "exec"))
+-			type = master_strdup($1);
+-		else
+-			type = master_strdup("program");
+-		if (!type) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		if (tmp) {
+-			if (format)
+-				free(format);
+-			format = master_strdup(tmp);
+-			if (!format) {
+-				master_error("memory allocation error");
+-				local_free_vars();
+-				YYABORT;
+-			}
+-		}
+-		tmp_argc++;
+-		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
+-		if (!tmp_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| MAPTYPE MAPNAME
+-	{
+-		char *tmp = NULL;
+-
+-		trim_maptype($1);
+-
+-		if ((tmp = strchr($1, ',')))
+-			*tmp++ = '\0';
+-
+-		if (type)
+-			free(type);
+-		if (strcmp($1, "exec"))
+-			type = master_strdup($1);
+-		else
+-			type = master_strdup("program");
+-		if (!type) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		if (tmp) {
+-			if (format)
+-				free(format);
+-			format = master_strdup(tmp);
+-			if (!format) {
+-				master_error("memory allocation error");
+-				local_free_vars();
+-				YYABORT;
+-			}
+-		}
+-		tmp_argc++;
+-		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
+-		if (!tmp_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	| MAPTYPE dn
+-	{
+-		char *tmp = NULL;
+-
+-		trim_maptype($1);
+-
+-		if ((tmp = strchr($1, ',')))
+-			*tmp++ = '\0';
+-
+-		if (type)
+-			free(type);
+-		if (strcmp($1, "exec"))
+-			type = master_strdup($1);
+-		else
+-			type = master_strdup("program");
+-		if (!type) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		if (tmp) {
+-			if (format)
+-				free(format);
+-			format = master_strdup(tmp);
+-			if (!format) {
+-				master_error("memory allocation error");
+-				local_free_vars();
+-				YYABORT;
+-			}
+-		}
+-		tmp_argc++;
+-		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
+-		if (!tmp_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-		/* Add back the type for lookup_ldap.c to handle ldaps */
+-		if (*tmp_argv[0]) {
+-			tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
+-			if (!tmp) {
+-				master_error("memory allocation error");
+-				local_free_vars();
+-				YYABORT;
+-			}
+-			strcpy(tmp, type);
+-			strcat(tmp, ":");
+-			strcat(tmp, tmp_argv[0]);
+-			free(tmp_argv[0]);
+-			tmp_argv[0] = tmp;
+-		}
+-	}
+-	;
+-
+-dn:	DNSERVER dnattrs
+-	{
+-		strcpy($$, $1);
+-		strcat($$, $2);
+-	}
+-	| dnattrs
+-	{
+-		strcpy($$, $1);
+-	}
+-	|
+-	{
+-		master_notify("syntax error in dn");
+-		YYABORT;
+-	}
+-	;
+-
+-dnattrs: DNATTR EQUAL DNNAME
+-	{
+-		if (strcasecmp($1, "cn") &&
+-		    strcasecmp($1, "ou") &&
+-		    strcasecmp($1, "automountMapName") &&
+-		    strcasecmp($1, "nisMapName")) {
+-			strcpy(errstr, $1);
+-			strcat(errstr, "=");
+-			strcat(errstr, $3);
+-			master_notify(errstr);
+-			YYABORT;
+-		}
+-		strcpy($$, $1);
+-		strcat($$, "=");
+-		strcat($$, $3);
+-	}
+-	| DNATTR EQUAL DNNAME COMMA dnattr
+-	{
+-		if (strcasecmp($1, "cn") &&
+-		    strcasecmp($1, "ou") &&
+-		    strcasecmp($1, "automountMapName") &&
+-		    strcasecmp($1, "nisMapName")) {
+-			strcpy(errstr, $1);
+-			strcat(errstr, "=");
+-			strcat(errstr, $3);
+-			master_notify(errstr);
+-			YYABORT;
+-		}
+-		strcpy($$, $1);
+-		strcat($$, "=");
+-		strcat($$, $3);
+-		strcat($$, ",");
+-		strcat($$, $5);
+-	}
+-	| DNNAME
+-	{
+-		/* Matches map in old style syntax ldap:server:map */
+-		strcpy($$, $1);
+-	}
+-	| DNATTR
+-	{
+-		master_notify($1);
+-		YYABORT;
+-	}
+-	;
+-
+-dnattr: DNATTR EQUAL DNNAME
+-	{
+-		if (!strcasecmp($1, "automountMapName") ||
+-		    !strcasecmp($1, "nisMapName")) {
+-			strcpy(errstr, $1);
+-			strcat(errstr, "=");
+-			strcat(errstr, $3);
+-			master_notify(errstr);
+-			YYABORT;
+-		}
+-		strcpy($$, $1);
+-		strcat($$, "=");
+-		strcat($$, $3);
+-	}
+-	| DNATTR EQUAL DNNAME COMMA dnattr
+-	{
+-		if (!strcasecmp($1, "automountMapName") ||
+-		    !strcasecmp($1, "nisMapName")) {
+-			strcpy(errstr, $1);
+-			strcat(errstr, "=");
+-			strcat(errstr, $3);
+-			master_notify(errstr);
+-			YYABORT;
+-		}
+-		strcpy($$, $1);
+-		strcat($$, "=");
+-		strcat($$, $3);
+-		strcat($$, ",");
+-		strcat($$, $5);
+-	}
+-	| DNATTR
+-	{
+-		master_notify($1);
+-		YYABORT;
+-	}
+-	| DNNAME
+-	{
+-		master_notify($1);
+-		YYABORT;
+-	}
+-	;
+-
+-options: option {}
+-	| options COMMA option {}
+-	| options option {}
+-	| options COMMA COMMA option
+-	{
+-		master_notify($1);
+-		YYABORT;
+-	}
+-	| options EQUAL
+-	{
+-		master_notify($1);
+-		YYABORT;
+-	}
+-	;
+-
+-option: daemon_option
+-	| mount_option {}
+-	| error
+-	{
+-		master_notify("bogus option");
+-		YYABORT;
+-	}
+-	;
+-
+-daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
+-	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
+-	| OPT_SYMLINK	{ symlnk = 1; }
+-	| OPT_STRICTEXPIRE { strictexpire = 1; }
+-	| OPT_SHARED	{ propagation = PROPAGATION_SHARED; }
+-	| OPT_SLAVE	{ propagation = PROPAGATION_SLAVE; }
+-	| OPT_PRIVATE	{ propagation = PROPAGATION_PRIVATE; }
+-	| OPT_NOBIND	{ nobind = 1; }
+-	| OPT_NOGHOST	{ ghost = 0; }
+-	| OPT_GHOST	{ ghost = 1; }
+-	| OPT_VERBOSE	{ verbose = 1; }
+-	| OPT_DEBUG	{ debug = 1; }
+-	| OPT_RANDOM	{ random_selection = 1; }
+-	| OPT_USE_WEIGHT { use_weight = 1; }
+-	| OPT_MODE OCTALNUMBER { mode = $2; }
+-	;
+-
+-mount_option: OPTION
+-	{
+-		tmp_argc++;
+-		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+-		if (!tmp_argv) {
+-			master_error("memory allocation error");
+-			local_free_vars();
+-			YYABORT;
+-		}
+-	}
+-	;
+-%%
+-
+-#if YYDEBUG
+-static int master_fprintf(FILE *f, char *msg, ...)
+-{
+-	va_list ap;
+-	va_start(ap, msg);
+-	vsyslog(LOG_DEBUG, msg, ap);
+-	va_end(ap);
+-	return 1;
+-}
+-#endif
+-
+-static char *master_strdup(char *str)
+-{
+-	char *tmp;
+-
+-	tmp = strdup(str);
+-	if (!tmp)
+-		master_error("memory allocation error");
+-	return tmp;
+-}
+-
+-static int master_error(const char *s)
+-{
+-	logmsg("%s while parsing map.", s);
+-	return 0;
+-}
+-
+-static int master_notify(const char *s)
+-{
+-	logmsg("syntax error in map near [ %s ]", s);
+-	return(0);
+-}
+-
+-static int master_msg(const char *s)
+-{
+-	logmsg("%s", s);
+-	return 0;
+-}
+-
+-static void local_init_vars(void)
+-{
+-	path = NULL;
+-	type = NULL;
+-	format = NULL;
+-	verbose = 0;
+-	debug = 0;
+-	timeout = -1;
+-	negative_timeout = 0;
+-	symlnk = 0;
+-	strictexpire = 0;
+-	propagation = PROPAGATION_SLAVE;
+-	nobind = 0;
+-	ghost = defaults_get_browse_mode();
+-	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
+-	use_weight = 0;
+-	mode = 0;
+-	tmp_argv = NULL;
+-	tmp_argc = 0;
+-	local_argv = NULL;
+-	local_argc = 0;
+-}
+-
+-static void local_free_vars(void)
+-{
+-	if (path)
+-		free(path);
+-
+-	if (type)
+-		free(type);
+-
+-	if (format)
+-		free(format);
+-
+-	if (local_argv) {
+-		free_argv(local_argc, (const char **) local_argv);
+-		local_argv = NULL;
+-		local_argc = 0;
+-	}
+-
+-	if (tmp_argv) {
+-		free_argv(tmp_argc, (const char **) tmp_argv);
+-		tmp_argv = NULL;
+-		tmp_argc = 0;
+-	}
+-}
+-
+-static void trim_maptype(char *type)
+-{
+-	char *tmp;
+-
+-	tmp = strchr(type, ':');
+-	if (tmp)
+-		*tmp = '\0';
+-	else {
+-		int len = strlen(type);
+-		while (len-- && isblank(type[len]))
+-			type[len] = '\0';
+-	}
+-	return;
+-}
+-
+-static int add_multi_mapstr(void)
+-{
+-	if (type) {
+-		/* If type given and format is non-null add it back */
+-		if (format) {
+-			int len = strlen(type) + strlen(format) + 2;
+-			char *tmp = realloc(type, len);
+-			if (!tmp)
+-				return 0;
+-			type = tmp;
+-			strcat(type, ",");
+-			strcat(type, format);
+-			free(format);
+-			format = NULL;
+-		}
+-
+-		local_argc++;
+-		local_argv = add_argv(local_argc, local_argv, type);
+-		if (!local_argv) {
+-			free(type);
+-			type = NULL;
+-			return 0;
+-		}
+-
+-		free(type);
+-		type = NULL;
+-	}
+-
+-	local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv);
+-	if (!local_argv) {
+-		free(type);
+-		type = NULL;
+-		return 0;
+-	}
+-	local_argc += tmp_argc;
+-
+-	tmp_argc = 0;
+-	tmp_argv = NULL;
+-
+-	return 1;
+-}
+-
+-void master_init_scan(void)
+-{
+-	lineno = 0;
+-}
+-
+-int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigned int logging, time_t age)
+-{
+-	struct master *master = master_list;
+-	struct mapent_cache *nc;
+-	struct master_mapent *entry, *new;
+-	struct map_source *source;
+-	unsigned int logopt = logging;
+-	unsigned int m_logopt = master->logopt;
+-	size_t mp_len;
+-	int ret;
+-
+-	local_init_vars();
+-
+-	lineno++;
+-
+-	master_set_scan_buffer(buffer);
+-
+-	ret = master_parse();
+-	if (ret != 0) {
+-		local_free_vars();
+-		return 0;
+-	}
+-
+-	mp_len = strlen(path);
+-	while (mp_len && path[--mp_len] == '/')
+-		path[mp_len] = 0;
+-
+-	nc = master->nc;
+-
+-	/* Add null map entries to the null map cache */
+-	if (type && !strcmp(type, "null")) {
+-		cache_update(nc, NULL, path, NULL, lineno);
+-		local_free_vars();
+-		return 1;
+-	}
+-
+-	/* Ignore all subsequent matching nulled entries */
+-	if (cache_lookup_distinct(nc, path)) {
+-		local_free_vars();
+-		return 1;
+-	}
+-
+-	if (debug || verbose) {
+-		logopt = (debug ? LOGOPT_DEBUG : 0);
+-		logopt |= (verbose ? LOGOPT_VERBOSE : 0);
+-	}
+-
+-	new = NULL;
+-	entry = master_find_mapent(master, path);
+-	if (!entry) {
+-		new = master_new_mapent(master, path, age);
+-		if (!new) {
+-			local_free_vars();
+-			return 0;
+-		}
+-		entry = new;
+-	} else {
+-		if (entry->age && entry->age == age) {
+-			if (strcmp(path, "/-")) {
+-				info(m_logopt,
+-				    "ignoring duplicate indirect mount %s",
+-				     path);
+-				local_free_vars();
+-				return 0;
+-			}
+-		}
+-	}
+-
+-	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();
+-		unsigned int flags = conf_amd_get_flags(path);
+-
+-		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
+-			logopt = LOGOPT_DEBUG;
+-		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
+-			logopt = LOGOPT_VERBOSE;
+-
+-		/* It isn't possible to provide the fullybrowsable amd
+-		 * browsing functionality within the autofs framework.
+-		 * This flag will not be set if browsable_dirs = full
+-		 * in the configuration or fullybrowsable is present as
+-		 * an option.
+-		 */
+-		if (flags & CONF_BROWSABLE_DIRS)
+-			ghost = 1;
+-	}
+-
+-	if (!entry->ap) {
+-		ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
+-		if (!ret) {
+-			error(m_logopt, "failed to add autofs_point");
+-			if (new)
+-				master_free_mapent(new);
+-			local_free_vars();
+-			return 0;
+-		}
+-	}
+-	entry->ap->flags &= ~(PROPAGATION_MASK);
+-	entry->ap->flags |= propagation;
+-
+-	if (random_selection)
+-		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
+-	if (use_weight)
+-		entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
+-	if (symlnk)
+-		entry->ap->flags |= MOUNT_FLAG_SYMLINK;
+-	if (strictexpire)
+-		entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
+-	if (negative_timeout)
+-		entry->ap->negative_timeout = negative_timeout;
+-	if (mode && mode < LONG_MAX)
+-		entry->ap->mode = mode;
+-
+-	if (timeout < 0) {
+-		/*
+-		 * If no timeout is given get the timout from the
+-		 * autofs point, or the first map, or the config
+-		 * for amd maps.
+-		 */
+-		if (format && !strcmp(format, "amd"))
+-			timeout = conf_amd_get_dismount_interval(path);
+-		else
+-			timeout = get_exp_timeout(entry->ap, entry->maps);
+-	}
+-
+-	if (format && !strcmp(format, "amd")) {
+-		char *opts = conf_amd_get_map_options(path);
+-		if (opts) {
+-			/* autofs uses the equivalent of cache:=inc,sync
+-			 * (except for file maps which use cache:=all,sync)
+-			 * but if the map is large then it may be necessary
+-			 * to read the whole map at startup even if browsing
+-			 * is is not enabled, so look for cache:=all in the
+-			 * map_options configuration entry.
+-			 */
+-			if (strstr(opts, "cache:=all"))
+-				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
+-			free(opts);
+-		}
+-	}
+-
+-/*
+-	source = master_find_map_source(entry, type, format,
+-					local_argc, (const char **) local_argv); 
+-	if (!source)
+-		source = master_add_map_source(entry, type, format, age, 
+-					local_argc, (const char **) local_argv);
+-	else
+-		source->age = age;
+-*/
+-	source = master_add_map_source(entry, type, format, age, 
+-					local_argc, (const char **) local_argv);
+-	if (!source) {
+-		error(m_logopt, "failed to add source");
+-		if (new)
+-			master_free_mapent(new);
+-		local_free_vars();
+-		return 0;
+-	}
+-	set_exp_timeout(entry->ap, source, timeout);
+-	source->master_line = lineno;
+-
+-	entry->age = age;
+-	entry->current = NULL;
+-
+-	if (new)
+-		master_add_mapent(master, entry);
+-
+-	local_free_vars();
+-
+-	return 1;
+-}
+-
+--- autofs-5.1.4.orig/lib/master_tok.l
++++ /dev/null
+@@ -1,504 +0,0 @@
+-%{
+-/* ----------------------------------------------------------------------- *
+- *   
+- *  master_tok.l - master map tokenizer.
+- *
+- *   Copyright 2006 Ian Kent <raven@themaw.net>
+- *
+- *   This program is free software; you can redistribute it and/or modify
+- *   it under the terms of the GNU General Public License as published by
+- *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+- *   USA; either version 2 of the License, or (at your option) any later
+- *   version.
+- *   
+- *   This program is distributed in the hope that it will be useful,
+- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- *   GNU General Public License for more details.
+- *
+- * ----------------------------------------------------------------------- */
+-
+-#ifdef ECHO
+-# undef ECHO
+-#endif /* ECHO */
+-static void master_echo(void);	/* forward definition */
+-#define ECHO master_echo()
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <ctype.h>
+-#include "master_parse.tab.h"
+-
+-/*
+- * There are some things that need to be defined only if useing GNU flex.
+- * These must not be defined if using standard lex
+- */
+-#ifdef FLEX_SCANNER
+-int master_lineno;
+-#endif
+-
+-int master_lex(void);
+-int master_wrap(void);
+-
+-/* no need for yywrap() */
+-#define YY_SKIP_YYWRAP
+-
+-#ifndef YY_STACK_USED
+-#define YY_STACK_USED 0
+-#endif
+-#ifndef YY_ALWAYS_INTERACTIVE
+-#define YY_ALWAYS_INTERACTIVE 0
+-#endif
+-#ifndef YY_NEVER_INTERACTIVE
+-#define YY_NEVER_INTERACTIVE 0
+-#endif
+-#ifndef YY_MAIN
+-#define YY_MAIN 0
+-#endif
+-
+-void master_set_scan_buffer(const char *);
+-const char *line = NULL;
+-
+-#ifdef FLEX_SCANNER
+-const char *line_pos = NULL;
+-const char *line_lim = NULL;
+-int my_yyinput(char *, int);
+-
+-#undef YY_INPUT
+-#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
+-#else
+-#undef input
+-#undef unput
+-#define input()  (*(char *) line++)
+-#define unput(c) (*(char *) --line = c)
+-#endif
+-
+-#define BUFF_LEN	1024
+-char buff[BUFF_LEN];
+-char *bptr;
+-char *optr = buff;
+-unsigned int tlen;
+-
+-%}
+-
+-%option nounput
+-
+-%x PATHSTR MAPSTR DNSTR OPTSTR OCTAL
+-
+-WS		[[:blank:]]+
+-OPTWS		[[:blank:]]*
+-NL		\r?\n
+-CONT		\\\n{OPTWS}
+-
+-OPTIONSTR	([\-]?([[:alpha:]_]([[:alnum:]_\-])*(=(\"?([[:alnum:]_\-\:\.])+\"?))?)+)
+-MACROSTR	(-D{OPTWS}([[:alpha:]_]([[:alnum:]_\-\.])*)=([[:alnum:]_\-\.])+)
+-SLASHIFYSTR	(--(no-)?slashify-colons)
+-NUMBER		[0-9]+
+-OCTALNUMBER	[0-7]+
+-
+-DNSERVSTR1	([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
+-DNSERVSTR2	(\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
+-DNSERVSTR3	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
+-DNSERVSTR4	(\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
+-DNSERVSTR5	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
+-DNSERVSTR6	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
+-DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
+-
+-AT_CN		([cC][[nN])
+-AT_NMN		([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
+-AT_AMN		([aA][uU][tT][oO][mM][oO][uU][nN][tT][Mm][aA][pP][Nn][aA][mM][eE])
+-AT_OU		([oO][[uU])
+-AT_DC		([dD][[cC])
+-AT_O		([oO])
+-AT_C		([cC])
+-AT_L		([lL])
+-DNATTRSTR	({AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}|{AT_L})
+-DNNAMESTR1	([[:alnum:]_.\- ]+)
+-DNNAMESTR2	([[:alnum:]_.\-]+)
+-
+-INTMAP		(-hosts|-null)
+-MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
+-MULTISEP	([\-]{2}[[:blank:]]+)
+-MTYPE		((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
+-
+-
+-OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
+-OPTNTOUT	(-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
+-
+-MODE		(--mode{OPTWS}|--mode{OPTWS}={OPTWS})
+-
+-%%
+-
+-<INITIAL>{
+-	{NL} | 
+-	\x00 {
+-		if (optr != buff) {
+-			*optr = '\0';
+-			strcpy(master_lval.strtype, buff);
+-			return NILL;
+-		}
+-	}
+-
+-	#.*  { return COMMENT; }
+-
+-	"/" {
+-		if (optr != buff) {
+-			*optr = '\0';
+-			strcpy(master_lval.strtype, buff);
+-			return NILL;
+-		}
+-		BEGIN(PATHSTR);
+-		bptr = buff;
+-		yyless(0);
+-	}
+-
+-	.    { *optr++ = *master_text; }
+-}
+-
+-<PATHSTR>{
+-	\x00 {
+-		BEGIN(INITIAL);
+-		*bptr++ = *master_text;
+-		strcpy(master_lval.strtype, buff);
+-		return NILL;
+-	}
+-
+-	\\.  { *bptr++ = *(master_text + 1); }
+-	\"   {
+-		BEGIN(INITIAL);
+-		*bptr++ = *master_text;
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		return QUOTE;
+-	}
+-
+-	{WS} {
+-		BEGIN(MAPSTR);
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		bptr = buff;
+-		memset(buff, 0, BUFF_LEN);
+-		return(PATH);
+-	}
+-
+-	<<EOF>> {
+-		BEGIN(INITIAL);
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		return(PATH);
+-	}
+-
+-	{NL} {
+-		BEGIN(INITIAL);
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		return PATH;
+-	}
+-
+-	.    { *bptr++ = *master_text; }
+-}
+-
+-<MAPSTR>{
+-	{OPTWS}\\\n{OPTWS} {}
+-
+-	{MULTI} {
+-		tlen = master_leng - 1;
+-		if (bptr != buff && isblank(master_text[tlen])) {
+-			/*
+-			 * We can't handle unescaped white space in map names
+-			 * so just eat the white space. We always have the
+-			 * "multi" at the beginning of the string so the while
+-			 * will not fall off the end.
+-			 */
+-			while (isblank(master_text[tlen - 1]))
+-				tlen--;
+-			strncat(buff, master_text, tlen);
+-			bptr += tlen;
+-			yyless(tlen);
+-		} else {
+-			strcpy(master_lval.strtype, master_text);
+-			return(MULTITYPE);
+-		}
+-	}
+-
+-	{MTYPE} |
+-	{MTYPE}/{DNSERVERSTR}{DNATTRSTR}= |
+-	{MTYPE}/{DNATTRSTR}= {
+-		tlen = master_leng - 1;
+-		if (bptr != buff && isblank(master_text[tlen])) {
+-			/*
+-			 * We can't handle unescaped white space in map names
+-			 * so just eat the white space. We always have the
+-			 * maptype keyword at the beginning of the string so
+-			 * the while will not fall off the end.
+-			 */
+-			while (isblank(master_text[tlen - 1]))
+-				tlen--;
+-			strncat(buff, master_text, tlen);
+-			bptr += tlen;
+-			yyless(tlen);
+-		} else {
+-			strcpy(master_lval.strtype, master_text);
+-			return(MAPTYPE);
+-		}
+-	}
+-
+-	{MULTISEP} { return(DDASH); }
+-
+-	":"	{ return(COLON); }
+-
+-	"-hosts" {
+-		BEGIN(OPTSTR);
+-		strcpy(master_lval.strtype, master_text);
+-		return MAPHOSTS;
+-	}
+-
+-	"-null" {
+-		BEGIN(OPTSTR);
+-		strcpy(master_lval.strtype, master_text);
+-		return MAPNULL;
+-	}
+-
+-	"-xfn" {
+-		/*
+-		 * The X/Open Federated Naming service isn't supported
+-		 * and the parser will call YYABORT() when it sees the
+-		 * MAPXFN token so we must set the start state to the
+-		 * INITIAL state here for the next yylex() call.
+-		 */
+-		BEGIN(INITIAL);
+-		strcpy(master_lval.strtype, master_text);
+-		return MAPXFN;
+-	}
+-
+-	"//" {
+-		BEGIN(DNSTR);
+-		yyless(0);
+-	}
+-
+-	{DNSERVERSTR}{DNATTRSTR}= {
+-		BEGIN(DNSTR);
+-		yyless(0);
+-	}
+-
+-	{DNATTRSTR}= {
+-		BEGIN(DNSTR);
+-		yyless(0);
+-	}
+-
+-	{OPTWS}/{NL} {
+-		BEGIN(INITIAL);
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		bptr = buff;
+-		return(MAPNAME);
+-	}
+-
+-	\\. { *bptr++ = *(master_text + 1); }
+-
+-	{WS} {
+-		BEGIN(OPTSTR);
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		bptr = buff;
+-		return(MAPNAME);
+-	}
+-
+-	{NL} |
+-	\x00 {
+-		BEGIN(INITIAL);
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		return(MAPNAME);
+-	}
+-
+-	<<EOF>> {
+-		BEGIN(INITIAL);
+-		*bptr = '\0';
+-		strcpy(master_lval.strtype, buff);
+-		return(MAPNAME);
+-	}
+-
+-	.	{ *bptr++ = *master_text; }
+-}
+-
+-<DNSTR>{
+-	{OPTWS}\\\n{OPTWS} {}
+-
+-	{DNSERVERSTR} {
+-		strcpy(master_lval.strtype, master_text);
+-		return DNSERVER;
+-	}
+-
+-	{DNATTRSTR}/"=" {
+-		strcpy(master_lval.strtype, master_text);
+-		return DNATTR;
+-	}
+-
+-	"=" {
+-		return EQUAL;
+-	}
+-
+-	{DNNAMESTR1}/","{DNATTRSTR}"=" {
+-		strcpy(master_lval.strtype, master_text);
+-		return DNNAME;
+-	}
+-
+-	{DNNAMESTR2} {
+-		strcpy(master_lval.strtype, master_text);
+-		return DNNAME;
+-	}
+-
+-	{OPTWS}","{OPTWS} {
+-		return COMMA;
+-	}
+-
+-	{WS}"=" |
+-	"="{WS} {
+-		BEGIN(INITIAL);
+-		strcpy(master_lval.strtype, master_text);
+-		return SPACE;
+-	}
+-
+-	{WS}    { BEGIN(OPTSTR); }
+-
+-	{NL} |
+-	\x00	{ BEGIN(INITIAL); }
+-
+-	<<EOF>> { BEGIN(INITIAL); }
+-}
+-
+-<OPTSTR>{
+-	{OPTWS}\\\n{OPTWS} {}
+-
+-	{MULTISEP} {
+-		BEGIN(MAPSTR);
+-		return(DDASH);
+-	}
+-
+-	{OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
+-
+-	{OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
+-
+-	{NUMBER} {
+-		master_lval.longtype = atol(master_text);
+-		return(NUMBER);
+-	}
+-
+-	-?symlink		{ return(OPT_SYMLINK); }
+-	-?nobind		{ return(OPT_NOBIND); }
+-	-?nobrowse		{ return(OPT_NOGHOST); }
+-	-?shared		{ return(OPT_SHARED); }
+-	-?slave			{ return(OPT_SLAVE); }
+-	-?private		{ return(OPT_PRIVATE); }
+-	-?strictexpire		{ return(OPT_STRICTEXPIRE); }
+-	-g|--ghost|-?browse	{ return(OPT_GHOST); }
+-	-v|--verbose		{ return(OPT_VERBOSE); }
+-	-d|--debug		{ return(OPT_DEBUG); }
+-	-w|--use-weight-only	{ return(OPT_USE_WEIGHT); }
+-	-r|--random-multimount-selection { return(OPT_RANDOM); }
+-
+-	{MODE}/{OCTALNUMBER} {
+-		BEGIN(OCTAL);
+-		return(OPT_MODE);
+-	}
+-
+-	{OPTWS}","{OPTWS}	{ return(COMMA); }
+-
+-	{OPTWS} {}
+-
+-	{SLASHIFYSTR} {
+-		strcpy(master_lval.strtype, master_text);
+-		return(OPTION);
+-	}
+-
+-	{MACROSTR} {
+-		strcpy(master_lval.strtype, master_text);
+-		return(OPTION);
+-	}
+-
+-	{OPTIONSTR} {
+-		strcpy(master_lval.strtype, master_text);
+-		return(OPTION);
+-	}
+-
+-	"="	{
+-		strcpy(master_lval.strtype, master_text);
+-		return(EQUAL);
+-	}
+-
+-	{WS}	{}
+-	{NL} |
+-	\x00 { BEGIN(INITIAL); }
+-
+-	<<EOF>> { BEGIN(INITIAL); }
+-}
+-
+-<OCTAL>{
+-	{OCTALNUMBER} {
+-		master_lval.longtype = strtoul(master_text, NULL, 8);
+-		return(OCTALNUMBER);
+-	}
+-
+-	. { BEGIN(OPTSTR); yyless(0); }
+-}
+-
+-%%
+-
+-#include "automount.h"
+-
+-int master_wrap(void)
+-{
+-	return 1;
+-}
+-
+-static void master_echo(void)
+-{
+-	logmsg("%s", master_text);
+-	return;
+-}
+-
+-#ifdef FLEX_SCANNER
+-
+-void master_set_scan_buffer(const char *buffer)
+-{
+-	memset(buff, 0, sizeof(buff));
+-	optr = buff;
+-
+-	YY_FLUSH_BUFFER;
+-
+-	line = buffer;
+-	line_pos = &line[0];
+-	/*
+-	 * Ensure buffer is 1 greater than string and is zeroed before
+-	 * the parse so we can fit the extra NULL which allows us to
+-	 * explicitly match an end of line within the buffer (ie. the
+-	 * need for 2 NULLS when parsing in memeory buffers).
+-	 */
+-	line_lim = line + strlen(buffer) + 1;
+-}
+-
+-#ifndef min
+-#define min(a,b) (((a) < (b)) ? (a) : (b))
+-#endif
+-
+-int my_yyinput(char *buffer, int max_size)
+-{
+-	int n = min(max_size, line_lim - line_pos);
+-
+-	if (n > 0) {
+-		memcpy(buffer, line_pos, n);
+-		line_pos += n;
+-	}
+-	return n;
+-}
+-
+-#else
+-
+-void master_set_scan_buffer(const char *buffer)
+-{
+-	line = buffer;
+-}
+-
+-#endif
diff --git a/SOURCES/autofs-5.1.6-move-submount-check-into-conditional_alarm_add.patch b/SOURCES/autofs-5.1.6-move-submount-check-into-conditional_alarm_add.patch
new file mode 100644
index 0000000..eff3fd1
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-move-submount-check-into-conditional_alarm_add.patch
@@ -0,0 +1,201 @@
+autofs-5.1.6 - move submount check into conditional_alarm_add()
+
+From: Ian Kent <raven@themaw.net>
+
+The expire of submounts is driven by the top level autofs mount in the
+mount tree so an expire alarm doesn't need to set if the autofs point
+is a submount.
+
+Take that check into conditional_alarm_add().
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    6 ++----
+ daemon/direct.c    |    3 +--
+ daemon/indirect.c  |    3 +--
+ daemon/state.c     |   26 +++++++++-----------------
+ lib/alarm.c        |    2 ++
+ lib/mounts.c       |    6 ++----
+ 7 files changed, 18 insertions(+), 29 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -132,6 +132,7 @@ xx/xx/2018 autofs-5.1.5
+ - use struct mnt_list mounted list for expire.
+ - remove unused function tree_get_mnt_list().
+ - only add expre alarm for active mounts.
++- move submount check into conditional_alarm_add().
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -1843,8 +1843,7 @@ int handle_mounts_exit(struct autofs_poi
+ 	}
+ 
+ 	if (ap->state != ST_SHUTDOWN) {
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 		/* Return to ST_READY is done immediately */
+ 		st_add_task(ap, ST_READY);
+ 		if (ap->submount)
+@@ -1888,8 +1887,7 @@ int handle_mounts_exit(struct autofs_poi
+ 
+ 	/* Failed shutdown returns to ready */
+ 	warn(ap->logopt, "can't shutdown: filesystem %s still busy", ap->path);
+-	if (!ap->submount)
+-		conditional_alarm_add(ap, ap->exp_runfreq);
++	conditional_alarm_add(ap, ap->exp_runfreq);
+ 	/* Return to ST_READY is done immediately */
+ 	st_add_task(ap, ST_READY);
+ 	if (ap->submount)
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -1246,8 +1246,7 @@ static void *do_mount_direct(void *arg)
+ 
+ 		mnts_set_mounted_mount(ap, mt.name);
+ 
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+ 		/* TODO: get mount return status from lookup_nss_mount */
+ 		ops->send_fail(ap->logopt,
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -754,8 +754,7 @@ static void *do_mount_indirect(void *arg
+ 
+ 		mnts_set_mounted_mount(ap, mt.name);
+ 
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+ 		/* TODO: get mount return status from lookup_nss_mount */
+ 		ops->send_fail(ap->logopt,
+--- autofs-5.1.4.orig/daemon/state.c
++++ autofs-5.1.4/daemon/state.c
+@@ -154,7 +154,7 @@ void expire_cleanup(void *arg)
+ 			} else if (ap->submount > 1)
+ 				ap->submount = 1;
+ 
+-			if (ap->state == ST_EXPIRE && !ap->submount)
++			if (ap->state == ST_EXPIRE)
+ 				conditional_alarm_add(ap, ap->exp_runfreq);
+ 
+ 			/* FALLTHROUGH */
+@@ -172,8 +172,7 @@ void expire_cleanup(void *arg)
+ 			rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
+ 			if (!rv && !idle && !ap->shutdown) {
+ 				next = ST_READY;
+-				if (!ap->submount)
+-					conditional_alarm_add(ap, ap->exp_runfreq);
++				conditional_alarm_add(ap, ap->exp_runfreq);
+ 				break;
+ 			}
+ 
+@@ -186,8 +185,7 @@ void expire_cleanup(void *arg)
+ 
+ 			/* Failed shutdown returns to ready */
+ 			warn(ap->logopt, "filesystem %s still busy", ap->path);
+-			if (!ap->submount)
+-				conditional_alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 			next = ST_READY;
+ 			break;
+ #endif
+@@ -577,8 +575,7 @@ static unsigned int st_readmap(struct au
+ 		error(ap->logopt, "failed to malloc readmap cond struct");
+ 		/* It didn't work: return to ready */
+ 		st_ready(ap);
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 		return 0;
+ 	}
+ 
+@@ -604,8 +601,7 @@ static unsigned int st_readmap(struct au
+ 		free(ra);
+ 		/* It didn't work: return to ready */
+ 		st_ready(ap);
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 		return 0;
+ 	}
+ 	ap->readmap_thread = thid;
+@@ -640,8 +636,7 @@ static unsigned int st_prepare_shutdown(
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+ 		/* It didn't work: return to ready */
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+@@ -666,8 +661,7 @@ static unsigned int st_force_shutdown(st
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+ 		/* It didn't work: return to ready */
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+@@ -699,8 +693,7 @@ static unsigned int st_prune(struct auto
+ 	switch (expire_proc(ap, AUTOFS_EXP_IMMEDIATE)) {
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+@@ -720,8 +713,7 @@ static unsigned int st_expire(struct aut
+ 	switch (expire_proc(ap, AUTOFS_EXP_NORMAL)) {
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+--- autofs-5.1.4.orig/lib/alarm.c
++++ autofs-5.1.4/lib/alarm.c
+@@ -187,6 +187,8 @@ int conditional_alarm_add(struct autofs_
+ {
+ 	int status;
+ 
++	if (ap->submount)
++		return 1;
+ 	if (!mnts_has_mounted_mounts(ap))
+ 		return 1;
+ 
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1921,8 +1921,7 @@ static int do_remount_direct(struct auto
+ 
+ 		info(ap->logopt, "re-connected to %s", path);
+ 
+-		if (!ap->submount)
+-			conditional_alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+ 		status = REMOUNT_FAIL;
+ 		info(ap->logopt, "failed to re-connect %s", path);
+@@ -1997,8 +1996,7 @@ static int do_remount_indirect(struct au
+ 
+ 			info(ap->logopt, "re-connected to %s", buf);
+ 
+-			if (!ap->submount)
+-				conditional_alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		} else {
+ 			status = REMOUNT_FAIL;
+ 			info(ap->logopt, "failed to re-connect %s", buf);
diff --git a/SOURCES/autofs-5.1.6-only-add-expire-alarm-for-active-mounts.patch b/SOURCES/autofs-5.1.6-only-add-expire-alarm-for-active-mounts.patch
new file mode 100644
index 0000000..c7ecc32
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-only-add-expire-alarm-for-active-mounts.patch
@@ -0,0 +1,334 @@
+autofs-5.1.6 - only add expire alarm for active mounts
+
+From: Ian Kent <raven@themaw.net>
+
+There's no need to add expire alarms for mount points that have no
+expirable mounts.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ daemon/automount.c  |    9 +-------
+ daemon/direct.c     |    3 ++
+ daemon/indirect.c   |    3 ++
+ daemon/state.c      |   25 +++++++++++-----------
+ include/automount.h |    1 
+ include/mounts.h    |    1 
+ lib/alarm.c         |   57 ++++++++++++++++++++++++++++++++++++++++++++++++----
+ lib/mounts.c        |   19 +++++++++++++++++
+ 9 files changed, 96 insertions(+), 23 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -131,6 +131,7 @@ xx/xx/2018 autofs-5.1.5
+ - use struct mnt_list to track mounted mounts.
+ - use struct mnt_list mounted list for expire.
+ - remove unused function tree_get_mnt_list().
++- only add expre alarm for active mounts.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -1844,7 +1844,7 @@ int handle_mounts_exit(struct autofs_poi
+ 
+ 	if (ap->state != ST_SHUTDOWN) {
+ 		if (!ap->submount)
+-			alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		/* Return to ST_READY is done immediately */
+ 		st_add_task(ap, ST_READY);
+ 		if (ap->submount)
+@@ -1889,7 +1889,7 @@ int handle_mounts_exit(struct autofs_poi
+ 	/* Failed shutdown returns to ready */
+ 	warn(ap->logopt, "can't shutdown: filesystem %s still busy", ap->path);
+ 	if (!ap->submount)
+-		alarm_add(ap, ap->exp_runfreq);
++		conditional_alarm_add(ap, ap->exp_runfreq);
+ 	/* Return to ST_READY is done immediately */
+ 	st_add_task(ap, ST_READY);
+ 	if (ap->submount)
+@@ -1952,11 +1952,6 @@ void *handle_mounts(void *arg)
+ 	suc->status = 0;
+ 	pthread_cleanup_pop(1);
+ 
+-	/* We often start several automounters at the same time.  Add some
+-	   randomness so we don't all expire at the same time. */
+-	if (!ap->submount && ap->exp_runfreq)
+-		alarm_add(ap, ap->exp_runfreq + rand() % ap->exp_runfreq);
+-
+ 	pthread_setcancelstate(cancel_state, NULL);
+ 
+ 	while (1) {
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -1245,6 +1245,9 @@ static void *do_mount_direct(void *arg)
+ 		info(ap->logopt, "mounted %s", mt.name);
+ 
+ 		mnts_set_mounted_mount(ap, mt.name);
++
++		if (!ap->submount)
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+ 		/* TODO: get mount return status from lookup_nss_mount */
+ 		ops->send_fail(ap->logopt,
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -753,6 +753,9 @@ static void *do_mount_indirect(void *arg
+ 		info(ap->logopt, "mounted %s", buf);
+ 
+ 		mnts_set_mounted_mount(ap, mt.name);
++
++		if (!ap->submount)
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+ 		/* TODO: get mount return status from lookup_nss_mount */
+ 		ops->send_fail(ap->logopt,
+--- autofs-5.1.4.orig/daemon/state.c
++++ autofs-5.1.4/daemon/state.c
+@@ -155,7 +155,7 @@ void expire_cleanup(void *arg)
+ 				ap->submount = 1;
+ 
+ 			if (ap->state == ST_EXPIRE && !ap->submount)
+-				alarm_add(ap, ap->exp_runfreq);
++				conditional_alarm_add(ap, ap->exp_runfreq);
+ 
+ 			/* FALLTHROUGH */
+ 
+@@ -173,7 +173,7 @@ void expire_cleanup(void *arg)
+ 			if (!rv && !idle && !ap->shutdown) {
+ 				next = ST_READY;
+ 				if (!ap->submount)
+-					alarm_add(ap, ap->exp_runfreq);
++					conditional_alarm_add(ap, ap->exp_runfreq);
+ 				break;
+ 			}
+ 
+@@ -187,7 +187,7 @@ void expire_cleanup(void *arg)
+ 			/* Failed shutdown returns to ready */
+ 			warn(ap->logopt, "filesystem %s still busy", ap->path);
+ 			if (!ap->submount)
+-				alarm_add(ap, ap->exp_runfreq);
++				conditional_alarm_add(ap, ap->exp_runfreq);
+ 			next = ST_READY;
+ 			break;
+ #endif
+@@ -522,9 +522,10 @@ static void *do_readmap(void *arg)
+ 		 * alarm will have been added. So add it here if there are
+ 		 * now map entries.
+ 		 */
+-		if (append_alarm && ap->exp_runfreq)
+-			alarm_add(ap, ap->exp_runfreq +
+-				  rand() % ap->exp_runfreq);
++		if (append_alarm && ap->exp_runfreq) {
++			time_t seconds = ap->exp_runfreq + rand() % ap->exp_runfreq;
++			conditional_alarm_add(ap, seconds);
++		}
+ 
+ 		pthread_cleanup_pop(1);
+ 		pthread_cleanup_pop(1);
+@@ -577,7 +578,7 @@ static unsigned int st_readmap(struct au
+ 		/* It didn't work: return to ready */
+ 		st_ready(ap);
+ 		if (!ap->submount)
+-			alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		return 0;
+ 	}
+ 
+@@ -604,7 +605,7 @@ static unsigned int st_readmap(struct au
+ 		/* It didn't work: return to ready */
+ 		st_ready(ap);
+ 		if (!ap->submount)
+-			alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		return 0;
+ 	}
+ 	ap->readmap_thread = thid;
+@@ -640,7 +641,7 @@ static unsigned int st_prepare_shutdown(
+ 	case EXP_PARTIAL:
+ 		/* It didn't work: return to ready */
+ 		if (!ap->submount)
+-			alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+@@ -666,7 +667,7 @@ static unsigned int st_force_shutdown(st
+ 	case EXP_PARTIAL:
+ 		/* It didn't work: return to ready */
+ 		if (!ap->submount)
+-			alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+@@ -699,7 +700,7 @@ static unsigned int st_prune(struct auto
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+ 		if (!ap->submount)
+-			alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+@@ -720,7 +721,7 @@ static unsigned int st_expire(struct aut
+ 	case EXP_ERROR:
+ 	case EXP_PARTIAL:
+ 		if (!ap->submount)
+-			alarm_add(ap, ap->exp_runfreq);
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 		st_ready(ap);
+ 		return 0;
+ 
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -637,6 +637,7 @@ static inline time_t monotonic_time(time
+ /* Expire alarm handling routines */
+ int alarm_start_handler(void);
+ int alarm_add(struct autofs_point *ap, time_t seconds);
++int conditional_alarm_add(struct autofs_point *ap, time_t seconds);
+ void alarm_delete(struct autofs_point *ap);
+ 
+ #endif
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -125,6 +125,7 @@ void mnts_remove_amdmount(const char *mp
+ struct mnt_list *mnts_add_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ void mnts_remove_mount(const char *mp, unsigned int flags);
+ struct mnt_list *get_mnt_list(const char *path, int include);
++unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name);
+--- autofs-5.1.4.orig/lib/alarm.c
++++ autofs-5.1.4/lib/alarm.c
+@@ -41,7 +41,7 @@ do { \
+ } while (0)
+ 
+ /* Insert alarm entry on ordered list. */
+-int alarm_add(struct autofs_point *ap, time_t seconds)
++int __alarm_add(struct autofs_point *ap, time_t seconds)
+ {
+ 	struct list_head *head;
+ 	struct list_head *p;
+@@ -62,8 +62,6 @@ int alarm_add(struct autofs_point *ap, t
+ 	new->cancel = 0;
+ 	new->time = now + seconds;
+ 
+-	alarm_lock();
+-
+ 	head = &alarms;
+ 
+ 	/* Check if we have a pending alarm */
+@@ -97,9 +95,42 @@ int alarm_add(struct autofs_point *ap, t
+ 			fatal(status);
+ 	}
+ 
++	return 1;
++}
++
++int alarm_add(struct autofs_point *ap, time_t seconds)
++{
++	int status;
++
++	alarm_lock();
++	status = __alarm_add(ap, seconds);
+ 	alarm_unlock();
+ 
+-	return 1;
++	return status;
++}
++
++static int __alarm_exists(struct autofs_point *ap)
++{
++	struct list_head *head;
++	struct list_head *p;
++
++	head = &alarms;
++
++	if (list_empty(head))
++		return 0;
++
++	p = head->next;
++	while (p != head) {
++		struct alarm *this;
++
++		this = list_entry(p, struct alarm, list);
++		p = p->next;
++
++		if (ap == this->ap)
++			return 1;
++	}
++
++	return 0;
+ }
+ 
+ void alarm_delete(struct autofs_point *ap)
+@@ -152,6 +183,24 @@ void alarm_delete(struct autofs_point *a
+ 	return;
+ }
+ 
++int conditional_alarm_add(struct autofs_point *ap, time_t seconds)
++{
++	int status;
++
++	if (!mnts_has_mounted_mounts(ap))
++		return 1;
++
++	alarm_lock();
++	if (__alarm_exists(ap)) {
++		alarm_unlock();
++		return 1;
++	}
++	status = __alarm_add(ap, seconds);
++	alarm_unlock();
++
++	return status;
++}
++
+ static void *alarm_handler(void *arg)
+ {
+ 	struct list_head *head;
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1208,6 +1208,19 @@ void mnts_set_mounted_mount(struct autof
+ 	}
+ }
+ 
++unsigned int mnts_has_mounted_mounts(struct autofs_point *ap)
++{
++	unsigned int has_mounted_mounts = 0;
++
++	mnts_hash_mutex_lock();
++	if (list_empty(&ap->mounts))
++		goto done;
++	has_mounted_mounts = 1;
++done:
++	mnts_hash_mutex_unlock();
++	return has_mounted_mounts;
++}
++
+ struct node {
+ 	struct mnt_list *mnt;
+ 	struct node *left;
+@@ -1907,6 +1920,9 @@ static int do_remount_direct(struct auto
+ 		mnts_set_mounted_mount(ap, path);
+ 
+ 		info(ap->logopt, "re-connected to %s", path);
++
++		if (!ap->submount)
++			conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+ 		status = REMOUNT_FAIL;
+ 		info(ap->logopt, "failed to re-connect %s", path);
+@@ -1980,6 +1996,9 @@ static int do_remount_indirect(struct au
+ 			mnts_set_mounted_mount(ap, buf);
+ 
+ 			info(ap->logopt, "re-connected to %s", buf);
++
++			if (!ap->submount)
++				conditional_alarm_add(ap, ap->exp_runfreq);
+ 		} else {
+ 			status = REMOUNT_FAIL;
+ 			info(ap->logopt, "failed to re-connect %s", buf);
diff --git a/SOURCES/autofs-5.1.6-remove-force-parameter-from-umount_all.patch b/SOURCES/autofs-5.1.6-remove-force-parameter-from-umount_all.patch
new file mode 100644
index 0000000..16c1d63
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-remove-force-parameter-from-umount_all.patch
@@ -0,0 +1,63 @@
+autofs-5.1.6 - remove force parameter from umount_all()
+
+From: Ian Kent <raven@themaw.net>
+
+The function umount_all() is always called with it's force parameter
+true so remove it.
+
+Because the failure case is not used make the function void as well.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    9 +++------
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -125,6 +125,7 @@ xx/xx/2018 autofs-5.1.5
+ - use mnt_list for submounts.
+ - use mnt_list for amdmounts.
+ - make umount_autofs() static.
++- remove force parameter from umount_all().
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -99,7 +99,6 @@ pthread_key_t key_thread_attempt_id = (p
+ 
+ int aquire_flag_file(void);
+ void release_flag_file(void);
+-static int umount_all(struct autofs_point *ap, int force);
+ 
+ extern struct master *master_list;
+ 
+@@ -710,16 +709,14 @@ int umount_multi(struct autofs_point *ap
+ 	return left;
+ }
+ 
+-static int umount_all(struct autofs_point *ap, int force)
++static void umount_all(struct autofs_point *ap)
+ {
+ 	int left;
+ 
+ 	left = umount_multi(ap, ap->path, 0);
+-	if (force && left)
++	if (left)
+ 		warn(ap->logopt, "could not unmount %d dirs under %s",
+ 		     left, ap->path);
+-
+-	return left;
+ }
+ 
+ static int umount_autofs(struct autofs_point *ap, const char *root)
+@@ -737,7 +734,7 @@ static int umount_autofs(struct autofs_p
+ 	lookup_close_lookup(ap);
+ 
+ 	if (ap->type == LKP_INDIRECT) {
+-		umount_all(ap, 1);
++		umount_all(ap);
+ 		ret = umount_autofs_indirect(ap, root);
+ 	} else
+ 		ret = umount_autofs_direct(ap);
diff --git a/SOURCES/autofs-5.1.6-remove-intr-hosts-map-mount-option.patch b/SOURCES/autofs-5.1.6-remove-intr-hosts-map-mount-option.patch
new file mode 100644
index 0000000..4b6e188
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-remove-intr-hosts-map-mount-option.patch
@@ -0,0 +1,113 @@
+autofs-5.1.6 - remove intr hosts map mount option
+
+From: Ian Kent <raven@themaw.net>
+
+Don't use the intr option on NFS mounts by default, it's been ignored
+by the kernel for a long time now.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG            |    1 +
+ man/auto.master.5.in |    4 ++--
+ man/autofs.5         |    4 ++--
+ modules/parse_sun.c  |    9 +++------
+ samples/auto.misc    |    2 +-
+ samples/auto.net     |    2 +-
+ 6 files changed, 10 insertions(+), 12 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -77,6 +77,7 @@
+ - add missing description of null map option.
+ - fix empty mounts list return from unlink_mount_tree().
+ - fix nonstrict offset mount fail handling.
++- remove intr hosts map mount option.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/man/auto.master.5.in
++++ autofs-5.1.4/man/auto.master.5.in
+@@ -260,8 +260,8 @@ For example, with an entry in the master
+ accessing /net/myserver will mount exports from myserver on directories below
+ /net/myserver.
+ .P
+-NOTE: mounts done from a hosts map will be mounted with the "nosuid,nodev,intr" options
+-unless overridden by explicitly specifying the "suid", "dev" or "nointr" options in the
++NOTE: mounts done from a hosts map will be mounted with the "nosuid,nodev" options
++unless overridden by explicitly specifying the "suid", "dev" options in the
+ master map entry.
+ .SH BUILTIN MAP \-null
+ If "\-null" is given as the map it is used to tell automount(8) to ignore a subsequent
+--- autofs-5.1.4.orig/man/autofs.5
++++ autofs-5.1.4/man/autofs.5
+@@ -86,13 +86,13 @@ Indirect map:
+ .RS +.2i
+ .ta 1.0i 3.0i
+ .nf
+-kernel	\-ro,soft,intr	ftp.kernel.org:/pub/linux
++kernel	\-ro,soft	ftp.kernel.org:/pub/linux
+ boot	\-fstype=ext2	:/dev/hda1
+ windoze	\-fstype=smbfs	://windoze/c
+ removable	\-fstype=ext2	:/dev/hdd
+ cd	\-fstype=iso9660,ro	:/dev/hdc
+ floppy	\-fstype=auto	:/dev/fd0
+-server	\-rw,hard,intr	/ \-ro myserver.me.org:/ \\
++server	\-rw,hard	/ \-ro myserver.me.org:/ \\
+ 			/usr myserver.me.org:/usr \\
+ 			/home myserver.me.org:/home
+ .fi
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -628,10 +628,9 @@ static int sun_mount(struct autofs_point
+ 			int len = strlen(options);
+ 			int suid = strstr(options, "suid") ? 0 : 7;
+ 			int dev = strstr(options, "dev") ? 0 : 6;
+-			int nointr = strstr(options, "nointr") ? 0 : 5;
+ 
+-			if (suid || dev || nointr) {
+-				char *tmp = alloca(len + suid + dev + nointr + 1);
++			if (suid || dev) {
++				char *tmp = alloca(len + suid + dev + 1);
+ 				if (!tmp) {
+ 					error(ap->logopt, MODPREFIX
+ 					      "alloca failed for options");
+@@ -645,8 +644,6 @@ static int sun_mount(struct autofs_point
+ 					strcat(tmp, ",nosuid");
+ 				if (dev)
+ 					strcat(tmp, ",nodev");
+-				if (nointr)
+-					strcat(tmp, ",intr");
+ 				options = tmp;
+ 			}
+ 		} else {
+@@ -658,7 +655,7 @@ static int sun_mount(struct autofs_point
+ 					return -1;
+ 				return 1;
+ 			}
+-			strcpy(tmp, "nosuid,nodev,intr");
++			strcpy(tmp, "nosuid,nodev");
+ 			options = tmp;
+ 		}
+ 	}
+--- autofs-5.1.4.orig/samples/auto.misc
++++ autofs-5.1.4/samples/auto.misc
+@@ -6,7 +6,7 @@
+ cd		-fstype=iso9660,ro,nosuid,nodev	:/dev/cdrom
+ 
+ # the following entries are samples to pique your imagination
+-#linux		-ro,soft,intr		ftp.example.org:/pub/linux
++#linux		-ro,soft		ftp.example.org:/pub/linux
+ #boot		-fstype=ext2		:/dev/hda1
+ #floppy		-fstype=auto		:/dev/fd0
+ #floppy		-fstype=ext2		:/dev/fd0
+--- autofs-5.1.4.orig/samples/auto.net
++++ autofs-5.1.4/samples/auto.net
+@@ -9,7 +9,7 @@ key="$1"
+ 
+ # add "nosymlink" here if you want to suppress symlinking local filesystems
+ # add "nonstrict" to make it OK for some filesystems to not mount
+-opts="-fstype=nfs,hard,intr,nodev,nosuid"
++opts="-fstype=nfs,hard,nodev,nosuid"
+ 
+ for P in /bin /sbin /usr/bin /usr/sbin
+ do
diff --git a/SOURCES/autofs-5.1.6-remove-unused-function-tree_get_mnt_list.patch b/SOURCES/autofs-5.1.6-remove-unused-function-tree_get_mnt_list.patch
new file mode 100644
index 0000000..b0c7bb3
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-remove-unused-function-tree_get_mnt_list.patch
@@ -0,0 +1,366 @@
+autofs-5.1.6 - remove unused function tree_get_mnt_list()
+
+From: Ian Kent <raven@themaw.net>
+
+Remove the now unused function tree_get_mnt_list() and friends.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 
+ include/mounts.h |   17 ---
+ lib/mounts.c     |  299 -------------------------------------------------------
+ 3 files changed, 1 insertion(+), 316 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -130,6 +130,7 @@ xx/xx/2018 autofs-5.1.5
+ - fix stale offset directories disable mount.
+ - use struct mnt_list to track mounted mounts.
+ - use struct mnt_list mounted list for expire.
++- remove unused function tree_get_mnt_list().
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -83,20 +83,8 @@ struct mnt_list {
+ 	 * List operations ie. get_mnt_list.
+ 	 */
+ 	struct mnt_list *next;
+-
+-	/*
+-	 * Tree operations ie. tree_make_tree,
+-	 * tree_get_mnt_list etc.
+-	 */
+-	struct mnt_list *left;
+-	struct mnt_list *right;
+-	struct list_head self;
+-	struct list_head list;
+-	struct list_head entries;
+-	struct list_head sublist;
+ };
+ 
+-
+ struct nfs_mount_vers {
+ 	unsigned int major;
+ 	unsigned int minor;
+@@ -143,11 +131,6 @@ void mnts_set_mounted_mount(struct autof
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+-void tree_free_mnt_tree(struct mnt_list *tree);
+-struct mnt_list *tree_make_mnt_tree(const char *path);
+-int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
+-int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
+-int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path);
+ void set_tsd_user_vars(unsigned int, uid_t, gid_t);
+ const char *mount_type_str(unsigned int);
+ void set_exp_timeout(struct autofs_point *ap, struct map_source *source, time_t timeout);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1685,305 +1685,6 @@ int is_mounted(const char *mp, unsigned
+ 		return table_is_mounted(mp, type);
+ }
+ 
+-/*
+- * Since we have to look at the entire mount tree for direct
+- * mounts (all mounts under "/") and we may have a large number
+- * of entries to traverse again and again we need to
+- * use a more efficient method than the routines above.
+- *
+- * Thre tree_... routines allow us to read the mount tree
+- * once and pass it to subsequent functions for use. Since
+- * it's a tree structure searching should be a low overhead
+- * operation.
+- */
+-void tree_free_mnt_tree(struct mnt_list *tree)
+-{
+-	struct list_head *head, *p;
+-
+-	if (!tree)
+-		return;
+-
+-	tree_free_mnt_tree(tree->left);
+-	tree_free_mnt_tree(tree->right);
+-
+-	head = &tree->self;
+-	p = head->next;
+-	while (p != head) {
+-		struct mnt_list *this;
+-
+-		this = list_entry(p, struct mnt_list, self);
+-
+-		p = p->next;
+-
+-		list_del(&this->self);
+-
+-		free(this->mp);
+-
+-		free(this);
+-	}
+-
+-	free(tree->mp);
+-	free(tree);
+-}
+-
+-/*
+- * Make tree of system mounts in /proc/mounts.
+- */
+-struct mnt_list *tree_make_mnt_tree(const char *path)
+-{
+-	FILE *tab;
+-	struct mntent mnt_wrk;
+-	char buf[PATH_MAX * 3];
+-	struct mntent *mnt;
+-	struct mnt_list *ent, *mptr;
+-	struct mnt_list *tree = NULL;
+-	size_t plen;
+-	int eq;
+-
+-	tab = open_fopen_r(_PROC_MOUNTS);
+-	if (!tab) {
+-		char *estr = strerror_r(errno, buf, PATH_MAX - 1);
+-		logerr("fopen: %s", estr);
+-		return NULL;
+-	}
+-
+-	plen = strlen(path);
+-
+-	while ((mnt = local_getmntent_r(tab, &mnt_wrk, buf, PATH_MAX * 3))) {
+-		size_t len = strlen(mnt->mnt_dir);
+-
+-		/* Not matching path */
+-		if (strncmp(mnt->mnt_dir, path, plen))
+-			continue;
+-
+-		/* Not a subdirectory of requested path */
+-		if (plen > 1 && len > plen && mnt->mnt_dir[plen] != '/')
+-			continue;
+-
+-		ent = malloc(sizeof(*ent));
+-		if (!ent) {
+-			endmntent(tab);
+-			tree_free_mnt_tree(tree);
+-			return NULL;
+-		}
+-		memset(ent, 0, sizeof(*ent));
+-
+-		INIT_LIST_HEAD(&ent->self);
+-		INIT_LIST_HEAD(&ent->list);
+-		INIT_LIST_HEAD(&ent->entries);
+-		INIT_LIST_HEAD(&ent->sublist);
+-
+-		ent->mp = malloc(len + 1);
+-		if (!ent->mp) {
+-			endmntent(tab);
+-			free(ent);
+-			tree_free_mnt_tree(tree);
+-			return NULL;
+-		}
+-		strcpy(ent->mp, mnt->mnt_dir);
+-
+-		if (!strcmp(mnt->mnt_type, "autofs"))
+-			ent->flags |= MNTS_AUTOFS;
+-
+-		if (ent->flags & MNTS_AUTOFS) {
+-			if (strstr(mnt->mnt_opts, "indirect"))
+-				ent->flags |= MNTS_INDIRECT;
+-			else if (strstr(mnt->mnt_opts, "direct"))
+-				ent->flags |= MNTS_DIRECT;
+-			else if (strstr(mnt->mnt_opts, "offset"))
+-				ent->flags |= MNTS_OFFSET;
+-		}
+-
+-		mptr = tree;
+-		while (mptr) {
+-			int elen = strlen(ent->mp);
+-			int mlen = strlen(mptr->mp);
+-
+-			if (elen < mlen) {
+-				if (mptr->left) {
+-					mptr = mptr->left;
+-					continue;
+-				} else {
+-					mptr->left = ent;
+-					break;
+-				}
+-			} else if (elen > mlen) {
+-				if (mptr->right) {
+-					mptr = mptr->right;
+-					continue;
+-				} else {
+-					mptr->right = ent;
+-					break;
+-				}
+-			}
+-
+-			eq = strcmp(ent->mp, mptr->mp);
+-			if (eq < 0) {
+-				if (mptr->left)
+-					mptr = mptr->left;
+-				else {
+-					mptr->left = ent;
+-					break;
+-				}
+-			} else if (eq > 0) {
+-				if (mptr->right)
+-					mptr = mptr->right;
+-				else {
+-					mptr->right = ent;
+-					break;
+-				}
+-			} else {
+-				list_add_tail(&ent->self, &mptr->self);
+-				break;
+-			}
+-		}
+-
+-		if (!tree)
+-			tree = ent;
+-	}
+-	fclose(tab);
+-
+-	return tree;
+-}
+-
+-/*
+- * Get list of mounts under "path" in longest->shortest order
+- */
+-int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include)
+-{
+-	size_t mlen, plen;
+-
+-	if (!mnts)
+-		return 0;
+-
+-	plen = strlen(path);
+-	mlen = strlen(mnts->mp);
+-	if (mlen < plen)
+-		return tree_get_mnt_list(mnts->right, list, path, include);
+-	else {
+-		struct list_head *self, *p;
+-
+-		tree_get_mnt_list(mnts->left, list, path, include);
+-
+-		if ((!include && mlen <= plen) ||
+-				strncmp(mnts->mp, path, plen))
+-			goto skip;
+-
+-		if (plen > 1 && mlen > plen && mnts->mp[plen] != '/')
+-			goto skip;
+-
+-		INIT_LIST_HEAD(&mnts->list);
+-		list_add(&mnts->list, list);
+-
+-		self = &mnts->self;
+-		list_for_each(p, self) {
+-			struct mnt_list *this;
+-
+-			this = list_entry(p, struct mnt_list, self);
+-			INIT_LIST_HEAD(&this->list);
+-			list_add(&this->list, list);
+-		}
+-skip:
+-		tree_get_mnt_list(mnts->right, list, path, include);
+-	}
+-
+-	if (list_empty(list))
+-		return 0;
+-
+-	return 1;
+-}
+-
+-/*
+- * Get list of mounts under "path" in longest->shortest order
+- */
+-int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include)
+-{
+-	size_t mlen, plen;
+-
+-	if (!mnts)
+-		return 0;
+-
+-	plen = strlen(path);
+-	mlen = strlen(mnts->mp);
+-	if (mlen < plen)
+-		return tree_get_mnt_sublist(mnts->right, list, path, include);
+-	else {
+-		struct list_head *self, *p;
+-
+-		tree_get_mnt_sublist(mnts->left, list, path, include);
+-
+-		if ((!include && mlen <= plen) ||
+-				strncmp(mnts->mp, path, plen))
+-			goto skip;
+-
+-		if (plen > 1 && mlen > plen && mnts->mp[plen] != '/')
+-			goto skip;
+-
+-		INIT_LIST_HEAD(&mnts->sublist);
+-		list_add(&mnts->sublist, list);
+-
+-		self = &mnts->self;
+-		list_for_each(p, self) {
+-			struct mnt_list *this;
+-
+-			this = list_entry(p, struct mnt_list, self);
+-			INIT_LIST_HEAD(&this->sublist);
+-			list_add(&this->sublist, list);
+-		}
+-skip:
+-		tree_get_mnt_sublist(mnts->right, list, path, include);
+-	}
+-
+-	if (list_empty(list))
+-		return 0;
+-
+-	return 1;
+-}
+-
+-int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path)
+-{
+-	int mlen, plen;
+-
+-	if (!mnts)
+-		return 0;
+-
+-	plen = strlen(path);
+-	mlen = strlen(mnts->mp);
+-	if (mlen < plen)
+-		return tree_find_mnt_ents(mnts->right, list, path);
+-	else if (mlen > plen)
+-		return tree_find_mnt_ents(mnts->left, list, path);
+-	else {
+-		struct list_head *self, *p;
+-
+-		tree_find_mnt_ents(mnts->left, list, path);
+-
+-		if (!strcmp(mnts->mp, path)) {
+-			INIT_LIST_HEAD(&mnts->entries);
+-			list_add(&mnts->entries, list);
+-		}
+-
+-		self = &mnts->self;
+-		list_for_each(p, self) {
+-			struct mnt_list *this;
+-
+-			this = list_entry(p, struct mnt_list, self);
+-
+-			if (!strcmp(this->mp, path)) {
+-				INIT_LIST_HEAD(&this->entries);
+-				list_add(&this->entries, list);
+-			}
+-		}
+-
+-		tree_find_mnt_ents(mnts->right, list, path);
+-
+-		if (!list_empty(list))
+-			return 1;
+-	}
+-
+-	return 0;
+-}
+-
+ void set_tsd_user_vars(unsigned int logopt, uid_t uid, gid_t gid)
+ {
+ 	struct thread_stdenv_vars *tsv;
diff --git a/SOURCES/autofs-5.1.6-update-list_h.patch b/SOURCES/autofs-5.1.6-update-list_h.patch
new file mode 100644
index 0000000..5843b37
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-update-list_h.patch
@@ -0,0 +1,513 @@
+autofs-5.1.6 - update list.h
+
+From: Ian Kent <raven@themaw.net>
+
+Update autofs include/list.h mostly to include the hlist
+implementation but also to simplify bits of it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG      |    1 
+ include/list.h |  402 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 378 insertions(+), 25 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -116,6 +116,7 @@ xx/xx/2018 autofs-5.1.5
+ - fix additional typing errors.
+ - make bind mounts propagation slave by default.
+ - fix browse dir not re-created on symlink expire.
++- update list.h.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/include/list.h
++++ autofs-5.1.4/include/list.h
+@@ -1,6 +1,27 @@
+ #ifndef _LINUX_LIST_H
+ #define _LINUX_LIST_H
+ 
++#include <stddef.h>
++
++/*
++ * Casts a member of a structure out to the containing structure
++ * @param ptr        the pointer to the member.
++ * @param type       the type of the container struct this is embedded in.
++ * @param member     the name of the member within the struct.
++ *
++ */
++#define container_of(ptr, type, member) ({                      \
++        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
++        (type *)( (char *)__mptr - offsetof(type,member) );})
++
++/*
++ * These are non-NULL pointers that will result in page faults
++ * under normal circumstances, used to verify that nobody uses
++ * non-initialized list entries.
++ */
++#define LIST_POISON1  ((void *) 0x00100100)
++#define LIST_POISON2  ((void *) 0x00200200)
++
+ /*
+  * Simple doubly linked list implementation.
+  *
+@@ -25,14 +46,14 @@ struct list_head {
+ } while (0)
+ 
+ /*
+- * Insert a new entry between two known consecutive entries. 
++ * Insert a new entry between two known consecutive entries.
+  *
+  * This is only for internal list manipulation where we know
+  * the prev/next entries already!
+  */
+-static __inline__ void __list_add(struct list_head * new,
+-	struct list_head * prev,
+-	struct list_head * next)
++static inline void __list_add(struct list_head *new,
++			      struct list_head *prev,
++			      struct list_head *next)
+ {
+ 	next->prev = new;
+ 	new->next = next;
+@@ -48,7 +69,7 @@ static __inline__ void __list_add(struct
+  * Insert a new entry after the specified head.
+  * This is good for implementing stacks.
+  */
+-static __inline__ void list_add(struct list_head *new, struct list_head *head)
++static inline void list_add(struct list_head *new, struct list_head *head)
+ {
+ 	__list_add(new, head, head->next);
+ }
+@@ -61,7 +82,7 @@ static __inline__ void list_add(struct l
+  * Insert a new entry before the specified head.
+  * This is useful for implementing queues.
+  */
+-static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
++static inline void list_add_tail(struct list_head *new, struct list_head *head)
+ {
+ 	__list_add(new, head->prev, head);
+ }
+@@ -73,8 +94,7 @@ static __inline__ void list_add_tail(str
+  * This is only for internal list manipulation where we know
+  * the prev/next entries already!
+  */
+-static __inline__ void __list_del(struct list_head * prev,
+-				  struct list_head * next)
++static inline void __list_del(struct list_head * prev, struct list_head * next)
+ {
+ 	next->prev = prev;
+ 	prev->next = next;
+@@ -83,50 +103,96 @@ static __inline__ void __list_del(struct
+ /**
+  * list_del - deletes entry from list.
+  * @entry: the element to delete from the list.
+- * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
++ * Note: list_empty on entry does not return true after this, the entry is
++ * in an undefined state.
+  */
+-static __inline__ void list_del(struct list_head *entry)
++static inline void list_del(struct list_head *entry)
+ {
+ 	__list_del(entry->prev, entry->next);
++	entry->next = LIST_POISON1;
++	entry->prev = LIST_POISON2;
+ }
+ 
+ /**
+  * list_del_init - deletes entry from list and reinitialize it.
+  * @entry: the element to delete from the list.
+  */
+-static __inline__ void list_del_init(struct list_head *entry)
++static inline void list_del_init(struct list_head *entry)
+ {
+ 	__list_del(entry->prev, entry->next);
+-	INIT_LIST_HEAD(entry); 
++	INIT_LIST_HEAD(entry);
++}
++
++/*
++ * list_move - delete from one list and add as another's head
++ * @list: the entry to move
++ * @head: the head that will precede our entry
++ */
++static inline void list_move(struct list_head *list, struct list_head *head)
++{
++        __list_del(list->prev, list->next);
++        list_add(list, head);
++}
++
++/**
++ * list_move_tail - delete from one list and add as another's tail
++ * @list: the entry to move
++ * @head: the head that will follow our entry
++ */
++static inline void list_move_tail(struct list_head *list,
++				  struct list_head *head)
++{
++        __list_del(list->prev, list->next);
++        list_add_tail(list, head);
+ }
+ 
+ /**
+  * list_empty - tests whether a list is empty
+  * @head: the list to test.
+  */
+-static __inline__ int list_empty(struct list_head *head)
++static inline int list_empty(const struct list_head *head)
+ {
+ 	return head->next == head;
+ }
+ 
++static inline void __list_splice(struct list_head *list,
++				 struct list_head *head)
++{
++	struct list_head *first = list->next;
++	struct list_head *last = list->prev;
++	struct list_head *at = head->next;
++
++	first->prev = head;
++	head->next = first;
++
++	last->next = at;
++	at->prev = last;
++}
++
+ /**
+  * list_splice - join two lists
+  * @list: the new list to add.
+  * @head: the place to add it in the first list.
+  */
+-static __inline__ void list_splice(struct list_head *list, struct list_head *head)
++static inline void list_splice(struct list_head *list, struct list_head *head)
+ {
+-	struct list_head *first = list->next;
+-
+-	if (first != list) {
+-		struct list_head *last = list->prev;
+-		struct list_head *at = head->next;
+-
+-		first->prev = head;
+-		head->next = first;
++	if (!list_empty(list))
++		__list_splice(list, head);
++}
+ 
+-		last->next = at;
+-		at->prev = last;
++/**
++ * list_splice_init - join two lists and reinitialise the emptied list.
++ * @list: the new list to add.
++ * @head: the place to add it in the first list.
++ *
++ * The list at @list is reinitialised
++ */
++static inline void list_splice_init(struct list_head *list,
++				    struct list_head *head)
++{
++	if (!list_empty(list)) {
++		__list_splice(list, head);
++		INIT_LIST_HEAD(list);
+ 	}
+ }
+ 
+@@ -137,7 +203,45 @@ static __inline__ void list_splice(struc
+  * @member:	the name of the list_struct within the struct.
+  */
+ #define list_entry(ptr, type, member) \
+-	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
++	container_of(ptr, type, member)
++
++/**
++ * list_first_entry - get the first element from a list
++ * @ptr:        the list head to take the element from.
++ * @type:       the type of the struct this is embedded in.
++ * @member:     the name of the list_head within the struct.
++ *
++ * Note, that list is expected to be not empty.
++ */
++#define list_first_entry(ptr, type, member) \
++        list_entry((ptr)->next, type, member)
++
++/**
++ * list_last_entry - get the last element from a list
++ * @ptr:        the list head to take the element from.
++ * @type:       the type of the struct this is embedded in.
++ * @member:     the name of the list_head within the struct.
++ *
++ * Note, that list is expected to be not empty.
++ */
++#define list_last_entry(ptr, type, member) \
++        list_entry((ptr)->prev, type, member)
++
++/**
++ * list_next_entry - get the next element in list
++ * @pos:        the type * to cursor
++ * @member:     the name of the list_head within the struct.
++ */
++#define list_next_entry(pos, member) \
++	list_entry((pos)->member.next, typeof(*(pos)), member)
++
++/**
++ * list_prev_entry - get the prev element in list
++ * @pos:        the type * to cursor
++ * @member:     the name of the list_head within the struct.
++ */
++#define list_prev_entry(pos, member) \
++	list_entry((pos)->member.prev, typeof(*(pos)), member)
+ 
+ /**
+  * list_for_each	-	iterate over a list
+@@ -155,4 +259,252 @@ static __inline__ void list_splice(struc
+ #define list_for_each_prev(pos, head) \
+ 	for (pos = (head)->prev; pos != (head); pos = pos->prev)
+ 
++/**
++ * list_for_each_safe	-	iterate over a list safe against removal of list entry
++ * @pos:	the &struct list_head to use as a loop counter.
++ * @n:		another &struct list_head to use as temporary storage
++ * @head:	the head for your list.
++ */
++#define list_for_each_safe(pos, n, head) \
++	for (pos = (head)->next, n = pos->next; pos != (head); \
++		pos = n, n = pos->next)
++
++/**
++ * list_for_each_entry	-	iterate over list of given type
++ * @pos:	the type * to use as a loop counter.
++ * @head:	the head for your list.
++ * @member:	the name of the list_struct within the struct.
++ */
++#define list_for_each_entry(pos, head, member)				\
++	for (pos = list_entry((head)->next, typeof(*pos), member);	\
++	     &pos->member != (head);					\
++	     pos = list_next_entry(pos, member))
++
++/**
++ * list_for_each_entry_reverse - iterate backwards over list of given type.
++ * @pos:	the type * to use as a loop counter.
++ * @head:	the head for your list.
++ * @member:	the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_reverse(pos, head, member)			\
++	for (pos = list_last_entry(head, typeof(*pos), member);	\
++	     &pos->member != (head); 	\
++	     pos = list_prev_entry(pos, member))
++
++/**
++ * list_prepare_entry - prepare a pos entry for use as a start point in
++ *			list_for_each_entry_continue
++ * @pos:	the type * to use as a start point
++ * @head:	the head of the list
++ * @member:	the name of the list_struct within the struct.
++ */
++#define list_prepare_entry(pos, head, member) \
++	((pos) ? : list_entry(head, typeof(*pos), member))
++
++/**
++ * list_for_each_entry_continue -	iterate over list of given type
++ *			continuing after existing point
++ * @pos:	the type * to use as a loop counter.
++ * @head:	the head for your list.
++ * @member:	the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_continue(pos, head, member) 		\
++	for (pos = list_next_entry(pos, member);			\
++	     &pos->member != (head);					\
++	     pos = list_next_entry(pos, member))
++
++/**
++ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
++ * @pos:	the type * to use as a loop counter.
++ * @n:		another type * to use as temporary storage
++ * @head:	the head for your list.
++ * @member:	the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_safe(pos, n, head, member)			\
++	for (pos = list_first_entry(head, typeof(*pos), member),	\
++		n = list_next_entry(pos, member);			\
++	     &pos->member != (head); 					\
++	     pos = n, n = list_next_entry(n, member))
++
++/**
++ * list_for_each_entry_safe_continue -	iterate over list of given type
++ *			continuing after existing point safe against removal of list entry
++ * @pos:	the type * to use as a loop counter.
++ * @n:		another type * to use as temporary storage
++ * @head:	the head for your list.
++ * @member:	the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
++	for (pos = list_next_entry(pos, member),				\
++	     n = list_next_entry(pos, member);					\
++	     &pos->member != (head);						\
++	     pos = n, n = list_next_entry(n, member))
++
++/**
++ * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
++ *				      removal of list entry
++ * @pos:	the type * to use as a loop counter.
++ * @n:		another type * to use as temporary storage
++ * @head:	the head for your list.
++ * @member:	the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
++	for (pos = list_last_entry(head, typeof(*pos), member),		\
++	     n = list_prev_entry(pos, member);				\
++	     &pos->member != (head); 					\
++	     pos = n, n = list_prev_entry(n, member))
++
++
++
++
++/*
++ * Double linked lists with a single pointer list head.
++ * Mostly useful for hash tables where the two pointer list head is
++ * too wasteful.
++ * You lose the ability to access the tail in O(1).
++ */
++
++struct hlist_head {
++	struct hlist_node *first;
++};
++
++struct hlist_node {
++	struct hlist_node *next, **pprev;
++};
++
++#define HLIST_HEAD_INIT { .first = NULL }
++#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
++#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
++#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
++
++static inline int hlist_unhashed(const struct hlist_node *h)
++{
++	return !h->pprev;
++}
++
++static inline int hlist_empty(const struct hlist_head *h)
++{
++	return !h->first;
++}
++
++static inline void __hlist_del(struct hlist_node *n)
++{
++	struct hlist_node *next = n->next;
++	struct hlist_node **pprev = n->pprev;
++	*pprev = next;
++	if (next)
++		next->pprev = pprev;
++}
++
++static inline void hlist_del(struct hlist_node *n)
++{
++	__hlist_del(n);
++	n->next = LIST_POISON1;
++	n->pprev = LIST_POISON2;
++}
++
++
++static inline void hlist_del_init(struct hlist_node *n)
++{
++	if (n->pprev)  {
++		__hlist_del(n);
++		INIT_HLIST_NODE(n);
++	}
++}
++
++static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
++{
++	struct hlist_node *first = h->first;
++	n->next = first;
++	if (first)
++		first->pprev = &n->next;
++	h->first = n;
++	n->pprev = &h->first;
++}
++
++
++
++/* next must be != NULL */
++static inline void hlist_add_before(struct hlist_node *n,
++					struct hlist_node *next)
++{
++	n->pprev = next->pprev;
++	n->next = next;
++	next->pprev = &n->next;
++	*(n->pprev) = n;
++}
++
++static inline void hlist_add_after(struct hlist_node *n,
++					struct hlist_node *next)
++{
++	next->next = n->next;
++	n->next = next;
++	next->pprev = &n->next;
++
++	if(next->next)
++		next->next->pprev  = &next->next;
++}
++
++
++
++#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
++
++#define hlist_for_each(pos, head) \
++	for (pos = (head)->first; pos; pos = pos->next)
++
++#define hlist_for_each_safe(pos, n, head) \
++	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
++	     pos = n)
++
++#define hlist_entry_safe(ptr, type, member) \
++        ({ typeof(ptr) ____ptr = (ptr); \
++           ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
++        })
++
++/**
++ * hlist_for_each_entry	- iterate over list of given type
++ * @tpos:	the type * to use as a loop counter.
++ * @pos:	the &struct hlist_node to use as a loop counter.
++ * @head:	the head for your list.
++ * @member:	the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry(pos, head, member)				\
++	for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
++	     pos;							\
++	     pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
++
++/**
++ * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
++ * @tpos:	the type * to use as a loop counter.
++ * @pos:	the &struct hlist_node to use as a loop counter.
++ * @member:	the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry_continue(pos, member)			\
++	for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
++	     pos;							\
++	     pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
++
++/**
++ * hlist_for_each_entry_from - iterate over a hlist continuing from existing point
++ * @tpos:	the type * to use as a loop counter.
++ * @pos:	the &struct hlist_node to use as a loop counter.
++ * @member:	the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry_from(pos, member)				\
++	for (; pos;							\
++	     pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
++
++/**
++ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
++ * @tpos:	the type * to use as a loop counter.
++ * @pos:	the &struct hlist_node to use as a loop counter.
++ * @n:		another &struct hlist_node to use as temporary storage
++ * @head:	the head for your list.
++ * @member:	the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry_safe(tpos, pos, n, head, member)		\
++	for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
++	     pos && ({ n = pos->next; 1; }) &&				\
++	     pos = hlist_entry_safe(n, typeof(*pos), member))
++
+ #endif
diff --git a/SOURCES/autofs-5.1.6-use-master_list_empty-for-list-empty-check.patch b/SOURCES/autofs-5.1.6-use-master_list_empty-for-list-empty-check.patch
new file mode 100644
index 0000000..0617b06
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-use-master_list_empty-for-list-empty-check.patch
@@ -0,0 +1,119 @@
+autofs-5.1.6 - use master_list_empty() for list empty check
+
+From: Ian Kent <raven@themaw.net>
+
+For consistency use the master_list_empty() function for list empty
+checks everywhere.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    2 +-
+ daemon/master.c    |   24 +++++++++++++++++-------
+ include/master.h   |    1 +
+ 4 files changed, 20 insertions(+), 8 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -134,6 +134,7 @@ xx/xx/2018 autofs-5.1.5
+ - only add expre alarm for active mounts.
+ - move submount check into conditional_alarm_add().
+ - move lib/master.c to daemon/master.c.
++- use master_list_empty() for list empty check.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -1596,7 +1596,7 @@ static void *statemachine(void *arg)
+ 		case SIGUSR2:
+ 			master_mutex_lock();
+ 			if (list_empty(&master_list->completed)) {
+-				if (list_empty(&master_list->mounts)) {
++				if (__master_list_empty(master_list)) {
+ 					master_mutex_unlock();
+ 					return NULL;
+ 				}
+--- autofs-5.1.4.orig/daemon/master.c
++++ autofs-5.1.4/daemon/master.c
+@@ -1110,7 +1110,7 @@ int master_read_master(struct master *ma
+ 			master_mount_mounts(master, age);
+ 	}
+ 
+-	if (list_empty(&master->mounts))
++	if (__master_list_empty(master))
+ 		warn(logopt, "no mounts in table");
+ 
+ 	master_mutex_unlock();
+@@ -1625,7 +1625,7 @@ int dump_map(struct master *master, cons
+ {
+ 	struct list_head *p, *head;
+ 
+-	if (list_empty(&master->mounts)) {
++	if (__master_list_empty(master)) {
+ 		printf("no master map entries found\n");
+ 		return 1;
+ 	}
+@@ -1743,7 +1743,7 @@ int master_show_mounts(struct master *ma
+ 		printf("global options %s be appended to map entries\n", append);
+ 	}
+ 
+-	if (list_empty(&master->mounts)) {
++	if (__master_list_empty(master)) {
+ 		printf("no master map entries found\n\n");
+ 		return 1;
+ 	}
+@@ -1831,13 +1831,22 @@ int master_show_mounts(struct master *ma
+ 	return 1;
+ }
+ 
+-int master_list_empty(struct master *master)
++int __master_list_empty(struct master *master)
+ {
+ 	int res = 0;
+ 
+-	master_mutex_lock();
+ 	if (list_empty(&master->mounts))
+ 		res = 1;
++
++	return res;
++}
++
++int master_list_empty(struct master *master)
++{
++	int res;
++
++	master_mutex_lock();
++	res = __master_list_empty(master);
+ 	master_mutex_unlock();
+ 
+ 	return res;
+@@ -1859,7 +1868,8 @@ int master_done(struct master *master)
+ 		master_free_mapent_sources(entry, 1);
+ 		master_free_mapent(entry);
+ 	}
+-	if (list_empty(&master->mounts))
++
++	if (__master_list_empty(master))
+ 		res = 1;
+ 
+ 	return res;
+@@ -1872,7 +1882,7 @@ unsigned int master_get_logopt(void)
+ 
+ int master_kill(struct master *master)
+ {
+-	if (!list_empty(&master->mounts))
++	if (!master_list_empty(master))
+ 		return 0;
+ 
+ 	if (master->name)
+--- autofs-5.1.4.orig/include/master.h
++++ autofs-5.1.4/include/master.h
+@@ -123,6 +123,7 @@ int master_mount_mounts(struct master *,
+ int dump_map(struct master *, const char *, const char *);
+ int master_show_mounts(struct master *);
+ unsigned int master_get_logopt(void);
++int __master_list_empty(struct master *);
+ int master_list_empty(struct master *);
+ int master_done(struct master *);
+ int master_kill(struct master *);
diff --git a/SOURCES/autofs-5.1.6-use-mnt_list-for-amdmounts.patch b/SOURCES/autofs-5.1.6-use-mnt_list-for-amdmounts.patch
new file mode 100644
index 0000000..ab4d0f3
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-use-mnt_list-for-amdmounts.patch
@@ -0,0 +1,547 @@
+autofs-5.1.6 - use mnt_list for amdmounts
+
+From: Ian Kent <raven@themaw.net>
+
+Use struct mnt_list objects for the list of amd mounts instead of
+struct amd_entry.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 
+ daemon/automount.c     |   48 ++++++++++------------
+ daemon/lookup.c        |   18 +++++---
+ include/automount.h    |    2 
+ include/master.h       |    2 
+ include/mounts.h       |   12 +++++
+ include/parse_amd.h    |    1 
+ lib/master.c           |   36 +----------------
+ lib/mounts.c           |  103 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ modules/mount_autofs.c |   15 ++++---
+ modules/parse_amd.c    |   43 +++++++++++++++-----
+ 11 files changed, 193 insertions(+), 88 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -123,6 +123,7 @@ xx/xx/2018 autofs-5.1.5
+ - make external mounts use simpler hashtable.
+ - add a hash index to mnt_list.
+ - use mnt_list for submounts.
++- use mnt_list for amdmounts.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -595,7 +595,8 @@ static int umount_subtree_mounts(struct
+ 	 * it already to ensure it's ok to remove any offset triggers.
+ 	 */
+ 	if (!is_mm_root && is_mounted(path, MNTS_REAL)) {
+-		struct amd_entry *entry;
++		struct mnt_list *mnt;
++
+ 		debug(ap->logopt, "unmounting dir = %s", path);
+ 		if (umount_ent(ap, path) &&
+ 		    is_mounted(path, MNTS_REAL)) {
+@@ -605,16 +606,12 @@ static int umount_subtree_mounts(struct
+ 		}
+ 
+ 		/* 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;
++		mnt = mnts_find_amdmount(path);
++		if (mnt) {
++			umount_amd_ext_mount(ap, mnt->ext_mp);
++			mnts_remove_amdmount(path);
++			mnts_put_mount(mnt);
+ 		}
+-		list_del(&entry->entries);
+-		mounts_mutex_unlock(ap);
+-		umount_amd_ext_mount(ap, entry->fs);
+-		free_amd_entry(entry);
+ 	}
+ done:
+ 	return left;
+@@ -639,7 +636,8 @@ int umount_multi(struct autofs_point *ap
+ 
+ 	/* if this is a symlink we can handle it now */
+ 	if (S_ISLNK(st.st_mode)) {
+-		struct amd_entry *entry;
++		struct mnt_list *mnt;
++
+ 		if (st.st_dev != ap->dev) {
+ 			crit(ap->logopt,
+ 			     "symlink %s has the wrong device, "
+@@ -671,17 +669,15 @@ int umount_multi(struct autofs_point *ap
+ 				     "mkdir_path %s failed: %s", path, estr);
+ 			}
+ 		}
++
+ 		/* 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);
+-		umount_amd_ext_mount(ap, entry->fs);
+-		free_amd_entry(entry);
++		mnt = mnts_find_amdmount(path);
++		if (mnt) {
++			umount_amd_ext_mount(ap, mnt->ext_mp);
++			mnts_remove_amdmount(path);
++			mnts_put_mount(mnt);
++		}
++
+ 		return 0;
+ 	}
+ 
+@@ -1720,17 +1716,17 @@ static void handle_mounts_cleanup(void *
+ 		clean = 1;
+ 
+ 	if (submount) {
+-		struct amd_entry *am;
++		struct mnt_list *mnt;
+ 
+ 		/* We are finishing up */
+ 		ap->parent->submnt_count--;
+ 
+ 		/* Submount at ap->path belongs to parent submount list. */
+ 		mnts_remove_submount(ap->path);
+-		am = __master_find_amdmount(ap->parent, ap->path);
+-		if (am) {
+-			list_del_init(&am->entries);
+-			free_amd_entry(am);
++		mnt = mnts_find_amdmount(ap->path);
++		if (mnt) {
++			mnts_remove_amdmount(ap->path);
++			mnts_put_mount(mnt);
+ 		}
+ 	}
+ 
+--- autofs-5.1.4.orig/daemon/lookup.c
++++ autofs-5.1.4/daemon/lookup.c
+@@ -838,7 +838,7 @@ static int lookup_amd_instance(struct au
+ 			       const char *name, int name_len)
+ {
+ 	struct map_source *instance;
+-	struct amd_entry *entry;
++	struct mnt_list *mnt;
+ 	const char *argv[2];
+ 	const char **pargv = NULL;
+ 	int argc = 0;
+@@ -861,21 +861,23 @@ static int lookup_amd_instance(struct au
+ 	strcpy(m_key, ap->path);
+ 	strcat(m_key, "/");
+ 	strcat(m_key, me->multi->key);
+-	entry = master_find_amdmount(ap, m_key);
++
++	mnt = mnts_find_amdmount(m_key);
+ 	free(m_key);
+ 
+-	if (!entry) {
++	if (!mnt) {
+ 		error(ap->logopt, "expected amd mount entry not found");
+ 		return NSS_STATUS_UNKNOWN;
+ 	}
+ 
+-	if (strcmp(entry->type, "host")) {
+-		error(ap->logopt, "unexpected map type %s", entry->type);
++	if (strcmp(mnt->amd_type, "host")) {
++		error(ap->logopt, "unexpected map type %s", mnt->amd_type);
++		mnts_put_mount(mnt);
+ 		return NSS_STATUS_UNKNOWN;
+ 	}
+ 
+-	if (entry->opts && *entry->opts) {
+-		argv[0] = entry->opts;
++	if (mnt->amd_opts && *mnt->amd_opts) {
++		argv[0] = mnt->amd_opts;
+ 		argv[1] = NULL;
+ 		pargv = argv;
+ 		argc = 1;
+@@ -894,9 +896,11 @@ static int lookup_amd_instance(struct au
+ 		}
+ 	}
+ 	if (!instance) {
++		mnts_put_mount(mnt);
+ 		error(ap->logopt, "expected hosts map instance not found");
+ 		return NSS_STATUS_UNKNOWN;
+ 	}
++	mnts_put_mount(mnt);
+ 
+ 	return do_lookup_mount(ap, instance, name, name_len);
+ }
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -568,10 +568,10 @@ 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 submnt_count;	/* Number of submounts */
+ 	struct list_head submounts;	/* List of child submounts */
++	struct list_head amdmounts;	/* List of non submount amd mounts */
+ 	unsigned int shutdown;		/* Shutdown notification */
+ };
+ 
+--- autofs-5.1.4.orig/include/master.h
++++ autofs-5.1.4/include/master.h
+@@ -109,8 +109,6 @@ void master_source_current_wait(struct m
+ void master_source_current_signal(struct master_mapent *);
+ struct master_mapent *master_find_mapent(struct master *, const char *);
+ unsigned int master_partial_match_mapent(struct master *, 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 *);
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -38,6 +38,7 @@
+ #define MNTS_INDIRECT	0x0008
+ #define MNTS_DIRECT	0x0010
+ #define MNTS_OFFSET	0x0020
++#define MNTS_AMD_MOUNT	0x0040
+ 
+ #define REMOUNT_SUCCESS		0x0000
+ #define REMOUNT_FAIL		0x0001
+@@ -64,6 +65,14 @@ struct mnt_list {
+ 	struct list_head submount;
+ 	struct list_head submount_work;
+ 
++	/* List of amd-mounts of an autofs_point */
++	char *ext_mp;
++	char *amd_pref;
++	char *amd_type;
++	char *amd_opts;
++	unsigned int amd_cache_opts;
++	struct list_head amdmount;
++
+ 	/*
+ 	 * List operations ie. get_mnt_list.
+ 	 */
+@@ -118,6 +127,9 @@ struct mnt_list *mnts_add_submount(struc
+ void mnts_remove_submount(const char *mp);
+ void mnts_get_submount_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_submount_list(struct list_head *mnts);
++struct mnt_list *mnts_find_amdmount(const char *path);
++struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *entry);
++void mnts_remove_amdmount(const char *mp);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+--- autofs-5.1.4.orig/include/parse_amd.h
++++ autofs-5.1.4/include/parse_amd.h
+@@ -65,7 +65,6 @@ struct amd_entry {
+ 	char *umount;
+ 	struct selector *selector;
+ 	struct list_head list;
+-	struct list_head entries;
+ };
+ 
+ int amd_parse_list(struct autofs_point *,
+--- autofs-5.1.4.orig/lib/master.c
++++ autofs-5.1.4/lib/master.c
+@@ -152,12 +152,10 @@ void master_free_autofs_point(struct aut
+ 	head = &ap->amdmounts;
+ 	p = head->next;
+ 	while (p != head) {
+-		struct amd_entry *entry = list_entry(p, struct amd_entry, entries);
++		struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
+ 		p = p->next;
+-		if (!list_empty(&entry->entries))
+-			list_del(&entry->entries);
+-		ext_mount_remove(entry->fs);
+-		free_amd_entry(entry);
++		ext_mount_remove(mnt->ext_mp);
++		mnts_remove_amdmount(mnt->mp);
+ 	}
+ 	mounts_mutex_unlock(ap);
+ 
+@@ -761,34 +759,6 @@ unsigned int master_partial_match_mapent
+ 	return ret;
+ }
+ 
+-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;
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -546,7 +546,6 @@ struct amd_entry *new_amd_entry(const st
+ 	memset(new, 0, sizeof(*new));
+ 	new->path = path;
+ 	INIT_LIST_HEAD(&new->list);
+-	INIT_LIST_HEAD(&new->entries);
+ 
+ 	return new;
+ }
+@@ -887,6 +886,7 @@ static struct mnt_list *mnts_alloc_mount
+ 	INIT_HLIST_NODE(&this->hash);
+ 	INIT_LIST_HEAD(&this->submount);
+ 	INIT_LIST_HEAD(&this->submount_work);
++	INIT_LIST_HEAD(&this->amdmount);
+ done:
+ 	return this;
+ }
+@@ -1048,6 +1048,107 @@ void mnts_put_submount_list(struct list_
+ 	mnts_hash_mutex_unlock();
+ }
+ 
++struct mnt_list *mnts_find_amdmount(const char *path)
++{
++	struct mnt_list *mnt;
++
++	mnt = mnts_lookup_mount(path);
++	if (mnt && mnt->flags & MNTS_AMD_MOUNT)
++		return mnt;
++	mnts_put_mount(mnt);
++	return NULL;
++}
++
++struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *entry)
++{
++	struct mnt_list *this;
++	char *type, *ext_mp, *pref, *opts;
++
++	ext_mp = pref = type = opts = NULL;
++
++	if (entry->fs) {
++		ext_mp = strdup(entry->fs);
++		if (!ext_mp)
++			goto fail;
++	}
++
++	if (entry->pref) {
++		pref = strdup(entry->pref);
++		if (!pref)
++			goto fail;
++	}
++
++	if (entry->type) {
++		type = strdup(entry->type);
++		if (!type)
++			goto fail;
++	}
++
++	if (entry->opts) {
++		opts = strdup(entry->opts);
++		if (!opts)
++			goto fail;
++	}
++
++	mnts_hash_mutex_lock();
++	this = mnts_get_mount(entry->path);
++	if (this) {
++		this->ext_mp = ext_mp;
++		this->amd_pref = pref;
++		this->amd_type = type;
++		this->amd_opts = opts;
++		this->amd_cache_opts = entry->cache_opts;
++		this->flags |= MNTS_AMD_MOUNT;
++		if (list_empty(&this->amdmount))
++			list_add_tail(&this->amdmount, &ap->amdmounts);
++	}
++	mnts_hash_mutex_unlock();
++
++	return this;
++fail:
++	if (ext_mp)
++		free(ext_mp);
++	if (pref)
++		free(pref);
++	if (type)
++		free(type);
++	if (opts)
++		free(opts);
++	return NULL;
++}
++
++void mnts_remove_amdmount(const char *mp)
++{
++	struct mnt_list *this;
++
++	mnts_hash_mutex_lock();
++	this = mnts_lookup(mp);
++	if (!(this && this->flags & MNTS_AMD_MOUNT))
++		goto done;
++	this->flags &= ~MNTS_AMD_MOUNT;
++	list_del_init(&this->submount);
++	if (this->ext_mp) {
++		free(this->ext_mp);
++		this->ext_mp = NULL;
++	}
++	if (this->amd_type) {
++		free(this->amd_type);
++		this->amd_type = NULL;
++	}
++	if (this->amd_pref) {
++		free(this->amd_pref);
++		this->amd_pref = NULL;
++	}
++	if (this->amd_opts) {
++		free(this->amd_opts);
++		this->amd_opts = NULL;
++	}
++	this->amd_cache_opts = 0;
++	__mnts_put_mount(this);
++done:
++	mnts_hash_mutex_unlock();
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
+--- autofs-5.1.4.orig/modules/mount_autofs.c
++++ autofs-5.1.4/modules/mount_autofs.c
+@@ -286,16 +286,19 @@ int mount_mount(struct autofs_point *ap,
+ 	mounts_mutex_lock(ap);
+ 
+ 	if (source->flags & MAP_FLAG_FORMAT_AMD) {
+-		struct amd_entry *am_entry = __master_find_amdmount(ap, entry->path);
++		struct mnt_list *mnt;
+ 
+-		if (am_entry) {
+-			if (am_entry->pref) {
+-				nap->pref = am_entry->pref;
+-				am_entry->pref = NULL;
++		mnt = mnts_find_amdmount(entry->path);
++		if (mnt) {
++			if (mnt->amd_pref) {
++				nap->pref = mnt->amd_pref;
++				mnt->amd_pref = NULL;
+ 			}
+ 
+-			if (am_entry->cache_opts & AMD_CACHE_OPTION_ALL)
++			if (mnt->amd_cache_opts & AMD_CACHE_OPTION_ALL)
+ 				nap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
++
++			mnts_put_mount(mnt);
+ 		}
+ 	}
+ 
+--- autofs-5.1.4.orig/modules/parse_amd.c
++++ autofs-5.1.4/modules/parse_amd.c
+@@ -1300,6 +1300,7 @@ static int do_host_mount(struct autofs_p
+ {
+ 	struct lookup_mod *lookup;
+ 	struct map_source *instance;
++	struct mnt_list *mnt = NULL;
+ 	struct mapent *me;
+ 	const char *argv[2];
+ 	const char **pargv = NULL;
+@@ -1316,7 +1317,9 @@ static int do_host_mount(struct autofs_p
+ 	 */
+ 	if (strcmp(name, entry->rhost)) {
+ 		char *target;
+-		size_t len = strlen(ap->path) + strlen(entry->rhost) + 2;
++		size_t len;
++
++		len = strlen(ap->path) + strlen(entry->rhost) + 2;
+ 		target = malloc(len);
+ 		if (!target) {
+ 			warn(ap->logopt, MODPREFIX
+@@ -1329,6 +1332,15 @@ static int do_host_mount(struct autofs_p
+ 		if (entry->path)
+ 			free(entry->path);
+ 		entry->path = target;
++
++		/* Add an mnt_list entry for the updated path. */
++		mnt = mnts_add_amdmount(ap, entry);
++		if (!mnt) {
++			error(ap->logopt, MODPREFIX
++			      "failed to update mount mnt_list entry");
++			goto out;
++		}
++
+ 		/*
+ 		 * Wait for any expire before racing to mount the
+ 		 * export tree or bail out if we're shutting down.
+@@ -1388,6 +1400,8 @@ static int do_host_mount(struct autofs_p
+ 		warn(ap->logopt, MODPREFIX
+ 		     "failed to create symlink to hosts mount base");
+ out:
++	if (ret && mnt)
++		mnts_remove_amdmount(mnt->mp);
+ 	return ret;
+ }
+ 
+@@ -2204,6 +2218,7 @@ int parse_mount(struct autofs_point *ap,
+ 	struct list_head entries, *p, *head;
+ 	struct amd_entry *defaults_entry;
+ 	struct amd_entry *cur_defaults;
++	struct mnt_list *mnt;
+ 	int rv = 1;
+ 	int cur_state;
+ 	int ret;
+@@ -2313,21 +2328,27 @@ int parse_mount(struct autofs_point *ap,
+ 		 * add parsed entry to parent amd mount list and remove
+ 		 * on mount fail.
+ 		 */
+-		mounts_mutex_lock(ap);
+-		list_add_tail(&this->entries, &ap->amdmounts);
+-		mounts_mutex_unlock(ap);
++		mnt = mnts_add_amdmount(ap, this);
++		if (!mnt) {
++			error(ap->logopt, MODPREFIX
++			      "failed to add mount to mnt_list");
++			break;
++		}
+ 
+ 		rv = amd_mount(ap, name, this, source, sv, flags, ctxt);
+-		mounts_mutex_lock(ap);
+ 		if (!rv) {
+-			/* Mounted, remove entry from parsed list */
+-			list_del_init(&this->list);
+-			mounts_mutex_unlock(ap);
++			/*
++			 * If entry->path doesn't match the mnt->mp then
++			 * the mount point path has changed and a new
++			 * mnt_list entry added for it, so remove the
++			 * original.
++			 */
++			if (strcmp(this->path, mnt->mp))
++				mnts_remove_amdmount(this->path);
+ 			break;
+ 		}
+-		/* Not mounted, remove entry from the parent list */
+-		list_del_init(&this->entries);
+-		mounts_mutex_unlock(ap);
++		/* Not mounted, remove the mnt_list entry from amdmount list */
++		mnts_remove_amdmount(this->path);
+ 	}
+ 	free_amd_entry(cur_defaults);
+ 
diff --git a/SOURCES/autofs-5.1.6-use-mnt_list-for-submounts.patch b/SOURCES/autofs-5.1.6-use-mnt_list-for-submounts.patch
new file mode 100644
index 0000000..8ffe5fe
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-use-mnt_list-for-submounts.patch
@@ -0,0 +1,472 @@
+autofs-5.1.6 - use mnt_list for submounts
+
+From: Ian Kent <raven@themaw.net>
+
+Use struct mnt_list objects for submount list entries instead of
+struct autofs_point itself.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 
+ daemon/automount.c     |   11 ++++-
+ daemon/direct.c        |    7 ++-
+ daemon/indirect.c      |    5 ++
+ include/automount.h    |    2 -
+ include/master.h       |    2 -
+ include/mounts.h       |   10 +++++
+ lib/master.c           |   93 +++++++++++++++----------------------------------
+ lib/mounts.c           |   81 ++++++++++++++++++++++++++++++++++++++++++
+ modules/mount_autofs.c |   17 ++++++++
+ 10 files changed, 157 insertions(+), 72 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -122,6 +122,7 @@ xx/xx/2018 autofs-5.1.5
+ - make external mounts independent of amd_entry.
+ - make external mounts use simpler hashtable.
+ - add a hash index to mnt_list.
++- use mnt_list for submounts.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -624,6 +624,7 @@ done:
+    it also tries to umount path itself */
+ int umount_multi(struct autofs_point *ap, const char *path, int incl)
+ {
++	struct mnt_list *sbmnt;
+ 	int is_autofs_fs;
+ 	struct stat st;
+ 	int left;
+@@ -685,8 +686,11 @@ int umount_multi(struct autofs_point *ap
+ 	}
+ 
+ 	is_autofs_fs = 0;
+-	if (master_find_submount(ap, path))
++	sbmnt = mnts_find_submount(path);
++	if (sbmnt) {
+ 		is_autofs_fs = 1;
++		mnts_put_mount(sbmnt);
++	}
+ 
+ 	left = 0;
+ 
+@@ -1717,9 +1721,12 @@ static void handle_mounts_cleanup(void *
+ 
+ 	if (submount) {
+ 		struct amd_entry *am;
++
+ 		/* We are finishing up */
+ 		ap->parent->submnt_count--;
+-		list_del_init(&ap->mounts);
++
++		/* Submount at ap->path belongs to parent submount list. */
++		mnts_remove_submount(ap->path);
+ 		am = __master_find_amdmount(ap->parent, ap->path);
+ 		if (am) {
+ 			list_del_init(&am->entries);
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -1211,14 +1211,17 @@ static void *do_mount_direct(void *arg)
+ 	 */
+ 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
+ 	if (status) {
++		struct mnt_list *sbmnt;
+ 		struct mapent *me;
+ 		struct statfs fs;
+ 		unsigned int close_fd = 0;
+ 
++		sbmnt = mnts_find_submount(mt.name);
+ 		if (statfs(mt.name, &fs) == -1 ||
+-		   (fs.f_type == AUTOFS_SUPER_MAGIC &&
+-		    !master_find_submount(ap, mt.name)))
++		   (fs.f_type == AUTOFS_SUPER_MAGIC && !sbmnt))
+ 			close_fd = 1;
++		if (sbmnt)
++			mnts_put_mount(sbmnt);
+ 		cache_writelock(mt.mc);
+ 		if ((me = cache_lookup_distinct(mt.mc, mt.name))) {
+ 			/*
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -401,6 +401,7 @@ void *expire_proc_indirect(void *arg)
+ 			if (next->flags & MNTS_INDIRECT)
+ 				master_notify_submount(ap, next->mp, ap->state);
+ 			else if (next->flags & MNTS_OFFSET) {
++				struct mnt_list *sbmnt;
+ 				struct map_source *map;
+ 				struct mapent_cache *mc = NULL;
+ 				struct mapent *me = NULL;
+@@ -413,7 +414,9 @@ void *expire_proc_indirect(void *arg)
+ 				}
+ 
+ 				/* Don't touch submounts */
+-				if (master_find_submount(ap, next->mp)) {
++				sbmnt = mnts_find_submount(next->mp);
++				if (sbmnt) {
++					mnts_put_mount(sbmnt);
+ 					pthread_setcancelstate(cur_state, NULL);
+ 					continue;
+ 				}
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -570,9 +570,9 @@ struct autofs_point {
+ 	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 */
+ 	struct list_head submounts;	/* List of child submounts */
++	unsigned int shutdown;		/* Shutdown notification */
+ };
+ 
+ #define UNLINK_AND_CONT		0x01
+--- autofs-5.1.4.orig/include/master.h
++++ autofs-5.1.4/include/master.h
+@@ -109,8 +109,6 @@ void master_source_current_wait(struct m
+ void master_source_current_signal(struct master_mapent *);
+ struct master_mapent *master_find_mapent(struct master *, const char *);
+ unsigned int master_partial_match_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);
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -59,6 +59,11 @@ struct mnt_list {
+ 	struct hlist_node hash;
+ 	unsigned int ref;
+ 
++	/* List of sub-mounts of an autofs_point */
++	struct autofs_point *ap;
++	struct list_head submount;
++	struct list_head submount_work;
++
+ 	/*
+ 	 * List operations ie. get_mnt_list.
+ 	 */
+@@ -108,6 +113,11 @@ int ext_mount_remove(const char *);
+ int ext_mount_inuse(const char *);
+ struct mnt_list *mnts_lookup_mount(const char *mp);
+ void mnts_put_mount(struct mnt_list *mnt);
++struct mnt_list *mnts_find_submount(const char *path);
++struct mnt_list *mnts_add_submount(struct autofs_point *ap);
++void mnts_remove_submount(const char *mp);
++void mnts_get_submount_list(struct list_head *mnts, struct autofs_point *ap);
++void mnts_put_submount_list(struct list_head *mnts);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+--- autofs-5.1.4.orig/lib/master.c
++++ autofs-5.1.4/lib/master.c
+@@ -761,34 +761,6 @@ unsigned int master_partial_match_mapent
+ 	return ret;
+ }
+ 
+-struct autofs_point *__master_find_submount(struct autofs_point *ap, const char *path)
+-{
+-	struct list_head *head, *p;
+-
+-	head = &ap->submounts;
+-	list_for_each(p, head) {
+-		struct autofs_point *submount;
+-
+-		submount = list_entry(p, struct autofs_point, mounts);
+-
+-		if (!strcmp(submount->path, path))
+-			return submount;
+-	}
+-
+-	return NULL;
+-}
+-
+-struct autofs_point *master_find_submount(struct autofs_point *ap, const char *path)
+-{
+-	struct autofs_point *submount;
+-
+-	mounts_mutex_lock(ap);
+-	submount = __master_find_submount(ap, path);
+-	mounts_mutex_unlock(ap);
+-
+-	return submount;
+-}
+-
+ struct amd_entry *__master_find_amdmount(struct autofs_point *ap, const char *path)
+ {
+ 	struct list_head *head, *p;
+@@ -1190,85 +1162,80 @@ int master_submount_list_empty(struct au
+ 
+ int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
+ {
+-	struct list_head *head, *p;
+-	struct autofs_point *this = NULL;
++	struct mnt_list *this, *sbmnt;
++	LIST_HEAD(sbmnts);
+ 	int ret = 1;
+ 
+-	mounts_mutex_lock(ap);
+-
+-	head = &ap->submounts;
+-	p = head->prev;
+-	while (p != head) {
+-		this = list_entry(p, struct autofs_point, mounts);
+-		p = p->prev;
++	mnts_get_submount_list(&sbmnts, ap);
++	if (list_empty(&sbmnts))
++		return 1;
++
++	list_for_each_entry(this, &sbmnts, submount_work) {
++		/* Not a submount */
++		if (!(this->flags & MNTS_AUTOFS))
++			continue;
+ 
+ 		/* path not the same */
+-		if (strcmp(this->path, path))
++		if (strcmp(this->mp, path))
+ 			continue;
+ 
+-		if (!master_submount_list_empty(this)) {
+-			char *this_path = strdup(this->path);
+-			if (this_path) {
+-				mounts_mutex_unlock(ap);
+-				master_notify_submount(this, path, state);
+-				mounts_mutex_lock(ap);
+-				if (!__master_find_submount(ap, this_path)) {
+-					free(this_path);
+-					continue;
+-				}
+-				free(this_path);
+-			}
++		if (!master_submount_list_empty(this->ap)) {
++			struct mnt_list *sm;
++
++			master_notify_submount(this->ap, path, state);
++			sm = mnts_find_submount(path);
++			if (!sm)
++				continue;
++			mnts_put_mount(sm);
+ 		}
+ 
+ 		/* Now we have found the submount we want to expire */
+ 
+ 		st_mutex_lock();
+ 
+-		if (this->state == ST_SHUTDOWN) {
++		if (this->ap->state == ST_SHUTDOWN) {
+ 			this = NULL;
+ 			st_mutex_unlock();
+ 			break;
+ 		}
+ 
+-		this->shutdown = ap->shutdown;
++		this->ap->shutdown = ap->shutdown;
+ 
+-		__st_add_task(this, state);
++		__st_add_task(this->ap, state);
+ 
+ 		st_mutex_unlock();
+-		mounts_mutex_unlock(ap);
+ 
+-		st_wait_task(this, state, 0);
++		st_wait_task(this->ap, state, 0);
+ 
+ 		/*
+ 		 * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
+ 		 * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
+ 		 * to ST_READY.
+ 		 */
+-		mounts_mutex_lock(ap);
+ 		st_mutex_lock();
+-		while ((this = __master_find_submount(ap, path))) {
++		while ((sbmnt = mnts_find_submount(path))) {
+ 			struct timespec t = { 0, 300000000 };
+ 			struct timespec r;
+ 
+-			if (this->state != ST_SHUTDOWN &&
+-			    this->state != ST_SHUTDOWN_PENDING &&
+-			    this->state != ST_SHUTDOWN_FORCE) {
++			if (sbmnt->ap->state != ST_SHUTDOWN &&
++			    sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
++			    sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
+ 				ret = 0;
++				mnts_put_mount(sbmnt);
+ 				break;
+ 			}
++			mnts_put_mount(sbmnt);
+ 
+ 			st_mutex_unlock();
+-			mounts_mutex_unlock(ap);
+ 			while (nanosleep(&t, &r) == -1 && errno == EINTR)
+ 				memcpy(&t, &r, sizeof(struct timespec));
+-			mounts_mutex_lock(ap);
+ 			st_mutex_lock();
+ 		}
+ 		st_mutex_unlock();
+ 		break;
+ 	}
+ 
+-	mounts_mutex_unlock(ap);
++	mnts_put_submount_list(&sbmnts);
+ 
+ 	return ret;
+ }
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -885,6 +885,8 @@ static struct mnt_list *mnts_alloc_mount
+ 
+ 	this->ref = 1;
+ 	INIT_HLIST_NODE(&this->hash);
++	INIT_LIST_HEAD(&this->submount);
++	INIT_LIST_HEAD(&this->submount_work);
+ done:
+ 	return this;
+ }
+@@ -967,6 +969,85 @@ void mnts_put_mount(struct mnt_list *mnt
+ 	mnts_hash_mutex_unlock();
+ }
+ 
++struct mnt_list *mnts_find_submount(const char *path)
++{
++	struct mnt_list *mnt;
++
++	mnt = mnts_lookup_mount(path);
++	if (mnt && mnt->flags & MNTS_AUTOFS)
++		return mnt;
++	mnts_put_mount(mnt);
++	return NULL;
++}
++
++struct mnt_list *mnts_add_submount(struct autofs_point *ap)
++{
++	struct mnt_list *this;
++
++	mnts_hash_mutex_lock();
++	this = mnts_get_mount(ap->path);
++	if (this) {
++		if (!this->ap)
++			this->ap = ap;
++		else if (this->ap != ap ||
++			 this->ap->parent != ap->parent) {
++			__mnts_put_mount(this);
++			mnts_hash_mutex_unlock();
++			error(ap->logopt,
++			      "conflict with submount owner: %s", ap->path);
++			goto fail;
++		}
++		this->flags |= MNTS_AUTOFS;
++		if (list_empty(&this->submount))
++			list_add_tail(&this->submount, &ap->parent->submounts);
++	}
++	mnts_hash_mutex_unlock();
++fail:
++	return this;
++}
++
++void mnts_remove_submount(const char *mp)
++{
++	struct mnt_list *this;
++
++	mnts_hash_mutex_lock();
++	this = mnts_lookup(mp);
++	if (this && this->flags & MNTS_AUTOFS) {
++		this->flags &= ~MNTS_AUTOFS;
++		this->ap = NULL;
++		list_del_init(&this->submount);
++		__mnts_put_mount(this);
++	}
++	mnts_hash_mutex_unlock();
++}
++
++void mnts_get_submount_list(struct list_head *mnts, struct autofs_point *ap)
++{
++	struct mnt_list *mnt;
++
++	mnts_hash_mutex_lock();
++	if (list_empty(&ap->submounts))
++		goto done;
++	list_for_each_entry(mnt, &ap->submounts, submount) {
++		__mnts_get_mount(mnt);
++		list_add(&mnt->submount_work, mnts);
++	}
++done:
++	mnts_hash_mutex_unlock();
++}
++
++void mnts_put_submount_list(struct list_head *mnts)
++{
++	struct mnt_list *mnt, *tmp;
++
++	mnts_hash_mutex_lock();
++	list_for_each_entry_safe(mnt, tmp, mnts, submount_work) {
++		list_del_init(&mnt->submount_work);
++		__mnts_put_mount(mnt);
++	}
++	mnts_hash_mutex_unlock();
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
+--- autofs-5.1.4.orig/modules/mount_autofs.c
++++ autofs-5.1.4/modules/mount_autofs.c
+@@ -65,6 +65,7 @@ int mount_mount(struct autofs_point *ap,
+ 	struct master_mapent *entry;
+ 	struct map_source *source;
+ 	struct autofs_point *nap;
++	struct mnt_list *mnt;
+ 	char buf[MAX_ERR_BUF];
+ 	char *options, *p;
+ 	int len, ret;
+@@ -307,6 +308,18 @@ int mount_mount(struct autofs_point *ap,
+ 		return 1;
+ 	}
+ 
++	mnt = mnts_add_submount(nap);
++	if (!mnt) {
++		crit(ap->logopt,
++		     MODPREFIX "failed to allocate mount %s", realpath);
++		handle_mounts_startup_cond_destroy(&suc);
++		mounts_mutex_unlock(ap);
++		master_free_map_source(source, 1);
++		master_free_mapent(entry);
++		return 1;
++	}
++
++
+ 	suc.ap = nap;
+ 	suc.root = mountpoint;
+ 	suc.done = 0;
+@@ -318,6 +331,7 @@ int mount_mount(struct autofs_point *ap,
+ 		     "failed to create mount handler thread for %s",
+ 		     realpath);
+ 		handle_mounts_startup_cond_destroy(&suc);
++		mnts_remove_submount(nap->path);
+ 		mounts_mutex_unlock(ap);
+ 		master_free_map_source(source, 1);
+ 		master_free_mapent(entry);
+@@ -328,6 +342,7 @@ int mount_mount(struct autofs_point *ap,
+ 		status = pthread_cond_wait(&suc.cond, &suc.mutex);
+ 		if (status) {
+ 			handle_mounts_startup_cond_destroy(&suc);
++			mnts_remove_submount(nap->path);
+ 			mounts_mutex_unlock(ap);
+ 			master_free_map_source(source, 1);
+ 			master_free_mapent(entry);
+@@ -339,6 +354,7 @@ int mount_mount(struct autofs_point *ap,
+ 		crit(ap->logopt,
+ 		     MODPREFIX "failed to create submount for %s", realpath);
+ 		handle_mounts_startup_cond_destroy(&suc);
++		mnts_remove_submount(nap->path);
+ 		mounts_mutex_unlock(ap);
+ 		master_free_map_source(source, 1);
+ 		master_free_mapent(entry);
+@@ -347,7 +363,6 @@ int mount_mount(struct autofs_point *ap,
+ 	nap->thid = thid;
+ 
+ 	ap->submnt_count++;
+-	list_add(&nap->mounts, &ap->submounts);
+ 
+ 	handle_mounts_startup_cond_destroy(&suc);
+ 	mounts_mutex_unlock(ap);
diff --git a/SOURCES/autofs-5.1.6-use-struct-mnt_list-mounted-list-for-expire.patch b/SOURCES/autofs-5.1.6-use-struct-mnt_list-mounted-list-for-expire.patch
new file mode 100644
index 0000000..91f6911
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-use-struct-mnt_list-mounted-list-for-expire.patch
@@ -0,0 +1,620 @@
+autofs-5.1.6 - use struct mnt_list mounted list for expire
+
+From: Ian Kent <raven@themaw.net>
+
+Now we are keeping track of mounted mounts using the mnt_list struct
+use it to drive the expire instead of using the system mount table.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG         |    1 
+ daemon/direct.c   |   61 +++++++----------
+ daemon/indirect.c |   66 +++++++++----------
+ include/mounts.h  |    5 -
+ lib/master.c      |   36 +---------
+ lib/mounts.c      |  185 ++++++++++++++++++++++++++++++++++++++++++++++--------
+ 6 files changed, 223 insertions(+), 131 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -129,6 +129,7 @@ xx/xx/2018 autofs-5.1.5
+ - fix remount expire.
+ - fix stale offset directories disable mount.
+ - use struct mnt_list to track mounted mounts.
++- use struct mnt_list mounted list for expire.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -77,9 +77,8 @@ static void key_mnt_params_init(void)
+ 
+ static void mnts_cleanup(void *arg)
+ {
+-	struct mnt_list *mnts = (struct mnt_list *) arg;
+-	tree_free_mnt_tree(mnts);
+-	return;
++	struct list_head *mnts = (struct list_head *) arg;
++	mnts_put_expire_list(mnts);
+ }
+ 
+ int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me)
+@@ -788,8 +787,8 @@ out_err:
+ void *expire_proc_direct(void *arg)
+ {
+ 	struct ioctl_ops *ops = get_ioctl_ops();
+-	struct mnt_list *mnts = NULL, *next;
+-	struct list_head list, *p;
++	struct mnt_list *mnt;
++	LIST_HEAD(mnts);
+ 	struct expire_args *ea;
+ 	struct expire_args ec;
+ 	struct autofs_point *ap;
+@@ -821,31 +820,24 @@ void *expire_proc_direct(void *arg)
+ 
+ 	left = 0;
+ 
+-	mnts = tree_make_mnt_tree("/");
+-	pthread_cleanup_push(mnts_cleanup, mnts);
+-
+-	/* Get a list of mounts select real ones and expire them if possible */
+-	INIT_LIST_HEAD(&list);
+-	if (!tree_get_mnt_list(mnts, &list, "/", 0)) {
+-		ec.status = 0;
+-		return NULL;
+-	}
+-
+-	list_for_each(p, &list) {
+-		next = list_entry(p, struct mnt_list, list);
+-
++	/* Get the list of real mounts and expire them if possible */
++	mnts_get_expire_list(&mnts, ap);
++	if (list_empty(&mnts))
++		goto done;
++	pthread_cleanup_push(mnts_cleanup, &mnts);
++	list_for_each_entry(mnt, &mnts, expire) {
+ 		/*
+ 		 * All direct mounts must be present in the map
+ 		 * entry cache.
+ 		 */
+ 		pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
+ 		master_source_readlock(ap->entry);
+-		me = lookup_source_mapent(ap, next->mp, LKP_DISTINCT);
++		me = lookup_source_mapent(ap, mnt->mp, LKP_DISTINCT);
+ 		pthread_cleanup_pop(1);
+ 		if (!me)
+ 			continue;
+ 
+-		if (next->flags & MNTS_AUTOFS) {
++		if (mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET)) {
+ 			struct stat st;
+ 			int ioctlfd;
+ 
+@@ -856,22 +848,17 @@ void *expire_proc_direct(void *arg)
+ 			 * one of them and pass on state change.
+ 			 */
+ 			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-			if (next->flags & MNTS_INDIRECT) {
+-				master_notify_submount(ap, next->mp, ap->state);
+-				pthread_setcancelstate(cur_state, NULL);
+-				continue;
+-			}
++			if (mnt->flags & MNTS_AUTOFS)
++				master_notify_submount(ap, mnt->mp, ap->state);
+ 
+ 			if (me->ioctlfd == -1) {
+ 				pthread_setcancelstate(cur_state, NULL);
+ 				continue;
+ 			}
+ 
+-			/* It's got a mount, deal with in the outer loop */
+-			if (is_mounted(me->key, MNTS_REAL)) {
+-				pthread_setcancelstate(cur_state, NULL);
+-				continue;
+-			}
++			/* It's got a mount, just send the expire. */
++			if (is_mounted(me->key, MNTS_REAL))
++				goto cont;
+ 
+ 			/*
+ 			 * Maybe a manual umount, repair.
+@@ -888,19 +875,19 @@ void *expire_proc_direct(void *arg)
+ 			cache_writelock(me->mc);
+ 			if (me->ioctlfd != -1 && 
+ 			    fstat(me->ioctlfd, &st) != -1 &&
+-			    !count_mounts(ap, next->mp, st.st_dev)) {
++			    !count_mounts(ap, mnt->mp, st.st_dev)) {
+ 				ops->close(ap->logopt, me->ioctlfd);
+ 				me->ioctlfd = -1;
+ 				cache_unlock(me->mc);
+-				mnts_remove_mount(next->mp, MNTS_MOUNTED);
++				mnts_remove_mount(mnt->mp, MNTS_MOUNTED);
+ 				pthread_setcancelstate(cur_state, NULL);
+ 				continue;
+ 			}
+ 			cache_unlock(me->mc);
+-
++cont:
+ 			ioctlfd = me->ioctlfd;
+ 
+-			ret = ops->expire(ap->logopt, ioctlfd, next->mp, how);
++			ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+ 			if (ret) {
+ 				left++;
+ 				pthread_setcancelstate(cur_state, NULL);
+@@ -923,10 +910,10 @@ void *expire_proc_direct(void *arg)
+ 		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
+ 			pthread_testcancel();
+ 
+-		debug(ap->logopt, "send expire to trigger %s", next->mp);
++		debug(ap->logopt, "send expire to trigger %s", mnt->mp);
+ 
+ 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-		ret = ops->expire(ap->logopt, ioctlfd, next->mp, how);
++		ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+ 		if (ret)
+ 			left++;
+ 		pthread_setcancelstate(cur_state, NULL);
+@@ -935,7 +922,7 @@ void *expire_proc_direct(void *arg)
+ 
+ 	if (left)
+ 		debug(ap->logopt, "%d remaining in %s", left, ap->path);
+-
++done:
+ 	ec.status = left;
+ 
+ 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -343,17 +343,17 @@ force_umount:
+ 
+ static void mnts_cleanup(void *arg)
+ {
+-	struct mnt_list *mnts = (struct mnt_list *) arg;
+-	free_mnt_list(mnts);
+-	return;
++	struct list_head *mnts = (struct list_head *) arg;
++	mnts_put_expire_list(mnts);
+ }
+ 
+ void *expire_proc_indirect(void *arg)
+ {
+ 	struct ioctl_ops *ops = get_ioctl_ops();
+ 	struct autofs_point *ap;
+-	struct mapent *me = NULL;
+-	struct mnt_list *mnts = NULL, *next;
++	struct mnt_list *mnt;
++	LIST_HEAD(mnts);
++	struct mapent *me;
+ 	struct expire_args *ea;
+ 	struct expire_args ec;
+ 	unsigned int how;
+@@ -385,36 +385,34 @@ void *expire_proc_indirect(void *arg)
+ 
+ 	left = 0;
+ 
+-	/* Get a list of real mounts and expire them if possible */
+-	mnts = get_mnt_list(ap->path, 0);
+-	pthread_cleanup_push(mnts_cleanup, mnts);
+-	for (next = mnts; next; next = next->next) {
++	/* Get the list of real mounts and expire them if possible */
++	mnts_get_expire_list(&mnts, ap);
++	if (list_empty(&mnts))
++		goto done;
++	pthread_cleanup_push(mnts_cleanup, &mnts);
++	list_for_each_entry(mnt, &mnts, expire) {
+ 		char *ind_key;
+ 		int ret;
+ 
+-		if (next->flags & MNTS_AUTOFS) {
++		if (mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET)) {
+ 			/*
+ 			 * If we have submounts check if this path lives below
+ 			 * one of them and pass on the state change.
+ 			 */
+ 			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-			if (next->flags & MNTS_INDIRECT)
+-				master_notify_submount(ap, next->mp, ap->state);
+-			else if (next->flags & MNTS_OFFSET) {
++			if (mnt->flags & MNTS_AUTOFS)
++				master_notify_submount(ap, mnt->mp, ap->state);
++
++			/* An offset without a real mount, check for manual umount */
++			if (mnt->flags & MNTS_OFFSET &&
++			    !is_mounted(mnt->mp, MNTS_REAL)) {
+ 				struct mnt_list *sbmnt;
+ 				struct map_source *map;
+ 				struct mapent_cache *mc = NULL;
+-				struct mapent *me = NULL;
+ 				struct stat st;
+ 
+-				/* It's got a mount, deal with in the outer loop */
+-				if (is_mounted(next->mp, MNTS_REAL)) {
+-					pthread_setcancelstate(cur_state, NULL);
+-					continue;
+-				}
+-
+ 				/* Don't touch submounts */
+-				sbmnt = mnts_find_submount(next->mp);
++				sbmnt = mnts_find_submount(mnt->mp);
+ 				if (sbmnt) {
+ 					mnts_put_mount(sbmnt);
+ 					pthread_setcancelstate(cur_state, NULL);
+@@ -427,7 +425,7 @@ void *expire_proc_indirect(void *arg)
+ 				while (map) {
+ 					mc = map->mc;
+ 					cache_writelock(mc);
+-					me = cache_lookup_distinct(mc, next->mp);
++					me = cache_lookup_distinct(mc, mnt->mp);
+ 					if (me)
+ 						break;
+ 					cache_unlock(mc);
+@@ -456,10 +454,10 @@ void *expire_proc_indirect(void *arg)
+ 
+ 				cache_unlock(mc);
+ 				master_source_unlock(ap->entry);
++				pthread_setcancelstate(cur_state, NULL);
++				continue;
+ 			}
+-
+ 			pthread_setcancelstate(cur_state, NULL);
+-			continue;
+ 		}
+ 
+ 		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
+@@ -469,7 +467,7 @@ void *expire_proc_indirect(void *arg)
+ 		 * If the mount corresponds to an offset trigger then
+ 		 * the key is the path, otherwise it's the last component.
+ 		 */
+-		ind_key = strrchr(next->mp, '/');
++		ind_key = strrchr(mnt->mp, '/');
+ 		if (ind_key)
+ 			ind_key++;
+ 
+@@ -482,7 +480,7 @@ void *expire_proc_indirect(void *arg)
+ 		 */
+ 		pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
+ 		master_source_readlock(ap->entry);
+-		me = lookup_source_mapent(ap, next->mp, LKP_DISTINCT);
++		me = lookup_source_mapent(ap, mnt->mp, LKP_DISTINCT);
+ 		if (!me && ind_key)
+ 			me = lookup_source_mapent(ap, ind_key, LKP_NORMAL);
+ 		pthread_cleanup_pop(1);
+@@ -494,10 +492,10 @@ void *expire_proc_indirect(void *arg)
+ 			cache_unlock(me->mc);
+ 		}
+ 
+-		debug(ap->logopt, "expire %s", next->mp);
++		debug(ap->logopt, "expire %s", mnt->mp);
+ 
+ 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-		ret = ops->expire(ap->logopt, ioctlfd, next->mp, how);
++		ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+ 		if (ret)
+ 			left++;
+ 		pthread_setcancelstate(cur_state, NULL);
+@@ -519,14 +517,14 @@ void *expire_proc_indirect(void *arg)
+ 	pthread_cleanup_pop(1);
+ 
+ 	count = offsets = submnts = 0;
+-	mnts = get_mnt_list(ap->path, 0);
+-	pthread_cleanup_push(mnts_cleanup, mnts);
++	mnts_get_expire_list(&mnts, ap);
++	pthread_cleanup_push(mnts_cleanup, &mnts);
+ 	/* Are there any real mounts left */
+-	for (next = mnts; next; next = next->next) {
+-		if (!(next->flags & MNTS_AUTOFS))
++	list_for_each_entry(mnt, &mnts, expire) {
++		if (!(mnt->flags & MNTS_AUTOFS))
+ 			count++;
+ 		else {
+-			if (next->flags & MNTS_INDIRECT)
++			if (mnt->flags & MNTS_INDIRECT)
+ 				submnts++;
+ 			else
+ 				offsets++;
+@@ -544,7 +542,7 @@ void *expire_proc_indirect(void *arg)
+ 	 */
+ 	if (count)
+ 		debug(ap->logopt, "%d remaining in %s", count, ap->path);
+-
++done:
+ 	ec.status = left;
+ 
+ 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -63,6 +63,8 @@ struct mnt_list {
+ 
+ 	/* List of mounts of an autofs_point */
+ 	struct list_head mount;
++	/* Mounted mounts list for expire */
++	struct list_head expire;
+ 
+ 	/* List of sub-mounts of an autofs_point */
+ 	struct autofs_point *ap;
+@@ -129,15 +131,12 @@ void mnts_put_mount(struct mnt_list *mnt
+ struct mnt_list *mnts_find_submount(const char *path);
+ struct mnt_list *mnts_add_submount(struct autofs_point *ap);
+ void mnts_remove_submount(const char *mp);
+-void mnts_get_submount_list(struct list_head *mnts, struct autofs_point *ap);
+-void mnts_put_submount_list(struct list_head *mnts);
+ struct mnt_list *mnts_find_amdmount(const char *path);
+ struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *entry);
+ void mnts_remove_amdmount(const char *mp);
+ struct mnt_list *mnts_add_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ void mnts_remove_mount(const char *mp, unsigned int flags);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+-unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name);
+--- autofs-5.1.4.orig/lib/master.c
++++ autofs-5.1.4/lib/master.c
+@@ -1133,40 +1133,17 @@ int master_submount_list_empty(struct au
+ int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
+ {
+ 	struct mnt_list *this, *sbmnt;
+-	LIST_HEAD(sbmnts);
+ 	int ret = 1;
+ 
+-	mnts_get_submount_list(&sbmnts, ap);
+-	if (list_empty(&sbmnts))
+-		return 1;
+-
+-	list_for_each_entry(this, &sbmnts, submount_work) {
+-		/* Not a submount */
+-		if (!(this->flags & MNTS_AUTOFS))
+-			continue;
+-
+-		/* path not the same */
+-		if (strcmp(this->mp, path))
+-			continue;
+-
+-		if (!master_submount_list_empty(this->ap)) {
+-			struct mnt_list *sm;
+-
+-			master_notify_submount(this->ap, path, state);
+-			sm = mnts_find_submount(path);
+-			if (!sm)
+-				continue;
+-			mnts_put_mount(sm);
+-		}
+-
+-		/* Now we have found the submount we want to expire */
+-
++	this = mnts_find_submount(path);
++	if (this) {
++		/* We have found a submount to expire */
+ 		st_mutex_lock();
+ 
+ 		if (this->ap->state == ST_SHUTDOWN) {
+ 			this = NULL;
+ 			st_mutex_unlock();
+-			break;
++			goto done;
+ 		}
+ 
+ 		this->ap->shutdown = ap->shutdown;
+@@ -1202,11 +1179,10 @@ int master_notify_submount(struct autofs
+ 			st_mutex_lock();
+ 		}
+ 		st_mutex_unlock();
+-		break;
++done:
++		mnts_put_mount(this);
+ 	}
+ 
+-	mnts_put_submount_list(&sbmnts);
+-
+ 	return ret;
+ }
+ 
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -888,6 +888,7 @@ static struct mnt_list *mnts_alloc_mount
+ 	INIT_LIST_HEAD(&this->submount);
+ 	INIT_LIST_HEAD(&this->submount_work);
+ 	INIT_LIST_HEAD(&this->amdmount);
++	INIT_LIST_HEAD(&this->expire);
+ done:
+ 	return this;
+ }
+@@ -1022,33 +1023,6 @@ void mnts_remove_submount(const char *mp
+ 	mnts_hash_mutex_unlock();
+ }
+ 
+-void mnts_get_submount_list(struct list_head *mnts, struct autofs_point *ap)
+-{
+-	struct mnt_list *mnt;
+-
+-	mnts_hash_mutex_lock();
+-	if (list_empty(&ap->submounts))
+-		goto done;
+-	list_for_each_entry(mnt, &ap->submounts, submount) {
+-		__mnts_get_mount(mnt);
+-		list_add(&mnt->submount_work, mnts);
+-	}
+-done:
+-	mnts_hash_mutex_unlock();
+-}
+-
+-void mnts_put_submount_list(struct list_head *mnts)
+-{
+-	struct mnt_list *mnt, *tmp;
+-
+-	mnts_hash_mutex_lock();
+-	list_for_each_entry_safe(mnt, tmp, mnts, submount_work) {
+-		list_del_init(&mnt->submount_work);
+-		__mnts_put_mount(mnt);
+-	}
+-	mnts_hash_mutex_unlock();
+-}
+-
+ struct mnt_list *mnts_find_amdmount(const char *path)
+ {
+ 	struct mnt_list *mnt;
+@@ -1234,6 +1208,163 @@ void mnts_set_mounted_mount(struct autof
+ 	}
+ }
+ 
++struct node {
++	struct mnt_list *mnt;
++	struct node *left;
++	struct node *right;
++};
++
++static struct node *new(struct mnt_list *mnt)
++{
++	struct node *n;
++
++	n = malloc(sizeof(struct node));
++	if (!n)
++		return NULL;
++	memset(n, 0, sizeof(struct node));
++	n->mnt = mnt;
++
++	return n;
++}
++
++static struct node *tree_root(struct mnt_list *mnt)
++{
++	struct node *n;
++
++	n = new(mnt);
++	if (!n) {
++		error(LOGOPT_ANY, "failed to allcate tree root");
++		return NULL;
++	}
++
++	return n;
++}
++
++static struct node *add_left(struct node *this, struct mnt_list *mnt)
++{
++	struct node *n;
++
++	n = new(mnt);
++	if (!n) {
++		error(LOGOPT_ANY, "failed to allcate tree node");
++		return NULL;
++	}
++	this->left = n;
++
++	return n;
++}
++
++static struct node *add_right(struct node *this, struct mnt_list *mnt)
++{
++	struct node *n;
++
++	n = new(mnt);
++	if (!n) {
++		error(LOGOPT_ANY, "failed to allcate tree node");
++		return NULL;
++	}
++	this->right = n;
++
++	return n;
++}
++
++static struct node *add_node(struct node *root, struct mnt_list *mnt)
++{
++	struct node *p, *q;
++	unsigned int mp_len;
++
++	mp_len = strlen(mnt->mp);
++
++	q = root;
++	p = root;
++
++	while (q && strcmp(mnt->mp, p->mnt->mp)) {
++		p = q;
++		if (mp_len < strlen(p->mnt->mp))
++			q = p->left;
++		else
++			q = p->right;
++	}
++
++	if (strcmp(mnt->mp, p->mnt->mp) == 0)
++		error(LOGOPT_ANY, "duplicate entry in mounts list");
++	else {
++		if (mp_len < strlen(p->mnt->mp))
++			return add_left(p, mnt);
++		else
++			return add_right(p, mnt);
++	}
++
++	return NULL;
++}
++
++static void tree_free(struct node *tree)
++{
++	if (tree->right)
++		tree_free(tree->right);
++	if (tree->left)
++		tree_free(tree->left);
++	free(tree);
++}
++
++static void traverse(struct node *node, struct list_head *mnts)
++{
++	if (node->right)
++		traverse(node->right, mnts);
++	list_add_tail(&node->mnt->expire, mnts);
++	if (node->left)
++		traverse(node->left, mnts);
++}
++
++void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
++{
++	struct mnt_list *mnt;
++	struct node *tree = NULL;
++
++	mnts_hash_mutex_lock();
++	if (list_empty(&ap->mounts))
++		goto done;
++
++	list_for_each_entry(mnt, &ap->mounts, mount) {
++		struct node *n;
++
++		__mnts_get_mount(mnt);
++
++		if (!tree) {
++			tree = tree_root(mnt);
++			if (!tree) {
++				error(LOGOPT_ANY, "failed to create expire tree root");
++				goto done;
++			}
++			continue;
++		}
++
++		n = add_node(tree, mnt);
++		if (!n) {
++			error(LOGOPT_ANY, "failed to add expire tree node");
++			tree_free(tree);
++			goto done;
++		}
++	}
++
++	traverse(tree, mnts);
++	tree_free(tree);
++done:
++	mnts_hash_mutex_unlock();
++}
++
++void mnts_put_expire_list(struct list_head *mnts)
++{
++	struct mnt_list *mnt, *tmp;
++
++	mnts_hash_mutex_lock();
++	list_for_each_entry_safe(mnt, tmp, mnts, expire) {
++		list_del_init(&mnt->expire);
++		__mnts_put_mount(mnt);
++	}
++	mnts_hash_mutex_unlock();
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/SOURCES/autofs-5.1.6-use-struct-mnt_list-to-track-mounted-mounts.patch b/SOURCES/autofs-5.1.6-use-struct-mnt_list-to-track-mounted-mounts.patch
new file mode 100644
index 0000000..4639315
--- /dev/null
+++ b/SOURCES/autofs-5.1.6-use-struct-mnt_list-to-track-mounted-mounts.patch
@@ -0,0 +1,360 @@
+autofs-5.1.6 - use struct mnt_list to track mounted mounts
+
+From: Ian Kent <raven@themaw.net>
+
+Use struct mnt_list to track mounted mounts so that it's no longer
+necessary to use the system mount table to get the list of mounted
+mounts.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 
+ daemon/automount.c |    5 ++
+ daemon/direct.c    |   19 ++++++++
+ daemon/indirect.c  |    3 +
+ include/mounts.h   |   10 ++++
+ lib/mounts.c       |  125 +++++++++++++++++++++++++++++++++++++++++++++++++----
+ 6 files changed, 154 insertions(+), 9 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -128,6 +128,7 @@ xx/xx/2018 autofs-5.1.5
+ - remove force parameter from umount_all().
+ - fix remount expire.
+ - fix stale offset directories disable mount.
++- use struct mnt_list to track mounted mounts.
+ 
+ 19/12/2017 autofs-5.1.4
+ - fix spec file url.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -677,6 +677,9 @@ int umount_multi(struct autofs_point *ap
+ 			mnts_put_mount(mnt);
+ 		}
+ 
++		/* Check for mounted mount and remove it if found */
++		mnts_remove_mount(path, MNTS_MOUNTED);
++
+ 		return 0;
+ 	}
+ 
+@@ -1719,6 +1722,8 @@ static void handle_mounts_cleanup(void *
+ 
+ 		/* Submount at ap->path belongs to parent submount list. */
+ 		mnts_remove_submount(ap->path);
++		/* Also remove from parent mounted list */
++		mnts_remove_mount(ap->path, MNTS_MOUNTED);
+ 		mnt = mnts_find_amdmount(ap->path);
+ 		if (mnt) {
+ 			mnts_remove_amdmount(ap->path);
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -606,6 +606,9 @@ force_umount:
+ 	} else
+ 		info(ap->logopt, "umounted offset mount %s", me->key);
+ 
++	if (!rv)
++		mnts_remove_mount(me->key, MNTS_OFFSET);
++
+ 	return rv;
+ }
+ 
+@@ -622,6 +625,7 @@ int mount_autofs_offset(struct autofs_po
+ 	const char *map_name = hosts_map_name;
+ 	const char *type;
+ 	char mountpoint[PATH_MAX];
++	struct mnt_list *mnt;
+ 
+ 	if (ops->version && ap->flags & MOUNT_FLAG_REMOUNT) {
+ 		ret = try_remount(ap, me, t_offset);
+@@ -635,6 +639,11 @@ int mount_autofs_offset(struct autofs_po
+ 			if (ap->state != ST_READMAP)
+ 				warn(ap->logopt,
+ 				     "trigger %s already mounted", me->key);
++			mnt = mnts_add_mount(ap, me->key, MNTS_OFFSET);
++			if (!mnt)
++				error(ap->logopt,
++				      "failed to add offset mount %s to mounted list",
++				      me->key);
+ 			return MOUNT_OFFSET_OK;
+ 		}
+ 
+@@ -757,6 +766,12 @@ int mount_autofs_offset(struct autofs_po
+ 		notify_mount_result(ap, me->key, timeout, str_offset);
+ 	ops->close(ap->logopt, ioctlfd);
+ 
++	mnt = mnts_add_mount(ap, mountpoint, MNTS_OFFSET);
++	if (!mnt)
++		error(ap->logopt,
++		      "failed to add offset mount %s to mounted list",
++		      mountpoint);
++
+ 	debug(ap->logopt, "mounted trigger %s at %s", me->key, mountpoint);
+ 
+ 	return MOUNT_OFFSET_OK;
+@@ -877,6 +892,7 @@ void *expire_proc_direct(void *arg)
+ 				ops->close(ap->logopt, me->ioctlfd);
+ 				me->ioctlfd = -1;
+ 				cache_unlock(me->mc);
++				mnts_remove_mount(next->mp, MNTS_MOUNTED);
+ 				pthread_setcancelstate(cur_state, NULL);
+ 				continue;
+ 			}
+@@ -1238,7 +1254,10 @@ static void *do_mount_direct(void *arg)
+ 		cache_unlock(mt.mc);
+ 		if (close_fd)
+ 			ops->close(ap->logopt, mt.ioctlfd);
++
+ 		info(ap->logopt, "mounted %s", mt.name);
++
++		mnts_set_mounted_mount(ap, mt.name);
+ 	} else {
+ 		/* TODO: get mount return status from lookup_nss_mount */
+ 		ops->send_fail(ap->logopt,
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -751,7 +751,10 @@ static void *do_mount_indirect(void *arg
+ 	if (status) {
+ 		ops->send_ready(ap->logopt,
+ 				ap->ioctlfd, mt.wait_queue_token);
++
+ 		info(ap->logopt, "mounted %s", buf);
++
++		mnts_set_mounted_mount(ap, mt.name);
+ 	} else {
+ 		/* TODO: get mount return status from lookup_nss_mount */
+ 		ops->send_fail(ap->logopt,
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -39,6 +39,7 @@
+ #define MNTS_DIRECT	0x0010
+ #define MNTS_OFFSET	0x0020
+ #define MNTS_AMD_MOUNT	0x0040
++#define MNTS_MOUNTED	0x0080
+ 
+ #define REMOUNT_SUCCESS		0x0000
+ #define REMOUNT_FAIL		0x0001
+@@ -60,6 +61,9 @@ struct mnt_list {
+ 	struct hlist_node hash;
+ 	unsigned int ref;
+ 
++	/* List of mounts of an autofs_point */
++	struct list_head mount;
++
+ 	/* List of sub-mounts of an autofs_point */
+ 	struct autofs_point *ap;
+ 	struct list_head submount;
+@@ -130,7 +134,13 @@ void mnts_put_submount_list(struct list_
+ struct mnt_list *mnts_find_amdmount(const char *path);
+ struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *entry);
+ void mnts_remove_amdmount(const char *mp);
++struct mnt_list *mnts_add_mount(struct autofs_point *ap, const char *name, unsigned int flags);
++void mnts_remove_mount(const char *mp, unsigned int flags);
+ struct mnt_list *get_mnt_list(const char *path, int include);
++unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
++void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
++void mnts_put_expire_list(struct list_head *mnts);
++void mnts_set_mounted_mount(struct autofs_point *ap, const char *name);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -884,6 +884,7 @@ static struct mnt_list *mnts_alloc_mount
+ 
+ 	this->ref = 1;
+ 	INIT_HLIST_NODE(&this->hash);
++	INIT_LIST_HEAD(&this->mount);
+ 	INIT_LIST_HEAD(&this->submount);
+ 	INIT_LIST_HEAD(&this->submount_work);
+ 	INIT_LIST_HEAD(&this->amdmount);
+@@ -1149,6 +1150,90 @@ done:
+ 	mnts_hash_mutex_unlock();
+ }
+ 
++struct mnt_list *mnts_add_mount(struct autofs_point *ap,
++				const char *name, unsigned int flags)
++{
++	struct mnt_list *this;
++	char *mp;
++
++	if (*name == '/') {
++		mp = strdup(name);
++		if (!mp)
++			goto fail;
++	} else {
++		int len = strlen(ap->path) + strlen(name) + 2;
++
++		mp = malloc(len);
++		if (!mp)
++			goto fail;
++		strcpy(mp, ap->path);
++		strcat(mp, "/");
++		strcat(mp, name);
++	}
++
++	mnts_hash_mutex_lock();
++	this = mnts_get_mount(mp);
++	if (this) {
++		this->flags |= flags;
++		if (list_empty(&this->mount))
++			list_add(&this->mount, &ap->mounts);
++	}
++	mnts_hash_mutex_unlock();
++	free(mp);
++
++	return this;
++fail:
++	if (mp)
++		free(mp);
++	return NULL;
++}
++
++void mnts_remove_mount(const char *mp, unsigned int flags)
++{
++	struct mnt_list *this;
++
++	mnts_hash_mutex_lock();
++	this = mnts_lookup(mp);
++	if (this && this->flags & flags) {
++		this->flags &= ~flags;
++		if (!(this->flags & (MNTS_OFFSET|MNTS_MOUNTED)))
++			list_del_init(&this->mount);
++		__mnts_put_mount(this);
++	}
++	mnts_hash_mutex_unlock();
++}
++
++void mnts_set_mounted_mount(struct autofs_point *ap, const char *name)
++{
++	struct mnt_list *mnt;
++
++	mnt = mnts_add_mount(ap, name, MNTS_MOUNTED);
++	if (!mnt) {
++		error(ap->logopt,
++		      "failed to add mount %s to mounted list", name);
++		return;
++	}
++
++	/* Offset mount failed but non-strict returns success */
++	if (mnt->flags & MNTS_OFFSET &&
++	    !is_mounted(mnt->mp, MNTS_REAL)) {
++		mnt->flags &= ~MNTS_MOUNTED;
++		mnts_put_mount(mnt);
++	}
++
++	/* Housekeeping.
++	 * Set the base type of the mounted mount.
++	 * MNTS_AUTOFS and MNTS_OFFSET are set at mount time and
++	 * are used during expire.
++	 */
++	if (!(mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET))) {
++		if (ap->type == LKP_INDIRECT)
++			mnt->flags |= MNTS_INDIRECT;
++		else
++			mnt->flags |= MNTS_DIRECT;
++	}
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
+@@ -1962,7 +2047,8 @@ void notify_mount_result(struct autofs_p
+ 	return;
+ }
+ 
+-static int do_remount_direct(struct autofs_point *ap, int fd, const char *path)
++static int do_remount_direct(struct autofs_point *ap,
++			     const unsigned int type, int fd, const char *path)
+ {
+ 	struct ioctl_ops *ops = get_ioctl_ops();
+ 	int status = REMOUNT_SUCCESS;
+@@ -1975,9 +2061,21 @@ static int do_remount_direct(struct auto
+ 		set_tsd_user_vars(ap->logopt, uid, gid);
+ 
+ 	ret = lookup_nss_mount(ap, NULL, path, strlen(path));
+-	if (ret)
++	if (ret) {
++		struct mnt_list *mnt;
++
++		/* If it's an offset mount add a mount reference */
++		if (type == t_offset) {
++			mnt = mnts_add_mount(ap, path, MNTS_OFFSET);
++			if (!mnt)
++				error(ap->logopt,
++				      "failed to add mount %s to mounted list", path);
++		}
++
++		mnts_set_mounted_mount(ap, path);
++
+ 		info(ap->logopt, "re-connected to %s", path);
+-	else {
++	} else {
+ 		status = REMOUNT_FAIL;
+ 		info(ap->logopt, "failed to re-connect %s", path);
+ 	}
+@@ -1985,7 +2083,7 @@ static int do_remount_direct(struct auto
+ 	return status;
+ }
+ 
+-static int do_remount_indirect(struct autofs_point *ap, int fd, const char *path)
++static int do_remount_indirect(struct autofs_point *ap, const unsigned int type, int fd, const char *path)
+ {
+ 	struct ioctl_ops *ops = get_ioctl_ops();
+ 	int status = REMOUNT_SUCCESS;
+@@ -2046,9 +2144,11 @@ static int do_remount_indirect(struct au
+ 		len = strlen(de[n]->d_name);
+ 
+ 		ret = lookup_nss_mount(ap, NULL, de[n]->d_name, len);
+-		if (ret)
++		if (ret) {
++			mnts_set_mounted_mount(ap, buf);
++
+ 			info(ap->logopt, "re-connected to %s", buf);
+-		else {
++		} else {
+ 			status = REMOUNT_FAIL;
+ 			info(ap->logopt, "failed to re-connect %s", buf);
+ 		}
+@@ -2149,9 +2249,9 @@ static int remount_active_mount(struct a
+ 		 * following will be broken?
+ 		 */
+ 		if (type == t_indirect)
+-			do_remount_indirect(ap, fd, path);
++			do_remount_indirect(ap, type, fd, path);
+ 		else
+-			do_remount_direct(ap, fd, path);
++			do_remount_direct(ap, type, fd, path);
+ 	}
+ 
+ 	debug(ap->logopt, "re-connected to mount %s", path);
+@@ -2389,7 +2489,7 @@ int umount_ent(struct autofs_point *ap,
+ 		 * so that we do not try to call rmdir_path on the
+ 		 * directory.
+ 		 */
+-		if (!rv && is_mounted(path, MNTS_REAL)) {
++		if (is_mounted(path, MNTS_REAL)) {
+ 			crit(ap->logopt,
+ 			     "the umount binary reported that %s was "
+ 			     "unmounted, but there is still something "
+@@ -2398,6 +2498,10 @@ int umount_ent(struct autofs_point *ap,
+ 		}
+ 	}
+ 
++	/* On success, check for mounted mount and remove it if found */
++	if (!rv)
++		mnts_remove_mount(path, MNTS_MOUNTED);
++
+ 	return rv;
+ }
+ 
+@@ -2690,6 +2794,9 @@ int umount_multi_triggers(struct autofs_
+ 		status = cache_delete_offset_list(mc, me->key);
+ 		if (status != CHE_OK)
+ 			warn(ap->logopt, "couldn't delete offset list");
++
++	       /* check for mounted mount entry and remove it if found */
++               mnts_remove_mount(root, MNTS_MOUNTED);
+ 	}
+ 
+ 	return left;
diff --git a/SOURCES/autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch b/SOURCES/autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch
new file mode 100644
index 0000000..985d984
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch
@@ -0,0 +1,122 @@
+autofs-5.1.7 - add a len field to struct autofs_point
+
+From: Ian Kent <raven@themaw.net>
+
+Add a path length field to struct autofs_point since the path length
+is needed at various times avoiding additional strlen() calls.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/lookup.c     |    2 +-
+ daemon/master.c     |    1 +
+ include/automount.h |    1 +
+ lib/mounts.c        |    6 +++---
+ modules/parse_amd.c |    4 ++--
+ modules/parse_sun.c |    4 ++--
+ 7 files changed, 11 insertions(+), 8 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -30,6 +30,7 @@
+ - fix program map multi-mount lookup after mount fail.
+ - add some multi-mount macros.
+ - remove unused functions cache_dump_multi() and cache_dump_cache().
++- add a len field to struct autofs_point.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/lookup.c
++++ autofs-5.1.4/daemon/lookup.c
+@@ -851,7 +851,7 @@ static int lookup_amd_instance(struct au
+ 		return NSS_STATUS_UNKNOWN;
+ 	}
+ 
+-	m_key = malloc(strlen(ap->path) + strlen(MM_ROOT(me)->key) + 2);
++	m_key = malloc(ap->len + strlen(MM_ROOT(me)->key) + 2);
+ 	if (!m_key) {
+ 		error(ap->logopt,
+ 		     "failed to allocate storage for search key");
+--- autofs-5.1.4.orig/daemon/master.c
++++ autofs-5.1.4/daemon/master.c
+@@ -86,6 +86,7 @@ int master_add_autofs_point(struct maste
+ 		free(ap);
+ 		return 0;
+ 	}
++	ap->len = strlen(ap->path);
+ 	ap->pref = NULL;
+ 
+ 	ap->entry = entry;
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -547,6 +547,7 @@ struct kernel_mod_version {
+ struct autofs_point {
+ 	pthread_t thid;
+ 	char *path;			/* Mount point name */
++	size_t len;			/* Length of mount point name */
+ 	mode_t mode;			/* Mount point mode */
+ 	char *pref;			/* amd prefix */
+ 	int pipefd;			/* File descriptor for pipe */
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1158,7 +1158,7 @@ struct mnt_list *mnts_add_mount(struct a
+ 		if (!mp)
+ 			goto fail;
+ 	} else {
+-		int len = strlen(ap->path) + strlen(name) + 2;
++		int len = ap->len + strlen(name) + 2;
+ 
+ 		mp = malloc(len);
+ 		if (!mp)
+@@ -2489,9 +2489,9 @@ static int rmdir_path_offset(struct auto
+ 	dir = strdup(oe->key);
+ 
+ 	if (ap->flags & MOUNT_FLAG_GHOST)
+-		split = strlen(ap->path) + strlen(MM_ROOT(oe)->key) + 1;
++		split = ap->len + strlen(MM_ROOT(oe)->key) + 1;
+ 	else
+-		split = strlen(ap->path);
++		split = ap->len;
+ 
+ 	dir[split] = '\0';
+ 	path = &dir[split + 1];
+--- autofs-5.1.4.orig/modules/parse_amd.c
++++ autofs-5.1.4/modules/parse_amd.c
+@@ -147,7 +147,7 @@ static struct substvar *add_lookup_vars(
+ 	struct mapent *me;
+ 	int len;
+ 
+-	len = strlen(ap->path) + 1 + key_len + 1;
++	len = ap->len + 1 + key_len + 1;
+ 	if (len > PATH_MAX) {
+ 		error(ap->logopt, MODPREFIX
+ 		      "error: lookup key is greater than PATH_MAX");
+@@ -1319,7 +1319,7 @@ static int do_host_mount(struct autofs_p
+ 		char *target;
+ 		size_t len;
+ 
+-		len = strlen(ap->path) + strlen(entry->rhost) + 2;
++		len = ap->len + strlen(entry->rhost) + 2;
+ 		target = malloc(len);
+ 		if (!target) {
+ 			warn(ap->logopt, MODPREFIX
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1156,7 +1156,7 @@ static int mount_subtree(struct autofs_p
+ 		mm_root = mm_key;
+ 		start = strlen(mm_key);
+ 	} else {
+-		start = strlen(ap->path) + strlen(mm_key) + 1;
++		start = ap->len + strlen(mm_key) + 1;
+ 		mm_root = alloca(start + 3);
+ 		strcpy(mm_root, ap->path);
+ 		strcat(mm_root, "/");
+@@ -1479,7 +1479,7 @@ dont_expand:
+ 			}
+ 			strcpy(m_root, name);
+ 		} else {
+-			m_root_len = strlen(ap->path) + name_len + 1;
++			m_root_len = ap->len + name_len + 1;
+ 			m_root = alloca(m_root_len + 1);
+ 			if (!m_root) {
+ 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
diff --git a/SOURCES/autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch b/SOURCES/autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch
new file mode 100644
index 0000000..11ec2f8
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch
@@ -0,0 +1,100 @@
+autofs-5.1.7 - add ext_mount_hash_mutex lock helpers
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: check_return: Calling "pthread_mutex_lock" without checking
+	  return value.
+
+Well, I use helpers to do this in many places so can't really disagree.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   26 ++++++++++++++++++++------
+ 2 files changed, 21 insertions(+), 6 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -65,6 +65,7 @@
+ - fix double free in parse_mapent().
+ - refactor lookup_prune_one_cache() a bit.
+ - cater for empty mounts list in mnts_get_expire_list().
++- add ext_mount_hash_mutex lock helpers.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -788,6 +788,20 @@ char *make_mnt_name_string(char *path)
+ 	return mnt_name;
+ }
+ 
++static void ext_mount_hash_mutex_lock(void)
++{
++	int status = pthread_mutex_lock(&ext_mount_hash_mutex);
++	if (status)
++		fatal(status);
++}
++
++static void ext_mount_hash_mutex_unlock(void)
++{
++	int status = pthread_mutex_unlock(&ext_mount_hash_mutex);
++	if (status)
++		fatal(status);
++}
++
+ static struct ext_mount *ext_mount_lookup(const char *mp)
+ {
+ 	uint32_t hval = hash(mp, HASH_SIZE(ext_mounts_hash));
+@@ -806,7 +820,7 @@ int ext_mount_add(const char *path, cons
+ 	struct ext_mount *em;
+ 	int ret = 0;
+ 
+-	pthread_mutex_lock(&ext_mount_hash_mutex);
++	ext_mount_hash_mutex_lock();
+ 
+ 	em = ext_mount_lookup(path);
+ 	if (em) {
+@@ -840,7 +854,7 @@ int ext_mount_add(const char *path, cons
+ 
+ 	ret = 1;
+ done:
+-	pthread_mutex_unlock(&ext_mount_hash_mutex);
++	ext_mount_hash_mutex_unlock();
+ 	return ret;
+ }
+ 
+@@ -849,7 +863,7 @@ int ext_mount_remove(const char *path)
+ 	struct ext_mount *em;
+ 	int ret = 0;
+ 
+-	pthread_mutex_lock(&ext_mount_hash_mutex);
++	ext_mount_hash_mutex_lock();
+ 
+ 	em = ext_mount_lookup(path);
+ 	if (!em)
+@@ -867,7 +881,7 @@ int ext_mount_remove(const char *path)
+ 		ret = 1;
+ 	}
+ done:
+-	pthread_mutex_unlock(&ext_mount_hash_mutex);
++	ext_mount_hash_mutex_unlock();
+ 	return ret;
+ }
+ 
+@@ -876,13 +890,13 @@ int ext_mount_inuse(const char *path)
+ 	struct ext_mount *em;
+ 	int ret = 0;
+ 
+-	pthread_mutex_lock(&ext_mount_hash_mutex);
++	ext_mount_hash_mutex_lock();
+ 	em = ext_mount_lookup(path);
+ 	if (!em)
+ 		goto done;
+ 	ret = em->ref;
+ done:
+-	pthread_mutex_unlock(&ext_mount_hash_mutex);
++	ext_mount_hash_mutex_unlock();
+ 	return ret;
+ }
+ 
diff --git a/SOURCES/autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch b/SOURCES/autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch
new file mode 100644
index 0000000..150a949
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch
@@ -0,0 +1,38 @@
+autofs-5.1.7 - add length check in umount_subtree_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: fixed_size_dest: You might overrun the 4097-character
+	  fixed-size string "key" by copying "me->key" without
+	  checking the length.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    5 +++++
+ 2 files changed, 6 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -55,6 +55,7 @@
+ - fix possible memory leak in master_parse().
+ - fix possible memory leak in mnts_add_amdmount().
+ - fix double unlock in parse_mount().
++- add length check in umount_subtree_mounts().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -562,6 +562,11 @@ static int umount_subtree_mounts(struct
+ 			left++;
+ 		}
+ 
++		if (me->len > PATH_MAX) {
++			crit(ap->logopt, "me->key too long for buffer");
++			return 1;
++		}
++
+ 		strcpy(key, me->key);
+ 
+ 		cache_unlock(mc);
diff --git a/SOURCES/autofs-5.1.7-add-mapent-tree-implementation.patch b/SOURCES/autofs-5.1.7-add-mapent-tree-implementation.patch
new file mode 100644
index 0000000..71e8b68
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-mapent-tree-implementation.patch
@@ -0,0 +1,167 @@
+autofs-5.1.7 - add mapent tree implementation
+
+From: Ian Kent <raven@themaw.net>
+
+Add a struct mapent basic tree implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    4 ++++
+ include/mounts.h    |    8 ++++++++
+ lib/cache.c         |    9 ++++++++-
+ lib/mounts.c        |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 71 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -32,6 +32,7 @@
+ - remove unused functions cache_dump_multi() and cache_dump_cache().
+ - add a len field to struct autofs_point.
+ - make tree implementation data independent.
++- add mapent tree implementation.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -166,10 +166,14 @@ struct mapent {
+ 	struct mapent_cache *mc;
+ 	struct map_source *source;
+ 	/* Need to know owner if we're a multi-mount */
++	struct tree_node *mm_root;
++	struct tree_node *mm_parent;
++	struct tree_node node;
+ 	struct mapent *multi;
+ 	/* Parent nesting point within multi-mount */
+ 	struct mapent *parent;
+ 	char *key;
++	size_t len;
+ 	char *mapent;
+ 	struct stack *stack;
+ 	time_t age;
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -66,6 +66,13 @@ struct tree_node {
+ #define MNT_LIST(n)		(container_of(n, struct mnt_list, node))
+ #define MNT_LIST_NODE(ptr)	((struct tree_node *) &((struct mnt_list *) ptr)->node)
+ 
++#define MAPENT(n)		(container_of(n, struct mapent, node))
++#define MAPENT_NODE(p)		((struct tree_node *) &((struct mapent *) p)->node)
++#define MAPENT_ROOT(p)		((struct tree_node *) ((struct mapent *) p)->mm_root)
++#define MAPENT_PARENT(p)	((struct tree_node *) ((struct mapent *) p)->mm_parent)
++#define MAPENT_SET_ROOT(p, r)	{ (((struct mapent *) p)->mm_root = (struct tree_node *) r); }
++#define MAPENT_SET_PARENT(p, n)	{ (((struct mapent *) p)->mm_parent = (struct tree_node *) n); }
++
+ typedef struct tree_node *(*tree_new_t) (void *ptr);
+ typedef int  (*tree_cmp_t) (struct tree_node *n, void *ptr);
+ typedef void (*tree_free_t) (struct tree_node *n);
+@@ -161,6 +168,7 @@ unsigned int mnts_has_mounted_mounts(str
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
++struct tree_node *tree_mapent_root(struct mapent *me);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -546,17 +546,21 @@ int cache_add(struct mapent_cache *mc, s
+ 	struct mapent *me, *existing = NULL;
+ 	char *pkey, *pent;
+ 	u_int32_t hashval = hash(key, mc->size);
++	size_t len;
+ 
+ 	me = (struct mapent *) malloc(sizeof(struct mapent));
+ 	if (!me)
+ 		return CHE_FAIL;
+ 
+-	pkey = malloc(strlen(key) + 1);
++	len = strlen(key);
++
++	pkey = malloc(len + 1);
+ 	if (!pkey) {
+ 		free(me);
+ 		return CHE_FAIL;
+ 	}
+ 	me->key = strcpy(pkey, key);
++	me->len = len;
+ 
+ 	if (mapent) {
+ 		pent = malloc(strlen(mapent) + 1);
+@@ -575,6 +579,9 @@ int cache_add(struct mapent_cache *mc, s
+ 	me->status = 0;
+ 	me->mc = mc;
+ 	me->source = ms;
++	me->mm_root = NULL;
++	me->mm_parent = NULL;
++	INIT_TREE_NODE(&me->node);
+ 	INIT_LIST_HEAD(&me->ino_index);
+ 	INIT_LIST_HEAD(&me->multi_list);
+ 	me->multi = NULL;
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -79,6 +79,17 @@ static struct tree_ops mnt_ops = {
+ };
+ static struct tree_ops *tree_mnt_ops = &mnt_ops;
+ 
++static struct tree_node *tree_mapent_new(void *ptr);
++static int tree_mapent_cmp(struct tree_node *n, void *ptr);
++static void tree_mapent_free(struct tree_node *n);
++
++static struct tree_ops mapent_ops = {
++	.new = tree_mapent_new,
++	.cmp = tree_mapent_cmp,
++	.free = tree_mapent_free,
++};
++static struct tree_ops *tree_mapent_ops = &mapent_ops;
++
+ unsigned int linux_version_code(void)
+ {
+ 	struct utsname my_utsname;
+@@ -1431,6 +1442,45 @@ void mnts_put_expire_list(struct list_he
+ 	mnts_hash_mutex_unlock();
+ }
+ 
++struct tree_node *tree_mapent_root(struct mapent *me)
++{
++	return tree_root(tree_mapent_ops, me);
++}
++
++static struct tree_node *tree_mapent_new(void *ptr)
++{
++	struct tree_node *n = MAPENT_NODE(ptr);
++
++	n->ops = tree_mapent_ops;
++	n->left = NULL;
++	n->right = NULL;
++
++	return n;
++}
++
++static int tree_mapent_cmp(struct tree_node *n, void *ptr)
++{
++	struct mapent *n_me = MAPENT(n);
++	size_t n_me_len = n_me->len;
++	struct mapent *me = ptr;
++	size_t me_len = me->len;
++
++	if (strncmp(me->key, n_me->key, n_me_len) == 0) {
++		if (me_len < n_me_len)
++			return -1;
++		else if (me_len > n_me_len)
++			return 1;
++	}
++	return strcmp(me->key, n_me->key);
++}
++
++static void tree_mapent_free(struct tree_node *n)
++{
++	n->ops = NULL;
++	n->left = NULL;
++	n->right = NULL;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/SOURCES/autofs-5.1.7-add-missing-description-of-null-map-option.patch b/SOURCES/autofs-5.1.7-add-missing-description-of-null-map-option.patch
new file mode 100644
index 0000000..f469d6d
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-missing-description-of-null-map-option.patch
@@ -0,0 +1,51 @@
+autofs-5.1.7 - add missing desciption of null map option
+
+From: Ian Kent <raven@themaw.net>
+
+The description of how the -null master map option behaves is
+mising from auto.master(5).
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG            |    1 +
+ man/auto.master.5.in |   19 +++++++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -74,6 +74,7 @@
+ - fix hosts map offset order.
+ - fix direct mount deadlock.
+ - fix lookup_prune_one_cache() refactoring change.
++- add missing description of null map option.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/man/auto.master.5.in
++++ autofs-5.1.4/man/auto.master.5.in
+@@ -263,6 +263,25 @@ accessing /net/myserver will mount expor
+ NOTE: mounts done from a hosts map will be mounted with the "nosuid,nodev,intr" options
+ unless overridden by explicitly specifying the "suid", "dev" or "nointr" options in the
+ master map entry.
++.SH BUILTIN MAP \-null
++If "\-null" is given as the map it is used to tell automount(8) to ignore a subsequent
++master map entry with the given path.
++.P
++It can only be used for paths that appear in the master map (or in direct mount maps).
++.P
++An indirect mount map top level mount point path can be nulled. If so no mounts from
++the nulled mount are performed (essentially it isn't mounted).
++.P
++Direct mount map path entries can be nulled. Since they must be present at startup
++they are (notionally) part of the master map.
++.P
++A nulled master map entry path will ignore a single subsequent matching entry. Any
++matching entry following that will be treated as it normally would be. An example
++use of this is allowing local master map entries to override remote ones.
++.P
++NOTE: If a duplicate master map entry path is seen (excluding paths of null entries)
++it will be ignored and noted in the log, that is the first encountered master map
++entry is used unless there is a corresponding null entry.
+ .SH LDAP MAPS
+ If the map type \fBldap\fP is specified the mapname is of the form
+ \fB[//servername/]dn\fP, where the optional \fBservername\fP is
diff --git a/SOURCES/autofs-5.1.7-add-missing-free-in-handle_mounts.patch b/SOURCES/autofs-5.1.7-add-missing-free-in-handle_mounts.patch
new file mode 100644
index 0000000..f320006
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-missing-free-in-handle_mounts.patch
@@ -0,0 +1,38 @@
+autofs-5.1.7 - add missing free in handle_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: error[doubleFree]: Memory pointed to by 'root' is freed twice
+
+No it's not, but root isn't freed before the fatal call which crashes
+automount so add a free() before the fatal() call.
+
+It appears Coverity doesn't recognise pthread_exit() as an exit condition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    2 ++
+ 2 files changed, 3 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -50,6 +50,7 @@
+ - check for offset with no mount location.
+ - remove mounts_mutex.
+ - remove unused variable from get_exports().
++- add missing free in handle_mounts().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -1917,6 +1917,8 @@ void *handle_mounts(void *arg)
+ 	status = pthread_mutex_lock(&suc->mutex);
+ 	if (status) {
+ 		logerr("failed to lock startup condition mutex!");
++		if (root)
++			free(root);
+ 		fatal(status);
+ 	}
+ 
diff --git a/SOURCES/autofs-5.1.7-add-mount-and-umount-offsets-functions.patch b/SOURCES/autofs-5.1.7-add-mount-and-umount-offsets-functions.patch
new file mode 100644
index 0000000..d35dbbd
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-mount-and-umount-offsets-functions.patch
@@ -0,0 +1,304 @@
+autofs-5.1.7 - add mount and umount offsets functions
+
+From: Ian Kent <raven@themaw.net>
+
+Add tree_mapent_mount_offsets() and tree_mapent_umount_offsets() to
+the mapent tree handling implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 
+ include/mounts.h |    2 
+ lib/mounts.c     |  260 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 263 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -39,6 +39,7 @@
+ - fix mount_fullpath().
+ - add tree_mapent_cleanup_offsets().
+ - add set_offset_tree_catatonic().
++- add mount and umount offsets functions.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -172,6 +172,8 @@ struct tree_node *tree_mapent_root(struc
+ int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ void tree_mapent_cleanup_offsets(struct mapent *oe);
++int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict);
++int tree_mapent_umount_offsets(struct mapent *oe, int nonstrict);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1692,6 +1692,266 @@ void tree_mapent_cleanup_offsets(struct
+ 	}
+ }
+ 
++static int tree_mapent_rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
++{
++	struct mapent *mm_root = MAPENT(MAPENT_ROOT(oe));
++	char *dir, *path;
++	unsigned int split;
++	int ret;
++
++	if (ap->type == LKP_DIRECT)
++		return rmdir_path(ap, oe->key, mm_root->dev);
++
++	dir = strdup(oe->key);
++
++	if (ap->flags & MOUNT_FLAG_GHOST)
++		split = ap->len + mm_root->len + 1;
++	else
++		split = ap->len;
++
++	dir[split] = '\0';
++	path = &dir[split + 1];
++
++	if (chdir(dir) == -1) {
++		error(ap->logopt, "failed to chdir to %s", dir);
++		free(dir);
++		return -1;
++	}
++
++	ret = rmdir_path(ap, path, ap->dev);
++
++	free(dir);
++
++	if (chdir("/") == -1)
++		error(ap->logopt, "failed to chdir to /");
++
++	return ret;
++}
++
++static int tree_mapent_mount_offset(struct mapent *oe, void *ptr)
++{
++	struct traverse_subtree_context *ctxt = ptr;
++	struct autofs_point *ap = ctxt->ap;
++	int ret;
++
++	debug(ap->logopt, "mount offset %s", oe->key);
++
++	ret = mount_autofs_offset(ap, oe);
++	if (ret < MOUNT_OFFSET_OK) {
++		if (ret != MOUNT_OFFSET_IGNORE) {
++			warn(ap->logopt, "failed to mount offset");
++			return 0;
++		} else {
++			debug(ap->logopt,
++			      "ignoring \"nohide\" trigger %s", oe->key);
++			/*
++			 * Ok, so we shouldn't modify the mapent but
++			 * mount requests are blocked at a point above
++			 * this and expire only uses the mapent key or
++			 * holds the cache write lock.
++			 */
++			free(oe->mapent);
++			oe->mapent = NULL;
++		}
++	}
++
++	return 1;
++}
++
++static int tree_mapent_umount_offset(struct mapent *oe, void *ptr)
++{
++	struct traverse_subtree_context *ctxt = ptr;
++	struct autofs_point *ap = ctxt->ap;
++	int ret = 1;
++
++	/*
++	 * Check for and umount subtree offsets resulting from
++	 * nonstrict mount fail.
++	 */
++	ret = tree_mapent_umount_offsets(oe, ctxt->strict);
++	if (!ret)
++		return 0;
++
++	/*
++	 * If an offset that has an active mount has been removed
++	 * from the multi-mount we don't want to attempt to trigger
++	 * mounts for it. Obviously this is because it has been
++	 * removed, but less obvious is the potential strange
++	 * behaviour that can result if we do try and mount it
++	 * again after it's been expired. For example, if an NFS
++	 * file system is no longer exported and is later umounted
++	 * it can be mounted again without any error message but
++	 * shows as an empty directory. That's going to confuse
++	 * people for sure.
++	 *
++	 * If the mount cannot be umounted (the process is now
++	 * using a stale mount) the offset needs to be invalidated
++	 * so no further mounts will be attempted but the offset
++	 * cache entry must remain so expires can continue to
++	 * attempt to umount it. If the mount can be umounted and
++	 * the offset is removed, at least for NFS we will get
++	 * ESTALE errors when attempting list the directory.
++	 */
++	if (oe->ioctlfd != -1 ||
++	    is_mounted(oe->key, MNTS_REAL)) {
++		if (umount_ent(ap, oe->key) &&
++		    is_mounted(oe->key, MNTS_REAL)) {
++			debug(ap->logopt,
++			      "offset %s has active mount, invalidate",
++			      oe->key);
++			/*
++			 * Ok, so we shouldn't modify the mapent but
++			 * mount requests are blocked at a point above
++			 * this and expire only uses the mapent key or
++			 * holds the cache write lock.
++			 */
++			if (oe->mapent) {
++				free(oe->mapent);
++				oe->mapent = NULL;
++			}
++			return 0;
++		}
++	}
++
++	/* Don't bother if there's noting to umount. */
++	if (!is_mounted(oe->key, MNTS_AUTOFS))
++		goto done;
++
++	debug(ap->logopt, "umount offset %s", oe->key);
++
++	if (umount_autofs_offset(ap, oe)) {
++		warn(ap->logopt, "failed to umount offset");
++		ret = 0;
++	} else {
++		struct stat st;
++		int ret;
++
++		if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
++			goto done;
++
++		/*
++		 * An error due to partial directory removal is
++		 * ok so only try and remount the offset if the
++		 * actual mount point still exists.
++		 */
++		ret = tree_mapent_rmdir_path_offset(ap, oe);
++		if (ret == -1 && !stat(oe->key, &st)) {
++			ret = tree_mapent_mount_offset(oe, ctxt);
++			/* But we did origianlly create this */
++			oe->flags |= MOUNT_FLAG_DIR_CREATED;
++		}
++	}
++done:
++	return ret;
++}
++
++static int tree_mapent_mount_offsets_work(struct tree_node *n, void *ptr)
++{
++	struct traverse_subtree_context *ctxt = ptr;
++	struct mapent *oe = MAPENT(n);
++	struct mapent *mm_root = MAPENT(MAPENT_ROOT(oe));
++	struct autofs_point *ap = ctxt->ap;
++	int ret;
++
++	if (!oe->mapent)
++		return 1;
++
++	/* Stale offset, no longer present in the mapent */
++	if (oe->age != mm_root->age) {
++		/* Best effort */
++		tree_mapent_umount_offset(oe, ctxt);
++		return 1;
++	}
++
++	ret = tree_mapent_mount_offset(oe, ctxt);
++
++	/*
++	 * If re-constructing a multi-mount it's necessary to walk
++	 * into nested mounts, unlike the usual "mount only what's
++	 * needed as you go" behavior.
++	 */
++	if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
++		if (oe->ioctlfd != -1 ||
++		    is_mounted(oe->key, MNTS_REAL))
++			/* Best effort */
++			tree_mapent_mount_offsets(oe, !ctxt->strict);
++	}
++
++	return ret;
++}
++
++int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict)
++{
++	struct tree_node *base = MAPENT_NODE(oe);
++	struct traverse_subtree_context ctxt = {
++		.ap = oe->mc->ap,
++		.base = base,
++		.strict = !nonstrict,
++	};
++
++	return tree_mapent_traverse_subtree(base,
++				tree_mapent_mount_offsets_work, &ctxt);
++}
++
++static int tree_mapent_umount_offsets_work(struct tree_node *n, void *ptr)
++{
++	struct mapent *oe = MAPENT(n);
++
++	return tree_mapent_umount_offset(oe, ptr);
++}
++
++int tree_mapent_umount_offsets(struct mapent *oe, int nonstrict)
++{
++	struct tree_node *base = MAPENT_NODE(oe);
++	struct autofs_point *ap = oe->mc->ap;
++	struct traverse_subtree_context ctxt = {
++		.ap = ap,
++		.base = base,
++		.strict = !nonstrict,
++	};
++	int ret;
++
++	ret = tree_mapent_traverse_subtree(base,
++				tree_mapent_umount_offsets_work, &ctxt);
++	if (ret && tree_mapent_is_root(oe)) {
++		char mp[PATH_MAX + 1];
++
++		/*
++		 * The map entry cache stores mapent keys. For indirect
++		 * mount maps they are single direcory components so when
++		 * one of these keys is the root of a multi-mount the mount
++		 * path must be constructed.
++		 */
++		if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key)) {
++			error(ap->logopt, "mount path is too long");
++			return 0;
++		}
++
++		/*
++		 * Special case.
++		 * If we can't umount the root container then we can't
++		 * delete the offsets from the cache and we need to put
++		 * the offset triggers back.
++		 */
++		if (is_mounted(mp, MNTS_REAL)) {
++			info(ap->logopt, "unmounting dir = %s", mp);
++			if (umount_ent(ap, mp) &&
++			    is_mounted(mp, MNTS_REAL)) {
++				if (!tree_mapent_mount_offsets(oe, 1))
++					warn(ap->logopt,
++					     "failed to remount offset triggers");
++				return 0;
++			}
++		}
++
++		/* check for mounted mount entry and remove it if found */
++		mnts_remove_mount(mp, MNTS_MOUNTED);
++
++	}
++
++	return ret;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/SOURCES/autofs-5.1.7-add-set_offset_tree_catatonic.patch b/SOURCES/autofs-5.1.7-add-set_offset_tree_catatonic.patch
new file mode 100644
index 0000000..11761b3
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-set_offset_tree_catatonic.patch
@@ -0,0 +1,46 @@
+autofs-5.1.7 - add set_offset_tree_catatonic()
+
+From: Ian Kent <raven@themaw.net>
+
+Add tree mapent support function set_offset_tree_catatonic().
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   15 +++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -38,6 +38,7 @@
+ - add tree_mapent_traverse_subtree().
+ - fix mount_fullpath().
+ - add tree_mapent_cleanup_offsets().
++- add set_offset_tree_catatonic().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2574,6 +2574,21 @@ static int set_mount_catatonic(struct au
+ 	return 0;
+ }
+ 
++static int set_offset_tree_catatonic_work(struct tree_node *n, void *ptr)
++{
++	struct mapent *me = MAPENT(n);
++	struct autofs_point *ap = me->mc->ap;
++
++	set_mount_catatonic(ap, me, me->ioctlfd);
++
++	return 1;
++}
++
++static void set_offset_tree_catatonic(struct autofs_point *ap, struct mapent *me)
++{
++	tree_traverse_inorder(MAPENT_ROOT(me), set_offset_tree_catatonic_work, NULL);
++}
++
+ static void set_multi_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+ {
+ 	if (!list_empty(&me->multi_list)) {
diff --git a/SOURCES/autofs-5.1.7-add-some-multi-mount-macros.patch b/SOURCES/autofs-5.1.7-add-some-multi-mount-macros.patch
new file mode 100644
index 0000000..cfcc693
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-some-multi-mount-macros.patch
@@ -0,0 +1,522 @@
+autofs-5.1.7 - add some multi-mount macros
+
+From: Ian Kent <raven@themaw.net>
+
+Add convienience macros IS_MM() to check is a mapent is part of a
+multi-mount, IS_MM_ROOT() to check if a mapent is the root of a
+multi-mount tree and MM_ROOT() to return the multi-mount root mapent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                |    1 +
+ daemon/automount.c       |   14 +++++++-------
+ daemon/direct.c          |    6 +++---
+ daemon/lookup.c          |   10 +++++-----
+ include/automount.h      |    5 +++++
+ lib/cache.c              |   30 +++++++++++++++---------------
+ lib/mounts.c             |   14 +++++++-------
+ modules/lookup_file.c    |    4 ++--
+ modules/lookup_hosts.c   |    4 ++--
+ modules/lookup_ldap.c    |    4 ++--
+ modules/lookup_nisplus.c |    4 ++--
+ modules/lookup_program.c |    4 ++--
+ modules/lookup_sss.c     |    4 ++--
+ modules/lookup_yp.c      |    4 ++--
+ modules/parse_sun.c      |   12 ++++++------
+ 15 files changed, 63 insertions(+), 57 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -28,6 +28,7 @@
+ - don't pass root to do_mount_autofs_offset().
+ - rename tree implementation functions.
+ - fix program map multi-mount lookup after mount fail.
++- add some multi-mount macros.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -545,27 +545,27 @@ static int umount_subtree_mounts(struct
+ 
+ 	if (me) {
+ 		mc = me->mc;
+-		is_mm_root = (me->multi == me);
++		is_mm_root = IS_MM_ROOT(me);
+ 	}
+ 
+ 	left = 0;
+ 
+-	if (me && me->multi) {
++	if (me && IS_MM(me)) {
+ 		char root[PATH_MAX + 1];
+ 		char key[PATH_MAX + 1];
+ 		struct mapent *tmp;
+ 		int status;
+ 		char *base;
+ 
+-		if (!strchr(me->multi->key, '/'))
++		if (!strchr(MM_ROOT(me)->key, '/'))
+ 			/* Indirect multi-mount root */
+ 			/* sprintf okay - if it's mounted, it's
+ 			 * PATH_MAX or less bytes */
+-			sprintf(root, "%s/%s", ap->path, me->multi->key);
++			sprintf(root, "%s/%s", ap->path, MM_ROOT(me)->key);
+ 		else
+-			strcpy(root, me->multi->key);
++			strcpy(root, MM_ROOT(me)->key);
+ 
+-		if (is_mm_root)
++		if (IS_MM_ROOT(me))
+ 			base = NULL;
+ 		else
+ 			base = me->key + strlen(root);
+@@ -588,7 +588,7 @@ static int umount_subtree_mounts(struct
+ 			return 0;
+ 		}
+ 
+-		if (!left && is_mm_root) {
++		if (!left && IS_MM_ROOT(me)) {
+ 			status = cache_delete_offset_list(mc, me->key);
+ 			if (status != CHE_OK) {
+ 				warn(ap->logopt, "couldn't delete offset list");
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -686,7 +686,7 @@ int mount_autofs_offset(struct autofs_po
+ 			 * a mount that has been automatically mounted by
+ 			 * the kernel NFS client.
+ 			 */
+-			if (me->multi != me &&
++			if (!IS_MM_ROOT(me) &&
+ 			    is_mounted(me->key, MNTS_REAL))
+ 				return MOUNT_OFFSET_IGNORE;
+ 
+@@ -1220,11 +1220,11 @@ static void *do_mount_direct(void *arg)
+ 			 * for direct mount multi-mounts with no real mount at
+ 			 * their base so they will be expired.
+ 			 */
+-			if (close_fd && me == me->multi)
++			if (close_fd && IS_MM_ROOT(me))
+ 				close_fd = 0;
+ 			if (!close_fd)
+ 				me->ioctlfd = mt.ioctlfd;
+-			if (me->multi && me->multi != me)
++			if (IS_MM(me) && !IS_MM_ROOT(me))
+ 				flags |= MNTS_OFFSET;
+ 		}
+ 		ops->send_ready(ap->logopt, mt.ioctlfd, mt.wait_queue_token);
+--- autofs-5.1.4.orig/daemon/lookup.c
++++ autofs-5.1.4/daemon/lookup.c
+@@ -756,7 +756,7 @@ int lookup_ghost(struct autofs_point *ap
+ 					goto next;
+ 
+ 				/* It's a busy multi-mount - leave till next time */
+-				if (list_empty(&me->multi_list))
++				if (IS_MM(me))
+ 					error(ap->logopt,
+ 					      "invalid key %s", me->key);
+ 				goto next;
+@@ -846,12 +846,12 @@ static int lookup_amd_instance(struct au
+ 	char *m_key;
+ 
+ 	me = cache_lookup_distinct(map->mc, name);
+-	if (!me || !me->multi) {
++	if (!me || !IS_MM(me)) {
+ 		error(ap->logopt, "expected multi mount entry not found");
+ 		return NSS_STATUS_UNKNOWN;
+ 	}
+ 
+-	m_key = malloc(strlen(ap->path) + strlen(me->multi->key) + 2);
++	m_key = malloc(strlen(ap->path) + strlen(MM_ROOT(me)->key) + 2);
+ 	if (!m_key) {
+ 		error(ap->logopt,
+ 		     "failed to allocate storage for search key");
+@@ -860,7 +860,7 @@ static int lookup_amd_instance(struct au
+ 
+ 	strcpy(m_key, ap->path);
+ 	strcat(m_key, "/");
+-	strcat(m_key, me->multi->key);
++	strcat(m_key, MM_ROOT(me)->key);
+ 
+ 	mnt = mnts_find_amdmount(m_key);
+ 	free(m_key);
+@@ -1363,7 +1363,7 @@ void lookup_prune_one_cache(struct autof
+ 			 * created on demand and managed by expire and don't
+ 			 * prune the multi-map owner map entry.
+ 			 */
+-			if (*me->key == '/' || me->multi == me) {
++			if (*me->key == '/' || IS_MM_ROOT(me)) {
+ 				me = cache_enumerate(mc, me);
+ 				continue;
+ 			}
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -183,6 +183,11 @@ struct mapent {
+ 	ino_t ino;
+ };
+ 
++#define IS_MM(me)	(me->multi)
++#define IS_MM_ROOT(me)	(me->multi == me)
++#define MM_ROOT(me)	(me->multi)
++#define MM_PARENT(me)	(me->parent)
++
+ void cache_lock_cleanup(void *arg);
+ void cache_readlock(struct mapent_cache *mc);
+ void cache_writelock(struct mapent_cache *mc);
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -374,7 +374,7 @@ struct mapent *cache_lookup_first(struct
+ 
+ 		while (me) {
+ 			/* Multi mount entries are not primary */
+-			if (me->multi && me->multi != me) {
++			if (IS_MM(me) && !IS_MM_ROOT(me)) {
+ 				me = me->next;
+ 				continue;
+ 			}
+@@ -397,7 +397,7 @@ struct mapent *cache_lookup_next(struct
+ 	this = me->next;
+ 	while (this) {
+ 		/* Multi mount entries are not primary */
+-		if (this->multi && this->multi != this) {
++		if (IS_MM(this) && !IS_MM_ROOT(this)) {
+ 			this = this->next;
+ 			continue;
+ 		}
+@@ -413,7 +413,7 @@ struct mapent *cache_lookup_next(struct
+ 
+ 			while (this) {
+ 				/* Multi mount entries are not primary */
+-				if (this->multi && this->multi != this) {
++				if (IS_MM(this) && !IS_MM_ROOT(this)) {
+ 					this = this->next;
+ 					continue;
+ 				}
+@@ -435,7 +435,7 @@ struct mapent *cache_lookup_key_next(str
+ 	next = me->next;
+ 	while (next) {
+ 		/* Multi mount entries are not primary */
+-		if (me->multi && me->multi != me)
++		if (IS_MM(me) && !IS_MM_ROOT(me))
+ 			continue;
+ 		if (!strcmp(me->key, next->key))
+ 			return next;
+@@ -706,7 +706,7 @@ int cache_update_offset(struct mapent_ca
+ 	me = cache_lookup_distinct(mc, key);
+ 	if (me) {
+ 		cache_add_ordered_offset(me, &owner->multi_list);
+-		me->multi = owner;
++		MM_ROOT(me) = owner;
+ 		goto done;
+ 	}
+ 	ret = CHE_FAIL;
+@@ -784,14 +784,14 @@ int cache_set_offset_parent(struct mapen
+ 	this = cache_lookup_distinct(mc, offset);
+ 	if (!this)
+ 		return 0;
+-	if (!this->multi)
++	if (!IS_MM(this))
+ 		return 0;
+ 
+ 	parent = get_offset_parent(mc, offset);
+ 	if (parent)
+ 		this->parent = parent;
+ 	else
+-		this->parent = this->multi;
++		this->parent = MM_ROOT(this);
+ 
+ 	return 1;
+ }
+@@ -849,7 +849,7 @@ int cache_delete_offset(struct mapent_ca
+ 		return CHE_FAIL;
+ 
+ 	if (strcmp(key, me->key) == 0) {
+-		if (me->multi && me->multi == me)
++		if (IS_MM(me) && IS_MM_ROOT(me))
+ 			return CHE_FAIL;
+ 		mc->hash[hashval] = me->next;
+ 		goto delete;
+@@ -859,7 +859,7 @@ int cache_delete_offset(struct mapent_ca
+ 		pred = me;
+ 		me = me->next;
+ 		if (strcmp(key, me->key) == 0) {
+-			if (me->multi && me->multi == me)
++			if (IS_MM(me) && IS_MM_ROOT(me))
+ 				return CHE_FAIL;
+ 			pred->next = me->next;
+ 			goto delete;
+@@ -897,7 +897,7 @@ int cache_delete(struct mapent_cache *mc
+ 		me = me->next;
+ 		if (strcmp(key, me->key) == 0) {
+ 			struct stack *s = me->stack;
+-			if (me->multi && !list_empty(&me->multi_list)) {
++			if (IS_MM(me)) {
+ 				ret = CHE_FAIL;
+ 				goto done;
+ 			}
+@@ -926,7 +926,7 @@ int cache_delete(struct mapent_cache *mc
+ 
+ 	if (strcmp(key, me->key) == 0) {
+ 		struct stack *s = me->stack;
+-		if (me->multi && !list_empty(&me->multi_list)) {
++		if (IS_MM(me)) {
+ 			ret = CHE_FAIL;
+ 			goto done;
+ 		}
+@@ -965,7 +965,7 @@ int cache_delete_offset_list(struct mape
+ 		return CHE_FAIL;
+ 
+ 	/* Not offset list owner */
+-	if (me->multi != me)
++	if (!IS_MM_ROOT(me))
+ 		return CHE_FAIL;
+ 
+ 	head = &me->multi_list;
+@@ -986,13 +986,13 @@ int cache_delete_offset_list(struct mape
+ 		this = list_entry(next, struct mapent, multi_list);
+ 		next = next->next;
+ 		list_del_init(&this->multi_list);
+-		this->multi = NULL;
++		MM_ROOT(this) = NULL;
+ 		debug(logopt, "deleting offset key %s", this->key);
+ 		status = cache_delete(mc, this->key);
+ 		if (status == CHE_FAIL) {
+ 			warn(logopt,
+ 			     "failed to delete offset %s", this->key);
+-			this->multi = me;
++			MM_ROOT(this) = me;
+ 			/* TODO: add list back in */
+ 			remain++;
+ 		}
+@@ -1000,7 +1000,7 @@ int cache_delete_offset_list(struct mape
+ 
+ 	if (!remain) {
+ 		list_del_init(&me->multi_list);
+-		me->multi = NULL;
++		MM_ROOT(me) = NULL;
+ 	}
+ 
+ 	if (remain)
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2159,7 +2159,7 @@ int try_remount(struct autofs_point *ap,
+ 	} else {
+ 		me->flags &= ~MOUNT_FLAG_DIR_CREATED;
+ 		if (type == t_offset) {
+-			if (!is_mounted(me->parent->key, MNTS_REAL))
++			if (!is_mounted(MM_PARENT(me)->key, MNTS_REAL))
+ 				me->flags |= MOUNT_FLAG_DIR_CREATED;
+ 		}
+ 	}
+@@ -2306,7 +2306,7 @@ void set_indirect_mount_tree_catatonic(s
+ 				goto next;
+ 
+ 			/* Only need to set offset mounts catatonic */
+-			if (me->multi && me->multi == me)
++			if (IS_MM(me) && IS_MM_ROOT(me))
+ 				set_multi_mount_tree_catatonic(ap, me);
+ next:
+ 			me = cache_enumerate(mc, me);
+@@ -2326,7 +2326,7 @@ next:
+ void set_direct_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+ {
+ 	/* Set offset mounts catatonic for this mapent */
+-	if (me->multi && me->multi == me)
++	if (IS_MM(me) && IS_MM_ROOT(me))
+ 		set_multi_mount_tree_catatonic(ap, me);
+ 	set_mount_catatonic(ap, me, me->ioctlfd);
+ }
+@@ -2484,12 +2484,12 @@ static int rmdir_path_offset(struct auto
+ 	int ret;
+ 
+ 	if (ap->type == LKP_DIRECT)
+-		return rmdir_path(ap, oe->key, oe->multi->dev);
++		return rmdir_path(ap, oe->key, MM_ROOT(oe)->dev);
+ 
+ 	dir = strdup(oe->key);
+ 
+ 	if (ap->flags & MOUNT_FLAG_GHOST)
+-		split = strlen(ap->path) + strlen(oe->multi->key) + 1;
++		split = strlen(ap->path) + strlen(MM_ROOT(oe)->key) + 1;
+ 	else
+ 		split = strlen(ap->path);
+ 
+@@ -2684,7 +2684,7 @@ int mount_multi_triggers(struct autofs_p
+ 		oe = cache_lookup_distinct(me->mc, key);
+ 		if (!oe || !oe->mapent)
+ 			goto cont;
+-		if (oe->age != me->multi->age) {
++		if (oe->age != MM_ROOT(me)->age) {
+ 			/* Best effort */
+ 			do_umount_offset(ap, oe, root, start);
+ 			goto cont;
+@@ -2718,7 +2718,7 @@ int umount_multi_triggers(struct autofs_
+ 
+ 	left = do_umount_multi_triggers(ap, me, root, start, base);
+ 
+-	if (!left && me->multi == me) {
++	if (!left && IS_MM_ROOT(me)) {
+ 		/*
+ 		 * Special case.
+ 		 * If we can't umount the root container then we can't
+--- autofs-5.1.4.orig/modules/lookup_file.c
++++ autofs-5.1.4/modules/lookup_file.c
+@@ -1217,8 +1217,8 @@ int lookup_mount(struct autofs_point *ap
+ 
+ 		cache_readlock(mc);
+ 		me = cache_lookup_distinct(mc, key);
+-		if (me && me->multi)
+-			lkp_key = strdup(me->multi->key);
++		if (me && IS_MM(me))
++			lkp_key = strdup(MM_ROOT(me)->key);
+ 		else if (!ap->pref)
+ 			lkp_key = strdup(key);
+ 		else {
+--- autofs-5.1.4.orig/modules/lookup_hosts.c
++++ autofs-5.1.4/modules/lookup_hosts.c
+@@ -177,7 +177,7 @@ static void update_hosts_mounts(struct a
+ 	me = cache_lookup_first(mc);
+ 	while (me) {
+ 		/* Hosts map entry not yet expanded or already expired */
+-		if (!me->multi)
++		if (!IS_MM(me))
+ 			goto next;
+ 
+ 		debug(ap->logopt, MODPREFIX "get list of exports for %s", me->key);
+@@ -200,7 +200,7 @@ next:
+ 		 * Hosts map entry not yet expanded, already expired
+ 		 * or not the base of the tree
+ 		 */
+-		if (!me->multi || me->multi != me)
++		if (!IS_MM(me) || !IS_MM_ROOT(me))
+ 			goto cont;
+ 
+ 		debug(ap->logopt, MODPREFIX
+--- autofs-5.1.4.orig/modules/lookup_ldap.c
++++ autofs-5.1.4/modules/lookup_ldap.c
+@@ -3718,8 +3718,8 @@ int lookup_mount(struct autofs_point *ap
+ 	if (ap->type == LKP_INDIRECT && *key != '/') {
+ 		cache_readlock(mc);
+ 		me = cache_lookup_distinct(mc, key);
+-		if (me && me->multi)
+-			lkp_key = strdup(me->multi->key);
++		if (me && IS_MM(me))
++			lkp_key = strdup(MM_ROOT(me)->key);
+ 		else if (!ap->pref)
+ 			lkp_key = strdup(key);
+ 		else {
+--- autofs-5.1.4.orig/modules/lookup_nisplus.c
++++ autofs-5.1.4/modules/lookup_nisplus.c
+@@ -740,8 +740,8 @@ int lookup_mount(struct autofs_point *ap
+ 	if (ap->type == LKP_INDIRECT && *key != '/') {
+ 		cache_readlock(mc);
+ 		me = cache_lookup_distinct(mc, key);
+-		if (me && me->multi)
+-			lkp_key = strdup(me->multi->key);
++		if (me && IS_MM(me))
++			lkp_key = strdup(MM_ROOT(me)->key);
+ 		else if (!ap->pref)
+ 			lkp_key = strdup(key);
+ 		else {
+--- autofs-5.1.4.orig/modules/lookup_program.c
++++ autofs-5.1.4/modules/lookup_program.c
+@@ -664,7 +664,7 @@ int lookup_mount(struct autofs_point *ap
+ 				 name_len, ent, ctxt->parse->context);
+ 			goto out_free;
+ 		} else {
+-			if (me->multi && me->multi != me) {
++			if (IS_MM(me) && !IS_MM_ROOT(me)) {
+ 				cache_unlock(mc);
+ 				warn(ap->logopt, MODPREFIX
+ 				     "unexpected lookup for active multi-mount"
+@@ -675,7 +675,7 @@ int lookup_mount(struct autofs_point *ap
+ 			cache_writelock(mc);
+ 			me = cache_lookup_distinct(mc, name);
+ 			if (me) {
+-				if (me->multi)
++				if (IS_MM(me))
+ 					cache_delete_offset_list(mc, name);
+ 				cache_delete(mc, name);
+ 			}
+--- autofs-5.1.4.orig/modules/lookup_sss.c
++++ autofs-5.1.4/modules/lookup_sss.c
+@@ -1073,8 +1073,8 @@ int lookup_mount(struct autofs_point *ap
+ 
+ 		cache_readlock(mc);
+ 		me = cache_lookup_distinct(mc, key);
+-		if (me && me->multi)
+-			lkp_key = strdup(me->multi->key);
++		if (me && IS_MM(me))
++			lkp_key = strdup(MM_ROOT(me)->key);
+ 		else
+ 			lkp_key = strdup(key);
+ 		cache_unlock(mc);
+--- autofs-5.1.4.orig/modules/lookup_yp.c
++++ autofs-5.1.4/modules/lookup_yp.c
+@@ -844,8 +844,8 @@ int lookup_mount(struct autofs_point *ap
+         if (ap->type == LKP_INDIRECT && *key != '/') {
+ 		cache_readlock(mc);
+ 		me = cache_lookup_distinct(mc, key);
+-		if (me && me->multi)
+-			lkp_key = strdup(me->multi->key);
++		if (me && IS_MM(me))
++			lkp_key = strdup(MM_ROOT(me)->key);
+ 		else if (!ap->pref)
+ 			lkp_key = strdup(key);
+ 		else {
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1150,7 +1150,7 @@ static int mount_subtree(struct autofs_p
+ 
+ 	rv = 0;
+ 
+-	mm_key = me->multi->key;
++	mm_key = MM_ROOT(me)->key;
+ 
+ 	if (*mm_key == '/') {
+ 		mm_root = mm_key;
+@@ -1164,7 +1164,7 @@ static int mount_subtree(struct autofs_p
+ 	}
+ 	mm_root_len = strlen(mm_root);
+ 
+-	if (me == me->multi) {
++	if (IS_MM_ROOT(me)) {
+ 		char key[PATH_MAX + 1];
+ 
+ 		if (mm_root_len + 1 > PATH_MAX) {
+@@ -1181,7 +1181,7 @@ static int mount_subtree(struct autofs_p
+ 
+ 		/* Mount root offset if it exists */
+ 		ro = cache_lookup_distinct(me->mc, key);
+-		if (ro && ro->age == me->multi->age) {
++		if (ro && ro->age == MM_ROOT(me)->age) {
+ 			char *myoptions, *ro_loc;
+ 			int namelen = name ? strlen(name) : 0;
+ 			int ro_len;
+@@ -1352,7 +1352,7 @@ int parse_mount(struct autofs_point *ap,
+ 	if (*name == '/') {
+ 		cache_readlock(mc);
+ 		me = cache_lookup_distinct(mc, name);
+-		if (me && me->multi && me->multi != me) {
++		if (me && IS_MM(me) && !IS_MM_ROOT(me)) {
+ 			cache_unlock(mc);
+ 			mapent_len = strlen(mapent) + 1;
+ 			pmapent = malloc(mapent_len + 1);
+@@ -1507,7 +1507,7 @@ dont_expand:
+ 		}
+ 
+ 		/* So we know we're the multi-mount root */
+-		if (!me->multi)
++		if (!IS_MM(me))
+ 			me->multi = me;
+ 		else {
+ 			/*
+@@ -1632,7 +1632,7 @@ dont_expand:
+ 		 */
+ 		cache_readlock(mc);
+ 		if (*name == '/' &&
+-		   (me = cache_lookup_distinct(mc, name)) && me->multi) {
++		   (me = cache_lookup_distinct(mc, name)) && IS_MM(me)) {
+ 			cache_unlock(mc);
+ 			loc = strdup(p);
+ 			if (!loc) {
diff --git a/SOURCES/autofs-5.1.7-add-tree_mapent_add_node.patch b/SOURCES/autofs-5.1.7-add-tree_mapent_add_node.patch
new file mode 100644
index 0000000..952c1f6
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-tree_mapent_add_node.patch
@@ -0,0 +1,123 @@
+autofs-5.1.7 - add tree_mapent_add_node()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_add_node() to the mapent tree handling
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    1 +
+ include/mounts.h    |    1 +
+ lib/cache.c         |    5 ++---
+ lib/mounts.c        |   47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 52 insertions(+), 3 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -33,6 +33,7 @@
+ - add a len field to struct autofs_point.
+ - make tree implementation data independent.
+ - add mapent tree implementation.
++- add tree_mapent_add_node().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -215,6 +215,7 @@ struct mapent *cache_partial_match_wild(
+ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age);
+ void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout);
++struct mapent *cache_get_offset_parent(struct mapent_cache *mc, const char *key);
+ int cache_set_offset_parent(struct mapent_cache *mc, const char *offset);
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -169,6 +169,7 @@ void mnts_get_expire_list(struct list_he
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
++int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -719,8 +719,7 @@ void cache_update_negative(struct mapent
+ }
+ 
+ 
+-static struct mapent *get_offset_parent(struct mapent_cache *mc,
+-					const char *key)
++struct mapent *cache_get_offset_parent(struct mapent_cache *mc, const char *key)
+ {
+ 	struct mapent *me;
+ 	char *parent, *tail;
+@@ -766,7 +765,7 @@ int cache_set_offset_parent(struct mapen
+ 	if (!IS_MM(this))
+ 		return 0;
+ 
+-	parent = get_offset_parent(mc, offset);
++	parent = cache_get_offset_parent(mc, offset);
+ 	if (parent)
+ 		this->parent = parent;
+ 	else
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1481,6 +1481,53 @@ static void tree_mapent_free(struct tree
+ 	n->right = NULL;
+ }
+ 
++int tree_mapent_add_node(struct mapent_cache *mc,
++			 const char *root, const char *key)
++{
++	unsigned int logopt = mc->ap->logopt;
++	struct tree_node *tree, *n;
++	struct mapent *base;
++	struct mapent *parent;
++	struct mapent *me;
++
++	base = cache_lookup_distinct(mc, root);
++	if (!base) {
++		error(logopt,
++		     "failed to find multi-mount root for key %s", key);
++		return 0;
++	}
++
++	if (MAPENT_ROOT(base) != MAPENT_NODE(base)) {
++		error(logopt,
++		     "failed to find multi-mount root of offset tree",
++		     key);
++		return 0;
++	}
++	tree = MAPENT_ROOT(base);
++
++	me = cache_lookup_distinct(mc, key);
++	if (!me) {
++		error(logopt,
++		     "failed to find key %s of multi-mount", key);
++		return 0;
++	}
++
++	n = tree_add_node(tree, me);
++	if (!n)
++		return 0;
++
++	MAPENT_SET_ROOT(me, tree)
++
++	/* Set the subtree parent */
++	parent = cache_get_offset_parent(mc, key);
++	if (!parent)
++		MAPENT_SET_PARENT(me, tree)
++	else
++		MAPENT_SET_PARENT(me, MAPENT_NODE(parent))
++
++	return 1;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/SOURCES/autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch b/SOURCES/autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch
new file mode 100644
index 0000000..93c4828
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch
@@ -0,0 +1,88 @@
+autofs-5.1.7 - add tree_mapent_cleanup_offsets()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_cleanup_offsets() to the mapent tree handling
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ include/mounts.h |    1 +
+ lib/mounts.c     |   45 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 47 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -37,6 +37,7 @@
+ - add tree_mapent_delete_offsets().
+ - add tree_mapent_traverse_subtree().
+ - fix mount_fullpath().
++- add tree_mapent_cleanup_offsets().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -171,6 +171,7 @@ void mnts_set_mounted_mount(struct autof
+ struct tree_node *tree_mapent_root(struct mapent *me);
+ int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
++void tree_mapent_cleanup_offsets(struct mapent *oe);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1647,6 +1647,51 @@ int tree_mapent_delete_offsets(struct ma
+ 	return 1;
+ }
+ 
++static void tree_mapent_umount_mount(struct autofs_point *ap, const char *mp)
++{
++	if (is_mounted(mp, MNTS_ALL)) {
++		if (umount(mp)) {
++			error(ap->logopt, "error recovering from mount fail");
++			error(ap->logopt, "cannot umount %s", mp);
++		}
++	}
++}
++
++static int tree_mapent_cleanup_offsets_work(struct tree_node *n, void *ptr)
++{
++	struct mapent *oe = MAPENT(n);
++	struct traverse_subtree_context *ctxt = ptr;
++
++	tree_mapent_umount_mount(ctxt->ap, oe->key);
++
++	return 1;
++}
++
++void tree_mapent_cleanup_offsets(struct mapent *oe)
++{
++	struct tree_node *base = MAPENT_NODE(oe);
++	struct traverse_subtree_context ctxt = {
++		.ap = oe->mc->ap,
++		.base = base,
++		.strict = 0,
++	};
++	struct autofs_point *ap = oe->mc->ap;
++
++	tree_mapent_traverse_subtree(base, tree_mapent_cleanup_offsets_work, &ctxt);
++
++	/* Cleanup base mount after offsets have been cleaned up */
++	if (*oe->key == '/')
++		tree_mapent_umount_mount(ap, oe->key);
++	else {
++		char mp[PATH_MAX + 1];
++
++		if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key))
++			error(ap->logopt, "mount path is too long");
++		else
++			tree_mapent_umount_mount(ap, mp);
++	}
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/SOURCES/autofs-5.1.7-add-tree_mapent_delete_offsets.patch b/SOURCES/autofs-5.1.7-add-tree_mapent_delete_offsets.patch
new file mode 100644
index 0000000..5357cb5
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-tree_mapent_delete_offsets.patch
@@ -0,0 +1,113 @@
+autofs-5.1.7 - add tree_mapent_delete_offsets()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_delete_offsets() to the mapent tree handling
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 
+ include/mounts.h |    1 
+ lib/mounts.c     |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 72 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -34,6 +34,7 @@
+ - make tree implementation data independent.
+ - add mapent tree implementation.
+ - add tree_mapent_add_node().
++- add tree_mapent_delete_offsets().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -170,6 +170,7 @@ void mnts_put_expire_list(struct list_he
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+ int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
++int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1528,6 +1528,76 @@ int tree_mapent_add_node(struct mapent_c
+ 	return 1;
+ }
+ 
++static int tree_mapent_delete_offset_tree(struct tree_node *root)
++{
++	struct mapent *me = MAPENT(root);
++	unsigned int logopt = me->mc->ap->logopt;
++	int ret = CHE_OK;
++
++	if (root->left) {
++		ret = tree_mapent_delete_offset_tree(root->left);
++		if (!ret)
++			return 0;
++		root->left = NULL;
++	}
++	if (root->right) {
++		ret = tree_mapent_delete_offset_tree(root->right);
++		if (!ret)
++			return 0;
++		root->right = NULL;
++	}
++
++	/* Keep the owner of the multi-mount offset tree and clear
++	 * the root and parent when done.
++	 */
++	if (MAPENT_ROOT(me) != MAPENT_NODE(me)) {
++		struct tree_node *root = MAPENT_ROOT(me);
++
++		debug(logopt, "deleting offset key %s", me->key);
++
++		/* cache_delete won't delete an active offset */
++		MAPENT_SET_ROOT(me, NULL);
++		ret = cache_delete(me->mc, me->key);
++		if (ret != CHE_OK) {
++			MAPENT_SET_ROOT(me, root);
++			warn(logopt, "failed to delete offset %s", me->key);
++		}
++	} else {
++		MAPENT_SET_ROOT(me, NULL);
++		MAPENT_SET_PARENT(me, NULL);
++	}
++
++	return ret == CHE_OK ? 1 : 0;
++}
++
++int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key)
++{
++	unsigned int logopt = mc->ap->logopt;
++	struct mapent *me;
++
++	me = cache_lookup_distinct(mc, key);
++	if (!me) {
++		error(logopt,
++		     "failed to find multi-mount root for key %s", key);
++		return 0;
++	}
++
++	/* Not offset list owner */
++	if (MAPENT_ROOT(me) != MAPENT_NODE(me)) {
++		error(logopt,
++		     "mapent for key %s is not multi-mount owner", key);
++		return 0;
++	}
++
++	if (!tree_mapent_delete_offset_tree(MAPENT_ROOT(me))) {
++		error(logopt,
++		     "could not delete map entry offsets for key %s", key);
++		return 0;
++	}
++
++	return 1;
++}
++
+ /* From glibc decode_name() */
+ /* Since the values in a line are separated by spaces, a name cannot
+  * contain a space.  Therefore some programs encode spaces in names
diff --git a/SOURCES/autofs-5.1.7-add-tree_mapent_traverse_subtree.patch b/SOURCES/autofs-5.1.7-add-tree_mapent_traverse_subtree.patch
new file mode 100644
index 0000000..482aea7
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-tree_mapent_traverse_subtree.patch
@@ -0,0 +1,79 @@
+autofs-5.1.7 - add tree_mapent_traverse_subtree()
+
+From: Ian Kent <raven@themaw.net>
+
+Add function tree_mapent_traverse_subtree() that enumerates offsets from
+a given base node bounded by subtree nesting points.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -35,6 +35,7 @@
+ - add mapent tree implementation.
+ - add tree_mapent_add_node().
+ - add tree_mapent_delete_offsets().
++- add tree_mapent_traverse_subtree().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1528,6 +1528,53 @@ int tree_mapent_add_node(struct mapent_c
+ 	return 1;
+ }
+ 
++static inline int tree_mapent_is_root(struct mapent *oe)
++{
++	/* Offset "/" is a special case, it's looked up and mounted
++	 * seperately because the offset tree may or may not have a
++	 * real mount at the base and the triggers inside it need to
++	 * be mounted in either case. Also the order requires the
++	 * offset at the top of the (sub)tree to be handled after
++	 * the traversal.
++	 */
++	return (oe->key[oe->len - 1] == '/' ||
++	        MAPENT_ROOT(oe) == MAPENT_NODE(oe));
++}
++
++struct traverse_subtree_context {
++	struct autofs_point *ap;
++	struct tree_node *base;
++	int strict;
++};
++
++static int tree_mapent_traverse_subtree(struct tree_node *n, tree_work_fn_t work, void *ptr)
++{
++	struct traverse_subtree_context *ctxt = ptr;
++	struct mapent *oe = MAPENT(n);
++	int ret = 1;
++
++	if (n->left) {
++		ret = tree_mapent_traverse_subtree(n->left, work, ctxt);
++		if (!ret && ctxt->strict)
++			goto done;
++	}
++
++	/* Node is not multi-mount root and is part of current subtree */
++	if (!tree_mapent_is_root(oe) && MAPENT_PARENT(oe) == ctxt->base) {
++		ret = work(n, ctxt);
++		if (!ret && ctxt->strict)
++			goto done;
++	}
++
++	if (n->right) {
++		ret = tree_mapent_traverse_subtree(n->right, work, ctxt);
++		if (!ret && ctxt->strict)
++			goto done;
++	}
++done:
++	return ret;
++}
++
+ static int tree_mapent_delete_offset_tree(struct tree_node *root)
+ {
+ 	struct mapent *me = MAPENT(root);
diff --git a/SOURCES/autofs-5.1.7-add-xdr_exports.patch b/SOURCES/autofs-5.1.7-add-xdr_exports.patch
new file mode 100644
index 0000000..93abd0a
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-add-xdr_exports.patch
@@ -0,0 +1,325 @@
+autofs-5.1.7 - add xdr_exports()
+
+From: Ian Kent <raven@themaw.net>
+
+Add an xdr_exports() function to get NFS exports from a server.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    3 +
+ include/rpc_subs.h     |   14 ++++++
+ lib/rpc_subs.c         |  120 +++++++++++++++++++++++++++++++++++-------------
+ modules/lookup_hosts.c |   25 +++-------
+ 4 files changed, 112 insertions(+), 50 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -1,3 +1,6 @@
++
++- add xdr_exports().
++
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+ - fix directory create permission.
+--- autofs-5.1.4.orig/include/rpc_subs.h
++++ autofs-5.1.4/include/rpc_subs.h
+@@ -17,6 +17,7 @@
+ #define _RPC_SUBS_H
+ 
+ #include <rpc/rpc.h>
++#include <rpc/types.h>
+ #include <rpc/pmap_prot.h>
+ #include <nfs/nfs.h>
+ #include <linux/nfs2.h>
+@@ -47,6 +48,17 @@
+ 
+ #define HOST_ENT_BUF_SIZE       2048
+ 
++struct hostinfo {
++	char *name;
++	struct hostinfo *next;
++};
++
++struct exportinfo {
++	char *dir;
++	struct hostinfo *hosts;
++	struct exportinfo *next;
++};
++
+ struct conn_info {
+ 	const char *host;
+ 	struct sockaddr *addr;
+@@ -71,6 +83,8 @@ int rpc_portmap_getport(struct conn_info
+ int rpc_ping_proto(struct conn_info *);
+ int rpc_ping(const char *, int, unsigned int, long, long, unsigned int);
+ double monotonic_elapsed(struct timespec, struct timespec);
++struct exportinfo *rpc_get_exports(const char *host, long seconds, long micros, unsigned int option);
++void rpc_exports_free(struct exportinfo *exports);
+ const char *get_addr_string(struct sockaddr *, char *, socklen_t);
+ 
+ #endif
+--- autofs-5.1.4.orig/lib/rpc_subs.c
++++ autofs-5.1.4/lib/rpc_subs.c
+@@ -41,7 +41,6 @@ const rpcprog_t rpcb_prog = PMAPPROG;
+ const rpcvers_t rpcb_version = PMAPVERS;
+ #endif
+ 
+-#include "mount.h"
+ #include "rpc_subs.h"
+ #include "replicated.h"
+ #include "automount.h"
+@@ -58,6 +57,17 @@ const rpcvers_t rpcb_version = PMAPVERS;
+ 
+ #define MAX_NETWORK_LEN		255
+ 
++#define EXPPATHLEN 1024
++#define EXPNAMELEN 255
++
++#define MOUNTPROG 100005
++
++#define MOUNTVERS	1
++#define MOUNTVERS_NFSV3 3
++#define MOUNTVERS_POSIX 2
++
++#define MOUNTPROC_EXPORT 5
++
+ /* Get numeric value of the n bits starting at position p */
+ #define getbits(x, p, n)      ((x >> (p + 1 - n)) & ~(~0 << n))
+ 
+@@ -1102,7 +1112,55 @@ double monotonic_elapsed(struct timespec
+ 	return t2 - t1;
+ }
+ 
+-static int rpc_get_exports_proto(struct conn_info *info, exports *exp)
++static bool_t xdr_host(XDR *xdrs, struct hostinfo *host)
++{
++	if (!xdr_string(xdrs, &host->name, EXPNAMELEN))
++		return FALSE;
++	return TRUE;
++}
++
++static bool_t xdr_hosts(XDR *xdrs, struct hostinfo **hosts)
++{
++	unsigned int size = sizeof(struct hostinfo);
++	char **host;
++
++	host = (char **) hosts;
++	while (1) {
++		if (!xdr_pointer(xdrs, host, size, (xdrproc_t) xdr_host))
++			return FALSE;
++		if (!*host)
++			break;
++		host = (char **) &((struct hostinfo *) *host)->next;
++	}
++	return TRUE;
++}
++
++static bool_t xdr_export(XDR *xdrs, struct exportinfo *export)
++{
++	if (!xdr_string(xdrs, &export->dir, EXPPATHLEN))
++		return FALSE;
++	if (!xdr_hosts(xdrs, &export->hosts))
++		return FALSE;
++	return TRUE;
++}
++
++bool_t xdr_exports(XDR *xdrs, struct exportinfo **exports)
++{
++	unsigned int size = sizeof(struct exportinfo);
++	char **export;
++
++	export = (char **) exports;
++	while (1) {
++		if (!xdr_pointer(xdrs, export, size, (xdrproc_t) xdr_export))
++			return FALSE;
++		if (!*export)
++			break;
++		export = (char **) &((struct exportinfo *) *export)->next;
++	}
++	return TRUE;
++}
++
++static int rpc_get_exports_proto(struct conn_info *info, struct exportinfo **exports)
+ {
+ 	CLIENT *client;
+ 	enum clnt_stat status;
+@@ -1133,7 +1191,7 @@ static int rpc_get_exports_proto(struct
+ 	while (1) {
+ 		status = clnt_call(client, MOUNTPROC_EXPORT,
+ 				 (xdrproc_t) xdr_void, NULL,
+-				 (xdrproc_t) xdr_exports, (caddr_t) exp,
++				 (xdrproc_t) xdr_exports, (caddr_t) exports,
+ 				 info->timeout);
+ 		if (status == RPC_SUCCESS)
+ 			break;
+@@ -1168,41 +1226,43 @@ static int rpc_get_exports_proto(struct
+ 	return 1;
+ }
+ 
+-static void rpc_export_free(exports item)
++static void rpc_export_free(struct exportinfo *export)
+ {
+-	groups grp;
+-	groups tmp;
++	struct hostinfo *host, *tmp;
+ 
+-	if (item->ex_dir)
+-		free(item->ex_dir);
++	if (export->dir)
++		free(export->dir);
+ 
+-	grp = item->ex_groups;
+-	while (grp) {
+-		if (grp->gr_name)
+-			free(grp->gr_name);
+-		tmp = grp;
+-		grp = grp->gr_next;
++	host = export->hosts;
++	while (host) {
++		if (host->name)
++			free(host->name);
++		tmp = host;
++		host = host->next;
+ 		free(tmp);
+ 	}
+-	free(item);
++	free(export);
+ }
+ 
+-void rpc_exports_free(exports list)
++void rpc_exports_free(struct exportinfo *exports)
+ {
+-	exports tmp;
++	struct exportinfo *export, *tmp;
+ 
+-	while (list) {
+-		tmp = list;
+-		list = list->ex_next;
++	export = exports;
++	while (export) {
++		tmp = export;
++		export = export->next;
+ 		rpc_export_free(tmp);
+ 	}
+ 	return;
+ }
+ 
+-exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option)
++struct exportinfo *rpc_get_exports(const char *host,
++				   long seconds, long micros,
++				   unsigned int option)
+ {
+ 	struct conn_info info;
+-	exports exportlist;
++	struct exportinfo *exports = NULL;
+ 	struct pmap parms;
+ 	int status;
+ 
+@@ -1231,11 +1291,9 @@ exports rpc_get_exports(const char *host
+ 	if (status < 0)
+ 		goto try_tcp;
+ 
+-	memset(&exportlist, '\0', sizeof(exportlist));
+-
+-	status = rpc_get_exports_proto(&info, &exportlist);
++	status = rpc_get_exports_proto(&info, &exports);
+ 	if (status)
+-		return exportlist;
++		return exports;
+ 
+ try_tcp:
+ 	info.proto = IPPROTO_TCP;
+@@ -1246,13 +1304,11 @@ try_tcp:
+ 	if (status < 0)
+ 		return NULL;
+ 
+-	memset(&exportlist, '\0', sizeof(exportlist));
+-
+-	status = rpc_get_exports_proto(&info, &exportlist);
++	status = rpc_get_exports_proto(&info, &exports);
+ 	if (!status)
+ 		return NULL;
+ 
+-	return exportlist;
++	return exports;
+ }
+ 
+ const char *get_addr_string(struct sockaddr *sa, char *name, socklen_t len)
+--- autofs-5.1.4.orig/modules/lookup_hosts.c
++++ autofs-5.1.4/modules/lookup_hosts.c
+@@ -20,14 +20,6 @@
+ #include <sys/stat.h>
+ #include <netdb.h>
+ 
+-/* 
+- * Avoid annoying compiler noise by using an alternate name for
+- * typedef name in mount.h
+- */
+-#define name __dummy_type_name
+-#include "mount.h"
+-#undef name
+-
+ #define MODULE_LOOKUP
+ #include "automount.h"
+ #include "nsswitch.h"
+@@ -43,9 +35,6 @@ struct lookup_context {
+ 
+ int lookup_version = AUTOFS_LOOKUP_VERSION;	/* Required by protocol */
+ 
+-exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option);
+-void rpc_exports_free(exports list);
+-
+ int lookup_init(const char *mapfmt,
+ 		int argc, const char *const *argv, void **context)
+ {
+@@ -99,7 +88,7 @@ static char *get_exports(struct autofs_p
+ {
+ 	char buf[MAX_ERR_BUF];
+ 	char *mapent;
+-	exports exp, this;
++	struct exportinfo *exp, *this;
+ 
+ 	debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+ 
+@@ -111,7 +100,7 @@ static char *get_exports(struct autofs_p
+ 		if (mapent) {
+ 			int len = strlen(mapent) + 1;
+ 
+-			len += strlen(host) + 2*(strlen(this->ex_dir) + 2) + 3;
++			len += strlen(host) + 2*(strlen(this->dir) + 2) + 3;
+ 			mapent = realloc(mapent, len);
+ 			if (!mapent) {
+ 				char *estr;
+@@ -121,10 +110,10 @@ static char *get_exports(struct autofs_p
+ 				return NULL;
+ 			}
+ 			strcat(mapent, " \"");
+-			strcat(mapent, this->ex_dir);
++			strcat(mapent, this->dir);
+ 			strcat(mapent, "\"");
+ 		} else {
+-			int len = 2*(strlen(this->ex_dir) + 2) + strlen(host) + 3;
++			int len = 2*(strlen(this->dir) + 2) + strlen(host) + 3;
+ 
+ 			mapent = malloc(len);
+ 			if (!mapent) {
+@@ -135,16 +124,16 @@ static char *get_exports(struct autofs_p
+ 				return NULL;
+ 			}
+ 			strcpy(mapent, "\"");
+-			strcat(mapent, this->ex_dir);
++			strcat(mapent, this->dir);
+ 			strcat(mapent, "\"");
+ 		}
+ 		strcat(mapent, " \"");
+ 		strcat(mapent, host);
+ 		strcat(mapent, ":");
+-		strcat(mapent, this->ex_dir);
++		strcat(mapent, this->dir);
+ 		strcat(mapent, "\"");
+ 
+-		this = this->ex_next;
++		this = this->next;
+ 	}
+ 	rpc_exports_free(exp);
+ 
diff --git a/SOURCES/autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch b/SOURCES/autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch
new file mode 100644
index 0000000..ee72041
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch
@@ -0,0 +1,40 @@
+autofs-5.1.7 - cater for empty mounts list in mnts_get_expire_list()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: var_deref_model: Passing null pointer "tree" to
+	  "tree_traverse_inorder", which dereferences it.
+
+This obviously can't happen but deal with it anyway to quiet Coverity.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    6 ++++--
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -64,6 +64,7 @@
+ - fix missing lock release in mount_subtree().
+ - fix double free in parse_mapent().
+ - refactor lookup_prune_one_cache() a bit.
++- cater for empty mounts list in mnts_get_expire_list().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1445,8 +1445,10 @@ void mnts_get_expire_list(struct list_he
+ 		}
+ 	}
+ 
+-	tree_traverse_inorder(tree, tree_mnt_expire_list_work, mnts);
+-	tree_free(tree);
++	if (tree) {
++		tree_traverse_inorder(tree, tree_mnt_expire_list_work, mnts);
++		tree_free(tree);
++	}
+ done:
+ 	mnts_hash_mutex_unlock();
+ }
diff --git a/SOURCES/autofs-5.1.7-check-for-offset-with-no-mount-location.patch b/SOURCES/autofs-5.1.7-check-for-offset-with-no-mount-location.patch
new file mode 100644
index 0000000..945c56d
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-check-for-offset-with-no-mount-location.patch
@@ -0,0 +1,46 @@
+autofs-5.1.7 - check for offset with no mount location
+
+From: Ian Kent <raven@themaw.net>
+
+Offsets need to have a mount location, check for it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   15 ++++++++++++++-
+ 2 files changed, 15 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -47,6 +47,7 @@
+ - pass root length to mount_fullpath().
+ - remove unused function master_submount_list_empty().
+ - move amd mounts removal into lib/mounts.c.
++- check for offset with no mount location.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -803,7 +803,20 @@ update_offset_entry(struct autofs_point
+ 
+ 	memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+ 
+-	/* Internal hosts map may have loc == NULL */
++	if (!loc || !*loc) {
++		const char *type = ap->entry->maps->type;
++
++		/* If it's not the internal hosts map it must have a
++		 * mount location.
++		 */
++		if (!type || strcmp(type, "hosts")) {
++			error(ap->logopt,
++			      MODPREFIX "syntax error in offset %s -> %s",
++			      m_offset, loc);
++			return CHE_FAIL;
++		}
++	}
++
+ 	if (!*m_offset) {
+ 		error(ap->logopt,
+ 		      MODPREFIX "syntax error in offset %s -> %s", m_offset, loc);
diff --git a/SOURCES/autofs-5.1.7-cleanup-cache_delete-a-little.patch b/SOURCES/autofs-5.1.7-cleanup-cache_delete-a-little.patch
new file mode 100644
index 0000000..9fd6022
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-cleanup-cache_delete-a-little.patch
@@ -0,0 +1,60 @@
+autofs-5.1.7 - cleanup cache_delete() a little
+
+From: Ian Kent <raven@themaw.net>
+
+There's no reason to use local function storage for the passed in key
+just use the given key.
+
+Also, if there's no hash array entry for the key then there's no cache
+entry so don't return a fail for this case.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG   |    1 +
+ lib/cache.c |   11 +++--------
+ 2 files changed, 4 insertions(+), 8 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -23,6 +23,7 @@
+ - eliminate some strlen calls in offset handling.
+ - don't add offset mounts to mounted mounts table.
+ - reduce umount EBUSY check delay.
++- cleanup cache_delete() a little.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -887,20 +887,15 @@ int cache_delete(struct mapent_cache *mc
+ 	struct mapent *me = NULL, *pred;
+ 	u_int32_t hashval = hash(key, mc->size);
+ 	int ret = CHE_OK;
+-	char this[PATH_MAX];
+-
+-	strcpy(this, key);
+ 
+ 	me = mc->hash[hashval];
+-	if (!me) {
+-		ret = CHE_FAIL;
++	if (!me)
+ 		goto done;
+-	}
+ 
+ 	while (me->next != NULL) {
+ 		pred = me;
+ 		me = me->next;
+-		if (strcmp(this, me->key) == 0) {
++		if (strcmp(key, me->key) == 0) {
+ 			struct stack *s = me->stack;
+ 			if (me->multi && !list_empty(&me->multi_list)) {
+ 				ret = CHE_FAIL;
+@@ -929,7 +924,7 @@ int cache_delete(struct mapent_cache *mc
+ 	if (!me)
+ 		goto done;
+ 
+-	if (strcmp(this, me->key) == 0) {
++	if (strcmp(key, me->key) == 0) {
+ 		struct stack *s = me->stack;
+ 		if (me->multi && !list_empty(&me->multi_list)) {
+ 			ret = CHE_FAIL;
diff --git a/SOURCES/autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch b/SOURCES/autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch
new file mode 100644
index 0000000..b6a2afd
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch
@@ -0,0 +1,197 @@
+autofs-5.1.7 - don't add offset mounts to mounted mounts table
+
+From: Ian Kent <raven@themaw.net>
+
+Multi-mount offset mounts are added to the mounted mounts table whether
+they have a real mount or not. If there are a large number of offsets
+this can add unnecessary overhead to the mounted mounts table processing.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG         |    1 +
+ daemon/direct.c   |   14 ++++----------
+ daemon/indirect.c |    4 +++-
+ include/mounts.h  |    2 +-
+ lib/mounts.c      |   43 +++++++++++--------------------------------
+ 5 files changed, 20 insertions(+), 44 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -21,6 +21,7 @@
+ - remove unused mount offset list lock functions.
+ - eliminate count_mounts() from expire_proc_indirect().
+ - eliminate some strlen calls in offset handling.
++- don't add offset mounts to mounted mounts table.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -605,9 +605,6 @@ force_umount:
+ 	} else
+ 		info(ap->logopt, "umounted offset mount %s", me->key);
+ 
+-	if (!rv)
+-		mnts_remove_mount(me->key, MNTS_OFFSET);
+-
+ 	return rv;
+ }
+ 
+@@ -761,12 +758,6 @@ int mount_autofs_offset(struct autofs_po
+ 		notify_mount_result(ap, me->key, timeout, str_offset);
+ 	ops->close(ap->logopt, ioctlfd);
+ 
+-	mnt = mnts_add_mount(ap, me->key, MNTS_OFFSET);
+-	if (!mnt)
+-		error(ap->logopt,
+-		      "failed to add offset mount %s to mounted list",
+-		      me->key);
+-
+ 	debug(ap->logopt, "mounted trigger %s", me->key);
+ 
+ 	return MOUNT_OFFSET_OK;
+@@ -1214,6 +1205,7 @@ static void *do_mount_direct(void *arg)
+ 		struct mapent *me;
+ 		struct statfs fs;
+ 		unsigned int close_fd = 0;
++		unsigned int flags = MNTS_DIRECT|MNTS_MOUNTED;
+ 
+ 		sbmnt = mnts_find_submount(mt.name);
+ 		if (statfs(mt.name, &fs) == -1 ||
+@@ -1232,6 +1224,8 @@ static void *do_mount_direct(void *arg)
+ 				close_fd = 0;
+ 			if (!close_fd)
+ 				me->ioctlfd = mt.ioctlfd;
++			if (me->multi && me->multi != me)
++				flags |= MNTS_OFFSET;
+ 		}
+ 		ops->send_ready(ap->logopt, mt.ioctlfd, mt.wait_queue_token);
+ 		cache_unlock(mt.mc);
+@@ -1240,7 +1234,7 @@ static void *do_mount_direct(void *arg)
+ 
+ 		info(ap->logopt, "mounted %s", mt.name);
+ 
+-		mnts_set_mounted_mount(ap, mt.name);
++		mnts_set_mounted_mount(ap, mt.name, flags);
+ 
+ 		conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -747,12 +747,14 @@ static void *do_mount_indirect(void *arg
+ 	status = lookup_nss_mount(ap, NULL, mt.name, mt.len);
+ 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
+ 	if (status) {
++		unsigned int flags = MNTS_INDIRECT|MNTS_MOUNTED;
++
+ 		ops->send_ready(ap->logopt,
+ 				ap->ioctlfd, mt.wait_queue_token);
+ 
+ 		info(ap->logopt, "mounted %s", buf);
+ 
+-		mnts_set_mounted_mount(ap, mt.name);
++		mnts_set_mounted_mount(ap, mt.name, flags);
+ 
+ 		conditional_alarm_add(ap, ap->exp_runfreq);
+ 	} else {
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -131,7 +131,7 @@ struct mnt_list *get_mnt_list(const char
+ unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+-void mnts_set_mounted_mount(struct autofs_point *ap, const char *name);
++void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ int unlink_mount_tree(struct autofs_point *ap, const char *mp);
+ void free_mnt_list(struct mnt_list *list);
+ int is_mounted(const char *mp, unsigned int type);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1172,7 +1172,7 @@ struct mnt_list *mnts_add_mount(struct a
+ 	this = mnts_get_mount(mp);
+ 	if (this) {
+ 		this->flags |= flags;
+-		if (list_empty(&this->mount))
++		if ((this->flags & MNTS_MOUNTED) && list_empty(&this->mount))
+ 			list_add(&this->mount, &ap->mounts);
+ 	}
+ 	mnts_hash_mutex_unlock();
+@@ -1193,42 +1193,23 @@ void mnts_remove_mount(const char *mp, u
+ 	this = mnts_lookup(mp);
+ 	if (this && this->flags & flags) {
+ 		this->flags &= ~flags;
+-		if (!(this->flags & (MNTS_OFFSET|MNTS_MOUNTED)))
++		if (!(this->flags & MNTS_MOUNTED))
+ 			list_del_init(&this->mount);
+ 		__mnts_put_mount(this);
+ 	}
+ 	mnts_hash_mutex_unlock();
+ }
+ 
+-void mnts_set_mounted_mount(struct autofs_point *ap, const char *name)
++void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags)
+ {
+ 	struct mnt_list *mnt;
+ 
+-	mnt = mnts_add_mount(ap, name, MNTS_MOUNTED);
++	mnt = mnts_add_mount(ap, name, flags);
+ 	if (!mnt) {
+ 		error(ap->logopt,
+ 		      "failed to add mount %s to mounted list", name);
+ 		return;
+ 	}
+-
+-	/* Offset mount failed but non-strict returns success */
+-	if (mnt->flags & MNTS_OFFSET &&
+-	    !is_mounted(mnt->mp, MNTS_REAL)) {
+-		mnt->flags &= ~MNTS_MOUNTED;
+-		mnts_put_mount(mnt);
+-	}
+-
+-	/* Housekeeping.
+-	 * Set the base type of the mounted mount.
+-	 * MNTS_AUTOFS and MNTS_OFFSET are set at mount time and
+-	 * are used during expire.
+-	 */
+-	if (!(mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET))) {
+-		if (ap->type == LKP_INDIRECT)
+-			mnt->flags |= MNTS_INDIRECT;
+-		else
+-			mnt->flags |= MNTS_DIRECT;
+-	}
+ }
+ 
+ unsigned int mnts_has_mounted_mounts(struct autofs_point *ap)
+@@ -1943,17 +1924,13 @@ static int do_remount_direct(struct auto
+ 
+ 	ret = lookup_nss_mount(ap, NULL, path, strlen(path));
+ 	if (ret) {
+-		struct mnt_list *mnt;
++		unsigned int flags = MNTS_DIRECT|MNTS_MOUNTED;
+ 
+ 		/* If it's an offset mount add a mount reference */
+-		if (type == t_offset) {
+-			mnt = mnts_add_mount(ap, path, MNTS_OFFSET);
+-			if (!mnt)
+-				error(ap->logopt,
+-				      "failed to add mount %s to mounted list", path);
+-		}
++		if (type == t_offset)
++			flags |= MNTS_OFFSET;
+ 
+-		mnts_set_mounted_mount(ap, path);
++		mnts_set_mounted_mount(ap, path, flags);
+ 
+ 		info(ap->logopt, "re-connected to %s", path);
+ 
+@@ -2028,7 +2005,9 @@ static int do_remount_indirect(struct au
+ 
+ 		ret = lookup_nss_mount(ap, NULL, de[n]->d_name, len);
+ 		if (ret) {
+-			mnts_set_mounted_mount(ap, buf);
++			unsigned int flags = MNTS_INDIRECT|MNTS_MOUNTED;
++
++			mnts_set_mounted_mount(ap, buf, flags);
+ 
+ 			info(ap->logopt, "re-connected to %s", buf);
+ 
diff --git a/SOURCES/autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch b/SOURCES/autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch
new file mode 100644
index 0000000..421a00d
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch
@@ -0,0 +1,60 @@
+autofs-5.1.7 - don't pass root to do_mount_autofs_offset()
+
+From: Ian Kent <raven@themaw.net>
+
+The root parameter of do_mount_autofs_offset() is used only in a
+debug log message. It doesn't really add any value to debugging
+so remove it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    9 ++++-----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -25,6 +25,7 @@
+ - reduce umount EBUSY check delay.
+ - cleanup cache_delete() a little.
+ - rename path to m_offset in update_offset_entry().
++- don't pass root to do_mount_autofs_offset().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2447,13 +2447,12 @@ out:
+ 	return rv;
+ }
+ 
+-static int do_mount_autofs_offset(struct autofs_point *ap,
+-				  struct mapent *oe, const char *root)
++static int do_mount_autofs_offset(struct autofs_point *ap, struct mapent *oe)
+ {
+ 	int mounted = 0;
+ 	int ret;
+ 
+-	debug(ap->logopt, "mount offset %s at %s", oe->key, root);
++	debug(ap->logopt, "mount offset %s", oe->key);
+ 
+ 	ret = mount_autofs_offset(ap, oe);
+ 	if (ret >= MOUNT_OFFSET_OK)
+@@ -2645,7 +2644,7 @@ static int do_umount_offset(struct autof
+ 		 */
+ 		ret = rmdir_path_offset(ap, oe);
+ 		if (ret == -1 && !stat(oe->key, &st)) {
+-			ret = do_mount_autofs_offset(ap, oe, root);
++			ret = do_mount_autofs_offset(ap, oe);
+ 			if (ret)
+ 				left++;
+ 			/* But we did origianlly create this */
+@@ -2691,7 +2690,7 @@ int mount_multi_triggers(struct autofs_p
+ 			goto cont;
+ 		}
+ 
+-		mounted += do_mount_autofs_offset(ap, oe, root);
++		mounted += do_mount_autofs_offset(ap, oe);
+ 
+ 		/*
+ 		 * If re-constructing a multi-mount it's necessary to walk
diff --git a/SOURCES/autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch b/SOURCES/autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch
new file mode 100644
index 0000000..aba0639
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch
@@ -0,0 +1,41 @@
+autofs-5.1.7 - dont try umount after stat() ENOENT fail
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: Calling function "umount" that uses "me->key" after a check
+	  function. This can cause a time-of-check, time-of-use race
+	  condition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/direct.c |    6 +++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -57,6 +57,7 @@
+ - fix double unlock in parse_mount().
+ - add length check in umount_subtree_mounts().
+ - fix flags check in umount_multi().
++- dont try umount after stat() ENOENT fail.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -739,9 +739,13 @@ int mount_autofs_offset(struct autofs_po
+ 
+ 	ret = stat(me->key, &st);
+ 	if (ret == -1) {
++		int save_errno = errno;
++
+ 		error(ap->logopt,
+ 		     "failed to stat direct mount trigger %s", me->key);
+-		goto out_umount;
++		if (save_errno != ENOENT)
++			goto out_umount;
++		goto out_err;
+ 	}
+ 
+ 	ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key);
diff --git a/SOURCES/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch b/SOURCES/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch
new file mode 100644
index 0000000..f4c2354
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch
@@ -0,0 +1,107 @@
+autofs-5.1.7 - dont use realloc in host exports list processing
+
+From: Ian Kent <raven@themaw.net>
+
+If a server exports list is very large calling realloc(3) for each
+export is slow. It's better to traverse the exports list twice, once
+to calculate the length of the mapent then allocate the memory and
+traverse the exports list again to construct the mapent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ modules/lookup_hosts.c |   59 +++++++++++++++++++++---------------------------
+ 2 files changed, 27 insertions(+), 33 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -1,6 +1,7 @@
+ 
+ - add xdr_exports().
+ - remove mount.x and rpcgen dependencies.
++- dont use realloc in host exports list processing.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/lookup_hosts.c
++++ autofs-5.1.4/modules/lookup_hosts.c
+@@ -89,44 +89,40 @@ static char *get_exports(struct autofs_p
+ 	char buf[MAX_ERR_BUF];
+ 	char *mapent;
+ 	struct exportinfo *exp, *this;
++	size_t hostlen = strlen(host);
++	size_t mapent_len;
+ 
+ 	debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+ 
+ 	exp = rpc_get_exports(host, 10, 0, RPC_CLOSE_NOLINGER);
+ 
+-	mapent = NULL;
+ 	this = exp;
++	mapent_len = 0;
+ 	while (this) {
+-		if (mapent) {
+-			int len = strlen(mapent) + 1;
++		mapent_len += hostlen + 2*(strlen(this->dir) + 2) + 3;
++		this = this->next;
++	}
+ 
+-			len += strlen(host) + 2*(strlen(this->dir) + 2) + 3;
+-			mapent = realloc(mapent, len);
+-			if (!mapent) {
+-				char *estr;
+-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-				error(ap->logopt, MODPREFIX "malloc: %s", estr);
+-				rpc_exports_free(exp);
+-				return NULL;
+-			}
+-			strcat(mapent, " \"");
+-			strcat(mapent, this->dir);
+-			strcat(mapent, "\"");
+-		} else {
+-			int len = 2*(strlen(this->dir) + 2) + strlen(host) + 3;
+-
+-			mapent = malloc(len);
+-			if (!mapent) {
+-				char *estr;
+-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-				error(ap->logopt, MODPREFIX "malloc: %s", estr);
+-				rpc_exports_free(exp);
+-				return NULL;
+-			}
++	mapent = malloc(mapent_len + 1);
++	if (!mapent) {
++		char *estr;
++		estr = strerror_r(errno, buf, MAX_ERR_BUF);
++		error(ap->logopt, MODPREFIX "malloc: %s", estr);
++		error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
++		rpc_exports_free(exp);
++		return NULL;
++	}
++	*mapent = 0;
++
++	this = exp;
++	while (this) {
++		if (!*mapent)
+ 			strcpy(mapent, "\"");
+-			strcat(mapent, this->dir);
+-			strcat(mapent, "\"");
+-		}
++		else
++			strcat(mapent, " \"");
++		strcat(mapent, this->dir);
++		strcat(mapent, "\"");
++
+ 		strcat(mapent, " \"");
+ 		strcat(mapent, host);
+ 		strcat(mapent, ":");
+@@ -137,9 +133,6 @@ static char *get_exports(struct autofs_p
+ 	}
+ 	rpc_exports_free(exp);
+ 
+-	if (!mapent)
+-		error(ap->logopt, MODPREFIX "exports lookup failed for %s", host);
+-
+ 	return mapent;
+ }
+ 
diff --git a/SOURCES/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch b/SOURCES/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch
new file mode 100644
index 0000000..2c506c1
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch
@@ -0,0 +1,372 @@
+autofs-5.1.7 - eliminate cache_lookup_offset() usage
+
+From: Ian Kent <raven@themaw.net>
+
+The function cache_lookup_offset() will do a linear search when
+looking for an offset. If the number of offsets is large this
+can be a lot of overhead.
+
+But it's possible to use the information already present where
+this is called to to do a hashed lookup instead.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ lib/mounts.c        |   82 +++++++++++++++++++++++++++++++++-------------------
+ modules/parse_sun.c |   77 ++++++++++++++++++++++++++++++------------------
+ 3 files changed, 102 insertions(+), 58 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -4,6 +4,7 @@
+ - dont use realloc in host exports list processing.
+ - use sprintf() when constructing hosts mapent.
+ - fix mnts_remove_amdmount() uses wrong list.
++- eliminate cache_lookup_offset() usage.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2489,24 +2489,27 @@ int mount_multi_triggers(struct autofs_p
+ 	char *offset = path;
+ 	struct mapent *oe;
+ 	struct list_head *pos = NULL;
+-	unsigned int fs_path_len;
++	unsigned int root_len = strlen(root);
+ 	int mounted;
+ 
+-	fs_path_len = start + strlen(base);
+-	if (fs_path_len > PATH_MAX)
+-		return -1;
+-
+ 	mounted = 0;
+ 	offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+ 	while (offset) {
+-		int plen = fs_path_len + strlen(offset);
++		char key[PATH_MAX + 1];
++		int key_len = root_len + strlen(offset);
+ 
+-		if (plen > PATH_MAX) {
++		if (key_len > PATH_MAX) {
+ 			warn(ap->logopt, "path loo long");
+ 			goto cont;
+ 		}
+ 
+-		oe = cache_lookup_offset(base, offset, start, &me->multi_list);
++		/* The root offset is always mounted seperately so the
++		 * offset path will always be root + offset.
++		 */
++		strcpy(key, root);
++		strcat(key, offset);
++
++		oe = cache_lookup_distinct(me->mc, key);
+ 		if (!oe || !oe->mapent)
+ 			goto cont;
+ 
+@@ -2519,12 +2522,8 @@ int mount_multi_triggers(struct autofs_p
+ 		 */
+ 		if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+ 			if (oe->ioctlfd != -1 ||
+-			    is_mounted(oe->key, MNTS_REAL)) {
+-				char oe_root[PATH_MAX + 1];
+-				strcpy(oe_root, root);
+-				strcat(oe_root, offset); 
+-				mount_multi_triggers(ap, oe, oe_root, strlen(oe_root), base);
+-			}
++			    is_mounted(oe->key, MNTS_REAL))
++				mount_multi_triggers(ap, oe, key, strlen(key), base);
+ 		}
+ cont:
+ 		offset = cache_get_offset(base,
+@@ -2578,6 +2577,8 @@ int umount_multi_triggers(struct autofs_
+ 	const char o_root[] = "/";
+ 	const char *mm_base;
+ 	int left, start;
++	unsigned int root_len;
++	unsigned int mm_base_len;
+ 
+ 	left = 0;
+ 	start = strlen(root);
+@@ -2591,11 +2592,28 @@ int umount_multi_triggers(struct autofs_
+ 
+ 	pos = NULL;
+ 	offset = path;
++	root_len = start;
++	mm_base_len = strlen(mm_base);
+ 
+ 	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
++		char key[PATH_MAX + 1];
++		int key_len = root_len + strlen(offset);
+ 		char *oe_base;
+ 
+-		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
++		if (mm_base_len > 1)
++			key_len += mm_base_len;
++
++		if (key_len > PATH_MAX) {
++			warn(ap->logopt, "path loo long");
++			continue;
++		}
++
++		strcpy(key, root);
++		if (mm_base_len > 1)
++			strcat(key, mm_base);
++		strcat(key, offset);
++
++		oe = cache_lookup_distinct(me->mc, key);
+ 		/* root offset is a special case */
+ 		if (!oe || (strlen(oe->key) - start) == 1)
+ 			continue;
+@@ -2680,13 +2698,14 @@ int clean_stale_multi_triggers(struct au
+ 	char *root;
+ 	char mm_top[PATH_MAX + 1];
+ 	char path[PATH_MAX + 1];
+-	char buf[MAX_ERR_BUF];
+ 	char *offset;
+ 	struct mapent *oe;
+ 	struct list_head *mm_root, *pos;
+ 	const char o_root[] = "/";
+ 	const char *mm_base;
+ 	int left, start;
++	unsigned int root_len;
++	unsigned int mm_base_len;
+ 	time_t age;
+ 
+ 	if (top)
+@@ -2714,14 +2733,30 @@ int clean_stale_multi_triggers(struct au
+ 
+ 	pos = NULL;
+ 	offset = path;
++	root_len = start;
++	mm_base_len = strlen(mm_base);
+ 	age = me->multi->age;
+ 
+ 	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
++		char key[PATH_MAX + 1];
++		int key_len = root_len + strlen(offset);
+ 		char *oe_base;
+-		char *key;
+ 		int ret;
+ 
+-		oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
++		if (mm_base_len > 1)
++			key_len += mm_base_len;
++
++		if (key_len > PATH_MAX) {
++			warn(ap->logopt, "path loo long");
++			continue;
++		}
++
++		strcpy(key, root);
++		if (mm_base_len > 1)
++			strcat(key, mm_base);
++		strcat(key, offset);
++
++		oe = cache_lookup_distinct(me->mc, key);
+ 		/* root offset is a special case */
+ 		if (!oe || (strlen(oe->key) - start) == 1)
+ 			continue;
+@@ -2772,14 +2807,6 @@ int clean_stale_multi_triggers(struct au
+ 			}
+ 		}
+ 
+-		key = strdup(oe->key);
+-		if (!key) {
+-	                char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-		        error(ap->logopt, "malloc: %s", estr);
+-			left++;
+-			continue;
+-		}
+-
+ 		debug(ap->logopt, "umount offset %s", oe->key);
+ 
+ 		if (umount_autofs_offset(ap, oe)) {
+@@ -2794,7 +2821,6 @@ int clean_stale_multi_triggers(struct au
+ 				if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
+ 					error(ap->logopt,
+ 					     "failed to delete offset key %s", key);
+-				free(key);
+ 				continue;
+ 			}
+ 
+@@ -2810,7 +2836,6 @@ int clean_stale_multi_triggers(struct au
+ 					left++;
+ 					/* But we did origianlly create this */
+ 					oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-					free(key);
+ 					continue;
+ 				}
+ 				/*
+@@ -2828,7 +2853,6 @@ int clean_stale_multi_triggers(struct au
+ 				error(ap->logopt,
+ 				     "failed to delete offset key %s", key);
+ 		}
+-		free(key);
+ 	}
+ 
+ 	return left;
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1088,6 +1088,8 @@ static void cleanup_multi_triggers(struc
+ 	struct list_head *mm_root, *pos;
+ 	const char o_root[] = "/";
+ 	const char *mm_base;
++	unsigned int root_len;
++	unsigned int mm_base_len;
+ 
+ 	mm_root = &me->multi->multi_list;
+ 
+@@ -1097,16 +1099,31 @@ static void cleanup_multi_triggers(struc
+ 		mm_base = base;
+ 
+ 	pos = NULL;
++	root_len = strlen(root);
++	mm_base_len = strlen(mm_base);
+ 
+ 	/* Make sure "none" of the offsets have an active mount. */
+ 	while ((poffset = cache_get_offset(mm_base, poffset, start, mm_root, &pos))) {
+-		oe = cache_lookup_offset(mm_base, poffset, start, &me->multi_list);
+-		/* root offset is a special case */
+-		if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
++		unsigned int path_len = root_len + strlen(poffset);
++
++		if (mm_base_len > 1)
++			path_len += mm_base_len;
++
++		if (path_len > PATH_MAX) {
++			warn(ap->logopt, "path loo long");
+ 			continue;
++		}
+ 
+ 		strcpy(path, root);
++		if (mm_base_len > 1)
++			strcat(path, mm_base);
+ 		strcat(path, poffset);
++
++		oe = cache_lookup_distinct(me->mc, path);
++		/* root offset is a special case */
++		if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
++			continue;
++
+ 		if (umount(path)) {
+ 			error(ap->logopt, "error recovering from mount fail");
+ 			error(ap->logopt, "cannot umount offset %s", path);
+@@ -1119,17 +1136,14 @@ static void cleanup_multi_triggers(struc
+ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
+ 			 const char *name, char *loc, char *options, void *ctxt)
+ {
+-	struct mapent *mm;
+ 	struct mapent *ro;
+ 	char *mm_root, *mm_base, *mm_key;
+-	const char *mnt_root;
+-	unsigned int mm_root_len, mnt_root_len;
++	unsigned int mm_root_len;
+ 	int start, ret = 0, rv;
+ 
+ 	rv = 0;
+ 
+-	mm = me->multi;
+-	mm_key = mm->key;
++	mm_key = me->multi->key;
+ 
+ 	if (*mm_key == '/') {
+ 		mm_root = mm_key;
+@@ -1143,20 +1157,26 @@ static int mount_subtree(struct autofs_p
+ 	}
+ 	mm_root_len = strlen(mm_root);
+ 
+-	mnt_root = mm_root;
+-	mnt_root_len = mm_root_len;
+-
+ 	if (me == me->multi) {
++		char key[PATH_MAX + 1];
++
++		if (mm_root_len + 1 > PATH_MAX) {
++			warn(ap->logopt, "path loo long");
++			return 1;
++		}
++
+ 		/* name = NULL */
+ 		/* destination = mm_root */
+ 		mm_base = "/";
+ 
++		strcpy(key, mm_root);
++		strcat(key, mm_base);
++
+ 		/* Mount root offset if it exists */
+-		ro = cache_lookup_offset(mm_base, mm_base, strlen(mm_root), &me->multi_list);
++		ro = cache_lookup_distinct(me->mc, key);
+ 		if (ro) {
+-			char *myoptions, *ro_loc, *tmp;
++			char *myoptions, *ro_loc;
+ 			int namelen = name ? strlen(name) : 0;
+-			const char *root;
+ 			int ro_len;
+ 
+ 			myoptions = NULL;
+@@ -1174,13 +1194,7 @@ static int mount_subtree(struct autofs_p
+ 			if (ro_loc)
+ 				ro_len = strlen(ro_loc);
+ 
+-			tmp = alloca(mnt_root_len + 2);
+-			strcpy(tmp, mnt_root);
+-			tmp[mnt_root_len] = '/';
+-			tmp[mnt_root_len + 1] = '\0';
+-			root = tmp;
+-
+-			rv = sun_mount(ap, root, name, namelen, ro_loc, ro_len, myoptions, ctxt);
++			rv = sun_mount(ap, key, name, namelen, ro_loc, ro_len, myoptions, ctxt);
+ 
+ 			free(myoptions);
+ 			if (ro_loc)
+@@ -1188,11 +1202,11 @@ static int mount_subtree(struct autofs_p
+ 		}
+ 
+ 		if (ro && rv == 0) {
+-			ret = mount_multi_triggers(ap, me, mnt_root, start, mm_base);
++			ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+ 			if (ret == -1) {
+ 				error(ap->logopt, MODPREFIX
+ 					 "failed to mount offset triggers");
+-				cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
++				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+ 				return 1;
+ 			}
+ 		} else if (rv <= 0) {
+@@ -1208,24 +1222,29 @@ static int mount_subtree(struct autofs_p
+ 		int loclen = strlen(loc);
+ 		int namelen = strlen(name);
+ 
+-		mnt_root = name;
+-
+ 		/* name = mm_root + mm_base */
+ 		/* destination = mm_root + mm_base = name */
+ 		mm_base = &me->key[start];
+ 
+-		rv = sun_mount(ap, mnt_root, name, namelen, loc, loclen, options, ctxt);
++		rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
+ 		if (rv == 0) {
+-			ret = mount_multi_triggers(ap, me->multi, mnt_root, start, mm_base);
++			ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
+ 			if (ret == -1) {
+ 				error(ap->logopt, MODPREFIX
+ 					 "failed to mount offset triggers");
+-				cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
++				cleanup_multi_triggers(ap, me, name, start, mm_base);
+ 				return 1;
+ 			}
+ 		} else if (rv < 0) {
+-			char *mm_root_base = alloca(strlen(mm_root) + strlen(mm_base) + 1);
++			char mm_root_base[PATH_MAX + 1];
++			unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
+ 	
++			if (mm_root_base_len > PATH_MAX) {
++				warn(ap->logopt, MODPREFIX "path too long");
++				cache_delete_offset_list(me->mc, name);
++				return 1;
++			}
++
+ 			strcpy(mm_root_base, mm_root);
+ 			strcat(mm_root_base, mm_base);
+ 
diff --git a/SOURCES/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch b/SOURCES/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch
new file mode 100644
index 0000000..f1138c0
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch
@@ -0,0 +1,285 @@
+autofs-5.1.7 - eliminate clean_stale_multi_triggers()
+
+From: Ian Kent <raven@themaw.net>
+
+Eliminate clean_stale_multi_triggers() by checking for stale offsets at
+the time mount_subtree() is called.
+
+This should result in the same behaviour but eliminate an additional
+seperate traversal of the offset list.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ lib/mounts.c        |  209 ++++++++++------------------------------------------
+ modules/parse_sun.c |   10 --
+ 3 files changed, 43 insertions(+), 177 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -11,6 +11,7 @@
+ - remove redundant variables from mount_autofs_offset().
+ - remove unused parameter form do_mount_autofs_offset().
+ - refactor umount_multi_triggers().
++- eliminate clean_stale_multi_triggers().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2595,10 +2595,44 @@ static int do_umount_offset(struct autof
+ 	oe_base = oe->key + strlen(root);
+ 	left += do_umount_multi_triggers(ap, oe, root, oe_base);
+ 
++	/*
++	 * If an offset that has an active mount has been removed
++	 * from the multi-mount we don't want to attempt to trigger
++	 * mounts for it. Obviously this is because it has been
++	 * removed, but less obvious is the potential strange
++	 * behaviour that can result if we do try and mount it
++	 * again after it's been expired. For example, if an NFS
++	 * file system is no longer exported and is later umounted
++	 * it can be mounted again without any error message but
++	 * shows as an empty directory. That's going to confuse
++	 * people for sure.
++	 *
++	 * If the mount cannot be umounted (the process is now
++	 * using a stale mount) the offset needs to be invalidated
++	 * so no further mounts will be attempted but the offset
++	 * cache entry must remain so expires can continue to
++	 * attempt to umount it. If the mount can be umounted and
++	 * the offset is removed, at least for NFS we will get
++	 * ESTALE errors when attempting list the directory.
++	 */
+ 	if (oe->ioctlfd != -1 ||
+ 	    is_mounted(oe->key, MNTS_REAL)) {
+-		left++;
+-		return left;
++		if (umount_ent(ap, oe->key) &&
++		    is_mounted(oe->key, MNTS_REAL)) {
++			debug(ap->logopt,
++			      "offset %s has active mount, invalidate",
++			      oe->key);
++			/*
++			 * Ok, so we shouldn't modify the mapent but
++			 * mount requests are blocked at a point above
++			 * this and expire only uses the mapent key.
++			 */
++			if (oe->mapent) {
++				free(oe->mapent);
++				oe->mapent = NULL;
++			}
++			return ++left;
++		}
+ 	}
+ 
+ 	debug(ap->logopt, "umount offset %s", oe->key);
+@@ -2660,6 +2694,11 @@ int mount_multi_triggers(struct autofs_p
+ 		oe = cache_lookup_distinct(me->mc, key);
+ 		if (!oe || !oe->mapent)
+ 			goto cont;
++		if (oe->age != me->multi->age) {
++			/* Best effort */
++			do_umount_offset(ap, oe, root);
++			goto cont;
++		}
+ 
+ 		mounted += do_mount_autofs_offset(ap, oe, root);
+ 
+@@ -2718,170 +2757,4 @@ int umount_multi_triggers(struct autofs_
+ 	}
+ 
+ 	return left;
+-}
+-
+-int clean_stale_multi_triggers(struct autofs_point *ap,
+-			       struct mapent *me, char *top, const char *base)
+-{
+-	char *root;
+-	char mm_top[PATH_MAX + 1];
+-	char path[PATH_MAX + 1];
+-	char *offset;
+-	struct mapent *oe;
+-	struct list_head *mm_root, *pos;
+-	const char o_root[] = "/";
+-	const char *mm_base;
+-	int left, start;
+-	unsigned int root_len;
+-	unsigned int mm_base_len;
+-	time_t age;
+-
+-	if (top)
+-		root = top;
+-	else {
+-		if (!strchr(me->multi->key, '/'))
+-			/* Indirect multi-mount root */
+-			/* sprintf okay - if it's mounted, it's
+-			 * PATH_MAX or less bytes */
+-			sprintf(mm_top, "%s/%s", ap->path, me->multi->key);
+-		else
+-			strcpy(mm_top, me->multi->key);
+-		root = mm_top;
+-	}
+-
+-	left = 0;
+-	start = strlen(root);
+-
+-	mm_root = &me->multi->multi_list;
+-
+-	if (!base)
+-		mm_base = o_root;
+-	else
+-		mm_base = base;
+-
+-	pos = NULL;
+-	offset = path;
+-	root_len = start;
+-	mm_base_len = strlen(mm_base);
+-	age = me->multi->age;
+-
+-	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+-		char key[PATH_MAX + 1];
+-		int key_len = root_len + strlen(offset);
+-		char *oe_base;
+-		int ret;
+-
+-		if (mm_base_len > 1)
+-			key_len += mm_base_len;
+-
+-		if (key_len > PATH_MAX) {
+-			warn(ap->logopt, "path loo long");
+-			continue;
+-		}
+-
+-		strcpy(key, root);
+-		if (mm_base_len > 1)
+-			strcat(key, mm_base);
+-		strcat(key, offset);
+-
+-		oe = cache_lookup_distinct(me->mc, key);
+-		/* root offset is a special case */
+-		if (!oe || (strlen(oe->key) - start) == 1)
+-			continue;
+-
+-		/* Check for and umount stale subtree offsets */
+-		oe_base = oe->key + strlen(root);
+-		ret = clean_stale_multi_triggers(ap, oe, root, oe_base);
+-		left += ret;
+-		if (ret)
+-			continue;
+-
+-		if (oe->age == age)
+-			continue;
+-
+-		/*
+-		 * If an offset that has an active mount has been removed
+-		 * from the multi-mount we don't want to attempt to trigger
+-		 * mounts for it. Obviously this is because it has been
+-		 * removed, but less obvious is the potential strange
+-		 * behaviour that can result if we do try and mount it
+-		 * again after it's been expired. For example, if an NFS
+-		 * file system is no longer exported and is later umounted
+-		 * it can be mounted again without any error message but
+-		 * shows as an empty directory. That's going to confuse
+-		 * people for sure.
+-		 *
+-		 * If the mount cannot be umounted (the process is now
+-		 * using a stale mount) the offset needs to be invalidated
+-		 * so no further mounts will be attempted but the offset
+-		 * cache entry must remain so expires can continue to
+-		 * attempt to umount it. If the mount can be umounted and
+-		 * the offset is removed, at least for NFS we will get
+-		 * ESTALE errors when attempting list the directory.
+-		 */
+-		if (oe->ioctlfd != -1 ||
+-		    is_mounted(oe->key, MNTS_REAL)) {
+-			if (umount_ent(ap, oe->key) &&
+-			    is_mounted(oe->key, MNTS_REAL)) {
+-				debug(ap->logopt,
+-				      "offset %s has active mount, invalidate",
+-				      oe->key);
+-				if (oe->mapent) {
+-					free(oe->mapent);
+-					oe->mapent = NULL;
+-				}
+-				left++;
+-				continue;
+-			}
+-		}
+-
+-		debug(ap->logopt, "umount offset %s", oe->key);
+-
+-		if (umount_autofs_offset(ap, oe)) {
+-			warn(ap->logopt, "failed to umount offset %s", key);
+-			left++;
+-		} else {
+-			struct stat st;
+-
+-			/* Mount point not ours to delete ? */
+-			if (!(oe->flags & MOUNT_FLAG_DIR_CREATED)) {
+-				debug(ap->logopt, "delete offset key %s", key);
+-				if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
+-					error(ap->logopt,
+-					     "failed to delete offset key %s", key);
+-				continue;
+-			}
+-
+-			/*
+-			 * An error due to partial directory removal is
+-			 * ok so only try and remount the offset if the
+-			 * actual mount point still exists.
+-			 */
+-			ret = rmdir_path_offset(ap, oe);
+-			if (ret == -1 && !stat(oe->key, &st)) {
+-				ret = do_mount_autofs_offset(ap, oe, root);
+-				if (ret) {
+-					left++;
+-					/* But we did origianlly create this */
+-					oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-					continue;
+-				}
+-				/*
+-				 * Fall through if the trigger can't be mounted
+-				 * again, since there is no offset there can't
+-				 * be any mount requests so remove the map
+-				 * entry from the cache. There's now a dead
+-				 * offset mount, but what else can we do ....
+-				 */
+-			}
+-
+-			debug(ap->logopt, "delete offset key %s", key);
+-
+-			if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
+-				error(ap->logopt,
+-				     "failed to delete offset key %s", key);
+-		}
+-	}
+-
+-	return left;
+ }
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1178,7 +1178,7 @@ static int mount_subtree(struct autofs_p
+ 
+ 		/* Mount root offset if it exists */
+ 		ro = cache_lookup_distinct(me->mc, key);
+-		if (ro) {
++		if (ro && ro->age == me->multi->age) {
+ 			char *myoptions, *ro_loc;
+ 			int namelen = name ? strlen(name) : 0;
+ 			int ro_len;
+@@ -1612,14 +1612,6 @@ dont_expand:
+ 			free(myoptions);
+ 		} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+ 
+-		/*
+-		 * We've got the ordered list of multi-mount entries so go
+-		 * through and remove any stale entries if this is the top
+-		 * of the multi-mount and set the parent entry of each.
+-		 */
+-		if (me == me->multi)
+-			clean_stale_multi_triggers(ap, me, NULL, NULL);
+-
+ 		rv = mount_subtree(ap, me, name, NULL, options, ctxt);
+ 
+ 		cache_multi_unlock(me);
diff --git a/SOURCES/autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch b/SOURCES/autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch
new file mode 100644
index 0000000..e630e8b
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch
@@ -0,0 +1,132 @@
+autofs-5.1.7 - eliminate count_mounts() from expire_proc_indirect()
+
+From: Ian Kent <raven@themaw.net>
+
+The count_mounts() function traverses the directory tree under a given
+automount in order to count the number of mounts.
+
+If there are many directories (such as when there is a very large
+number of offset trigger mounts) this can take a long time.
+
+Eliminate the call in expire_proc_indirect() by changing the expire
+ioctl function to better use the expire return from the kernel.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/direct.c     |    4 ++--
+ daemon/indirect.c   |   10 +++++-----
+ lib/dev-ioctl-lib.c |   21 +++++++++++++--------
+ 4 files changed, 21 insertions(+), 15 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -19,6 +19,7 @@
+ - pass mapent_cache to update_offset_entry().
+ - fix inconsistent locking in parse_mount().
+ - remove unused mount offset list lock functions.
++- eliminate count_mounts() from expire_proc_indirect().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -884,7 +884,7 @@ cont:
+ 			ioctlfd = me->ioctlfd;
+ 
+ 			ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+-			if (ret) {
++			if (ret == 1) {
+ 				left++;
+ 				pthread_setcancelstate(cur_state, NULL);
+ 				continue;
+@@ -910,7 +910,7 @@ cont:
+ 
+ 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+ 		ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+-		if (ret)
++		if (ret == 1)
+ 			left++;
+ 		pthread_setcancelstate(cur_state, NULL);
+ 	}
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -358,7 +358,6 @@ void *expire_proc_indirect(void *arg)
+ 	struct expire_args ec;
+ 	unsigned int how;
+ 	int offsets, submnts, count;
+-	int retries;
+ 	int ioctlfd, cur_state;
+ 	int status, ret, left;
+ 
+@@ -496,7 +495,7 @@ void *expire_proc_indirect(void *arg)
+ 
+ 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+ 		ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
+-		if (ret)
++		if (ret == 1)
+ 			left++;
+ 		pthread_setcancelstate(cur_state, NULL);
+ 	}
+@@ -507,10 +506,11 @@ void *expire_proc_indirect(void *arg)
+ 	 * so we need to umount or unlink them here.
+ 	 */
+ 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-	retries = (count_mounts(ap, ap->path, ap->dev) + 1);
+-	while (retries--) {
++	while (1) {
+ 		ret = ops->expire(ap->logopt, ap->ioctlfd, ap->path, how);
+-		if (ret)
++		if (ret != 0 && errno == EAGAIN)
++			break;
++		if (ret == 1)
+ 			left++;
+ 	}
+ 	pthread_setcancelstate(cur_state, NULL);
+--- autofs-5.1.4.orig/lib/dev-ioctl-lib.c
++++ autofs-5.1.4/lib/dev-ioctl-lib.c
+@@ -650,6 +650,7 @@ static int expire(unsigned int logopt,
+ {
+ 	int ret, retries = EXPIRE_RETRIES;
+ 	unsigned int may_umount;
++	int save_errno = 0;
+ 
+ 	while (retries--) {
+ 		struct timespec tm = {0, 100000000};
+@@ -657,9 +658,11 @@ static int expire(unsigned int logopt,
+ 		/* Ggenerate expire message for the mount. */
+ 		ret = ioctl(fd, cmd, arg);
+ 		if (ret == -1) {
++			save_errno = errno;
++
+ 			/* Mount has gone away */
+ 			if (errno == EBADF || errno == EINVAL)
+-				return 0;
++				break;
+ 
+ 			/*
+ 			 * Other than EAGAIN is an expire error so continue.
+@@ -673,14 +676,16 @@ static int expire(unsigned int logopt,
+ 		nanosleep(&tm, NULL);
+ 	}
+ 
+-	may_umount = 0;
+-	if (ctl.ops->askumount(logopt, ioctlfd, &may_umount))
+-		return -1;
+-
+-	if (!may_umount)
+-		return 1;
++	if (!ret || save_errno == EAGAIN) {
++		may_umount = 0;
++		if (!ctl.ops->askumount(logopt, ioctlfd, &may_umount)) {
++			if (!may_umount)
++				ret = 1;
++		}
++	}
++	errno = save_errno;
+ 
+-	return 0;
++	return ret;
+ }
+ 
+ static int dev_ioctl_expire(unsigned int logopt,
diff --git a/SOURCES/autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch b/SOURCES/autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch
new file mode 100644
index 0000000..4bb965f
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch
@@ -0,0 +1,82 @@
+autofs-5.1.7 - eliminate redundant cache lookup in tree_mapent_add_node()
+
+From: Ian Kent <raven@themaw.net>
+
+Since we need to create the offset tree after adding the offset entries
+to the mapent cache (from a list.h list) there's no need to lookup the
+mapent in tree_mapent_add_node() and validate it. Just use it directly
+when calling tree_mapent_add_node() and avoid a cache lookup on every
+node addition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/mounts.h    |    2 +-
+ lib/mounts.c        |   13 ++-----------
+ modules/parse_sun.c |    2 +-
+ 4 files changed, 5 insertions(+), 13 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -70,6 +70,7 @@
+ - fix amd hosts mount expire.
+ - fix offset entries order.
+ - use mapent tree root for tree_mapent_add_node().
++- eliminate redundant cache lookup in tree_mapent_add_node().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -170,7 +170,7 @@ void mnts_get_expire_list(struct list_he
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+-int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, const char *key);
++int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, struct mapent *me);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ void tree_mapent_cleanup_offsets(struct mapent *oe);
+ int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1519,19 +1519,10 @@ static void tree_mapent_free(struct tree
+ }
+ 
+ int tree_mapent_add_node(struct mapent_cache *mc,
+-			 struct tree_node *root, const char *key)
++			 struct tree_node *root, struct mapent *me)
+ {
+-	unsigned int logopt = mc->ap->logopt;
+ 	struct tree_node *n;
+ 	struct mapent *parent;
+-	struct mapent *me;
+-
+-	me = cache_lookup_distinct(mc, key);
+-	if (!me) {
+-		error(logopt,
+-		     "failed to find key %s of multi-mount", key);
+-		return 0;
+-	}
+ 
+ 	n = tree_add_node(root, me);
+ 	if (!n)
+@@ -1540,7 +1531,7 @@ int tree_mapent_add_node(struct mapent_c
+ 	MAPENT_SET_ROOT(me, root)
+ 
+ 	/* Set the subtree parent */
+-	parent = cache_get_offset_parent(mc, key);
++	parent = cache_get_offset_parent(mc, me->key);
+ 	if (!parent)
+ 		MAPENT_SET_PARENT(me, root)
+ 	else
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1548,7 +1548,7 @@ dont_expand:
+ 			return 1;
+ 		}
+ 		list_for_each_entry_safe(oe, tmp, &offsets, work) {
+-			if (!tree_mapent_add_node(mc, MAPENT_ROOT(me), oe->key))
++			if (!tree_mapent_add_node(mc, MAPENT_ROOT(me), oe))
+ 				error(ap->logopt, "failed to add offset %s to tree", oe->key);
+ 			list_del_init(&oe->work);
+ 		}
diff --git a/SOURCES/autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch b/SOURCES/autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch
new file mode 100644
index 0000000..03f39ab
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch
@@ -0,0 +1,124 @@
+autofs-5.1.7 - eliminate some strlen calls in offset handling
+
+From: Ian Kent <raven@themaw.net>
+
+There are a number of places where strlen() is used to re-calculate
+the length of a string. Eliminate some of those by calculating the
+length once and passing it to the functions that do the re-calculation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   30 +++++++++++++++++-------------
+ 2 files changed, 18 insertions(+), 13 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -20,6 +20,7 @@
+ - fix inconsistent locking in parse_mount().
+ - remove unused mount offset list lock functions.
+ - eliminate count_mounts() from expire_proc_indirect().
++- eliminate some strlen calls in offset handling.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2534,10 +2534,12 @@ static int rmdir_path_offset(struct auto
+ 	return ret;
+ }
+ 
+-static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root);
++static int do_umount_offset(struct autofs_point *ap,
++			    struct mapent *oe, const char *root, int start);
+ 
+ static int do_umount_multi_triggers(struct autofs_point *ap,
+-				    struct mapent *me, const char *root, const char *base)
++				    struct mapent *me, const char *root,
++				    int start, const char *base)
+ {
+ 	char path[PATH_MAX + 1];
+ 	char *offset;
+@@ -2545,12 +2547,11 @@ static int do_umount_multi_triggers(stru
+ 	struct list_head *mm_root, *pos;
+ 	const char o_root[] = "/";
+ 	const char *mm_base;
+-	int left, start;
++	int left;
+ 	unsigned int root_len;
+ 	unsigned int mm_base_len;
+ 
+ 	left = 0;
+-	start = strlen(root);
+ 
+ 	mm_root = &me->multi->multi_list;
+ 
+@@ -2586,13 +2587,14 @@ static int do_umount_multi_triggers(stru
+ 		if (!oe || (strlen(oe->key) - start) == 1)
+ 			continue;
+ 
+-		left += do_umount_offset(ap, oe, root);
++		left += do_umount_offset(ap, oe, root, start);
+ 	}
+ 
+ 	return left;
+ }
+ 
+-static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root)
++static int do_umount_offset(struct autofs_point *ap,
++			    struct mapent *oe, const char *root, int start)
+ {
+ 	char *oe_base;
+ 	int left = 0;
+@@ -2601,8 +2603,8 @@ static int do_umount_offset(struct autof
+ 	 * Check for and umount subtree offsets resulting from
+ 	 * nonstrict mount fail.
+ 	 */
+-	oe_base = oe->key + strlen(root);
+-	left += do_umount_multi_triggers(ap, oe, root, oe_base);
++	oe_base = oe->key + start;
++	left += do_umount_multi_triggers(ap, oe, root, start, oe_base);
+ 
+ 	/*
+ 	 * If an offset that has an active mount has been removed
+@@ -2706,7 +2708,7 @@ int mount_multi_triggers(struct autofs_p
+ 			goto cont;
+ 		if (oe->age != me->multi->age) {
+ 			/* Best effort */
+-			do_umount_offset(ap, oe, root);
++			do_umount_offset(ap, oe, root, start);
+ 			goto cont;
+ 		}
+ 
+@@ -2720,7 +2722,7 @@ int mount_multi_triggers(struct autofs_p
+ 		if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+ 			if (oe->ioctlfd != -1 ||
+ 			    is_mounted(oe->key, MNTS_REAL))
+-				mount_multi_triggers(ap, oe, key, strlen(key), base);
++				mount_multi_triggers(ap, oe, key, key_len, base);
+ 		}
+ cont:
+ 		offset = cache_get_offset(base,
+@@ -2732,9 +2734,11 @@ cont:
+ 
+ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
+ {
+-	int left;
++	int left, start;
++
++	start = strlen(root);
+ 
+-	left = do_umount_multi_triggers(ap, me, root, base);
++	left = do_umount_multi_triggers(ap, me, root, start, base);
+ 
+ 	if (!left && me->multi == me) {
+ 		/*
+@@ -2747,7 +2751,7 @@ int umount_multi_triggers(struct autofs_
+ 			info(ap->logopt, "unmounting dir = %s", root);
+ 			if (umount_ent(ap, root) &&
+ 			    is_mounted(root, MNTS_REAL)) {
+-				if (mount_multi_triggers(ap, me, root, strlen(root), "/") < 0)
++				if (mount_multi_triggers(ap, me, root, start, "/") < 0)
+ 					warn(ap->logopt,
+ 					     "failed to remount offset triggers");
+ 				return ++left;
diff --git a/SOURCES/autofs-5.1.7-fix-amd-hosts-mount-expire.patch b/SOURCES/autofs-5.1.7-fix-amd-hosts-mount-expire.patch
new file mode 100644
index 0000000..5087c74
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-amd-hosts-mount-expire.patch
@@ -0,0 +1,48 @@
+autofs-5.1.7 - fix amd hosts mount expire
+
+From: Ian Kent <raven@themaw.net>
+
+When swicthing to use the mnt_list to track mounts for expire, if the
+amd hosts map entry name is for the host short name, the amd mount
+entry for the short name gets removed. This causes a subsequent mounts
+for host exports to fail.
+
+What should happen is the short name amd entry not be removed and a
+mounted mount entry for the symlinked FQDN mount added so it expires.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_amd.c |    9 +++++----
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -67,6 +67,7 @@
+ - cater for empty mounts list in mnts_get_expire_list().
+ - add ext_mount_hash_mutex lock helpers.
+ - fix amd section mounts map reload.
++- fix amd hosts mount expire.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_amd.c
++++ autofs-5.1.4/modules/parse_amd.c
+@@ -2341,12 +2341,13 @@ int parse_mount(struct autofs_point *ap,
+ 		if (!rv) {
+ 			/*
+ 			 * If entry->path doesn't match the mnt->mp then
+-			 * the mount point path has changed and a new
+-			 * mnt_list entry added for it, so remove the
+-			 * original.
++			 * it's a "host" map and the mount point path is
++			 * different to the lookup name. Add a new mnt_list
++			 * entry so that both the symlinked name and the
++			 * mount expire.
+ 			 */
+ 			if (strcmp(this->path, mnt->mp))
+-				mnts_remove_amdmount(this->path);
++				mnts_add_mount(ap, this->rhost, MNTS_INDIRECT|MNTS_MOUNTED);
+ 			break;
+ 		}
+ 		/* Not mounted, remove the mnt_list entry from amdmount list */
diff --git a/SOURCES/autofs-5.1.7-fix-amd-section-mounts-map-reload.patch b/SOURCES/autofs-5.1.7-fix-amd-section-mounts-map-reload.patch
new file mode 100644
index 0000000..572ba6d
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-amd-section-mounts-map-reload.patch
@@ -0,0 +1,120 @@
+autofs-5.1.7 - fix amd section mounts map reload
+
+From: Ian Kent <raven@themaw.net>
+
+Master map section mounts (amd format mounts) get umounted on reload.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 
+ daemon/master.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 81 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -66,6 +66,7 @@
+ - refactor lookup_prune_one_cache() a bit.
+ - cater for empty mounts list in mnts_get_expire_list().
+ - add ext_mount_hash_mutex lock helpers.
++- fix amd section mounts map reload.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/master.c
++++ autofs-5.1.4/daemon/master.c
+@@ -882,6 +882,83 @@ struct master *master_new(const char *na
+ 	return master;
+ }
+ 
++static void master_update_amd_mount_section_mount(struct master *master,
++						  const char *path, time_t age)
++{
++	unsigned int m_logopt = master->logopt;
++	struct master_mapent *entry;
++	struct map_source *source;
++	unsigned int loglevel;
++	unsigned int logopt;
++	unsigned int flags;
++	time_t timeout;
++	char *map;
++	char *opts;
++
++	entry = master_find_mapent(master, path);
++	if (!entry)
++		return;
++
++	map = conf_amd_get_map_name(path);
++	if (!map)
++		return;
++
++	/* amd top level mounts have only one map */
++	source = entry->maps;
++	if (strcmp(source->name, map) != 0) {
++		struct map_source *new;
++		char *type;
++		char *argv[2];
++
++		type = conf_amd_get_map_type(path);
++		argv[0] = map;
++		argv[1] = NULL;
++
++		new = master_add_map_source(entry, type, "amd",
++					    age, 1, (const char **) argv);
++		if (!new) {
++			error(m_logopt,
++			      "failed to add source for amd section mount %s",
++			      path);
++			if (type)
++				free(type);
++			goto out;
++		}
++		master_free_map_source(source, 0);
++		entry->maps = new;
++		source = new;
++		if (type)
++			free(type);
++	}
++
++	loglevel = conf_amd_get_log_options();
++	logopt = m_logopt;
++	if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
++		logopt = LOGOPT_DEBUG;
++	else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
++		logopt = LOGOPT_VERBOSE;
++
++	flags = conf_amd_get_flags(path);
++	if (flags & CONF_BROWSABLE_DIRS)
++		entry->ap->flags |= MOUNT_FLAG_GHOST;
++
++	opts = conf_amd_get_map_options(path);
++	if (opts) {
++		if (strstr(opts, "cache:=all"))
++			entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
++		free(opts);
++	}
++
++	entry->ap->logopt = logopt;
++
++	timeout = conf_amd_get_dismount_interval(path);
++	set_exp_timeout(entry->ap, source, timeout);
++	source->master_line = 0;
++	entry->age = age;
++out:
++	free(map);
++}
++
+ static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
+ {
+ 	unsigned int m_logopt = master->logopt;
+@@ -916,8 +993,10 @@ static void master_add_amd_mount_section
+ 			 * master map it's not a duplicate, don't issue
+ 			 * an error message.
+ 			 */
+-			if (ret == 1)
++			if (ret == 1) {
++				master_update_amd_mount_section_mount(master, path, age);
+ 				goto next;
++			}
+ 			info(m_logopt,
+ 			     "amd section mount path conflict, %s ignored",
+ 			     path);
diff --git a/SOURCES/autofs-5.1.7-fix-arg-not-used-in-print.patch b/SOURCES/autofs-5.1.7-fix-arg-not-used-in-print.patch
new file mode 100644
index 0000000..69196bf
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-arg-not-used-in-print.patch
@@ -0,0 +1,36 @@
+autofs-5.1.7 - fix arg not used in error print
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: extra_argument: This argument was not used by the format
+	  string: "key".
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    4 +---
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -60,6 +60,7 @@
+ - dont try umount after stat() ENOENT fail.
+ - remove redundant assignment in master_add_amd_mount_section_mounts().
+ - fix dead code in mnts_add_mount().
++- fix arg not used in error print.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1519,9 +1519,7 @@ int tree_mapent_add_node(struct mapent_c
+ 	}
+ 
+ 	if (MAPENT_ROOT(base) != MAPENT_NODE(base)) {
+-		error(logopt,
+-		     "failed to find multi-mount root of offset tree",
+-		     key);
++		error(logopt, "key %s is not multi-mount root", root);
+ 		return 0;
+ 	}
+ 	tree = MAPENT_ROOT(base);
diff --git a/SOURCES/autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch b/SOURCES/autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch
new file mode 100644
index 0000000..c83d273
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch
@@ -0,0 +1,51 @@
+autofs-5.1.7 - fix dead code in mnts_add_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: dead_error_line: Execution cannot reach this statement: "free(mp);".
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    8 ++------
+ 2 files changed, 3 insertions(+), 6 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -59,6 +59,7 @@
+ - fix flags check in umount_multi().
+ - dont try umount after stat() ENOENT fail.
+ - remove redundant assignment in master_add_amd_mount_section_mounts().
++- fix dead code in mnts_add_mount().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1205,13 +1205,13 @@ struct mnt_list *mnts_add_mount(struct a
+ 	if (*name == '/') {
+ 		mp = strdup(name);
+ 		if (!mp)
+-			goto fail;
++			return NULL;
+ 	} else {
+ 		int len = ap->len + strlen(name) + 2;
+ 
+ 		mp = malloc(len);
+ 		if (!mp)
+-			goto fail;
++			return NULL;
+ 		strcpy(mp, ap->path);
+ 		strcat(mp, "/");
+ 		strcat(mp, name);
+@@ -1228,10 +1228,6 @@ struct mnt_list *mnts_add_mount(struct a
+ 	free(mp);
+ 
+ 	return this;
+-fail:
+-	if (mp)
+-		free(mp);
+-	return NULL;
+ }
+ 
+ void mnts_remove_mount(const char *mp, unsigned int flags)
diff --git a/SOURCES/autofs-5.1.7-fix-direct-mount-deadlock.patch b/SOURCES/autofs-5.1.7-fix-direct-mount-deadlock.patch
new file mode 100644
index 0000000..ebe8930
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-direct-mount-deadlock.patch
@@ -0,0 +1,129 @@
+autofs-5.1.7 - fix direct mount deadlock
+
+From: Ian Kent <raven@themaw.net>
+
+When umounting direct mounts at exit or when umounting mounts no
+longer in the map on re-load a deadlock can occur.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/direct.c |   22 +++++++++++++++++++++-
+ daemon/state.c  |   14 +++++++++-----
+ 3 files changed, 31 insertions(+), 6 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -72,6 +72,7 @@
+ - use mapent tree root for tree_mapent_add_node().
+ - eliminate redundant cache lookup in tree_mapent_add_node().
+ - fix hosts map offset order.
++- fix direct mount deadlock.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -84,11 +84,27 @@ static void mnts_cleanup(void *arg)
+ int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me)
+ {
+ 	struct ioctl_ops *ops = get_ioctl_ops();
++	struct mapent_cache *mc = me->mc;
+ 	char buf[MAX_ERR_BUF];
+ 	int ioctlfd = -1, rv, left, retries;
++	char key[PATH_MAX + 1];
++	struct mapent *tmp;
+ 	int opened = 0;
+ 
+-	left = umount_multi(ap, me->key, 0);
++	if (me->len > PATH_MAX) {
++		error(ap->logopt, "path too long");
++		return 1;
++	}
++	strcpy(key, me->key);
++
++	cache_unlock(mc);
++	left = umount_multi(ap, key, 0);
++	cache_readlock(mc);
++	tmp = cache_lookup_distinct(mc, key);
++	if (tmp != me) {
++		error(ap->logopt, "key %s no longer in mapent cache", key);
++		return -1;
++	}
+ 	if (left) {
+ 		warn(ap->logopt, "could not unmount %d dirs under %s",
+ 		     left, me->key);
+@@ -213,6 +229,7 @@ int umount_autofs_direct(struct autofs_p
+ 		mc = map->mc;
+ 		pthread_cleanup_push(cache_lock_cleanup, mc);
+ 		cache_readlock(mc);
++restart:
+ 		me = cache_enumerate(mc, NULL);
+ 		while (me) {
+ 			int error;
+@@ -230,6 +247,9 @@ int umount_autofs_direct(struct autofs_p
+ 			 * failed umount.
+ 			 */
+ 			error = do_umount_autofs_direct(ap, me);
++			/* cache became invalid, restart */
++			if (error == -1)
++				goto restart;
+ 			if (!error)
+ 				goto done;
+ 
+--- autofs-5.1.4.orig/daemon/state.c
++++ autofs-5.1.4/daemon/state.c
+@@ -348,11 +348,12 @@ static void do_readmap_cleanup(void *arg
+ 	return;
+ }
+ 
+-static void do_readmap_mount(struct autofs_point *ap,
++static int do_readmap_mount(struct autofs_point *ap,
+ 			     struct map_source *map, struct mapent *me, time_t now)
+ {
+ 	struct mapent_cache *nc;
+ 	struct mapent *ne, *nested, *valid;
++	int ret = 0;
+ 
+ 	nc = ap->entry->master->nc;
+ 
+@@ -411,7 +412,7 @@ static void do_readmap_mount(struct auto
+ 				cache_unlock(vmc);
+ 				error(ap->logopt,
+ 				     "failed to find expected existing valid map entry");
+-				return;
++				return ret;
+ 			}
+ 			/* Take over the mount if there is one */
+ 			valid->ioctlfd = me->ioctlfd;
+@@ -430,14 +431,14 @@ static void do_readmap_mount(struct auto
+ 					ap->exp_runfreq = runfreq;
+ 			}
+ 		} else if (!is_mounted(me->key, MNTS_REAL))
+-			do_umount_autofs_direct(ap, me);
++			ret = do_umount_autofs_direct(ap, me);
+ 		else
+ 			debug(ap->logopt,
+ 			      "%s is mounted", me->key);
+ 	} else
+ 		do_mount_autofs_direct(ap, me, get_exp_timeout(ap, map));
+ 
+-	return;
++	return ret;
+ }
+ 
+ static void *do_readmap(void *arg)
+@@ -504,9 +505,12 @@ static void *do_readmap(void *arg)
+ 			mc = map->mc;
+ 			pthread_cleanup_push(cache_lock_cleanup, mc);
+ 			cache_readlock(mc);
++restart:
+ 			me = cache_enumerate(mc, NULL);
+ 			while (me) {
+-				do_readmap_mount(ap, map, me, now);
++				int ret = do_readmap_mount(ap, map, me, now);
++				if (ret == -1)
++					goto restart;
+ 				me = cache_enumerate(mc, me);
+ 			}
+ 			lookup_prune_one_cache(ap, map->mc, now);
diff --git a/SOURCES/autofs-5.1.7-fix-double-free-in-parse_mapent.patch b/SOURCES/autofs-5.1.7-fix-double-free-in-parse_mapent.patch
new file mode 100644
index 0000000..3d39c28
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-double-free-in-parse_mapent.patch
@@ -0,0 +1,35 @@
+autofs-5.1.7 - fix double free in parse_mapent()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity:
+in parse_mapent(): double_free: Calling "free" frees pointer "newopt"
+		   which has already been freed.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |    2 --
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -62,6 +62,7 @@
+ - fix dead code in mnts_add_mount().
+ - fix arg not used in error print.
+ - fix missing lock release in mount_subtree().
++- fix double free in parse_mapent().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -976,8 +976,6 @@ static int parse_mapent(const char *ent,
+ 					estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ 					error(logopt, MODPREFIX
+ 					      "concat_options: %s", estr);
+-					if (newopt)
+-						free(newopt);
+ 					free(myoptions);
+ 					return 0;
+ 				}
diff --git a/SOURCES/autofs-5.1.7-fix-double-unlock-in-parse_mount.patch b/SOURCES/autofs-5.1.7-fix-double-unlock-in-parse_mount.patch
new file mode 100644
index 0000000..ad68849
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-double-unlock-in-parse_mount.patch
@@ -0,0 +1,33 @@
+autofs-5.1.7 - fix double unlock in parse_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: double_unlock: "cache_unlock" unlocks "mc->rwlock" while it
+	  is unlocked.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |    1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -54,6 +54,7 @@
+ - remove redundant if check.
+ - fix possible memory leak in master_parse().
+ - fix possible memory leak in mnts_add_amdmount().
++- fix double unlock in parse_mount().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1528,7 +1528,6 @@ dont_expand:
+ 			if (!loc) {
+ 				free(options);
+ 				free(pmapent);
+-				cache_unlock(mc);
+ 				warn(ap->logopt, MODPREFIX "out of memory");
+ 				return 1;
+ 			}
diff --git a/SOURCES/autofs-5.1.7-fix-flag-check-in-umount_multi.patch b/SOURCES/autofs-5.1.7-fix-flag-check-in-umount_multi.patch
new file mode 100644
index 0000000..5921abd
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-flag-check-in-umount_multi.patch
@@ -0,0 +1,34 @@
+autofs-5.1.7 - fix flags check in umount_multi()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: operator_confusion: "ap->flags | 1" is always 1/true
+	  regardless of the values of its operand.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -56,6 +56,7 @@
+ - fix possible memory leak in mnts_add_amdmount().
+ - fix double unlock in parse_mount().
+ - add length check in umount_subtree_mounts().
++- fix flags check in umount_multi().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -661,7 +661,7 @@ int umount_multi(struct autofs_point *ap
+ 		/* Check if the autofs mount has browse mode enabled.
+ 		 * If so re-create the directory entry.
+ 		 */
+-		if (ap->flags | MOUNT_FLAG_GHOST) {
++		if (ap->flags & MOUNT_FLAG_GHOST) {
+ 			int ret;
+ 
+ 			/* If the browse directory create fails log an
diff --git a/SOURCES/autofs-5.1.7-fix-hosts-map-offset-order.patch b/SOURCES/autofs-5.1.7-fix-hosts-map-offset-order.patch
new file mode 100644
index 0000000..e9b07d6
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-hosts-map-offset-order.patch
@@ -0,0 +1,289 @@
+autofs-5.1.7 - fix hosts map offset order
+
+From: Ian Kent <raven@themaw.net>
+
+Map entry offset paths to be in shortest to longest order but exports
+from a server could come in any order. If there are a large number of
+exports this can result in a lot of overhead when adding the offset
+to the ordered list use to mount the offset during parsing since the
+path length of exports can cary a lot.
+
+So leverage the tree implemention to sort the export offsets into
+shortest to longest order as we go when constructing the mapent from
+the exports list.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 
+ include/automount.h    |    2 -
+ include/mounts.h       |    8 +++++
+ include/rpc_subs.h     |    3 ++
+ lib/mounts.c           |   57 +++++++++++++++++++++++++++++++++++++--
+ modules/lookup_hosts.c |   71 ++++++++++++++++++++++++++++++++++++++-----------
+ 6 files changed, 124 insertions(+), 18 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -71,6 +71,7 @@
+ - fix offset entries order.
+ - use mapent tree root for tree_mapent_add_node().
+ - eliminate redundant cache lookup in tree_mapent_add_node().
++- fix hosts map offset order.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -31,9 +31,9 @@
+ #include "master.h"
+ #include "macros.h"
+ #include "log.h"
++#include "mounts.h"
+ #include "rpc_subs.h"
+ #include "parse_subs.h"
+-#include "mounts.h"
+ #include "dev-ioctl-lib.h"
+ #include "parse_amd.h"
+ 
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -52,6 +52,7 @@ extern const unsigned int t_direct;
+ extern const unsigned int t_offset;
+ 
+ struct mnt_list;
++struct exportinfo;
+ struct mapent;
+ 
+ struct tree_ops;
+@@ -66,6 +67,9 @@ struct tree_node {
+ #define MNT_LIST(n)		(container_of(n, struct mnt_list, node))
+ #define MNT_LIST_NODE(ptr)	((struct tree_node *) &((struct mnt_list *) ptr)->node)
+ 
++#define EXPORTINFO(n)		(container_of(n, struct exportinfo, node))
++#define EXPORT_NODE(ptr)	((struct tree_node *) &((struct exportinfo *) ptr)->node)
++
+ #define MAPENT(n)		(container_of(n, struct mapent, node))
+ #define MAPENT_NODE(p)		((struct tree_node *) &((struct mapent *) p)->node)
+ #define MAPENT_ROOT(p)		((struct tree_node *) ((struct mapent *) p)->mm_root)
+@@ -166,9 +170,13 @@ struct mnt_list *mnts_add_mount(struct a
+ void mnts_remove_mount(const char *mp, unsigned int flags);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+ unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
++int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr);
++void tree_free(struct tree_node *root);
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
++struct tree_node *tree_host_root(struct exportinfo *exp);
++struct tree_node *tree_host_add_node(struct tree_node *root, struct exportinfo *exp);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+ int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, struct mapent *me);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+--- autofs-5.1.4.orig/include/rpc_subs.h
++++ autofs-5.1.4/include/rpc_subs.h
+@@ -23,6 +23,8 @@
+ #include <linux/nfs2.h>
+ #include <linux/nfs3.h>
+ 
++#include "automount.h"
++
+ #define NFS4_VERSION		4
+ 
+ /* rpc helper subs */
+@@ -57,6 +59,7 @@ struct exportinfo {
+ 	char *dir;
+ 	struct hostinfo *hosts;
+ 	struct exportinfo *next;
++	struct tree_node node;
+ };
+ 
+ struct conn_info {
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -79,6 +79,17 @@ static struct tree_ops mnt_ops = {
+ };
+ static struct tree_ops *tree_mnt_ops = &mnt_ops;
+ 
++static struct tree_node *tree_host_new(void *ptr);
++static int tree_host_cmp(struct tree_node *n, void *ptr);
++static void tree_host_free(struct tree_node *n);
++
++static struct tree_ops host_ops = {
++	.new = tree_host_new,
++	.cmp = tree_host_cmp,
++	.free = tree_host_free,
++};
++static struct tree_ops *tree_host_ops = &host_ops;
++
+ static struct tree_node *tree_mapent_new(void *ptr);
+ static int tree_mapent_cmp(struct tree_node *n, void *ptr);
+ static void tree_mapent_free(struct tree_node *n);
+@@ -1341,7 +1352,7 @@ static struct tree_node *tree_add_node(s
+ 	return NULL;
+ }
+ 
+-static void tree_free(struct tree_node *root)
++void tree_free(struct tree_node *root)
+ {
+ 	struct tree_ops *ops = root->ops;
+ 
+@@ -1352,7 +1363,7 @@ static void tree_free(struct tree_node *
+ 	ops->free(root);
+ }
+ 
+-static int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr)
++int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr)
+ {
+ 	int ret;
+ 
+@@ -1479,6 +1490,48 @@ void mnts_put_expire_list(struct list_he
+ 	mnts_hash_mutex_unlock();
+ }
+ 
++struct tree_node *tree_host_root(struct exportinfo *exp)
++{
++	return tree_root(tree_host_ops, exp);
++}
++
++static struct tree_node *tree_host_new(void *ptr)
++{
++	struct tree_node *n = EXPORT_NODE(ptr);
++
++	n->ops = tree_host_ops;
++	n->left = NULL;
++	n->right = NULL;
++
++	return n;
++}
++
++static int tree_host_cmp(struct tree_node *n, void *ptr)
++{
++	struct exportinfo *n_exp = EXPORTINFO(n);
++	size_t n_exp_len = strlen(n_exp->dir);
++	struct exportinfo *exp = ptr;
++	size_t exp_len = strlen(exp->dir);
++	int eq;
++
++	eq = strcmp(exp->dir, n_exp->dir);
++	if (!eq)
++		return 0;
++	return (exp_len < n_exp_len) ? -1 : 1;
++}
++
++static void tree_host_free(struct tree_node *n)
++{
++	n->ops = NULL;
++	n->left = NULL;
++	n->right = NULL;
++}
++
++struct tree_node *tree_host_add_node(struct tree_node *root, struct exportinfo *exp)
++{
++	return tree_add_node(root, exp);
++}
++
+ struct tree_node *tree_mapent_root(struct mapent *me)
+ {
+ 	return tree_root(tree_mapent_ops, me);
+--- autofs-5.1.4.orig/modules/lookup_hosts.c
++++ autofs-5.1.4/modules/lookup_hosts.c
+@@ -84,14 +84,38 @@ int lookup_read_master(struct master *ma
+ 	return NSS_STATUS_UNKNOWN;
+ }
+ 
++struct work_info {
++	char *mapent;
++	const char *host;
++	int pos;
++};
++
++static int tree_host_work(struct tree_node *n, void *ptr)
++{
++	struct exportinfo *exp = EXPORTINFO(n);
++	struct work_info *wi = ptr;
++	int len;
++
++	if (!wi->pos)
++		len = sprintf(wi->mapent, "\"%s\" \"%s:%s\"",
++				exp->dir, wi->host, exp->dir);
++	else
++		len = sprintf(wi->mapent + wi->pos, " \"%s\" \"%s:%s\"",
++				exp->dir, wi->host, exp->dir);
++	wi->pos += len;
++
++	return 1;
++}
++
+ static char *get_exports(struct autofs_point *ap, const char *host)
+ {
+ 	char buf[MAX_ERR_BUF];
+ 	char *mapent;
+ 	struct exportinfo *exp, *this;
++	struct tree_node *tree = NULL;
++	struct work_info wi;
+ 	size_t hostlen = strlen(host);
+ 	size_t mapent_len;
+-	int len, pos;
+ 
+ 	debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+ 
+@@ -100,7 +124,28 @@ static char *get_exports(struct autofs_p
+ 	this = exp;
+ 	mapent_len = 0;
+ 	while (this) {
++		struct tree_node *n;
++
+ 		mapent_len += hostlen + 2*(strlen(this->dir) + 2) + 3;
++
++		if (!tree) {
++			tree = tree_host_root(this);
++			if (!tree) {
++				error(ap->logopt, "failed to create exports tree root");
++				rpc_exports_free(exp);
++				return NULL;
++			}
++			goto next;
++		}
++
++		n = tree_host_add_node(tree, this);
++		if (!n) {
++			error(ap->logopt, "failed to add exports tree node");
++			tree_free(tree);
++			rpc_exports_free(exp);
++			return NULL;
++		}
++next:
+ 		this = this->next;
+ 	}
+ 
+@@ -115,20 +160,16 @@ static char *get_exports(struct autofs_p
+ 	}
+ 	*mapent = 0;
+ 
+-	pos = 0;
+-	this = exp;
+-	if (this) {
+-		len = sprintf(mapent, "\"%s\" \"%s:%s\"",
+-				this->dir, host, this->dir);
+-		pos += len;
+-		this = this->next;
+-	}
+-
+-	while (this) {
+-		len = sprintf(mapent + pos, " \"%s\" \"%s:%s\"",
+-				this->dir, host, this->dir);
+-		pos += len;
+-		this = this->next;
++	wi.mapent = mapent;
++	wi.host = host;
++	wi.pos = 0;
++
++	if (!tree) {
++		free(mapent);
++		mapent = NULL;
++	} else {
++		tree_traverse_inorder(tree, tree_host_work, &wi);
++		tree_free(tree);
+ 	}
+ 	rpc_exports_free(exp);
+ 
diff --git a/SOURCES/autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch b/SOURCES/autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch
new file mode 100644
index 0000000..a36338c
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch
@@ -0,0 +1,245 @@
+autofs-5.1.7 - fix inconsistent locking in parse_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+Some map entry cache locking inconsistencies have crept in.
+
+In parse_mount() of the sun format parser the cache read lock is too
+heavily used and has too broad a scope. This has lead to some operations
+that should hold the write lock being called with only the read lock.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ lib/mounts.c        |    9 +++++++-
+ modules/parse_sun.c |   53 ++++++++++++++++++++++++++++++++--------------------
+ 3 files changed, 42 insertions(+), 21 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -17,6 +17,7 @@
+ - fix inconsistent locking in umount_subtree_mounts().
+ - fix return from umount_subtree_mounts() on offset list delete.
+ - pass mapent_cache to update_offset_entry().
++- fix inconsistent locking in parse_mount().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2485,6 +2485,12 @@ static int do_mount_autofs_offset(struct
+ 		else {
+ 			debug(ap->logopt, "ignoring \"nohide\" trigger %s",
+ 			      oe->key);
++			/*
++			 * Ok, so we shouldn't modify the mapent but
++			 * mount requests are blocked at a point above
++			 * this and expire only uses the mapent key or
++			 * holds the cache write lock.
++			 */
+ 			free(oe->mapent);
+ 			oe->mapent = NULL;
+ 		}
+@@ -2628,7 +2634,8 @@ static int do_umount_offset(struct autof
+ 			/*
+ 			 * Ok, so we shouldn't modify the mapent but
+ 			 * mount requests are blocked at a point above
+-			 * this and expire only uses the mapent key.
++			 * this and expire only uses the mapent key or
++			 * holds the cache write lock.
+ 			 */
+ 			if (oe->mapent) {
+ 				free(oe->mapent);
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -853,10 +853,12 @@ update_offset_entry(struct autofs_point
+ 			strcpy(m_mapent, loc);
+ 	}
+ 
++	cache_writelock(mc);
+ 	ret = cache_update_offset(mc, name, m_key, m_mapent, age);
+ 
+ 	if (!cache_set_offset_parent(mc, m_key))
+ 		error(ap->logopt, "failed to set offset parent");
++	cache_unlock(mc);
+ 
+ 	if (ret == CHE_DUPLICATE) {
+ 		warn(ap->logopt, MODPREFIX
+@@ -1130,14 +1132,22 @@ static void cleanup_multi_triggers(struc
+ 	return;
+ }
+ 
+-static int mount_subtree(struct autofs_point *ap, struct mapent *me,
++static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+ 			 const char *name, char *loc, char *options, void *ctxt)
+ {
++	struct mapent *me;
+ 	struct mapent *ro;
+ 	char *mm_root, *mm_base, *mm_key;
+ 	unsigned int mm_root_len;
+ 	int start, ret = 0, rv;
+ 
++	cache_readlock(mc);
++	me = cache_lookup_distinct(mc, name);
++	if (!me) {
++		cache_unlock(mc);
++		return 0;
++	}
++
+ 	rv = 0;
+ 
+ 	mm_key = me->multi->key;
+@@ -1182,9 +1192,12 @@ static int mount_subtree(struct autofs_p
+ 			rv = parse_mapent(ro->mapent,
+ 				options, &myoptions, &ro_loc, ap->logopt);
+ 			if (!rv) {
++				cache_unlock(mc);
+ 				warn(ap->logopt,
+ 				      MODPREFIX "failed to parse root offset");
+-				cache_delete_offset_list(me->mc, name);
++				cache_writelock(mc);
++				cache_delete_offset_list(mc, name);
++				cache_unlock(mc);
+ 				return 1;
+ 			}
+ 			ro_len = 0;
+@@ -1201,9 +1214,10 @@ static int mount_subtree(struct autofs_p
+ 		if ((ro && rv == 0) || rv <= 0) {
+ 			ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+ 			if (ret == -1) {
++				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++				cache_unlock(mc);
+ 				error(ap->logopt, MODPREFIX
+ 					 "failed to mount offset triggers");
+-				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+ 				return 1;
+ 			}
+ 		}
+@@ -1219,9 +1233,10 @@ static int mount_subtree(struct autofs_p
+ 		if (rv == 0) {
+ 			ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
+ 			if (ret == -1) {
++				cleanup_multi_triggers(ap, me, name, start, mm_base);
++				cache_unlock(mc);
+ 				error(ap->logopt, MODPREFIX
+ 					 "failed to mount offset triggers");
+-				cleanup_multi_triggers(ap, me, name, start, mm_base);
+ 				return 1;
+ 			}
+ 		} else if (rv < 0) {
+@@ -1229,8 +1244,11 @@ static int mount_subtree(struct autofs_p
+ 			unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
+ 	
+ 			if (mm_root_base_len > PATH_MAX) {
++				cache_unlock(mc);
+ 				warn(ap->logopt, MODPREFIX "path too long");
+-				cache_delete_offset_list(me->mc, name);
++				cache_writelock(mc);
++				cache_delete_offset_list(mc, name);
++				cache_unlock(mc);
+ 				return 1;
+ 			}
+ 
+@@ -1239,13 +1257,15 @@ static int mount_subtree(struct autofs_p
+ 
+ 			ret = mount_multi_triggers(ap, me->multi, mm_root_base, start, mm_base);
+ 			if (ret == -1) {
++				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++				cache_unlock(mc);
+ 				error(ap->logopt, MODPREFIX
+ 					 "failed to mount offset triggers");
+-				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+ 				return 1;
+ 			}
+ 		}
+ 	}
++	cache_unlock(mc);
+ 
+ 	/* Mount for base of tree failed */
+ 	if (rv > 0)
+@@ -1486,7 +1506,6 @@ dont_expand:
+ 			return 1;
+ 		}
+ 
+-		cache_multi_writelock(me);
+ 		/* So we know we're the multi-mount root */
+ 		if (!me->multi)
+ 			me->multi = me;
+@@ -1511,14 +1530,13 @@ dont_expand:
+ 			if (source->flags & MAP_FLAG_FORMAT_AMD) {
+ 				free(options);
+ 				free(pmapent);
+-				cache_multi_unlock(me);
+ 				cache_unlock(mc);
+ 				pthread_setcancelstate(cur_state, NULL);
+ 				return 0;
+ 			}
+ 		}
+-
+ 		age = me->age;
++		cache_unlock(mc);
+ 
+ 		/* It's a multi-mount; deal with it */
+ 		do {
+@@ -1539,8 +1557,8 @@ dont_expand:
+ 
+ 			if (!path) {
+ 				warn(ap->logopt, MODPREFIX "null path or out of memory");
++				cache_writelock(mc);
+ 				cache_delete_offset_list(mc, name);
+-				cache_multi_unlock(me);
+ 				cache_unlock(mc);
+ 				free(options);
+ 				free(pmapent);
+@@ -1556,8 +1574,8 @@ dont_expand:
+ 
+ 			l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
+ 			if (!l) {
++				cache_writelock(mc);
+ 				cache_delete_offset_list(mc, name);
+-				cache_multi_unlock(me);
+ 				cache_unlock(mc);
+ 				free(path);
+ 				free(options);
+@@ -1575,8 +1593,8 @@ dont_expand:
+ 
+ 			if (status != CHE_OK) {
+ 				warn(ap->logopt, MODPREFIX "error adding multi-mount");
++				cache_writelock(mc);
+ 				cache_delete_offset_list(mc, name);
+-				cache_multi_unlock(me);
+ 				cache_unlock(mc);
+ 				free(path);
+ 				free(options);
+@@ -1594,10 +1612,7 @@ dont_expand:
+ 			free(myoptions);
+ 		} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+ 
+-		rv = mount_subtree(ap, me, name, NULL, options, ctxt);
+-
+-		cache_multi_unlock(me);
+-		cache_unlock(mc);
++		rv = mount_subtree(ap, mc, name, NULL, options, ctxt);
+ 
+ 		free(options);
+ 		free(pmapent);
+@@ -1618,6 +1633,7 @@ dont_expand:
+ 		cache_readlock(mc);
+ 		if (*name == '/' &&
+ 		   (me = cache_lookup_distinct(mc, name)) && me->multi) {
++			cache_unlock(mc);
+ 			loc = strdup(p);
+ 			if (!loc) {
+ 				free(options);
+@@ -1626,10 +1642,7 @@ dont_expand:
+ 				warn(ap->logopt, MODPREFIX "out of memory");
+ 				return 1;
+ 			}
+-			cache_multi_writelock(me);
+-			rv = mount_subtree(ap, me, name, loc, options, ctxt);
+-			cache_multi_unlock(me);
+-			cache_unlock(mc);
++			rv = mount_subtree(ap, mc, name, loc, options, ctxt);
+ 			free(loc);
+ 			free(options);
+ 			free(pmapent);
diff --git a/SOURCES/autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch b/SOURCES/autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch
new file mode 100644
index 0000000..1a9dbfa
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch
@@ -0,0 +1,129 @@
+autofs-5.1.7 - fix inconsistent locking in umount_subtree_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Some map entry cache locking inconsistencies have crept in.
+
+In umount_subtree_mounts() the cache write lock should be held when
+deleting multi-mount cache entries.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |   42 ++++++++++++++++++++++++++++++------------
+ lib/mounts.c       |    8 --------
+ 3 files changed, 31 insertions(+), 20 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -14,6 +14,7 @@
+ - eliminate clean_stale_multi_triggers().
+ - simplify mount_subtree() mount check.
+ - fix mnts_get_expire_list() expire list construction.
++- fix inconsistent locking in umount_subtree_mounts().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -527,8 +527,11 @@ static int umount_subtree_mounts(struct
+ 	struct mapent_cache *mc;
+ 	struct mapent *me;
+ 	unsigned int is_mm_root = 0;
++	int cur_state;
+ 	int left;
+ 
++	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
++
+ 	me = lookup_source_mapent(ap, path, LKP_DISTINCT);
+ 	if (!me) {
+ 		char *ind_key;
+@@ -548,11 +551,11 @@ static int umount_subtree_mounts(struct
+ 	left = 0;
+ 
+ 	if (me && me->multi) {
+-		char root[PATH_MAX];
++		char root[PATH_MAX + 1];
++		char key[PATH_MAX + 1];
++		struct mapent *tmp;
++		int status;
+ 		char *base;
+-		int cur_state;
+-
+-		pthread_cleanup_push(cache_lock_cleanup, mc);
+ 
+ 		if (!strchr(me->multi->key, '/'))
+ 			/* Indirect multi-mount root */
+@@ -567,25 +570,40 @@ static int umount_subtree_mounts(struct
+ 		else
+ 			base = me->key + strlen(root);
+ 
+-		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+-		/* Lock the closest parent nesting point for umount */
+-		cache_multi_writelock(me->parent);
+-		if (umount_multi_triggers(ap, me, root, base)) {
++		left = umount_multi_triggers(ap, me, root, base);
++		if (left) {
+ 			warn(ap->logopt,
+ 			     "some offset mounts still present under %s", path);
++		}
++
++		strcpy(key, me->key);
++
++		cache_unlock(mc);
++		cache_writelock(mc);
++		tmp = cache_lookup_distinct(mc, key);
++		/* mapent went away while we waited? */
++		if (tmp != me) {
++			cache_unlock(mc);
++			pthread_setcancelstate(cur_state, NULL);
++			return 0;
++		}
++
++		if (!left && is_mm_root) {
++			status = cache_delete_offset_list(mc, me->key);
++			if (status != CHE_OK)
++				warn(ap->logopt, "couldn't delete offset list");
+ 			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);
+-		pthread_cleanup_pop(0);
+ 	}
+-
+ 	if (me)
+ 		cache_unlock(mc);
+ 
++	pthread_setcancelstate(cur_state, NULL);
++
+ 	if (left || is_autofs_fs)
+ 		return left;
+ 
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2730,9 +2730,6 @@ int umount_multi_triggers(struct autofs_
+ 	left = do_umount_multi_triggers(ap, me, root, base);
+ 
+ 	if (!left && me->multi == me) {
+-		struct mapent_cache *mc = me->mc;
+-		int status;
+-
+ 		/*
+ 		 * Special case.
+ 		 * If we can't umount the root container then we can't
+@@ -2750,11 +2747,6 @@ int umount_multi_triggers(struct autofs_
+ 			}
+ 		}
+ 
+-		/* We're done - clean out the offsets */
+-		status = cache_delete_offset_list(mc, me->key);
+-		if (status != CHE_OK)
+-			warn(ap->logopt, "couldn't delete offset list");
+-
+ 	       /* check for mounted mount entry and remove it if found */
+                mnts_remove_mount(root, MNTS_MOUNTED);
+ 	}
diff --git a/SOURCES/autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch b/SOURCES/autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch
new file mode 100644
index 0000000..65f6ec0
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch
@@ -0,0 +1,58 @@
+autofs-5.1.7 - fix is mounted check on non existent path
+
+From: Ian Kent <raven@themaw.net>
+
+When checking if a path is a mount point the case of a non-existent path
+was not being handled.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/dev-ioctl-lib.c |    3 +++
+ lib/mounts.c        |   12 +++++++++++-
+ 3 files changed, 15 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -5,6 +5,7 @@
+ - use sprintf() when constructing hosts mapent.
+ - fix mnts_remove_amdmount() uses wrong list.
+ - eliminate cache_lookup_offset() usage.
++- fix is mounted check on non existent path.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/dev-ioctl-lib.c
++++ autofs-5.1.4/lib/dev-ioctl-lib.c
+@@ -759,6 +759,9 @@ static int dev_ioctl_ismountpoint(unsign
+ 		int save_errno = errno;
+ 		free_dev_ioctl_path(param);
+ 		errno = save_errno;
++		/* Path doesn't exist */
++		if (errno == ENOENT)
++			return 0;
+ 		return -1;
+ 	}
+ 
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1645,8 +1645,18 @@ static int table_is_mounted(const char *
+ 	struct mntent mnt_wrk;
+ 	char buf[PATH_MAX * 3];
+ 	size_t mp_len = strlen(mp);
++	struct stat st;
+ 	FILE *tab;
+-	int ret = 0;
++	int ret;
++
++	ret = stat(mp, &st);
++	if (ret == -1) {
++		if (errno == ENOENT) {
++			/* Path does not exist */
++			return 0;
++		}
++		ret = 0;
++	}
+ 
+ 	if (!mp || !mp_len || mp_len >= PATH_MAX)
+ 		return 0;
diff --git a/SOURCES/autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch b/SOURCES/autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch
new file mode 100644
index 0000000..faf51d7
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch
@@ -0,0 +1,56 @@
+autofs-5.1.7 - fix lookup_prune_one_cache() refactoring change
+
+From: Ian Kent <raven@themaw.net>
+
+Commit 256963d6b (autofs-5.1.7 - refactor lookup_prune_one_cache() a bit)
+changed the position of the getting the next enumeration map entry but
+failed to update a couple of other locations that assume the next map
+entry has been set. Under certain fairly common conditions this leads
+to an infinite loop.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/lookup.c |    5 ++++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -73,6 +73,7 @@
+ - eliminate redundant cache lookup in tree_mapent_add_node().
+ - fix hosts map offset order.
+ - fix direct mount deadlock.
++- fix lookup_prune_one_cache() refactoring change.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/lookup.c
++++ autofs-5.1.4/daemon/lookup.c
+@@ -1387,6 +1387,7 @@ void lookup_prune_one_cache(struct autof
+ 		if (!key || strchr(key, '*')) {
+ 			if (key)
+ 				free(key);
++			me = cache_enumerate(mc, me);
+ 			continue;
+ 		}
+ 
+@@ -1394,6 +1395,7 @@ void lookup_prune_one_cache(struct autof
+ 		if (!path) {
+ 			warn(ap->logopt, "can't malloc storage for path");
+ 			free(key);
++			me = cache_enumerate(mc, me);
+ 			continue;
+ 		}
+ 
+@@ -1421,9 +1423,10 @@ void lookup_prune_one_cache(struct autof
+ 		}
+ 		if (!valid &&
+ 		    is_mounted(path, MNTS_REAL)) {
+-			debug(ap->logopt, "prune posponed, %s mounted", path);
++			debug(ap->logopt, "prune postponed, %s mounted", path);
+ 			free(key);
+ 			free(path);
++			me = cache_enumerate(mc, me);
+ 			continue;
+ 		}
+ 		if (valid)
diff --git a/SOURCES/autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch b/SOURCES/autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch
new file mode 100644
index 0000000..88acca8
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch
@@ -0,0 +1,32 @@
+autofs-5.1.7 - fix missing lock release in mount_subtree()
+
+From: Ian Kent <raven@themaw.net>
+
+Covarity: missing_unlock: Returning without unlocking "mc->rwlock".
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |    1 +
+ 2 files changed, 2 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -61,6 +61,7 @@
+ - remove redundant assignment in master_add_amd_mount_section_mounts().
+ - fix dead code in mnts_add_mount().
+ - fix arg not used in error print.
++- fix missing lock release in mount_subtree().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1107,6 +1107,7 @@ static int mount_subtree(struct autofs_p
+ 		len = mount_fullpath(key, PATH_MAX, ap->path, ap->len, me->key);
+ 		if (!len) {
+ 			warn(ap->logopt, "path loo long");
++			cache_unlock(mc);
+ 			return 1;
+ 		}
+ 		key[len] = '/';
diff --git a/SOURCES/autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch b/SOURCES/autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch
new file mode 100644
index 0000000..afb8497
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch
@@ -0,0 +1,36 @@
+autofs-5.1.7 - fix mnts_get_expire_list() expire list construction
+
+From: Ian Kent <raven@themaw.net>
+
+The mnts_get_expire_list() function is supposed to return an ordered
+list of expire candidates but it is not checking the mounted status
+of list entries and is returning a larger list than is needed.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    3 +++
+ 2 files changed, 4 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -13,6 +13,7 @@
+ - refactor umount_multi_triggers().
+ - eliminate clean_stale_multi_triggers().
+ - simplify mount_subtree() mount check.
++- fix mnts_get_expire_list() expire list construction.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1364,6 +1364,9 @@ void mnts_get_expire_list(struct list_he
+ 	list_for_each_entry(mnt, &ap->mounts, mount) {
+ 		struct node *n;
+ 
++		if (!(mnt->flags & MNTS_MOUNTED))
++			continue;
++
+ 		__mnts_get_mount(mnt);
+ 
+ 		if (!tree) {
diff --git a/SOURCES/autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch b/SOURCES/autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch
new file mode 100644
index 0000000..e7789fd
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch
@@ -0,0 +1,34 @@
+autofs-5.1.7 - fix mnts_remove_amdmount() uses wrong list
+
+From: Ian Kent <raven@themaw.net>
+
+Function mnts_remove_amdmount() uses the wrong list when removing an
+amd mount.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -3,6 +3,7 @@
+ - remove mount.x and rpcgen dependencies.
+ - dont use realloc in host exports list processing.
+ - use sprintf() when constructing hosts mapent.
++- fix mnts_remove_amdmount() uses wrong list.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1124,7 +1124,7 @@ void mnts_remove_amdmount(const char *mp
+ 	if (!(this && this->flags & MNTS_AMD_MOUNT))
+ 		goto done;
+ 	this->flags &= ~MNTS_AMD_MOUNT;
+-	list_del_init(&this->submount);
++	list_del_init(&this->amdmount);
+ 	if (this->ext_mp) {
+ 		free(this->ext_mp);
+ 		this->ext_mp = NULL;
diff --git a/SOURCES/autofs-5.1.7-fix-mount_fullpath.patch b/SOURCES/autofs-5.1.7-fix-mount_fullpath.patch
new file mode 100644
index 0000000..138d6e1
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-mount_fullpath.patch
@@ -0,0 +1,61 @@
+autofs-5.1.7 - fix mount_fullpath()
+
+From: Ian Kent <raven@themaw.net>
+
+mount_fullpath() incorrecly fills fullpath with the contents of root
+when name[0] == '/'. The cases root[last] == '/' and name[0] == '/'
+need to be handled seperately.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/mounts.c        |    4 +++-
+ modules/parse_amd.c |    6 ++++--
+ 3 files changed, 8 insertions(+), 3 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -36,6 +36,7 @@
+ - add tree_mapent_add_node().
+ - add tree_mapent_delete_offsets().
+ - add tree_mapent_traverse_subtree().
++- fix mount_fullpath().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -371,8 +371,10 @@ int mount_fullpath(char *fullpath, size_
+ 	/* Root offset of multi-mount or direct or offset mount.
+ 	 * Direct or offset mount, name (or root) is absolute path.
+ 	 */
+-	if (root[last] == '/' || *name == '/')
++	if (root[last] == '/')
+ 		len = snprintf(fullpath, max_len, "%s", root);
++	else if (*name == '/')
++		len = snprintf(fullpath, max_len, "%s", name);
+ 	else
+ 		len = snprintf(fullpath, max_len, "%s/%s", root, name);
+ 
+--- autofs-5.1.4.orig/modules/parse_amd.c
++++ autofs-5.1.4/modules/parse_amd.c
+@@ -1177,7 +1177,8 @@ static int do_generic_mount(struct autof
+ 		 * the automount filesystem.
+ 		 */
+ 		if (!is_mounted(entry->fs, MNTS_REAL)) {
+-			ret = do_mount(ap, entry->fs, "/", 1,
++			ret = do_mount(ap, entry->fs,
++				       entry->fs, strlen(entry->fs),
+ 				       target, entry->type, opts);
+ 			if (ret)
+ 				goto out;
+@@ -1227,7 +1228,8 @@ static int do_nfs_mount(struct autofs_po
+ 					     mount_nfs->context);
+ 	} else {
+ 		if (!is_mounted(entry->fs, MNTS_REAL)) {
+-			ret = mount_nfs->mount_mount(ap, entry->fs, "/", 1,
++			ret = mount_nfs->mount_mount(ap, entry->fs,
++						entry->fs, strlen(entry->fs),
+ 						target, entry->type, opts,
+ 						mount_nfs->context);
+ 			if (ret)
diff --git a/SOURCES/autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch b/SOURCES/autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch
new file mode 100644
index 0000000..46572bf
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch
@@ -0,0 +1,54 @@
+autofs-5.1.7 - fix nonstrict offset mount fail handling
+
+From: Ian Kent <raven@themaw.net>
+
+If a triggered offset mount fails automount is not handling nonstrict
+mount failure correctly.
+
+The nonstrict mount failure handling needs to convert an offset mount
+failure to a success if the offset subtree below the failed mount is not
+empty otherwise it must return the failure. The previous implementation
+used -1 to indicate the subtree was empty and that was used to detect
+when the mount should fail instead of converting the fail to a success.
+
+Make the new implementation do the same.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ lib/mounts.c        |    2 +-
+ modules/parse_sun.c |    2 +-
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -76,6 +76,7 @@
+ - fix lookup_prune_one_cache() refactoring change.
+ - add missing description of null map option.
+ - fix empty mounts list return from unlink_mount_tree().
++- fix nonstrict offset mount fail handling.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1616,7 +1616,7 @@ static int tree_mapent_traverse_subtree(
+ {
+ 	struct traverse_subtree_context *ctxt = ptr;
+ 	struct mapent *oe = MAPENT(n);
+-	int ret = 1;
++	int ret = -1;
+ 
+ 	if (n->left) {
+ 		ret = tree_mapent_traverse_subtree(n->left, work, ctxt);
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1183,7 +1183,7 @@ static int mount_subtree(struct autofs_p
+ 		 * offsets to be mounted.
+ 		 */
+ 		rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
+-		if (rv == 0) {
++		if (rv <= 0) {
+ 			ret = tree_mapent_mount_offsets(me, 1);
+ 			if (!ret) {
+ 				tree_mapent_cleanup_offsets(me);
diff --git a/SOURCES/autofs-5.1.7-fix-offset-entries-order.patch b/SOURCES/autofs-5.1.7-fix-offset-entries-order.patch
new file mode 100644
index 0000000..3fd36a3
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-offset-entries-order.patch
@@ -0,0 +1,199 @@
+autofs-5.1.7 - fix offset entries order
+
+From: Ian Kent <raven@themaw.net>
+
+While it's rare it's possible that a mapent entry might not have
+it's offsets in shortest to longest path order.
+
+If this happens adding an entry to the mapent tree can result in
+an incorrect tree topology that doesn't work. That's because adding
+tree entries ensures that nodes in a sub-tree are placed below the
+containing node so the containing node must be present for that to
+work. This topology is critical to the performance of map entries
+that have a very large number of offsets such as an NFS server with
+many exports.
+
+There's no other choice but make a traversal after the offset entries
+have all been added to create the mapent tree.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ include/automount.h |    1 
+ lib/cache.c         |    1 
+ modules/parse_sun.c |   74 +++++++++++++++++++++++++++++++++++++++++-----------
+ 4 files changed, 62 insertions(+), 15 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -68,6 +68,7 @@
+ - add ext_mount_hash_mutex lock helpers.
+ - fix amd section mounts map reload.
+ - fix amd hosts mount expire.
++- fix offset entries order.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -169,6 +169,7 @@ struct mapent {
+ 	/* Parent nesting point within multi-mount */
+ 	struct tree_node *mm_parent;
+ 	struct tree_node node;
++	struct list_head work;
+ 	char *key;
+ 	size_t len;
+ 	char *mapent;
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -559,6 +559,7 @@ int cache_add(struct mapent_cache *mc, s
+ 	me->mm_parent = NULL;
+ 	INIT_TREE_NODE(&me->node);
+ 	INIT_LIST_HEAD(&me->ino_index);
++	INIT_LIST_HEAD(&me->work);
+ 	me->ioctlfd = -1;
+ 	me->dev = (dev_t) -1;
+ 	me->ino = (ino_t) -1;
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -791,14 +791,15 @@ static int check_is_multi(const char *ma
+ 
+ static int
+ update_offset_entry(struct autofs_point *ap,
+-		    struct mapent_cache *mc, const char *name,
+-		    const char *m_root, int m_root_len,
++		    struct mapent_cache *mc, struct list_head *offsets,
++		    const char *name, const char *m_root, int m_root_len,
+ 		    const char *m_offset, const char *myoptions,
+ 		    const char *loc, time_t age)
+ {
+ 	char m_key[PATH_MAX + 1];
+ 	char m_mapent[MAPENT_MAX_LEN + 1];
+ 	int o_len, m_key_len, m_options_len, m_mapent_len;
++	struct mapent *me;
+ 	int ret;
+ 
+ 	memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+@@ -864,8 +865,29 @@ update_offset_entry(struct autofs_point
+ 	cache_writelock(mc);
+ 	ret = cache_update_offset(mc, name, m_key, m_mapent, age);
+ 
+-	if (!tree_mapent_add_node(mc, name, m_key))
+-		error(ap->logopt, "failed to add offset %s to tree", m_key);
++	me = cache_lookup_distinct(mc, m_key);
++	if (me && list_empty(&me->work)) {
++		struct list_head *last;
++
++		/* Offset entries really need to be in shortest to
++		 * longest path order. If not and the list of offsets
++		 * is large there will be a performace hit.
++		 */
++		list_for_each_prev(last, offsets) {
++			struct mapent *this;
++
++			this = list_entry(last, struct mapent, work);
++			if (me->len >= this->len) {
++				if (last->next == offsets)
++					list_add_tail(&me->work, offsets);
++				else
++					list_add_tail(&me->work, last);
++				break;
++			}
++		}
++		if (list_empty(&me->work))
++			list_add(&me->work, offsets);
++	}
+ 	cache_unlock(mc);
+ 
+ 	if (ret == CHE_DUPLICATE) {
+@@ -1211,6 +1233,25 @@ static char *do_expandsunent(const char
+ 	return mapent;
+ }
+ 
++static void cleanup_offset_entries(struct autofs_point *ap,
++				   struct mapent_cache *mc,
++				   struct list_head *offsets)
++{
++	struct mapent *me, *tmp;
++	int ret;
++
++	if (list_empty(offsets))
++		return;
++	cache_writelock(mc);
++	list_for_each_entry_safe(me, tmp, offsets, work) {
++		list_del(&me->work);
++		ret = cache_delete(mc, me->key);
++		if (ret != CHE_OK)
++			crit(ap->logopt, "failed to delete offset %s", me->key);
++	}
++	cache_unlock(mc);
++}
++
+ /*
+  * syntax is:
+  *	[-options] location [location] ...
+@@ -1230,7 +1271,8 @@ int parse_mount(struct autofs_point *ap,
+ 	char buf[MAX_ERR_BUF];
+ 	struct map_source *source;
+ 	struct mapent_cache *mc;
+-	struct mapent *me;
++	struct mapent *me, *oe, *tmp;
++	LIST_HEAD(offsets);
+ 	char *pmapent, *options;
+ 	const char *p;
+ 	int mapent_len, rv = 0;
+@@ -1446,9 +1488,7 @@ dont_expand:
+ 
+ 			if (!m_offset) {
+ 				warn(ap->logopt, MODPREFIX "null path or out of memory");
+-				cache_writelock(mc);
+-				tree_mapent_delete_offsets(mc, name);
+-				cache_unlock(mc);
++				cleanup_offset_entries(ap, mc, &offsets);
+ 				free(options);
+ 				free(pmapent);
+ 				pthread_setcancelstate(cur_state, NULL);
+@@ -1463,9 +1503,7 @@ dont_expand:
+ 
+ 			l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
+ 			if (!l) {
+-				cache_writelock(mc);
+-				tree_mapent_delete_offsets(mc, name);
+-				cache_unlock(mc);
++				cleanup_offset_entries(ap, mc, &offsets);
+ 				free(m_offset);
+ 				free(options);
+ 				free(pmapent);
+@@ -1476,15 +1514,13 @@ dont_expand:
+ 			p += l;
+ 			p = skipspace(p);
+ 
+-			status = update_offset_entry(ap, mc,
++			status = update_offset_entry(ap, mc, &offsets,
+ 						     name, m_root, m_root_len,
+ 						     m_offset, myoptions, loc, age);
+ 
+ 			if (status != CHE_OK) {
+ 				warn(ap->logopt, MODPREFIX "error adding multi-mount");
+-				cache_writelock(mc);
+-				tree_mapent_delete_offsets(mc, name);
+-				cache_unlock(mc);
++				cleanup_offset_entries(ap, mc, &offsets);
+ 				free(m_offset);
+ 				free(options);
+ 				free(pmapent);
+@@ -1501,6 +1537,14 @@ dont_expand:
+ 			free(myoptions);
+ 		} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+ 
++		cache_writelock(mc);
++		list_for_each_entry_safe(oe, tmp, &offsets, work) {
++			if (!tree_mapent_add_node(mc, name, oe->key))
++				error(ap->logopt, "failed to add offset %s to tree", oe->key);
++			list_del_init(&oe->work);
++		}
++		cache_unlock(mc);
++
+ 		rv = mount_subtree(ap, mc, name, NULL, options, ctxt);
+ 
+ 		free(options);
diff --git a/SOURCES/autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch b/SOURCES/autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch
new file mode 100644
index 0000000..6dddb70
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch
@@ -0,0 +1,34 @@
+autofs-5.1.7 - fix possible memory leak in master_parse()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: Overwriting "path" in "path = master_strdup(yyvsp[-1].strtype)"
+	  leaks the storage that "path" points to.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG             |    1 +
+ daemon/master_parse.y |    2 ++
+ 2 files changed, 3 insertions(+)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -52,6 +52,7 @@
+ - remove unused variable from get_exports().
+ - add missing free in handle_mounts().
+ - remove redundant if check.
++- fix possible memory leak in master_parse().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/master_parse.y
++++ autofs-5.1.4/daemon/master_parse.y
+@@ -155,6 +155,8 @@ file: {
+ line:
+ 	| PATH mapspec
+ 	{
++		if (path)
++			free(path);
+ 		path = master_strdup($1);
+ 		if (!path) {
+ 			local_free_vars();
diff --git a/SOURCES/autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch b/SOURCES/autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch
new file mode 100644
index 0000000..37c0cdf
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch
@@ -0,0 +1,54 @@
+autofs-5.1.7 - fix possible memory leak in mnts_add_amdmount()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: leaked_storage: Variable "ext_mp" going out of scope leaks
+	  the storage it points to.
+
+Same applies to the other duped fields destined for the mnt_list struct.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   20 ++++++++++----------
+ 2 files changed, 11 insertions(+), 10 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -53,6 +53,7 @@
+ - add missing free in handle_mounts().
+ - remove redundant if check.
+ - fix possible memory leak in master_parse().
++- fix possible memory leak in mnts_add_amdmount().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1119,16 +1119,16 @@ struct mnt_list *mnts_add_amdmount(struc
+ 
+ 	mnts_hash_mutex_lock();
+ 	this = mnts_get_mount(entry->path);
+-	if (this) {
+-		this->ext_mp = ext_mp;
+-		this->amd_pref = pref;
+-		this->amd_type = type;
+-		this->amd_opts = opts;
+-		this->amd_cache_opts = entry->cache_opts;
+-		this->flags |= MNTS_AMD_MOUNT;
+-		if (list_empty(&this->amdmount))
+-			list_add_tail(&this->amdmount, &ap->amdmounts);
+-	}
++	if (!this)
++		goto fail;
++	this->ext_mp = ext_mp;
++	this->amd_pref = pref;
++	this->amd_type = type;
++	this->amd_opts = opts;
++	this->amd_cache_opts = entry->cache_opts;
++	this->flags |= MNTS_AMD_MOUNT;
++	if (list_empty(&this->amdmount))
++		list_add_tail(&this->amdmount, &ap->amdmounts);
+ 	mnts_hash_mutex_unlock();
+ 
+ 	return this;
diff --git a/SOURCES/autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch b/SOURCES/autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch
new file mode 100644
index 0000000..d62cb37
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch
@@ -0,0 +1,40 @@
+autofs-5.1.7 - fix return from umount_subtree_mounts() on offset list delete
+
+From: Ian Kent <raven@themaw.net>
+
+When there are no mounts left in a subtree of offset mounts the offset
+list is deleted. If all goes well deleting the list this shouldn't cause
+a positive return from umount_subtree_mounts() (essentially saying not
+the umount of the subtree has not succeeded).
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG          |    1 +
+ daemon/automount.c |    5 +++--
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -15,6 +15,7 @@
+ - simplify mount_subtree() mount check.
+ - fix mnts_get_expire_list() expire list construction.
+ - fix inconsistent locking in umount_subtree_mounts().
++- fix return from umount_subtree_mounts() on offset list delete.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -590,9 +590,10 @@ static int umount_subtree_mounts(struct
+ 
+ 		if (!left && is_mm_root) {
+ 			status = cache_delete_offset_list(mc, me->key);
+-			if (status != CHE_OK)
++			if (status != CHE_OK) {
+ 				warn(ap->logopt, "couldn't delete offset list");
+-			left++;
++				left++;
++			}
+ 		}
+ 
+ 		if (ap->entry->maps &&
diff --git a/SOURCES/autofs-5.1.7-make-tree-implementation-data-independent.patch b/SOURCES/autofs-5.1.7-make-tree-implementation-data-independent.patch
new file mode 100644
index 0000000..1c6dc1f
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-make-tree-implementation-data-independent.patch
@@ -0,0 +1,346 @@
+autofs-5.1.7 - make tree implementation data independent
+
+From: Ian Kent <raven@themaw.net>
+
+Generalise the tree implementation so that it's independent of the
+data structure that's used.
+
+Do this by refactoring it into core tree functions and functions
+specific to the data structure to be used so that different data
+structures can be used when needed by adding an implementation for
+the data structure specific functions.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 
+ include/mounts.h |   29 +++++++++
+ lib/mounts.c     |  174 ++++++++++++++++++++++++++++++++++---------------------
+ 3 files changed, 140 insertions(+), 64 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -31,6 +31,7 @@
+ - add some multi-mount macros.
+ - remove unused functions cache_dump_multi() and cache_dump_cache().
+ - add a len field to struct autofs_point.
++- make tree implementation data independent.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -51,10 +51,36 @@ extern const unsigned int t_indirect;
+ extern const unsigned int t_direct;
+ extern const unsigned int t_offset;
+ 
++struct mnt_list;
+ struct mapent;
+ 
++struct tree_ops;
++
++struct tree_node {
++	struct tree_ops *ops;
++	struct tree_node *left;
++	struct tree_node *right;
++};
++#define INIT_TREE_NODE(ptr)	((ptr)->ops = NULL, (ptr)->left = NULL, (ptr)->right = NULL)
++
++#define MNT_LIST(n)		(container_of(n, struct mnt_list, node))
++#define MNT_LIST_NODE(ptr)	((struct tree_node *) &((struct mnt_list *) ptr)->node)
++
++typedef struct tree_node *(*tree_new_t) (void *ptr);
++typedef int  (*tree_cmp_t) (struct tree_node *n, void *ptr);
++typedef void (*tree_free_t) (struct tree_node *n);
++
++struct tree_ops {
++	tree_new_t new;
++	tree_cmp_t cmp;
++	tree_free_t free;
++};
++
++typedef int (*tree_work_fn_t) (struct tree_node *n, void *ptr);
++
+ struct mnt_list {
+ 	char *mp;
++	size_t len;
+ 	unsigned int flags;
+ 
+ 	/* Hash of all mounts */
+@@ -79,6 +105,9 @@ struct mnt_list {
+ 	unsigned int amd_cache_opts;
+ 	struct list_head amdmount;
+ 
++	/* Tree operations */
++	struct tree_node node;
++
+ 	/*
+ 	 * List operations ie. get_mnt_list.
+ 	 */
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -68,6 +68,17 @@ static pthread_mutex_t ext_mount_hash_mu
+ static DEFINE_HASHTABLE(mnts_hash, MNTS_HASH_BITS);
+ static pthread_mutex_t mnts_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
+ 
++static struct tree_node *tree_mnt_new(void *ptr);
++static int tree_mnt_cmp(struct tree_node *n, void *ptr);
++static void tree_mnt_free(struct tree_node *n);
++
++static struct tree_ops mnt_ops = {
++	.new = tree_mnt_new,
++	.cmp = tree_mnt_cmp,
++	.free = tree_mnt_free,
++};
++static struct tree_ops *tree_mnt_ops = &mnt_ops;
++
+ unsigned int linux_version_code(void)
+ {
+ 	struct utsname my_utsname;
+@@ -904,6 +915,7 @@ static struct mnt_list *mnts_alloc_mount
+ 		this = NULL;
+ 		goto done;
+ 	}
++	this->len = strlen(mp);
+ 
+ 	this->ref = 1;
+ 	INIT_HLIST_NODE(&this->hash);
+@@ -912,6 +924,7 @@ static struct mnt_list *mnts_alloc_mount
+ 	INIT_LIST_HEAD(&this->submount_work);
+ 	INIT_LIST_HEAD(&this->amdmount);
+ 	INIT_LIST_HEAD(&this->expire);
++	INIT_TREE_NODE(&this->node);
+ done:
+ 	return this;
+ }
+@@ -1225,91 +1238,58 @@ done:
+ 	return has_mounted_mounts;
+ }
+ 
+-struct tree_node {
+-	struct mnt_list *mnt;
+-	struct tree_node *left;
+-	struct tree_node *right;
+-};
+-
+-static struct tree_node *tree_new(struct mnt_list *mnt)
+-{
+-	struct tree_node *n;
+-
+-	n = malloc(sizeof(struct tree_node));
+-	if (!n)
+-		return NULL;
+-	memset(n, 0, sizeof(struct tree_node));
+-	n->mnt = mnt;
+-
+-	return n;
+-}
+-
+-static struct tree_node *tree_root(struct mnt_list *mnt)
++static inline struct tree_node *tree_root(struct tree_ops *ops, void *ptr)
+ {
+-	struct tree_node *n;
+-
+-	n = tree_new(mnt);
+-	if (!n) {
+-		error(LOGOPT_ANY, "failed to allcate tree root");
+-		return NULL;
+-	}
+-
+-	return n;
++	return ops->new(ptr);
+ }
+ 
+-static struct tree_node *tree_add_left(struct tree_node *n, struct mnt_list *mnt)
++static struct tree_node *tree_add_left(struct tree_node *n, void *ptr)
+ {
+ 	struct tree_node *new;
+ 
+-	new = tree_new(mnt);
+-	if (!new) {
+-		error(LOGOPT_ANY, "failed to allcate tree node");
+-		return NULL;
+-	}
++	new = n->ops->new(ptr);
+ 	n->left = new;
+ 
+-	return n;
++	return new;
+ }
+ 
+-static struct tree_node *tree_add_right(struct tree_node *n, struct mnt_list *mnt)
++static struct tree_node *tree_add_right(struct tree_node *n, void *ptr)
+ {
+ 	struct tree_node *new;
+ 
+-	new = tree_new(mnt);
+-	if (!new) {
+-		error(LOGOPT_ANY, "failed to allcate tree node");
+-		return NULL;
+-	}
++	new = n->ops->new(ptr);
+ 	n->right = new;
+ 
+-	return n;
++	return new;
+ }
+ 
+-static struct tree_node *tree_add_node(struct tree_node *root, struct mnt_list *mnt)
++static struct tree_node *tree_add_node(struct tree_node *root, void *ptr)
+ {
+ 	struct tree_node *p, *q;
+-	unsigned int mp_len;
+-
+-	mp_len = strlen(mnt->mp);
++	struct tree_ops *ops = root->ops;
++	int eq;
+ 
+ 	q = root;
+ 	p = root;
+ 
+-	while (q && strcmp(mnt->mp, p->mnt->mp)) {
++	while (q) {
+ 		p = q;
+-		if (mp_len < strlen(p->mnt->mp))
++		eq = ops->cmp(p, ptr);
++		if (!eq)
++			break;
++		if (eq < 0)
+ 			q = p->left;
+ 		else
+ 			q = p->right;
+ 	}
+ 
+-	if (strcmp(mnt->mp, p->mnt->mp) == 0)
+-		error(LOGOPT_ANY, "duplicate entry in mounts list");
++	if (!eq)
++		error(LOGOPT_ANY, "cannot add duplicate entry to tree");
+ 	else {
+-		if (mp_len < strlen(p->mnt->mp))
+-			return tree_add_left(p, mnt);
++		if (eq < 0)
++			return tree_add_left(p, ptr);
+ 		else
+-			return tree_add_right(p, mnt);
++			return tree_add_right(p, ptr);
+ 	}
+ 
+ 	return NULL;
+@@ -1317,26 +1297,92 @@ static struct tree_node *tree_add_node(s
+ 
+ static void tree_free(struct tree_node *root)
+ {
++	struct tree_ops *ops = root->ops;
++
+ 	if (root->right)
+ 		tree_free(root->right);
+ 	if (root->left)
+ 		tree_free(root->left);
+-	free(root);
++	ops->free(root);
++}
++
++static int tree_traverse_inorder(struct tree_node *n, tree_work_fn_t work, void *ptr)
++{
++	int ret;
++
++	if (n->left) {
++		ret = tree_traverse_inorder(n->left, work, ptr);
++		if (!ret)
++			goto done;
++	}
++	ret = work(n, ptr);
++	if (!ret)
++		goto done;
++	if (n->right) {
++		ret = tree_traverse_inorder(n->right, work, ptr);
++		if (!ret)
++			goto done;
++	}
++done:
++	return ret;
++}
++
++static struct tree_node *tree_mnt_root(struct mnt_list *mnt)
++{
++	return tree_root(tree_mnt_ops, mnt);
++}
++
++static struct tree_node *tree_mnt_new(void *ptr)
++{
++	struct tree_node *n = MNT_LIST_NODE(ptr);
++
++	n->ops = tree_mnt_ops;
++	n->left = NULL;
++	n->right = NULL;
++
++	return n;
++}
++
++static int tree_mnt_cmp(struct tree_node *n, void *ptr)
++{
++	struct mnt_list *n_mnt = MNT_LIST(n);
++	size_t n_mnt_len = n_mnt->len;
++	struct mnt_list *mnt = ptr;
++	size_t mnt_len = mnt->len;
++	int eq;
++
++	eq = strcmp(mnt->mp, n_mnt->mp);
++	if (!eq)
++		return 0;
++	return (mnt_len < n_mnt_len) ? -1 : 1;
++}
++
++static void tree_mnt_free(struct tree_node *n)
++{
++	n->ops = NULL;
++	n->left = NULL;
++	n->right = NULL;
+ }
+ 
+-static void tree_traverse(struct tree_node *n, struct list_head *mnts)
++static int tree_mnt_expire_list_work(struct tree_node *n, void *ptr)
+ {
+-	if (n->right)
+-		tree_traverse(n->right, mnts);
+-	list_add_tail(&n->mnt->expire, mnts);
+-	if (n->left)
+-		tree_traverse(n->left, mnts);
++	struct mnt_list *mnt = MNT_LIST(n);
++	struct list_head *mnts = ptr;
++
++	/* The expire of the root offset of an offset tree is the same
++	 * as expiring the offset tree root itself (if theree is a root
++	 * offset).
++	 */
++	if (mnt->mp[mnt->len - 1] != '/')
++		list_add(&mnt->expire, mnts);
++
++	return 1;
+ }
+ 
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+ {
+-	struct mnt_list *mnt;
+ 	struct tree_node *tree = NULL;
++	struct mnt_list *mnt;
+ 
+ 	mnts_hash_mutex_lock();
+ 	if (list_empty(&ap->mounts))
+@@ -1351,7 +1397,7 @@ void mnts_get_expire_list(struct list_he
+ 		__mnts_get_mount(mnt);
+ 
+ 		if (!tree) {
+-			tree = tree_root(mnt);
++			tree = tree_mnt_root(mnt);
+ 			if (!tree) {
+ 				error(LOGOPT_ANY, "failed to create expire tree root");
+ 				goto done;
+@@ -1367,7 +1413,7 @@ void mnts_get_expire_list(struct list_he
+ 		}
+ 	}
+ 
+-	tree_traverse(tree, mnts);
++	tree_traverse_inorder(tree, tree_mnt_expire_list_work, mnts);
+ 	tree_free(tree);
+ done:
+ 	mnts_hash_mutex_unlock();
diff --git a/SOURCES/autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch b/SOURCES/autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch
new file mode 100644
index 0000000..7b7cb0a
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch
@@ -0,0 +1,110 @@
+autofs-5.1.7 - move amd mounts removal into lib/mounts.c
+
+From: Ian Kent <raven@themaw.net>
+
+Move the amd mounts removal from master_free_autofs_point() into
+lib/mounts.c along with the rest of the amd mount handling.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ daemon/master.c  |   12 +-----------
+ include/mounts.h |    1 +
+ lib/mounts.c     |   28 ++++++++++++++++++++++++----
+ 4 files changed, 27 insertions(+), 15 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -46,6 +46,7 @@
+ - use mount_fullpath() in one spot in parse_mount().
+ - pass root length to mount_fullpath().
+ - remove unused function master_submount_list_empty().
++- move amd mounts removal into lib/mounts.c.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/master.c
++++ autofs-5.1.4/daemon/master.c
+@@ -143,22 +143,12 @@ int master_add_autofs_point(struct maste
+ 
+ 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 mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
+-		p = p->next;
+-		ext_mount_remove(mnt->ext_mp);
+-		mnts_remove_amdmount(mnt->mp);
+-	}
+-	mounts_mutex_unlock(ap);
++	mnts_remove_amdmounts(ap);
+ 
+ 	status = pthread_mutex_destroy(&ap->mounts_mutex);
+ 	if (status)
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -161,6 +161,7 @@ void mnts_remove_submount(const char *mp
+ struct mnt_list *mnts_find_amdmount(const char *path);
+ struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *entry);
+ void mnts_remove_amdmount(const char *mp);
++void mnts_remove_amdmounts(struct autofs_point *ap);
+ struct mnt_list *mnts_add_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ void mnts_remove_mount(const char *mp, unsigned int flags);
+ struct mnt_list *get_mnt_list(const char *path, int include);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1144,14 +1144,13 @@ fail:
+ 	return NULL;
+ }
+ 
+-void mnts_remove_amdmount(const char *mp)
++static void __mnts_remove_amdmount(const char *mp)
+ {
+ 	struct mnt_list *this;
+ 
+-	mnts_hash_mutex_lock();
+ 	this = mnts_lookup(mp);
+ 	if (!(this && this->flags & MNTS_AMD_MOUNT))
+-		goto done;
++		return;
+ 	this->flags &= ~MNTS_AMD_MOUNT;
+ 	list_del_init(&this->amdmount);
+ 	if (this->ext_mp) {
+@@ -1172,7 +1171,28 @@ void mnts_remove_amdmount(const char *mp
+ 	}
+ 	this->amd_cache_opts = 0;
+ 	__mnts_put_mount(this);
+-done:
++}
++
++void mnts_remove_amdmount(const char *mp)
++{
++	mnts_hash_mutex_lock();
++	__mnts_remove_amdmount(mp);
++	mnts_hash_mutex_unlock();
++}
++
++void mnts_remove_amdmounts(struct autofs_point *ap)
++{
++	struct list_head *head, *p;
++
++	mnts_hash_mutex_lock();
++	head = &ap->amdmounts;
++	p = head->next;
++	while (p != head) {
++		struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
++		p = p->next;
++		ext_mount_remove(mnt->ext_mp);
++		__mnts_remove_amdmount(mnt->mp);
++	}
+ 	mnts_hash_mutex_unlock();
+ }
+ 
diff --git a/SOURCES/autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch b/SOURCES/autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch
new file mode 100644
index 0000000..5b87e51
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch
@@ -0,0 +1,68 @@
+autofs-5.1.7 - pass mapent_cache to update_offset_entry()
+
+From: Ian Kent <raven@themaw.net>
+
+Pass mapent_cache to update_offset_entry() rather than use the wait/signal
+mechanism, it isn't needed here.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   22 ++++++----------------
+ 2 files changed, 7 insertions(+), 16 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -16,6 +16,7 @@
+ - fix mnts_get_expire_list() expire list construction.
+ - fix inconsistent locking in umount_subtree_mounts().
+ - fix return from umount_subtree_mounts() on offset list delete.
++- pass mapent_cache to update_offset_entry().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -795,24 +795,17 @@ static int check_is_multi(const char *ma
+ }
+ 
+ static int
+-update_offset_entry(struct autofs_point *ap, const char *name,
++update_offset_entry(struct autofs_point *ap,
++		    struct mapent_cache *mc, const char *name,
+ 		    const char *m_root, int m_root_len,
+-		    const char *path, const char *myoptions, const char *loc,
+-		    time_t age)
++		    const char *path, const char *myoptions,
++		    const char *loc, time_t age)
+ {
+-	struct map_source *source;
+-	struct mapent_cache *mc;
+ 	char m_key[PATH_MAX + 1];
+ 	char m_mapent[MAPENT_MAX_LEN + 1];
+ 	int p_len, m_key_len, m_options_len, m_mapent_len;
+ 	int ret;
+ 
+-	source = ap->entry->current;
+-	ap->entry->current = NULL;
+-	master_source_current_signal(ap->entry);
+-
+-	mc = source->mc;
+-
+ 	memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+ 
+ 	/* Internal hosts map may have loc == NULL */
+@@ -1576,11 +1569,8 @@ dont_expand:
+ 			p += l;
+ 			p = skipspace(p);
+ 
+-			master_source_current_wait(ap->entry);
+-			ap->entry->current = source;
+-
+-			status = update_offset_entry(ap, name,
+-						     m_root, m_root_len,
++			status = update_offset_entry(ap, mc,
++						     name, m_root, m_root_len,
+ 						     path, myoptions, loc, age);
+ 
+ 			if (status != CHE_OK) {
diff --git a/SOURCES/autofs-5.1.7-pass-root-length-to-mount_fullpath.patch b/SOURCES/autofs-5.1.7-pass-root-length-to-mount_fullpath.patch
new file mode 100644
index 0000000..47abf2b
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-pass-root-length-to-mount_fullpath.patch
@@ -0,0 +1,153 @@
+autofs-5.1.7 - pass root length to mount_fullpath()
+
+From: Ian Kent <raven@themaw.net>
+
+The length of root may already be known, add a parameter to allow
+passing it to mount_fullpath() so a strlen() call can be avoided.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG               |    1 +
+ include/mounts.h        |    2 +-
+ lib/mounts.c            |   11 +++++++----
+ modules/mount_bind.c    |    2 +-
+ modules/mount_changer.c |    2 +-
+ modules/mount_ext2.c    |    2 +-
+ modules/mount_generic.c |    2 +-
+ modules/mount_nfs.c     |    2 +-
+ modules/parse_sun.c     |    4 ++--
+ 9 files changed, 16 insertions(+), 12 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -44,6 +44,7 @@
+ - remove obsolete functions.
+ - remove redundant local var from sun_mount().
+ - use mount_fullpath() in one spot in parse_mount().
++- pass root length to mount_fullpath().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -131,7 +131,7 @@ int check_nfs_mount_version(struct nfs_m
+ extern unsigned int nfs_mount_uses_string_options;
+ 
+ int mount_fullpath(char *fullpath, size_t max_len,
+-		   const char *root, const char *name);
++		   const char *root, size_t root_len, const char *name);
+ 
+ struct amd_entry;
+ 
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -362,11 +362,14 @@ int check_nfs_mount_version(struct nfs_m
+ #endif
+ 
+ int mount_fullpath(char *fullpath, size_t max_len,
+-		   const char *root, const char *name)
++		   const char *root, size_t root_len, const char *name)
+ {
+ 	int last, len;
+ 
+-	last = strlen(root) - 1;
++	if (root_len)
++		last = root_len - 1;
++	else
++		last = strlen(root) - 1;
+ 
+ 	/* Root offset of multi-mount or direct or offset mount.
+ 	 * Direct or offset mount, name (or root) is absolute path.
+@@ -1685,7 +1688,7 @@ void tree_mapent_cleanup_offsets(struct
+ 	else {
+ 		char mp[PATH_MAX + 1];
+ 
+-		if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key))
++		if (!mount_fullpath(mp, PATH_MAX, ap->path, ap->len, oe->key))
+ 			error(ap->logopt, "mount path is too long");
+ 		else
+ 			tree_mapent_umount_mount(ap, mp);
+@@ -1922,7 +1925,7 @@ int tree_mapent_umount_offsets(struct ma
+ 		 * one of these keys is the root of a multi-mount the mount
+ 		 * path must be constructed.
+ 		 */
+-		if (!mount_fullpath(mp, PATH_MAX, ap->path, oe->key)) {
++		if (!mount_fullpath(mp, PATH_MAX, ap->path, ap->len, oe->key)) {
+ 			error(ap->logopt, "mount path is too long");
+ 			return 0;
+ 		}
+--- autofs-5.1.4.orig/modules/mount_bind.c
++++ autofs-5.1.4/modules/mount_bind.c
+@@ -122,7 +122,7 @@ int mount_mount(struct autofs_point *ap,
+ 		}
+ 	}
+ 
+-	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+ 	if (!len) {
+ 		error(ap->logopt,
+ 		      MODPREFIX "mount point path too long");
+--- autofs-5.1.4.orig/modules/mount_changer.c
++++ autofs-5.1.4/modules/mount_changer.c
+@@ -59,7 +59,7 @@ int mount_mount(struct autofs_point *ap,
+ 
+ 	fstype = "iso9660";
+ 
+-	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+ 	if (!len) {
+ 		error(ap->logopt,
+ 		      MODPREFIX "mount point path too long");
+--- autofs-5.1.4.orig/modules/mount_ext2.c
++++ autofs-5.1.4/modules/mount_ext2.c
+@@ -55,7 +55,7 @@ int mount_mount(struct autofs_point *ap,
+ 	if (defaults_get_mount_verbose())
+ 		mountlog = &log_info;
+ 
+-	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+ 	if (!len) {
+ 		error(ap->logopt,
+ 		      MODPREFIX "mount point path too long");
+--- autofs-5.1.4.orig/modules/mount_generic.c
++++ autofs-5.1.4/modules/mount_generic.c
+@@ -54,7 +54,7 @@ int mount_mount(struct autofs_point *ap,
+ 	if (defaults_get_mount_verbose())
+ 		mountlog = &log_info;
+ 
+-	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+ 	if (!len) {
+ 		error(ap->logopt,
+ 		      MODPREFIX "mount point path too long");
+--- autofs-5.1.4.orig/modules/mount_nfs.c
++++ autofs-5.1.4/modules/mount_nfs.c
+@@ -213,7 +213,7 @@ int mount_mount(struct autofs_point *ap,
+ 	}
+ 
+ 	/* Construct mount point directory */
+-	len = mount_fullpath(fullpath, PATH_MAX, root, name);
++	len = mount_fullpath(fullpath, PATH_MAX, root, 0, name);
+ 	if (!len) {
+ 		error(ap->logopt,
+ 		      MODPREFIX "mount point path too long");
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1091,7 +1091,7 @@ static int mount_subtree(struct autofs_p
+ 		struct mapent *ro;
+ 		size_t len;
+ 
+-		len = mount_fullpath(key, PATH_MAX, ap->path, me->key);
++		len = mount_fullpath(key, PATH_MAX, ap->path, ap->len, me->key);
+ 		if (!len) {
+ 			warn(ap->logopt, "path loo long");
+ 			return 1;
+@@ -1361,7 +1361,7 @@ dont_expand:
+ 		time_t age;
+ 		int l;
+ 
+-		m_root_len = mount_fullpath(m_root, PATH_MAX, ap->path, name);
++		m_root_len = mount_fullpath(m_root, PATH_MAX, ap->path, ap->len, name);
+ 		if (!m_root_len) {
+ 			error(ap->logopt,
+ 			      MODPREFIX "multi-mount root path too long");
diff --git a/SOURCES/autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch b/SOURCES/autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch
new file mode 100644
index 0000000..e3758a8
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch
@@ -0,0 +1,75 @@
+autofs-5.1.7 - reduce umount EBUSY check delay
+
+From: Ian Kent <raven@themaw.net>
+
+Some time ago I had to wait and retry umount() for autofs mounts
+becuase I found EBUSY would be returned for a time after the call
+causing false negative umount returns.
+
+I think that problem has been resolved but removing the retry is
+probably a little risky.
+
+But the wait time is quite long at one fifth of a second so reduce
+that to one twentieth of a second and increase the retries to make
+it more resposive.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/direct.c     |    4 ++--
+ daemon/indirect.c   |    2 +-
+ include/automount.h |    2 +-
+ 4 files changed, 5 insertions(+), 4 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -22,6 +22,7 @@
+ - eliminate count_mounts() from expire_proc_indirect().
+ - eliminate some strlen calls in offset handling.
+ - don't add offset mounts to mounted mounts table.
++- reduce umount EBUSY check delay.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -150,7 +150,7 @@ int do_umount_autofs_direct(struct autof
+ 
+ 	retries = UMOUNT_RETRIES;
+ 	while ((rv = umount(me->key)) == -1 && retries--) {
+-		struct timespec tm = {0, 200000000};
++		struct timespec tm = {0, 50000000};
+ 		if (errno != EBUSY)
+ 			break;
+ 		nanosleep(&tm, NULL);
+@@ -573,7 +573,7 @@ int umount_autofs_offset(struct autofs_p
+ 
+ 	retries = UMOUNT_RETRIES;
+ 	while ((rv = umount(me->key)) == -1 && retries--) {
+-		struct timespec tm = {0, 200000000};
++		struct timespec tm = {0, 50000000};
+ 		if (errno != EBUSY)
+ 			break;
+ 		nanosleep(&tm, NULL);
+--- autofs-5.1.4.orig/daemon/indirect.c
++++ autofs-5.1.4/daemon/indirect.c
+@@ -265,7 +265,7 @@ int umount_autofs_indirect(struct autofs
+ 
+ 	retries = UMOUNT_RETRIES;
+ 	while ((rv = umount(mountpoint)) == -1 && retries--) {
+-		struct timespec tm = {0, 200000000};
++		struct timespec tm = {0, 50000000};
+ 		if (errno != EBUSY)
+ 			break;
+ 		nanosleep(&tm, NULL);
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -140,7 +140,7 @@ struct autofs_point;
+ #define NULL_MAP_HASHSIZE	64
+ #define NEGATIVE_TIMEOUT	10
+ #define POSITIVE_TIMEOUT	120
+-#define UMOUNT_RETRIES		8
++#define UMOUNT_RETRIES		16
+ #define EXPIRE_RETRIES		3
+ 
+ struct mapent_cache {
diff --git a/SOURCES/autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch b/SOURCES/autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch
new file mode 100644
index 0000000..c859acf
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch
@@ -0,0 +1,71 @@
+autofs-5.1.7 - refactor lookup_prune_one_cache() a bit
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: use: Using an unreliable value of "me" inside the second locked
+	  section.
+
+Change lookup_prune_one_cache() a little, move the location the next
+key is set (before releasing the lock) and add a comment explaining
+why we don't care about the side effects of the read lock release/
+write lock aquire/write lock release/read lock reaquire.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/lookup.c |   20 +++++++++++++++++++-
+ 2 files changed, 20 insertions(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -63,6 +63,7 @@
+ - fix arg not used in error print.
+ - fix missing lock release in mount_subtree().
+ - fix double free in parse_mapent().
++- refactor lookup_prune_one_cache() a bit.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/lookup.c
++++ autofs-5.1.4/daemon/lookup.c
+@@ -1383,7 +1383,6 @@ void lookup_prune_one_cache(struct autof
+ 		}
+ 
+ 		key = strdup(me->key);
+-		me = cache_enumerate(mc, me);
+ 		/* Don't consider any entries with a wildcard */
+ 		if (!key || strchr(key, '*')) {
+ 			if (key)
+@@ -1430,6 +1429,7 @@ void lookup_prune_one_cache(struct autof
+ 		if (valid)
+ 			cache_unlock(valid->mc);
+ 
++		me = cache_enumerate(mc, me);
+ 		if (me)
+ 			next_key = strdup(me->key);
+ 
+@@ -1464,6 +1464,24 @@ void lookup_prune_one_cache(struct autof
+ next:
+ 		cache_readlock(mc);
+ 		if (next_key) {
++			/* The lock release and reaquire above can mean
++			 * a number of things could happen.
++			 *
++			 * First, mapents could be added between the
++			 * current mapent and the mapent of next_key.
++			 * Don't care about that because there's no
++			 * need to prune newly added entries.
++			 *
++			 * Second, the next mapent data could have
++			 * changed. Don't care about that either since
++			 * we are looking to prune stale map entries
++			 * and don't care when they become stale.
++			 *
++			 * Finally, the mapent of next_key could have
++			 * gone away. Again don't care about this either,
++			 * the loop will exit prematurely so just wait
++			 * until the next prune and try again.
++			 */
+ 			me = cache_lookup_distinct(mc, next_key);
+ 			free(next_key);
+ 		}
diff --git a/SOURCES/autofs-5.1.7-refactor-umount_multi_triggers.patch b/SOURCES/autofs-5.1.7-refactor-umount_multi_triggers.patch
new file mode 100644
index 0000000..1770d64
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-refactor-umount_multi_triggers.patch
@@ -0,0 +1,255 @@
+autofs-5.1.7 - refactor umount_multi_triggers()
+
+From: Ian Kent <raven@themaw.net>
+
+Refactor umount_multi_triggers() to try the umount of an offset subtree
+in a seperate function.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 
+ lib/mounts.c |  187 ++++++++++++++++++++++++++++++++---------------------------
+ 2 files changed, 104 insertions(+), 84 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -10,6 +10,7 @@
+ - set offset parent in update_offset_entry().
+ - remove redundant variables from mount_autofs_offset().
+ - remove unused parameter form do_mount_autofs_offset().
++- refactor umount_multi_triggers().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2490,57 +2490,6 @@ static int do_mount_autofs_offset(struct
+ 	return mounted;
+ }
+ 
+-int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+-			 const char *root, unsigned int start, const char *base)
+-{
+-	char path[PATH_MAX + 1];
+-	char *offset = path;
+-	struct mapent *oe;
+-	struct list_head *pos = NULL;
+-	unsigned int root_len = strlen(root);
+-	int mounted;
+-
+-	mounted = 0;
+-	offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+-	while (offset) {
+-		char key[PATH_MAX + 1];
+-		int key_len = root_len + strlen(offset);
+-
+-		if (key_len > PATH_MAX) {
+-			warn(ap->logopt, "path loo long");
+-			goto cont;
+-		}
+-
+-		/* The root offset is always mounted seperately so the
+-		 * offset path will always be root + offset.
+-		 */
+-		strcpy(key, root);
+-		strcat(key, offset);
+-
+-		oe = cache_lookup_distinct(me->mc, key);
+-		if (!oe || !oe->mapent)
+-			goto cont;
+-
+-		mounted += do_mount_autofs_offset(ap, oe, root);
+-
+-		/*
+-		 * If re-constructing a multi-mount it's necessary to walk
+-		 * into nested mounts, unlike the usual "mount only what's
+-		 * needed as you go" behavior.
+-		 */
+-		if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+-			if (oe->ioctlfd != -1 ||
+-			    is_mounted(oe->key, MNTS_REAL))
+-				mount_multi_triggers(ap, oe, key, strlen(key), base);
+-		}
+-cont:
+-		offset = cache_get_offset(base,
+-				offset, start, &me->multi_list, &pos);
+-	}
+-
+-	return mounted;
+-}
+-
+ static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+ {
+ 	char *dir, *path;
+@@ -2576,7 +2525,10 @@ static int rmdir_path_offset(struct auto
+ 	return ret;
+ }
+ 
+-int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
++static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root);
++
++static int do_umount_multi_triggers(struct autofs_point *ap,
++				    struct mapent *me, const char *root, const char *base)
+ {
+ 	char path[PATH_MAX + 1];
+ 	char *offset;
+@@ -2606,7 +2558,6 @@ int umount_multi_triggers(struct autofs_
+ 	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+ 		char key[PATH_MAX + 1];
+ 		int key_len = root_len + strlen(offset);
+-		char *oe_base;
+ 
+ 		if (mm_base_len > 1)
+ 			key_len += mm_base_len;
+@@ -2626,47 +2577,116 @@ int umount_multi_triggers(struct autofs_
+ 		if (!oe || (strlen(oe->key) - start) == 1)
+ 			continue;
+ 
++		left += do_umount_offset(ap, oe, root);
++	}
++
++	return left;
++}
++
++static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const char *root)
++{
++	char *oe_base;
++	int left = 0;
++
++	/*
++	 * Check for and umount subtree offsets resulting from
++	 * nonstrict mount fail.
++	 */
++	oe_base = oe->key + strlen(root);
++	left += do_umount_multi_triggers(ap, oe, root, oe_base);
++
++	if (oe->ioctlfd != -1 ||
++	    is_mounted(oe->key, MNTS_REAL)) {
++		left++;
++		return left;
++	}
++
++	debug(ap->logopt, "umount offset %s", oe->key);
++
++	if (umount_autofs_offset(ap, oe)) {
++		warn(ap->logopt, "failed to umount offset");
++		left++;
++	} else {
++		struct stat st;
++		int ret;
++
++		if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
++			return left;
++
+ 		/*
+-		 * Check for and umount subtree offsets resulting from
+-		 * nonstrict mount fail.
++		 * An error due to partial directory removal is
++		 * ok so only try and remount the offset if the
++		 * actual mount point still exists.
+ 		 */
+-		oe_base = oe->key + strlen(root);
+-		left += umount_multi_triggers(ap, oe, root, oe_base);
++		ret = rmdir_path_offset(ap, oe);
++		if (ret == -1 && !stat(oe->key, &st)) {
++			ret = do_mount_autofs_offset(ap, oe, root);
++			if (ret)
++				left++;
++			/* But we did origianlly create this */
++			oe->flags |= MOUNT_FLAG_DIR_CREATED;
++		}
++	}
++	return left;
++}
+ 
+-		if (oe->ioctlfd != -1 ||
+-		    is_mounted(oe->key, MNTS_REAL)) {
+-			left++;
+-			continue;
++int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
++			 const char *root, unsigned int start, const char *base)
++{
++	char path[PATH_MAX + 1];
++	char *offset = path;
++	struct mapent *oe;
++	struct list_head *pos = NULL;
++	unsigned int root_len = strlen(root);
++	int mounted;
++
++	mounted = 0;
++	offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
++	while (offset) {
++		char key[PATH_MAX + 1];
++		int key_len = root_len + strlen(offset);
++
++		if (key_len > PATH_MAX) {
++			warn(ap->logopt, "path loo long");
++			goto cont;
+ 		}
+ 
+-		debug(ap->logopt, "umount offset %s", oe->key);
++		/* The root offset is always mounted seperately so the
++		 * offset path will always be root + offset.
++		 */
++		strcpy(key, root);
++		strcat(key, offset);
+ 
+-		if (umount_autofs_offset(ap, oe)) {
+-			warn(ap->logopt, "failed to umount offset");
+-			left++;
+-		} else {
+-			struct stat st;
+-			int ret;
++		oe = cache_lookup_distinct(me->mc, key);
++		if (!oe || !oe->mapent)
++			goto cont;
+ 
+-			if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
+-				continue;
++		mounted += do_mount_autofs_offset(ap, oe, root);
+ 
+-			/*
+-			 * An error due to partial directory removal is
+-			 * ok so only try and remount the offset if the
+-			 * actual mount point still exists.
+-			 */
+-			ret = rmdir_path_offset(ap, oe);
+-			if (ret == -1 && !stat(oe->key, &st)) {
+-				ret = do_mount_autofs_offset(ap, oe, root);
+-				if (ret)
+-					left++;
+-				/* But we did origianlly create this */
+-				oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-			}
++		/*
++		 * If re-constructing a multi-mount it's necessary to walk
++		 * into nested mounts, unlike the usual "mount only what's
++		 * needed as you go" behavior.
++		 */
++		if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
++			if (oe->ioctlfd != -1 ||
++			    is_mounted(oe->key, MNTS_REAL))
++				mount_multi_triggers(ap, oe, key, strlen(key), base);
+ 		}
++cont:
++		offset = cache_get_offset(base,
++				offset, start, &me->multi_list, &pos);
+ 	}
+ 
++	return mounted;
++}
++
++int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
++{
++	int left;
++
++	left = do_umount_multi_triggers(ap, me, root, base);
++
+ 	if (!left && me->multi == me) {
+ 		struct mapent_cache *mc = me->mc;
+ 		int status;
+@@ -2865,4 +2885,3 @@ int clean_stale_multi_triggers(struct au
+ 
+ 	return left;
+ }
+-
diff --git a/SOURCES/autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch b/SOURCES/autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch
new file mode 100644
index 0000000..64fe382
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch
@@ -0,0 +1,544 @@
+autofs-5.1.7 - remove mount.x and rpcgen dependencies
+
+From: Ian Kent <raven@themaw.net>
+
+Adding a local implementation to get the exports list from a server
+means the the rpcgen generataed code is no longer needed so remove
+mount.x and the build dependencies.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ Makefile.conf.in    |    1 
+ autofs.spec         |    2 
+ configure           |   58 ---------
+ configure.in        |    1 
+ include/automount.h |    1 
+ include/config.h.in |    3 
+ lib/Makefile        |   26 ----
+ lib/mount.x         |  345 ---------------------------------------------------
+ 9 files changed, 5 insertions(+), 433 deletions(-)
+ delete mode 100644 lib/mount.x
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -1,5 +1,6 @@
+ 
+ - add xdr_exports().
++- remove mount.x and rpcgen dependencies.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/Makefile.conf.in
++++ autofs-5.1.4/Makefile.conf.in
+@@ -65,7 +65,6 @@ FEDFS = @ENABLE_FEDFS@
+ 
+ LEX = @PATH_LEX@
+ YACC = @PATH_YACC@
+-RPCGEN = @PATH_RPCGEN@
+ RANLIB = @PATH_RANLIB@
+ 
+ # Use libtirpc if requested and available
+--- autofs-5.1.4.orig/configure
++++ autofs-5.1.4/configure
+@@ -651,8 +651,6 @@ XML_CONFIG
+ ENABLE_FEDFS
+ sssldir
+ HAVE_SSS_AUTOFS
+-PATH_RPCGEN
+-RPCGEN
+ PATH_RANLIB
+ RANLIB
+ PATH_YACC
+@@ -4322,62 +4320,6 @@ else
+   as_fn_error $? "required program RANLIB not found" "$LINENO" 5
+ fi
+ 
+-for ac_prog in rpcgen
+-do
+-  # Extract the first word of "$ac_prog", so it can be a program name with args.
+-set dummy $ac_prog; ac_word=$2
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-$as_echo_n "checking for $ac_word... " >&6; }
+-if ${ac_cv_path_RPCGEN+:} false; then :
+-  $as_echo_n "(cached) " >&6
+-else
+-  case $RPCGEN in
+-  [\\/]* | ?:[\\/]*)
+-  ac_cv_path_RPCGEN="$RPCGEN" # Let the user override the test with a path.
+-  ;;
+-  *)
+-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $searchpath
+-do
+-  IFS=$as_save_IFS
+-  test -z "$as_dir" && as_dir=.
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+-    ac_cv_path_RPCGEN="$as_dir/$ac_word$ac_exec_ext"
+-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-  ;;
+-esac
+-fi
+-RPCGEN=$ac_cv_path_RPCGEN
+-if test -n "$RPCGEN"; then
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RPCGEN" >&5
+-$as_echo "$RPCGEN" >&6; }
+-else
+-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-fi
+-
+-
+-  test -n "$RPCGEN" && break
+-done
+-
+-if test -n "$RPCGEN"; then
+-
+-cat >>confdefs.h <<_ACEOF
+-#define PATH_RPCGEN "$RPCGEN"
+-_ACEOF
+-
+-  PATH_RPCGEN="$RPCGEN"
+-else
+-  as_fn_error $? "required program RPCGEN not found" "$LINENO" 5
+-fi
+-
+ 
+ if test -z "$sssldir"; then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sssd autofs library" >&5
+--- autofs-5.1.4.orig/configure.in
++++ autofs-5.1.4/configure.in
+@@ -165,7 +165,6 @@ AF_PATH_INCLUDE(E4FSCK, fsck.ext4 e4fsck
+ AF_CHECK_PROG(LEX, flex lex, , $searchpath)
+ AF_CHECK_PROG(YACC, bison, , $searchpath)
+ AF_CHECK_PROG(RANLIB, ranlib, , $searchpath)
+-AF_CHECK_PROG(RPCGEN, rpcgen, , $searchpath)
+ 
+ AF_CHECK_SSS_LIB(SSS_AUTOFS, libsss_autofs.so)
+ AC_SUBST(HAVE_SSS_AUTOFS)
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -32,7 +32,6 @@
+ #include "macros.h"
+ #include "log.h"
+ #include "rpc_subs.h"
+-#include "mounts.h"
+ #include "parse_subs.h"
+ #include "mounts.h"
+ #include "dev-ioctl-lib.h"
+--- autofs-5.1.4.orig/include/config.h.in
++++ autofs-5.1.4/include/config.h.in
+@@ -135,9 +135,6 @@
+ /* define if you have RANLIB */
+ #undef PATH_RANLIB
+ 
+-/* define if you have RPCGEN */
+-#undef PATH_RPCGEN
+-
+ /* define if you have UMOUNT */
+ #undef PATH_UMOUNT
+ 
+--- autofs-5.1.4.orig/lib/Makefile
++++ autofs-5.1.4/lib/Makefile
+@@ -8,10 +8,9 @@ include ../Makefile.rules
+ SRCS = cache.c cat_path.c rpc_subs.c mounts.c log.c nsswitch.c \
+ 	nss_tok.c nss_parse.tab.c args.c alarm.c macros.c defaults.c \
+ 	parse_subs.c dev-ioctl-lib.c
+-RPCS = mount.h mount_clnt.c mount_xdr.c
+-OBJS = cache.o mount_clnt.o mount_xdr.o cat_path.o rpc_subs.o \
+-	mounts.o log.o nsswitch.o nss_tok.o nss_parse.tab.o args.o \
+-	alarm.o macros.o defaults.o parse_subs.o dev-ioctl-lib.o
++OBJS = cache.o cat_path.o rpc_subs.o mounts.o log.o nsswitch.o \
++	nss_tok.o nss_parse.tab.o args.o alarm.o macros.o defaults.o \
++	parse_subs.o dev-ioctl-lib.o
+ 
+ YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h
+ 
+@@ -34,23 +33,6 @@ autofs.a: $(OBJS)
+ 	$(AR) $(ARFLAGS) $(LIB) $(OBJS)
+ 	-$(RANLIB) $(LIB)
+ 
+-mount.h: mount.x
+-	$(RPCGEN) -h -o mount.h mount.x
+-
+-mount_clnt.c: mount.h
+-	$(RPCGEN) -l -o mount_clnt.c mount.x
+-
+-mount_clnt.o: mount_clnt.c
+-	$(CC) $(CFLAGS) -o mount_clnt.o -c mount_clnt.c
+-	$(STRIP) mount_clnt.o
+-
+-mount_xdr.c: mount.h
+-	$(RPCGEN) -c -o mount_xdr.c mount.x
+-
+-mount_xdr.o: mount_xdr.c
+-	$(CC) $(CFLAGS) -Wno-unused-variable -o mount_xdr.o -c mount_xdr.c
+-	$(STRIP) mount_xdr.o
+-
+ nss_tok.c: nss_tok.l
+ 	$(LEX) -o$@ -Pnss_ $?
+ 
+@@ -61,8 +43,6 @@ nss_tok.o: nss_tok.c nss_parse.tab.h
+ 
+ nss_parse.tab.o: nss_parse.tab.c nss_parse.tab.h
+ 
+-rpc_subs.o: mount.h
+-
+ install: all
+ 
+ clean:
+--- autofs-5.1.4.orig/lib/mount.x
++++ /dev/null
+@@ -1,345 +0,0 @@
+-%/*
+-% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+-% * unrestricted use provided that this legend is included on all tape
+-% * media and as a part of the software program in whole or part.  Users
+-% * may copy or modify Sun RPC without charge, but are not authorized
+-% * to license or distribute it to anyone else except as part of a product or
+-% * program developed by the user or with the express written consent of
+-% * Sun Microsystems, Inc.
+-% *
+-% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+-% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+-% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+-% *
+-% * Sun RPC is provided with no support and without any obligation on the
+-% * part of Sun Microsystems, Inc. to assist in its use, correction,
+-% * modification or enhancement.
+-% *
+-% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+-% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+-% * OR ANY PART THEREOF.
+-% *
+-% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+-% * or profits or other special, indirect and consequential damages, even if
+-% * Sun has been advised of the possibility of such damages.
+-% *
+-% * Sun Microsystems, Inc.
+-% * 2550 Garcia Avenue
+-% * Mountain View, California  94043
+-% */
+-
+-%/*
+-% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+-% */
+-%
+-%/* from @(#)mount.x	1.3 91/03/11 TIRPC 1.0 */
+-
+-/*
+- * Protocol description for the mount program
+- */
+-
+-#ifdef RPC_HDR
+-%#ifndef _rpcsvc_mount_h
+-%#define _rpcsvc_mount_h
+-%#include <memory.h>
+-#endif
+-
+-const MNTPATHLEN = 1024;	/* maximum bytes in a pathname argument */
+-const MNTNAMLEN = 255;		/* maximum bytes in a name argument */
+-const FHSIZE = 32;		/* size in bytes of a file handle */
+-
+-/*
+- * The fhandle is the file handle that the server passes to the client.
+- * All file operations are done using the file handles to refer to a file
+- * or a directory. The file handle can contain whatever information the
+- * server needs to distinguish an individual file.
+- */
+-typedef opaque fhandle[FHSIZE];	
+-
+-/*
+- * If a status of zero is returned, the call completed successfully, and 
+- * a file handle for the directory follows. A non-zero status indicates
+- * some sort of error. The status corresponds with UNIX error numbers.
+- */
+-union fhstatus switch (unsigned fhs_status) {
+-case 0:
+-	fhandle fhs_fhandle;
+-default:
+-	void;
+-};
+-
+-/*
+- * The type dirpath is the pathname of a directory
+- */
+-typedef string dirpath<MNTPATHLEN>;
+-
+-/*
+- * The type name is used for arbitrary names (hostnames, groupnames)
+- */
+-typedef string name<MNTNAMLEN>;
+-
+-/*
+- * A list of who has what mounted
+- */
+-typedef struct mountbody *mountlist;
+-struct mountbody {
+-	name ml_hostname;
+-	dirpath ml_directory;
+-	mountlist ml_next;
+-};
+-
+-/*
+- * A list of netgroups
+- */
+-typedef struct groupnode *groups;
+-struct groupnode {
+-	name gr_name;
+-	groups gr_next;
+-};
+-
+-/*
+- * A list of what is exported and to whom
+- */
+-typedef struct exportnode *exports;
+-struct exportnode {
+-	dirpath ex_dir;
+-	groups ex_groups;
+-	exports ex_next;
+-};
+-
+-/*
+- * POSIX pathconf information
+- */
+-struct ppathcnf {
+-	int	pc_link_max;	/* max links allowed */
+-	short	pc_max_canon;	/* max line len for a tty */
+-	short	pc_max_input;	/* input a tty can eat all at once */
+-	short	pc_name_max;	/* max file name length (dir entry) */
+-	short	pc_path_max;	/* max path name length (/x/y/x/.. ) */
+-	short	pc_pipe_buf;	/* size of a pipe (bytes) */
+-	u_char	pc_vdisable;	/* safe char to turn off c_cc[i] */
+-	char	pc_xxx;		/* alignment padding; cc_t == char */
+-	short	pc_mask[2];	/* validity and boolean bits */
+-};
+-
+-/*
+- * NFSv3 file handle
+- */
+-const FHSIZE3 =	64;		/* max size of NFSv3 file handle in bytes */
+-typedef opaque		fhandle3<FHSIZE3>;
+-
+-/*
+- * NFSv3 mount status
+- */
+-enum mountstat3 {
+-	MNT_OK			= 0,	/* no error */
+-	MNT3ERR_PERM		= 1,	/* not owner */
+-	MNT3ERR_NOENT		= 2,	/* no such file or directory */
+-	MNT3ERR_IO		= 5,	/* I/O error */
+-	MNT3ERR_ACCES		= 13,	/* Permission denied */
+-	MNT3ERR_NOTDIR		= 20,	/* Not a directory */
+-	MNT3ERR_INVAL		= 22,	/* Invalid argument */
+-	MNT3ERR_NAMETOOLONG	= 63,	/* File name too long */
+-	MNT3ERR_NOTSUPP		= 10004,/* Operation not supported */
+-	MNT3ERR_SERVERFAULT	= 10006	/* A failure on the server */
+-};
+-
+-/*
+- * NFSv3 mount result
+- */
+-struct mountres3_ok {
+-	fhandle3	fhandle;
+-	int		auth_flavors<>;
+-};
+-
+-union mountres3 switch (mountstat3 fhs_status) {
+-case MNT_OK:
+-	mountres3_ok	mountinfo; /* File handle and supported flavors */
+-default:
+-	void;
+-};
+-
+-program MOUNTPROG {
+-	/*
+-	 * Version one of the mount protocol communicates with version two
+-	 * of the NFS protocol. The only connecting point is the fhandle 
+-	 * structure, which is the same for both protocols.
+-	 */
+-	version MOUNTVERS {
+-		/*
+-		 * Does no work. It is made available in all RPC services
+-		 * to allow server reponse testing and timing
+-		 */
+-		void
+-		MOUNTPROC_NULL(void) = 0;
+-
+-		/*	
+-		 * If fhs_status is 0, then fhs_fhandle contains the
+-	 	 * file handle for the directory. This file handle may
+-		 * be used in the NFS protocol. This procedure also adds
+-		 * a new entry to the mount list for this client mounting
+-		 * the directory.
+-		 * Unix authentication required.
+-		 */
+-		fhstatus 
+-		MOUNTPROC_MNT(dirpath) = 1;
+-
+-		/*
+-		 * Returns the list of remotely mounted filesystems. The 
+-		 * mountlist contains one entry for each hostname and 
+-		 * directory pair.
+-		 */
+-		mountlist
+-		MOUNTPROC_DUMP(void) = 2;
+-
+-		/*
+-		 * Removes the mount list entry for the directory
+-		 * Unix authentication required.
+-		 */
+-		void
+-		MOUNTPROC_UMNT(dirpath) = 3;
+-
+-		/*
+-		 * Removes all of the mount list entries for this client
+-		 * Unix authentication required.
+-		 */
+-		void
+-		MOUNTPROC_UMNTALL(void) = 4;
+-
+-		/*
+-		 * Returns a list of all the exported filesystems, and which
+-		 * machines are allowed to import it.
+-		 */
+-		exports
+-		MOUNTPROC_EXPORT(void)  = 5;
+-
+-		/*
+-		 * Identical to MOUNTPROC_EXPORT above
+-		 */
+-		exports
+-		MOUNTPROC_EXPORTALL(void) = 6;
+-	} = 1;
+-
+-	/*
+-	 * Version two of the mount protocol communicates with version two
+-	 * of the NFS protocol.
+-	 * The only difference from version one is the addition of a POSIX
+-	 * pathconf call.
+-	 */
+-	version MOUNTVERS_POSIX {
+-		/*
+-		 * Does no work. It is made available in all RPC services
+-		 * to allow server reponse testing and timing
+-		 */
+-		void
+-		MOUNTPROC_NULL(void) = 0;
+-
+-		/*	
+-		 * If fhs_status is 0, then fhs_fhandle contains the
+-	 	 * file handle for the directory. This file handle may
+-		 * be used in the NFS protocol. This procedure also adds
+-		 * a new entry to the mount list for this client mounting
+-		 * the directory.
+-		 * Unix authentication required.
+-		 */
+-		fhstatus 
+-		MOUNTPROC_MNT(dirpath) = 1;
+-
+-		/*
+-		 * Returns the list of remotely mounted filesystems. The 
+-		 * mountlist contains one entry for each hostname and 
+-		 * directory pair.
+-		 */
+-		mountlist
+-		MOUNTPROC_DUMP(void) = 2;
+-
+-		/*
+-		 * Removes the mount list entry for the directory
+-		 * Unix authentication required.
+-		 */
+-		void
+-		MOUNTPROC_UMNT(dirpath) = 3;
+-
+-		/*
+-		 * Removes all of the mount list entries for this client
+-		 * Unix authentication required.
+-		 */
+-		void
+-		MOUNTPROC_UMNTALL(void) = 4;
+-
+-		/*
+-		 * Returns a list of all the exported filesystems, and which
+-		 * machines are allowed to import it.
+-		 */
+-		exports
+-		MOUNTPROC_EXPORT(void)  = 5;
+-
+-		/*
+-		 * Identical to MOUNTPROC_EXPORT above
+-		 */
+-		exports
+-		MOUNTPROC_EXPORTALL(void) = 6;
+-
+-		/*
+-		 * POSIX pathconf info (Sun hack)
+-		 */
+-		ppathcnf
+-		MOUNTPROC_PATHCONF(dirpath) = 7;
+-	} = 2;
+-
+-	/*
+-	 * Version 3 of the protocol is for NFSv3
+-	 */
+-	version MOUNTVERS_NFSV3 {
+-		/*
+-		 * Does no work. It is made available in all RPC services
+-		 * to allow server reponse testing and timing
+-		 */
+-		void
+-		MOUNTPROC3_NULL(void) = 0;
+-
+-		/*	
+-		 * If fhs_status is 0, then fhs_fhandle contains the
+-	 	 * file handle for the directory. This file handle may
+-		 * be used in the NFS protocol. This procedure also adds
+-		 * a new entry to the mount list for this client mounting
+-		 * the directory.
+-		 * Unix authentication required.
+-		 */
+-		mountres3 
+-		MOUNTPROC3_MNT(dirpath) = 1;
+-
+-		/*
+-		 * Returns the list of remotely mounted filesystems. The 
+-		 * mountlist contains one entry for each hostname and 
+-		 * directory pair.
+-		 */
+-		mountlist
+-		MOUNTPROC3_DUMP(void) = 2;
+-
+-		/*
+-		 * Removes the mount list entry for the directory
+-		 * Unix authentication required.
+-		 */
+-		void
+-		MOUNTPROC3_UMNT(dirpath) = 3;
+-
+-		/*
+-		 * Removes all of the mount list entries for this client
+-		 * Unix authentication required.
+-		 */
+-		void
+-		MOUNTPROC3_UMNTALL(void) = 4;
+-
+-		/*
+-		 * Returns a list of all the exported filesystems, and which
+-		 * machines are allowed to import it.
+-		 */
+-		exports
+-		MOUNTPROC3_EXPORT(void)  = 5;
+-	} = 3;
+-} = 100005;
+-
+-#ifdef RPC_HDR
+-%#endif /*!_rpcsvc_mount_h*/
+-#endif
diff --git a/SOURCES/autofs-5.1.7-remove-mounts_mutex.patch b/SOURCES/autofs-5.1.7-remove-mounts_mutex.patch
new file mode 100644
index 0000000..7990ea7
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-mounts_mutex.patch
@@ -0,0 +1,168 @@
+autofs-5.1.7 - remove mounts_mutex
+
+From: Ian Kent <raven@themaw.net>
+
+The mounts_mutex is no longer used, remove it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ daemon/automount.c     |    8 +-------
+ daemon/master.c        |   13 -------------
+ include/automount.h    |    1 -
+ modules/mount_autofs.c |    8 --------
+ 5 files changed, 2 insertions(+), 29 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -48,6 +48,7 @@
+ - remove unused function master_submount_list_empty().
+ - move amd mounts removal into lib/mounts.c.
+ - check for offset with no mount location.
++- remove mounts_mutex.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -1749,7 +1749,6 @@ static void handle_mounts_cleanup(void *
+ 	 * here.
+ 	 */
+ 	if (submount) {
+-		mounts_mutex_unlock(ap->parent);
+ 		master_source_unlock(ap->parent->entry);
+ 		master_free_mapent_sources(ap->entry, 1);
+ 		master_free_mapent(ap->entry);
+@@ -1787,13 +1786,9 @@ static int submount_source_writelock_nes
+ 	if (status)
+ 		goto done;
+ 
+-	mounts_mutex_lock(parent);
+-
+ 	status = pthread_rwlock_trywrlock(&ap->entry->source_lock);
+-	if (status) {
+-		mounts_mutex_unlock(parent);
++	if (status)
+ 		master_source_unlock(parent->entry);
+-	}
+ 
+ done:
+ 	if (status && status != EBUSY) {
+@@ -1809,7 +1804,6 @@ static void submount_source_unlock_neste
+ 	struct autofs_point *parent = ap->parent;
+ 
+ 	master_source_unlock(ap->entry);
+-	mounts_mutex_unlock(parent);
+ 	master_source_unlock(parent->entry);
+ }
+ 
+--- autofs-5.1.4.orig/daemon/master.c
++++ autofs-5.1.4/daemon/master.c
+@@ -69,7 +69,6 @@ int master_add_autofs_point(struct maste
+ 			    unsigned nobind, unsigned ghost, int submount)
+ {
+ 	struct autofs_point *ap;
+-	int status;
+ 
+ 	ap = malloc(sizeof(struct autofs_point));
+ 	if (!ap)
+@@ -128,12 +127,6 @@ int master_add_autofs_point(struct maste
+ 	INIT_LIST_HEAD(&ap->amdmounts);
+ 	ap->shutdown = 0;
+ 
+-	status = pthread_mutex_init(&ap->mounts_mutex, NULL);
+-	if (status) {
+-		free(ap->path);
+-		free(ap);
+-		return 0;
+-	}
+ 	ap->mode = 0;
+ 
+ 	entry->ap = ap;
+@@ -143,17 +136,11 @@ int master_add_autofs_point(struct maste
+ 
+ void master_free_autofs_point(struct autofs_point *ap)
+ {
+-	int status;
+-
+ 	if (!ap)
+ 		return;
+ 
+ 	mnts_remove_amdmounts(ap);
+ 
+-	status = pthread_mutex_destroy(&ap->mounts_mutex);
+-	if (status)
+-		fatal(status);
+-
+ 	if (ap->pref)
+ 		free(ap->pref);
+ 	free(ap->path);
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -564,7 +564,6 @@ struct autofs_point {
+ 	enum states state;		/* Current state */
+ 	int state_pipe[2];		/* State change router pipe */
+ 	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 */
+ 	unsigned int submount;		/* Is this a submount */
+ 	unsigned int submnt_count;	/* Number of submounts */
+--- autofs-5.1.4.orig/modules/mount_autofs.c
++++ autofs-5.1.4/modules/mount_autofs.c
+@@ -283,8 +283,6 @@ int mount_mount(struct autofs_point *ap,
+ 	set_exp_timeout(nap, NULL, timeout);
+ 	nap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+ 
+-	mounts_mutex_lock(ap);
+-
+ 	if (source->flags & MAP_FLAG_FORMAT_AMD) {
+ 		struct mnt_list *mnt;
+ 
+@@ -305,7 +303,6 @@ int mount_mount(struct autofs_point *ap,
+ 	if (handle_mounts_startup_cond_init(&suc)) {
+ 		crit(ap->logopt, MODPREFIX
+ 		     "failed to init startup cond for mount %s", entry->path);
+-		mounts_mutex_unlock(ap);
+ 		master_free_map_source(source, 1);
+ 		master_free_mapent(entry);
+ 		return 1;
+@@ -316,7 +313,6 @@ int mount_mount(struct autofs_point *ap,
+ 		crit(ap->logopt,
+ 		     MODPREFIX "failed to allocate mount %s", realpath);
+ 		handle_mounts_startup_cond_destroy(&suc);
+-		mounts_mutex_unlock(ap);
+ 		master_free_map_source(source, 1);
+ 		master_free_mapent(entry);
+ 		return 1;
+@@ -335,7 +331,6 @@ int mount_mount(struct autofs_point *ap,
+ 		     realpath);
+ 		handle_mounts_startup_cond_destroy(&suc);
+ 		mnts_remove_submount(nap->path);
+-		mounts_mutex_unlock(ap);
+ 		master_free_map_source(source, 1);
+ 		master_free_mapent(entry);
+ 		return 1;
+@@ -346,7 +341,6 @@ int mount_mount(struct autofs_point *ap,
+ 		if (status) {
+ 			handle_mounts_startup_cond_destroy(&suc);
+ 			mnts_remove_submount(nap->path);
+-			mounts_mutex_unlock(ap);
+ 			master_free_map_source(source, 1);
+ 			master_free_mapent(entry);
+ 			fatal(status);
+@@ -358,7 +352,6 @@ int mount_mount(struct autofs_point *ap,
+ 		     MODPREFIX "failed to create submount for %s", realpath);
+ 		handle_mounts_startup_cond_destroy(&suc);
+ 		mnts_remove_submount(nap->path);
+-		mounts_mutex_unlock(ap);
+ 		master_free_map_source(source, 1);
+ 		master_free_mapent(entry);
+ 		return 1;
+@@ -368,7 +361,6 @@ int mount_mount(struct autofs_point *ap,
+ 	ap->submnt_count++;
+ 
+ 	handle_mounts_startup_cond_destroy(&suc);
+-	mounts_mutex_unlock(ap);
+ 
+ 	return 0;
+ }
diff --git a/SOURCES/autofs-5.1.7-remove-obsolete-functions.patch b/SOURCES/autofs-5.1.7-remove-obsolete-functions.patch
new file mode 100644
index 0000000..5582589
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-obsolete-functions.patch
@@ -0,0 +1,739 @@
+autofs-5.1.7 - remove obsolete functions
+
+From: Ian Kent <raven@themaw.net>
+
+Remove the code that's no longer used due to the tree mapent
+implementation.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ include/automount.h |   10 -
+ include/mounts.h    |    2 
+ lib/cache.c         |  227 -------------------------------------
+ lib/mounts.c        |  311 ----------------------------------------------------
+ modules/parse_sun.c |   56 ---------
+ 6 files changed, 2 insertions(+), 605 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -41,6 +41,7 @@
+ - add set_offset_tree_catatonic().
+ - add mount and umount offsets functions.
+ - switch to use tree implementation for offsets.
++- remove obsolete functions.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -162,16 +162,13 @@ struct stack {
+ struct mapent {
+ 	struct mapent *next;
+ 	struct list_head ino_index;
+-	struct list_head multi_list;
+ 	struct mapent_cache *mc;
+ 	struct map_source *source;
+ 	/* Need to know owner if we're a multi-mount */
+ 	struct tree_node *mm_root;
++	/* Parent nesting point within multi-mount */
+ 	struct tree_node *mm_parent;
+ 	struct tree_node node;
+-	struct mapent *multi;
+-	/* Parent nesting point within multi-mount */
+-	struct mapent *parent;
+ 	char *key;
+ 	size_t len;
+ 	char *mapent;
+@@ -209,23 +206,18 @@ struct mapent *cache_lookup_next(struct
+ struct mapent *cache_lookup_key_next(struct mapent *me);
+ struct mapent *cache_lookup(struct mapent_cache *mc, const char *key);
+ struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key);
+-struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int start, struct list_head *head);
+ struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix);
+ struct mapent *cache_partial_match_wild(struct mapent_cache *mc, const char *prefix);
+ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age);
+ void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout);
+ struct mapent *cache_get_offset_parent(struct mapent_cache *mc, const char *key);
+-int cache_set_offset_parent(struct mapent_cache *mc, const char *offset);
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+-int cache_delete_offset(struct mapent_cache *mc, const char *key);
+-int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
+ void cache_release(struct map_source *map);
+ void cache_clean_null_cache(struct mapent_cache *mc);
+ void cache_release_null_cache(struct master *master);
+ struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me);
+-char *cache_get_offset(const char *prefix, char *offset, int start, struct list_head *head, struct list_head **pos);
+ 
+ /* Utility functions */
+ 
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -187,8 +187,6 @@ void set_indirect_mount_tree_catatonic(s
+ void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *);
+ int umount_ent(struct autofs_point *, const char *);
+ int umount_amd_ext_mount(struct autofs_point *, const char *);
+-int mount_multi_triggers(struct autofs_point *, struct mapent *, const char *, unsigned int, const char *);
+-int umount_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
+ int clean_stale_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *);
+ 
+ #endif
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -461,30 +461,6 @@ struct mapent *cache_lookup_distinct(str
+ 	return NULL;
+ }
+ 
+-/* Lookup an offset within a multi-mount entry */
+-struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int start, struct list_head *head)
+-{
+-	struct list_head *p;
+-	struct mapent *this;
+-	/* Keys for direct maps may be as long as a path name */
+-	char o_key[PATH_MAX];
+-	/* Avoid "//" at the beginning of paths */
+-	const char *path_prefix = strlen(prefix) > 1 ? prefix : "";
+-	size_t size;
+-
+-	/* root offset duplicates "/" */
+-	size = snprintf(o_key, sizeof(o_key), "%s%s", path_prefix, offset);
+-	if (size >= sizeof(o_key))
+-		return NULL;
+-
+-	list_for_each(p, head) {
+-		this = list_entry(p, struct mapent, multi_list);
+-		if (!strcmp(&this->key[start], o_key))
+-			return this;
+-	}
+-	return NULL;
+-}
+-
+ /* cache must be read locked by caller */
+ static struct mapent *__cache_partial_match(struct mapent_cache *mc,
+ 					    const char *prefix,
+@@ -583,9 +559,6 @@ int cache_add(struct mapent_cache *mc, s
+ 	me->mm_parent = NULL;
+ 	INIT_TREE_NODE(&me->node);
+ 	INIT_LIST_HEAD(&me->ino_index);
+-	INIT_LIST_HEAD(&me->multi_list);
+-	me->multi = NULL;
+-	me->parent = NULL;
+ 	me->ioctlfd = -1;
+ 	me->dev = (dev_t) -1;
+ 	me->ino = (ino_t) -1;
+@@ -616,33 +589,6 @@ int cache_add(struct mapent_cache *mc, s
+ }
+ 
+ /* cache must be write locked by caller */
+-static void cache_add_ordered_offset(struct mapent *me, struct list_head *head)
+-{
+-	struct list_head *p;
+-	struct mapent *this;
+-
+-	list_for_each(p, head) {
+-		size_t tlen;
+-		int eq;
+-
+-		this = list_entry(p, struct mapent, multi_list);
+-		tlen = strlen(this->key);
+-
+-		eq = strncmp(this->key, me->key, tlen);
+-		if (!eq && tlen == strlen(me->key))
+-			return;
+-
+-		if (eq > 0) {
+-			list_add_tail(&me->multi_list, p);
+-			return;
+-		}
+-	}
+-	list_add_tail(&me->multi_list, p);
+-
+-	return;
+-}
+-
+-/* cache must be write locked by caller */
+ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age)
+ {
+ 	unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt();
+@@ -747,25 +693,6 @@ struct mapent *cache_get_offset_parent(s
+ 	return NULL;
+ }
+ 
+-int cache_set_offset_parent(struct mapent_cache *mc, const char *offset)
+-{
+-	struct mapent *this, *parent;
+-
+-	this = cache_lookup_distinct(mc, offset);
+-	if (!this)
+-		return 0;
+-	if (!IS_MM(this))
+-		return 0;
+-
+-	parent = cache_get_offset_parent(mc, offset);
+-	if (parent)
+-		this->parent = parent;
+-	else
+-		this->parent = MM_ROOT(this);
+-
+-	return 1;
+-}
+-
+ /* cache must be write locked by caller */
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age)
+ {
+@@ -807,50 +734,6 @@ int cache_update(struct mapent_cache *mc
+ 	return ret;
+ }
+ 
+-/* cache write lock of the multi mount owner must be held by caller */
+-int cache_delete_offset(struct mapent_cache *mc, const char *key)
+-{
+-	u_int32_t hashval = hash(key, mc->size);
+-	struct mapent *me = NULL, *pred;
+-	int status;
+-
+-	me = mc->hash[hashval];
+-	if (!me)
+-		return CHE_FAIL;
+-
+-	if (strcmp(key, me->key) == 0) {
+-		if (IS_MM(me) && IS_MM_ROOT(me))
+-			return CHE_FAIL;
+-		mc->hash[hashval] = me->next;
+-		goto delete;
+-	}
+-
+-	while (me->next != NULL) {
+-		pred = me;
+-		me = me->next;
+-		if (strcmp(key, me->key) == 0) {
+-			if (IS_MM(me) && IS_MM_ROOT(me))
+-				return CHE_FAIL;
+-			pred->next = me->next;
+-			goto delete;
+-		}
+-	}
+-
+-	return CHE_FAIL;
+-
+-delete:
+-	list_del(&me->multi_list);
+-	ino_index_lock(mc);
+-	list_del(&me->ino_index);
+-	ino_index_unlock(mc);
+-	free(me->key);
+-	if (me->mapent)
+-		free(me->mapent);
+-	free(me);
+-
+-	return CHE_OK;
+-}
+-
+ /* cache must be write locked by caller */
+ int cache_delete(struct mapent_cache *mc, const char *key)
+ {
+@@ -1024,113 +907,3 @@ struct mapent *cache_enumerate(struct ma
+ 
+ 	return cache_lookup_next(mc, me);
+ }
+-
+-/*
+- * Get each offset from list head under prefix.
+- * Maintain traversal current position in pos for subsequent calls. 
+- * Return each offset into offset.
+- */
+-/* cache must be read locked by caller */
+-char *cache_get_offset(const char *prefix, char *offset, int start,
+-			struct list_head *head, struct list_head **pos)
+-{
+-	struct list_head *next;
+-	struct mapent *this;
+-	size_t plen = strlen(prefix);
+-	size_t len = 0;
+-
+-	if (*pos == head)
+-		return NULL;
+-
+-	/* Find an offset */
+-	*offset = '\0';
+-	next = *pos ? (*pos)->next : head->next;
+-	while (next != head) {
+-		char *offset_start, *pstart, *pend;
+-
+-		this = list_entry(next, struct mapent, multi_list);
+-		*pos = next;
+-		next = next->next;
+-
+-		offset_start = &this->key[start];
+-		if (strlen(offset_start) <= plen)
+-			continue;
+-
+-		if (!strncmp(prefix, offset_start, plen)) {
+-			struct mapent *np = NULL;
+-			char pe[PATH_MAX + 1];
+-
+-			/* "/" doesn't count for root offset */
+-			if (plen == 1)
+-				pstart = &offset_start[plen - 1];
+-			else
+-				pstart = &offset_start[plen];
+-
+-			/* not part of this sub-tree */
+-			if (*pstart != '/')
+-				continue;
+-
+-			/* get next offset */
+-			pend = pstart;
+-			while (*pend++) {
+-				size_t nest_pt_offset;
+-
+-				if (*pend != '/')
+-					continue;
+-
+-				nest_pt_offset = start + pend - pstart;
+-				if (plen > 1)
+-					nest_pt_offset += plen;
+-				strcpy(pe, this->key);
+-				pe[nest_pt_offset] = '\0';
+-
+-				np = cache_lookup_distinct(this->mc, pe);
+-				if (np)
+-					break;
+-			}
+-			if (np)
+-				continue;
+-			len = pend - pstart - 1;
+-			strncpy(offset, pstart, len);
+-			offset[len] ='\0';
+-			break;
+-		}
+-	}
+-
+-	/* Seek to next offset */
+-	while (next != head) {
+-		char *offset_start, *pstart;
+-
+-		this = list_entry(next, struct mapent, multi_list);
+-
+-		offset_start = &this->key[start];
+-		if (strlen(offset_start) <= plen + len)
+-			break;
+-
+-		/* "/" doesn't count for root offset */
+-		if (plen == 1)
+-			pstart = &offset_start[plen - 1];
+-		else
+-			pstart = &offset_start[plen];
+-
+-		/* not part of this sub-tree */
+-		if (*pstart != '/')
+-			break;
+-
+-		/* new offset */
+-		if (!*(pstart + len + 1))
+-			break;
+-
+-		/* compare offset */
+-		if (pstart[len] != '/' ||
+-		    strlen(pstart) != len ||
+-		    strncmp(offset, pstart, len))
+-			break;
+-
+-		*pos = next;
+-		next = next->next;
+-	}
+-
+-	return *offset ? offset : NULL;
+-}
+-
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2849,21 +2849,6 @@ static void set_offset_tree_catatonic(st
+ 	tree_traverse_inorder(MAPENT_ROOT(me), set_offset_tree_catatonic_work, NULL);
+ }
+ 
+-static void set_multi_mount_tree_catatonic(struct autofs_point *ap, struct mapent *me)
+-{
+-	if (!list_empty(&me->multi_list)) {
+-		struct list_head *head = &me->multi_list;
+-		struct list_head *p;
+-
+-		list_for_each(p, head) {
+-			struct mapent *this;
+-
+-			this = list_entry(p, struct mapent, multi_list);
+-			set_mount_catatonic(ap, this, this->ioctlfd);
+-		}
+-	}
+-}
+-
+ void set_indirect_mount_tree_catatonic(struct autofs_point *ap)
+ {
+ 	struct master_mapent *entry = ap->entry;
+@@ -3028,299 +3013,3 @@ done:
+ out:
+ 	return rv;
+ }
+-
+-static int do_mount_autofs_offset(struct autofs_point *ap, struct mapent *oe)
+-{
+-	int mounted = 0;
+-	int ret;
+-
+-	debug(ap->logopt, "mount offset %s", oe->key);
+-
+-	ret = mount_autofs_offset(ap, oe);
+-	if (ret >= MOUNT_OFFSET_OK)
+-		mounted++;
+-	else {
+-		if (ret != MOUNT_OFFSET_IGNORE)
+-			warn(ap->logopt, "failed to mount offset");
+-		else {
+-			debug(ap->logopt, "ignoring \"nohide\" trigger %s",
+-			      oe->key);
+-			/*
+-			 * Ok, so we shouldn't modify the mapent but
+-			 * mount requests are blocked at a point above
+-			 * this and expire only uses the mapent key or
+-			 * holds the cache write lock.
+-			 */
+-			free(oe->mapent);
+-			oe->mapent = NULL;
+-		}
+-	}
+-
+-	return mounted;
+-}
+-
+-static int rmdir_path_offset(struct autofs_point *ap, struct mapent *oe)
+-{
+-	char *dir, *path;
+-	unsigned int split;
+-	int ret;
+-
+-	if (ap->type == LKP_DIRECT)
+-		return rmdir_path(ap, oe->key, MM_ROOT(oe)->dev);
+-
+-	dir = strdup(oe->key);
+-
+-	if (ap->flags & MOUNT_FLAG_GHOST)
+-		split = ap->len + strlen(MM_ROOT(oe)->key) + 1;
+-	else
+-		split = ap->len;
+-
+-	dir[split] = '\0';
+-	path = &dir[split + 1];
+-
+-	if (chdir(dir) == -1) {
+-		error(ap->logopt, "failed to chdir to %s", dir);
+-		free(dir);
+-		return -1;
+-	}
+-
+-	ret = rmdir_path(ap, path, ap->dev);
+-
+-	free(dir);
+-
+-	if (chdir("/") == -1)
+-		error(ap->logopt, "failed to chdir to /");
+-
+-	return ret;
+-}
+-
+-static int do_umount_offset(struct autofs_point *ap,
+-			    struct mapent *oe, const char *root, int start);
+-
+-static int do_umount_multi_triggers(struct autofs_point *ap,
+-				    struct mapent *me, const char *root,
+-				    int start, const char *base)
+-{
+-	char path[PATH_MAX + 1];
+-	char *offset;
+-	struct mapent *oe;
+-	struct list_head *mm_root, *pos;
+-	const char o_root[] = "/";
+-	const char *mm_base;
+-	int left;
+-	unsigned int root_len;
+-	unsigned int mm_base_len;
+-
+-	left = 0;
+-
+-	mm_root = &me->multi->multi_list;
+-
+-	if (!base)
+-		mm_base = o_root;
+-	else
+-		mm_base = base;
+-
+-	pos = NULL;
+-	offset = path;
+-	root_len = start;
+-	mm_base_len = strlen(mm_base);
+-
+-	while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+-		char key[PATH_MAX + 1];
+-		int key_len = root_len + strlen(offset);
+-
+-		if (mm_base_len > 1)
+-			key_len += mm_base_len;
+-
+-		if (key_len > PATH_MAX) {
+-			warn(ap->logopt, "path loo long");
+-			continue;
+-		}
+-
+-		strcpy(key, root);
+-		if (mm_base_len > 1)
+-			strcat(key, mm_base);
+-		strcat(key, offset);
+-
+-		oe = cache_lookup_distinct(me->mc, key);
+-		/* root offset is a special case */
+-		if (!oe || (strlen(oe->key) - start) == 1)
+-			continue;
+-
+-		left += do_umount_offset(ap, oe, root, start);
+-	}
+-
+-	return left;
+-}
+-
+-static int do_umount_offset(struct autofs_point *ap,
+-			    struct mapent *oe, const char *root, int start)
+-{
+-	char *oe_base;
+-	int left = 0;
+-
+-	/*
+-	 * Check for and umount subtree offsets resulting from
+-	 * nonstrict mount fail.
+-	 */
+-	oe_base = oe->key + start;
+-	left += do_umount_multi_triggers(ap, oe, root, start, oe_base);
+-
+-	/*
+-	 * If an offset that has an active mount has been removed
+-	 * from the multi-mount we don't want to attempt to trigger
+-	 * mounts for it. Obviously this is because it has been
+-	 * removed, but less obvious is the potential strange
+-	 * behaviour that can result if we do try and mount it
+-	 * again after it's been expired. For example, if an NFS
+-	 * file system is no longer exported and is later umounted
+-	 * it can be mounted again without any error message but
+-	 * shows as an empty directory. That's going to confuse
+-	 * people for sure.
+-	 *
+-	 * If the mount cannot be umounted (the process is now
+-	 * using a stale mount) the offset needs to be invalidated
+-	 * so no further mounts will be attempted but the offset
+-	 * cache entry must remain so expires can continue to
+-	 * attempt to umount it. If the mount can be umounted and
+-	 * the offset is removed, at least for NFS we will get
+-	 * ESTALE errors when attempting list the directory.
+-	 */
+-	if (oe->ioctlfd != -1 ||
+-	    is_mounted(oe->key, MNTS_REAL)) {
+-		if (umount_ent(ap, oe->key) &&
+-		    is_mounted(oe->key, MNTS_REAL)) {
+-			debug(ap->logopt,
+-			      "offset %s has active mount, invalidate",
+-			      oe->key);
+-			/*
+-			 * Ok, so we shouldn't modify the mapent but
+-			 * mount requests are blocked at a point above
+-			 * this and expire only uses the mapent key or
+-			 * holds the cache write lock.
+-			 */
+-			if (oe->mapent) {
+-				free(oe->mapent);
+-				oe->mapent = NULL;
+-			}
+-			return ++left;
+-		}
+-	}
+-
+-	debug(ap->logopt, "umount offset %s", oe->key);
+-
+-	if (umount_autofs_offset(ap, oe)) {
+-		warn(ap->logopt, "failed to umount offset");
+-		left++;
+-	} else {
+-		struct stat st;
+-		int ret;
+-
+-		if (!(oe->flags & MOUNT_FLAG_DIR_CREATED))
+-			return left;
+-
+-		/*
+-		 * An error due to partial directory removal is
+-		 * ok so only try and remount the offset if the
+-		 * actual mount point still exists.
+-		 */
+-		ret = rmdir_path_offset(ap, oe);
+-		if (ret == -1 && !stat(oe->key, &st)) {
+-			ret = do_mount_autofs_offset(ap, oe);
+-			if (ret)
+-				left++;
+-			/* But we did origianlly create this */
+-			oe->flags |= MOUNT_FLAG_DIR_CREATED;
+-		}
+-	}
+-	return left;
+-}
+-
+-int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
+-			 const char *root, unsigned int start, const char *base)
+-{
+-	char path[PATH_MAX + 1];
+-	char *offset = path;
+-	struct mapent *oe;
+-	struct list_head *pos = NULL;
+-	unsigned int root_len = strlen(root);
+-	int mounted;
+-
+-	mounted = 0;
+-	offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+-	while (offset) {
+-		char key[PATH_MAX + 1];
+-		int key_len = root_len + strlen(offset);
+-
+-		if (key_len > PATH_MAX) {
+-			warn(ap->logopt, "path loo long");
+-			goto cont;
+-		}
+-
+-		/* The root offset is always mounted seperately so the
+-		 * offset path will always be root + offset.
+-		 */
+-		strcpy(key, root);
+-		strcat(key, offset);
+-
+-		oe = cache_lookup_distinct(me->mc, key);
+-		if (!oe || !oe->mapent)
+-			goto cont;
+-		if (oe->age != MM_ROOT(me)->age) {
+-			/* Best effort */
+-			do_umount_offset(ap, oe, root, start);
+-			goto cont;
+-		}
+-
+-		mounted += do_mount_autofs_offset(ap, oe);
+-
+-		/*
+-		 * If re-constructing a multi-mount it's necessary to walk
+-		 * into nested mounts, unlike the usual "mount only what's
+-		 * needed as you go" behavior.
+-		 */
+-		if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
+-			if (oe->ioctlfd != -1 ||
+-			    is_mounted(oe->key, MNTS_REAL))
+-				mount_multi_triggers(ap, oe, key, key_len, base);
+-		}
+-cont:
+-		offset = cache_get_offset(base,
+-				offset, start, &me->multi_list, &pos);
+-	}
+-
+-	return mounted;
+-}
+-
+-int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root, const char *base)
+-{
+-	int left, start;
+-
+-	start = strlen(root);
+-
+-	left = do_umount_multi_triggers(ap, me, root, start, base);
+-
+-	if (!left && IS_MM_ROOT(me)) {
+-		/*
+-		 * Special case.
+-		 * If we can't umount the root container then we can't
+-		 * delete the offsets from the cache and we need to put
+-		 * the offset triggers back.
+-		 */
+-		if (is_mounted(root, MNTS_REAL)) {
+-			info(ap->logopt, "unmounting dir = %s", root);
+-			if (umount_ent(ap, root) &&
+-			    is_mounted(root, MNTS_REAL)) {
+-				if (mount_multi_triggers(ap, me, root, start, "/") < 0)
+-					warn(ap->logopt,
+-					     "failed to remount offset triggers");
+-				return ++left;
+-			}
+-		}
+-
+-	       /* check for mounted mount entry and remove it if found */
+-               mnts_remove_mount(root, MNTS_MOUNTED);
+-	}
+-
+-	return left;
+-}
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1076,62 +1076,6 @@ next:
+ 	return (p - ent);
+ }
+ 
+-static void cleanup_multi_triggers(struct autofs_point *ap,
+-			    struct mapent *me, const char *root, int start,
+-			    const char *base)
+-{
+-	char path[PATH_MAX + 1];
+-	char offset[PATH_MAX + 1];
+-	char *poffset = offset;
+-	struct mapent *oe;
+-	struct list_head *mm_root, *pos;
+-	const char o_root[] = "/";
+-	const char *mm_base;
+-	unsigned int root_len;
+-	unsigned int mm_base_len;
+-
+-	mm_root = &me->multi->multi_list;
+-
+-	if (!base)
+-		mm_base = o_root;
+-	else
+-		mm_base = base;
+-
+-	pos = NULL;
+-	root_len = strlen(root);
+-	mm_base_len = strlen(mm_base);
+-
+-	/* Make sure "none" of the offsets have an active mount. */
+-	while ((poffset = cache_get_offset(mm_base, poffset, start, mm_root, &pos))) {
+-		unsigned int path_len = root_len + strlen(poffset);
+-
+-		if (mm_base_len > 1)
+-			path_len += mm_base_len;
+-
+-		if (path_len > PATH_MAX) {
+-			warn(ap->logopt, "path loo long");
+-			continue;
+-		}
+-
+-		strcpy(path, root);
+-		if (mm_base_len > 1)
+-			strcat(path, mm_base);
+-		strcat(path, poffset);
+-
+-		oe = cache_lookup_distinct(me->mc, path);
+-		/* root offset is a special case */
+-		if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
+-			continue;
+-
+-		if (umount(path)) {
+-			error(ap->logopt, "error recovering from mount fail");
+-			error(ap->logopt, "cannot umount offset %s", path);
+-		}
+-	}
+-
+-	return;
+-}
+-
+ static int mount_subtree(struct autofs_point *ap, struct mapent_cache *mc,
+ 			 const char *name, char *loc, char *options, void *ctxt)
+ {
diff --git a/SOURCES/autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch b/SOURCES/autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch
new file mode 100644
index 0000000..c5d2c17
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch
@@ -0,0 +1,36 @@
+autofs-5.1.7 - remove redundant assignment in master_add_amd_mount_section_mounts()
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: missing_lock: Accessing "entry->current" without holding lock
+	  "master_mapent.current_mutex".
+
+This is initialization not clearing current source. But the field has
+already been initialized in the master_new_mapent() call.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/master.c |    1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -58,6 +58,7 @@
+ - add length check in umount_subtree_mounts().
+ - fix flags check in umount_multi().
+ - dont try umount after stat() ENOENT fail.
++- remove redundant assignment in master_add_amd_mount_section_mounts().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/master.c
++++ autofs-5.1.4/daemon/master.c
+@@ -996,7 +996,6 @@ static void master_add_amd_mount_section
+ 		source->master_line = 0;
+ 
+ 		entry->age = age;
+-		entry->current = NULL;
+ 
+ 		master_add_mapent(master, entry);
+ next:
diff --git a/SOURCES/autofs-5.1.7-remove-redundant-if-check.patch b/SOURCES/autofs-5.1.7-remove-redundant-if-check.patch
new file mode 100644
index 0000000..06d2cca
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-redundant-if-check.patch
@@ -0,0 +1,36 @@
+autofs-5.1.7 - remove redundant if check
+
+From: Ian Kent <raven@themaw.net>
+
+Coverity: identical code in if condition branches.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG       |    1 +
+ daemon/direct.c |    5 +----
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -51,6 +51,7 @@
+ - remove mounts_mutex.
+ - remove unused variable from get_exports().
+ - add missing free in handle_mounts().
++- remove redundant if check.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -752,10 +752,7 @@ int mount_autofs_offset(struct autofs_po
+ 
+ 	ops->timeout(ap->logopt, ioctlfd, timeout);
+ 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
+-	if (ap->logopt & LOGOPT_DEBUG)
+-		notify_mount_result(ap, me->key, timeout, str_offset);
+-	else
+-		notify_mount_result(ap, me->key, timeout, str_offset);
++	notify_mount_result(ap, me->key, timeout, str_offset);
+ 	ops->close(ap->logopt, ioctlfd);
+ 
+ 	debug(ap->logopt, "mounted trigger %s", me->key);
diff --git a/SOURCES/autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch b/SOURCES/autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch
new file mode 100644
index 0000000..be6b966
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch
@@ -0,0 +1,70 @@
+autofs-5.1.7 - remove redundant local var from sun_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+The local variable mountpoint in sun_mount() is set directly from a
+passed in parameter and never changed and the source isn't changed
+either, so use the variable directly.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   13 ++++---------
+ 2 files changed, 5 insertions(+), 9 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -42,6 +42,7 @@
+ - add mount and umount offsets functions.
+ - switch to use tree implementation for offsets.
+ - remove obsolete functions.
++- remove redundant local var from sun_mount().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -530,7 +530,6 @@ static int sun_mount(struct autofs_point
+ 	int nonstrict = 1;
+ 	int use_weight_only = ap->flags & MOUNT_FLAG_USE_WEIGHT_ONLY;
+ 	int rv, cur_state;
+-	char *mountpoint;
+ 	char *what;
+ 	char *type;
+ 
+@@ -623,9 +622,6 @@ static int sun_mount(struct autofs_point
+ 		}
+ 	}
+ 
+-	mountpoint = alloca(namelen + 1);
+-	sprintf(mountpoint, "%.*s", namelen, name);
+-
+ 	type = ap->entry->maps->type;
+ 	if (type && !strcmp(type, "hosts")) {
+ 		if (options && *options != '\0') {
+@@ -700,9 +696,9 @@ static int sun_mount(struct autofs_point
+ 		debug(ap->logopt, MODPREFIX
+ 		      "mounting root %s, mountpoint %s, "
+ 		      "what %s, fstype %s, options %s",
+-		      root, mountpoint, what, fstype, options);
++		      root, name, what, fstype, options);
+ 
+-		rv = mount_nfs->mount_mount(ap, root, mountpoint, strlen(mountpoint),
++		rv = mount_nfs->mount_mount(ap, root, name, namelen,
+ 					    what, fstype, options, mount_nfs->context);
+ 	} else {
+ 		if (!loclen)
+@@ -722,11 +718,10 @@ static int sun_mount(struct autofs_point
+ 		debug(ap->logopt, MODPREFIX
+ 		      "mounting root %s, mountpoint %s, "
+ 		      "what %s, fstype %s, options %s",
+-		      root, mountpoint, what, fstype, options);
++		      root, name, what, fstype, options);
+ 
+ 		/* Generic mount routine */
+-		rv = do_mount(ap, root, mountpoint, strlen(mountpoint), what, fstype,
+-			      options);
++		rv = do_mount(ap, root, name, namelen, what, fstype, options);
+ 	}
+ 	pthread_setcancelstate(cur_state, NULL);
+ 
diff --git a/SOURCES/autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch b/SOURCES/autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch
new file mode 100644
index 0000000..72e1016
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch
@@ -0,0 +1,174 @@
+autofs-5.1.7 - remove redundant variables from mount_autofs_offset()
+
+From: Ian Kent <raven@themaw.net>
+
+The path to be mounted is the key in the passed in mapent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ daemon/direct.c     |   42 +++++++++++++++++++-----------------------
+ include/automount.h |    2 +-
+ lib/mounts.c        |    2 +-
+ 4 files changed, 22 insertions(+), 25 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -8,6 +8,7 @@
+ - fix is mounted check on non existent path.
+ - simplify cache_get_parent().
+ - set offset parent in update_offset_entry().
++- remove redundant variables from mount_autofs_offset().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/direct.c
++++ autofs-5.1.4/daemon/direct.c
+@@ -611,7 +611,7 @@ force_umount:
+ 	return rv;
+ }
+ 
+-int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *root, const char *offset)
++int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
+ {
+ 	const char *str_offset = mount_type_str(t_offset);
+ 	struct ioctl_ops *ops = get_ioctl_ops();
+@@ -623,7 +623,6 @@ int mount_autofs_offset(struct autofs_po
+ 	const char *hosts_map_name = "-hosts";
+ 	const char *map_name = hosts_map_name;
+ 	const char *type;
+-	char mountpoint[PATH_MAX];
+ 	struct mnt_list *mnt;
+ 
+ 	if (ops->version && ap->flags & MOUNT_FLAG_REMOUNT) {
+@@ -681,11 +680,8 @@ int mount_autofs_offset(struct autofs_po
+ 			return MOUNT_OFFSET_OK;
+ 	}
+ 
+-	strcpy(mountpoint, root);
+-	strcat(mountpoint, offset);
+-
+ 	/* In case the directory doesn't exist, try to mkdir it */
+-	if (mkdir_path(mountpoint, mp_mode) < 0) {
++	if (mkdir_path(me->key, mp_mode) < 0) {
+ 		if (errno == EEXIST) {
+ 			/*
+ 			 * If the mount point directory is a real mount
+@@ -694,7 +690,7 @@ int mount_autofs_offset(struct autofs_po
+ 			 * the kernel NFS client.
+ 			 */
+ 			if (me->multi != me &&
+-			    is_mounted(mountpoint, MNTS_REAL))
++			    is_mounted(me->key, MNTS_REAL))
+ 				return MOUNT_OFFSET_IGNORE;
+ 
+ 			/* 
+@@ -714,13 +710,13 @@ int mount_autofs_offset(struct autofs_po
+ 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ 			debug(ap->logopt,
+ 			     "can't create mount directory: %s, %s",
+-			     mountpoint, estr);
++			     me->key, estr);
+ 			return MOUNT_OFFSET_FAIL;
+ 		} else {
+ 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ 			crit(ap->logopt,
+ 			     "failed to create mount directory: %s, %s",
+-			     mountpoint, estr);
++			     me->key, estr);
+ 			return MOUNT_OFFSET_FAIL;
+ 		}
+ 	} else {
+@@ -730,56 +726,56 @@ int mount_autofs_offset(struct autofs_po
+ 
+ 	debug(ap->logopt,
+ 	      "calling mount -t autofs " SLOPPY " -o %s automount %s",
+-	      mp->options, mountpoint);
++	      mp->options, me->key);
+ 
+ 	type = ap->entry->maps->type;
+ 	if (!type || strcmp(ap->entry->maps->type, "hosts"))
+ 		map_name = me->mc->map->argv[0];
+ 
+-	ret = mount(map_name, mountpoint, "autofs", MS_MGC_VAL, mp->options);
++	ret = mount(map_name, me->key, "autofs", MS_MGC_VAL, mp->options);
+ 	if (ret) {
+ 		crit(ap->logopt,
+ 		     "failed to mount offset trigger %s at %s",
+-		     me->key, mountpoint);
++		     me->key, me->key);
+ 		goto out_err;
+ 	}
+ 
+-	ret = stat(mountpoint, &st);
++	ret = stat(me->key, &st);
+ 	if (ret == -1) {
+ 		error(ap->logopt,
+-		     "failed to stat direct mount trigger %s", mountpoint);
++		     "failed to stat direct mount trigger %s", me->key);
+ 		goto out_umount;
+ 	}
+ 
+-	ops->open(ap->logopt, &ioctlfd, st.st_dev, mountpoint);
++	ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key);
+ 	if (ioctlfd < 0) {
+-		crit(ap->logopt, "failed to create ioctl fd for %s", mountpoint);
++		crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
+ 		goto out_umount;
+ 	}
+ 
+ 	ops->timeout(ap->logopt, ioctlfd, timeout);
+ 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
+ 	if (ap->logopt & LOGOPT_DEBUG)
+-		notify_mount_result(ap, mountpoint, timeout, str_offset);
++		notify_mount_result(ap, me->key, timeout, str_offset);
+ 	else
+ 		notify_mount_result(ap, me->key, timeout, str_offset);
+ 	ops->close(ap->logopt, ioctlfd);
+ 
+-	mnt = mnts_add_mount(ap, mountpoint, MNTS_OFFSET);
++	mnt = mnts_add_mount(ap, me->key, MNTS_OFFSET);
+ 	if (!mnt)
+ 		error(ap->logopt,
+ 		      "failed to add offset mount %s to mounted list",
+-		      mountpoint);
++		      me->key);
+ 
+-	debug(ap->logopt, "mounted trigger %s at %s", me->key, mountpoint);
++	debug(ap->logopt, "mounted trigger %s", me->key);
+ 
+ 	return MOUNT_OFFSET_OK;
+ 
+ out_umount:
+-	umount(mountpoint);
++	umount(me->key);
+ out_err:
+-	if (stat(mountpoint, &st) == 0 && me->flags & MOUNT_FLAG_DIR_CREATED)
+-		 rmdir_path(ap, mountpoint, st.st_dev);
++	if (stat(me->key, &st) == 0 && me->flags & MOUNT_FLAG_DIR_CREATED)
++		 rmdir_path(ap, me->key, st.st_dev);
+ 
+ 	return MOUNT_OFFSET_FAIL;
+ }
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -595,7 +595,7 @@ int expire_offsets_direct(struct autofs_
+ int mount_autofs_indirect(struct autofs_point *ap, const char *root);
+ int do_mount_autofs_direct(struct autofs_point *ap, struct mapent *me, time_t timeout);
+ int mount_autofs_direct(struct autofs_point *ap);
+-int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *root, const char *offset);
++int mount_autofs_offset(struct autofs_point *ap, struct mapent *me);
+ void submount_signal_parent(struct autofs_point *ap, unsigned int success);
+ void close_mount_fds(struct autofs_point *ap);
+ int umount_autofs_indirect(struct autofs_point *ap, const char *root);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2475,7 +2475,7 @@ static int do_mount_autofs_offset(struct
+ 
+ 	debug(ap->logopt, "mount offset %s at %s", oe->key, root);
+ 
+-	ret = mount_autofs_offset(ap, oe, root, offset);
++	ret = mount_autofs_offset(ap, oe);
+ 	if (ret >= MOUNT_OFFSET_OK)
+ 		mounted++;
+ 	else {
diff --git a/SOURCES/autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch b/SOURCES/autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch
new file mode 100644
index 0000000..f5bf7fe
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch
@@ -0,0 +1,54 @@
+autofs-5.1.7 - remove unused function master_submount_list_empty()
+
+From: Ian Kent <raven@themaw.net>
+
+This function is not used anywhere now, remove it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG        |    1 +
+ daemon/master.c  |   12 ------------
+ include/master.h |    1 -
+ 3 files changed, 1 insertion(+), 13 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -45,6 +45,7 @@
+ - remove redundant local var from sun_mount().
+ - use mount_fullpath() in one spot in parse_mount().
+ - pass root length to mount_fullpath().
++- remove unused function master_submount_list_empty().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/master.c
++++ autofs-5.1.4/daemon/master.c
+@@ -1119,18 +1119,6 @@ int master_read_master(struct master *ma
+ 	return 1;
+ }
+ 
+-int master_submount_list_empty(struct autofs_point *ap)
+-{
+-	int res = 0;
+-
+-	mounts_mutex_lock(ap);
+-	if (list_empty(&ap->submounts))
+-		res = 1;
+-	mounts_mutex_unlock(ap);
+-
+-	return res;
+-}
+-
+ int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
+ {
+ 	struct mnt_list *this, *sbmnt;
+--- autofs-5.1.4.orig/include/master.h
++++ autofs-5.1.4/include/master.h
+@@ -116,7 +116,6 @@ void master_free_mapent_sources(struct m
+ void master_free_mapent(struct master_mapent *);
+ struct master *master_new(const char *, unsigned int, unsigned int);
+ int master_read_master(struct master *, time_t);
+-int master_submount_list_empty(struct autofs_point *ap);
+ int master_notify_submount(struct autofs_point *, const char *path, enum states);
+ void master_notify_state_change(struct master *, int);
+ int master_mount_mounts(struct master *, time_t);
diff --git a/SOURCES/autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch b/SOURCES/autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch
new file mode 100644
index 0000000..7f71119
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch
@@ -0,0 +1,59 @@
+autofs-5.1.7 - remove unused functions cache_dump_multi() and cache_dump_cache()
+
+From: Ian Kent <raven@themaw.net>
+
+Remove debugging functions cache_dump_multi() and cache_dump_cache()
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG   |    1 +
+ lib/cache.c |   28 ----------------------------
+ 2 files changed, 1 insertion(+), 28 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -29,6 +29,7 @@
+ - rename tree implementation functions.
+ - fix program map multi-mount lookup after mount fail.
+ - add some multi-mount macros.
++- remove unused functions cache_dump_multi() and cache_dump_cache().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -24,34 +24,6 @@
+ 
+ #include "automount.h"
+ 
+-void cache_dump_multi(struct list_head *list)
+-{
+-	struct list_head *p;
+-	struct mapent *me;
+-
+-	list_for_each(p, list) {
+-		me = list_entry(p, struct mapent, multi_list);
+-		logmsg("key=%s", me->key);
+-	}
+-}
+-
+-void cache_dump_cache(struct mapent_cache *mc)
+-{
+-	struct mapent *me;
+-	unsigned int i;
+-
+-	for (i = 0; i < mc->size; i++) {
+-		me = mc->hash[i];
+-		if (me == NULL)
+-			continue;
+-		while (me) {
+-			logmsg("me->key=%s me->multi=%p dev=%ld ino=%ld",
+-				me->key, me->multi, me->dev, me->ino);
+-			me = me->next;
+-		}
+-	}
+-}
+-
+ void cache_readlock(struct mapent_cache *mc)
+ {
+ 	int status;
diff --git a/SOURCES/autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch b/SOURCES/autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch
new file mode 100644
index 0000000..077f93e
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch
@@ -0,0 +1,173 @@
+autofs-5.1.7 - remove unused mount offset list lock functions
+
+From: Ian Kent <raven@themaw.net>
+
+When fixing the locking in parse_mount() it was evident that there was
+no real benefit of having an additional lock for the offset list so its
+use was eliminated.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 
+ include/automount.h |    4 --
+ lib/cache.c         |   70 +---------------------------------------------------
+ 3 files changed, 3 insertions(+), 72 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -18,6 +18,7 @@
+ - fix return from umount_subtree_mounts() on offset list delete.
+ - pass mapent_cache to update_offset_entry().
+ - fix inconsistent locking in parse_mount().
++- remove unused mount offset list lock functions.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -162,7 +162,6 @@ struct stack {
+ struct mapent {
+ 	struct mapent *next;
+ 	struct list_head ino_index;
+-	pthread_rwlock_t multi_rwlock;
+ 	struct list_head multi_list;
+ 	struct mapent_cache *mc;
+ 	struct map_source *source;
+@@ -211,9 +210,6 @@ int cache_set_offset_parent(struct mapen
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+ int cache_delete_offset(struct mapent_cache *mc, const char *key);
+-void cache_multi_readlock(struct mapent *me);
+-void cache_multi_writelock(struct mapent *me);
+-void cache_multi_unlock(struct mapent *me);
+ int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
+ void cache_release(struct map_source *map);
+ void cache_clean_null_cache(struct mapent_cache *mc);
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -108,58 +108,6 @@ void cache_lock_cleanup(void *arg)
+ 	return;
+ }
+ 
+-void cache_multi_readlock(struct mapent *me)
+-{
+-	int status;
+-
+-	if (!me)
+-		return;
+-
+-	status = pthread_rwlock_rdlock(&me->multi_rwlock);
+-	if (status) {
+-		logmsg("mapent cache multi mutex lock failed");
+-		fatal(status);
+-	}
+-	return;
+-}
+-
+-void cache_multi_writelock(struct mapent *me)
+-{
+-	int status;
+-
+-	if (!me)
+-		return;
+-
+-	status = pthread_rwlock_wrlock(&me->multi_rwlock);
+-	if (status) {
+-		logmsg("mapent cache multi mutex lock failed");
+-		fatal(status);
+-	}
+-	return;
+-}
+-
+-void cache_multi_unlock(struct mapent *me)
+-{
+-	int status;
+-
+-	if (!me)
+-		return;
+-
+-	status = pthread_rwlock_unlock(&me->multi_rwlock);
+-	if (status) {
+-		logmsg("mapent cache multi mutex unlock failed");
+-		fatal(status);
+-	}
+-	return;
+-}
+-
+-void cache_multi_lock_cleanup(void *arg)
+-{
+-	struct mapent *me = (struct mapent *) arg;
+-	cache_multi_unlock(me);
+-	return;
+-}
+-
+ static inline void ino_index_lock(struct mapent_cache *mc)
+ {
+ 	int status = pthread_mutex_lock(&mc->ino_index_mutex);
+@@ -626,7 +574,6 @@ int cache_add(struct mapent_cache *mc, s
+ 	struct mapent *me, *existing = NULL;
+ 	char *pkey, *pent;
+ 	u_int32_t hashval = hash(key, mc->size);
+-	int status;
+ 
+ 	me = (struct mapent *) malloc(sizeof(struct mapent));
+ 	if (!me)
+@@ -665,10 +612,6 @@ int cache_add(struct mapent_cache *mc, s
+ 	me->ino = (ino_t) -1;
+ 	me->flags = 0;
+ 
+-	status = pthread_rwlock_init(&me->multi_rwlock, NULL);
+-	if (status)
+-		fatal(status);
+-
+ 	/* 
+ 	 * We need to add to the end if values exist in order to
+ 	 * preserve the order in which the map was read on lookup.
+@@ -894,7 +837,7 @@ int cache_update(struct mapent_cache *mc
+ 	return ret;
+ }
+ 
+-/* cache_multi_lock of the multi mount owner must be held by caller */
++/* cache write lock of the multi mount owner must be held by caller */
+ int cache_delete_offset(struct mapent_cache *mc, const char *key)
+ {
+ 	u_int32_t hashval = hash(key, mc->size);
+@@ -926,9 +869,6 @@ int cache_delete_offset(struct mapent_ca
+ 	return CHE_FAIL;
+ 
+ delete:
+-	status = pthread_rwlock_destroy(&me->multi_rwlock);
+-	if (status)
+-		fatal(status);
+ 	list_del(&me->multi_list);
+ 	ino_index_lock(mc);
+ 	list_del(&me->ino_index);
+@@ -946,7 +886,7 @@ int cache_delete(struct mapent_cache *mc
+ {
+ 	struct mapent *me = NULL, *pred;
+ 	u_int32_t hashval = hash(key, mc->size);
+-	int status, ret = CHE_OK;
++	int ret = CHE_OK;
+ 	char this[PATH_MAX];
+ 
+ 	strcpy(this, key);
+@@ -967,9 +907,6 @@ int cache_delete(struct mapent_cache *mc
+ 				goto done;
+ 			}
+ 			pred->next = me->next;
+-			status = pthread_rwlock_destroy(&me->multi_rwlock);
+-			if (status)
+-				fatal(status);
+ 			ino_index_lock(mc);
+ 			list_del(&me->ino_index);
+ 			ino_index_unlock(mc);
+@@ -999,9 +936,6 @@ int cache_delete(struct mapent_cache *mc
+ 			goto done;
+ 		}
+ 		mc->hash[hashval] = me->next;
+-		status = pthread_rwlock_destroy(&me->multi_rwlock);
+-		if (status)
+-			fatal(status);
+ 		ino_index_lock(mc);
+ 		list_del(&me->ino_index);
+ 		ino_index_unlock(mc);
diff --git a/SOURCES/autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch b/SOURCES/autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch
new file mode 100644
index 0000000..52483dd
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch
@@ -0,0 +1,62 @@
+autofs-5.1.7 - remove unused parameter form do_mount_autofs_offset()
+
+From: Ian Kent <raven@themaw.net>
+
+The offset parameter of do_mount_autofs_offset() isn't used.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 +
+ lib/mounts.c |   10 ++++------
+ 2 files changed, 5 insertions(+), 6 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -9,6 +9,7 @@
+ - simplify cache_get_parent().
+ - set offset parent in update_offset_entry().
+ - remove redundant variables from mount_autofs_offset().
++- remove unused parameter form do_mount_autofs_offset().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2466,9 +2466,7 @@ out:
+ }
+ 
+ static int do_mount_autofs_offset(struct autofs_point *ap,
+-				  struct mapent *oe, const char *root,
+-				  char *offset)
+-
++				  struct mapent *oe, const char *root)
+ {
+ 	int mounted = 0;
+ 	int ret;
+@@ -2523,7 +2521,7 @@ int mount_multi_triggers(struct autofs_p
+ 		if (!oe || !oe->mapent)
+ 			goto cont;
+ 
+-		mounted += do_mount_autofs_offset(ap, oe, root, offset);
++		mounted += do_mount_autofs_offset(ap, oe, root);
+ 
+ 		/*
+ 		 * If re-constructing a multi-mount it's necessary to walk
+@@ -2660,7 +2658,7 @@ int umount_multi_triggers(struct autofs_
+ 			 */
+ 			ret = rmdir_path_offset(ap, oe);
+ 			if (ret == -1 && !stat(oe->key, &st)) {
+-				ret = do_mount_autofs_offset(ap, oe, root, offset);
++				ret = do_mount_autofs_offset(ap, oe, root);
+ 				if (ret)
+ 					left++;
+ 				/* But we did origianlly create this */
+@@ -2841,7 +2839,7 @@ int clean_stale_multi_triggers(struct au
+ 			 */
+ 			ret = rmdir_path_offset(ap, oe);
+ 			if (ret == -1 && !stat(oe->key, &st)) {
+-				ret = do_mount_autofs_offset(ap, oe, root, offset);
++				ret = do_mount_autofs_offset(ap, oe, root);
+ 				if (ret) {
+ 					left++;
+ 					/* But we did origianlly create this */
diff --git a/SOURCES/autofs-5.1.7-remove-unused-variable-from-get_exports.patch b/SOURCES/autofs-5.1.7-remove-unused-variable-from-get_exports.patch
new file mode 100644
index 0000000..54c8f39
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-remove-unused-variable-from-get_exports.patch
@@ -0,0 +1,32 @@
+autofs-5.1.7 - remove unused variable from get_exports()
+
+From: Ian Kent <raven@themaw.net>
+
+Fix complier warning about unused variable entry in get_exports().
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ modules/lookup_hosts.c |    1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -49,6 +49,7 @@
+ - move amd mounts removal into lib/mounts.c.
+ - check for offset with no mount location.
+ - remove mounts_mutex.
++- remove unused variable from get_exports().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/lookup_hosts.c
++++ autofs-5.1.4/modules/lookup_hosts.c
+@@ -87,7 +87,6 @@ int lookup_read_master(struct master *ma
+ static char *get_exports(struct autofs_point *ap, const char *host)
+ {
+ 	char buf[MAX_ERR_BUF];
+-	char entry[PATH_MAX + 1];
+ 	char *mapent;
+ 	struct exportinfo *exp, *this;
+ 	size_t hostlen = strlen(host);
diff --git a/SOURCES/autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch b/SOURCES/autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch
new file mode 100644
index 0000000..8e45446
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch
@@ -0,0 +1,155 @@
+autofs-5.1.7 - rename path to m_offset in update_offset_entry()
+
+From: Ian Kent <raven@themaw.net>
+
+Rename local variable from path to m_offset in update_offset_entry() to
+make the meaning of this variable clear.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   46 +++++++++++++++++++++++-----------------------
+ 2 files changed, 24 insertions(+), 23 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -24,6 +24,7 @@
+ - don't add offset mounts to mounted mounts table.
+ - reduce umount EBUSY check delay.
+ - cleanup cache_delete() a little.
++- rename path to m_offset in update_offset_entry().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -798,36 +798,36 @@ static int
+ update_offset_entry(struct autofs_point *ap,
+ 		    struct mapent_cache *mc, const char *name,
+ 		    const char *m_root, int m_root_len,
+-		    const char *path, const char *myoptions,
++		    const char *m_offset, const char *myoptions,
+ 		    const char *loc, time_t age)
+ {
+ 	char m_key[PATH_MAX + 1];
+ 	char m_mapent[MAPENT_MAX_LEN + 1];
+-	int p_len, m_key_len, m_options_len, m_mapent_len;
++	int o_len, m_key_len, m_options_len, m_mapent_len;
+ 	int ret;
+ 
+ 	memset(m_mapent, 0, MAPENT_MAX_LEN + 1);
+ 
+ 	/* Internal hosts map may have loc == NULL */
+-	if (!*path) {
++	if (!*m_offset) {
+ 		error(ap->logopt,
+-		      MODPREFIX "syntax error in offset %s -> %s", path, loc);
++		      MODPREFIX "syntax error in offset %s -> %s", m_offset, loc);
+ 		return CHE_FAIL;
+ 	}
+ 
+-	p_len = strlen(path);
++	o_len = strlen(m_offset);
+ 	/* Trailing '/' causes us pain */
+-	if (p_len > 1) {
+-		while (p_len > 1 && path[p_len - 1] == '/')
+-			p_len--;
++	if (o_len > 1) {
++		while (o_len > 1 && m_offset[o_len - 1] == '/')
++			o_len--;
+ 	}
+-	m_key_len = m_root_len + p_len;
++	m_key_len = m_root_len + o_len;
+ 	if (m_key_len > PATH_MAX) {
+ 		error(ap->logopt, MODPREFIX "multi mount key too long");
+ 		return CHE_FAIL;
+ 	}
+ 	strcpy(m_key, m_root);
+-	strncat(m_key, path, p_len);
++	strncat(m_key, m_offset, o_len);
+ 	m_key[m_key_len] = '\0';
+ 
+ 	m_options_len = 0;
+@@ -862,15 +862,15 @@ update_offset_entry(struct autofs_point
+ 
+ 	if (ret == CHE_DUPLICATE) {
+ 		warn(ap->logopt, MODPREFIX
+-		     "syntax error or duplicate offset %s -> %s", path, loc);
++		     "syntax error or duplicate offset %s -> %s", m_offset, loc);
+ 		ret = CHE_OK;
+ 	} else if (ret == CHE_FAIL)
+ 		debug(ap->logopt, MODPREFIX
+-		      "failed to update multi-mount offset %s -> %s", path, m_mapent);
++		      "failed to update multi-mount offset %s -> %s", m_offset, m_mapent);
+ 	else {
+ 		ret = CHE_OK;
+ 		debug(ap->logopt, MODPREFIX
+-		      "updated multi-mount offset %s -> %s", path, m_mapent);
++		      "updated multi-mount offset %s -> %s", m_offset, m_mapent);
+ 	}
+ 
+ 	return ret;
+@@ -1540,22 +1540,22 @@ dont_expand:
+ 
+ 		/* It's a multi-mount; deal with it */
+ 		do {
+-			char *path, *myoptions, *loc;
++			char *m_offset, *myoptions, *loc;
+ 			int status;
+ 
+ 			if ((*p == '"' && *(p + 1) != '/') || (*p != '"' && *p != '/')) {
+ 				l = 0;
+-				path = dequote("/", 1, ap->logopt);
++				m_offset = dequote("/", 1, ap->logopt);
+ 				debug(ap->logopt,
+-				      MODPREFIX "dequote(\"/\") -> %s", path);
++				      MODPREFIX "dequote(\"/\") -> %s", m_offset);
+ 			} else {
+ 				l = span_space(p, mapent_len - (p - pmapent));
+-				path = sanitize_path(p, l, LKP_MULTI, ap->logopt);
++				m_offset = sanitize_path(p, l, LKP_MULTI, ap->logopt);
+ 				debug(ap->logopt, MODPREFIX
+-				      "dequote(\"%.*s\") -> %s", l, p, path);
++				      "dequote(\"%.*s\") -> %s", l, p, m_offset);
+ 			}
+ 
+-			if (!path) {
++			if (!m_offset) {
+ 				warn(ap->logopt, MODPREFIX "null path or out of memory");
+ 				cache_writelock(mc);
+ 				cache_delete_offset_list(mc, name);
+@@ -1577,7 +1577,7 @@ dont_expand:
+ 				cache_writelock(mc);
+ 				cache_delete_offset_list(mc, name);
+ 				cache_unlock(mc);
+-				free(path);
++				free(m_offset);
+ 				free(options);
+ 				free(pmapent);
+ 				pthread_setcancelstate(cur_state, NULL);
+@@ -1589,14 +1589,14 @@ dont_expand:
+ 
+ 			status = update_offset_entry(ap, mc,
+ 						     name, m_root, m_root_len,
+-						     path, myoptions, loc, age);
++						     m_offset, myoptions, loc, age);
+ 
+ 			if (status != CHE_OK) {
+ 				warn(ap->logopt, MODPREFIX "error adding multi-mount");
+ 				cache_writelock(mc);
+ 				cache_delete_offset_list(mc, name);
+ 				cache_unlock(mc);
+-				free(path);
++				free(m_offset);
+ 				free(options);
+ 				free(pmapent);
+ 				free(myoptions);
+@@ -1608,7 +1608,7 @@ dont_expand:
+ 
+ 			if (loc)
+ 				free(loc);
+-			free(path);
++			free(m_offset);
+ 			free(myoptions);
+ 		} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+ 
diff --git a/SOURCES/autofs-5.1.7-rename-tree-implementation-functions.patch b/SOURCES/autofs-5.1.7-rename-tree-implementation-functions.patch
new file mode 100644
index 0000000..9ad2c11
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-rename-tree-implementation-functions.patch
@@ -0,0 +1,196 @@
+autofs-5.1.7 - rename tree implementation functions
+
+From: Ian Kent <raven@themaw.net>
+
+Rename the tree struct and functions to make them consistent.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG    |    1 
+ lib/mounts.c |   86 +++++++++++++++++++++++++++++------------------------------
+ 2 files changed, 44 insertions(+), 43 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -26,6 +26,7 @@
+ - cleanup cache_delete() a little.
+ - rename path to m_offset in update_offset_entry().
+ - don't pass root to do_mount_autofs_offset().
++- rename tree implementation functions.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1225,30 +1225,30 @@ done:
+ 	return has_mounted_mounts;
+ }
+ 
+-struct node {
++struct tree_node {
+ 	struct mnt_list *mnt;
+-	struct node *left;
+-	struct node *right;
++	struct tree_node *left;
++	struct tree_node *right;
+ };
+ 
+-static struct node *new(struct mnt_list *mnt)
++static struct tree_node *tree_new(struct mnt_list *mnt)
+ {
+-	struct node *n;
++	struct tree_node *n;
+ 
+-	n = malloc(sizeof(struct node));
++	n = malloc(sizeof(struct tree_node));
+ 	if (!n)
+ 		return NULL;
+-	memset(n, 0, sizeof(struct node));
++	memset(n, 0, sizeof(struct tree_node));
+ 	n->mnt = mnt;
+ 
+ 	return n;
+ }
+ 
+-static struct node *tree_root(struct mnt_list *mnt)
++static struct tree_node *tree_root(struct mnt_list *mnt)
+ {
+-	struct node *n;
++	struct tree_node *n;
+ 
+-	n = new(mnt);
++	n = tree_new(mnt);
+ 	if (!n) {
+ 		error(LOGOPT_ANY, "failed to allcate tree root");
+ 		return NULL;
+@@ -1257,37 +1257,37 @@ static struct node *tree_root(struct mnt
+ 	return n;
+ }
+ 
+-static struct node *add_left(struct node *this, struct mnt_list *mnt)
++static struct tree_node *tree_add_left(struct tree_node *n, struct mnt_list *mnt)
+ {
+-	struct node *n;
++	struct tree_node *new;
+ 
+-	n = new(mnt);
+-	if (!n) {
++	new = tree_new(mnt);
++	if (!new) {
+ 		error(LOGOPT_ANY, "failed to allcate tree node");
+ 		return NULL;
+ 	}
+-	this->left = n;
++	n->left = new;
+ 
+ 	return n;
+ }
+ 
+-static struct node *add_right(struct node *this, struct mnt_list *mnt)
++static struct tree_node *tree_add_right(struct tree_node *n, struct mnt_list *mnt)
+ {
+-	struct node *n;
++	struct tree_node *new;
+ 
+-	n = new(mnt);
+-	if (!n) {
++	new = tree_new(mnt);
++	if (!new) {
+ 		error(LOGOPT_ANY, "failed to allcate tree node");
+ 		return NULL;
+ 	}
+-	this->right = n;
++	n->right = new;
+ 
+ 	return n;
+ }
+ 
+-static struct node *add_node(struct node *root, struct mnt_list *mnt)
++static struct tree_node *tree_add_node(struct tree_node *root, struct mnt_list *mnt)
+ {
+-	struct node *p, *q;
++	struct tree_node *p, *q;
+ 	unsigned int mp_len;
+ 
+ 	mp_len = strlen(mnt->mp);
+@@ -1307,43 +1307,43 @@ static struct node *add_node(struct node
+ 		error(LOGOPT_ANY, "duplicate entry in mounts list");
+ 	else {
+ 		if (mp_len < strlen(p->mnt->mp))
+-			return add_left(p, mnt);
++			return tree_add_left(p, mnt);
+ 		else
+-			return add_right(p, mnt);
++			return tree_add_right(p, mnt);
+ 	}
+ 
+ 	return NULL;
+ }
+ 
+-static void tree_free(struct node *tree)
++static void tree_free(struct tree_node *root)
+ {
+-	if (tree->right)
+-		tree_free(tree->right);
+-	if (tree->left)
+-		tree_free(tree->left);
+-	free(tree);
+-}
+-
+-static void traverse(struct node *node, struct list_head *mnts)
+-{
+-	if (node->right)
+-		traverse(node->right, mnts);
+-	list_add_tail(&node->mnt->expire, mnts);
+-	if (node->left)
+-		traverse(node->left, mnts);
++	if (root->right)
++		tree_free(root->right);
++	if (root->left)
++		tree_free(root->left);
++	free(root);
++}
++
++static void tree_traverse(struct tree_node *n, struct list_head *mnts)
++{
++	if (n->right)
++		tree_traverse(n->right, mnts);
++	list_add_tail(&n->mnt->expire, mnts);
++	if (n->left)
++		tree_traverse(n->left, mnts);
+ }
+ 
+ void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
+ {
+ 	struct mnt_list *mnt;
+-	struct node *tree = NULL;
++	struct tree_node *tree = NULL;
+ 
+ 	mnts_hash_mutex_lock();
+ 	if (list_empty(&ap->mounts))
+ 		goto done;
+ 
+ 	list_for_each_entry(mnt, &ap->mounts, mount) {
+-		struct node *n;
++		struct tree_node *n;
+ 
+ 		if (!(mnt->flags & MNTS_MOUNTED))
+ 			continue;
+@@ -1359,7 +1359,7 @@ void mnts_get_expire_list(struct list_he
+ 			continue;
+ 		}
+ 
+-		n = add_node(tree, mnt);
++		n = tree_add_node(tree, mnt);
+ 		if (!n) {
+ 			error(LOGOPT_ANY, "failed to add expire tree node");
+ 			tree_free(tree);
+@@ -1367,7 +1367,7 @@ void mnts_get_expire_list(struct list_he
+ 		}
+ 	}
+ 
+-	traverse(tree, mnts);
++	tree_traverse(tree, mnts);
+ 	tree_free(tree);
+ done:
+ 	mnts_hash_mutex_unlock();
diff --git a/SOURCES/autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch b/SOURCES/autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch
new file mode 100644
index 0000000..dd2f24f
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch
@@ -0,0 +1,96 @@
+autofs-5.1.7 - set offset parent in update_offset_entry()
+
+From: Ian Kent <raven@themaw.net>
+
+Avoid the list traversal in cache_set_parents() by setting the
+offset parent when updating the offset.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/automount.h |    2 +-
+ lib/cache.c         |   26 +++++++++++---------------
+ modules/parse_sun.c |    5 ++++-
+ 4 files changed, 17 insertions(+), 17 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -7,6 +7,7 @@
+ - eliminate cache_lookup_offset() usage.
+ - fix is mounted check on non existent path.
+ - simplify cache_get_parent().
++- set offset parent in update_offset_entry().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -207,7 +207,7 @@ struct mapent *cache_partial_match_wild(
+ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age);
+ void cache_update_negative(struct mapent_cache *mc, struct map_source *ms, const char *key, time_t timeout);
+-int cache_set_parents(struct mapent *mm);
++int cache_set_offset_parent(struct mapent_cache *mc, const char *offset);
+ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
+ int cache_delete(struct mapent_cache *mc, const char *key);
+ int cache_delete_offset(struct mapent_cache *mc, const char *key);
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -834,25 +834,21 @@ static struct mapent *get_offset_parent(
+ 	return NULL;
+ }
+ 
+-int cache_set_parents(struct mapent *mm)
++int cache_set_offset_parent(struct mapent_cache *mc, const char *offset)
+ {
+-	struct list_head *multi_head, *p;
+-	struct mapent *this;
++	struct mapent *this, *parent;
+ 
+-	if (!mm->multi)
++	this = cache_lookup_distinct(mc, offset);
++	if (!this)
++		return 0;
++	if (!this->multi)
+ 		return 0;
+ 
+-	multi_head = &mm->multi->multi_list;
+-
+-	list_for_each(p, multi_head) {
+-		struct mapent *parent;
+-		this = list_entry(p, struct mapent, multi_list);
+-		parent = get_offset_parent(mm->mc, this->key);
+-		if (parent)
+-			this->parent = parent;
+-		else
+-			this->parent = mm->multi;
+-	}
++	parent = get_offset_parent(mc, offset);
++	if (parent)
++		this->parent = parent;
++	else
++		this->parent = this->multi;
+ 
+ 	return 1;
+ }
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -861,6 +861,10 @@ update_offset_entry(struct autofs_point
+ 	}
+ 
+ 	ret = cache_update_offset(mc, name, m_key, m_mapent, age);
++
++	if (!cache_set_offset_parent(mc, m_key))
++		error(ap->logopt, "failed to set offset parent");
++
+ 	if (ret == CHE_DUPLICATE) {
+ 		warn(ap->logopt, MODPREFIX
+ 		     "syntax error or duplicate offset %s -> %s", path, loc);
+@@ -1615,7 +1619,6 @@ dont_expand:
+ 		 */
+ 		if (me == me->multi)
+ 			clean_stale_multi_triggers(ap, me, NULL, NULL);
+-		cache_set_parents(me);
+ 
+ 		rv = mount_subtree(ap, me, name, NULL, options, ctxt);
+ 
diff --git a/SOURCES/autofs-5.1.7-simplify-get_parent.patch b/SOURCES/autofs-5.1.7-simplify-get_parent.patch
new file mode 100644
index 0000000..f50b00e
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-simplify-get_parent.patch
@@ -0,0 +1,101 @@
+autofs-5.1.7 - simplify cache_get_parent()
+
+From: Ian Kent <raven@themaw.net>
+
+Eliminate the list traversal from get_parent() and rename it to
+get_offset_parent() to better describe it's usage.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG   |    1 +
+ lib/cache.c |   46 ++++++++++++++++++++++++++++------------------
+ 2 files changed, 29 insertions(+), 18 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -6,6 +6,7 @@
+ - fix mnts_remove_amdmount() uses wrong list.
+ - eliminate cache_lookup_offset() usage.
+ - fix is mounted check on non existent path.
++- simplify cache_get_parent().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -797,47 +797,57 @@ void cache_update_negative(struct mapent
+ }
+ 
+ 
+-static struct mapent *get_parent(const char *key, struct list_head *head, struct list_head **pos)
++static struct mapent *get_offset_parent(struct mapent_cache *mc,
++					const char *key)
+ {
+-	struct list_head *next;
+-	struct mapent *this, *last;
+-	int eq;
++	struct mapent *me;
++	char *parent, *tail;
++	int key_len;
+ 
+-	last = NULL;
+-	next = *pos ? (*pos)->next : head->next;
++	key_len = strlen(key);
+ 
+-	list_for_each(next, head) {
+-		this = list_entry(next, struct mapent, multi_list);
++	/* Check if this is the root offset */
++	if (key[key_len - 1] == '/')
++		return NULL;
+ 
+-		if (!strcmp(this->key, key))
++	parent = strdup(key);
++	tail = &parent[key_len - 1];
++
++	while (*tail) {
++		while (*tail != '/')
++			tail--;
++
++		*tail = 0;
++
++		tail--;
++		if (tail == parent)
+ 			break;
+ 
+-		eq = strncmp(this->key, key, strlen(this->key));
+-		if (eq == 0) {
+-			*pos = next;
+-			last = this;
+-			continue;
++		me = cache_lookup_distinct(mc, parent);
++		if (me) {
++			free(parent);
++			return me;
+ 		}
+ 	}
++	free(parent);
+ 
+-	return last;
++	return NULL;
+ }
+ 
+ int cache_set_parents(struct mapent *mm)
+ {
+-	struct list_head *multi_head, *p, *pos;
++	struct list_head *multi_head, *p;
+ 	struct mapent *this;
+ 
+ 	if (!mm->multi)
+ 		return 0;
+ 
+-	pos = NULL;
+ 	multi_head = &mm->multi->multi_list;
+ 
+ 	list_for_each(p, multi_head) {
+ 		struct mapent *parent;
+ 		this = list_entry(p, struct mapent, multi_list);
+-		parent = get_parent(this->key, multi_head, &pos);
++		parent = get_offset_parent(mm->mc, this->key);
+ 		if (parent)
+ 			this->parent = parent;
+ 		else
diff --git a/SOURCES/autofs-5.1.7-simplify-mount_subtree-mount-check.patch b/SOURCES/autofs-5.1.7-simplify-mount_subtree-mount-check.patch
new file mode 100644
index 0000000..a13453f
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-simplify-mount_subtree-mount-check.patch
@@ -0,0 +1,42 @@
+autofs-5.1.7 - simplify mount_subtree() mount check
+
+From: Ian Kent <raven@themaw.net>
+
+The check of the return from sun_mount() following the possible mount
+of the root offset in mount_subtree() can be simpler.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   10 +---------
+ 2 files changed, 2 insertions(+), 9 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -12,6 +12,7 @@
+ - remove unused parameter form do_mount_autofs_offset().
+ - refactor umount_multi_triggers().
+ - eliminate clean_stale_multi_triggers().
++- simplify mount_subtree() mount check.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1205,15 +1205,7 @@ static int mount_subtree(struct autofs_p
+ 				free(ro_loc);
+ 		}
+ 
+-		if (ro && rv == 0) {
+-			ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+-			if (ret == -1) {
+-				error(ap->logopt, MODPREFIX
+-					 "failed to mount offset triggers");
+-				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
+-				return 1;
+-			}
+-		} else if (rv <= 0) {
++		if ((ro && rv == 0) || rv <= 0) {
+ 			ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+ 			if (ret == -1) {
+ 				error(ap->logopt, MODPREFIX
diff --git a/SOURCES/autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch b/SOURCES/autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch
new file mode 100644
index 0000000..aaeb832
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch
@@ -0,0 +1,398 @@
+autofs-5.1.7 - switch to use tree implementation for offsets
+
+From: Ian Kent <raven@themaw.net>
+
+Change to use the tree mapent implementation for the handling
+of offset mounts.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG                |    1 
+ daemon/automount.c       |   25 ++----------
+ daemon/lookup.c          |    2 -
+ include/automount.h      |    8 ++--
+ lib/cache.c              |   67 ---------------------------------
+ lib/mounts.c             |    4 +-
+ modules/lookup_program.c |    2 -
+ modules/parse_sun.c      |   94 ++++++++++++-----------------------------------
+ 8 files changed, 39 insertions(+), 164 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -40,6 +40,7 @@
+ - add tree_mapent_cleanup_offsets().
+ - add set_offset_tree_catatonic().
+ - add mount and umount offsets functions.
++- switch to use tree implementation for offsets.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/daemon/automount.c
++++ autofs-5.1.4/daemon/automount.c
+@@ -551,29 +551,15 @@ static int umount_subtree_mounts(struct
+ 	left = 0;
+ 
+ 	if (me && IS_MM(me)) {
+-		char root[PATH_MAX + 1];
+ 		char key[PATH_MAX + 1];
+ 		struct mapent *tmp;
+-		int status;
+-		char *base;
++		int ret;
+ 
+-		if (!strchr(MM_ROOT(me)->key, '/'))
+-			/* Indirect multi-mount root */
+-			/* sprintf okay - if it's mounted, it's
+-			 * PATH_MAX or less bytes */
+-			sprintf(root, "%s/%s", ap->path, MM_ROOT(me)->key);
+-		else
+-			strcpy(root, MM_ROOT(me)->key);
+-
+-		if (IS_MM_ROOT(me))
+-			base = NULL;
+-		else
+-			base = me->key + strlen(root);
+-
+-		left = umount_multi_triggers(ap, me, root, base);
+-		if (left) {
++		ret = tree_mapent_umount_offsets(me, 1);
++		if (!ret) {
+ 			warn(ap->logopt,
+ 			     "some offset mounts still present under %s", path);
++			left++;
+ 		}
+ 
+ 		strcpy(key, me->key);
+@@ -589,8 +575,7 @@ static int umount_subtree_mounts(struct
+ 		}
+ 
+ 		if (!left && IS_MM_ROOT(me)) {
+-			status = cache_delete_offset_list(mc, me->key);
+-			if (status != CHE_OK) {
++			if (!tree_mapent_delete_offsets(mc, me->key)) {
+ 				warn(ap->logopt, "couldn't delete offset list");
+ 				left++;
+ 			}
+--- autofs-5.1.4.orig/daemon/lookup.c
++++ autofs-5.1.4/daemon/lookup.c
+@@ -851,7 +851,7 @@ static int lookup_amd_instance(struct au
+ 		return NSS_STATUS_UNKNOWN;
+ 	}
+ 
+-	m_key = malloc(ap->len + strlen(MM_ROOT(me)->key) + 2);
++	m_key = malloc(ap->len + MM_ROOT(me)->len + 2);
+ 	if (!m_key) {
+ 		error(ap->logopt,
+ 		     "failed to allocate storage for search key");
+--- autofs-5.1.4.orig/include/automount.h
++++ autofs-5.1.4/include/automount.h
+@@ -187,10 +187,10 @@ struct mapent {
+ 	ino_t ino;
+ };
+ 
+-#define IS_MM(me)	(me->multi)
+-#define IS_MM_ROOT(me)	(me->multi == me)
+-#define MM_ROOT(me)	(me->multi)
+-#define MM_PARENT(me)	(me->parent)
++#define IS_MM(me)	(me->mm_root)
++#define IS_MM_ROOT(me)	(me->mm_root == &me->node)
++#define MM_ROOT(me)	(MAPENT(me->mm_root))
++#define MM_PARENT(me)	(MAPENT(me->mm_parent))
+ 
+ void cache_lock_cleanup(void *arg);
+ void cache_readlock(struct mapent_cache *mc);
+--- autofs-5.1.4.orig/lib/cache.c
++++ autofs-5.1.4/lib/cache.c
+@@ -682,14 +682,6 @@ int cache_update_offset(struct mapent_ca
+ 		return CHE_FAIL;
+ 	}
+ 
+-	me = cache_lookup_distinct(mc, key);
+-	if (me) {
+-		cache_add_ordered_offset(me, &owner->multi_list);
+-		MM_ROOT(me) = owner;
+-		goto done;
+-	}
+-	ret = CHE_FAIL;
+-done:
+ 	return ret; 
+ }
+ 
+@@ -928,65 +920,6 @@ done:
+ 	return ret;
+ }
+ 
+-/* cache must be write locked by caller */
+-int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
+-{
+-	unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt();
+-	struct mapent *me;
+-	struct mapent *this;
+-	struct list_head *head, *next;
+-	int remain = 0;
+-	int status;
+-
+-	me = cache_lookup_distinct(mc, key);
+-	if (!me)
+-		return CHE_FAIL;
+-
+-	/* Not offset list owner */
+-	if (!IS_MM_ROOT(me))
+-		return CHE_FAIL;
+-
+-	head = &me->multi_list;
+-	next = head->next;
+-	while (next != head) {
+-		this = list_entry(next, struct mapent, multi_list);
+-		next = next->next;
+-		if (this->ioctlfd != -1) {
+-			error(logopt,
+-			      "active offset mount key %s", this->key);
+-			return CHE_FAIL;
+-		}
+-	}
+-
+-	head = &me->multi_list;
+-	next = head->next;
+-	while (next != head) {
+-		this = list_entry(next, struct mapent, multi_list);
+-		next = next->next;
+-		list_del_init(&this->multi_list);
+-		MM_ROOT(this) = NULL;
+-		debug(logopt, "deleting offset key %s", this->key);
+-		status = cache_delete(mc, this->key);
+-		if (status == CHE_FAIL) {
+-			warn(logopt,
+-			     "failed to delete offset %s", this->key);
+-			MM_ROOT(this) = me;
+-			/* TODO: add list back in */
+-			remain++;
+-		}
+-	}
+-
+-	if (!remain) {
+-		list_del_init(&me->multi_list);
+-		MM_ROOT(me) = NULL;
+-	}
+-
+-	if (remain)
+-		return CHE_FAIL;
+-
+-	return CHE_OK;
+-}
+-
+ void cache_release(struct map_source *map)
+ {
+ 	struct mapent_cache *mc;
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -2889,7 +2889,7 @@ void set_indirect_mount_tree_catatonic(s
+ 
+ 			/* Only need to set offset mounts catatonic */
+ 			if (IS_MM(me) && IS_MM_ROOT(me))
+-				set_multi_mount_tree_catatonic(ap, me);
++				set_offset_tree_catatonic(ap, me);
+ next:
+ 			me = cache_enumerate(mc, me);
+ 		}
+@@ -2909,7 +2909,7 @@ void set_direct_mount_tree_catatonic(str
+ {
+ 	/* Set offset mounts catatonic for this mapent */
+ 	if (IS_MM(me) && IS_MM_ROOT(me))
+-		set_multi_mount_tree_catatonic(ap, me);
++		set_offset_tree_catatonic(ap, me);
+ 	set_mount_catatonic(ap, me, me->ioctlfd);
+ }
+ 
+--- autofs-5.1.4.orig/modules/lookup_program.c
++++ autofs-5.1.4/modules/lookup_program.c
+@@ -676,7 +676,7 @@ int lookup_mount(struct autofs_point *ap
+ 			me = cache_lookup_distinct(mc, name);
+ 			if (me) {
+ 				if (IS_MM(me))
+-					cache_delete_offset_list(mc, name);
++					tree_mapent_delete_offsets(mc, name);
+ 				cache_delete(mc, name);
+ 			}
+ 			cache_unlock(mc);
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -856,8 +856,8 @@ update_offset_entry(struct autofs_point
+ 	cache_writelock(mc);
+ 	ret = cache_update_offset(mc, name, m_key, m_mapent, age);
+ 
+-	if (!cache_set_offset_parent(mc, m_key))
+-		error(ap->logopt, "failed to set offset parent");
++	if (!tree_mapent_add_node(mc, name, m_key))
++		error(ap->logopt, "failed to add offset %s to tree", m_key);
+ 	cache_unlock(mc);
+ 
+ 	if (ret == CHE_DUPLICATE) {
+@@ -1136,10 +1136,7 @@ static int mount_subtree(struct autofs_p
+ 			 const char *name, char *loc, char *options, void *ctxt)
+ {
+ 	struct mapent *me;
+-	struct mapent *ro;
+-	char *mm_root, *mm_base, *mm_key;
+-	unsigned int mm_root_len;
+-	int start, ret = 0, rv;
++	int ret = 0, rv;
+ 
+ 	cache_readlock(mc);
+ 	me = cache_lookup_distinct(mc, name);
+@@ -1150,34 +1147,18 @@ static int mount_subtree(struct autofs_p
+ 
+ 	rv = 0;
+ 
+-	mm_key = MM_ROOT(me)->key;
+-
+-	if (*mm_key == '/') {
+-		mm_root = mm_key;
+-		start = strlen(mm_key);
+-	} else {
+-		start = ap->len + strlen(mm_key) + 1;
+-		mm_root = alloca(start + 3);
+-		strcpy(mm_root, ap->path);
+-		strcat(mm_root, "/");
+-		strcat(mm_root, mm_key);
+-	}
+-	mm_root_len = strlen(mm_root);
+-
+ 	if (IS_MM_ROOT(me)) {
+ 		char key[PATH_MAX + 1];
++		struct mapent *ro;
++		size_t len;
+ 
+-		if (mm_root_len + 1 > PATH_MAX) {
++		len = mount_fullpath(key, PATH_MAX, ap->path, me->key);
++		if (!len) {
+ 			warn(ap->logopt, "path loo long");
+ 			return 1;
+ 		}
+-
+-		/* name = NULL */
+-		/* destination = mm_root */
+-		mm_base = "/";
+-
+-		strcpy(key, mm_root);
+-		strcat(key, mm_base);
++		key[len] = '/';
++		key[len + 1] = 0;
+ 
+ 		/* Mount root offset if it exists */
+ 		ro = cache_lookup_distinct(me->mc, key);
+@@ -1196,7 +1177,7 @@ static int mount_subtree(struct autofs_p
+ 				warn(ap->logopt,
+ 				      MODPREFIX "failed to parse root offset");
+ 				cache_writelock(mc);
+-				cache_delete_offset_list(mc, name);
++				tree_mapent_delete_offsets(mc, name);
+ 				cache_unlock(mc);
+ 				return 1;
+ 			}
+@@ -1211,10 +1192,10 @@ static int mount_subtree(struct autofs_p
+ 				free(ro_loc);
+ 		}
+ 
+-		if ((ro && rv == 0) || rv <= 0) {
+-			ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
+-			if (ret == -1) {
+-				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++		if (rv <= 0) {
++			ret = tree_mapent_mount_offsets(me, 1);
++			if (!ret) {
++				tree_mapent_cleanup_offsets(me);
+ 				cache_unlock(mc);
+ 				error(ap->logopt, MODPREFIX
+ 					 "failed to mount offset triggers");
+@@ -1225,39 +1206,14 @@ static int mount_subtree(struct autofs_p
+ 		int loclen = strlen(loc);
+ 		int namelen = strlen(name);
+ 
+-		/* name = mm_root + mm_base */
+-		/* destination = mm_root + mm_base = name */
+-		mm_base = &me->key[start];
+-
++		/* Mounts at nesting points must succeed for subtree
++		 * offsets to be mounted.
++		 */
+ 		rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
+ 		if (rv == 0) {
+-			ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
+-			if (ret == -1) {
+-				cleanup_multi_triggers(ap, me, name, start, mm_base);
+-				cache_unlock(mc);
+-				error(ap->logopt, MODPREFIX
+-					 "failed to mount offset triggers");
+-				return 1;
+-			}
+-		} else if (rv < 0) {
+-			char mm_root_base[PATH_MAX + 1];
+-			unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
+-	
+-			if (mm_root_base_len > PATH_MAX) {
+-				cache_unlock(mc);
+-				warn(ap->logopt, MODPREFIX "path too long");
+-				cache_writelock(mc);
+-				cache_delete_offset_list(mc, name);
+-				cache_unlock(mc);
+-				return 1;
+-			}
+-
+-			strcpy(mm_root_base, mm_root);
+-			strcat(mm_root_base, mm_base);
+-
+-			ret = mount_multi_triggers(ap, me->multi, mm_root_base, start, mm_base);
+-			if (ret == -1) {
+-				cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
++			ret = tree_mapent_mount_offsets(me, 1);
++			if (!ret) {
++				tree_mapent_cleanup_offsets(me);
+ 				cache_unlock(mc);
+ 				error(ap->logopt, MODPREFIX
+ 					 "failed to mount offset triggers");
+@@ -1267,7 +1223,7 @@ static int mount_subtree(struct autofs_p
+ 	}
+ 	cache_unlock(mc);
+ 
+-	/* Mount for base of tree failed */
++	/* strict mount failed */
+ 	if (rv > 0)
+ 		return rv;
+ 
+@@ -1508,7 +1464,7 @@ dont_expand:
+ 
+ 		/* So we know we're the multi-mount root */
+ 		if (!IS_MM(me))
+-			me->multi = me;
++			MAPENT_SET_ROOT(me, tree_mapent_root(me))
+ 		else {
+ 			/*
+ 			 * The amd host mount type assumes the lookup name
+@@ -1558,7 +1514,7 @@ dont_expand:
+ 			if (!m_offset) {
+ 				warn(ap->logopt, MODPREFIX "null path or out of memory");
+ 				cache_writelock(mc);
+-				cache_delete_offset_list(mc, name);
++				tree_mapent_delete_offsets(mc, name);
+ 				cache_unlock(mc);
+ 				free(options);
+ 				free(pmapent);
+@@ -1575,7 +1531,7 @@ dont_expand:
+ 			l = parse_mapent(p, options, &myoptions, &loc, ap->logopt);
+ 			if (!l) {
+ 				cache_writelock(mc);
+-				cache_delete_offset_list(mc, name);
++				tree_mapent_delete_offsets(mc, name);
+ 				cache_unlock(mc);
+ 				free(m_offset);
+ 				free(options);
+@@ -1594,7 +1550,7 @@ dont_expand:
+ 			if (status != CHE_OK) {
+ 				warn(ap->logopt, MODPREFIX "error adding multi-mount");
+ 				cache_writelock(mc);
+-				cache_delete_offset_list(mc, name);
++				tree_mapent_delete_offsets(mc, name);
+ 				cache_unlock(mc);
+ 				free(m_offset);
+ 				free(options);
diff --git a/SOURCES/autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch b/SOURCES/autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch
new file mode 100644
index 0000000..58ba41b
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch
@@ -0,0 +1,111 @@
+autofs-5.1.7 - use mapent tree root for tree_mapent_add_node()
+
+From: Ian Kent <raven@themaw.net>
+
+Since we need to create the offset tree after adding the offset entries
+to the mapent cache lookup the root mapent once and use it when calling
+tree_mapent_add_node() instread of doing a cache lookup on every node
+addition.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ include/mounts.h    |    2 +-
+ lib/mounts.c        |   24 +++++-------------------
+ modules/parse_sun.c |   11 ++++++++++-
+ 4 files changed, 17 insertions(+), 21 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -69,6 +69,7 @@
+ - fix amd section mounts map reload.
+ - fix amd hosts mount expire.
+ - fix offset entries order.
++- use mapent tree root for tree_mapent_add_node().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/include/mounts.h
++++ autofs-5.1.4/include/mounts.h
+@@ -170,7 +170,7 @@ void mnts_get_expire_list(struct list_he
+ void mnts_put_expire_list(struct list_head *mnts);
+ void mnts_set_mounted_mount(struct autofs_point *ap, const char *name, unsigned int flags);
+ struct tree_node *tree_mapent_root(struct mapent *me);
+-int tree_mapent_add_node(struct mapent_cache *mc, const char *base, const char *key);
++int tree_mapent_add_node(struct mapent_cache *mc, struct tree_node *root, const char *key);
+ int tree_mapent_delete_offsets(struct mapent_cache *mc, const char *key);
+ void tree_mapent_cleanup_offsets(struct mapent *oe);
+ int tree_mapent_mount_offsets(struct mapent *oe, int nonstrict);
+--- autofs-5.1.4.orig/lib/mounts.c
++++ autofs-5.1.4/lib/mounts.c
+@@ -1519,27 +1519,13 @@ static void tree_mapent_free(struct tree
+ }
+ 
+ int tree_mapent_add_node(struct mapent_cache *mc,
+-			 const char *root, const char *key)
++			 struct tree_node *root, const char *key)
+ {
+ 	unsigned int logopt = mc->ap->logopt;
+-	struct tree_node *tree, *n;
+-	struct mapent *base;
++	struct tree_node *n;
+ 	struct mapent *parent;
+ 	struct mapent *me;
+ 
+-	base = cache_lookup_distinct(mc, root);
+-	if (!base) {
+-		error(logopt,
+-		     "failed to find multi-mount root for key %s", key);
+-		return 0;
+-	}
+-
+-	if (MAPENT_ROOT(base) != MAPENT_NODE(base)) {
+-		error(logopt, "key %s is not multi-mount root", root);
+-		return 0;
+-	}
+-	tree = MAPENT_ROOT(base);
+-
+ 	me = cache_lookup_distinct(mc, key);
+ 	if (!me) {
+ 		error(logopt,
+@@ -1547,16 +1533,16 @@ int tree_mapent_add_node(struct mapent_c
+ 		return 0;
+ 	}
+ 
+-	n = tree_add_node(tree, me);
++	n = tree_add_node(root, me);
+ 	if (!n)
+ 		return 0;
+ 
+-	MAPENT_SET_ROOT(me, tree)
++	MAPENT_SET_ROOT(me, root)
+ 
+ 	/* Set the subtree parent */
+ 	parent = cache_get_offset_parent(mc, key);
+ 	if (!parent)
+-		MAPENT_SET_PARENT(me, tree)
++		MAPENT_SET_PARENT(me, root)
+ 	else
+ 		MAPENT_SET_PARENT(me, MAPENT_NODE(parent))
+ 
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1538,8 +1538,17 @@ dont_expand:
+ 		} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
+ 
+ 		cache_writelock(mc);
++		me = cache_lookup_distinct(mc, name);
++		if (!me) {
++			cache_unlock(mc);
++			free(options);
++			free(pmapent);
++			cleanup_offset_entries(ap, mc, &offsets);
++			pthread_setcancelstate(cur_state, NULL);
++			return 1;
++		}
+ 		list_for_each_entry_safe(oe, tmp, &offsets, work) {
+-			if (!tree_mapent_add_node(mc, name, oe->key))
++			if (!tree_mapent_add_node(mc, MAPENT_ROOT(me), oe->key))
+ 				error(ap->logopt, "failed to add offset %s to tree", oe->key);
+ 			list_del_init(&oe->work);
+ 		}
diff --git a/SOURCES/autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch b/SOURCES/autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch
new file mode 100644
index 0000000..799fe9e
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch
@@ -0,0 +1,70 @@
+autofs-5.1.7 - use mount_fullpath() in one spot in parse_mount()
+
+From: Ian Kent <raven@themaw.net>
+
+mount_fullpath() is meant to be used for this type of path construction
+so use it.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG           |    1 +
+ modules/parse_sun.c |   34 ++++++++--------------------------
+ 2 files changed, 9 insertions(+), 26 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -43,6 +43,7 @@
+ - switch to use tree implementation for offsets.
+ - remove obsolete functions.
+ - remove redundant local var from sun_mount().
++- use mount_fullpath() in one spot in parse_mount().
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/parse_sun.c
++++ autofs-5.1.4/modules/parse_sun.c
+@@ -1356,36 +1356,18 @@ dont_expand:
+ 	debug(ap->logopt, MODPREFIX "gathered options: %s", options);
+ 
+ 	if (check_is_multi(p)) {
+-		char *m_root = NULL;
++		char m_root[PATH_MAX + 1];
+ 		int m_root_len;
+ 		time_t age;
+ 		int l;
+ 
+-		/* If name starts with "/" it's a direct mount */
+-		if (*name == '/') {
+-			m_root_len = name_len;
+-			m_root = alloca(m_root_len + 1);
+-			if (!m_root) {
+-				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-				free(options);
+-				free(pmapent);
+-				logerr(MODPREFIX "alloca: %s", estr);
+-				return 1;
+-			}
+-			strcpy(m_root, name);
+-		} else {
+-			m_root_len = ap->len + name_len + 1;
+-			m_root = alloca(m_root_len + 1);
+-			if (!m_root) {
+-				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+-				free(options);
+-				free(pmapent);
+-				logerr(MODPREFIX "alloca: %s", estr);
+-				return 1;
+-			}
+-			strcpy(m_root, ap->path);
+-			strcat(m_root, "/");
+-			strcat(m_root, name);
++		m_root_len = mount_fullpath(m_root, PATH_MAX, ap->path, name);
++		if (!m_root_len) {
++			error(ap->logopt,
++			      MODPREFIX "multi-mount root path too long");
++			free(options);
++			free(pmapent);
++			return 1;
+ 		}
+ 
+ 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
diff --git a/SOURCES/autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch b/SOURCES/autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch
new file mode 100644
index 0000000..41d1c4e
--- /dev/null
+++ b/SOURCES/autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch
@@ -0,0 +1,72 @@
+autofs-5.1.7 - use snprintf() when constructing hosts mapent
+
+From: Ian Kent <raven@themaw.net>
+
+Using multiple strcpy() and strcat() functions when constructing the
+hosts map offset for each export is much slower than using a single
+sprintf() for each.
+
+Signed-off-by: Ian Kent <raven@themaw.net>
+---
+ CHANGELOG              |    1 +
+ modules/lookup_hosts.c |   26 +++++++++++++-------------
+ 2 files changed, 14 insertions(+), 13 deletions(-)
+
+--- autofs-5.1.4.orig/CHANGELOG
++++ autofs-5.1.4/CHANGELOG
+@@ -2,6 +2,7 @@
+ - add xdr_exports().
+ - remove mount.x and rpcgen dependencies.
+ - dont use realloc in host exports list processing.
++- use sprintf() when constructing hosts mapent.
+ 
+ xx/xx/2018 autofs-5.1.5
+ - fix flag file permission.
+--- autofs-5.1.4.orig/modules/lookup_hosts.c
++++ autofs-5.1.4/modules/lookup_hosts.c
+@@ -87,10 +87,12 @@ int lookup_read_master(struct master *ma
+ static char *get_exports(struct autofs_point *ap, const char *host)
+ {
+ 	char buf[MAX_ERR_BUF];
++	char entry[PATH_MAX + 1];
+ 	char *mapent;
+ 	struct exportinfo *exp, *this;
+ 	size_t hostlen = strlen(host);
+ 	size_t mapent_len;
++	int len, pos;
+ 
+ 	debug(ap->logopt, MODPREFIX "fetchng export list for %s", host);
+ 
+@@ -114,21 +116,19 @@ static char *get_exports(struct autofs_p
+ 	}
+ 	*mapent = 0;
+ 
++	pos = 0;
+ 	this = exp;
+-	while (this) {
+-		if (!*mapent)
+-			strcpy(mapent, "\"");
+-		else
+-			strcat(mapent, " \"");
+-		strcat(mapent, this->dir);
+-		strcat(mapent, "\"");
+-
+-		strcat(mapent, " \"");
+-		strcat(mapent, host);
+-		strcat(mapent, ":");
+-		strcat(mapent, this->dir);
+-		strcat(mapent, "\"");
++	if (this) {
++		len = sprintf(mapent, "\"%s\" \"%s:%s\"",
++				this->dir, host, this->dir);
++		pos += len;
++		this = this->next;
++	}
+ 
++	while (this) {
++		len = sprintf(mapent + pos, " \"%s\" \"%s:%s\"",
++				this->dir, host, this->dir);
++		pos += len;
+ 		this = this->next;
+ 	}
+ 	rpc_exports_free(exp);
diff --git a/SPECS/autofs.spec b/SPECS/autofs.spec
index db33408..a69b0c3 100644
--- a/SPECS/autofs.spec
+++ b/SPECS/autofs.spec
@@ -8,7 +8,7 @@
 Summary: A tool for automatically mounting and unmounting filesystems
 Name: autofs
 Version: 5.1.4
-Release: 48%{?dist}.1
+Release: 74%{?dist}
 Epoch: 1
 License: GPLv2+
 Group: System Environment/Daemons
@@ -134,7 +134,118 @@ Patch117: autofs-5.1.6-use-a-valid-timeout-in-lookup_prune_one_cache.patch
 Patch118: autofs-5.1.6-dont-prune-offset-map-entries.patch
 Patch119: autofs-5.1.6-simplify-sss-source-stale-check.patch
 
-Patch120: autofs-5.1.6-fix-empty-mounts-list-return-from-unlink_mount_tree.patch
+# Bug 1912106
+# Dependendant patches for expire improvement series.
+Patch120: autofs-5.1.4-use-defines-for-expire-type.patch
+Patch121: autofs-5.1.4-remove-unused-function-dump_master.patch
+Patch122: autofs-5.1.5-fix-additional-typing-errors.patch
+Patch123: autofs-5.1.6-make-bind-mounts-propagation-slave-by-default.patch
+Patch124: autofs-5.1.6-fix-browse-dir-not-re-created-on-symlink-expire.patch
+# Expire improvement series.
+Patch125: autofs-5.1.6-update-list_h.patch
+Patch126: autofs-5.1.6-add-hashtable-implementation.patch
+Patch127: autofs-5.1.6-change-mountpoint-to-mp-in-struct-ext_mount.patch
+Patch128: autofs-5.1.6-make-external-mounts-independent-of-amd_entry.patch
+Patch129: autofs-5.1.6-make-external-mounts-use-simpler-hashtable.patch
+Patch130: autofs-5.1.6-add-a-hash-index-to-mnt_list.patch
+Patch131: autofs-5.1.6-use-mnt_list-for-submounts.patch
+Patch132: autofs-5.1.6-use-mnt_list-for-amdmounts.patch
+Patch133: autofs-5.1.6-make-umount_autofs-static.patch
+Patch134: autofs-5.1.6-remove-force-parameter-from-umount_all.patch
+Patch135: autofs-5.1.6-fix-remount-expire.patch
+Patch136: autofs-5.1.6-fix-stale-offset-directories-disable-mount.patch
+Patch137: autofs-5.1.6-use-struct-mnt_list-to-track-mounted-mounts.patch
+Patch138: autofs-5.1.6-use-struct-mnt_list-mounted-list-for-expire.patch
+Patch139: autofs-5.1.6-remove-unused-function-tree_get_mnt_list.patch
+Patch140: autofs-5.1.6-only-add-expire-alarm-for-active-mounts.patch
+Patch141: autofs-5.1.6-move-submount-check-into-conditional_alarm_add.patch
+Patch142: autofs-5.1.6-move-lib_master_c-to-daemon_master_c.patch
+Patch143: autofs-5.1.6-use-master_list_empty-for-list-empty-check.patch
+Patch144: autofs-5.1.6-add-helper-to-construct-mount-point-path.patch
+# Additional fixes for bug 1912106.
+Patch145: autofs-5.1.7-add-xdr_exports.patch
+Patch146: autofs-5.1.7-remove-mount_x-and-rpcgen-dependencies.patch
+Patch147: autofs-5.1.7-dont-use-realloc-in-host-exports-list-processing.patch
+Patch148: autofs-5.1.7-use-sprintf-when-constructing-hosts-mapent.patch
+Patch149: autofs-5.1.7-fix-mnts_remove_amdmount-uses-wrong-list.patch
+Patch150: autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch
+Patch151: autofs-5.1.7-fix-is-mounted-check-on-non-existent-path.patch
+Patch152: autofs-5.1.7-simplify-get_parent.patch
+Patch153: autofs-5.1.7-set-offset-parent-in-update_offset_entry.patch
+Patch154: autofs-5.1.7-remove-redundant-variables-from-mount_autofs_offset.patch
+Patch155: autofs-5.1.7-remove-unused-parameter-form-do_mount_autofs_offset.patch
+Patch156: autofs-5.1.7-refactor-umount_multi_triggers.patch
+Patch157: autofs-5.1.7-eliminate-clean_stale_multi_triggers.patch
+Patch158: autofs-5.1.7-simplify-mount_subtree-mount-check.patch
+Patch159: autofs-5.1.7-fix-mnts_get_expire_list-expire-list-construction.patch
+Patch160: autofs-5.1.7-fix-inconsistent-locking-in-umount_subtree_mounts.patch
+Patch161: autofs-5.1.7-fix-return-from-umount_subtree_mounts-on-offset-list-delete.patch
+Patch162: autofs-5.1.7-pass-mapent_cache-to-update_offset_entry.patch
+Patch163: autofs-5.1.7-fix-inconsistent-locking-in-parse_mount.patch
+Patch164: autofs-5.1.7-remove-unused-mount-offset-list-lock-functions.patch
+Patch165: autofs-5.1.7-eliminate-count_mounts-from-expire_proc_indirect.patch
+Patch166: autofs-5.1.7-eliminate-some-strlen-calls-in-offset-handling.patch
+Patch167: autofs-5.1.7-dont-add-offset-mounts-to-mounted-mounts-table.patch
+Patch168: autofs-5.1.7-reduce-umount-EBUSY-check-delay.patch
+Patch169: autofs-5.1.7-cleanup-cache_delete-a-little.patch
+Patch170: autofs-5.1.7-rename-path-to-m_offset-in-update_offset_entry.patch
+Patch171: autofs-5.1.7-dont-pass-root-to-do_mount_autofs_offset.patch
+Patch172: autofs-5.1.7-rename-tree-implementation-functions.patch
+Patch173: autofs-5.1.6-fix-program-map-multi-mount-lookup-after-mount-fail.patch
+Patch174: autofs-5.1.7-add-some-multi-mount-macros.patch
+Patch175: autofs-5.1.7-remove-unused-functions-cache_dump_multi-and-cache_dump_cache.patch
+Patch176: autofs-5.1.7-add-a-len-field-to-struct-autofs_point.patch
+Patch177: autofs-5.1.7-make-tree-implementation-data-independent.patch
+Patch178: autofs-5.1.7-add-mapent-tree-implementation.patch
+Patch179: autofs-5.1.7-add-tree_mapent_add_node.patch
+Patch180: autofs-5.1.7-add-tree_mapent_delete_offsets.patch
+Patch181: autofs-5.1.7-add-tree_mapent_traverse_subtree.patch
+Patch182: autofs-5.1.7-fix-mount_fullpath.patch
+Patch183: autofs-5.1.7-add-tree_mapent_cleanup_offsets.patch
+Patch184: autofs-5.1.7-add-set_offset_tree_catatonic.patch
+Patch185: autofs-5.1.7-add-mount-and-umount-offsets-functions.patch
+Patch186: autofs-5.1.7-switch-to-use-tree-implementation-for-offsets.patch
+Patch187: autofs-5.1.7-remove-obsolete-functions.patch
+Patch188: autofs-5.1.7-remove-redundant-local-var-from-sun_mount.patch
+Patch189: autofs-5.1.7-use-mount_fullpath-in-one-spot-in-parse_mount.patch
+Patch190: autofs-5.1.7-pass-root-length-to-mount_fullpath.patch
+Patch191: autofs-5.1.7-remove-unused-function-master_submount_list_empty.patch
+Patch192: autofs-5.1.7-move-amd-mounts-removal-into-lib_mounts_c.patch
+Patch193: autofs-5.1.7-check-for-offset-with-no-mount-location.patch
+Patch194: autofs-5.1.7-remove-mounts_mutex.patch
+Patch195: autofs-5.1.7-remove-unused-variable-from-get_exports.patch
+# Coverity fixes resulting from bug 1912106 change.
+Patch196: autofs-5.1.7-add-missing-free-in-handle_mounts.patch
+Patch197: autofs-5.1.7-remove-redundant-if-check.patch
+Patch198: autofs-5.1.7-fix-possible-memory-leak-in-master_parse.patch
+Patch199: autofs-5.1.7-fix-possible-memory-leak-in-mnts_add_amdmount.patch
+Patch200: autofs-5.1.7-fix-double-unlock-in-parse_mount.patch
+Patch201: autofs-5.1.7-add-length-check-in-umount_subtree_mounts.patch
+Patch202: autofs-5.1.7-fix-flag-check-in-umount_multi.patch
+Patch203: autofs-5.1.7-dont-try-umount-after-stat-ENOENT-fail.patch
+Patch204: autofs-5.1.7-remove-redundant-assignment-in-master_add_amd_mount_section_mounts.patch
+Patch205: autofs-5.1.7-fix-dead-code-in-mnts_add_mount.patch
+Patch206: autofs-5.1.7-fix-arg-not-used-in-print.patch
+Patch207: autofs-5.1.7-fix-missing-lock-release-in-mount_subtree.patch
+Patch208: autofs-5.1.7-fix-double-free-in-parse_mapent.patch
+Patch209: autofs-5.1.7-refactor-lookup_prune_one_cache-a-bit.patch
+Patch210: autofs-5.1.7-cater-for-empty-mounts-list-in-mnts_get_expire_list.patch
+Patch211: autofs-5.1.7-add-ext_mount_hash_mutex-lock-helpers.patch
+
+Patch212: autofs-5.1.7-fix-amd-section-mounts-map-reload.patch
+Patch213: autofs-5.1.7-fix-amd-hosts-mount-expire.patch
+Patch214: autofs-5.1.7-fix-offset-entries-order.patch
+Patch215: autofs-5.1.7-use-mapent-tree-root-for-tree_mapent_add_node.patch
+Patch216: autofs-5.1.7-eliminate-redundant-cache-lookup-in-tree_mapent_add_node.patch
+Patch217: autofs-5.1.7-fix-hosts-map-offset-order.patch
+Patch218: autofs-5.1.7-fix-direct-mount-deadlock.patch
+
+Patch219: autofs-5.1.7-fix-lookup_prune_one_cache-refactoring-change.patch
+Patch220: autofs-5.1.7-add-missing-description-of-null-map-option.patch
+Patch221: autofs-5.1.6-fix-empty-mounts-list-return-from-unlink_mount_tree.patch
+
+Patch222: autofs-5.1.7-fix-nonstrict-offset-mount-fail-handling.patch
+Patch223: autofs-5.1.6-remove-intr-hosts-map-mount-option.patch
 
 %if %{with_systemd}
 BuildRequires: systemd-units
@@ -144,7 +255,7 @@ BuildRequires: gcc
 BuildRequires: autoconf, openldap-devel, bison, flex, libxml2-devel
 BuildRequires: cyrus-sasl-devel, openssl-devel module-init-tools util-linux
 BuildRequires: e2fsprogs libtirpc-devel libsss_autofs libnsl2-devel
-BuildRequires: rpcgen pkgconfig
+BuildRequires: pkgconfig
 Conflicts: cyrus-sasl-lib < 2.1.23-9
 Requires: bash coreutils sed gawk grep module-init-tools /bin/ps
 %if %{with_systemd}
@@ -317,6 +428,112 @@ echo %{version}-%{release} > .version
 %patch119 -p1
 
 %patch120 -p1
+%patch121 -p1
+%patch122 -p1
+%patch123 -p1
+%patch124 -p1
+%patch125 -p1
+%patch126 -p1
+%patch127 -p1
+%patch128 -p1
+%patch129 -p1
+%patch130 -p1
+%patch131 -p1
+%patch132 -p1
+%patch133 -p1
+%patch134 -p1
+%patch135 -p1
+%patch136 -p1
+%patch137 -p1
+%patch138 -p1
+%patch139 -p1
+%patch140 -p1
+%patch141 -p1
+%patch142 -p1
+%patch143 -p1
+%patch144 -p1
+%patch145 -p1
+%patch146 -p1
+%patch147 -p1
+%patch148 -p1
+%patch149 -p1
+%patch150 -p1
+%patch151 -p1
+%patch152 -p1
+%patch153 -p1
+%patch154 -p1
+%patch155 -p1
+%patch156 -p1
+%patch157 -p1
+%patch158 -p1
+%patch159 -p1
+%patch160 -p1
+%patch161 -p1
+%patch162 -p1
+%patch163 -p1
+%patch164 -p1
+%patch165 -p1
+%patch166 -p1
+%patch167 -p1
+%patch168 -p1
+%patch169 -p1
+%patch170 -p1
+%patch171 -p1
+%patch172 -p1
+%patch173 -p1
+%patch174 -p1
+%patch175 -p1
+%patch176 -p1
+%patch177 -p1
+%patch178 -p1
+%patch179 -p1
+%patch180 -p1
+%patch181 -p1
+%patch182 -p1
+%patch183 -p1
+%patch184 -p1
+%patch185 -p1
+%patch186 -p1
+%patch187 -p1
+%patch188 -p1
+%patch189 -p1
+%patch190 -p1
+%patch191 -p1
+%patch192 -p1
+%patch193 -p1
+%patch194 -p1
+%patch195 -p1
+%patch196 -p1
+%patch197 -p1
+%patch198 -p1
+%patch199 -p1
+%patch200 -p1
+%patch201 -p1
+%patch202 -p1
+%patch203 -p1
+%patch204 -p1
+%patch205 -p1
+%patch206 -p1
+%patch207 -p1
+%patch208 -p1
+%patch209 -p1
+%patch210 -p1
+%patch211 -p1
+
+%patch212 -p1
+%patch213 -p1
+%patch214 -p1
+%patch215 -p1
+%patch216 -p1
+%patch217 -p1
+%patch218 -p1
+
+%patch219 -p1
+%patch220 -p1
+%patch221 -p1
+
+%patch222 -p1
+%patch223 -p1
 
 %build
 LDFLAGS=-Wl,-z,now
@@ -412,11 +629,169 @@ fi
 %dir /etc/auto.master.d
 
 %changelog
-* Mon Jun 21 2021 Ian Kent <ikent@redhat.com> - 5.1.4-48.el8_4.1
-- bz1973888 - autofs: already mounted as other than autofs or failed to unlink
+* Tue Jun 22 2021 Ian Kent <ikent@redhat.com> - 5.1.4-74
+- bz1974309 - Removal of default intr mount option while using -hosts
+  and host.net
+  - remove intr hosts map mount option.
+  - fix previous changelog entry revision.
+- Resolves: rhbz#1974309
+
+* Fri Jun 18 2021 Ian Kent <ikent@redhat.com> - 5.1.4-73
+- bz1973025 - /net mount being not cleanly mounted and unmounted
+  - correct patch, fix nonstrict offset mount fail handling.
+- Related: rhbz#1973025
+
+* Fri Jun 18 2021 Ian Kent <ikent@redhat.com> - 5.1.4-72
+- bz1973025 - /net mount being not cleanly mounted and unmounted
+  - fix nonstrict offset mount fail handling.
+- Resolves: rhbz#1973025
+
+* Tue Jun 08 2021 Ian Kent <ikent@redhat.com> - 5.1.4-71
+- bz1969210 - autofs: already mounted as other than autofs or failed to unlink
   entry in tree
   - fix empty mounts list return from unlink_mount_tree().
-- Resolves: rhbz#1973888
+- Resolves: rhbz#1969210
+
+* Tue Jun 01 2021 Ian Kent <ikent@redhat.com> - 5.1.4-70
+- bz1965862 - A recent Coverity change can cause an infinit loop on map reload
+  - fix lookup_prune_one_cache() refactoring change.
+- bz1963129 - auto.master manpage doesn't mention -null or other built-in maps
+  - add missing desciption of null map option.
+- Resolves: rhbz#1965862 rhbz#1963129
+
+* Wed May 19 2021 Ian Kent <ikent@redhat.com> - 5.1.4-69
+- bz1961492 - autofs: regression in offset ordering
+  - fix offset entries order.
+  - use mapent tree root for tree_mapent_add_node().
+  - eliminate redundant cache lookup in tree_mapent_add_node().
+  - fix hosts map offset order.
+  - fix direct mount deadlock.
+- Resolves: rhbz#1961492
+
+* Mon May 10 2021 Ian Kent <ikent@redhat.com> - 5.1.4-68
+- bz1958487 - autofs amd mounts present in the configuration get umounted
+  on reload
+  - fix amd section mounts map reload.
+- bz1958485 - autofs amd type host mounts fail for certain host names
+  - fix amd hosts mount expire.
+- Resolves: rhbz#1958487 rhbz#1958485
+
+* Thu May 06 2021 Ian Kent <ikent@redhat.com> - 5.1.4-67
+- bz1954430 - Please, rebuild autofs-5.1.4-66.el8
+  - rebuild with fixed binutils.
+- Resolves: rhbz#1954430
+
+* Tue Mar 16 2021 Ian Kent <ikent@redhat.com> - 5.1.4-66
+- bz1912106 - Using -hosts option does not resolve host from /etc/hosts and mount
+  failes
+  - Coverity fixes
+    - add missing free in handle_mounts().
+    - remove redundant if check.
+    - fix possible memory leak in master_parse().
+    - fix possible memory leak in mnts_add_amdmount().
+    - fix double unlock in parse_mount().
+    - add length check in umount_subtree_mounts().
+    - fix flags check in umount_multi().
+    - dont try umount after stat() ENOENT fail.
+    - remove redundant assignment in master_add_amd_mount_section_mounts().
+    - fix dead code in mnts_add_mount().
+    - fix arg not used in error print.
+    - fix missing lock release in mount_subtree().
+    - fix double free in parse_mapent().
+    - refactor lookup_prune_one_cache() a bit.
+    - cater for empty mounts list in mnts_get_expire_list().
+    - add ext_mount_hash_mutex lock helpers.
+- Related: rhbz#1912106
+
+* Tue Mar 16 2021 Ian Kent <ikent@redhat.com> - 5.1.4-65
+- bz1912106 - Using -hosts option does not resolve host from /etc/hosts and mount
+  failes
+  - fix unapplied patch.
+  - remove unused variable from get_exports().
+- Related: rhbz#1912106
+
+* Tue Mar 16 2021 Ian Kent <ikent@redhat.com> - 5.1.4-64
+- bz1912106 - Using -hosts option does not resolve host from /etc/hosts and mount
+  failes
+  # Dependendant patches for expire improvement series.
+  - use defines for expire type.
+  - remove unused function dump_master().
+  - fix additional typing errors.
+  - make bind mounts propagation slave by default.
+  - fix browse dir not re-created on symlink expire.
+  # Expire improvement series.
+  - update list.h.
+  - add hashtable implementation.
+  - change mountpoint to mp in struct ext_mount.
+  - make external mounts independent of amd_entry.
+  - make external mounts use simpler hashtable.
+  - add a hash index to mnt_list.
+  - use mnt_list for submounts.
+  - use mnt_list for amdmounts.
+  - make umount_autofs() static.
+  - remove force parameter from umount_all().
+  - fix remount expire.
+  - fix stale offset directories disable mount.
+  - use struct mnt_list to track mounted mounts.
+  - use struct mnt_list mounted list for expire.
+  - remove unused function tree_get_mnt_list().
+  - only add expre alarm for active mounts.
+  - move submount check into conditional_alarm_add().
+  - move lib/master.c to daemon/master.c.
+  - use master_list_empty() for list empty check.
+  - add helper to construct mount point path.
+  # Additional fixes.
+  - add xdr_exports().
+  - remove mount.x and rpcgen dependencies.
+  - dont use realloc in host exports list processing.
+  - use sprintf() when constructing hosts mapent.
+  - fix mnts_remove_amdmount() uses wrong list.
+  - eliminate cache_lookup_offset() usage.
+  - fix is mounted check on non existent path.
+  - simplify cache_get_parent().
+  - set offset parent in update_offset_entry().
+  - remove redundant variables from mount_autofs_offset().
+  - remove unused parameter form do_mount_autofs_offset().
+  - refactor umount_multi_triggers().
+  - eliminate clean_stale_multi_triggers().
+  - simplify mount_subtree() mount check.
+  - fix mnts_get_expire_list() expire list construction.
+  - fix inconsistent locking in umount_subtree_mounts().
+  - fix return from umount_subtree_mounts() on offset list delete.
+  - pass mapent_cache to update_offset_entry().
+  - fix inconsistent locking in parse_mount().
+  - remove unused mount offset list lock functions.
+  - eliminate count_mounts() from expire_proc_indirect().
+  - eliminate some strlen calls in offset handling.
+  - don't add offset mounts to mounted mounts table.
+  - reduce umount EBUSY check delay.
+  - cleanup cache_delete() a little.
+  - rename path to m_offset in update_offset_entry().
+  - don't pass root to do_mount_autofs_offset().
+  - rename tree implementation functions.
+  - fix program map multi-mount lookup after mount fail.
+  - add some multi-mount macros.
+  - remove unused functions cache_dump_multi() and cache_dump_cache().
+  - add a len field to struct autofs_point.
+  - make tree implementation data independent.
+  - add mapent tree implementation.
+  - add tree_mapent_add_node().
+  - add tree_mapent_delete_offsets().
+  - add tree_mapent_traverse_subtree().
+  - fix mount_fullpath().
+  - add tree_mapent_cleanup_offsets().
+  - add set_offset_tree_catatonic().
+  - add mount and umount offsets functions.
+  - switch to use tree implementation for offsets.
+  - remove obsolete functions.
+  - remove redundant local var from sun_mount().
+  - use mount_fullpath() in one spot in parse_mount().
+  - pass root length to mount_fullpath().
+  - remove unused function master_submount_list_empty().
+  - move amd mounts removal into lib/mounts.c.
+  - check for offset with no mount location.
+  - remove mounts_mutex.
+- Resolves: rhbz#1912106
 
 * Fri Nov 27 2020 Ian Kent <ikent@redhat.com> - 5.1.4-48
 - bz1892184 - autofs: return a connection failure until maps have been fetched