Skip to content

Commit 12b7636

Browse files
gerald-schaeferSasha Levin
authored and
Sasha Levin
committed
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 1c29fb3 commit 12b7636

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
@@ -98,11 +98,12 @@ static long cmm_alloc_pages(long nr, long *counter,
9898
(*counter)++;
9999
spin_unlock(&cmm_lock);
100100
nr--;
101+
cond_resched();
101102
}
102103
return nr;
103104
}
104105

105-
static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
106+
static long __cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
106107
{
107108
struct cmm_page_array *pa;
108109
unsigned long addr;
@@ -126,6 +127,21 @@ static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
126127
return nr;
127128
}
128129

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

0 commit comments

Comments
 (0)