Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Revert "vfs: stop d_splice_alias creating directory aliases"

This reverts commit 7732a557b1342c6e6966efb5f07effcf99f56167 (and commit
3f50fff4dace23d3cfeb195d5cd4ee813cee68b7, which was a follow-up
cleanup).

We're chasing an elusive bug that Dave Jones can apparently reproduce
using his system call fuzzer tool, and that looks like some kind of
locking ordering problem on the directory i_mutex chain. Our i_mutex
locking is rather complex, and depends on the topological ordering of
the directories, which is why we have been very wary of splicing
directory entries around.

Of course, we really don't want to ever see aliased unconnected
directories anyway, so none of this should ever happen, but this revert
aims to basically get us back to a known older state.

Bruce points to some of the previous discussion at

http://marc.info/?i=<20110310105821.GE22723@ZenIV.linux.org.uk>

and in particular a long post from Neil:

http://marc.info/?i=<20110311150749.2fa2be66@notabene.brown>

It should be noted that it's possible that Dave's problems come from
other changes altohgether, including possibly just the fact that Dave
constantly is teachning his fuzzer new tricks. So what appears to be a
new bug could in fact be an old one that just gets newly triggered, but
reverting these patches as "still under heavy discussion" is the right
thing regardless.

Requested-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: J. Bruce Fields <bfields@fieldses.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+10 -6
+10 -6
fs/dcache.c
··· 683 683 /** 684 684 * d_find_alias - grab a hashed alias of inode 685 685 * @inode: inode in question 686 + * @want_discon: flag, used by d_splice_alias, to request 687 + * that only a DISCONNECTED alias be returned. 686 688 * 687 689 * If inode has a hashed alias, or is a directory and has any alias, 688 690 * acquire the reference to alias and return it. Otherwise return NULL. ··· 693 691 * of a filesystem. 694 692 * 695 693 * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer 696 - * any other hashed alias over that. 694 + * any other hashed alias over that one unless @want_discon is set, 695 + * in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias. 697 696 */ 698 - static struct dentry *__d_find_alias(struct inode *inode) 697 + static struct dentry *__d_find_alias(struct inode *inode, int want_discon) 699 698 { 700 699 struct dentry *alias, *discon_alias; 701 700 ··· 708 705 if (IS_ROOT(alias) && 709 706 (alias->d_flags & DCACHE_DISCONNECTED)) { 710 707 discon_alias = alias; 711 - } else { 708 + } else if (!want_discon) { 712 709 __dget_dlock(alias); 713 710 spin_unlock(&alias->d_lock); 714 711 return alias; ··· 739 736 740 737 if (!list_empty(&inode->i_dentry)) { 741 738 spin_lock(&inode->i_lock); 742 - de = __d_find_alias(inode); 739 + de = __d_find_alias(inode, 0); 743 740 spin_unlock(&inode->i_lock); 744 741 } 745 742 return de; ··· 1650 1647 1651 1648 if (inode && S_ISDIR(inode->i_mode)) { 1652 1649 spin_lock(&inode->i_lock); 1653 - new = __d_find_any_alias(inode); 1650 + new = __d_find_alias(inode, 1); 1654 1651 if (new) { 1652 + BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED)); 1655 1653 spin_unlock(&inode->i_lock); 1656 1654 security_d_instantiate(new, inode); 1657 1655 d_move(new, dentry); ··· 2482 2478 struct dentry *alias; 2483 2479 2484 2480 /* Does an aliased dentry already exist? */ 2485 - alias = __d_find_alias(inode); 2481 + alias = __d_find_alias(inode, 0); 2486 2482 if (alias) { 2487 2483 actual = alias; 2488 2484 write_seqlock(&rename_lock);