diff options
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 42 |
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 | } |
1649 | EXPORT_SYMBOL(d_set_d_op); | 1650 | EXPORT_SYMBOL(d_set_d_op); |
1650 | 1651 | ||
1652 | static 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 | |||
1651 | static void __d_instantiate(struct dentry *dentry, struct inode *inode) | 1679 | static 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); |