[RFC PATCH 17/57] mm/collapse: copy the sources into the destinations

Kiryl Shutsemau <[email protected]>
Newsgroups org.kernel.vger.bpf,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kernel.vger.linux-trace-kernel,org.kvack.linux-mm
Message-ID <[email protected]>
From: "Kiryl Shutsemau (Meta)" <[email protected]>

Fill in the copy.  For each candidate that both froze and has a
destination folio, the page mapped at slot k of its window becomes page k
of that folio.  A slot with no source -- a hole, or a zeropage the freeze
cleared -- is zero-filled instead.

Neither condition implies the other.  A reserve before the lock can leave
a folio on a candidate that then fails to freeze, and the provision
inside the window can decline one for a candidate that froze.

Nothing else is carried across: the destination's PTE bits are not
derived from the sources, and the install rebuilds them the way a fault
would.

A machine check reading a source is the only failure the copy can report,
and only where the architecture provides an MC-safe copy.  The candidate
records SCAN_COPY_MC and the install undoes it, that being where the ptl
the undoing needs is held.

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

diff --git a/mm/collapse.c b/mm/collapse.c
index cf2b9b3640ae..a3882d897d11 100644
--- a/mm/collapse.c
+++ b/mm/collapse.c
@@ -1040,6 +1040,46 @@ static void collapse_provision(struct mm_struct *mm,
 static void collapse_copy(struct vm_area_struct *vma,
 			  struct collapse_control *cc)
 {
+	unsigned int i;
+
+	for (i = 0; i < cc->nr_candidates; i++) {
+		struct collapse_candidate *cand = &cc->candidates[i];
+		const unsigned int nr_pages = candidate_nr_pages(cand);
+		unsigned long addr = cand->addr;
+		unsigned int k;
+
+		/* A folio does not imply a freeze: reserve runs before the lock */
+		if (cand->state != CAND_FROZEN)
+			continue;
+
+		/* A freeze does not imply a folio: provision may have declined */
+		if (!cand->new_folio)
+			continue;
+
+		/* Each source lands where its address puts it: slot k, page k */
+		for (k = 0; k < nr_pages; k++, addr += PAGE_SIZE) {
+			struct page *dst = folio_page(cand->new_folio, k);
+			struct page *src;
+
+			/* No source: a hole, or a zeropage the freeze cleared */
+			if (pte_none_or_zero(cand->saved_ptes[k])) {
+				clear_user_highpage(dst, addr);
+				continue;
+			}
+
+			src = pte_page(cand->saved_ptes[k]);
+
+			/*
+			 * A machine check on a source is the only way this
+			 * fails, and the install is what undoes the candidate:
+			 * that is where the ptl the undoing needs is held.
+			 */
+			if (copy_mc_user_highpage(dst, src, addr, vma)) {
+				cand->result = SCAN_COPY_MC;
+				break;
+			}
+		}
+	}
 }
 
 /* Publish each destination folio in place of the sources it replaces */
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.