From 31e332b911fca54df467d264d7e2a2ef9317f3ca Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Mon, 6 Oct 2025 01:15:26 +0200 Subject: [PATCH] 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 Signed-off-by: Christian Brauner --- fs/dcache.c | 4 ++++ fs/inode.c | 8 ++++++++ include/linux/writeback.h | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index a067fa0a965a1..806d6a665124f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -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 diff --git a/fs/inode.c b/fs/inode.c index fa82cb810af44..37fc7a72aba55 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -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 diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 22dd4adc5667d..e1e1231a68303 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -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 -- 2.47.3