Commit 66eca10
mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist()
It's expected that no page should be left in pcp_list after calling
zone_pcp_disable() in offline_pages(). Previously, it's observed that
offline_pages() gets stuck [1] due to some pages remaining in pcp_list.
Cause:
There is a race condition between drain_pages_zone() and __rmqueue_pcplist()
involving the pcp->count variable. See below scenario:
CPU0 CPU1
---------------- ---------------
spin_lock(&pcp->lock);
__rmqueue_pcplist() {
zone_pcp_disable() {
/* list is empty */
if (list_empty(list)) {
/* add pages to pcp_list */
alloced = rmqueue_bulk()
mutex_lock(&pcp_batch_high_lock)
...
__drain_all_pages() {
drain_pages_zone() {
/* read pcp->count, it's 0 here */
count = READ_ONCE(pcp->count)
/* 0 means nothing to drain */
/* update pcp->count */
pcp->count += alloced << order;
...
...
spin_unlock(&pcp->lock);
In this case, after calling zone_pcp_disable() though, there are still some
pages in pcp_list. And these pages in pcp_list are neither movable nor
isolated, offline_pages() gets stuck as a result.
Solution:
Expand the scope of the pcp->lock to also protect pcp->count in
drain_pages_zone(), to ensure no pages are left in the pcp list after
zone_pcp_disable()
[1] https://lore.kernel.org/linux-mm/[email protected]/
Link: https://lkml.kernel.org/r/[email protected]
Fixes: 4b23a68 ("mm/page_alloc: protect PCP lists with a spinlock")
Signed-off-by: Li Zhijian <[email protected]>
Reported-by: Yao Xingtao <[email protected]>
Reviewed-by: Vlastimil Babka <[email protected]>
Cc: David Hildenbrand <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>1 parent f59adcf commit 66eca10
1 file changed
+11
-7
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2343 | 2343 | | |
2344 | 2344 | | |
2345 | 2345 | | |
2346 | | - | |
2347 | | - | |
2348 | | - | |
2349 | | - | |
2350 | | - | |
| 2346 | + | |
2351 | 2347 | | |
| 2348 | + | |
2352 | 2349 | | |
2353 | | - | |
| 2350 | + | |
| 2351 | + | |
| 2352 | + | |
| 2353 | + | |
| 2354 | + | |
| 2355 | + | |
| 2356 | + | |
| 2357 | + | |
2354 | 2358 | | |
2355 | | - | |
| 2359 | + | |
2356 | 2360 | | |
2357 | 2361 | | |
2358 | 2362 | | |
| |||
0 commit comments