Skip to content

Commit 31e332b

Browse files
mjguzikbrauner
authored andcommitted
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>
1 parent 0f607a8 commit 31e332b

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

fs/dcache.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,6 +1981,10 @@ void d_instantiate_new(struct dentry *entry, struct inode *inode)
19811981
spin_lock(&inode->i_lock);
19821982
__d_instantiate(entry, inode);
19831983
WARN_ON(!(inode->i_state & I_NEW));
1984+
/*
1985+
* Pairs with smp_rmb in wait_on_inode().
1986+
*/
1987+
smp_wmb();
19841988
inode->i_state &= ~I_NEW & ~I_CREATING;
19851989
/*
19861990
* Pairs with the barrier in prepare_to_wait_event() to make sure

fs/inode.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,10 @@ void unlock_new_inode(struct inode *inode)
11811181
lockdep_annotate_inode_mutex_key(inode);
11821182
spin_lock(&inode->i_lock);
11831183
WARN_ON(!(inode->i_state & I_NEW));
1184+
/*
1185+
* Pairs with smp_rmb in wait_on_inode().
1186+
*/
1187+
smp_wmb();
11841188
inode->i_state &= ~I_NEW & ~I_CREATING;
11851189
/*
11861190
* Pairs with the barrier in prepare_to_wait_event() to make sure
@@ -1198,6 +1202,10 @@ void discard_new_inode(struct inode *inode)
11981202
lockdep_annotate_inode_mutex_key(inode);
11991203
spin_lock(&inode->i_lock);
12001204
WARN_ON(!(inode->i_state & I_NEW));
1205+
/*
1206+
* Pairs with smp_rmb in wait_on_inode().
1207+
*/
1208+
smp_wmb();
12011209
inode->i_state &= ~I_NEW;
12021210
/*
12031211
* Pairs with the barrier in prepare_to_wait_event() to make sure

include/linux/writeback.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ static inline void wait_on_inode(struct inode *inode)
194194
{
195195
wait_var_event(inode_state_wait_address(inode, __I_NEW),
196196
!(READ_ONCE(inode->i_state) & I_NEW));
197+
/*
198+
* Pairs with routines clearing I_NEW.
199+
*/
200+
smp_rmb();
197201
}
198202

199203
#ifdef CONFIG_CGROUP_WRITEBACK

0 commit comments

Comments
 (0)