Merge branch 'devel' into next
[pandora-kernel.git] / fs / nfs / getroot.c
index 0ee4384..fae9719 100644 (file)
@@ -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;
 }
@@ -85,7 +96,7 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
        inode = nfs_fhget(sb, mntfh, fsinfo.fattr);
        if (IS_ERR(inode)) {
                dprintk("nfs_get_root: get root inode failed\n");
-               return ERR_PTR(PTR_ERR(inode));
+               return ERR_CAST(inode);
        }
 
        error = nfs_superblock_set_dummy_root(sb, inode);
@@ -255,7 +266,7 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
        inode = nfs_fhget(sb, mntfh, &fattr);
        if (IS_ERR(inode)) {
                dprintk("nfs_get_root: get root inode failed\n");
-               return ERR_PTR(PTR_ERR(inode));
+               return ERR_CAST(inode);
        }
 
        error = nfs_superblock_set_dummy_root(sb, inode);