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

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