Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull vfs fixes from Al Viro:
"A bunch of race fixes, mostly around lazy pathwalk.

All of it is -stable fodder, a large part going back to 2013"

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
make sure that __dentry_kill() always invalidates d_seq, unhashed or not
fix __legitimize_mnt()/mntput() race
fix mntput/mntput race
root dentries need RCU-delayed freeing

+32 -9
+6 -7
fs/dcache.c
··· 358 358 __releases(dentry->d_inode->i_lock) 359 359 { 360 360 struct inode *inode = dentry->d_inode; 361 - bool hashed = !d_unhashed(dentry); 362 361 363 - if (hashed) 364 - raw_write_seqcount_begin(&dentry->d_seq); 362 + raw_write_seqcount_begin(&dentry->d_seq); 365 363 __d_clear_type_and_inode(dentry); 366 364 hlist_del_init(&dentry->d_u.d_alias); 367 - if (hashed) 368 - raw_write_seqcount_end(&dentry->d_seq); 365 + raw_write_seqcount_end(&dentry->d_seq); 369 366 spin_unlock(&dentry->d_lock); 370 367 spin_unlock(&inode->i_lock); 371 368 if (!inode->i_nlink) ··· 1929 1932 1930 1933 if (root_inode) { 1931 1934 res = d_alloc_anon(root_inode->i_sb); 1932 - if (res) 1935 + if (res) { 1936 + res->d_flags |= DCACHE_RCUACCESS; 1933 1937 d_instantiate(res, root_inode); 1934 - else 1938 + } else { 1935 1939 iput(root_inode); 1940 + } 1936 1941 } 1937 1942 return res; 1938 1943 }
+26 -2
fs/namespace.c
··· 659 659 return 0; 660 660 mnt = real_mount(bastard); 661 661 mnt_add_count(mnt, 1); 662 + smp_mb(); // see mntput_no_expire() 662 663 if (likely(!read_seqretry(&mount_lock, seq))) 663 664 return 0; 664 665 if (bastard->mnt_flags & MNT_SYNC_UMOUNT) { 665 666 mnt_add_count(mnt, -1); 666 667 return 1; 667 668 } 669 + lock_mount_hash(); 670 + if (unlikely(bastard->mnt_flags & MNT_DOOMED)) { 671 + mnt_add_count(mnt, -1); 672 + unlock_mount_hash(); 673 + return 1; 674 + } 675 + unlock_mount_hash(); 676 + /* caller will mntput() */ 668 677 return -1; 669 678 } 670 679 ··· 1204 1195 static void mntput_no_expire(struct mount *mnt) 1205 1196 { 1206 1197 rcu_read_lock(); 1207 - mnt_add_count(mnt, -1); 1208 - if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */ 1198 + if (likely(READ_ONCE(mnt->mnt_ns))) { 1199 + /* 1200 + * Since we don't do lock_mount_hash() here, 1201 + * ->mnt_ns can change under us. However, if it's 1202 + * non-NULL, then there's a reference that won't 1203 + * be dropped until after an RCU delay done after 1204 + * turning ->mnt_ns NULL. So if we observe it 1205 + * non-NULL under rcu_read_lock(), the reference 1206 + * we are dropping is not the final one. 1207 + */ 1208 + mnt_add_count(mnt, -1); 1209 1209 rcu_read_unlock(); 1210 1210 return; 1211 1211 } 1212 1212 lock_mount_hash(); 1213 + /* 1214 + * make sure that if __legitimize_mnt() has not seen us grab 1215 + * mount_lock, we'll see their refcount increment here. 1216 + */ 1217 + smp_mb(); 1218 + mnt_add_count(mnt, -1); 1213 1219 if (mnt_get_count(mnt)) { 1214 1220 rcu_read_unlock(); 1215 1221 unlock_mount_hash();