|
|
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;
|