Pull misc vfs updates from Al Viro: "Assorted patches from previous cycle(s)..." * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: fix hostfs_open() use of ->f_path.dentry Make sure that make_create_in_sticky() never sees uninitialized value of dir_mode fs: Kill DCACHE_DONTCACHE dentry even if DCACHE_REFERENCED is set fs: Handle I_DONTCACHE in iput_final() instead of generic_drop_inode() fs/namespace.c: WARN if mnt_count has become negative
Unified · Split
| @@ -793,10 +793,17 @@ static inline bool fast_dput(struct dentry *dentry) · 792 unmodified lines | ||
| 793 | 793 | * a reference to the dentry and change that, but |
| 794 | 794 | * our work is done - we can leave the dentry |
| 795 | 795 | * around with a zero refcount. |
| 796 | + * | |
| 797 | + * Nevertheless, there are two cases that we should kill | |
| 798 | + * the dentry anyway. | |
| 799 | + * 1. free disconnected dentries as soon as their refcount | |
| 800 | + * reached zero. | |
| 801 | + * 2. free dentries if they should not be cached. | |
| 796 | 802 | */ |
| 797 | 803 | smp_rmb(); |
| 798 | 804 | d_flags = READ_ONCE(dentry->d_flags); |
| 799 | − d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED; | |
| 805 | + d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | | |
| 806 | + DCACHE_DISCONNECTED | DCACHE_DONTCACHE; | |
| 800 | 807 | |
| 801 | 808 | /* Nothing to do? Dropping the reference was all we needed? */ |
| 802 | 809 | if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) |
| @@ -315,7 +315,7 @@ retry: · 314 unmodified lines | ||
| 315 | 315 | if (mode & FMODE_WRITE) |
| 316 | 316 | r = w = 1; |
| 317 | 317 | |
| 318 | − name = dentry_name(file->f_path.dentry); | |
| 318 | + name = dentry_name(d_real(file->f_path.dentry, file->f_inode)); | |
| 319 | 319 | if (name == NULL) |
| 320 | 320 | return -ENOMEM; |
| 321 | 321 | |
| @@ -1624,7 +1624,9 @@ static void iput_final(struct inode *inode) · 1623 unmodified lines | ||
| 1624 | 1624 | else |
| 1625 | 1625 | drop = generic_drop_inode(inode); |
| 1626 | 1626 | |
| 1627 | − if (!drop && (sb->s_flags & SB_ACTIVE)) { | |
| 1627 | + if (!drop && | |
| 1628 | + !(inode->i_state & I_DONTCACHE) && | |
| 1629 | + (sb->s_flags & SB_ACTIVE)) { | |
| 1628 | 1630 | inode_add_lru(inode); |
| 1629 | 1631 | spin_unlock(&inode->i_lock); |
| 1630 | 1632 | return; |
| @@ -2114,8 +2114,10 @@ static int link_path_walk(const char *name, struct nameidata *nd) · 2113 unmodified lines | ||
| 2114 | 2114 | return PTR_ERR(name); |
| 2115 | 2115 | while (*name=='/') |
| 2116 | 2116 | name++; |
| 2117 | − if (!*name) | |
| 2117 | + if (!*name) { | |
| 2118 | + nd->dir_mode = 0; // short-circuit the 'hardening' idiocy | |
| 2118 | 2119 | return 0; |
| 2120 | + } | |
| 2119 | 2121 | |
| 2120 | 2122 | /* At this point we know we have a real path component. */ |
| 2121 | 2123 | for(;;) { |
| @@ -156,10 +156,10 @@ static inline void mnt_add_count(struct mount *mnt, int n) · 155 unmodified lines | ||
| 156 | 156 | /* |
| 157 | 157 | * vfsmount lock must be held for write |
| 158 | 158 | */ |
| 159 | −unsigned int mnt_get_count(struct mount *mnt) | |
| 159 | +int mnt_get_count(struct mount *mnt) | |
| 160 | 160 | { |
| 161 | 161 | #ifdef CONFIG_SMP |
| 162 | − unsigned int count = 0; | |
| 162 | + int count = 0; | |
| 163 | 163 | int cpu; |
| 164 | 164 | |
| 165 | 165 | for_each_possible_cpu(cpu) { |
| @@ -1139,6 +1139,7 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput); · 973 unmodified lines | ||
| 1139 | 1139 | static void mntput_no_expire(struct mount *mnt) |
| 1140 | 1140 | { |
| 1141 | 1141 | LIST_HEAD(list); |
| 1142 | + int count; | |
| 1142 | 1143 | |
| 1143 | 1144 | rcu_read_lock(); |
| 1144 | 1145 | if (likely(READ_ONCE(mnt->mnt_ns))) { |
| @@ -1162,7 +1163,9 @@ static void mntput_no_expire(struct mount *mnt) · 17 unmodified lines | ||
| 1162 | 1163 | */ |
| 1163 | 1164 | smp_mb(); |
| 1164 | 1165 | mnt_add_count(mnt, -1); |
| 1165 | − if (mnt_get_count(mnt)) { | |
| 1166 | + count = mnt_get_count(mnt); | |
| 1167 | + if (count != 0) { | |
| 1168 | + WARN_ON(count < 0); | |
| 1166 | 1169 | rcu_read_unlock(); |
| 1167 | 1170 | unlock_mount_hash(); |
| 1168 | 1171 | return; |
| @@ -44,7 +44,7 @@ int propagate_mount_busy(struct mount *, int); · 43 unmodified lines | ||
| 44 | 44 | void propagate_mount_unlock(struct mount *); |
| 45 | 45 | void mnt_release_group_id(struct mount *); |
| 46 | 46 | int get_dominating_id(struct mount *mnt, const struct path *root); |
| 47 | −unsigned int mnt_get_count(struct mount *mnt); | |
| 47 | +int mnt_get_count(struct mount *mnt); | |
| 48 | 48 | void mnt_set_mountpoint(struct mount *, struct mountpoint *, |
| 49 | 49 | struct mount *); |
| 50 | 50 | void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, |
| @@ -2876,8 +2876,7 @@ extern int inode_needs_sync(struct inode *inode); · 2875 unmodified lines | ||
| 2876 | 2876 | extern int generic_delete_inode(struct inode *inode); |
| 2877 | 2877 | static inline int generic_drop_inode(struct inode *inode) |
| 2878 | 2878 | { |
| 2879 | − return !inode->i_nlink || inode_unhashed(inode) || | |
| 2880 | − (inode->i_state & I_DONTCACHE); | |
| 2879 | + return !inode->i_nlink || inode_unhashed(inode); | |
| 2881 | 2880 | } |
| 2882 | 2881 | extern void d_mark_dontcache(struct inode *inode); |
| 2883 | 2882 | |