diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-12-12 11:12:15 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-12-12 11:12:15 -0500 |
commit | a10db50a4ae813fcb2f431f2fb039933c109a925 (patch) | |
tree | 0c07781c5de3b7445add25db6d3471d71cf5cb86 /fs/nfs/getroot.c | |
parent | a5576cfa5cd8d8aa874bd4ee500dc8a2e7cbad18 (diff) | |
download | op-kernel-dev-a10db50a4ae813fcb2f431f2fb039933c109a925.zip op-kernel-dev-a10db50a4ae813fcb2f431f2fb039933c109a925.tar.gz |
NFS: Fix an Oops in NFS unmount
Ensure that the dummy 'root dentry' is invisible to d_find_alias(). If not,
then it may be spliced into the tree if a parent directory from the same
filesystem gets mounted at a later time.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/getroot.c')
-rw-r--r-- | fs/nfs/getroot.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 0ee4384..e6242cd 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -57,6 +57,17 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i } /* Circumvent igrab(): we know the inode is not being freed */ atomic_inc(&inode->i_count); + /* + * Ensure that this dentry is invisible to d_find_alias(). + * Otherwise, it may be spliced into the tree by + * d_materialise_unique if a parent directory from the same + * filesystem gets mounted at a later time. + * This again causes shrink_dcache_for_umount_subtree() to + * Oops, since the test for IS_ROOT() will fail. + */ + spin_lock(&dcache_lock); + list_del_init(&sb->s_root->d_alias); + spin_unlock(&dcache_lock); } return 0; } |