Skip to content

Commit e057a29

Browse files
alanskindKent Overstreet
authored andcommitted
bcachefs: Fix lost wake up
If the reader acquires the read lock and then the writer enters the slow path, while the reader proceeds to the unlock path, the following scenario can occur without the change: writer: pcpu_read_count(lock) return 1 (so __do_six_trylock will return 0) reader: this_cpu_dec(*lock->readers) reader: smp_mb() reader: state = atomic_read(&lock->state) (there is no waiting flag set) writer: six_set_bitmask() then the writer will sleep forever. Signed-off-by: Alan Huang <mmpgouride@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent d50d7a5 commit e057a29

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

fs/bcachefs/six.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,17 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type,
169169
ret = -1 - SIX_LOCK_write;
170170
}
171171
} else if (type == SIX_LOCK_write && lock->readers) {
172-
if (try) {
172+
if (try)
173173
atomic_add(SIX_LOCK_HELD_write, &lock->state);
174-
smp_mb__after_atomic();
175-
}
176174

175+
/*
176+
* Make sure atomic_add happens before pcpu_read_count and
177+
* six_set_bitmask in slow path happens before pcpu_read_count.
178+
*
179+
* Paired with the smp_mb() in read lock fast path (per-cpu mode)
180+
* and the one before atomic_read in read unlock path.
181+
*/
182+
smp_mb();
177183
ret = !pcpu_read_count(lock);
178184

179185
if (try && !ret) {

0 commit comments

Comments
 (0)