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 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fixes from Al Viro:

- backport-friendly part of lock_parent() race fix

- a fix for an assumption in the heurisic used by path_connected() that
is not true on NFS

- livelock fixes for d_alloc_parallel()

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
fs: Teach path_connected to handle nfs filesystems with multiple roots.
fs: dcache: Use READ_ONCE when accessing i_dir_seq
fs: dcache: Avoid livelock between d_alloc_parallel and __d_add
lock_parent() needs to recheck if dentry got __dentry_kill'ed under it

+22 -7
+16 -5
fs/dcache.c
··· 647 647 spin_unlock(&parent->d_lock); 648 648 goto again; 649 649 } 650 - rcu_read_unlock(); 651 - if (parent != dentry) 650 + if (parent != dentry) { 652 651 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); 653 - else 652 + if (unlikely(dentry->d_lockref.count < 0)) { 653 + spin_unlock(&parent->d_lock); 654 + parent = NULL; 655 + } 656 + } else { 654 657 parent = NULL; 658 + } 659 + rcu_read_unlock(); 655 660 return parent; 656 661 } 657 662 ··· 2479 2474 2480 2475 retry: 2481 2476 rcu_read_lock(); 2482 - seq = smp_load_acquire(&parent->d_inode->i_dir_seq) & ~1; 2477 + seq = smp_load_acquire(&parent->d_inode->i_dir_seq); 2483 2478 r_seq = read_seqbegin(&rename_lock); 2484 2479 dentry = __d_lookup_rcu(parent, name, &d_seq); 2485 2480 if (unlikely(dentry)) { ··· 2500 2495 rcu_read_unlock(); 2501 2496 goto retry; 2502 2497 } 2498 + 2499 + if (unlikely(seq & 1)) { 2500 + rcu_read_unlock(); 2501 + goto retry; 2502 + } 2503 + 2503 2504 hlist_bl_lock(b); 2504 - if (unlikely(parent->d_inode->i_dir_seq != seq)) { 2505 + if (unlikely(READ_ONCE(parent->d_inode->i_dir_seq) != seq)) { 2505 2506 hlist_bl_unlock(b); 2506 2507 rcu_read_unlock(); 2507 2508 goto retry;
+3 -2
fs/namei.c
··· 559 559 static bool path_connected(const struct path *path) 560 560 { 561 561 struct vfsmount *mnt = path->mnt; 562 + struct super_block *sb = mnt->mnt_sb; 562 563 563 - /* Only bind mounts can have disconnected paths */ 564 - if (mnt->mnt_root == mnt->mnt_sb->s_root) 564 + /* Bind mounts and multi-root filesystems can have disconnected paths */ 565 + if (!(sb->s_iflags & SB_I_MULTIROOT) && (mnt->mnt_root == sb->s_root)) 565 566 return true; 566 567 567 568 return is_subdir(path->dentry, mnt->mnt_root);
+2
fs/nfs/super.c
··· 2631 2631 /* initial superblock/root creation */ 2632 2632 mount_info->fill_super(s, mount_info); 2633 2633 nfs_get_cache_cookie(s, mount_info->parsed, mount_info->cloned); 2634 + if (!(server->flags & NFS_MOUNT_UNSHARED)) 2635 + s->s_iflags |= SB_I_MULTIROOT; 2634 2636 } 2635 2637 2636 2638 mntroot = nfs_get_root(s, mount_info->mntfh, dev_name);
+1
include/linux/fs.h
··· 1317 1317 #define SB_I_CGROUPWB 0x00000001 /* cgroup-aware writeback enabled */ 1318 1318 #define SB_I_NOEXEC 0x00000002 /* Ignore executables on this fs */ 1319 1319 #define SB_I_NODEV 0x00000004 /* Ignore devices on this fs */ 1320 + #define SB_I_MULTIROOT 0x00000008 /* Multiple roots to the dentry tree */ 1320 1321 1321 1322 /* sb->s_iflags to limit user namespace mounts */ 1322 1323 #define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */