• NeilBrown's avatar
    [PATCH] Fix dcache race during umount · 0feae5c4
    NeilBrown authored
    The race is that the shrink_dcache_memory shrinker could get called while a
    filesystem is being unmounted, and could try to prune a dentry belonging to
    that filesystem.
    
    If it does, then it will call in to iput on the inode while the dentry is
    no longer able to be found by the umounting process.  If iput takes a
    while, generic_shutdown_super could get all the way though
    shrink_dcache_parent and shrink_dcache_anon and invalidate_inodes without
    ever waiting on this particular inode.
    
    Eventually the superblock gets freed anyway and if the iput tried to touch
    it (which some filesystems certainly do), it will lose.  The promised
    "Self-destruct in 5 seconds" doesn't lead to a nice day.
    
    The race is closed by holding s_umount while calling prune_one_dentry on
    someone else's dentry.  As a down_read_trylock is used,
    shrink_dcache_memory will no longer try to prune the dentry of a filesystem
    that is being unmounted, and unmount will not be able to start until any
    such active prune_one_dentry completes.
    
    This requires that prune_dcache *knows* which filesystem (if any) it is
    doing the prune on behalf of so that it can be careful of other
    filesystems.  shrink_dcache_memory isn't called it on behalf of any
    filesystem, and so is careful of everything.
    
    shrink_dcache_anon is now passed a super_block rather than the s_anon list
    out of the superblock, so it can get the s_anon list itself, and can pass
    the superblock down to prune_dcache.
    
    If prune_dcache finds a dentry that it cannot free, it leaves it where it
    is (at the tail of the list) and exits, on the assumption that some other
    thread will be removing that dentry soon.  To try to make sure that some
    work gets done, a limited number of dnetries which are untouchable are
    skipped over while choosing the dentry to work on.
    
    I believe this race was first found by Kirill Korotaev.
    
    Cc: Jan Blunck <jblunck@suse.de>
    Acked-by: default avatarKirill Korotaev <dev@openvz.org>
    Cc: Olaf Hering <olh@suse.de>
    Acked-by: default avatarBalbir Singh <balbir@in.ibm.com>
    Signed-off-by: default avatarNeil Brown <neilb@suse.de>
    Signed-off-by: default avatarBalbir Singh <balbir@in.ibm.com>
    Acked-by: default avatarDavid Howells <dhowells@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    0feae5c4
dcache.c 46.4 KB