mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 11:06:41 -05:00
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: Mateusz Guzik <mjguzik@gmail.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
committed by
Christian Brauner
parent
0f607a89af
commit
31e332b911
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user