aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index fb7bcf3ba5d6..525770e576db 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -343,6 +343,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
343 __releases(dentry->d_inode->i_lock) 343 __releases(dentry->d_inode->i_lock)
344{ 344{
345 struct inode *inode = dentry->d_inode; 345 struct inode *inode = dentry->d_inode;
346 __d_clear_type(dentry);
346 dentry->d_inode = NULL; 347 dentry->d_inode = NULL;
347 hlist_del_init(&dentry->d_alias); 348 hlist_del_init(&dentry->d_alias);
348 dentry_rcuwalk_barrier(dentry); 349 dentry_rcuwalk_barrier(dentry);
@@ -1648,14 +1649,42 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
1648} 1649}
1649EXPORT_SYMBOL(d_set_d_op); 1650EXPORT_SYMBOL(d_set_d_op);
1650 1651
1652static unsigned d_flags_for_inode(struct inode *inode)
1653{
1654 unsigned add_flags = DCACHE_FILE_TYPE;
1655
1656 if (!inode)
1657 return DCACHE_MISS_TYPE;
1658
1659 if (S_ISDIR(inode->i_mode)) {
1660 add_flags = DCACHE_DIRECTORY_TYPE;
1661 if (unlikely(!(inode->i_opflags & IOP_LOOKUP))) {
1662 if (unlikely(!inode->i_op->lookup))
1663 add_flags = DCACHE_AUTODIR_TYPE;
1664 else
1665 inode->i_opflags |= IOP_LOOKUP;
1666 }
1667 } else if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) {
1668 if (unlikely(inode->i_op->follow_link))
1669 add_flags = DCACHE_SYMLINK_TYPE;
1670 else
1671 inode->i_opflags |= IOP_NOFOLLOW;
1672 }
1673
1674 if (unlikely(IS_AUTOMOUNT(inode)))
1675 add_flags |= DCACHE_NEED_AUTOMOUNT;
1676 return add_flags;
1677}
1678
1651static void __d_instantiate(struct dentry *dentry, struct inode *inode) 1679static void __d_instantiate(struct dentry *dentry, struct inode *inode)
1652{ 1680{
1681 unsigned add_flags = d_flags_for_inode(inode);
1682
1653 spin_lock(&dentry->d_lock); 1683 spin_lock(&dentry->d_lock);
1654 if (inode) { 1684 dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
1655 if (unlikely(IS_AUTOMOUNT(inode))) 1685 dentry->d_flags |= add_flags;
1656 dentry->d_flags |= DCACHE_NEED_AUTOMOUNT; 1686 if (inode)
1657 hlist_add_head(&dentry->d_alias, &inode->i_dentry); 1687 hlist_add_head(&dentry->d_alias, &inode->i_dentry);
1658 }
1659 dentry->d_inode = inode; 1688 dentry->d_inode = inode;
1660 dentry_rcuwalk_barrier(dentry); 1689 dentry_rcuwalk_barrier(dentry);
1661 spin_unlock(&dentry->d_lock); 1690 spin_unlock(&dentry->d_lock);
@@ -1860,6 +1889,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
1860 static const struct qstr anonstring = QSTR_INIT("/", 1); 1889 static const struct qstr anonstring = QSTR_INIT("/", 1);
1861 struct dentry *tmp; 1890 struct dentry *tmp;
1862 struct dentry *res; 1891 struct dentry *res;
1892 unsigned add_flags;
1863 1893
1864 if (!inode) 1894 if (!inode)
1865 return ERR_PTR(-ESTALE); 1895 return ERR_PTR(-ESTALE);
@@ -1885,9 +1915,11 @@ struct dentry *d_obtain_alias(struct inode *inode)
1885 } 1915 }
1886 1916
1887 /* attach a disconnected dentry */ 1917 /* attach a disconnected dentry */
1918 add_flags = d_flags_for_inode(inode) | DCACHE_DISCONNECTED;
1919
1888 spin_lock(&tmp->d_lock); 1920 spin_lock(&tmp->d_lock);
1889 tmp->d_inode = inode; 1921 tmp->d_inode = inode;
1890 tmp->d_flags |= DCACHE_DISCONNECTED; 1922 tmp->d_flags |= add_flags;
1891 hlist_add_head(&tmp->d_alias, &inode->i_dentry); 1923 hlist_add_head(&tmp->d_alias, &inode->i_dentry);
1892 hlist_bl_lock(&tmp->d_sb->s_anon); 1924 hlist_bl_lock(&tmp->d_sb->s_anon);
1893 hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); 1925 hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);