Skip to content

Commit dd9e2f5

Browse files
jankaraakpm00
authored andcommitted
flex_proportions: make fprop_new_period() hardirq safe
Bernd has reported a lockdep splat from flexible proportions code that is essentially complaining about the following race: <timer fires> run_timer_softirq - we are in softirq context call_timer_fn writeout_period fprop_new_period write_seqcount_begin(&p->sequence); <hardirq is raised> ... blk_mq_end_request() blk_update_request() ext4_end_bio() folio_end_writeback() __wb_writeout_add() __fprop_add_percpu_max() if (unlikely(max_frac < FPROP_FRAC_BASE)) { fprop_fraction_percpu() seq = read_seqcount_begin(&p->sequence); - sees odd sequence so loops indefinitely Note that a deadlock like this is only possible if the bdi has configured maximum fraction of writeout throughput which is very rare in general but frequent for example for FUSE bdis. To fix this problem we have to make sure write section of the sequence counter is irqsafe. Link: https://lkml.kernel.org/r/20260121112729.24463-2-jack@suse.cz Fixes: a91befd ("lib/flex_proportions.c: remove local_irq_ops in fprop_new_period()") Signed-off-by: Jan Kara <jack@suse.cz> Reported-by: Bernd Schubert <bernd@bsbernd.com> Link: https://lore.kernel.org/all/9b845a47-9aee-43dd-99bc-1a82bea00442@bsbernd.com/ Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Joanne Koong <joannelkoong@gmail.com> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent d54887e commit dd9e2f5

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

lib/flex_proportions.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,22 @@ void fprop_global_destroy(struct fprop_global *p)
6464
bool fprop_new_period(struct fprop_global *p, int periods)
6565
{
6666
s64 events = percpu_counter_sum(&p->events);
67+
unsigned long flags;
6768

6869
/*
6970
* Don't do anything if there are no events.
7071
*/
7172
if (events <= 1)
7273
return false;
73-
preempt_disable_nested();
74+
local_irq_save(flags);
7475
write_seqcount_begin(&p->sequence);
7576
if (periods < 64)
7677
events -= events >> periods;
7778
/* Use addition to avoid losing events happening between sum and set */
7879
percpu_counter_add(&p->events, -events);
7980
p->period += periods;
8081
write_seqcount_end(&p->sequence);
81-
preempt_enable_nested();
82+
local_irq_restore(flags);
8283

8384
return true;
8485
}

0 commit comments

Comments
 (0)