• Ian Kent's avatar
    autofs4: fix pending mount race · a1362fe9
    Ian Kent authored
    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: default avatarJeff Moyer <jmoyer@redhat.com>
    Signed-off-by: default avatarIan Kent <raven@themaw.net>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    a1362fe9
waitq.c 11.6 KB