-
Alexander Viro authored
Ugh. nfs_unlink() is actually racy as hell - look what happens if we enter it with ->d_count == 1, see that nfs_sillyrename() doesn't need to do anything and call nfs_safe_remove(). In the meanwhile somebody does dcache lookup (without going into NFS code - plain and simple cache hit) and increments ->d_count. nfs_safe_remove() decides that something is very rotten and fails. AFAICS we should take the test for ->d_count + d_drop if it's 1 under dcache_lock (and in one place). Comments? Proposed fix follows: * dget/dput killed in vfs_unlink() (safely) * nfs_unlink() starts with check for ->d_count (under dcache_lock) * if it's > 1 - sillyrename * if it is 1 - immediately unhash, then drop dcache_lock. after that we do as in old variant, except that rehashing is done in nfs_unlink() and only if there was an error - if there was none we simply leave d_delete() to vfs_unlink().
17191a2c