Skip to content

Commit e790484

Browse files
gerald-schaefergregkh
authored andcommitted
s390/mm: Add cond_resched() to cmm_alloc/free_pages()
[ Upstream commit 131b8db ] Adding/removing large amount of pages at once to/from the CMM balloon can result in rcu_sched stalls or workqueue lockups, because of busy looping w/o cond_resched(). Prevent this by adding a cond_resched(). cmm_free_pages() holds a spin_lock while looping, so it cannot be added directly to the existing loop. Instead, introduce a wrapper function that operates on maximum 256 pages at once, and add it there. Signed-off-by: Gerald Schaefer <[email protected]> Reviewed-by: Heiko Carstens <[email protected]> Signed-off-by: Heiko Carstens <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 7a04cc2 commit e790484

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

arch/s390/mm/cmm.c

+17-1
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,12 @@ static long cmm_alloc_pages(long nr, long *counter,
9595
(*counter)++;
9696
spin_unlock(&cmm_lock);
9797
nr--;
98+
cond_resched();
9899
}
99100
return nr;
100101
}
101102

102-
static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
103+
static long __cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
103104
{
104105
struct cmm_page_array *pa;
105106
unsigned long addr;
@@ -123,6 +124,21 @@ static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
123124
return nr;
124125
}
125126

127+
static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
128+
{
129+
long inc = 0;
130+
131+
while (nr) {
132+
inc = min(256L, nr);
133+
nr -= inc;
134+
inc = __cmm_free_pages(inc, counter, list);
135+
if (inc)
136+
break;
137+
cond_resched();
138+
}
139+
return nr + inc;
140+
}
141+
126142
static int cmm_oom_notify(struct notifier_block *self,
127143
unsigned long dummy, void *parm)
128144
{

0 commit comments

Comments
 (0)