Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

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

+23 -10
+8 -1
fs/dcache.c
··· 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))
+1 -1
fs/hostfs/hostfs_kern.c
··· 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
+3 -1
fs/inode.c
··· 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;
+3 -1
fs/namei.c
··· 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(;;) {
+6 -3
fs/namespace.c
··· 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 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))) { ··· 1163 1162 */ 1164 1163 smp_mb(); 1165 1164 mnt_add_count(mnt, -1); 1166 - if (mnt_get_count(mnt)) { 1165 + count = mnt_get_count(mnt); 1166 + if (count != 0) { 1167 + WARN_ON(count < 0); 1167 1168 rcu_read_unlock(); 1168 1169 unlock_mount_hash(); 1169 1170 return;
+1 -1
fs/pnode.h
··· 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,
+1 -2
include/linux/fs.h
··· 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