}
/* 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;
}
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);
* if the dentry tree reaches them; however if the dentry already
* exists, we'll pick it up at this point and use it as the root
*/
- mntroot = d_alloc_anon(inode);
- if (!mntroot) {
- iput(inode);
+ mntroot = d_obtain_alias(inode);
+ if (IS_ERR(mntroot)) {
dprintk("nfs_get_root: get root dentry failed\n");
- return ERR_PTR(-ENOMEM);
+ return mntroot;
}
security_d_instantiate(mntroot, inode);
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);
* if the dentry tree reaches them; however if the dentry already
* exists, we'll pick it up at this point and use it as the root
*/
- mntroot = d_alloc_anon(inode);
- if (!mntroot) {
- iput(inode);
+ mntroot = d_obtain_alias(inode);
+ if (IS_ERR(mntroot)) {
dprintk("nfs_get_root: get root dentry failed\n");
- return ERR_PTR(-ENOMEM);
+ return mntroot;
}
security_d_instantiate(mntroot, inode);