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