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
