From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46EDA48642B for ; Tue, 13 Oct 2026 04:33:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791866036; cv=none; b=LyTxQ0auSs3KAWXWxCDcsjFuYgeo0egQvVInqPzPfwgDBCJediI1a4vLYYkJIPIolqFLzezbpqGZvi1KAwKcmU/uE0YRNL+RGrAGWCoAKjBsqX309j8c06E/YbQrtYzaD/2OzbvXYfy49nPRqRl0u/HI2avuUkXFEm6f9SZaQ9M= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791866036; c=relaxed/simple; bh=JTni1MQd1y2f+VN3xr3ckBWB29M7IGU5K13vrnkSvyA=; h=Date:To:From:Subject:Message-Id; b=FASWHsXHgAUMOAoYma4MI/52mJ55K+21t1emzzxW2wXarxDtScFa/LKoUNRt62n+fXS/41HJUvmzT/kbDWc7O4EZRCMj+t5O2s/riqaxEhXA1irL/E70hWt3jKNbVveqlGcLR30v0T2R2BLlpHVEXcNE5oWGqzqfQA35nL0nzWc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b=LL7NasYQ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b="LL7NasYQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 144751F00899; Tue, 13 Oct 2026 04:33:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux-foundation.org; s=korg; t=1791866032; bh=h7RV3TwM7XAN0DWKIxISnq34EJg7DUMZmREH5cArimg=; h=Date:To:From:Subject; b=LL7NasYQrskaNA3tw0PEqL/lk83kiYY4wzfFEa4bt0/6MgdlNCZzaGXyGP9vvR9Tr AZtYmyhV49F0bPjmPQJmPztF3nU9nkmtoztk+qS1PivdpTytRwhH3KXVRGgUwDjox5 u+HO82ukCUlJZwqgzJBt28dcqTSy8+mvRRItcfQM= Date: Mon, 12 Oct 2026 21:33:51 -0700 To: mm-commits@vger.kernel.org,ziy@nvidia.com,vbabka@kernel.org,usama.arif@linux.dev,usama.anjum@arm.com,surenb@google.com,shuah@kernel.org,ryan.roberts@arm.com,rppt@kernel.org,nico.pache@linux.dev,mhocko@suse.com,ljs@kernel.org,liam@infradead.org,leon@kernel.org,lance.yang@linux.dev,kernel-team@meta.com,jgg@ziepe.ca,hughd@google.com,dev.jain@arm.com,david@kernel.org,baolin.wang@linux.alibaba.com,baohua@kernel.org,agordeev@linux.ibm.com,kas@kernel.org,akpm@linux-foundation.org From: Andrew Morton Subject: [merged mm-stable] selftests-mm-cover-a-shared-source-collapse-write-race.patch removed from -mm tree Message-Id: <20261013043352.144751F00899@smtp.kernel.org> Precedence: bulk X-Mailing-List: mm-commits@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: The quilt patch titled Subject: selftests/mm: cover a shared-source collapse write race has been removed from the -mm tree. Its filename was selftests-mm-cover-a-shared-source-collapse-write-race.patch This patch was dropped because it was merged into the mm-stable branch of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm ------------------------------------------------------ From: "Kiryl Shutsemau (Meta)" Subject: selftests/mm: cover a shared-source collapse write race Date: Sat, 19 Sep 2026 01:24:43 +0100 collapse_fork() checks that a fork-shared range collapses in the child while the parent keeps its own pages, but the parent sits still while that happens. Nothing checks that CoW isolation survives a collapse racing with writes to the shared source. Add a case where the parent writes to the shared range throughout the child's collapse. CoW has to keep the two apart: the child must see the content from before the fork, and the parent only its own writes. The parent unshares one page every 10ms, starting only once the child says it is about to collapse. Writing the range in a burst would break CoW on all of it before the collapse begins, leaving the child to collapse pages that are already exclusive to it. Preparation for changing how collapse handles fork-shared sources. Link: https://lore.kernel.org/20260919002451.496763-14-kirill@shutemov.name Signed-off-by: Kiryl Shutsemau (Meta) Signed-off-by: Andrew Morton Tested-by: Muhammad Usama Anjum Assisted-by: LLM Cc: Alexander Gordeev Cc: Baolin Wang Cc: Barry Song Cc: "David Hildenbrand (arm)" Cc: Dev Jain Cc: Hugh Dickens Cc: Jason Gunthorpe Cc: kernel-team@meta.com Cc: Lance Yang Cc: Leon Romanovsky Cc: Liam Howlett Cc: Lorenzo Stoakes (ARM) Cc: Michal Hocko Cc: Mike Rapoport (Microsoft) Cc: Nico Pache (Red Hat) Cc: Ryan Roberts Cc: Shuah Khan (Samsung OSG) Cc: Suren Baghdasaryan Cc: Usama Arif Cc: "Vlastimil Babka (SUSE)" Cc: Zi Yan --- tools/testing/selftests/mm/khugepaged.c | 106 ++++++++++++++++++++++ 1 file changed, 106 insertions(+) --- a/tools/testing/selftests/mm/khugepaged.c~selftests-mm-cover-a-shared-source-collapse-write-race +++ a/tools/testing/selftests/mm/khugepaged.c @@ -1166,6 +1166,109 @@ static void collapse_max_ptes_shared(str ksft_test_result_report(exit_status, "%s\n", __func__); } +/* + * The parent writes to the fork-shared range throughout the child's + * collapse. CoW must keep the two apart: the child sees the pre-fork + * content, the parent only its own writes. + */ +static void collapse_fork_cow_race(struct collapse_context *c, struct mem_ops *ops) +{ + const int stride = page_size / sizeof(int); + int wstatus, child_status, i, n; + unsigned long shared; + volatile int *ip; + pid_t child; + int sync[2]; + char go = 1; + void *p; + + /* At a page per 10 ms, 64 pages spread the writes across the collapse */ + n = 64; + shared = n * page_size; + + p = ops->setup_area(1); + /* Shared prefix, with the pre-fork pattern */ + ops->fault(p, 0, shared); + if (pipe(sync)) + ksft_exit_fail_perror("pipe()"); + + /* A volatile pointer so the stores are not merged or dropped */ + ip = p; + + ksft_print_msg("Fork, collapse in the child while the parent rewrites..."); + child = fork(); + if (!child) { + int collapse_status; + + close(sync[0]); + /* Private remainder */ + ops->fault(p, shared, hpage_pmd_size); + /* Start the parent unsharing, and give it a head start */ + if (write(sync[1], &go, 1) != 1) + _exit(KSFT_FAIL); + usleep(5000); + c->collapse("Collapse a range the parent is writing to", + p, 1, ops, true); + collapse_status = exit_status; + for (i = 0; i < n; i++) + if (ip[i * stride] != i + 0xdead0000) + break; + if (i == n) + success("OK"); + else + fail("Fail: child content"); + /* The content check must not bury a failed collapse */ + if (exit_status != KSFT_FAIL) + exit_status = collapse_status; + ops->cleanup_area(p, hpage_pmd_size); + _exit(exit_status); + } + + close(sync[1]); + if (read(sync[0], &go, 1) != 1) + ksft_exit_fail_msg("child never reached the collapse\n"); + close(sync[0]); + + /* + * Unshare one page at a time: a burst would break CoW on the whole + * range before the collapse starts, leaving nothing shared to collapse. + */ + i = 0; + for (;;) { + pid_t ret; + + if (i < n) + ip[i * stride] = i + 0xbeef0000; + i++; + usleep(10 * 1000); + ret = waitpid(child, &wstatus, WNOHANG); + if (ret == child) + break; + if (ret < 0) + ksft_exit_fail_perror("waitpid()"); + } + + /* Finish whatever the paced sweep did not reach */ + for (; i < n; i++) + ip[i * stride] = i + 0xbeef0000; + /* A child that died reading the racing pages is a failure, not a zero */ + child_status = WIFEXITED(wstatus) ? WEXITSTATUS(wstatus) : KSFT_FAIL; + + ksft_print_msg("Check the parent sees only its own writes..."); + for (i = 0; i < n; i++) + if (ip[i * stride] != i + 0xbeef0000) + break; + if (i == n) + success("OK"); + else + fail("Fail: parent content"); + ops->cleanup_area(p, hpage_pmd_size); + /* The parent's check must not bury the child's verdict */ + if (exit_status != KSFT_FAIL) + exit_status = child_status; + ksft_test_result_report(exit_status, "%s\n", __func__); +} + static void madvise_collapse_existing_thps(struct collapse_context *c, struct mem_ops *ops) { @@ -1700,6 +1803,9 @@ int main(int argc, char **argv) TEST(collapse_max_ptes_shared, khugepaged_context, anon_ops); TEST(collapse_max_ptes_shared, madvise_context, anon_ops); + TEST(collapse_fork_cow_race, khugepaged_context, anon_ops); + TEST(collapse_fork_cow_race, madvise_context, anon_ops); + TEST(madvise_collapse_existing_thps, madvise_context, anon_ops); TEST(madvise_collapse_existing_thps, madvise_context, read_only_file_ops); TEST(madvise_collapse_existing_thps, madvise_context, read_write_file_read_ops); _ Patches currently in -mm which might be from kas@kernel.org are mm-page_alloc-make-defrag_mode-retries-follow-the-promoted-order.patch mm-khugepaged-drop-redundant-mm_struct-pin-in-madvise_collapse.patch mm-khugepaged-count-collapses-where-khugepaged-makes-them.patch mm-khugepaged-rename-mthp_present_ptes-bitmap-to-eligible_ptes.patch mm-collapse-add-collapseh-for-the-collapse-interface.patch mm-collapse-state-what-a-collapse-may-do-in-the-policy.patch mm-collapse-drop-the-collapse_possible-wrapper.patch mm-collapse-name-the-per-table-scan-reset-for-what-it-resets.patch mm-collapse-call-collapse_file-from-collapse_single_pmd.patch mm-collapse-separate-scanning-a-pte-table-from-collapsing-it.patch mm-collapse-open-code-collapse_single_pmd-in-its-two-callers.patch mm-collapse-work-out-the-orders-a-vma-allows-once-per-vma.patch mm-collapse-declare-the-collapse-interface-in-collapseh.patch mm-collapse-implement-madv_collapse-in-madvisec.patch