From: "Kiryl Shutsemau (Meta)" <[email protected]>

A candidate a round attempts either collapsed or did not, and if it did
not there is a reason.  Selection needs those outcomes to decide what
comes next: carry on past the window, try the same region at a lower
order, or give the table up.

Fill in collapse_run_batch(): run the round, then walk the batch handing
each candidate's result to classification.

The walk covers the whole batch.  A pass that refuses one candidate marks
it and carries on rather than truncating the round, so every candidate
has a result of its own to hand back.  Only an outcome that condemns the
table cuts the walk short, and then nothing of that table re-enters
selection.

The round and the classification it feeds are both stubs, so nothing is
attempted and nothing is decided.

Assisted-by: Claude-Code:claude-opus-5
Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]>
---
 mm/collapse.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/mm/collapse.c b/mm/collapse.c
index 6dae5e35e61d..ad9e5a447854 100644
--- a/mm/collapse.c
+++ b/mm/collapse.c
@@ -115,8 +115,16 @@
 struct collapse_candidate {
        unsigned long addr;
        unsigned int order;
+       enum scan_result result;
 };
 
+/* Where a candidate sits in the table, in the PTE offsets selection counts in 
*/
+static unsigned int candidate_offset(const struct collapse_candidate *cand,
+                                    unsigned long pmd_addr)
+{
+       return (cand->addr - pmd_addr) >> PAGE_SHIFT;
+}
+
 void collapse_control_release(struct collapse_control *cc)
 {
        kfree(cc->candidates);
@@ -132,6 +140,17 @@ int collapse_control_init(struct collapse_control *cc)
        return 0;
 }
 
+/*
+ * Carry one batch of candidates through the passes.  Every candidate comes 
back
+ * with a result of its own: the passes before the freeze mark what they refuse
+ * and carry on, each pass after it works on what the last left, so no failure
+ * truncates the round.
+ */
+static void collapse_round(struct mm_struct *mm, unsigned long pmd_addr,
+                          struct collapse_control *cc)
+{
+}
+
 /*
  * Is @count past a limit stated per PMD, when only part of a table was 
scanned?
  * Scale the comparison to the table so a partial scan is held to the same
@@ -455,6 +474,18 @@ static bool collapse_next_candidate(struct 
collapse_control *cc,
        return false;
 }
 
+/*
+ * Feed one candidate's outcome back into selection: its region is done, it
+ * re-enters the retry store at a lower order, or the table is abandoned.
+ * Returns false in that last case.
+ */
+static bool collapse_classify_result(struct collapse_control *cc,
+                                    unsigned int offset, unsigned int order,
+                                    enum scan_result result)
+{
+       return true;
+}
+
 /*
  * Run and classify the collected batch.  Returns false when a candidate's
  * outcome abandons the table.
@@ -462,9 +493,30 @@ static bool collapse_next_candidate(struct 
collapse_control *cc,
 static bool collapse_run_batch(struct mm_struct *mm, unsigned long pmd_addr,
                               struct collapse_control *cc)
 {
+       unsigned int i;
+
        /* collapse_anon_pmd() only runs a round it has put something in */
        VM_WARN_ON_ONCE(!cc->nr_candidates);
 
+       collapse_round(mm, pmd_addr, cc);
+
+       for (i = 0; i < cc->nr_candidates; i++) {
+               struct collapse_candidate *cand = &cc->candidates[i];
+               unsigned int offset = candidate_offset(cand, pmd_addr);
+
+               if (!collapse_classify_result(cc, offset, cand->order,
+                                             cand->result)) {
+                       /*
+                        * The table is abandoned: the candidates behind this 
one
+                        * keep their results and are left unclassified, so
+                        * nothing more of this table enters selection, and the
+                        * abandoning result clears what earlier ones left 
there.
+                        */
+                       cc->nr_candidates = 0;
+                       return false;
+               }
+       }
+
        cc->nr_candidates = 0;
        return true;
 }
@@ -502,6 +554,7 @@ static void collapse_add_candidate(struct collapse_control 
*cc,
        cc->nr_candidates++;
        cand->addr = addr;
        cand->order = order;
+       cand->result = SCAN_FAIL;
 }
 
 /*
-- 
2.54.0


Reply via email to