[RFC PATCH 42/57] mm/collapse: allow error injection into the freeze

From: Kiryl Shutsemau

Date: Sun Aug 16 2026 - 18:57:57 EST


From: "Kiryl Shutsemau (Meta)" <kas@xxxxxxxxxx>

The freeze refuses a candidate for reasons a test cannot arrange: a
co-mapper appearing between the two sweeps, a GUP-fast pin, writeback.
What the round does then -- the candidate drops out, its neighbours carry
on, the region goes back to selection at a lower order -- is worth
exercising on purpose.

Tag collapse_freeze_candidate(), noinline so fail_function can find the
symbol. ERRNO is the only injection type for a function that returns a
value rather than a pointer or a bool, so an injected result is a negative
errno. It only ever reaches cand->result, where every caller compares it
against SCAN_SUCCEED and finds it unequal, which is the refusal the test
wants. Tracing prints it as a number, having no symbol for it.

A forced return happens at function entry, so this reaches the refusal,
not the freeze's own unwind path.

Assisted-by: Claude-Code:claude-opus-5
Signed-off-by: Kiryl Shutsemau (Meta) <kas@xxxxxxxxxx>
---
mm/collapse.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/mm/collapse.c b/mm/collapse.c
index 952e3f62d920..76a53616b240 100644
--- a/mm/collapse.c
+++ b/mm/collapse.c
@@ -4,6 +4,7 @@
#include <linux/backing-dev.h>
#include <linux/bitops.h>
#include <linux/dax.h>
+#include <linux/error-injection.h>
#include <linux/highmem.h>
#include <linux/huge_mm.h>
#include <linux/hugetlb.h> /* x86 flush_tlb_range() uses hstate_vma() */
@@ -937,7 +938,7 @@ static enum scan_result collapse_check_candidate(struct vm_area_struct *vma,
* collapse_freeze() issues the ranged TLB flush over everything that froze
* before dropping the ptl. No copy may run before it completes.
*/
-static enum scan_result collapse_freeze_candidate(struct mm_struct *mm,
+static noinline enum scan_result collapse_freeze_candidate(struct mm_struct *mm,
struct collapse_candidate *cand, pte_t *pte)
{
const unsigned int nr_pages = candidate_nr_pages(cand);
@@ -1085,6 +1086,7 @@ static enum scan_result collapse_freeze_candidate(struct mm_struct *mm,
collapse_unfreeze_candidate(mm, cand, pte, nr_saved, nr_frozen);
return result;
}
+ALLOW_ERROR_INJECTION(collapse_freeze_candidate, ERRNO);

/*
* Raise the two barriers on the sources of every candidate: migration entries in
--
2.54.0