autofs4: fix pending mount race
Close a race between a pending mount that is about to finish and a new lookup for the same directory. Process P1 triggers a mount of directory foo. It sets DCACHE_AUTOFS_PENDING in the ->lookup routine, creates a waitq entry for 'foo', and calls out to the daemon to perform the mount. The autofs daemon will then create the directory 'foo', using a new dentry that will be hashed in the dcache. Before the mount completes, another process, P2, tries to walk into the 'foo' directory. The vfs path walking code finds an entry for 'foo' and calls the revalidate method. Revalidate finds that the entry is not PENDING (because PENDING was never set on the dentry created by the mkdir), but it does find the directory is empty. Revalidate calls try_to_fill_dentry, which sets the PENDING flag and then calls into the autofs4 wait code to trigger or wait for a mount of 'foo'. The wait code finds the entry for 'foo' and goes to sleep waiting for the completion of the mount. Yet another process, P3, tries to walk into the 'foo' directory. This process again finds a dentry in the dcache for 'foo', and calls into the autofs revalidate code. The revalidate code finds that the PENDING flag is set, and so calls try_to_fill_dentry. a) try_to_fill_dentry sets the PENDING flag redundantly for this dentry, then calls into the autofs4 wait code. b) the autofs4 wait code takes the waitq mutex and searches for an entry for 'foo' Between a and b, P1 is woken up because the mount completed. P1 takes the wait queue mutex, clears the PENDING flag from the dentry, and removes the waitqueue entry for 'foo' from the list. When it releases the waitq mutex, P3 (eventually) acquires it. At this time, it looks for an existing waitq for 'foo', finds none, and so creates a new one and calls out to the daemon to mount the 'foo' directory. Now, the reason that three processes are required to trigger this race is that, because the PENDING flag is not set on the dentry created by mkdir, the window for the race would be way to slim for it to ever occur. Basically, between the testing of d_mountpoint(dentry) and the taking of the waitq mutex, the mount would have to complete and the daemon would have to be woken up, and that in turn would have to wake up P1. This is simply impossible. Add the third process, though, and it becomes slightly more likely. Signed-off-by: Jeff Moyer <jmoyer@redhat.com> Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
parent
5a11d4d0
Please register or sign in to comment