Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df09348f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents cfb61b5e 95dd7758
Loading
Loading
Loading
Loading
+16 −5
Original line number Original line Diff line number Diff line
@@ -647,11 +647,16 @@ static inline struct dentry *lock_parent(struct dentry *dentry)
		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;
			parent = NULL;
		}
	} else {
		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 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
		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;
+3 −2
Original line number Original line Diff line number Diff line
@@ -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);
+2 −0
Original line number Original line Diff line number Diff line
@@ -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);
+1 −0
Original line number Original line Diff line number Diff line
@@ -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 */