Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a12b82d7 authored by Gerald Schaefer's avatar Gerald Schaefer Committed by Greg Kroah-Hartman
Browse files

s390/mm: Add cond_resched() to cmm_alloc/free_pages()



[ Upstream commit 131b8db78558120f58c5dc745ea9655f6b854162 ]

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: default avatarGerald Schaefer <gerald.schaefer@linux.ibm.com>
Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent f559306a
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -98,11 +98,12 @@ static long cmm_alloc_pages(long nr, long *counter,
		(*counter)++;
		spin_unlock(&cmm_lock);
		nr--;
		cond_resched();
	}
	return nr;
}

static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
static long __cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
{
	struct cmm_page_array *pa;
	unsigned long addr;
@@ -126,6 +127,21 @@ static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
	return nr;
}

static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
{
	long inc = 0;

	while (nr) {
		inc = min(256L, nr);
		nr -= inc;
		inc = __cmm_free_pages(inc, counter, list);
		if (inc)
			break;
		cond_resched();
	}
	return nr + inc;
}

static int cmm_oom_notify(struct notifier_block *self,
			  unsigned long dummy, void *parm)
{