Unverified Commit 31e332b9 authored by Mateusz Guzik's avatar Mateusz Guzik Committed by Christian Brauner
Browse files

fs: add missing fences to I_NEW handling



Suppose there are 2 CPUs racing inode hash lookup func (say ilookup5())
and unlock_new_inode().

In principle the latter can clear the I_NEW flag before prior stores
into the inode were made visible.

The former can in turn observe I_NEW is cleared and proceed to use the
inode, while possibly reading from not-yet-published areas.

Signed-off-by: default avatarMateusz Guzik <mjguzik@gmail.com>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 0f607a89
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1981,6 +1981,10 @@ void d_instantiate_new(struct dentry *entry, struct inode *inode)
	spin_lock(&inode->i_lock);
	__d_instantiate(entry, inode);
	WARN_ON(!(inode->i_state & I_NEW));
	/*
	 * Pairs with smp_rmb in wait_on_inode().
	 */
	smp_wmb();
	inode->i_state &= ~I_NEW & ~I_CREATING;
	/*
	 * Pairs with the barrier in prepare_to_wait_event() to make sure
+8 −0
Original line number Diff line number Diff line
@@ -1181,6 +1181,10 @@ void unlock_new_inode(struct inode *inode)
	lockdep_annotate_inode_mutex_key(inode);
	spin_lock(&inode->i_lock);
	WARN_ON(!(inode->i_state & I_NEW));
	/*
	 * Pairs with smp_rmb in wait_on_inode().
	 */
	smp_wmb();
	inode->i_state &= ~I_NEW & ~I_CREATING;
	/*
	 * Pairs with the barrier in prepare_to_wait_event() to make sure
@@ -1198,6 +1202,10 @@ void discard_new_inode(struct inode *inode)
	lockdep_annotate_inode_mutex_key(inode);
	spin_lock(&inode->i_lock);
	WARN_ON(!(inode->i_state & I_NEW));
	/*
	 * Pairs with smp_rmb in wait_on_inode().
	 */
	smp_wmb();
	inode->i_state &= ~I_NEW;
	/*
	 * Pairs with the barrier in prepare_to_wait_event() to make sure
+4 −0
Original line number Diff line number Diff line
@@ -194,6 +194,10 @@ static inline void wait_on_inode(struct inode *inode)
{
	wait_var_event(inode_state_wait_address(inode, __I_NEW),
		       !(READ_ONCE(inode->i_state) & I_NEW));
	/*
	 * Pairs with routines clearing I_NEW.
	 */
	smp_rmb();
}

#ifdef CONFIG_CGROUP_WRITEBACK