On Mon, 20 Sep 2021 09:54:32 +0100 Mel Gorman wrote: > +static void > +reclaim_throttle(pg_data_t *pgdat, enum vmscan_throttle_state reason, > + long timeout) > +{ > + wait_queue_head_t *wqh =3D &pgdat->reclaim_wait; > + unsigned long start =3D jiffies; > + long ret; > + DEFINE_WAIT(wait); > + > + atomic_inc(&pgdat->nr_reclaim_throttled); > + WRITE_ONCE(pgdat->nr_reclaim_start, > + node_page_state(pgdat, NR_THROTTLED_WRITTEN)); Missing wakeup could happen if the current sleeper overwrites pgdat->nr_reclaim_start set by the existing sleeper. if (1 == atomic_inc_and_return(&pgdat->nr_reclaim_throttled)) WRITE_ONCE(pgdat->nr_reclaim_start, node_page_state(pgdat, NR_THROTTLED_WRITTEN)); > + > + prepare_to_wait(wqh, &wait, TASK_INTERRUPTIBLE); > + ret =3D schedule_timeout(timeout); > + finish_wait(wqh, &wait); > + atomic_dec(&pgdat->nr_reclaim_throttled); > + > + trace_mm_vmscan_throttled(pgdat->node_id, jiffies_to_usecs(timeout), > + jiffies_to_usecs(jiffies - start), > + reason); > +} > + > +/* > + * Account for pages written if tasks are throttled waiting on dirty > + * pages to clean. If enough pages have been cleaned since throttling > + * started then wakeup the throttled tasks. > + */ > +void __acct_reclaim_writeback(pg_data_t *pgdat, struct page *page) > +{ > + unsigned long nr_written; > + int nr_throttled =3D atomic_read(&pgdat->nr_reclaim_throttled); > + > + __inc_node_page_state(page, NR_THROTTLED_WRITTEN); > + nr_written =3D node_page_state(pgdat, NR_THROTTLED_WRITTEN) - > + READ_ONCE(pgdat->nr_reclaim_start); > + > + if (nr_written > SWAP_CLUSTER_MAX * nr_throttled) > + wake_up_interruptible_all(&pgdat->reclaim_wait); > +}