Blame SOURCES/autofs-5.0.6-fix-recursive-mount-deadlock.patch

304803
autofs-5.0.6 - fix recursive mount deadlock
304803
304803
From: Ian Kent <raven@themaw.net>
304803
304803
Prior to the vfs-automount changes that went into 2.6.38
304803
and were finalized in 3.1 it was not possible to block
304803
path walks into multi-mounts whose root was covered by
304803
another mount. To deal with that a write lock was used
304803
to ensure the mount tree construction was completed. This
304803
restricts the types of recursively defined mount maps that
304803
can be used and can lead to a deadlock during lookup.
304803
304803
Now that we can prevent processes walking into multi-mounts
304803
that are under construction we no longer need to use a
304803
write lock.
304803
304803
Also, in the patch below, a cache writelock is changed to
304803
a read lock because a write lock isn't needed since the
304803
map cache entry isn't being updated.
304803
---
304803
304803
 CHANGELOG       |    1 +
304803
 daemon/direct.c |   14 ++++++++++++--
304803
 2 files changed, 13 insertions(+), 2 deletions(-)
304803
304803
304803
diff --git a/CHANGELOG b/CHANGELOG
304803
index 936c9ab..9cdad6e 100644
304803
--- a/CHANGELOG
304803
+++ b/CHANGELOG
304803
@@ -12,6 +12,7 @@
304803
 - configure.in: allow cross compilation.
304803
 - README: update mailing list subscription info.
304803
 - allow non root user to check status.
304803
+- fix recursive mount deadlock.
304803
 
304803
 25/07/2012 autofs-5.0.7
304803
 =======================
304803
diff --git a/daemon/direct.c b/daemon/direct.c
304803
index 7e2f0d7..3e09c5d 100644
304803
--- a/daemon/direct.c
304803
+++ b/daemon/direct.c
304803
@@ -1285,6 +1285,8 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
304803
 	struct timespec wait;
304803
 	struct timeval now;
304803
 	int ioctlfd, len, state;
304803
+	unsigned int kver_major = get_kver_major();
304803
+	unsigned int kver_minor = get_kver_minor();
304803
 
304803
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
304803
 
304803
@@ -1297,8 +1299,16 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
304803
 	 * cache entry we will not be able to find the mapent. So
304803
 	 * we must take the source writelock to ensure the parent
304803
 	 * has mount is complete before we look for the entry.
304803
+	 *
304803
+	 * Since the vfs-automount kernel changes we can now block
304803
+	 * on covered mounts during mount tree construction so a
304803
+	 * write lock is no longer needed. So we now can handle a
304803
+	 * wider class of recursively define mount lookups.
304803
 	 */
304803
-	master_source_writelock(ap->entry);
304803
+	if (kver_major > 5 || (kver_major == 5 && kver_minor > 1))
304803
+		master_source_readlock(ap->entry);
304803
+	else
304803
+		master_source_writelock(ap->entry);
304803
 	map = ap->entry->maps;
304803
 	while (map) {
304803
 		/*
304803
@@ -1311,7 +1321,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
304803
 		}
304803
 
304803
 		mc = map->mc;
304803
-		cache_writelock(mc);
304803
+		cache_readlock(mc);
304803
 		me = cache_lookup_ino(mc, pkt->dev, pkt->ino);
304803
 		if (me)
304803
 			break;