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
This commit is contained in:
commit
df09348f78
21
fs/dcache.c
21
fs/dcache.c
@ -647,11 +647,16 @@ again:
|
|||||||
spin_unlock(&parent->d_lock);
|
spin_unlock(&parent->d_lock);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
if (parent != dentry) {
|
||||||
if (parent != dentry)
|
|
||||||
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
|
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
|
||||||
else
|
if (unlikely(dentry->d_lockref.count < 0)) {
|
||||||
|
spin_unlock(&parent->d_lock);
|
||||||
|
parent = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
parent = NULL;
|
parent = NULL;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2474,7 +2479,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
|
|||||||
|
|
||||||
retry:
|
retry:
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
seq = smp_load_acquire(&parent->d_inode->i_dir_seq) & ~1;
|
seq = smp_load_acquire(&parent->d_inode->i_dir_seq);
|
||||||
r_seq = read_seqbegin(&rename_lock);
|
r_seq = read_seqbegin(&rename_lock);
|
||||||
dentry = __d_lookup_rcu(parent, name, &d_seq);
|
dentry = __d_lookup_rcu(parent, name, &d_seq);
|
||||||
if (unlikely(dentry)) {
|
if (unlikely(dentry)) {
|
||||||
@ -2495,8 +2500,14 @@ retry:
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(seq & 1)) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
hlist_bl_lock(b);
|
hlist_bl_lock(b);
|
||||||
if (unlikely(parent->d_inode->i_dir_seq != seq)) {
|
if (unlikely(READ_ONCE(parent->d_inode->i_dir_seq) != seq)) {
|
||||||
hlist_bl_unlock(b);
|
hlist_bl_unlock(b);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
goto retry;
|
goto retry;
|
||||||
|
@ -559,9 +559,10 @@ static int __nd_alloc_stack(struct nameidata *nd)
|
|||||||
static bool path_connected(const struct path *path)
|
static bool path_connected(const struct path *path)
|
||||||
{
|
{
|
||||||
struct vfsmount *mnt = path->mnt;
|
struct vfsmount *mnt = path->mnt;
|
||||||
|
struct super_block *sb = mnt->mnt_sb;
|
||||||
|
|
||||||
/* Only bind mounts can have disconnected paths */
|
/* Bind mounts and multi-root filesystems can have disconnected paths */
|
||||||
if (mnt->mnt_root == mnt->mnt_sb->s_root)
|
if (!(sb->s_iflags & SB_I_MULTIROOT) && (mnt->mnt_root == sb->s_root))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return is_subdir(path->dentry, mnt->mnt_root);
|
return is_subdir(path->dentry, mnt->mnt_root);
|
||||||
|
@ -2631,6 +2631,8 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
|
|||||||
/* initial superblock/root creation */
|
/* initial superblock/root creation */
|
||||||
mount_info->fill_super(s, mount_info);
|
mount_info->fill_super(s, mount_info);
|
||||||
nfs_get_cache_cookie(s, mount_info->parsed, mount_info->cloned);
|
nfs_get_cache_cookie(s, mount_info->parsed, mount_info->cloned);
|
||||||
|
if (!(server->flags & NFS_MOUNT_UNSHARED))
|
||||||
|
s->s_iflags |= SB_I_MULTIROOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
mntroot = nfs_get_root(s, mount_info->mntfh, dev_name);
|
mntroot = nfs_get_root(s, mount_info->mntfh, dev_name);
|
||||||
|
@ -1317,6 +1317,7 @@ extern int send_sigurg(struct fown_struct *fown);
|
|||||||
#define SB_I_CGROUPWB 0x00000001 /* cgroup-aware writeback enabled */
|
#define SB_I_CGROUPWB 0x00000001 /* cgroup-aware writeback enabled */
|
||||||
#define SB_I_NOEXEC 0x00000002 /* Ignore executables on this fs */
|
#define SB_I_NOEXEC 0x00000002 /* Ignore executables on this fs */
|
||||||
#define SB_I_NODEV 0x00000004 /* Ignore devices on this fs */
|
#define SB_I_NODEV 0x00000004 /* Ignore devices on this fs */
|
||||||
|
#define SB_I_MULTIROOT 0x00000008 /* Multiple roots to the dentry tree */
|
||||||
|
|
||||||
/* sb->s_iflags to limit user namespace mounts */
|
/* sb->s_iflags to limit user namespace mounts */
|
||||||
#define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */
|
#define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user