From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 9608A27AC4D; Sat, 19 Sep 2026 00:24:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777501; cv=none; b=Dx7JlUOtSGSTpSZ52m3U8mwpqRZq1XzC7ZNrJ2gzJDoP9eKEMiuAGYlYMor44sS9moCgDpaFNfDJ943JLlBbsanzuctEttoSXfEwbNwqGN9+287IBDJZ0OqAuUDVZKF1CSpDkARB7TW/vO7EXFDIPGxuqh8IWQ+N66Z0MVRCbzY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777501; c=relaxed/simple; bh=oihi97UF0W+Euvg2yKxo3S7vW1lBLqlVXCLDLPb/rGA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l01LIV53UaHXgz5Ey+XtZcd/0lj8+9EQ5iTvkNZBPHcYilcYw+dJEoSARHhWSBCxR4RCFpHEFpon7UlWblemDk/8uVO5vu/LbxPoi2wNSLYiAqLCW2TZ5VSvr4MlzEvDcvYGdiunNfH9GL/a6er2aqgV3L5zeml+RCpjyzOpahQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=lZfXBWcc; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=IHTDTava; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="lZfXBWcc"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="IHTDTava" Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailfout.phl.internal (Postfix) with ESMTP id 97EBDEC0232; Fri, 18 Sep 2026 20:24:58 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Fri, 18 Sep 2026 20:24:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777498; x= 1789863898; bh=fo76vmrg4cxg21gPYqwdjCzZp7TsVtRf/8vWWUFNPFg=; b=l ZfXBWccAMPvC2qPAVaDlQt61nq4HN5Mi+I1M7G/Z2tn6MtTbiFgBMQHYHR4G9s30 CtOOINuX5S7jlro7UluFW4YKuJ9d8cYKyAmpVuA210EZJtzuQR7lVwj+/vTcdgJM KR1ZZ7RZtBWenbuH31MqD3KdR21ueuxa607ewZHy4CYFfjXzN+qLivxZ/QViAVVn p4Paq4bRz7m8HvIiCPucvHZokWkkdnqe/h5tA5AQHRIPYAiqmDV46r+s6IomGu7n LyiQrJYJWWm8QXi/wQEvhPMeJiYljifHqVqZMbrOceBU2JeMJPpQrOL6sci//YS2 DlwfU4AWrK4V41eFjYpKA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777498; x=1789863898; bh=f o76vmrg4cxg21gPYqwdjCzZp7TsVtRf/8vWWUFNPFg=; b=IHTDTavaN5BPAZjn1 nb+tf234GGchB6TRqEPGjvis35+hOPoUM+4LWLkdoowMOz/jO+k0inhVLYK+gNAA VAw933NoRZRtDaBp2T523sVEXRl1UXexl5kSiZ3fUHopmJ4t3tj5KDE0tmuMReqV rYTRDnsaN7bl5YRf8QX++g61Gcvf9muh4JGdVFlArC7HlptqSeox25nV2WDRONnL tZ0cWkEoADbEHkSHh6q5jx3Twc4pPFk6XfIn+IGe3O3DXliC/aSkYmvWDH7WJ6lD yDsqoSZdP3wim9Su1ISNuEMT/grXnOzFsqnH1ktqkowJO7ReQE5MYQ2B9tpGT2YA tSQ8Q== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMLH oHJ9HNYzZnkDKS1K8Ngn6glJpoAJiwfFQtmosaAwPr6HHW/c5Fs/OG20UCk7mR1J+pkJlt RJvl2gFpnHl+J/iUvVWt0Fwg1nnmp9OaBTY0l/8mmUua7WuweLrx8GwjSYkt4okpW3tY9b BobACyLC13eAvQ+mg5RgfIzwrZSti6H6tBBjbY4ZQW6YVQ3l51oFC8HYKSs1DoGQ1TmQEJ ACZM5pYsUyMyLiJm0afVVT/drw7VcjvG+rTG+u33CLRAqrZcWc/nOhkDgTh1CKBGJbX7fn 91pfQ0e8zUkmgSxWeGxapdWCLKbWjVD/eBmS87HwLAmUIe6GxE+zUZQqxMyQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:24:57 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 01/19] selftests/mm: raise the khugepaged test-case cap Date: Sat, 19 Sep 2026 01:24:31 +0100 Message-ID: <20260919002451.496763-2-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" TEST() ends the run with "MAX_TEST_CASES is too small" when the table fills, and the table holds 64. A full invocation already registers 63, so the next case added anywhere aborts the whole suite before a single test runs. Raise the cap to 256. The table is a static array of small structs, so the room costs nothing worth counting. Assisted-by: LLM Acked-by: Usama Arif Acked-by: Lorenzo Stoakes (ARM) Reviewed-by: Mike Rapoport (Microsoft) Reviewed-by: Baolin Wang Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 525108cace54..c44bc18f7536 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1290,7 +1290,7 @@ struct test_case { test_fn fn; }; =20 -#define MAX_TEST_CASES 64 +#define MAX_TEST_CASES 256 static struct test_case test_cases[MAX_TEST_CASES]; static int nr_test_cases; =20 --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 DEB3C64A91; Sat, 19 Sep 2026 00:25:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777503; cv=none; b=Ztg1ZoMaIm7TrzL8+DQB8xofgOnwYylp31jZZo2RbenXcXtJxuYBpflELWkxbz4Ds0wnu+2EwFZIAmOOC/gFxoy95mSQwEfJZTHUdtediQ8zEeNFv7VHP9MVLlfjBCD8Wj+M7UBnKuwwqbnv0AyMxxN2Vv5BdQlngZx/0LUtBX4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777503; c=relaxed/simple; bh=W2HfU1srPKa1GnKZB50hCkDu/NdjzAz9+jIdL0D7zMk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qUcvuEGn2g/J+Nmf8iDHwwaVlVVn6p1Z2rj7CfiY48EkToGWipDM9DKMzRk1s0FPe5M+MdYANBrhpXNt3iN+98ns0oq6GhfkfoqdGbsayUh0VnZKxbFAxi/XnOGFT4cDVwFleRcsapwtlWLESKwNYgcA61qE2jegVkkS+6n9Tec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=jKbVWodS; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=W3Vq72TC; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="jKbVWodS"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="W3Vq72TC" Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailfhigh.phl.internal (Postfix) with ESMTP id 05F8E1400165; Fri, 18 Sep 2026 20:25:01 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Fri, 18 Sep 2026 20:25:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777501; x= 1789863901; bh=Tvadg5PnjaO+JyB3jIAGCIC7KUlwEu9asx5MUc98HYY=; b=j KbVWodSA+B/CqaEXHYWQuWCYcGqo9M4Z8QzBSskiHvSL+vAK22rlxDcR6KlkKdZ0 QjoGrQMdnGTPPmsVtlHLQ1mcbd+rm8KIYeYWPc1MmzqNH59+m1ozFMVxDQeolm7/ /+0+1ek1ORfB297uPiv2ek0DLoyJHuTHg4o1hPTcsrJSdkei8bKfqXlgVnvT6jmi CVWak6Rb7CC8mHovQhhQInfGDOCLCJooBCsAsywyeb6/iBjF69665h901bMDsGkr AgBVhGLwHa28J5ubVohSb1tg7/aOctt6anmUFY1SKh9H2hGwhR3s+fJUt4U32Fhq 0gyOd23dGUkYv/1G7IuMg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777501; x=1789863901; bh=T vadg5PnjaO+JyB3jIAGCIC7KUlwEu9asx5MUc98HYY=; b=W3Vq72TCPoDtcf1/9 LO/wUW7jL+c4Ugac5akCOHVcS7Fl8zRMEp42qpXrNjduFd7GQgVTO0JvAEkCtdOx B1CSZtp/90GAB70U95KD1Cp8fpOrxw947yQyGNiD517UH1mn6fRFHhdRAVY/cH3I 9aMBgD1CvE4j1OcuboSiOgsjURn8cgjbtOU138BPiXj1D62IxXR3Cm5rcFixswaY G7N6XQzJWNX5QSZSlmHCb2WUjfRt2IKyF8Pl8Az5WMzxNpXBup7Zm1K5Tx4gXDs7 HwuAt78cyl+6yyGm/4zMYe7rBddiOLhp6jZB/9KtM+DZNynC3+550dThS5xTtouA clt4Q== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMtw 2JUZNzO3XtQf+ECyivU8gCQ3mPq0O/nR21ASeZ8wiqHq4vhuDkVDXyGnAP9iZreBgRlzge o8gf5broCgxBPTKv3nrKR50uDlFFuglaz1fGUy8vzBMvhz3CZ6OSlQypTWvSZzsEiaU/4o /vqHgwJ7B9CCZK13xRRxEzM5MMMxO6H/enQdxkRnQ7uikJj4CG+itPt52BaZ36xp8454wE FCFJzVqQiitn2P2x+lWUgCwtbCLkYRMilzmjYE27ZH7R1G1AJ0EWccBAuJRREaYof+HH3Z YheCIwHzJMTP5O55u6B1tUhiw0h1XUCcf4Ec6xZVdhKuxvXf112wOlIZ0bVw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:00 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 02/19] selftests/mm: skip collapse_compound_extreme() where the PMD is too large Date: Sat, 19 Sep 2026 01:24:32 +0100 Message-ID: <20260919002451.496763-3-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" collapse_compound_extreme() builds a PTE table full of distinct PTE-mapped compound pages by cycling hpage_pmd_nr fault-time THPs through mremap. It therefore needs hpage_pmd_nr PMD-order allocations in a row. That is fine at a 2M PMD (4K base pages) or a 32M one (16K). A 512M PMD -- arm64 with 64K base pages -- makes each of those an order-13 allocation, which the allocator cannot reliably hand out even once, let alone 8192 times. The failure is not a quiet one: the case calls ksft_exit_fail_msg(), so the whole binary stops and every case after it is lost. Skip the case where the PMD is larger than 32M. The MADV_COLLAPSE cases still cover PMD-order collapse on those configurations, and 4K and 16K PMDs are unaffected. Assisted-by: LLM Acked-by: Lorenzo Stoakes (ARM) Reviewed-by: Mike Rapoport (Microsoft) Reviewed-by: Baolin Wang Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index c44bc18f7536..8a6d708026b7 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -940,6 +940,16 @@ static void collapse_compound_extreme(struct collapse_= context *c, struct mem_ops void *p; int i; =20 + /* + * This needs hpage_pmd_nr PMD-order allocations in a row, which the + * allocator will not supply if the PMD is very large. + */ + if (hpage_pmd_size > (32UL << 20)) { + ksft_test_result_skip("%s: PMD too large for fault-time THP construction= \n", + __func__); + return; + } + p =3D ops->setup_area(1); ksft_print_msg("Construct PTE page table full of different PTE-mapped com= pound pages\n"); for (i =3D 0; i < hpage_pmd_nr; i++) { --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 166ED282F3A; Sat, 19 Sep 2026 00:25:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777507; cv=none; b=rPWprj+6kgaTEmjC1MatuuAj5jUOHbUTLSnyGXbx8EWyzaPW4tthdIf8gXDdud20cdfj/vilQmvLCp0LiNWGfsmXLOE9YyC1Z9XT6L879r8vvCAgRGiSDrK5FDL50SfmWn7AvP+bw6+X+ptDe9eBgAbcJO8lvNh5wbFCaNojCwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777507; c=relaxed/simple; bh=FGJJxjxAXxiWCjd6HdT7/p3aXTUUliCrodLMid3aH30=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AcykUJp/OaW21B2V4hGRozlM+YCdlgJwCQCNROVEUtZXkiLiPMxr1Pnygsw3YLVFjpuF+bruiUS0mLtpfix+Xa9PzdkWOh2gn95EgmjMIijX3V92AFnqgsuybYCtLaGzsFtDra5KBpdaoAEb/Xw/M6lG5adaJjmI8196xufLdw4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=WD69CBLt; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=UNIpvzQ8; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="WD69CBLt"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="UNIpvzQ8" Received: from phl-compute-09.internal (phl-compute-09.internal [10.202.2.49]) by mailfhigh.phl.internal (Postfix) with ESMTP id 334BB140016D; Fri, 18 Sep 2026 20:25:04 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-09.internal (MEProxy); Fri, 18 Sep 2026 20:25:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777504; x= 1789863904; bh=bpxeXbnbOj0UDoqQAf9nzaCtUzuS3tS0/UkkxEQ26AA=; b=W D69CBLtOWCM4S7EgMjV+POR/cncBs71Ol5PFqjoveP+zL0lLDfATApzdjzXErQTv pCCdYMTcEHkLDfqG8SusK6XpnC1BJ7+mXi1dmAAd96P00qRHylj/ZdqRBS5fUoCy 9Z5kqcx1AcyXW5stzXt+O2DmT6F94UJ7IqMO8XJUCASiqfhc+itLaboOlENSqnX9 kLgNZPq/yx5S6L/DQg+MIKnCKkxnltu64Zov2nD/4kE3S0ZNu3uUMMQ868XaTCyf Rb3IUx8wo4T2hLwUYFJFDnyzU5z5snYMiGarp9+Vv5J0sGTZxbtLXSHGorLSTaVM c30x70h+MJO5GGGPT/kcw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777504; x=1789863904; bh=b pxeXbnbOj0UDoqQAf9nzaCtUzuS3tS0/UkkxEQ26AA=; b=UNIpvzQ8QvAF4nnvz n1f2aIKArJF208zrbfoFonPfqId8ELG8wNOjh9WKlkkuj9F085SzDnoO3ifiGPIY bwifGzSRFqQ2ZEA5mMn1oXCC8DwXnJ8/sbttkKG1Uuq/vueaXecxsfFWWI69pTDy Ds4hTBcw5jIVzwLHGRHwa4rrtmf107xj1NlGNauP0SJjOTvRymlrAyGQewy9ucM+ MeGzFr5k3U4ft26q6vbuuwKiINxAtcmRgSdoqSOyRzMlTtFkJ4yHfWGs1/uYVsj2 tEWuGkLlYEGpsHG9m9433p6qqq3UoTN16wnDPtKSv+OvWDwuaOQxYNRsnRlIkVoH lE0sQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMIe 80jfhDgdcpW6UhorbgwxywTZCRoFQkugBsnXE60iKAHu6CWCEz+3/Sut+Y/Bb3aLG2bIoj WvUoU6rTcFqk0WIqlh8qHR2eG0EAGRtxYfIf/ek2w0O0USb7kaH5nMk3XesCrpUjr+rmNq JER5ODHTHu47swWt67U0UUEtu2enEF/aDTyo0trZQsguHJup2ecb9W8gzFHwiuRqlva4ul y8yQ+jewxXn4ORXu1KYoK8ziKwYC8cKxWzwRpdy5Z6hYsegvHTXOX9XV3tTiZr3hu6b8hJ guYj9GBQmINoPf5hK2Mr+zb+PMNCOYxJAP0JUj8zJDLtAk0zRIBEQSMGykFQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:03 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 03/19] selftests/mm: scale khugepaged's collapse wait with the PMD size Date: Sat, 19 Sep 2026 01:24:33 +0100 Message-ID: <20260919002451.496763-4-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" wait_for_scan() gives every case the same three seconds, whatever the huge page costs to build. collapse_full() asks for four of them: 8M at a 2M PMD, but 2G at a 512M PMD -- arm64 with 64K base pages. Three seconds is thin at that size, and the case has reported a failure for a collapse that was still going. The timeout is a ceiling on a poll loop, not a sleep: the loop stops as soon as ops->check_huge() sees the collapse, or as soon as full_scans has advanced by two. Raising it costs a passing case nothing. Across 80 runs of collapse_full() on arm64 with 64K pages the wait was half a second in 73 of them, with a tail to two seconds. Keep three seconds as the floor and add a second per 128M collapsed. A 2M PMD is unchanged, so x86-64 is too; a 512M PMD gets 19 seconds. On arm64 with 64K pages a passing ./khugepaged all:anon takes 49 seconds under TCG before and after this change. Assisted-by: LLM Acked-by: Lorenzo Stoakes (ARM) Reviewed-by: Mike Rapoport (Microsoft) Reviewed-by: Baolin Wang Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 8a6d708026b7..189cc4fee18f 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -561,8 +561,11 @@ static bool wait_for_scan(const char *msg, char *p, si= ze_t len, int nr_hpages, int collap_order, struct mem_ops *ops) { unsigned long hpage_size =3D page_size << collap_order; - int full_scans; - int timeout =3D 6; /* 3 seconds */ + unsigned long bytes =3D (unsigned long)nr_hpages * hpage_size; + int timeout, full_scans; + + /* Half-second ticks: three seconds floor, plus a second per 128M */ + timeout =3D 6 + 2 * (bytes / (128UL << 20)); =20 /* Sanity check */ if (!ops->check_huge(p, len, 0, hpage_size)) --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 544772BEC52; Sat, 19 Sep 2026 00:25:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777509; cv=none; b=n+ArE4CqEfP3FQ3WrmfT9EH71idK2/QEpdtY8rUq6RtaYMFqS+G+76jdPghc3BmDYV0vAJS8zE9n3ylA6qd4+4mk2JxWI8s2Ru95tyLWKQAL2eBJJpGFaj6Pe2mmIALG/geLNMtFNZUj5M+odieVuDGEYyiaHrLXot2tGjL9f70= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777509; c=relaxed/simple; bh=r9KxW/pUOtDOKWAXtqy9E5Dqp/slGSIywK9qYd8Fz7E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ndo4RIHZ9z7erYl1eQZyxHjazAtjg13ZJ7Ky/hsmvVZiwzQa0re04UL8PLSlMPXkmAbbdZyCwxccFwNI1+Q6vZYsquP7a9UE0MgBGD3b3IqLnVSQWv3EIWIuJLihKen/hEKvgDt/O61Sa06vLUQHFppYZwCJpB1GnGwFoBAgdyg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=bmRjiuXt; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=Uwkym9r6; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="bmRjiuXt"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="Uwkym9r6" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 745F014000FE; Fri, 18 Sep 2026 20:25:06 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-05.internal (MEProxy); Fri, 18 Sep 2026 20:25:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777506; x= 1789863906; bh=O8IAR5vD5SCVxu0A7qSyVndGraz+I6DqEP+PM8vYqhw=; b=b mRjiuXtVkQEoqqZ5x10ZX0KiN0ZIkJBVsZOqKr3gZCMjKugrjhF7jhdtDD31ygAs fiZpvJuDVkg7XLTCgSDmZ0JUaSqxLsKX6p8g/6XLvvLsJjcvgljiaCPMFHoprXHC aMtJw0MqxTDEGCN5TLTBDddtVIEeJ0DcWsOkmSYgQzfD2Byx4j4jE3XOPgnuVVOB /Bh3u59fFWE3HdN7s13Gsf/GyUj2LLtCaghHeoVfK6jvz3JhhhqJkJXs4JxppDxe uicz6l8k1s/W5XjVEakg+mUgq0foZuFRN3XrFc9wgRqnLBqKFgj0gewgYoimokVP ta2wmnrWuFYWizEK1BRMw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777506; x=1789863906; bh=O 8IAR5vD5SCVxu0A7qSyVndGraz+I6DqEP+PM8vYqhw=; b=Uwkym9r6sk6LSf5y3 1OIZVjTH5YY64arTcBH5+3mB39tDcNEfwn/QbCBM2vAlTNi5NPEgzwmRLPTLNb2z IEJBUGRHxKwUD0IEIzfWUOczDGcndI6qjXytwx0wgJpEc7PGcaZTdOhcddn2Q6I0 nR3DF0LA1ksKWffVvaTrzWl3W09oF/RPmWu0BWO5+HDrQrXEfeKI4pi9SENAQ2Pm uLier1DZNO9lg0EEDS24T5EwXgGDH206Dl4Z4Mt09qB6qUrQ/AB/N6jb62PHLJWO GzkqgKq45gGbfFLY82a4s/yDkBbZQdfidBX5VYXjJCe+KiXlGI4jG10jrtiI8uYN UI6LQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMfx L1imsBc7GKPy3QB909e6AYlrfJuc9CCvY/TvwvN4F5Vf1wSeUPBayPkIcewsfuXZ//CXkK d5MzgPYuC6cU1zvr0k0SVhh5xDRsAj55w2AIO4FC+DCXwaZqtxhIKXhyU6Vth+RIi1lt1t b/LmP9emsC9mVyKTP7veK7dUgrf5UuOrk+nN78P77e3vnH5A71G4tACFpN33j9Bq0+wy9P k4L2UX9tA2sDKLLbhGYnKBZ4Vo4fkZZfoKw6CW2vEY+Bjlq+tCE2PL2skC15yAqD6v+IV1 W7217gqf/GHG4JK0cB1fGe5Elqk3Bcb3vKSm5tnwX8hqTxBqQan3Wp4AsW5A X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:05 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 04/19] selftests/mm: skip khugepaged page cache cases without a PMD folio Date: Sat, 19 Sep 2026 01:24:34 +0100 Message-ID: <20260919002451.496763-5-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" The page cache caps folio order at MAX_PAGECACHE_ORDER, which is below the PMD order on arm64 with 64K pages, where a PMD is 512M. A PMD-sized page cache folio is impossible there, so the kernel refuses these collapses: MADV_COLLAPSE answers -EINVAL and khugepaged passes over the range. Four shmem cases ask for a PMD-sized folio anyway, fail, and the run bails out in the middle. Skip the shmem and file mem types where the cap is below the PMD order. The cap is not shmem-specific: it applies to every file folio. Add thp_file_supported_orders() to read the orders the page cache allows. Anonymous collapse is unaffected: its orders are not capped this way. Assisted-by: LLM Reviewed-by: Mike Rapoport (Microsoft) Reviewed-by: Baolin Wang Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/lib/mm/hugepage_settings.h | 9 +++++++++ tools/testing/selftests/mm/khugepaged.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/tools/lib/mm/hugepage_settings.h b/tools/lib/mm/hugepage_setti= ngs.h index 548e9d288d1d..94d9fc747f49 100644 --- a/tools/lib/mm/hugepage_settings.h +++ b/tools/lib/mm/hugepage_settings.h @@ -87,6 +87,15 @@ void thp_set_read_ahead_path(char *path); unsigned long thp_supported_orders(void); unsigned long thp_shmem_supported_orders(void); =20 +/* + * The per-order shmem_enabled attribute is created for the orders the page + * cache can hold, not just for shmem, so it answers for regular files too. + */ +static inline unsigned long thp_file_supported_orders(void) +{ + return thp_shmem_supported_orders(); +} + bool thp_available(void); bool thp_is_enabled(void); =20 diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 189cc4fee18f..5318f3cfc0d0 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1358,6 +1358,25 @@ int main(int argc, char **argv) =20 setbuf(stdout, NULL); =20 + /* + * Without a PMD-order page cache folio the kernel refuses these + * collapses, so there is nothing to test. + */ + if (!(thp_file_supported_orders() & (1UL << hpage_pmd_order))) { + if (shmem_ops) { + ksft_print_msg("no PMD-order page cache folio: skipping shmem\n"); + shmem_ops =3D NULL; + } + if (read_only_file_ops) { + ksft_print_msg("no PMD-order page cache folio: skipping file\n"); + read_only_file_ops =3D NULL; + read_write_file_read_ops =3D NULL; + read_write_file_write_ops =3D NULL; + } + if (!anon_ops && !shmem_ops && !read_only_file_ops) + ksft_exit_skip("No mem_type left to run\n"); + } + default_settings.khugepaged.max_ptes_none =3D hpage_pmd_nr - 1; default_settings.khugepaged.max_ptes_swap =3D hpage_pmd_nr / 8; default_settings.khugepaged.max_ptes_shared =3D hpage_pmd_nr / 2; --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 63DCF1DF261; Sat, 19 Sep 2026 00:25:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777513; cv=none; b=t7bZqaU5wfia1Ov/RopRr40i/ehh3s431aEIJp9vna0rsZOQ0yqG07a0rZLRB3yRGbYKgzP1ReQcgxHq9Q19q/TY9QUZ8N844C9cq3snEG7TEO6eE9mQ20QY68EtKKHAiGYOCU1I2Jsz1dCIKgxGeL4nQWh1FCpZVfL7LYK/6sA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777513; c=relaxed/simple; bh=74sW+EnsmK5iOfReG2R+O+Tx+lpNiK3mfv6p06M79xA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tIbxFgcC7HIv/AqvSR3w8drQS6DIEX+QIdTjW2G0G12ApdnI/N+j55LIri+DRMkQtWKPuhY79Eb2qlQ2smqPQ5a8iMcLBJMdsJAsrBUl3Xt8XqwpyUZ/qOocRTFIojiKR7G34AJ0DrjrikEG6YR+Uf+8fD0IwXngGdS2cmfgWDw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=QK6trjxA; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=okjo/XZx; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="QK6trjxA"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="okjo/XZx" Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfout.phl.internal (Postfix) with ESMTP id 8DF9BEC01A0; Fri, 18 Sep 2026 20:25:08 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-02.internal (MEProxy); Fri, 18 Sep 2026 20:25:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777508; x= 1789863908; bh=0jxXZ932RTloRPkXJ26iTQ69+3zOv0gA9f87bGPUF1Y=; b=Q K6trjxA1vG1JZ/W8coRdqkfpWyM7J20BUChzzZo376iEalMb1/yBRYFSfm3J2MgA aKDB6+vRsZljeBE0T43fZBzaHRNG5W+HtZmx+fkJ7Fgjqka9klZPcBWAJRGUkpMN PeQbOt3Ypu/xl4uwhAMeUACvoWY5AbHzJjeNpVkEylYN1ibl/siIBK2p+7dV4OPk 1/zkUaR87Pw+ILjEK+CGAAbHfxrVJebmtBWowP7WK4zQCbdIblYHBkvVFdsLqV8i NzgQJuhLED39AR1vG8gOyOAD43cLavsqpq7HljSGwfjvzfzi7znubjoEWrjiC35t 2RN21e0qGVwglFoIJ6dHw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777508; x=1789863908; bh=0 jxXZ932RTloRPkXJ26iTQ69+3zOv0gA9f87bGPUF1Y=; b=okjo/XZxMMeDR5lHq JfCHFY+gIsfdka8yKm6PiF+WLXMeE19SdTPTAi3zxsVGH3E8EaEfzIe+8DtOpUbl qi3DUkIzZLn4ynGlpKoVRLiH/xuAOFxFVemms/k1vUZGdk26hKmk5w/nM7AhlZKU 2zSy0cgCPOpmTy7DxYg3a+dG2uYMa+fGkRq72sJ6PkJWwcLL5BCxmsyLv6oyZJcQ +LH4CXmjV6R6px7RGAYnrqRtFSxmKmmDn14cp1vflO8NVgYEzLAIOPoFoLnvnpa6 byXNIdGcV1M2VdxQaA8v4y2WG7r/RPinfRvVGhJs7jA7IIrXnhiXMhZg32uA2j/k L0bmw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMFK gChYU2BEFFB9NOF1vNFE7k40lrB57q5k5i69CWvfmdsQKgad4bHeO3w/G34aFpcNwxvZGe ufJ1PCPrsJvoR2vup6W1g+fn0IkEMfRA6RUqWDjWoOW6hqdvB3U+zwIUdoYlJhLK5arfDX LJiqlHH+P0e7oXO8WGzpoqUmdA5LXT4pc5sWKdCjE8FpUjM8z0X7M1nYUIpQEI59TyEN+D esLRpRcwcZdpOu8A47+q8O+pQykY29kuTM456oHHusrDmTikzbG9Tfbid2g5c4noHAsuOT gy89aAeKZdFV6BEEx2YfQuDRFo67aWXGhOpI0SeNlPJV9a7GzSWOMqN4rEgQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:07 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 05/19] selftests/mm: make the swap cases' swapout reliable Date: Sat, 19 Sep 2026 01:24:35 +0100 Message-ID: <20260919002451.496763-6-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" collapse_swapin_single_pte() and collapse_max_ptes_swap() swap a range out and then require smaps to report exactly the count they asked for. Two things keep that count from arriving. MADV_PAGEOUT is best effort, so the count often turns up a moment late. And wait_for_scan() leaves the range eligible for collapsing, so khugepaged is still working on it. Collapsing reads the swapped-out pages back in, so the daemon empties the swap as fast as the case fills it. On arm64 with 64K pages max_ptes_swap is 1024 pages, which is 64M a step, and the case loses the race: # Swapout 1024 of 8192 pages... Fail not ok 10 collapse_max_ptes_swap Retry for up to two seconds, holding the range out of khugepaged's reach meanwhile. The collapse each case runs next restores MADV_HUGEPAGE, so only the setup is affected. If the pages still won't swap out, skip: no swap, swap too small or full, a memcg cap or busy writeback. None of that is a kernel bug. Assisted-by: LLM Reviewed-by: Muhammad Usama Anjum Reviewed-by: Baolin Wang Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged.c | 41 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 5318f3cfc0d0..13a2a47ab110 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -221,6 +221,29 @@ static bool check_swap(void *addr, unsigned long size) return swap; } =20 +static bool swapout_range(void *p, unsigned long size) +{ + int i; + + /* keep khugepaged from collapsing the range and swapping it back in */ + if (madvise(p, size, MADV_NOHUGEPAGE)) + ksft_exit_fail_perror("madvise(MADV_NOHUGEPAGE)"); + + /* + * Retry several times because MADV_PAGEOUT is best effort. Sleep + * between the retries to give outstanding writeback a chance to + * finish. + */ + for (i =3D 0; i < 40; i++) { + if (madvise(p, size, MADV_PAGEOUT)) + ksft_exit_fail_perror("madvise(MADV_PAGEOUT)"); + if (check_swap(p, size)) + return true; + usleep(50 * 1000); + } + return false; +} + static void *alloc_mapping(int nr) { void *p; @@ -828,12 +851,10 @@ static void collapse_swapin_single_pte(struct collaps= e_context *c, struct mem_op ops->fault(p, 0, hpage_pmd_size); =20 ksft_print_msg("Swapout one page..."); - if (madvise(p, page_size, MADV_PAGEOUT)) - ksft_exit_fail_perror("madvise(MADV_PAGEOUT)"); - if (check_swap(p, page_size)) { + if (swapout_range(p, page_size)) { success("OK"); } else { - fail("Fail"); + skip("Could not swap out"); goto out; } =20 @@ -854,12 +875,10 @@ static void collapse_max_ptes_swap(struct collapse_co= ntext *c, struct mem_ops *o ops->fault(p, 0, hpage_pmd_size); =20 ksft_print_msg("Swapout %d of %d pages...", max_ptes_swap + 1, hpage_pmd_= nr); - if (madvise(p, (max_ptes_swap + 1) * page_size, MADV_PAGEOUT)) - ksft_exit_fail_perror("madvise(MADV_PAGEOUT)"); - if (check_swap(p, (max_ptes_swap + 1) * page_size)) { + if (swapout_range(p, (max_ptes_swap + 1) * page_size)) { success("OK"); } else { - fail("Fail"); + skip("Could not swap out"); goto out; } =20 @@ -871,12 +890,10 @@ static void collapse_max_ptes_swap(struct collapse_co= ntext *c, struct mem_ops *o ops->fault(p, 0, hpage_pmd_size); ksft_print_msg("Swapout %d of %d pages...", max_ptes_swap, hpage_pmd_nr); - if (madvise(p, max_ptes_swap * page_size, MADV_PAGEOUT)) - ksft_exit_fail_perror("madvise(MADV_PAGEOUT)"); - if (check_swap(p, max_ptes_swap * page_size)) { + if (swapout_range(p, max_ptes_swap * page_size)) { success("OK"); } else { - fail("Fail"); + skip("Could not swap out"); goto out; } =20 --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 587C319CCF5; Sat, 19 Sep 2026 00:25:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777512; cv=none; b=cHEjccnArlEJCv7d7DDHmm9sPLlHzNz19c8JJRai4N00+LgoO8pBPRcTEC/wJi8XEpis0zCuHsZ1IGDdA5Xc+d9Pj2nCK9W/8v9rhBVGq9eVkYntqul9JFbb0qkViCsT0cR7StUvAHsP/uygE046CoBwHYeydAF7bbLMfD1UGiY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777512; c=relaxed/simple; bh=tPUBhNQDaq/WkUUh616Zvkdkhdecru468dYEpcqn9aA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Yf2sY+GtDGxuFNFanAsmdNo9glAZtdHY7XJO8gdicPncaYryaFFt4NKi92Z6b5qKZ/AjWkvZnzmCYNpG0QfILmMpU/EcwBHAoJUjkTDsNhhM0QLhJgEmjfAb/jZnqTdwXPFtaD8WCX4Cn5mkP0QMbFslSuUAJZJXQ1EcM969Go8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=fpvhKEOs; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=p0fdNOtV; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="fpvhKEOs"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="p0fdNOtV" Received: from phl-compute-08.internal (phl-compute-08.internal [10.202.2.48]) by mailfout.phl.internal (Postfix) with ESMTP id 8DEA0EC020B; Fri, 18 Sep 2026 20:25:10 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-08.internal (MEProxy); Fri, 18 Sep 2026 20:25:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777510; x= 1789863910; bh=b2EjQwNXVZ3kBO5GV05H9uox01LTGQvy8R6+J7n+hI4=; b=f pvhKEOsnferr1TcELH0ZjHcmCKDsp7M8cEp+bv8VH9TaXB4Q6Tj9YXYl1dszTn+7 rxHRsHxJ8fNyPWLxwLum+AqjSh3tgoJrgTVzEIAykBkoVGaailLTL8ygdCXx/UZ7 BN51HOu5z68vqOQkpwRaCR0j3hORXzfVbVWEPj0eupXkDpLy6NeouvFmLzqrbD0r hFtzLQwSfxyHYFptCfkkTOAmm6tKDUF0tPzH1kbIJflo5yuOzMds+U6yOp0+xSGU dLdOtF+ICdTZ6uV2QSBTH8i5IbCjwL+BSEoXeUDNDGngrlp7+/VJ9iFsXw3tHGB+ GGjDuIj1IQBVnDXxx7e6Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777510; x=1789863910; bh=b 2EjQwNXVZ3kBO5GV05H9uox01LTGQvy8R6+J7n+hI4=; b=p0fdNOtVkteZenxx4 RX5+fgb+XldF8DelrvXyps4ZtW4VieNLSFaGzQvs6PLCvkzMu77mx2PjWDDcsrTX zTIdHZm14LkhWgQDeXtAScOkJ8gmwKyTazcBxOIT7Z6k+522EbuKcoNDmmgzcxQ2 nkvATOnpkaEQc8rJmfwMXbcdXWnYvLppXcND83MquDgU0N43HiT+PDoD0NdU3hwe a0cUihwsDoYmaeUnGEFJPh8L23idDawphD+TsrO2Xj3UdeQlCfv0RgJPFK3DtOsB pEUCFfqoiqdj4BYrfPwrADQkJTtEgqnFDz5lZH4D3CpeWDRxnD4+13f7o5A48oEW kmZIQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIME9 uYZjolEHn+PrRoQ3gunGcY531LB4NKn1ulXhKnB5hZbu6jfSqL52hNw5Bm8YaKVHImFX6k rbx7VgDsl19eZrOCN4Cwjvh91Nb4WjXuHc7NwO7T5rJVZIe46Rh4+fKpySSYCzxgBSy4u6 hkX2g1jivopcIqWvY9jGMPyiTIi+P8huS8YKqMencvrUzsfbh56N9KA4/STLlqbRNMS9O7 GoFIdDj9oeN/IqIfInOTzomBVdLdnoyOgH5gDMC1pG74PfzGdZnyTT0fAO0UEfFGhUWMVO AjI46RulfUP6t4T5EQdNms9qaQ2CbM94ZQnCAjNGmWd3cMbGrifAEvJQeQVA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:09 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 06/19] selftests/mm: stop khugepaged during the MADV_COLLAPSE cases Date: Sat, 19 Sep 2026 01:24:36 +0100 Message-ID: <20260919002451.496763-7-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" __madvise_collapse() turns THP off before each MADV_COLLAPSE, both to keep khugepaged out of the range and to prove MADV_COLLAPSE ignores the setting. It clears the global controls only, which is no longer enough. A per-order control overrides them, and -s, which makes the cases fault in folios of one order, leaves that order's control at "always". khugepaged then collapses the very range the case is working on, and the case fails on a collapse that was interfered with rather than refused. Clear the per-order controls too. MADV_COLLAPSE does not consult them: anon never did, and shmem stopped with "mm: shmem: ignore sysfs configs for shmem forced collapse". Fixes: b7f16963efe7 ("mm/khugepaged: run khugepaged for all orders") Assisted-by: LLM Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- tools/testing/selftests/mm/khugepaged.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 13a2a47ab110..e013eebc7136 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -538,8 +538,8 @@ static bool is_anon(struct mem_ops *ops) static void __madvise_collapse(const char *msg, char *p, int nr_hpages, struct mem_ops *ops, bool expect) { - int ret; struct thp_settings settings =3D *thp_current_settings(); + int ret, i; =20 ksft_print_msg("%s...", msg); =20 @@ -555,6 +555,10 @@ static void __madvise_collapse(const char *msg, char *= p, int nr_hpages, */ settings.thp_enabled =3D THP_NEVER; settings.shmem_enabled =3D SHMEM_NEVER; + for (i =3D 0; i < NR_ORDERS; i++) { + settings.hugepages[i].enabled =3D THP_NEVER; + settings.shmem_hugepages[i].enabled =3D SHMEM_NEVER; + } thp_push_settings(&settings); =20 /* Clear VM_NOHUGEPAGE */ --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 8BE572DB789; Sat, 19 Sep 2026 00:25:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777515; cv=none; b=YA/xrMBEvnuRAyrxjkOtlpqfEqWucBCpXD7RTC16lydFwJFK4x+/UIytisUXsfuw9LRct5obJ+vMJD+2BxCJ6tRCWm4/aAi7J4qPOBk68tkaYaBCsxH7ddGX9xXstBH0QXg5flLTnZfwtm7Rxyc9fSB6W/tGNQEd26LvqfRtCQU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777515; c=relaxed/simple; bh=36dbQvhiQV0zFlNjYIAZbcxcfSfThnt1hKEK6mMHXm0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XAM7TuTZAlOLAhMw1AFZLbPeUasfzh9jZev4pBhkTG1sQKBbd13i3UykYivdipenZZr2kWifrT002CPyo0l6CzZeY4x8Gue2a/SWu60okROn1qRA9HOVf8VacxYMtsQfjrq80HlssNMBXNAqY1ClR6A0vQAL0+5wA9o1NY4BuRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=dzcUVM1Z; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=OAtfrkZO; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="dzcUVM1Z"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="OAtfrkZO" Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id AE46BEC0232; Fri, 18 Sep 2026 20:25:12 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-01.internal (MEProxy); Fri, 18 Sep 2026 20:25:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777512; x= 1789863912; bh=E20qks4EGRXlLr5iwwk3xar+b94xA/2CHubWgJ4qnkI=; b=d zcUVM1Zub0MueH1wRB6cZbScLWZsIjm0WsCXCmlW65fcbX3MDA1WcsrjsQCHXFas 1UXuuGhUBJcBgg68DJy2MHUi68VLZA0fjqHRZ3c1w+akUpK7iYkmIZDU597p2GIC BC7fRP4YbfGG10J0VCMwRp887LsAH/+tBc9F7+loTw2jgRQqxgRKKoHeWS1I9TyI E3p1e/cmaNuoLf3z+parbFJS5LaIVXprQtm2jCgesrPjPsErl/hPkIdLqnSEbvle VFWufWVEqWK+OPl3eBZ0xpZco/4iXBxSvgfFF/TDgvG8wfEKRV+RnDBijYaEq/WH Ge+nPuFx4KJ/8HvFMlxGQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777512; x=1789863912; bh=E 20qks4EGRXlLr5iwwk3xar+b94xA/2CHubWgJ4qnkI=; b=OAtfrkZOIBPmRkb6u zmmiAT0WXBX0k6glN1ORs9tpqV7JoeCnkmND+oXdLCNcDStC9HJzAjL+PloWSoZe Nx2ffaaVrBCPEXZFYQGwY76Hc707EDcEy8dtDSBLZSjgSGeI1R7HS8EhfIxlDv3c N1+2p3VTSzMsDvIDAZi/KAVOb5SVh3Zu1Zk9dKkhuLHvBXE/fyj8ICvOtFhRuqTM 68v5f4S5Lr9A7AhlyTpDYWTJKpiXYTVDj5tI+jHBM4TbBTInsAn6NRjRc4R7DfZv 8E7F2SBim/TXwNc+Emt76W65rDU/i0PuhOjowLdku97OAb/wkfpR0bIX5Rfuiko0 0TraA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMpb L5ESyndOi5bpaoFBmYeOsEvwEeyOHIUd7LfqffZ1zJn/8T6rxqqLc5X+pIl0tLpk/I/6lI /m45Kkjv6LalblttsA9sVVkWfW66qntLgNMH+qJw1GNJLP4FWUOa1W8xhs7TwkJFRw4FTH y+wT+BZuEF+uA2L7okyeFi3weDYxSq6LAiBZLt+3uD+C0GGXGaCMA8qHFifjwmTCNGcw6C 7DP3l6YC/8NPz72pHkfr1IAbIxWRIGx+Uc+g2wFMtzscVj8gpIsVDAdGm8YUYEyZiLpZos lrS40yPVOEWU/+6cprb6tzvgBFdWbi8bVY0ROLUzRB+i4cuDKvn1etqkrH7Q X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:11 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 07/19] selftests/mm: move is_backed_by_folio() into vm_util Date: Sat, 19 Sep 2026 01:24:37 +0100 Message-ID: <20260919002451.496763-8-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" Checking that an address range is backed by a folio of a given order is useful to any test that builds or collapses large folios. mTHP collapse coverage in the khugepaged selftest needs exactly that. split_huge_page_test.c already has the building block: is_backed_by_folio() reads the compound head and tail flags from /proc/kpageflags to classify the folio behind a page. Move it into vm_util so other tests can use it. No functional change. Assisted-by: LLM Acked-by: Mike Rapoport (Microsoft) Acked-by: Lorenzo Stoakes (ARM) Reviewed-by: Baolin Wang Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- .../selftests/mm/split_huge_page_test.c | 61 ------------------- tools/testing/selftests/mm/vm_util.c | 61 +++++++++++++++++++ tools/testing/selftests/mm/vm_util.h | 2 + 3 files changed, 63 insertions(+), 61 deletions(-) diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/test= ing/selftests/mm/split_huge_page_test.c index 68f508c9a355..c5d96a4b1db3 100644 --- a/tools/testing/selftests/mm/split_huge_page_test.c +++ b/tools/testing/selftests/mm/split_huge_page_test.c @@ -41,67 +41,6 @@ const char *kpageflags_proc =3D "/proc/kpageflags"; int pagemap_fd; int kpageflags_fd; =20 -static bool is_backed_by_folio(char *vaddr, int order, int pagemap_fd, - int kpageflags_fd) -{ - const uint64_t folio_head_flags =3D KPF_THP | KPF_COMPOUND_HEAD; - const uint64_t folio_tail_flags =3D KPF_THP | KPF_COMPOUND_TAIL; - const unsigned long nr_pages =3D 1UL << order; - unsigned long pfn_head; - uint64_t pfn_flags; - unsigned long pfn; - unsigned long i; - - pfn =3D pagemap_get_pfn(pagemap_fd, vaddr); - - /* non present page */ - if (pfn =3D=3D -1UL) - return false; - - if (pageflags_get(pfn, kpageflags_fd, &pfn_flags)) - goto fail; - - /* check for order-0 pages */ - if (!order) { - if (pfn_flags & (folio_head_flags | folio_tail_flags)) - return false; - return true; - } - - /* non THP folio */ - if (!(pfn_flags & KPF_THP)) - return false; - - pfn_head =3D pfn & ~(nr_pages - 1); - - if (pageflags_get(pfn_head, kpageflags_fd, &pfn_flags)) - goto fail; - - /* head PFN has no compound_head flag set */ - if ((pfn_flags & folio_head_flags) !=3D folio_head_flags) - return false; - - /* check all tail PFN flags */ - for (i =3D 1; i < nr_pages; i++) { - if (pageflags_get(pfn_head + i, kpageflags_fd, &pfn_flags)) - goto fail; - if ((pfn_flags & folio_tail_flags) !=3D folio_tail_flags) - return false; - } - - /* - * check the PFN after this folio, but if its flags cannot be obtained, - * assume this folio has the expected order - */ - if (pageflags_get(pfn_head + nr_pages, kpageflags_fd, &pfn_flags)) - return true; - - /* If we find another tail page, then the folio is larger. */ - return (pfn_flags & folio_tail_flags) !=3D folio_tail_flags; -fail: - ksft_exit_fail_msg("Failed to get folio info\n"); -} - static int check_after_split_folio_orders(char *vaddr_start, size_t len, int pagemap_fd, int kpageflags_fd, int orders[], int nr_orders) { diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests= /mm/vm_util.c index 4751db798c3a..cc5dfd1e6c94 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -494,6 +494,67 @@ int pageflags_get(unsigned long pfn, int kpageflags_fd= , uint64_t *flags) return 0; } =20 +bool is_backed_by_folio(char *vaddr, int order, int pagemap_fd, + int kpageflags_fd) +{ + const uint64_t folio_head_flags =3D KPF_THP | KPF_COMPOUND_HEAD; + const uint64_t folio_tail_flags =3D KPF_THP | KPF_COMPOUND_TAIL; + const unsigned long nr_pages =3D 1UL << order; + unsigned long pfn_head; + uint64_t pfn_flags; + unsigned long pfn; + unsigned long i; + + pfn =3D pagemap_get_pfn(pagemap_fd, vaddr); + + /* non present page */ + if (pfn =3D=3D -1UL) + return false; + + if (pageflags_get(pfn, kpageflags_fd, &pfn_flags)) + goto fail; + + /* check for order-0 pages */ + if (!order) { + if (pfn_flags & (folio_head_flags | folio_tail_flags)) + return false; + return true; + } + + /* non THP folio */ + if (!(pfn_flags & KPF_THP)) + return false; + + pfn_head =3D pfn & ~(nr_pages - 1); + + if (pageflags_get(pfn_head, kpageflags_fd, &pfn_flags)) + goto fail; + + /* head PFN has no compound_head flag set */ + if ((pfn_flags & folio_head_flags) !=3D folio_head_flags) + return false; + + /* check all tail PFN flags */ + for (i =3D 1; i < nr_pages; i++) { + if (pageflags_get(pfn_head + i, kpageflags_fd, &pfn_flags)) + goto fail; + if ((pfn_flags & folio_tail_flags) !=3D folio_tail_flags) + return false; + } + + /* + * check the PFN after this folio, but if its flags cannot be obtained, + * assume this folio has the expected order + */ + if (pageflags_get(pfn_head + nr_pages, kpageflags_fd, &pfn_flags)) + return true; + + /* If we find another tail page, then the folio is larger. */ + return (pfn_flags & folio_tail_flags) !=3D folio_tail_flags; +fail: + ksft_exit_fail_msg("Failed to get folio info\n"); +} + /* If `ioctls' non-NULL, the allowed ioctls will be returned into the var = */ int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len, bool miss, bool wp, bool minor, uint64_t *ioctls) diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests= /mm/vm_util.h index 64a86e8a0c41..f12979a70135 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -99,6 +99,8 @@ int64_t allocate_transhuge(void *ptr, int pagemap_fd); int pageflags_get(unsigned long pfn, int kpageflags_fd, uint64_t *flags); int gather_folio_orders(char *vaddr_start, size_t len, int pagemap_fd, int kpageflags_fd, int orders[], int nr_orders); +bool is_backed_by_folio(char *vaddr, int order, int pagemap_fd, + int kpageflags_fd); =20 int uffd_register(int uffd, void *addr, uint64_t len, bool miss, bool wp, bool minor); --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 4CC492D7DE9; Sat, 19 Sep 2026 00:25:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777519; cv=none; b=KUZP+CUhMGW1KZuVBkniws0zcKiUFyjAo0/YGf5LKHBbsmjpcxs10o0hQsFn+P0k/SK1rjike4ghXB7hnfenDrL5zcVuJfMd/ukbWM5z27cU/OP4kOdCV5zQ4tmLQi9v8NwyHUQ6bh4ZwMcCUnJVmC1Z2GsTlIudLvWWpDMOw4w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777519; c=relaxed/simple; bh=gJHEmF7xCwqYHMp7G/UtGzV2/FEIiJe92/thvIsw6wY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pr6DkFcGl2ZUUVf3dp5mGW5ltPX5C8FKCVgF4UMRM/PRMAupwktizwhC+B4XYp72LiMXtLoP4pZrQAwAE2MsoFJVh8bT/vp6NxKj25U/4KvO4DZq+Yj4DHQX0YvbrWFPMLP3q6RJYvVr3G+sGHs5kFqBjBpVRTqaefAeL5zZ0mk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=QwotEtql; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=pd4ebgcr; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="QwotEtql"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="pd4ebgcr" Received: from phl-compute-09.internal (phl-compute-09.internal [10.202.2.49]) by mailfout.phl.internal (Postfix) with ESMTP id 62F40EC01A0; Fri, 18 Sep 2026 20:25:14 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-09.internal (MEProxy); Fri, 18 Sep 2026 20:25:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777514; x= 1789863914; bh=r5nTkTHjVvMlyFTA7E1YaHuqOSpZFDKLhDsNT7zZVk4=; b=Q wotEtqlZ0AxHw8nD1qvwn+xUskD7FqxxJ5G5WbdDPSvVhIODO1ylw2Of7xnF4gz4 FdgWnoGi0829zhFZMehVtg0hlnybpRjfqhgbdg0lHxrLBFcN/Yo0U80gEYvqCGqA pMRILwvlMkB1sbutBq/O9c2fpPiF/mdLnkkdnbCv4HTf+hzx/oIF1qQnPoyHLSl6 HkBAfWLk0WpqJFJaoCWOmnVrOXRlf1u56S5Paj2KOTcVQLpqi2Y1kMfFLnJDEl7K JHMKN0G6FXtSZPqFeLdhPHKYqCjOCg8EUv5zzV6WvhGsDK5EzbaM+RpT6OwVPK2R +YALW5APEDFLUlZljiKbQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777514; x=1789863914; bh=r 5nTkTHjVvMlyFTA7E1YaHuqOSpZFDKLhDsNT7zZVk4=; b=pd4ebgcrEe4MB+KtT StrwrRvM+97GB0qHUIozEgo/p23VongCb5EfL/kL0fPvRti81YsdQPgfj5dDjtvu Qyj03KKp/jSHw9g6CFnCstVbqe0lN1aeifxBARqFna1y7DWqeUnrwmYmDUy7ACas uGKgpc/kuEjF5K52ySRJk9KYbUVVZ1X0JxJ6NlD7uQWahueF8o2+sYvfuJcdTsVc NGfbOD/WC5wcplO3JggmIyinvnuuV2aqVq5PGBOugv8Bs6oYSPwLsz1KLKfTNUlQ 1SAcrIguzYS9Rp6mABesd8wPeIgS9xdy32PBD8BIsn2Sk9SkaLGk2kI0jAQZYdl+ /3ILg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEzseHgHAxanvosBbYuJPOsY+n0X5UbYs0PPazNY//kQZ3NkUWvwvZaeFG4K6MaM1 51QpOH4aelOmHBptEhruNIkMmEsuOQeZbGrvL7mQj2kdmmCNYrJ7V/Gxu8ar4BzJpo5rV7 vKP2ia7U0+Vm59vAPsz2JcwivFHP+0OmSoqV+JfA3yKlcOkTPrhdGkX4AgOHLm4XJUt5mM HeqMESXl6ibr/xrgjBd4IZM9oAbU6DWk9Q3+fqdUek4rHv8tNSmXbmq+2iLXuPMZjgN42W gGRNasGU39A5UL6wnmEy31YC46agADHTZYQX6KPmc3+B0CXfmIhRtSns1d+buSvmpYlDBj Riz3LPJ5ewmbfFS034Junho+nA59C2QdPnd8vA078CVbfnIVBuVyeZunIF1BdFpJy+o2iN 5vZCICEeIFyBnK4XAtYqzjAbdcsq9wu34gWczIkUsEAsprD6tQ8OD8MOQgcBf0ywWXKXFI 27xd1zREAGJOHifR7SJSbs+DiSkzcOQ8yzDWYHidssHN8IjIbQEtXt1mZ5nMsnBoj8dzhf XF1JaGZj3WlcgrIXMSPvCcH52rugKrlwp2TQWMwgehKsP/lB9bPQ7en5g+Lg7wt1jbjF/H R5WQnK3fOt+WAqCb1/7XU80vMXxm1AXpyucuzzd4PMOSSe2FT3Iv3q0CecqA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:13 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 08/19] selftests/mm: add folio-order check for address ranges Date: Sat, 19 Sep 2026 01:24:38 +0100 Message-ID: <20260919002451.496763-9-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" An mTHP collapse test needs to know that a range is backed by folios of the target order, and that they sit where a collapse would put them. Nothing answers both: is_backed_by_folio() classifies the folio behind a single page, and check_huge_anon() counts the folios of an order in a range without saying where they start. Add is_range_backed_by_order(). It requires every folio-sized, folio- aligned part of the range to map one folio of that order, head to tail, with the head at the start of the part. A part backed by two smaller folios fails, and so does a folio mapped off its natural alignment. The mTHP cases need both to tell a collapsed range from the one beside it. Assisted-by: LLM Reviewed-by: Mike Rapoport (Microsoft) Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/vm_util.c | 47 ++++++++++++++++++++++++++++ tools/testing/selftests/mm/vm_util.h | 2 ++ 2 files changed, 49 insertions(+) diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests= /mm/vm_util.c index cc5dfd1e6c94..c8c5cd8ab6c1 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -555,6 +555,53 @@ bool is_backed_by_folio(char *vaddr, int order, int pa= gemap_fd, ksft_exit_fail_msg("Failed to get folio info\n"); } =20 +/** + * is_range_backed_by_order() - check that a range is backed by @order fol= ios + * @start: start of the range, a multiple of the folio size + * @len: length of the range in bytes, a multiple of the folio size + * @order: the folio order to check for + * @pagemap_fd: open /proc//pagemap of the range's owner + * @kpageflags_fd: open /proc/kpageflags + * + * Every folio-sized, folio-aligned part of the range must map one folio of + * @order, head to tail, with the head at the start of the part. A part + * backed by several smaller folios fails, and so does a folio mapped off + * its natural alignment. + * + * Returns: true if the whole range is backed that way, false otherwise. + */ +bool is_range_backed_by_order(char *start, size_t len, int order, + int pagemap_fd, int kpageflags_fd) +{ + const unsigned long nr_pages =3D 1UL << order; + const size_t folio_size =3D nr_pages * psize(); + char *vaddr; + + if ((uintptr_t)start % folio_size || len % folio_size) + return false; + + for (vaddr =3D start; vaddr < start + len; vaddr +=3D folio_size) { + const unsigned long pfn =3D pagemap_get_pfn(pagemap_fd, vaddr); + unsigned long i; + + /* Not present, or a tail page */ + if (pfn =3D=3D -1UL || pfn % nr_pages) + return false; + + for (i =3D 1; i < nr_pages; i++) { + char *page =3D vaddr + i * psize(); + + if (pagemap_get_pfn(pagemap_fd, page) !=3D pfn + i) + return false; + } + + if (!is_backed_by_folio(vaddr, order, pagemap_fd, kpageflags_fd)) + return false; + } + + return true; +} + /* If `ioctls' non-NULL, the allowed ioctls will be returned into the var = */ int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len, bool miss, bool wp, bool minor, uint64_t *ioctls) diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests= /mm/vm_util.h index f12979a70135..0172003c16dc 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -101,6 +101,8 @@ int gather_folio_orders(char *vaddr_start, size_t len, int pagemap_fd, int kpageflags_fd, int orders[], int nr_orders); bool is_backed_by_folio(char *vaddr, int order, int pagemap_fd, int kpageflags_fd); +bool is_range_backed_by_order(char *start, size_t len, int order, + int pagemap_fd, int kpageflags_fd); =20 int uffd_register(int uffd, void *addr, uint64_t len, bool miss, bool wp, bool minor); --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 E55902D7D3A; Sat, 19 Sep 2026 00:25:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777519; cv=none; b=KB8wh026fg7//hIZKEJ15ChB6IooL8SrAyT50LAP+P/CIXtxpKf5pRoSs4qxQ4qqbwQu9hQR1CdDcEoG5sgM+Wt5ssZoOsBZGffsw3lMTvaRbvWrmSX1P4InChfGP51TCgkFRrUY52LTTb/YdF2kyFzJorGHuZ7JZG6Ha8UlLoc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777519; c=relaxed/simple; bh=0tegOHLpniAeeRORXRa+2CjcFl6T3I2FlKK8XChS9NA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=q54SU+9a/3eM1epon1XKUyIWLZ+aRpE5U17ZBEk8ZMt0GTmdb+d+a1ZfjnmxU7S4HILvSKd0/REUKLvEi4H9A54+sQgOaBVx8nMuK7eTyioh//Zq79T3Kau+hx06Rnndb+s1FgjYEXSl1lxi0Rf+jWJqSPQ/lM0ZFm26AwvVjc4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=He0n/kbf; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=cegSi7EI; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="He0n/kbf"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="cegSi7EI" Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfhigh.phl.internal (Postfix) with ESMTP id 188E51400165; Fri, 18 Sep 2026 20:25:16 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-02.internal (MEProxy); Fri, 18 Sep 2026 20:25:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777516; x= 1789863916; bh=JoUp1yN/qSNv1NBhj8IRdHW8JRjYh6PqAm057ehiBQc=; b=H e0n/kbfBbLnAEMjZSRXH0qlyrKZwW8xWxZ8J27bU1OkkXMqKMCjh40M+KE3KTGhR LKN2tWeD4BPhs1EsM/i3sXXxIEjH50QNuQyRZwxB4/CylPilQVrCMQ5ZVo+x7dt2 QjY4J13QH+fVczJPjPpODHABUB9NhvSW1ZOoSHZ6Lf+xNPQ4XSHYKvt0ILLw7RTe SsAi/+2SfeOCU/muer/wI9Pha88pKR31AJ1Q+DmQmpWvuBMVTEgNDO5FEdwKyH8P QwTJ+PVoPIw59K/HAxYaXgP8GbvgPiZ348v8eMlbLZ4Xtcea5O25JSd1KIy2XYUT q50t89Tc0Qk05C1O/mazg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777516; x=1789863916; bh=J oUp1yN/qSNv1NBhj8IRdHW8JRjYh6PqAm057ehiBQc=; b=cegSi7EIBCDaGg6qY D6hu56p/UR3ekYX+I+xqQ0MdjtS+vDalshkbX89eq61EvugLKknY/lPLK2hKbLyl k6sG9oNjZX4Y5H6SOe2+Bn+dhYTp6S+P7xlxwWxoa1/ZekVacO6xdj3s0WGUAnxo o5CmmpHcATnFbteaCPMrfqtzkAWGWQa5v4P/Etfjw2fvD4ejElQeqnrPzUfdoiaz gogW9XX6GTWHUr063uoKl9K9o6tdf7VPN5CLHBeXnPH0nRwsgJJYDyxWqrwMyxwd V9QUzAlFLy5L9pk4WC1SVjRCtBfFQIQJjDGEOe6SKmemB2QEJSU5EYGBwDIbhM4u pdLZQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEzseHgHAxanvosBbYuJPOsY+n0X5UbYs0PPazNY//kQZ3NkUWvwvZaeFG4K6MaM1 51QpOH4aelOmHBptEhruNIkMmEsuOQeZbGrvL7mQj2kdmmCNYrJ7V/Gxu8ar4BzJpo5rV7 vKP2ia7U0+Vm59vAPsz2JcwivFHP+0OmSoqV+JfA3yKlcOkTPrhdGkX4AgOHLm4XJUt5mM HeqMESXl6ibr/xrgjBd4IZM9oAbU6DWk9Q3+fqdUek4rHv8tNSmXbmq+2iLXuPMZjgN42W gGRNasGU39A5UL6wnmEy31YC46agADHTZYQX6KPmc3+B0CXfmIhRtSns1d+buSvmpYlDQ1 Nct0DJqYbFtgMLBwl0Mgq8h4lDVNt7z5slUUQuGUTarwDhgKg0aPdeteZazVyMm9CiA4mk tE4dt4mV9xRAYcebFPnbh8QDNGw9dlzxhAqpOEdyHhcfRGPnnU9J6vEXGzPPGEtJRINDqC MjmY0ZAinZrxX+DA8VHF13sgIl3c28QFzc0fO2nrcVUB7C30VnGnNGH6pB8T1shIN2dixa AyGX6eUBscu1tbWunQ8qNN81NNYQS6loqJbBKGnbLJrSZ8Pb+V8ikSaAGT6fHT5xBkC0Wf tamYsYP4AZSmYN4GLK5UiKP4j1tfXqC8iPxzBE74LuMSImTM2UI+wyyTitpw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:15 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 09/19] selftests/mm: add folio-order detection self-check Date: Sat, 19 Sep 2026 01:24:39 +0100 Message-ID: <20260919002451.496763-10-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" The khugepaged mTHP tests detect collapse results with the vm_util folio-order helpers rather than smaps AnonHugePages, which only sees PMD mappings. If those helpers are wrong, every case built on them is wrong the same way, and nothing says so. Check them directly. For every anon THP order the kernel supports, fault memory in with only that order enabled. Require the helpers to classify the backing as exactly that order: not the order below it, and base-page memory as order 0. Run it in the thp category, ahead of ./khugepaged, so a broken helper is reported as itself rather than as a collapse failure. Verified on x86-64 4K (orders 0, 2-9) and arm64 64K (orders 0, 2-13). The test needs ALIGN(), which hmm-tests.c and migration.c each defined privately. Move it to vm_util.h and drop both copies. Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/Makefile | 1 + .../testing/selftests/mm/folio_order_check.c | 122 ++++++++++++++++++ tools/testing/selftests/mm/hmm-tests.c | 1 - tools/testing/selftests/mm/migration.c | 1 - tools/testing/selftests/mm/run_vmtests.sh | 2 + tools/testing/selftests/mm/vm_util.h | 2 + 6 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/mm/folio_order_check.c diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/= mm/Makefile index 7d69baeb93f4..cb32cf5d867e 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -105,6 +105,7 @@ TEST_GEN_FILES +=3D guard-regions TEST_GEN_FILES +=3D merge TEST_GEN_FILES +=3D rmap TEST_GEN_FILES +=3D folio_split_race_test +TEST_GEN_FILES +=3D folio_order_check TEST_GEN_FILES +=3D soft-dirty =20 ifeq ($(ARCH),x86_64) diff --git a/tools/testing/selftests/mm/folio_order_check.c b/tools/testing= /selftests/mm/folio_order_check.c new file mode 100644 index 000000000000..5eafbcc1b4f3 --- /dev/null +++ b/tools/testing/selftests/mm/folio_order_check.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Self-check for the vm_util folio-order helpers, is_backed_by_folio() and + * is_range_backed_by_order(), which the khugepaged mTHP cases use to dete= ct + * collapse results. For every anon THP order the kernel supports, fault + * memory in with only that order enabled and require the helpers to report + * exactly that order. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include "kselftest.h" +#include "vm_util.h" +#include + +static int pagemap_fd; +static int kpageflags_fd; + +static char *alloc_aligned(size_t size) +{ + size_t len =3D size * 2; + char *p, *aligned; + + p =3D mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (p =3D=3D MAP_FAILED) + ksft_exit_fail_perror("mmap()"); + + aligned =3D (char *)ALIGN((uintptr_t)p, size); + if (aligned !=3D p) + munmap(p, aligned - p); + if (aligned + size !=3D p + len) + munmap(aligned + size, p + len - aligned - size); + + return aligned; +} + +static void check_order(int order) +{ + struct thp_settings settings =3D *thp_current_settings(); + size_t size =3D psize() << order; + bool ok =3D true; + char *p; + int i; + + for (i =3D 0; i < NR_ORDERS; i++) + settings.hugepages[i].enabled =3D THP_NEVER; + if (order) + settings.hugepages[order].enabled =3D THP_ALWAYS; + thp_push_settings(&settings); + + p =3D alloc_aligned(size); + *p =3D 1; + + if (!is_range_backed_by_order(p, size, order, pagemap_fd, kpageflags_fd))= { + ksft_print_msg("order %d not detected after fault\n", order); + ok =3D false; + } + + /* A lower order must be rejected: the folio is larger */ + if (order && is_range_backed_by_order(p, size, order - 1, + pagemap_fd, kpageflags_fd)) { + ksft_print_msg("order %d also reported as order %d\n", + order, order - 1); + ok =3D false; + } + + /* A large folio must not pass as order 0 */ + if (order && is_range_backed_by_order(p, size, 0, + pagemap_fd, kpageflags_fd)) { + ksft_print_msg("order %d also reported as order 0\n", order); + ok =3D false; + } + + munmap(p, size); + thp_pop_settings(); + + ksft_test_result(ok, "order %d classified\n", order); +} + +int main(void) +{ + struct thp_settings settings; + unsigned long orders; + int order; + + ksft_print_header(); + + if (!thp_available()) + ksft_exit_skip("Transparent Hugepages not available\n"); + + pagemap_fd =3D open("/proc/self/pagemap", O_RDONLY); + if (pagemap_fd < 0) + ksft_exit_fail_perror("open(/proc/self/pagemap)"); + kpageflags_fd =3D open("/proc/kpageflags", O_RDONLY); + if (kpageflags_fd < 0) + ksft_exit_skip("open(/proc/kpageflags) requires root\n"); + + orders =3D thp_supported_orders(); + if (!orders) + ksft_exit_skip("No supported THP orders\n"); + + ksft_set_plan(__builtin_popcountl(orders) + 1); + + thp_save_settings(); + thp_read_settings(&settings); + /* Base of the settings stack; the bottom entry is never popped */ + thp_push_settings(&settings); + + check_order(0); + for (order =3D 1; order < NR_ORDERS; order++) { + if (!(orders & (1UL << order))) + continue; + check_order(order); + } + + ksft_finished(); +} diff --git a/tools/testing/selftests/mm/hmm-tests.c b/tools/testing/selftes= ts/mm/hmm-tests.c index fa1a651963fd..e5f273ca84c1 100644 --- a/tools/testing/selftests/mm/hmm-tests.c +++ b/tools/testing/selftests/mm/hmm-tests.c @@ -65,7 +65,6 @@ enum { #define HMM_PATH_MAX 64 #define NTIMES 10 =20 -#define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1))) /* Just the flags we need, copied from mm.h: */ =20 #ifndef FOLL_WRITE diff --git a/tools/testing/selftests/mm/migration.c b/tools/testing/selftes= ts/mm/migration.c index a35e2b57e05b..d1d0989ed2ca 100644 --- a/tools/testing/selftests/mm/migration.c +++ b/tools/testing/selftests/mm/migration.c @@ -20,7 +20,6 @@ =20 #define TWOMEG (2<<20) #define RUNTIME (20) -#define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1))) =20 HUGETLB_SETUP_DEFAULT_PAGES(1) =20 diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/self= tests/mm/run_vmtests.sh index 4cc1d1a55ebf..3a111bc9c29e 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -382,6 +382,8 @@ CATEGORY=3D"pfnmap" run_test ./pfnmap # COW tests CATEGORY=3D"cow" run_test ./cow =20 +CATEGORY=3D"thp" run_test ./folio_order_check + CATEGORY=3D"thp" run_test ./khugepaged =20 CATEGORY=3D"thp" run_test ./khugepaged -s 2 diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests= /mm/vm_util.h index 0172003c16dc..ea48e6a7527e 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -12,6 +12,8 @@ #include =20 #define BIT_ULL(nr) (1ULL << (nr)) +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + #define PM_SOFT_DIRTY BIT_ULL(55) #define PM_MMAP_EXCLUSIVE BIT_ULL(56) #define PM_UFFD_WP BIT_ULL(57) --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 2BF6225B0BE; Sat, 19 Sep 2026 00:25:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777522; cv=none; b=TeoClQbmOw9EL7SeM/v2TL05GYuN1EyX1g7Qk41ryz0zE0k7d1ImnCC7+PTgmKgmz7smrKwzL8AUE/CYykLlT39/hb2i3cNC1Q2gD4L3o3BGV4fipH6VgY00YSikKQdLFkDwEneWrQiALaHBNZoJ4lhHPHuYyIXGkse1f3vCr64= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777522; c=relaxed/simple; bh=bFbAdD5WwJ7BRCb9eIeM5k8fGbdRcmIshjpH6mjf5U0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NPIWUnxR9Mddk6LeOG4vvy1gP1UIONWO5xn3Dgg2ABsFBgTStwuA6LGRIWRmA5rseRzAjJ5HSMG/jaNVXGFt2IxqLucyOz2JS73tZCl7iWt+F4Fx5kukIEJb8w7+TeaGVglRPLXykBeZeQfrZHr3NJ192pm2NKktoq+eXznXSyE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=YyYYiDI3; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=OG3pXCew; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="YyYYiDI3"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="OG3pXCew" Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfout.phl.internal (Postfix) with ESMTP id B0774EC020B; Fri, 18 Sep 2026 20:25:17 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-02.internal (MEProxy); Fri, 18 Sep 2026 20:25:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777517; x= 1789863917; bh=OrQSW9PySTD5pqcXZKw4HeeHztfLYLHLZ88GO+dc7EA=; b=Y yYYiDI3Q5HTbw/tbAfd8rDW/2Kzi8T4+aoFUJbTMd88hjoSGBOKD7sbiEyvJ8Jpb m/l8Ly2mhl2+c/lhnEkzKc5QOBwKryezfTZfZBPbGcLQbDqGWu6naXJ+9ao/PsD7 8Joaxcb4r1SMQxlxpsD9vo3EzRcWKOV+VJKav7kAcwG/OnpKLF0yFf3FSsqcsNLo It5ppUBxc6Xbyt1ZZCw1OpQjsyoeQYC/fTWNzJ9yjTTRmxPLgbJnWRmK+phXu+8j wrFTa4rULui9mCUr6pXIFi/UDEhXQL66+8IIEiz3PRbUEXhbyBSedz89j3MreGdq fz6MNO+yZuiUHRWJ+u/MQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777517; x=1789863917; bh=O rQSW9PySTD5pqcXZKw4HeeHztfLYLHLZ88GO+dc7EA=; b=OG3pXCewdhljr8JHr YlH6l8CooCxcfLobrHKScUPuGADBAA718f+YWA56zlFjCNaw/IcUL5wrAqHDXwu0 ABGXQlqANJGVE9Cvoak5T4ABiD+Xqymx/Vv5tN5PSNbUlDRf8r4v5J91mrtI1JLt KbZbOFMiC29sxwWuylGJ8y7rVKcjSmLb5pIYJx8fW0zcSACEQm64bCwuWR0tHhmQ qKAfgQS/3UULY/yDbwp62jIEA4zJs3oaCwewsSK4EpKFAQ5TKHraHeGU8yUoBuaM gM6Y65XkbjxQYpMnLO2R/kgy2DegAja/mP1tkNGaPmYBWbQhUJRZe59X/LEDKmyc 0FidQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEzseHgHAxanvosBbYuJPOsY+n0X5UbYs0PPazNY//kQZ3NkUWvwvZaeFG4K6MaM1 51QpOH4aelOmHBptEhruNIkMmEsuOQeZbGrvL7mQj2kdmmCNYrJ7V/Gxu8ar4BzJpo5rV7 vKP2ia7U0+Vm59vAPsz2JcwivFHP+0OmSoqV+JfA3yKlcOkTPrhdGkX4AgOHLm4XJUt5mM HeqMESXl6ibr/xrgjBd4IZM9oAbU6DWk9Q3+fqdUek4rHv8tNSmXbmq+2iLXuPMZjgN42W gGRNasGU39A5UL6wnmEy31YC46agADHTZYQX6KPmc3+B0CXfmIhRtSns1d+buSvmpYlDYa Ea8F6iMJgeQKGBr6iJ6jS5t/l5kFUJnfWycrqY24cckliWVai2FLR26JRYV4iw4sX32X2i EfEzbad5eybuXifwnMO7/nyVEQbt6L9OQsQxevONb3UmKp3N0K6snWnX7lTO2MJ66Mbb0b slMcJIV8yM6ej+537hiz0S4+IctIiyGVy6byPF1QrbNmJisJ2MPp6v9lpvP0vwF3Q7FXRI Z2sJIQMS6uXkTcnCkwcV8MQ0b3yHsVQ9xH51hEsMbxMwVPHHjfkyMMnQxNsc8pzBomEkfY 5HGoXJzje8BjlIPd8fmeLOd/xchC2spbg+r8krgCEAGrEh22jNHSVdd32VTg X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:17 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 10/19] selftests/mm: add khugepaged completion barrier helper Date: Sat, 19 Sep 2026 01:24:40 +0100 Message-ID: <20260919002451.496763-11-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" A khugepaged test has to tell "not collapsed" from "not scanned yet", and nothing in the selftests can. wait_for_scan() in khugepaged.c comes closest: it polls full_scans until the counter has advanced by two, since the pass in progress may already have passed the test's mm. But it only returns in time if scan_sleep_millisecs happens to be short, and it is private to that one test. Add khugepaged_full_pass() to hugepage_settings, built on the same advance-by-two wait but driven through sysfs: a store to scan_sleep_millisecs wakes the daemon, so the barrier completes whatever the scan cadence. A store made while the daemon is scanning rather than sleeping is lost, so the helper keeps storing until the pass lands. One wake completes one pass only if pages_to_scan covers every mm on the list, so callers need it large. Settings pushes must not start passes of their own. A store to either sleep knob wakes the daemon, so thp_write_settings() now writes a khugepaged knob only when its value changes. Assisted-by: LLM Reviewed-by: Baolin Wang Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/lib/mm/hugepage_settings.c | 60 +++++++++++++++++++++++++++----- tools/lib/mm/hugepage_settings.h | 2 ++ 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/tools/lib/mm/hugepage_settings.c b/tools/lib/mm/hugepage_setti= ngs.c index 656442c8d395..77918677a9cd 100644 --- a/tools/lib/mm/hugepage_settings.c +++ b/tools/lib/mm/hugepage_settings.c @@ -217,6 +217,13 @@ void thp_read_settings(struct thp_settings *settings) } } =20 +/* A store to either sleep knob wakes khugepaged, so write only on change = */ +static void thp_update_num(const char *name, unsigned long num) +{ + if (thp_read_num(name) !=3D num) + thp_write_num(name, num); +} + void thp_write_settings(struct thp_settings *settings) { struct khugepaged_settings *khugepaged =3D &settings->khugepaged; @@ -232,15 +239,15 @@ void thp_write_settings(struct thp_settings *settings) shmem_enabled_strings[settings->shmem_enabled]); thp_write_num("use_zero_page", settings->use_zero_page); =20 - thp_write_num("khugepaged/defrag", khugepaged->defrag); - thp_write_num("khugepaged/alloc_sleep_millisecs", - khugepaged->alloc_sleep_millisecs); - thp_write_num("khugepaged/scan_sleep_millisecs", - khugepaged->scan_sleep_millisecs); - thp_write_num("khugepaged/max_ptes_none", khugepaged->max_ptes_none); - thp_write_num("khugepaged/max_ptes_swap", khugepaged->max_ptes_swap); - thp_write_num("khugepaged/max_ptes_shared", khugepaged->max_ptes_shared); - thp_write_num("khugepaged/pages_to_scan", khugepaged->pages_to_scan); + thp_update_num("khugepaged/defrag", khugepaged->defrag); + thp_update_num("khugepaged/alloc_sleep_millisecs", + khugepaged->alloc_sleep_millisecs); + thp_update_num("khugepaged/scan_sleep_millisecs", + khugepaged->scan_sleep_millisecs); + thp_update_num("khugepaged/max_ptes_none", khugepaged->max_ptes_none); + thp_update_num("khugepaged/max_ptes_swap", khugepaged->max_ptes_swap); + thp_update_num("khugepaged/max_ptes_shared", khugepaged->max_ptes_shared); + thp_update_num("khugepaged/pages_to_scan", khugepaged->pages_to_scan); =20 if (dev_queue_read_ahead_path[0]) { int ret =3D write_num(dev_queue_read_ahead_path, @@ -271,6 +278,41 @@ void thp_write_settings(struct thp_settings *settings) } } =20 +/* + * Wait for a full khugepaged scan pass that started after this call: the + * pass in progress may already have passed this mm, so full_scans has to + * advance twice. + * + * A store to scan_sleep_millisecs wakes the daemon, but one made while it + * is scanning rather than sleeping is lost, so keep storing until the pass + * lands. + * + * One wake is one pass only if pages_to_scan covers every mm on the list. + */ +bool khugepaged_full_pass(unsigned int timeout_s) +{ + unsigned long deadline_ms =3D timeout_s * 1000UL; + unsigned long elapsed_ms =3D 0, poll_ms =3D 10; + unsigned long sleep_ms; + int pass; + + sleep_ms =3D thp_read_num("khugepaged/scan_sleep_millisecs"); + for (pass =3D 0; pass < 2; pass++) { + unsigned long target =3D + thp_read_num("khugepaged/full_scans") + 1; + + while (thp_read_num("khugepaged/full_scans") < target) { + if (elapsed_ms >=3D deadline_ms) + return false; + thp_write_num("khugepaged/scan_sleep_millisecs", + sleep_ms); + usleep(poll_ms * 1000); + elapsed_ms +=3D poll_ms; + } + } + return true; +} + struct thp_settings *thp_current_settings(void) { if (!settings_index) { diff --git a/tools/lib/mm/hugepage_settings.h b/tools/lib/mm/hugepage_setti= ngs.h index 94d9fc747f49..8f4581099b7a 100644 --- a/tools/lib/mm/hugepage_settings.h +++ b/tools/lib/mm/hugepage_settings.h @@ -83,6 +83,8 @@ static inline void thp_save_settings(void) hugepage_save_settings(/* thp =3D */ true, /* hugetlb =3D */ false); } =20 +bool khugepaged_full_pass(unsigned int timeout_s); + void thp_set_read_ahead_path(char *path); unsigned long thp_supported_orders(void); unsigned long thp_shmem_supported_orders(void); --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 DFCFE27AC4D; Sat, 19 Sep 2026 00:25:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777525; cv=none; b=iG55mg2K71vPKmHvOYzTwP1P9FEpriKyfOwaw2szKnMiqybyDHAPNGyqwOJspk2St46cLcAZhuDYAmPvSKzcvmfwQcAbA77ZPViyHe2pJjYqUheA1GqQWUzBDM7bPMrN2yEyQjFx76x6PCR9feD1E9m1xq6qqflNnzVTgvNdKaE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777525; c=relaxed/simple; bh=JrHyvkuLqXJRquq5KZ5Ug/US5G/MD4G7mMxi/6LACaI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rINb7J5E5rJKNmuNd2y98lqiMXOS76llKc5iJi4TOVCxCWh5bq3jek7zVFbpy5vVffBbDj33vx5ibdewZuHNzYG6MBnf3wNuvSMgqxICfafZiFgR3pBGY16qwLdgrntfMQAQz46jLmCL+LSJaPJ5KSQLKtpKFBBgaWB6IDP39ZQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=Pdp0K7hE; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=fPxIfBAm; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="Pdp0K7hE"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="fPxIfBAm" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 883831400157; Fri, 18 Sep 2026 20:25:19 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-05.internal (MEProxy); Fri, 18 Sep 2026 20:25:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777519; x= 1789863919; bh=fa/WJc2cfEFuyIl50fDbtXrH+t+EEF5j2F2zkGzhbgo=; b=P dp0K7hEqo2aY9AKX0qqbhmo0IHLrT66+pJkvcbdHc8SCAhxtUcKpeW0ECcWaGOxz PPUC7bhLh6jcVbm+rarofqzoz9Y060VoIVmFPylwAksIiycrnwtHasdATyqfDpw2 eZGQJ4img2a4+ogJf2goujALnEYZ/fDT+yrVYTFw4vKVQnG5zyYWW8alMdGdldn1 EJ/Ti133299GN+48XysoGGLfftu3e80or5MY9KCBucOiKasOUA7RTCqTDYZRz7hs 3dzAsu8wgGySN4/W0cyQBt+Xh8BQqqjxCLcEPuW3HY5lMPFp3/a6Si5ClJUsToUc TukOqx6mFHHGvpTJA/48w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777519; x=1789863919; bh=f a/WJc2cfEFuyIl50fDbtXrH+t+EEF5j2F2zkGzhbgo=; b=fPxIfBAmqorJipw6l ZW0VjNuw/NDwAMzwiFD88fduiZs20i56kOQ6Hq610K3QFjqNTsJr9MJ/+ztsaNq+ Vj92MuD8po0wn4Q8ELxQwi8Kb4KvEjdYLgGlI7zsAeYDyuvCGIa0ckm7n+VXDOgj CwScS+vHGv11plf+056tk8Gur4RZKlo0tTYybJ0rLt1aKhPC9nMvszPhKHuNaJxQ OcD9k7FOAkQDztWK6TPzXsb9+RKHRV2KLjDN0Pw3aC4yV8La11hSvZKF0kSjQJzo LyahbfRmbo7r/R49ifQhazTecBNvnmjCX0B8QoSMiBFctWx86wk10g62gdjPTXEG Y1OHw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEzseHgHAxanvosBbYuJPOsY+n0X5UbYs0PPazNY//kQZ3NkUWvwvZaeFG4K6MaM1 51QpOH4aelOmHBptEhruNIkMmEsuOQeZbGrvL7mQj2kdmmCNYrJ7V/Gxu8ar4BzJpo5rV7 vKP2ia7U0+Vm59vAPsz2JcwivFHP+0OmSoqV+JfA3yKlcOkTPrhdGkX4AgOHLm4XJUt5mM HeqMESXl6ibr/xrgjBd4IZM9oAbU6DWk9Q3+fqdUek4rHv8tNSmXbmq+2iLXuPMZjgN42W gGRNasGU39A5UL6wnmEy31YC46agADHTZYQX6KPmc3+B0CXfmIhRtSns1d+buSvmpYlDp9 j6GFWtDjZQsGlRkbX/dsu0s7jWW7EO1cfRuTcY+UE8AlB0fR385acoC+SqLw4KEIHZVYJ7 RlxUp8478WKHcL6UgnYOt4wMQncTQvzdsvR6I0RBACFW40USEQkXMs57QveT6Ne4KKR2H+ wQoywy4x4VmaQ1j8BBLkeVJsZrBBZvRxo+kStTpfypsnYjJFHVKl739ROevHthakKZ3px3 X0AjsgCwq5+SX1EC/zZkfGRo4pUP/LNFfhy3jP7rTTdsXUgzqHPJLIQXDvkB349nu5QT7w maSFRJwSnBZPgGl3Aq3hrwnONEIc3eFqh5MbHMqcoNf6L9rhy90NYVSstmVw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:18 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 11/19] selftests/mm: add order-parameterized khugepaged collapse cases Date: Sat, 19 Sep 2026 01:24:41 +0100 Message-ID: <20260919002451.496763-12-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" The mthp_khugepaged context runs the generic cases at a sub-PMD order, which answers how many folios of that order a range ends up with. It cannot say which order-sized window they landed in, so "the populated window collapsed" and "the empty window next to it collapsed instead" look alike. Add four cases that check each window on its own, with the folio-order helpers in vm_util: - collapse_order_single_window(): only the populated window collapses; - collapse_order_partial_window(): the default max_ptes_none lets a window with one present PTE collapse; - collapse_order_max_ptes_none(): with max_ptes_none=3D0 a full window collapses and one missing a page does not; - collapse_order_mixed_sources(): sources that are already large folios of a smaller order collapse to the target. Each case faults its region before MADV_HUGEPAGE with only the target order enabled, so the sources are order 0 and the result can only come from khugepaged. They wait for a full pass rather than for the result to appear: without a completed pass, "not collapsed" and "not scanned yet" are the same thing. Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Tested-by: Baolin Wang --- tools/testing/selftests/mm/khugepaged.c | 212 ++++++++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index e013eebc7136..51bda01446cd 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -30,6 +30,8 @@ static unsigned long page_size; static int hpage_pmd_nr; static int anon_order; static int collapse_order; +static int pagemap_fd =3D -1; +static int kpageflags_fd =3D -1; =20 #define PID_SMAPS "/proc/self/smaps" #define TEST_FILE "collapse_test_file" @@ -1209,6 +1211,198 @@ static void madvise_retracted_page_tables(struct co= llapse_context *c, ksft_test_result_report(exit_status, "%s\n", __func__); } =20 +/* Smallest order khugepaged will consider for mTHP collapse */ +#define MIN_MTHP_ORDER 2 + +/* Time budget for one khugepaged pass in the collapse_order_* cases */ +#define MTHP_PASS_TIMEOUT_S 30 + +static size_t mthp_window_size(void) +{ + return page_size << collapse_order; +} + +static void mthp_push_target_order(void) +{ + struct thp_settings settings =3D *thp_current_settings(); + int i; + + /* + * Only the target order, and only for madvise: the cases fault their + * region first, so the sources stay order 0 whatever -s asked for. + */ + settings.thp_enabled =3D THP_NEVER; + for (i =3D 0; i < NR_ORDERS; i++) + settings.hugepages[i].enabled =3D THP_NEVER; + settings.hugepages[collapse_order].enabled =3D THP_MADVISE; + thp_push_settings(&settings); +} + +static bool all_windows_at_order(void *p, size_t len) +{ + return is_range_backed_by_order(p, len, collapse_order, + pagemap_fd, kpageflags_fd); +} + +static bool any_window_at_order(void *p, size_t len) +{ + size_t window =3D mthp_window_size(); + char *addr =3D p; + + for (; len >=3D window; addr +=3D window, len -=3D window) { + if (all_windows_at_order(addr, window)) + return true; + } + return false; +} + +static void collapse_order_single_window(struct collapse_context *c, + struct mem_ops *ops) +{ + size_t window =3D mthp_window_size(); + void *p; + + mthp_push_target_order(); + + p =3D ops->setup_area(1); + ops->fault(p, window, 2 * window); + if (any_window_at_order(p, hpage_pmd_size)) + ksft_exit_fail_msg("Unexpected large folio after fault\n"); + + if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE)) + ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)"); + ksft_print_msg("Collapse one fully populated window..."); + if (!khugepaged_full_pass(MTHP_PASS_TIMEOUT_S)) + fail("Timeout"); + else if (all_windows_at_order(p + window, window) && + !any_window_at_order(p, window) && + !any_window_at_order(p + 2 * window, + hpage_pmd_size - 2 * window)) + success("OK"); + else + fail("Fail"); + + validate_memory(p, window, 2 * window); + ops->cleanup_area(p, hpage_pmd_size); + thp_pop_settings(); + ksft_test_result_report(exit_status, "%s\n", __func__); +} + +static void collapse_order_partial_window(struct collapse_context *c, + struct mem_ops *ops) +{ + void *p; + + mthp_push_target_order(); + + p =3D ops->setup_area(1); + ops->fault(p, 0, page_size); + if (any_window_at_order(p, hpage_pmd_size)) + ksft_exit_fail_msg("Unexpected large folio after fault\n"); + + if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE)) + ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)"); + ksft_print_msg("Collapse window with single PTE entry present..."); + if (!khugepaged_full_pass(MTHP_PASS_TIMEOUT_S)) + fail("Timeout"); + else if (all_windows_at_order(p, mthp_window_size())) + success("OK"); + else + fail("Fail"); + + validate_memory(p, 0, page_size); + ops->cleanup_area(p, hpage_pmd_size); + thp_pop_settings(); + ksft_test_result_report(exit_status, "%s\n", __func__); +} + +static void collapse_order_max_ptes_none(struct collapse_context *c, + struct mem_ops *ops) +{ + struct thp_settings settings; + size_t window =3D mthp_window_size(); + void *p; + + mthp_push_target_order(); + settings =3D *thp_current_settings(); + settings.khugepaged.max_ptes_none =3D 0; + thp_push_settings(&settings); + + p =3D ops->setup_area(1); + ops->fault(p, 0, 2 * window - page_size); + if (any_window_at_order(p, hpage_pmd_size)) + ksft_exit_fail_msg("Unexpected large folio after fault\n"); + + if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE)) + ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)"); + ksft_print_msg("Collapse full window, not the one missing a page..."); + if (!khugepaged_full_pass(MTHP_PASS_TIMEOUT_S)) + fail("Timeout"); + else if (all_windows_at_order(p, window) && + !any_window_at_order(p + window, window)) + success("OK"); + else + fail("Fail"); + + validate_memory(p, 0, 2 * window - page_size); + ops->cleanup_area(p, hpage_pmd_size); + thp_pop_settings(); + thp_pop_settings(); + ksft_test_result_report(exit_status, "%s\n", __func__); +} + +static void collapse_order_mixed_sources(struct collapse_context *c, + struct mem_ops *ops) +{ + struct thp_settings settings; + void *p; + + if (collapse_order <=3D MIN_MTHP_ORDER) { + ksft_test_result_skip("%s: no source order below target\n", + __func__); + return; + } + + mthp_push_target_order(); + + settings =3D *thp_current_settings(); + settings.hugepages[MIN_MTHP_ORDER].enabled =3D THP_ALWAYS; + thp_push_settings(&settings); + p =3D ops->setup_area(1); + ops->fault(p, 0, hpage_pmd_size); + thp_pop_settings(); + + /* + * The allocator can fall back to smaller folios under fragmentation; + * having nothing to collapse from is not a failure. + */ + if (!is_range_backed_by_order(p, hpage_pmd_size, MIN_MTHP_ORDER, + pagemap_fd, kpageflags_fd)) { + ksft_print_msg("No order-%d sources to collapse...", + MIN_MTHP_ORDER); + skip("Skip"); + ops->cleanup_area(p, hpage_pmd_size); + thp_pop_settings(); + ksft_test_result_report(exit_status, "%s\n", __func__); + return; + } + + if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE)) + ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)"); + ksft_print_msg("Collapse region backed by smaller large folios..."); + if (!khugepaged_full_pass(MTHP_PASS_TIMEOUT_S)) + fail("Timeout"); + else if (all_windows_at_order(p, hpage_pmd_size)) + success("OK"); + else + fail("Fail"); + + validate_memory(p, 0, hpage_pmd_size); + ops->cleanup_area(p, hpage_pmd_size); + thp_pop_settings(); + ksft_test_result_report(exit_status, "%s\n", __func__); +} + static void usage(void) { fprintf(stderr, "\nUsage: ./khugepaged [OPTIONS] [dir]\n\n"); @@ -1377,6 +1571,20 @@ int main(int argc, char **argv) =20 parse_test_type(argc, argv); =20 + if (mthp_khugepaged_context && + !(thp_supported_orders() & (1UL << collapse_order))) + ksft_exit_skip("Order %d is not a supported anon THP order\n", + collapse_order); + + if (mthp_khugepaged_context) { + pagemap_fd =3D open("/proc/self/pagemap", O_RDONLY); + if (pagemap_fd < 0) + ksft_exit_fail_perror("open(/proc/self/pagemap)"); + kpageflags_fd =3D open("/proc/kpageflags", O_RDONLY); + if (kpageflags_fd < 0) + ksft_exit_fail_perror("open(/proc/kpageflags)"); + } + setbuf(stdout, NULL); =20 /* @@ -1427,6 +1635,10 @@ int main(int argc, char **argv) TEST(collapse_empty, madvise_context, anon_ops); =20 TEST(collapse_single_mthp, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_single_window, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_partial_window, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_max_ptes_none, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_mixed_sources, mthp_khugepaged_context, anon_ops); =20 TEST(collapse_single_pte_entry, khugepaged_context, anon_ops); TEST(collapse_single_pte_entry, khugepaged_context, read_only_file_ops); --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 7F79E2AD00; Sat, 19 Sep 2026 00:25:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777525; cv=none; b=q62i9bbC5m0ijCEN1M8UB6aQtmKVVKmz0R0/7R/UqFjQtRfdLMW/IHkJQdKZ/5+Hb+sW15weYfLup2pU1a0gAnsPfRiCVdobSyi0rvBxO/VCagmRmmf/60HNFDmpCY75rO7HV+5lQ3dnvCnUrjIrJDTCod3WowY/mZIBBQoc+2A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777525; c=relaxed/simple; bh=xHxWWQVPiX1xV2ngFVQTcENr5JBXW5gWgYQElXhF1D8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lxUGd1pvuh5YbhW3ARd5UYswvaOq9QCEfmDlTd/Q9f5xAfL4Q676p4LoUCc+hF9/QXc+KNV8+gxXfcu7CimaXQpktTbaMYR94ZHFvH+2SmLE15ExISseDrAWOMuw0X/3r1A7Ps0mjBOsGvWtAIYRIbSeJicW0WKBVaSy5gxbMCI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=fP3GmIiB; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=bhpMb4fE; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="fP3GmIiB"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="bhpMb4fE" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfout.phl.internal (Postfix) with ESMTP id 50048EC0198; Fri, 18 Sep 2026 20:25:21 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Fri, 18 Sep 2026 20:25:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777521; x= 1789863921; bh=woAtTKSUrAOJywezkPjP/PLaIChkiihi6VKhVfSPERI=; b=f P3GmIiBK6HZ5fGIcXGDIUODVSOcL3LT8XoaXdTMNuubaa/Qjxlum0+xGM0OBxsSi 6jBfVNsTabaUnVA3uDuZAwm7nZh168ozs3/hM/lQe64SogUKSeWsEqE9Ds4XdcQu X+iIRvRdiidDvM/029MXNvpgBihgvuJT7Cy6KlCymZ+TPQggaPBkYsso5h72KEZP Dpb/NMgYdfkPHFwYTwBBGK4T8kZiZR38LSEKKapXFxeQuTQwegCzeSIVk+AjyA8v OJ7Jv1i+BHDcgegmQeom/1EUWZCTs+fZxUhRgfzko/Tz9zhusEap/mwGsSq8TJLR egJaZyUZqRm8i3otAidPg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777521; x=1789863921; bh=w oAtTKSUrAOJywezkPjP/PLaIChkiihi6VKhVfSPERI=; b=bhpMb4fEi+7Sz9LZv A39GMVPwJcBjPP4KIjaqnyhb+Mw81Xzt3EcZ/kGZKzJH4cgJLfrt4uMyjd4F/tF4 oh/u+IUIxWvXZ6i6gbtAgrUAMlcGECDs0wPlEqNE39OS52lrI7qCJPDU8PcYGBLw cUmJ9VwdKTVNUYfWy7T/SI26ZBNnnLmGfxLYn0TDWVbDdVthuds5yA9bdgEFqUa/ f7Xz89aX7bFwMYjqd1EDofwI+eRi1kpFAOpIUHJyXItwbVF81Sk98IvsyjMnCWEs HYpL/QIZSvdSZjGzaeU3WmY4mU4ONFqL3eybrIhuKg05BvSszWiseuNtR9QFymts uN03w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMBw QQND7SieWtt/aXz5uKT9DiEHRhvYRwDLjNMrZi9QZALZ/12AZ3Zf4NPQaM79q8yJXhO5D4 mgydrB4dpKv6oFpVFxvKxTxzuzkzF6JzHSfyfPOE/W2C8Ho6P08KlQEN5muATVcjHH/zY1 fe7odX8BguwojpsMGHN4w0lhDpxTXbH+2bMpQs1mlkdAPd+xnvCJg/Sdle46ItJw+HmJ/A BoNbGTbzr371oySzuTVZvONAaXSjwrSB47KlvqxJxbd/6f6gASMpVlCZ11o/leCgCgUkpP A+2GeiX63HVUrzXdmDcz4kER+634TQWkynYMIc9RDoAJuY0Bif+jfDP05mUQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:20 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 12/19] selftests/mm: parameterize the mixed-source collapse case by source order Date: Sat, 19 Sep 2026 01:24:42 +0100 Message-ID: <20260919002451.496763-13-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" collapse_order_mixed_sources() faults its region as order-2 folios and collapses them to the -c target. Order 2 is below the contpte size on every arm64 page size, so nothing in this suite collapses a contpte-mapped source on purpose. Let -s name the source order alongside -c. The case then faults at that order, keeping order 2 when -s is absent, and the source order has to be a supported mTHP order below the target. The other mTHP cases are unaffected: mthp_push_target_order() enables only the target order. A -c at or below -s is refused before any case runs: the sources would already be the size being asked for. Without the check the generic cases fail on that one by one instead of saying why. "-s 5 -c 7" on arm64/64K then collapses contpte-mapped sources into a larger mTHP. Assisted-by: LLM Acked-by: Lorenzo Stoakes (ARM) Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang Tested-by: Baolin Wang --- tools/testing/selftests/mm/khugepaged.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 51bda01446cd..9d1c47bd5013 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1354,11 +1354,13 @@ static void collapse_order_max_ptes_none(struct col= lapse_context *c, static void collapse_order_mixed_sources(struct collapse_context *c, struct mem_ops *ops) { + int source_order =3D anon_order ? anon_order : MIN_MTHP_ORDER; struct thp_settings settings; void *p; =20 - if (collapse_order <=3D MIN_MTHP_ORDER) { - ksft_test_result_skip("%s: no source order below target\n", + if (source_order >=3D collapse_order || + !(thp_supported_orders() & (1UL << source_order))) { + ksft_test_result_skip("%s: no supported source order below target\n", __func__); return; } @@ -1366,7 +1368,7 @@ static void collapse_order_mixed_sources(struct colla= pse_context *c, mthp_push_target_order(); =20 settings =3D *thp_current_settings(); - settings.hugepages[MIN_MTHP_ORDER].enabled =3D THP_ALWAYS; + settings.hugepages[source_order].enabled =3D THP_ALWAYS; thp_push_settings(&settings); p =3D ops->setup_area(1); ops->fault(p, 0, hpage_pmd_size); @@ -1376,10 +1378,9 @@ static void collapse_order_mixed_sources(struct coll= apse_context *c, * The allocator can fall back to smaller folios under fragmentation; * having nothing to collapse from is not a failure. */ - if (!is_range_backed_by_order(p, hpage_pmd_size, MIN_MTHP_ORDER, + if (!is_range_backed_by_order(p, hpage_pmd_size, source_order, pagemap_fd, kpageflags_fd)) { - ksft_print_msg("No order-%d sources to collapse...", - MIN_MTHP_ORDER); + ksft_print_msg("No order-%d sources to collapse...", source_order); skip("Skip"); ops->cleanup_area(p, hpage_pmd_size); thp_pop_settings(); @@ -1389,7 +1390,8 @@ static void collapse_order_mixed_sources(struct colla= pse_context *c, =20 if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE)) ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)"); - ksft_print_msg("Collapse region backed by smaller large folios..."); + ksft_print_msg("Collapse region backed by order-%d sources...", + source_order); if (!khugepaged_full_pass(MTHP_PASS_TIMEOUT_S)) fail("Timeout"); else if (all_windows_at_order(p, hpage_pmd_size)) @@ -1420,6 +1422,7 @@ static void usage(void) fprintf(stderr, "\t\t-s: mTHP size, expressed as page order.\n"); fprintf(stderr, "\t\t Defaults to 0. Use this size for anon or shmem a= llocations.\n"); fprintf(stderr, "\t\t-c: collapse order for mTHP collapse, expressed as p= age order.\n"); + fprintf(stderr, "\t\t -s, if set, is the source order for the mixed-so= urce case.\n"); exit(1); } =20 @@ -1575,6 +1578,9 @@ int main(int argc, char **argv) !(thp_supported_orders() & (1UL << collapse_order))) ksft_exit_skip("Order %d is not a supported anon THP order\n", collapse_order); + if (mthp_khugepaged_context && collapse_order <=3D anon_order) + ksft_exit_skip("-c %d needs a source order below it, -s says %d\n", + collapse_order, anon_order); =20 if (mthp_khugepaged_context) { pagemap_fd =3D open("/proc/self/pagemap", O_RDONLY); --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 EF0812BEC52; Sat, 19 Sep 2026 00:25:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777526; cv=none; b=hR2tMshy/VtyzozImWUeK23SRWyEnm8TjgYtB3Bn5K5DysReww9zvvgsYRpXcZoGv6fyb8HBOsjz1SUEiiI/sr+Cq1rqsgDpYNgPuChBceuM4DGC9ldIX4YDTUaOsPnwNZk9lv91BFrAHHnxzXsFS0jM498pdt31vNwql6XIdsU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777526; c=relaxed/simple; bh=FZ7JYHr9B27l0som+TzXQpfAEkfbSgB2zVnAfudAYF4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=A5ZKabsrAO3ScmTwl+iqSIH2tNsIbKkNiDK4gU8hSQrFdEg34XCkRWAtKoNvUEj0hHQG8MKWx7w9lCzwLFDsm7RuZSS7BaYWfWVWSaWlKh+/g1yjpn/Sjo3CBljLDvw4Z7jM4FUmQEy/prpLSxiC8+OwnKWBLyxUc1nQhNCZ0lE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=lGdJN3Lv; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=aJZIMws/; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="lGdJN3Lv"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="aJZIMws/" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfout.phl.internal (Postfix) with ESMTP id F28FCEC01A0; Fri, 18 Sep 2026 20:25:22 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-05.internal (MEProxy); Fri, 18 Sep 2026 20:25:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777522; x= 1789863922; bh=0/Oan2MDRATB6LmyEXW7puKyqnDvdR8Sq8s2qi8OMjE=; b=l GdJN3LvcN6YCf/+td4HtMK8L6vLlg7tykEPUtc/Jz11g2qWaRMTHxVAj6W7do3qa orvG+af0TMuKUZPt0nMNBki5voZkEJ4esRr9NjoTxwMZZ6AwMJD/XRS2bP9XfLSL WuCDNvAvVyu/ixzOgmfQ+zUGkl6P7Zx//YI4Tt4aJK1bPe3RgZjZSnZwvO/8O0AK I+tIkcAI/iR12/c8++UKWMq3nxczWJxopTPq5/He/fTmpir0O6wj/EX3XcNFKGZa xpoZnVm+o/cBWcHlNmjECyjkHp+jFoG018A1prhazbRQaoCRqfck7/IQJsanAva1 383bDE68ZMiY0f2inpj1Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777522; x=1789863922; bh=0 /Oan2MDRATB6LmyEXW7puKyqnDvdR8Sq8s2qi8OMjE=; b=aJZIMws/7LmqoRQbP wR7FcaM7n8zR1gvmSRIQfvpv/p35HCyC5FyGwrcjXR9TmGRGQJ9nAfaFrTJjLdf3 w+vftGBnjUeFUluONZf+LUANCBNvg4N94MVMLtdK/KzKWYKur0GdJdqRiv23afo8 zDQE+Qhoe+rfQjkcNBAkYCv2Sbm7ipSe4SrfZdr3eTHqTCpoYSJIs54gIW324FF9 W8AHuOveBp+7frsG9PXOmqYGsHwnL/g1bNLENb9RZiIaJ2e+vMiQqy5SaNHJBKpm C3i8iM+YF4C5F7YXkKQzrU/fqL1eOQi2hU3wfgyRMwQqT2QHSQwcy6qlhWr+A6y7 y8klg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEr5yKr4sxuQbXqh6mxNPhLx5TPKhba5+X7XnlS/zJ9vgRk2t0FxRNN7MLg+r6CPW Mu6PNIlmN7ZPoxynBFUAJAPtPIX+NuZRIFaOEVqo689ggMVwgiN48ZIazRbbn8524IbcBa VFaAXtPPhux2zoqYNSaL4fhjV7u8LwweVoGm0ycn2eaUICY9i4xSWPBSrUzWeffPDzxnz4 WggCaU37X5tXMmNpoupzaGNfQ+amnYr5ymN7dEq2+UMtHRoF6bcIpmQfw03IlrWSCYa/Ho OSQdXdtFB8WyOz/pBd87oZ5qPprkCNYTXqaz9hCIAMLkvF6M+JOqCuEaEpX/p3iuKuZ/hO en0/iPchRVYImZYh/v36F1+B6+fXgakRSzQwPl1xwjwCbd3gtWuKH7++CyEgDstKecr+M+ oOvhk2Dptz0AlsCiPvG7fiZP8z62zyxG8jSLUL9sXWyLcPt2AX7k4shelBUCi8HotjDa7H qlZHsArb+g+QFpcKaHAN2m/VsROOfblQS2zpLbwUgH0fjE4cxXatZa7elB0Xa8kJ/ib+76 8TNlwWJDJDEmcJlADX3TvROWkKm8LxeMTItJRrUflc/tsbLAoGtKCBDywL2wKMPkIdsUZU JGdph8i5zQ0WJrt66UrpjxQScTg5BIDo8gP8DFHIqzuo3zJHaKtCwClXvQbA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:22 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 13/19] selftests/mm: cover a shared-source collapse write race Date: Sat, 19 Sep 2026 01:24:43 +0100 Message-ID: <20260919002451.496763-14-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" 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. Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged.c | 106 ++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 9d1c47bd5013..21ae258bd56e 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1166,6 +1166,109 @@ static void collapse_max_ptes_shared(struct collaps= e_context *c, struct mem_ops ksft_test_result_report(exit_status, "%s\n", __func__); } =20 +/* + * 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 =3D page_size / sizeof(int); + int wstatus, child_status, i, n; + unsigned long shared; + volatile int *ip; + pid_t child; + int sync[2]; + char go =3D 1; + void *p; + + /* At a page per 10 ms, 64 pages spread the writes across the collapse */ + n =3D 64; + shared =3D n * page_size; + + p =3D 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 =3D p; + + ksft_print_msg("Fork, collapse in the child while the parent rewrites..."= ); + child =3D 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) !=3D 1) + _exit(KSFT_FAIL); + usleep(5000); + c->collapse("Collapse a range the parent is writing to", + p, 1, ops, true); + collapse_status =3D exit_status; + for (i =3D 0; i < n; i++) + if (ip[i * stride] !=3D i + 0xdead0000) + break; + if (i =3D=3D n) + success("OK"); + else + fail("Fail: child content"); + /* The content check must not bury a failed collapse */ + if (exit_status !=3D KSFT_FAIL) + exit_status =3D collapse_status; + ops->cleanup_area(p, hpage_pmd_size); + _exit(exit_status); + } + + close(sync[1]); + if (read(sync[0], &go, 1) !=3D 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 =3D 0; + for (;;) { + pid_t ret; + + if (i < n) + ip[i * stride] =3D i + 0xbeef0000; + i++; + usleep(10 * 1000); + ret =3D waitpid(child, &wstatus, WNOHANG); + if (ret =3D=3D 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] =3D i + 0xbeef0000; + /* A child that died reading the racing pages is a failure, not a zero */ + child_status =3D WIFEXITED(wstatus) ? WEXITSTATUS(wstatus) : KSFT_FAIL; + + ksft_print_msg("Check the parent sees only its own writes..."); + for (i =3D 0; i < n; i++) + if (ip[i * stride] !=3D i + 0xbeef0000) + break; + if (i =3D=3D 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 !=3D KSFT_FAIL) + exit_status =3D 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); =20 + 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_rea= d_ops); --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 B39A330569F; Sat, 19 Sep 2026 00:25:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777534; cv=none; b=kFb9ksix95UmdCARpYkGqyzCVIxKeHkYlIMihtCaDjb6OQh/v6/6Eu3K0LS4ScvVwkiyJXKBoHOUo8PJuBwmTEhjsyCtINQYYFSjB1w43/0UdHHzN/NG3BZ7WqZFhriOH3hU394EM1gfNP+4vKu+9jXL2XnP7KMXzbrEuY1ssvc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777534; c=relaxed/simple; bh=Vdq+yGLjUMPC4uMrWKuY60b7MGvPoeeapbnMB7xQ+D8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KkPyXevaAf5q53efVH2Ro5lWub+2rbgXrwVLLNdl/BKroTbNZgT1dG94EJ9P+I3L5xB96mIpP8SnzuisvvSY8AUKqWElbFnq3cSdOBaaRl8jY0PVRDLAKvPpc1Ydjlzq8QzMyTJUHx3GRpKRozJXeYRWUf1m0X+yTULKgzk23N8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=BORlJLas; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=wFfmqNXM; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="BORlJLas"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="wFfmqNXM" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfhigh.phl.internal (Postfix) with ESMTP id B4241140016B; Fri, 18 Sep 2026 20:25:24 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Fri, 18 Sep 2026 20:25:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777524; x= 1789863924; bh=PuV84aXEC3RcsI9Zwrd99iTd8Q3qr/SBlm+s2ZYrws4=; b=B ORlJLas1wLwywvfWd3BoMrBUabwJB7qHgPBBNCbZMzPf+Kw+fpfseus7QXxw8vjP TfR2OGroiYQ1B9BUnq1mQOeNX6ll5EfmwR2wZRXIhXRDlejlcQLw+QyxTVBzO7pY 0c6kxBab7bBH+qiNOiaQzLH1M3AJj/w/5R3iPPWOCv4PSNqIHEFPgQlUdeb/ZLnr ZOS0efla+x6Y4IOxqvxlQw7z2310VLmqctkc016DRNxOeZEox1zg/1Qui+rrek3g 7+N7RWqAahe7JJrpgNhtxwFoHeJk3/Lc9PwJSgEaHeRqVmmnNij4LiGnzZzBrKPs 2GsJ3sr7YbKbvdruh9nJQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777524; x=1789863924; bh=P uV84aXEC3RcsI9Zwrd99iTd8Q3qr/SBlm+s2ZYrws4=; b=wFfmqNXMRYn82w6oB U9Ei1/MPrTL9eCmq/nOZoTLvX9/wj3kT7w4u7jRbFt5FM2qcBrbccK0ZoAXUorUv uGLNNmMz39fUf6z18D5j8IT8QO7zPXZJ0q5Vg+/1ibNutdB9mRh1octjxUFrq5YS L+Q3pHCixiyh7P7DNDmfcXEBvHuAcAC8AktwwPs53u5HKb5aP0gekrcajtOpORQR BxBUvmrJlD8qL2dH/qDj7Wq+4RsV4PDvT+a4M6yoGUB3YK2hj+J3CNKHtJHGpwqT KHov7tGklZiyYomRkIqOWVZ59dBngLtRO2CSMHYd3YYqKcn6sUYDDIbp+NBccw5A 9toeg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMRm DH+J0asLfQyORvWu8lzQQKGGhmWXkwqxVQFZVyAd8+jtR5bfWrfV5CaiXJ71rN5wb49i+v QOua96izRlqXUB79CEcmwUw9SoKJ9rUSqlkGLPwUKQutU971DkCt1u5TgLhBnMLObRK9ke FLiWHbTCo1um3GSLsMxwds37r5MIs+LmF+d1L3zFD9i3FmZ+aTqWsg3xVgxqGWpe3LkfdV d8nCSM0oq0LpVvBlo/dh4v2Qjxl149tlLbwo7GX4WSB1T2lkaJBScjbgZRnL6kgCtZqrxv SXCJex10vChjG5N76WWrHcpV+x0T9V/QLn6mn+ml1937wMFP+O/utkgceR5w X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:24 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 14/19] selftests/mm: run every supported collapse order by default Date: Sat, 19 Sep 2026 01:24:44 +0100 Message-ID: <20260919002451.496763-15-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" The mTHP collapse cases only run when the caller names both the context and an order, so a plain ./khugepaged covers the PMD contexts on anon and nothing else. run_vmtests.sh pinned order 4 and covered no other. Run the mTHP cases once per supported anon THP order below the PMD when -c is absent, and pull that context into both the no-argument invocation and "all". Also: - -c still pins one order, and now says what is wrong instead of printing the usage text. - Both orders end up as array indices and shift counts, so -s and -c are range-checked before they get there. - The mTHP context has only anon cases, so a run that names a different mem_type -- "all:shmem", say -- drops it again rather than refusing to start. Naming both explicitly still refuses. - A case carries the order it was registered at, so a result names it: # Run test: collapse_single_mthp (mthp_khugepaged:anon, order 6) On x86-64 with 4K pages that is orders 2 through 8, and ./khugepaged goes from 29 results in 17 seconds to 77 in 29, so run_vmtests.sh can drop its pinned order-4 line. Assisted-by: LLM Reviewed-by: Baolin Wang Tested-by: Muhammad Usama Anjum Tested-by: Baolin Wang Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged.c | 101 +++++++++++++++++----- tools/testing/selftests/mm/run_vmtests.sh | 2 - 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 21ae258bd56e..a2ac3b3ca5de 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -30,6 +30,9 @@ static unsigned long page_size; static int hpage_pmd_nr; static int anon_order; static int collapse_order; +static bool collapse_order_set; +static int collapse_orders[NR_ORDERS]; +static int nr_collapse_orders; static int pagemap_fd =3D -1; static int kpageflags_fd =3D -1; =20 @@ -1525,12 +1528,14 @@ static void usage(void) fprintf(stderr, "\t\t-s: mTHP size, expressed as page order.\n"); fprintf(stderr, "\t\t Defaults to 0. Use this size for anon or shmem a= llocations.\n"); fprintf(stderr, "\t\t-c: collapse order for mTHP collapse, expressed as p= age order.\n"); + fprintf(stderr, "\t\t Defaults to every supported order below the PMD.= \n"); fprintf(stderr, "\t\t -s, if set, is the source order for the mixed-so= urce case.\n"); exit(1); } =20 static void parse_test_type(int argc, char **argv) { + bool mthp_context_implied =3D false; int opt; char *buf; const char *token; @@ -1542,6 +1547,7 @@ static void parse_test_type(int argc, char **argv) break; case 'c': collapse_order =3D atoi(optarg); + collapse_order_set =3D true; break; case 'h': default: @@ -1549,12 +1555,25 @@ static void parse_test_type(int argc, char **argv) } } =20 + /* + * Both orders end up as array indices and shift counts, so neither + * can be negative, and a zero collapse order asks for base pages. + */ + if (anon_order < 0 || anon_order > hpage_pmd_order) + ksft_exit_fail_msg("-s takes an order in 0..%d, not %d\n", + hpage_pmd_order, anon_order); + if (collapse_order_set && + (collapse_order <=3D 0 || collapse_order >=3D hpage_pmd_order)) + ksft_exit_fail_msg("-c takes an order in 1..%d, not %d\n", + hpage_pmd_order - 1, collapse_order); + argv +=3D optind; argc -=3D optind; =20 if (argc =3D=3D 0) { - /* Backwards compatibility */ + /* No arguments: anon under every context */ khugepaged_context =3D &__khugepaged_context; + mthp_khugepaged_context =3D &__mthp_khugepaged_context; madvise_context =3D &__madvise_context; anon_ops =3D &__anon_ops; return; @@ -1565,13 +1584,14 @@ static void parse_test_type(int argc, char **argv) =20 if (!strcmp(token, "all")) { khugepaged_context =3D &__khugepaged_context; + mthp_khugepaged_context =3D &__mthp_khugepaged_context; madvise_context =3D &__madvise_context; + /* The mTHP context has only anon cases; let other mem_types drop it */ + mthp_context_implied =3D true; } else if (!strcmp(token, "khugepaged")) { khugepaged_context =3D &__khugepaged_context; } else if (!strcmp(token, "mthp_khugepaged")) { mthp_khugepaged_context =3D &__mthp_khugepaged_context; - if (collapse_order <=3D 0 || collapse_order >=3D hpage_pmd_order) - usage(); } else if (!strcmp(token, "madvise")) { madvise_context =3D &__madvise_context; } else { @@ -1587,20 +1607,20 @@ static void parse_test_type(int argc, char **argv) read_write_file_write_ops =3D &__read_write_file_write_ops; anon_ops =3D &__anon_ops; shmem_ops =3D &__shmem_ops; - if (mthp_khugepaged_context) - usage(); } else if (!strcmp(buf, "anon")) { anon_ops =3D &__anon_ops; } else if (!strcmp(buf, "file")) { read_only_file_ops =3D &__read_only_file_ops; read_write_file_read_ops =3D &__read_write_file_read_ops; read_write_file_write_ops =3D &__read_write_file_write_ops; - if (mthp_khugepaged_context) + if (mthp_khugepaged_context && !mthp_context_implied) usage(); + mthp_khugepaged_context =3D NULL; } else if (!strcmp(buf, "shmem")) { shmem_ops =3D &__shmem_ops; - if (mthp_khugepaged_context) + if (mthp_khugepaged_context && !mthp_context_implied) usage(); + mthp_khugepaged_context =3D NULL; } else { usage(); } @@ -1622,6 +1642,7 @@ struct test_case { struct mem_ops *ops; const char *desc; test_fn fn; + int order; /* mTHP contexts: the collapse order */ }; =20 #define MAX_TEST_CASES 256 @@ -1637,6 +1658,7 @@ static int nr_test_cases; .ops =3D o, \ .desc =3D #t, \ .fn =3D t, \ + .order =3D collapse_order, \ }; \ } \ } while (0) @@ -1677,13 +1699,35 @@ int main(int argc, char **argv) =20 parse_test_type(argc, argv); =20 - if (mthp_khugepaged_context && - !(thp_supported_orders() & (1UL << collapse_order))) - ksft_exit_skip("Order %d is not a supported anon THP order\n", - collapse_order); - if (mthp_khugepaged_context && collapse_order <=3D anon_order) - ksft_exit_skip("-c %d needs a source order below it, -s says %d\n", - collapse_order, anon_order); + if (mthp_khugepaged_context) { + unsigned long orders =3D thp_supported_orders(); + + if (collapse_order_set) { + if (!(orders & (1UL << collapse_order))) + ksft_exit_skip("Order %d is not a supported anon THP order\n", + collapse_order); + if (collapse_order <=3D anon_order) + ksft_exit_skip("-c %d needs a source order below it, -s says %d\n", + collapse_order, anon_order); + collapse_orders[nr_collapse_orders++] =3D collapse_order; + } else { + /* + * Every supported order above the source: -s makes the + * fault path hand out folios of that order, so a target + * at or below it has nothing to collapse. + */ + int first =3D anon_order + 1; + + if (first < MIN_MTHP_ORDER) + first =3D MIN_MTHP_ORDER; + for (int i =3D first; i < hpage_pmd_order; i++) { + if (orders & (1UL << i)) + collapse_orders[nr_collapse_orders++] =3D i; + } + if (!nr_collapse_orders) + ksft_print_msg("mTHP cases skipped: no order above the source\n"); + } + } =20 if (mthp_khugepaged_context) { pagemap_fd =3D open("/proc/self/pagemap", O_RDONLY); @@ -1732,7 +1776,17 @@ int main(int argc, char **argv) TEST(collapse_full, khugepaged_context, read_write_file_read_ops); TEST(collapse_full, khugepaged_context, read_write_file_write_ops); TEST(collapse_full, khugepaged_context, shmem_ops); - TEST(collapse_full, mthp_khugepaged_context, anon_ops); + for (int i =3D 0; i < nr_collapse_orders; i++) { + collapse_order =3D collapse_orders[i]; + TEST(collapse_full, mthp_khugepaged_context, anon_ops); + TEST(collapse_empty, mthp_khugepaged_context, anon_ops); + TEST(collapse_single_mthp, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_single_window, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_partial_window, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_max_ptes_none, mthp_khugepaged_context, anon_ops); + TEST(collapse_order_mixed_sources, mthp_khugepaged_context, anon_ops); + } + TEST(collapse_full, madvise_context, anon_ops); TEST(collapse_full, madvise_context, read_only_file_ops); TEST(collapse_full, madvise_context, read_write_file_read_ops); @@ -1740,15 +1794,8 @@ int main(int argc, char **argv) TEST(collapse_full, madvise_context, shmem_ops); =20 TEST(collapse_empty, khugepaged_context, anon_ops); - TEST(collapse_empty, mthp_khugepaged_context, anon_ops); TEST(collapse_empty, madvise_context, anon_ops); =20 - TEST(collapse_single_mthp, mthp_khugepaged_context, anon_ops); - TEST(collapse_order_single_window, mthp_khugepaged_context, anon_ops); - TEST(collapse_order_partial_window, mthp_khugepaged_context, anon_ops); - TEST(collapse_order_max_ptes_none, mthp_khugepaged_context, anon_ops); - TEST(collapse_order_mixed_sources, mthp_khugepaged_context, anon_ops); - TEST(collapse_single_pte_entry, khugepaged_context, anon_ops); TEST(collapse_single_pte_entry, khugepaged_context, read_only_file_ops); TEST(collapse_single_pte_entry, khugepaged_context, read_write_file_read_= ops); @@ -1821,7 +1868,15 @@ int main(int argc, char **argv) for (int i =3D 0; i < nr_test_cases; i++) { struct test_case *t =3D &test_cases[i]; =20 - ksft_print_msg("\n# Run test: %s (%s:%s)\n", t->desc, t->ctx->name, t->o= ps->name); + if (t->ctx =3D=3D &__mthp_khugepaged_context) { + collapse_order =3D t->order; + ksft_print_msg("\n# Run test: %s (%s:%s, order %d)\n", + t->desc, t->ctx->name, t->ops->name, + t->order); + } else { + ksft_print_msg("\n# Run test: %s (%s:%s)\n", t->desc, + t->ctx->name, t->ops->name); + } t->fn(t->ctx, t->ops); } =20 diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/self= tests/mm/run_vmtests.sh index 3a111bc9c29e..98a33f6d15d4 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -392,8 +392,6 @@ CATEGORY=3D"thp" run_test ./khugepaged all:shmem =20 CATEGORY=3D"thp" run_test ./khugepaged -s 4 all:shmem =20 -CATEGORY=3D"thp" run_test ./khugepaged -c 4 mthp_khugepaged:anon - # Try to create XFS if not provided if [ -z "${SPLIT_HUGE_PAGE_TEST_XFS_PATH}" ]; then if test_selected "thp"; then --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 9467D2FA0C6; Sat, 19 Sep 2026 00:25:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777535; cv=none; b=Nl5MgSVABoPL965pdcMi8A0Gfp0J+rQepuOTBk3HcF1P712PGMD4sjvhYkEnA9JtLoUcoe3ivFMou8oswf0qBb8Mz6CsTayJ7Ia/cU919b+v5lSzt5ekdzCor/y3Zb6w9pBmbgfljFGGqmFc6WGL3Octun5ISHxBSgXV3PNyUsw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777535; c=relaxed/simple; bh=z7CFFsZYo8seHlMATOyZ8dSWt3E+lX08WIPxXISyjlE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TCS7ETj+Xvk2oSoDH3uOjaIKBl7zAUgBWWAkE6ZFkIT6/jd9qM6KudMbCPU9W9NemAdQUuRxoAQp79+p09SEW57ZLFQgnRhppr9Dl2HMdvP3DjirjlLeBvHircT6ENjW9h+kshpHbDa+JcjzqnwB9rYi80jfeGdd7lDTsa6BMLg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=cq0M3Hta; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=Ce2n4BGQ; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="cq0M3Hta"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="Ce2n4BGQ" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfhigh.phl.internal (Postfix) with ESMTP id 679471400157; Fri, 18 Sep 2026 20:25:26 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Fri, 18 Sep 2026 20:25:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777526; x= 1789863926; bh=mR9pCgBHcxHPmqpCWWzP1dD7seP1IcB/o66x6smjktA=; b=c q0M3Hta2n0HLYrDD2ASXF11Mqh/y3tR9ybQXSq+Walk/5i3cAjJMWdBPz3mJw9FB iV4NFmdzRVyfFbsO/Y2gqMAyjXUNpuD5RtXZAiFqhsiwzDM53003u2YDbXh8Zn7V KcKS0qU1Dlz1b+sQW0YtlYL1Gl5AHgvPA8tsLyMRpqNKWOBFmMYaow9TVAiPYqqo zfhBs35t/ng0aySv8QHurCwUbpk+snjRZn8Enc6tL8ur0NN5D7RhMBQNs4RiXyk3 jcHZdcF/SVzUqx390A/kWhdxt/yj3pVXMW1CUGdJFDevGEXKKWonJuQS5tnRs0Wn ymDxHuGNg9TZb6xzM5KLw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777526; x=1789863926; bh=m R9pCgBHcxHPmqpCWWzP1dD7seP1IcB/o66x6smjktA=; b=Ce2n4BGQbXgh8pkKt Qz74bilNXehWx3KxQiKv5LH2bygQEiyaSVUEk0Omh8Z0I78bfoTaLZVg6aJiCAhz /ho1DFvwFFeaRC2RhH35DbR7V39KzoVi06XpY6vydpgKjTuD3AVk8PikTHykb8PU 33xfUsvmL2jm7L5WjdTQ/3V6f5dUEQKs27H7D3Qp2CFl5LG46tiqbGNnZPFwOP9i BcIxU04U67p8NvOdB+se50QH9oDcFsXDWHw6/10KLGeJAoITXioEJtP4UTOGwfM7 W3F1G4poVrFpslX7ITJHismsc6sBEDHCKtUTghEvVvzIcVZAQpX7nyVbnxC6JuAd 0JIWA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEr5yKr4sxuQbXqh6mxNPhLx5TPKhba5+X7XnlS/zJ9vgRk2t0FxRNN7MLg+r6CPW Mu6PNIlmN7ZPoxynBFUAJAPtPIX+NuZRIFaOEVqo689ggMVwgiN48ZIazRbbn8524IbcBa VFaAXtPPhux2zoqYNSaL4fhjV7u8LwweVoGm0ycn2eaUICY9i4xSWPBSrUzWeffPDzxnz4 WggCaU37X5tXMmNpoupzaGNfQ+amnYr5ymN7dEq2+UMtHRoF6bcIpmQfw03IlrWSCYa/Ho OSQdXdtFB8WyOz/pBd87oZ5qPprkCNYTXqaz9hCIAMLkvF6M+JOqCuEaEpX/p3iuKuZ/AY 3wxej3Gego0TQyMZGd62Y7jQDn9PLpumtTSUuXVHq454jXGAT6Ba2Z/FsPe8qJEYGhY67k vzCYolx/jEcg+uZOjcRd76zRadiBiUEmJ7sMB+W5Gb0kpRKuykuMwrrhYEOA21lvkP+Fbk AY7HC6MZAegvs4/v8DQiLii18SYYFeAn8dlhftmhhBP8RhMVZNb8ZdGxvPVPb3loR3f5cv MQDOtOocmxOIlkKwi8hKXHgq+rBjWqbGc00gA6jYR+2TWCCj5MM9sybvHkhwb40rXI8tBH vbpdn0WPErWiSV5aDb0TUZvxFOIaL8+c1xMombQG0h+Arjkx5JerQ2n7Lmpw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:25 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 15/19] selftests/mm: check that one khugepaged pass collapses one window Date: Sat, 19 Sep 2026 01:24:45 +0100 Message-ID: <20260919002451.496763-16-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" khugepaged_full_pass() drives the daemon through sysfs: a store to scan_sleep_millisecs wakes it, and full_scans advancing by two marks one pass that started after setup. Every mTHP collapse result in the suite rests on that pair, and nothing checks it. Add khugepaged_sync_check. Each step: - prepare one aligned window - record its source PFNs from pagemap - run one khugepaged_full_pass() barrier - require the window came out collapsed, with exactly one collapse attempt attributed to it The anon events carry no virtual address, so an attempt is matched by the source folio PFN and order that the mm_collapse_huge_page_isolate tracepoint reports. Reading the trace buffer takes four small helpers in vm_util: open an event subsystem's enable file, flip it, clear the buffer, and open it for reading. scan_sleep_millisecs is set to a minute, so a step that took a sleep instead of a wake would blow the budget. Passes 5/5 on x86-64 4K and arm64 64K. Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/Makefile | 1 + .../selftests/mm/khugepaged_sync_check.c | 179 ++++++++++++++++++ tools/testing/selftests/mm/run_vmtests.sh | 2 + tools/testing/selftests/mm/vm_util.c | 38 ++++ tools/testing/selftests/mm/vm_util.h | 4 + 5 files changed, 224 insertions(+) create mode 100644 tools/testing/selftests/mm/khugepaged_sync_check.c diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/= mm/Makefile index cb32cf5d867e..2ed881324911 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -106,6 +106,7 @@ TEST_GEN_FILES +=3D merge TEST_GEN_FILES +=3D rmap TEST_GEN_FILES +=3D folio_split_race_test TEST_GEN_FILES +=3D folio_order_check +TEST_GEN_FILES +=3D khugepaged_sync_check TEST_GEN_FILES +=3D soft-dirty =20 ifeq ($(ARCH),x86_64) diff --git a/tools/testing/selftests/mm/khugepaged_sync_check.c b/tools/tes= ting/selftests/mm/khugepaged_sync_check.c new file mode 100644 index 000000000000..28a9b1ff5d44 --- /dev/null +++ b/tools/testing/selftests/mm/khugepaged_sync_check.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Check that khugepaged_full_pass() drives khugepaged in step: one barrier + * over one prepared window must collapse it with exactly one collapse + * attempt attributed to its source pages, step after step. + * + * scan_sleep_millisecs is a minute so that a step which slept instead of + * being woken blows the budget. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "kselftest.h" +#include "vm_util.h" +#include + +#define BASE_ADDR ((void *)(1UL << 30)) +/* Smallest order khugepaged considers */ +#define TARGET_ORDER 2 +#define NR_ITERATIONS 5 +#define PASS_TIMEOUT_S 30 + +static int pagemap_fd; +static int kpageflags_fd; +static int trace_events_fd =3D -1; +static unsigned long hpage_pmd_size; + +/* + * The events are system-wide: switch them off however the test ends, + * including from inside a helper that gives up. + */ +static void trace_events_off(void) +{ + if (trace_events_fd >=3D 0) + tracing_events_enable(trace_events_fd, false); +} + +/* Count the isolate events whose scan_pfn is one of the window's source P= FNs */ +static int count_attributed(unsigned long *pfns, int nr_pfns, + unsigned int order) +{ + char line[1024]; + int count =3D 0; + FILE *fp; + + fp =3D tracing_open_trace(); + if (!fp) + ksft_exit_fail_msg("Cannot open trace buffer\n"); + + while (fgets(line, sizeof(line), fp)) { + unsigned long val; + unsigned int ord; + char *s, *o; + int i; + + s =3D strstr(line, "mm_collapse_huge_page_isolate:"); + if (!s) + continue; + if (sscanf(s, "mm_collapse_huge_page_isolate: scan_pfn=3D0x%lx", + &val) !=3D 1) + continue; + o =3D strstr(s, "order=3D"); + if (!o || sscanf(o, "order=3D%u", &ord) !=3D 1 || ord !=3D order) + continue; + for (i =3D 0; i < nr_pfns; i++) { + if (val =3D=3D pfns[i]) { + count++; + break; + } + } + } + fclose(fp); + return count; +} + +static void one_step(int iteration) +{ + const size_t window =3D getpagesize() << TARGET_ORDER; + const int nr_pages =3D 1 << TARGET_ORDER; + unsigned long pfns[1 << TARGET_ORDER]; + bool collapsed, passed; + int attributed; + char *p; + int i; + + p =3D mmap(BASE_ADDR, hpage_pmd_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0); + if (p !=3D BASE_ADDR) + ksft_exit_fail_perror("mmap() window"); + + for (i =3D 0; i < nr_pages; i++) { + p[i * getpagesize()] =3D i + 1; + pfns[i] =3D pagemap_get_pfn(pagemap_fd, p + i * getpagesize()); + if (pfns[i] =3D=3D -1UL) + ksft_exit_fail_msg("Source page not present\n"); + } + + /* Clear before enabling so the buffer holds only this step's events */ + if (tracing_clear_trace()) + ksft_exit_fail_msg("Cannot clear the trace buffer\n"); + if (tracing_events_enable(trace_events_fd, true)) + ksft_exit_fail_msg("Cannot enable huge_memory events\n"); + + if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE)) + ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)"); + passed =3D khugepaged_full_pass(PASS_TIMEOUT_S); + + /* Off before anything that can give up: the events are system-wide */ + if (tracing_events_enable(trace_events_fd, false)) + ksft_exit_fail_msg("Cannot disable huge_memory events\n"); + if (!passed) + ksft_exit_fail_msg("khugepaged did not complete a full pass\n"); + + collapsed =3D is_range_backed_by_order(p, window, TARGET_ORDER, + pagemap_fd, kpageflags_fd); + attributed =3D count_attributed(pfns, nr_pages, TARGET_ORDER); + + ksft_test_result(collapsed && attributed =3D=3D 1, + "step %d: window collapsed, %d attributed result(s)\n", + iteration, attributed); + + munmap(p, hpage_pmd_size); +} + +int main(void) +{ + struct thp_settings settings; + int i; + + ksft_print_header(); + + if (!thp_available()) + ksft_exit_skip("Transparent Hugepages not available\n"); + if (!(thp_supported_orders() & (1UL << TARGET_ORDER))) + ksft_exit_skip("Order %d is not a supported anon THP order\n", + TARGET_ORDER); + + hpage_pmd_size =3D read_pmd_pagesize(); + if (!hpage_pmd_size) + ksft_exit_fail_msg("Reading PMD pagesize failed\n"); + pagemap_fd =3D open("/proc/self/pagemap", O_RDONLY); + if (pagemap_fd < 0) + ksft_exit_fail_perror("open(/proc/self/pagemap)"); + kpageflags_fd =3D open("/proc/kpageflags", O_RDONLY); + if (kpageflags_fd < 0) + ksft_exit_skip("open(/proc/kpageflags) requires root\n"); + trace_events_fd =3D tracing_events_open("huge_memory"); + if (trace_events_fd < 0) + ksft_exit_skip("huge_memory events require tracefs and root\n"); + atexit(trace_events_off); + + ksft_set_plan(NR_ITERATIONS); + + thp_save_settings(); + thp_read_settings(&settings); + settings.thp_enabled =3D THP_MADVISE; + settings.thp_defrag =3D THP_DEFRAG_ALWAYS; + settings.khugepaged.defrag =3D 1; + settings.khugepaged.scan_sleep_millisecs =3D 60 * 1000; + settings.khugepaged.alloc_sleep_millisecs =3D 60 * 1000; + settings.khugepaged.max_ptes_none =3D (hpage_pmd_size / getpagesize()) - = 1; + /* One wake must complete one full pass; see khugepaged_full_pass() */ + settings.khugepaged.pages_to_scan =3D 1UL << 24; + for (i =3D 0; i < NR_ORDERS; i++) + settings.hugepages[i].enabled =3D THP_NEVER; + settings.hugepages[TARGET_ORDER].enabled =3D THP_INHERIT; + /* Base of the settings stack; the bottom entry is never popped */ + thp_push_settings(&settings); + + for (i =3D 0; i < NR_ITERATIONS; i++) + one_step(i); + + ksft_finished(); +} diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/self= tests/mm/run_vmtests.sh index 98a33f6d15d4..612a8c4afc53 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -384,6 +384,8 @@ CATEGORY=3D"cow" run_test ./cow =20 CATEGORY=3D"thp" run_test ./folio_order_check =20 +CATEGORY=3D"thp" run_test ./khugepaged_sync_check + CATEGORY=3D"thp" run_test ./khugepaged =20 CATEGORY=3D"thp" run_test ./khugepaged -s 2 diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests= /mm/vm_util.c index c8c5cd8ab6c1..31d331c1c452 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -602,6 +602,44 @@ bool is_range_backed_by_order(char *start, size_t len,= int order, return true; } =20 +#define TRACEFS_ROOT "/sys/kernel/tracing" + +/* + * Returns -1 without tracefs or the subsystem. The events are system-wid= e: + * whoever switches them on has to switch them off again, on every exit pa= th. + */ +int tracing_events_open(const char *subsys) +{ + char path[256]; + + snprintf(path, sizeof(path), TRACEFS_ROOT "/events/%s/enable", + subsys); + return open(path, O_WRONLY); +} + +int tracing_events_enable(int fd, bool enable) +{ + if (pwrite(fd, enable ? "1" : "0", 1, 0) !=3D 1) + return -1; + return 0; +} + +/* Drop what the trace buffer holds so far */ +int tracing_clear_trace(void) +{ + int fd =3D open(TRACEFS_ROOT "/trace", O_WRONLY | O_TRUNC); + + if (fd < 0) + return -1; + close(fd); + return 0; +} + +FILE *tracing_open_trace(void) +{ + return fopen(TRACEFS_ROOT "/trace", "r"); +} + /* If `ioctls' non-NULL, the allowed ioctls will be returned into the var = */ int uffd_register_with_ioctls(int uffd, void *addr, uint64_t len, bool miss, bool wp, bool minor, uint64_t *ioctls) diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests= /mm/vm_util.h index ea48e6a7527e..072a6c756c51 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -121,6 +121,10 @@ int close_procmap(struct procmap_fd *procmap); int write_sysfs(const char *file_path, unsigned long val); int read_sysfs(const char *file_path, unsigned long *val); bool softdirty_supported(void); +int tracing_events_open(const char *subsys); +int tracing_events_enable(int fd, bool enable); +int tracing_clear_trace(void); +FILE *tracing_open_trace(void); =20 static inline int open_self_procmap(struct procmap_fd *procmap_out) { --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 AA81A64A91; Sat, 19 Sep 2026 00:25:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777534; cv=none; b=gMjfyJDpzHMtPv4HxLu3IxOZOByxaFzZTM8Oe8gnVisq8HDkj8OBS7/TaAx3vb7pn1f3Q2q4mXpDa/2arTzKSgUa2KhZHLoIqaLNCCkecL9UMiAU5eM1qt5d0Goi0drASC4JyJPPfeLe5RNYGXZqnGpuGG0wr9MlLUTptDilrw4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777534; c=relaxed/simple; bh=QOynQJBh4q4EJPvRMDD8Lk91MiG59b9uEfxlC+sU8OY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=vA0ABCLoI2XkAjPGo3h1Ko4fOrusDmU8Wv6sj9fV+nkSJ2AnozfnMrvcjN3ps0tqs3Vgsrd1i/yTggMOasXEATW+szYBwO0DS1uexkwhJG1+IzHCuB0LuQlF+Jtrfc7Cw4UtIZnAFwTbpLO3jGeka/v8PRCscCrR38xqDKfgYzA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=C531B/w9; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=EJ2bXYXV; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="C531B/w9"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="EJ2bXYXV" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfout.phl.internal (Postfix) with ESMTP id 22406EC020B; Fri, 18 Sep 2026 20:25:28 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-05.internal (MEProxy); Fri, 18 Sep 2026 20:25:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777528; x= 1789863928; bh=fZqVlKB5Ahaa32ahyNh/7jJg4/PpDw7vdO8QuZXsxdw=; b=C 531B/w9BcMkCVupe0MVCxjVp8V1p3js3+LVE5hMiSWkpZL49wCWQ6GRpNGp0Ufvp RVIwuMBCXoqL/Zy66DJl3b1QTKLfbXtZQl9JLjDBI4fSqn8m6c1i7FOt2lZCQ1lA xD9ZcbJbje4LduVRKUKF+6x2SMJQ1x3aNx+tp2RdWWcLaZ5mFa/z7zKskRI8Bsyv Ou85d3rU3Vv3RKDPA3oUf7Z8wvxHfg+DwqSlfueCWqPCS59xGLIo2Ea+pgZWjAnX 98KdsjYyGMukzoKbS03KZ43Cr5J0RDOCDt2ver55b7eCJPs+3/JwwynRvjc2JRaP HR/wPY2NbsaY+9wU+AL5Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777528; x=1789863928; bh=f ZqVlKB5Ahaa32ahyNh/7jJg4/PpDw7vdO8QuZXsxdw=; b=EJ2bXYXVN7l76TLd5 CyNnJwQfIgzQwaeLfnb/nJMAhC9dj8BvaqjblbLsCQjwVomOy0ur7m8StW3/rLRp KCXFt2R0M/dPI+sTPmU1qkKWbG+D5CPlE6vpt3edKEzPKoHKa+hKKS1Egw0XKCWT XtOWCVRsmLJUfi1OV8e0VHSF2iot+rmsTzEAXa84kiY0v8G1XJsvBsiN7KzHVOx9 ElpZAJEk+nJMNRpJcwSg7dlb6vu6Pi4ns2NWG36kiZprKKfP3OHzAeSGGGZyK7aD Q5iugm9LOucj+7L/qa0JvDN2rE9gXxeSwor/jPEI8grFNJ1jpd7PGyHj5LvHGDju 7LYgw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFdeCslqvGFSSbmnhtdeah2m5aJ+JS0pA7YZcLyjOSl38+BaMD8ToGDiujTmfb1FY hwc6MyP6OTrwB9YZ5cf4L42pzgHwmSUyeXVwqH+rQjzPLdOU7n8WI+L1MfkDKNJ/RFAPzh NlCaR2Fewfb53OcTxvB5KvIlzV5JISHwTvfMhxp8O5pDxNZaie3hjiM7DwEdIJtFqP5P16 IJzN4rLPSq8PL3AzI9mCzJTBQz13YM+0hrUjs/JUttTBmoH69TA/2ONguP0NQ8nHQtvIz0 3uJBRgi18k1Lqi8M3Hll9BkUCzWjsIEVqdaORpYkNdmWXEBvzlr7NFm9TsFftEQV4t5xgo RidHLGDjvW809CzufWbBh8c56jDxQwaPfPyxtZWlsijYNl3bkOOM5eUwvbFai/ThW+ptnr YbJ5S+6TsCsXeHTrZG2ZQMPfCwKXVJqSPivF1ONpgfjsNTm/x6gK3wMqpB1UMdiwTGIx/j 2nBDy8MDG48TRX4TTrn8uhMjhfviO3Jwl3TgEzdr/VMawMuQhK3NqIMUHJkRtAl0WwVqDr QxVkT+Zs+PS2IKu/rRSp+nEuWDddAT9NxviK1OV+l+vyj02W4wWQw74jvvyCEAdrQBZZiI op+gq0MyX9tZbdmoa8Co/VN4XHcRS+SD4lm/F2D2EOwLVsXnLUrjfoC3hbdQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:27 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 16/19] selftests/mm: add khugepaged race harness Date: Sat, 19 Sep 2026 01:24:46 +0100 Message-ID: <20260919002451.496763-17-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" Collapse serialises against faults, GUP, fork, mremap and zapping through a protocol of locks, TLB flushes and refcount checks. No khugepaged selftest exercises any of it under contention. Add khugepaged_race. Six racing threads work the same address space: - two faulters - an MADV_DONTNEED thread - a transient FOLL_PIN thread (gup_test) - a forker - an mremap thread One of three drivers collapses under them: stepped khugepaged, one full pass at a time via khugepaged_full_pass(), so each step covers a known extent; free khugepaged left to run (scan_sleep_millisecs=3D0), for soak; madvise an MADV_COLLAPSE and MADV_DONTNEED loop. Every mode runs in turn unless -m names one, five seconds each. Every supported anon THP order is set to inherit and max_ptes_none is 0, so a window collapses only once fully populated and the racing MADV_DONTNEED steers selection across orders. The rule is that a racing page reads as its pattern or as zero, never anything else. The faulters and fork children check it throughout, and a final sweep checks it again. The other half of the check is the kernel's own assertions, so read dmesg too. The pin thread goes through gup_test, so the harness skips without CONFIG_GUP_TEST or root. The default playground is three shared PMD-sized areas plus the mremap thread's, over two gigabytes at a 512M PMD; -a shrinks it. Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/Makefile | 1 + tools/testing/selftests/mm/khugepaged_race.c | 415 +++++++++++++++++++ tools/testing/selftests/mm/run_vmtests.sh | 2 + 3 files changed, 418 insertions(+) create mode 100644 tools/testing/selftests/mm/khugepaged_race.c diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/= mm/Makefile index 2ed881324911..beacc0f87304 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -107,6 +107,7 @@ TEST_GEN_FILES +=3D rmap TEST_GEN_FILES +=3D folio_split_race_test TEST_GEN_FILES +=3D folio_order_check TEST_GEN_FILES +=3D khugepaged_sync_check +TEST_GEN_FILES +=3D khugepaged_race TEST_GEN_FILES +=3D soft-dirty =20 ifeq ($(ARCH),x86_64) diff --git a/tools/testing/selftests/mm/khugepaged_race.c b/tools/testing/s= elftests/mm/khugepaged_race.c new file mode 100644 index 000000000000..66c9e2c10f66 --- /dev/null +++ b/tools/testing/selftests/mm/khugepaged_race.c @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Race collapse against faults, GUP pins, fork, mremap and MADV_DONTNEED + * over the same ranges. A racing page must read as its pattern or as + * zero, never anything else; the kernel's own assertions in dmesg are the + * other half of the check. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kselftest.h" +#include "vm_util.h" +#include +#include "../../../../mm/gup_test.h" + +#ifndef FOLL_WRITE +#define FOLL_WRITE 0x01 +#endif + +#define BASE_ADDR ((void *)(1UL << 30)) +#define PASS_TIMEOUT_S 30 + +/* + * PMD-sized areas the racing threads share, plus one for the mremap + * thread. -a shrinks it where a PMD is 512M. + */ +#define DEFAULT_SHARED_AREAS 3 +static int nr_shared_areas; +static int nr_areas; + +static unsigned long hpage_pmd_size; +static unsigned long page_size; +/* nr_areas PMD-sized areas; the last one belongs to the mremap thread */ +static char *region; +static char *mremap_area; +static char *mremap_scratch; +static int gup_fd =3D -1; +static volatile int stop; +static volatile int corrupted; + +static unsigned int pattern(unsigned long page_idx) +{ + unsigned int val =3D (unsigned int)page_idx * 2654435761U; + + return val ? val : 1; /* never collides with the zero-fill */ +} + +/* Zero means never written; anything else must be this page's pattern */ +static bool page_is_corrupt(unsigned long page_idx, unsigned int *val) +{ + *val =3D *(unsigned int *)(region + page_idx * page_size); + + return *val && *val !=3D pattern(page_idx); +} + +static void check_page(unsigned long page_idx) +{ + unsigned int val; + + if (page_is_corrupt(page_idx, &val)) { + corrupted =3D 1; + ksft_print_msg("Corruption at page %lu: %#x !=3D %#x\n", + page_idx, val, pattern(page_idx)); + } +} + +static unsigned long shared_pages(void) +{ + return nr_shared_areas * hpage_pmd_size / page_size; +} + +static unsigned long rand_page(unsigned int *seed) +{ + return (unsigned long)rand_r(seed) % shared_pages(); +} + +/* Clamp so a range never reaches the mremap thread's area */ +static unsigned long room_from(unsigned long page_idx, unsigned long want) +{ + unsigned long left =3D shared_pages() - page_idx; + + return want < left ? want : left; +} + +static void *faulter_fn(void *arg) +{ + unsigned int seed =3D (unsigned long)arg; + + while (!stop) { + unsigned long page_idx =3D rand_page(&seed); + + if (rand_r(&seed) & 1) + *(unsigned int *)(region + page_idx * page_size) =3D + pattern(page_idx); + else + check_page(page_idx); + } + return NULL; +} + +static void *dontneed_fn(void *arg) +{ + unsigned int seed =3D (unsigned long)arg; + + while (!stop) { + unsigned long page_idx =3D rand_page(&seed); + unsigned long nr =3D 1UL << (rand_r(&seed) % 6); /* 1..32 pages */ + + madvise(region + page_idx * page_size, + room_from(page_idx, nr) * page_size, MADV_DONTNEED); + usleep(rand_r(&seed) % 500); + } + return NULL; +} + +static void *pinner_fn(void *arg) +{ + unsigned int seed =3D (unsigned long)arg; + + while (!stop) { + struct gup_test gup =3D {}; + unsigned long page_idx =3D rand_page(&seed); + unsigned long nr =3D room_from(page_idx, 16); + + gup.addr =3D (unsigned long)(region + page_idx * page_size); + gup.size =3D nr * page_size; + gup.nr_pages_per_call =3D nr; + gup.gup_flags =3D FOLL_WRITE; + /* Racing MADV_DONTNEED makes transient failures expected */ + ioctl(gup_fd, PIN_FAST_BENCHMARK, &gup); + usleep(rand_r(&seed) % 200); + } + return NULL; +} + +static void *forker_fn(void *arg) +{ + unsigned int seed =3D (unsigned long)arg; + + while (!stop) { + pid_t pid =3D fork(); + + if (pid =3D=3D 0) { + unsigned int val; + int bad =3D 0; + + /* + * No stdio in the child: a thread may hold stdout's + * lock across the fork, and printing under it hangs. + */ + for (int i =3D 0; i < 16; i++) + bad |=3D page_is_corrupt(rand_page(&seed), &val); + _exit(bad); + } + if (pid > 0) { + int wstatus; + + if (waitpid(pid, &wstatus, 0) < 0) + ksft_exit_fail_perror("waitpid()"); + /* A child killed on the read counts too */ + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) + corrupted =3D 1; + } + usleep(rand_r(&seed) % 2000); + } + return NULL; +} + +static void *mremapper_fn(void *arg) +{ + unsigned int seed =3D (unsigned long)arg; + + while (!stop) { + void *p; + + p =3D mremap(mremap_area, hpage_pmd_size, hpage_pmd_size, + MREMAP_MAYMOVE | MREMAP_FIXED, mremap_scratch); + if (p =3D=3D MAP_FAILED) + ksft_exit_fail_perror("mremap() away"); + for (int i =3D 0; i < 8; i++) + mremap_scratch[(rand_r(&seed) % + (hpage_pmd_size / page_size)) * page_size] =3D 1; + p =3D mremap(mremap_scratch, hpage_pmd_size, hpage_pmd_size, + MREMAP_MAYMOVE | MREMAP_FIXED, mremap_area); + if (p =3D=3D MAP_FAILED) + ksft_exit_fail_perror("mremap() back"); + /* The move back unmapped the scratch address: claim it again */ + if (mmap(mremap_scratch, hpage_pmd_size, PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, + -1, 0) !=3D (void *)mremap_scratch) + ksft_exit_fail_perror("mmap() mremap scratch"); + usleep(rand_r(&seed) % 2000); + } + return NULL; +} + +static unsigned long now_ms(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000UL + tv.tv_usec / 1000; +} + +static void usage(void) +{ + fprintf(stderr, + "Usage: khugepaged_race [-d seconds] [-m stepped|free|madvise] [-a areas= ] [-t mask]\n" + "\tWithout -m, every mode runs in turn.\n" + "\t-d: seconds per mode (default 5)\n" + "\t-a: number of shared PMD-sized playground areas (default 3)\n" + "\t-t: bitmask of racing threads to start, for bisecting a failure\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + static const char * const thread_names[] =3D { + "faulter", "faulter2", "dontneed", "pinner", "forker", + "mremapper", + }; + void *(*const thread_fns[])(void *) =3D { + faulter_fn, faulter_fn, dontneed_fn, pinner_fn, forker_fn, + mremapper_fn, + }; + const int nr_threads =3D ARRAY_SIZE(thread_names); + pthread_t threads[ARRAY_SIZE(thread_names)]; + static const char * const all_modes[] =3D { "stepped", "free", "madvise" = }; + const char *one_mode[1]; + const char * const *modes =3D all_modes; + int nr_modes =3D ARRAY_SIZE(all_modes); + const char *mode_arg =3D NULL; + struct thp_settings settings; + unsigned long end_ms; + int duration_s =3D 5; + unsigned long thread_mask =3D ~0UL; + int nr_areas_arg =3D 0; + unsigned long i; + int steps =3D 0; + int opt; + + while ((opt =3D getopt(argc, argv, "a:d:m:t:h")) !=3D -1) { + switch (opt) { + case 'a': + nr_areas_arg =3D atoi(optarg); + break; + case 'd': + duration_s =3D atoi(optarg); + break; + case 'm': + mode_arg =3D optarg; + break; + case 't': + thread_mask =3D strtoul(optarg, NULL, 0); + break; + default: + usage(); + } + } + + if (mode_arg) { + if (strcmp(mode_arg, "stepped") && strcmp(mode_arg, "free") && + strcmp(mode_arg, "madvise")) + usage(); + one_mode[0] =3D mode_arg; + modes =3D one_mode; + nr_modes =3D 1; + } + + ksft_print_header(); + if (!thp_available()) + ksft_exit_skip("Transparent Hugepages not available\n"); + + page_size =3D getpagesize(); + hpage_pmd_size =3D read_pmd_pagesize(); + if (!hpage_pmd_size) + ksft_exit_fail_msg("Reading PMD pagesize failed\n"); + + gup_fd =3D open("/sys/kernel/debug/gup_test", O_RDWR); + if (gup_fd < 0) + ksft_exit_skip("/sys/kernel/debug/gup_test requires CONFIG_GUP_TEST and = root\n"); + + nr_shared_areas =3D nr_areas_arg > 0 ? nr_areas_arg : DEFAULT_SHARED_AREA= S; + nr_areas =3D nr_shared_areas + 1; + + /* + * MREMAP_FIXED unmaps whatever is in the way without saying so, so + * claim the mremap thread's scratch address up front. + */ + mremap_scratch =3D (char *)BASE_ADDR + 2 * nr_areas * hpage_pmd_size; + if (mmap(mremap_scratch, hpage_pmd_size, PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, + -1, 0) !=3D (void *)mremap_scratch) + ksft_exit_fail_perror("mmap() mremap scratch"); + + ksft_set_plan(nr_modes); + + thp_save_settings(); + thp_read_settings(&settings); + + /* Base of the settings stack; the bottom entry is never popped */ + thp_push_settings(&settings); + + for (int m =3D 0; m < nr_modes; m++) { + const char *mode =3D modes[m]; + + thp_read_settings(&settings); + settings.thp_enabled =3D THP_MADVISE; + settings.thp_defrag =3D THP_DEFRAG_ALWAYS; + settings.shmem_enabled =3D SHMEM_NEVER; + settings.khugepaged.defrag =3D 1; + settings.khugepaged.scan_sleep_millisecs =3D + strcmp(mode, "free") ? 1000 : 0; + settings.khugepaged.alloc_sleep_millisecs =3D 10; + /* + * mTHP collapse honours only 0 or HPAGE_PMD_NR - 1 here, and 0 + * keeps a step from being spent on PMD allocations that racing + * MADV_DONTNEED will not let succeed. + */ + settings.khugepaged.max_ptes_none =3D 0; + /* One wake, one pass: the playground plus the forked children's copies = */ + settings.khugepaged.pages_to_scan =3D + nr_areas * (hpage_pmd_size / page_size) * 8; + for (i =3D 0; i < NR_ORDERS; i++) { + if (thp_supported_orders() & (1UL << i)) + settings.hugepages[i].enabled =3D THP_INHERIT; + } + thp_push_settings(&settings); + + region =3D mmap(BASE_ADDR, nr_areas * hpage_pmd_size, + PROT_READ | PROT_WRITE, MAP_ANONYMOUS | + MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0); + if (region !=3D BASE_ADDR) + ksft_exit_fail_perror("mmap() playground"); + mremap_area =3D region + nr_shared_areas * hpage_pmd_size; + + /* Populate so the first pass has something to collapse */ + for (i =3D 0; i < nr_shared_areas * hpage_pmd_size / page_size; i++) + *(unsigned int *)(region + i * page_size) =3D pattern(i); + memset(mremap_area, 1, hpage_pmd_size); + if (madvise(region, nr_areas * hpage_pmd_size, MADV_HUGEPAGE)) + ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)"); + + for (i =3D 0; i < nr_threads; i++) { + if (!(thread_mask & (1UL << i))) { + threads[i] =3D 0; + continue; + } + if (pthread_create(&threads[i], NULL, thread_fns[i], + (void *)(i + 1))) + ksft_exit_fail_perror(thread_names[i]); + } + + end_ms =3D now_ms() + duration_s * 1000UL; + if (!strcmp(mode, "stepped")) { + while (now_ms() < end_ms && !corrupted) { + if (!khugepaged_full_pass(PASS_TIMEOUT_S)) + ksft_exit_fail_msg("khugepaged pass timed out\n"); + steps++; + } + } else if (!strcmp(mode, "free")) { + while (now_ms() < end_ms && !corrupted) + usleep(100 * 1000); + } else { /* madvise */ + while (now_ms() < end_ms && !corrupted) { + for (i =3D 0; i < nr_shared_areas; i++) { + madvise(region + i * hpage_pmd_size, + hpage_pmd_size, MADV_COLLAPSE); + } + madvise(region, nr_shared_areas * hpage_pmd_size, + MADV_DONTNEED); + steps++; + } + } + + stop =3D 1; + for (i =3D 0; i < nr_threads; i++) { + if (threads[i]) + pthread_join(threads[i], NULL); + } + + for (i =3D 0; i < nr_shared_areas * hpage_pmd_size / page_size; i++) + check_page(i); + + ksft_test_result(!corrupted, + "%s: %ds, %d steps, no corruption\n", + mode, duration_s, steps); + + /* The next mode maps the same fixed address with its own settings */ + munmap(region, nr_areas * hpage_pmd_size); + thp_pop_settings(); + stop =3D 0; + steps =3D 0; + + if (corrupted) { + /* Memory is suspect; the rest would prove nothing */ + while (++m < nr_modes) + ksft_test_result_skip("%s: skipped after corruption\n", + modes[m]); + break; + } + } + + ksft_finished(); +} diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/self= tests/mm/run_vmtests.sh index 612a8c4afc53..6990485b1a9d 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -386,6 +386,8 @@ CATEGORY=3D"thp" run_test ./folio_order_check =20 CATEGORY=3D"thp" run_test ./khugepaged_sync_check =20 +CATEGORY=3D"thp" run_test ./khugepaged_race + CATEGORY=3D"thp" run_test ./khugepaged =20 CATEGORY=3D"thp" run_test ./khugepaged -s 2 --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 2E7A327280A; Sat, 19 Sep 2026 00:25:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777536; cv=none; b=b20CkehBM7c1YQzOZGmCvLVt85Flq8DoecxlRE2f9VEPH2yd0SgJ91c9tYtin4hAXEm5/G/pELX7lGgBO/5gouTrx3Sw0HpAKG6pvs04q4ZAElEmOo51ieKvKaNnchQe4lzwOt4kYXxfWgY1ItEbfW7h0xpp1APRXEZLC7BpVtI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777536; c=relaxed/simple; bh=6h3AsLvNob4o9n5kE4I7Sb+wFTfjJdGPoFllWv+34jY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jkx8wOqzI9OvXBdp7ZoNg5RSuKX3JQ1u+Xl3B9piIx0CSPJPJnRy11ksXTjGV8JeNDBl4ARRQVNfw9/Bdj2hzvjKtE3LaAqeL8SVz0Q1RYHPKmgTpvqJZcmt6azbhFrSZIzuMbBK33PHnnv3GxZ2UL/Yc/gmEdKc/Z07skUTeKE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=mbqnUeIX; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=GZ3A7Gqb; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="mbqnUeIX"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="GZ3A7Gqb" Received: from phl-compute-12.internal (phl-compute-12.internal [10.202.2.52]) by mailfhigh.phl.internal (Postfix) with ESMTP id 1747E1400165; Fri, 18 Sep 2026 20:25:30 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-12.internal (MEProxy); Fri, 18 Sep 2026 20:25:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777530; x= 1789863930; bh=ufxG1px/IbSsOIWc/2sGIs7BPQfcDu7SsQiuBytVLoo=; b=m bqnUeIX3B+AS2eiWoVa88fUnn1LmIaxXhlQMnXqoP7zRENalwX7ApfFe+6KCSZ5K GS0UR7yuS6MDttmCNOz6WkjRFtPvJi0ozkDDuTsN+5BmXCPZM99HnQ/v4UKHPWED hOCYx0TwXKuiQC691tdb/Q5I4PuhH9h+MViSLui0CrX4kPJEoIWTfLRByDZp6rJo Lh+eMcF6aeuiiN00EXRgFPIBCC9A+WpGgafpORXeqCseDWJgay65LpBB0i/KKXfG 2S41/zSoplg3wUEzzwXhBbuexYs8nTvcCOr1llleWTAUVh7FNCKrBW5P3fvgt/wD aaXfLRc/4sXXzunQ1nHaw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777530; x=1789863930; bh=u fxG1px/IbSsOIWc/2sGIs7BPQfcDu7SsQiuBytVLoo=; b=GZ3A7GqbeiaN39XlB vs6pqwn818UhRER3mMC14qSWEjU8A3yrgTrDDJ8EwdgikDzKkuZ0rLaJ0FAEa3Yf h/LFQmmTn0hrkxa4RH6DsCVTp81f40VfGLdxjG4+QvScsqwinRmEWWDodCcIjuk+ 4mvWfXB3YGna9dofBydJFNeM2JHrlSRS0OUEG3Bd10tM3dJeFDPql3hXBGn051vZ pW2dkpZHaDhG23vrx9wxwr372mBedSNVz8RqkUkL2RO2XaPkeaCNMprHs1Ypbi2o +SfIhuill2aSeqwtt+Vd5GrZSLDesAnFCfLoQzta+7ZG+U8iSmEbdbdDMnrCVjts /BUlw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMWh knMy8hezREC8xLos5iJLzU0pvnkntBZ1CmYDMNQQB5vgpf+cSpSatuEUu4n2Rwovhj5ZWB rLqO0pR+NBc0xV58OOlGf5KrKV7WHNRBL2k+FMBT2XI5CGpJj29oXJx4Rb24l7tXwjUitM vQotH3iBuCJWkcXckW67rCOx96tauCl+BdOq2Uk+5zHD2wmmkU6wRDA8KcTfBinaysDgOe LKYnL/uVTuCsp483J25Ot5qaClGU/e13U9aMtEEXj772wDku9anRx/ugiwvgz9jEJ069lm +ijZefoHgqcpFVB9VAzHcC7pTVrIlRe9y3Tlb+IFijqwXSm0SFPbcrI4tghQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:29 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 17/19] selftests/mm: race the collapse of windows with holes Date: Sat, 19 Sep 2026 01:24:47 +0100 Message-ID: <20260919002451.496763-18-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" The harness pins max_ptes_none to 0, so khugepaged only collapses a window once every PTE in it is present. A window with holes takes a different route, and never gets raced. A hole is zero-filled in the new folio rather than copied. Which slots count as holes keeps moving under the racing MADV_DONTNEED, right up to the moment the PMD is detached. Run both ends of the occupancy scale for every driver mode, one after the other. mTHP collapse supports only those two, 0 and HPAGE_PMD_NR - 1, and coerces anything between them to 0. Each result says which end it ran: ok 1 stepped/strict: 5s, 231 steps, no corruption ok 2 stepped/holes: 5s, 194 steps, no corruption Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged_race.c | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged_race.c b/tools/testing/s= elftests/mm/khugepaged_race.c index 66c9e2c10f66..6575045c0482 100644 --- a/tools/testing/selftests/mm/khugepaged_race.c +++ b/tools/testing/selftests/mm/khugepaged_race.c @@ -236,6 +236,8 @@ int main(int argc, char **argv) const int nr_threads =3D ARRAY_SIZE(thread_names); pthread_t threads[ARRAY_SIZE(thread_names)]; static const char * const all_modes[] =3D { "stepped", "free", "madvise" = }; + static const bool occupancies[] =3D { false, true }; /* strict, holes */ + const int nr_occupancies =3D ARRAY_SIZE(occupancies); const char *one_mode[1]; const char * const *modes =3D all_modes; int nr_modes =3D ARRAY_SIZE(all_modes); @@ -303,7 +305,7 @@ int main(int argc, char **argv) -1, 0) !=3D (void *)mremap_scratch) ksft_exit_fail_perror("mmap() mremap scratch"); =20 - ksft_set_plan(nr_modes); + ksft_set_plan(nr_modes * nr_occupancies); =20 thp_save_settings(); thp_read_settings(&settings); @@ -311,8 +313,9 @@ int main(int argc, char **argv) /* Base of the settings stack; the bottom entry is never popped */ thp_push_settings(&settings); =20 - for (int m =3D 0; m < nr_modes; m++) { - const char *mode =3D modes[m]; + for (int run =3D 0; run < nr_modes * nr_occupancies; run++) { + const char *mode =3D modes[run / nr_occupancies]; + bool holes =3D occupancies[run % nr_occupancies]; =20 thp_read_settings(&settings); settings.thp_enabled =3D THP_MADVISE; @@ -322,12 +325,14 @@ int main(int argc, char **argv) settings.khugepaged.scan_sleep_millisecs =3D strcmp(mode, "free") ? 1000 : 0; settings.khugepaged.alloc_sleep_millisecs =3D 10; + /* - * mTHP collapse honours only 0 or HPAGE_PMD_NR - 1 here, and 0 - * keeps a step from being spent on PMD allocations that racing - * MADV_DONTNEED will not let succeed. + * mTHP collapse honours only 0 or HPAGE_PMD_NR - 1 here. The two + * ends race different paths: a strict window has every PTE + * present, a hole-heavy one is mostly zero-filled. */ - settings.khugepaged.max_ptes_none =3D 0; + settings.khugepaged.max_ptes_none =3D holes ? + (hpage_pmd_size / page_size) - 1 : 0; /* One wake, one pass: the playground plus the forked children's copies = */ settings.khugepaged.pages_to_scan =3D nr_areas * (hpage_pmd_size / page_size) * 8; @@ -393,8 +398,9 @@ int main(int argc, char **argv) check_page(i); =20 ksft_test_result(!corrupted, - "%s: %ds, %d steps, no corruption\n", - mode, duration_s, steps); + "%s/%s: %ds, %d steps, no corruption\n", + mode, holes ? "holes" : "strict", + duration_s, steps); =20 /* The next mode maps the same fixed address with its own settings */ munmap(region, nr_areas * hpage_pmd_size); @@ -404,9 +410,11 @@ int main(int argc, char **argv) =20 if (corrupted) { /* Memory is suspect; the rest would prove nothing */ - while (++m < nr_modes) - ksft_test_result_skip("%s: skipped after corruption\n", - modes[m]); + while (++run < nr_modes * nr_occupancies) + ksft_test_result_skip("%s/%s: skipped after corruption\n", + modes[run / nr_occupancies], + occupancies[run % nr_occupancies] ? + "holes" : "strict"); break; } } --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (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 190342F3C07; Sat, 19 Sep 2026 00:25:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777536; cv=none; b=Ebqyy9Y7f2nkXMp8+5NEP37qs9owvhVO4JVpEcSlcR7kr02KZqslzWuOCNONoUMpkDT/GdmSiTBS8i1I6SIZmtWrICcYLzKe+yjuqSQfjyUkecNMbxfIDvq1fbfDW34oLmWDjf8Nt3BTLlnhTf/ymJOKclbDynGDXOxJtqGJUlY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777536; c=relaxed/simple; bh=GvKrau4wLEyE8GU3Un/RSoTxypsV0iNq26gyohcwXj0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T7OjvTc+bKs30v0AKpPc3IEWmUoSl+NClGmDsdZMkFFC2Z/ALiBUqcM/sc1SmNC1Kb79epyMuI9RFCI40qA3lp4GlAsE/+Mjte9zghJWiYqbPlenfKBkw9qIOhys8k0y+Znjr/h+fcz5eG+awbrzasq3cCgNTnIscw6Hpq+vUio= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=ANdQgC+W; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=OUvKr+t8; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="ANdQgC+W"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="OUvKr+t8" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfout.phl.internal (Postfix) with ESMTP id B4C08EC0232; Fri, 18 Sep 2026 20:25:31 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Fri, 18 Sep 2026 20:25:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777531; x= 1789863931; bh=0hSKa8/sTyi+jf6ploRbE5LilQNqTTyCg9z8yjvcVBA=; b=A NdQgC+W2bZFOcVIoI4T8bHZS0N1i8PAzJVNbgghGQyba3z7Y7q3XMa8rPUkQTTgm f8w6jJBqUVAq7dFgNdvrv+c2xWLmizvRXCQXaDlkP44OtYa57KIbYPj51wu+S6p1 kxHANAVyrHR+b5OFD+p0KYdOzNBaqrgRTMG21buK75KTh2GE8aUuTo3o21sXxumX 5V8Bqzhy23s1sNpXg5BQ82dVrxrerIOWUwIMCwBC27W1JoBHvVieGfMXt5WZMr5j hDFFPUbNURVCk+oSdnoYnxNXlfISP062th4XcJQ2mezNXu70iEgt7GiQMn7uegF/ 9dRShJfYweO/zQaIyQfRg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777531; x=1789863931; bh=0 hSKa8/sTyi+jf6ploRbE5LilQNqTTyCg9z8yjvcVBA=; b=OUvKr+t8nldXfgooL J15lfCu1YPcoKvc6mCAds2YTBu2p1wwGaDuFmLKcMlklPcTX0aC+Q/V0GWUaMtyA jq0zOO+Q44xn0p+U0GxiUWf26eDpnqONHWoBOl169cRkRC9pWjS2cRUXFc0rmas+ pg1HCk52i6FrhnMUFpxRpAd52ikU4OdAOYcSO/kQoGnA+26vIHtUdVce1kamILfQ t0knQO5zBY3MsU394pEPu8ez1rdDkPtq3xsWQBhWB7hesv0nalFExpG1P1wfytrF Tc8MslSC+FCUCb/ffXE/A0sEPrgo7T7ZcMqUKQWmpXAAJtwFMIqU0keuns0zUung a9Kpw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFdeCslqvGFSSbmnhtdeah2m5aJ+JS0pA7YZcLyjOSl38+BaMD8ToGDiujTmfb1FY hwc6MyP6OTrwB9YZ5cf4L42pzgHwmSUyeXVwqH+rQjzPLdOU7n8WI+L1MfkDKNJ/RFAPzh NlCaR2Fewfb53OcTxvB5KvIlzV5JISHwTvfMhxp8O5pDxNZaie3hjiM7DwEdIJtFqP5P16 IJzN4rLPSq8PL3AzI9mCzJTBQz13YM+0hrUjs/JUttTBmoH69TA/2ONguP0NQ8nHQtvIz0 3uJBRgi18k1Lqi8M3Hll9BkUCzWjsIEVqdaORpYkNdmWXEBvzlr7NFm9TsFftEQV4t5xs5 JYtk2rCMb4KS87zC7serU0f9USLxq0fLzi7UaQV0oWZxxP9NbTq3K9wpk2GV/8P30K8k0A p0SSrjokXJVK9PMUwRPKpAu5O6c3/d1Wjf2Q/6rduQ0xbcl0kyQp/CLcSqGkFVNaSN3E3O nu5z2Su6ZetWS2nFgWLQ+bQWNOB9lDQgXXc9oGBeAchiC3RtK6tTOahUr6v/M3fAgbKRCR 2nfMVRtUvk+6ZLz1wQ8G1tIpZxTNRonsWIIxDluPYOuPeVzJvUk0UIgeO0zr3iORf76ofj MKMjYL2NgwtDyckSq3QcqMKsuxvhlXXyjxvbq9CMsa6fjH2G5jLODhL5SX6Q X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:31 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 18/19] selftests/mm: add memory-pressure threads to the khugepaged race harness Date: Sat, 19 Sep 2026 01:24:48 +0100 Message-ID: <20260919002451.496763-19-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" The harness races collapse against faults, pins, fork, mremap and MADV_DONTNEED, but nothing in it runs reclaim or compaction against the collapse. Add two more threads, and run every mode and occupancy limit both with and without them: - pageout: cycles MADV_PAGEOUT over a region of its own, faults it back in and checks the content each round, since a page's pattern must survive the trip through swap. Left out when the host has no swap, because then there is no anon reclaim to drive. - compactor: writes /proc/sys/vm/compact_memory in a loop. Compaction isolates and migrates folios, so it competes with a collapse for the pages it is gathering, with refcount elevations and migration entries of its own. Each result says whether it ran under pressure: ok 2 stepped/strict/pressure: 5s, 88 steps, no corruption A full run is now twelve combinations; -m picks one mode, -d shortens each run. Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged_race.c | 142 ++++++++++++++++--- 1 file changed, 122 insertions(+), 20 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged_race.c b/tools/testing/s= elftests/mm/khugepaged_race.c index 6575045c0482..68046f0bf6d3 100644 --- a/tools/testing/selftests/mm/khugepaged_race.c +++ b/tools/testing/selftests/mm/khugepaged_race.c @@ -44,6 +44,8 @@ static unsigned long page_size; static char *region; static char *mremap_area; static char *mremap_scratch; +static char *pageout_area; +static size_t pageout_size; static int gup_fd =3D -1; static volatile int stop; static volatile int corrupted; @@ -204,6 +206,69 @@ static void *mremapper_fn(void *arg) return NULL; } =20 +/* + * Swap traffic and LRU churn on a region nothing else writes, so a page's + * pattern must survive the trip through swap exactly. + */ +static void *pageout_fn(void *arg) +{ + unsigned int seed =3D (unsigned long)arg; + unsigned long nr =3D pageout_size / page_size; + unsigned long i; + + for (i =3D 0; i < nr; i++) + *(unsigned int *)(pageout_area + i * page_size) =3D pattern(i); + + while (!stop) { + madvise(pageout_area, pageout_size, MADV_PAGEOUT); + for (i =3D 0; i < nr && !stop; i++) { + unsigned int val =3D *(unsigned int *)(pageout_area + + i * page_size); + + if (val !=3D pattern(i)) { + corrupted =3D 1; + ksft_print_msg("Pageout corruption at page %lu: %#x !=3D %#x\n", + i, val, pattern(i)); + } + } + usleep(rand_r(&seed) % 2000); + } + return NULL; +} + +/* Compaction migrates the collapse sources while they are being gathered = */ +static void *compactor_fn(void *arg) +{ + unsigned int seed =3D (unsigned long)arg; + int fd =3D open("/proc/sys/vm/compact_memory", O_WRONLY); + + if (fd < 0) { + ksft_print_msg("No compact_memory; compactor idle\n"); + return NULL; + } + while (!stop) { + if (write(fd, "1", 1) < 0) + break; + usleep(10000 + rand_r(&seed) % 100000); + } + close(fd); + return NULL; +} + +static bool swap_available(void) +{ + char line[256]; + int lines =3D 0; + FILE *fp =3D fopen("/proc/swaps", "r"); + + if (!fp) + return false; + while (fgets(line, sizeof(line), fp)) + lines++; + fclose(fp); + return lines > 1; +} + static unsigned long now_ms(void) { struct timeval tv; @@ -227,17 +292,23 @@ int main(int argc, char **argv) { static const char * const thread_names[] =3D { "faulter", "faulter2", "dontneed", "pinner", "forker", - "mremapper", + "mremapper", "pageout", "compactor", }; void *(*const thread_fns[])(void *) =3D { faulter_fn, faulter_fn, dontneed_fn, pinner_fn, forker_fn, - mremapper_fn, + mremapper_fn, pageout_fn, compactor_fn, }; + enum { T_FAULTER, T_FAULTER2, T_DONTNEED, T_PINNER, T_FORKER, + T_MREMAPPER, T_PAGEOUT, T_COMPACTOR }; + const unsigned long pageout_bit =3D 1UL << T_PAGEOUT; + const unsigned long compactor_bit =3D 1UL << T_COMPACTOR; const int nr_threads =3D ARRAY_SIZE(thread_names); pthread_t threads[ARRAY_SIZE(thread_names)]; static const char * const all_modes[] =3D { "stepped", "free", "madvise" = }; static const bool occupancies[] =3D { false, true }; /* strict, holes */ + static const bool pressures[] =3D { false, true }; /* quiet, under pressu= re */ const int nr_occupancies =3D ARRAY_SIZE(occupancies); + const int nr_pressures =3D ARRAY_SIZE(pressures); const char *one_mode[1]; const char * const *modes =3D all_modes; int nr_modes =3D ARRAY_SIZE(all_modes); @@ -246,6 +317,9 @@ int main(int argc, char **argv) unsigned long end_ms; int duration_s =3D 5; unsigned long thread_mask =3D ~0UL; + unsigned long base_mask; + bool have_swap; + char label[64]; int nr_areas_arg =3D 0; unsigned long i; int steps =3D 0; @@ -305,7 +379,13 @@ int main(int argc, char **argv) -1, 0) !=3D (void *)mremap_scratch) ksft_exit_fail_perror("mmap() mremap scratch"); =20 - ksft_set_plan(nr_modes * nr_occupancies); + base_mask =3D thread_mask; + have_swap =3D swap_available(); + if (!have_swap) + /* No swap, no anon reclaim: compaction-only pressure */ + ksft_print_msg("no swap: the pageout thread is not started\n"); + + ksft_set_plan(nr_modes * nr_occupancies * nr_pressures); =20 thp_save_settings(); thp_read_settings(&settings); @@ -313,9 +393,25 @@ int main(int argc, char **argv) /* Base of the settings stack; the bottom entry is never popped */ thp_push_settings(&settings); =20 - for (int run =3D 0; run < nr_modes * nr_occupancies; run++) { - const char *mode =3D modes[run / nr_occupancies]; - bool holes =3D occupancies[run % nr_occupancies]; + for (int run =3D 0; run < nr_modes * nr_occupancies * nr_pressures; run++= ) { + int rem =3D run % (nr_occupancies * nr_pressures); + const char *mode =3D modes[run / (nr_occupancies * nr_pressures)]; + bool holes =3D occupancies[rem / nr_pressures]; + bool pressure =3D pressures[rem % nr_pressures]; + + snprintf(label, sizeof(label), "%s/%s%s", mode, + holes ? "holes" : "strict", pressure ? "/pressure" : ""); + if (corrupted) { + /* Memory is suspect; the rest would prove nothing */ + ksft_test_result_skip("%s: skipped after corruption\n", label); + continue; + } + + thread_mask =3D base_mask; + if (!pressure) + thread_mask &=3D ~(pageout_bit | compactor_bit); + else if (!have_swap) + thread_mask &=3D ~pageout_bit; =20 thp_read_settings(&settings); settings.thp_enabled =3D THP_MADVISE; @@ -349,6 +445,20 @@ int main(int argc, char **argv) ksft_exit_fail_perror("mmap() playground"); mremap_area =3D region + nr_shared_areas * hpage_pmd_size; =20 + if (thread_mask & pageout_bit) { + /* Enough to drive real reclaim without swamping a small guest */ + pageout_size =3D 4 * hpage_pmd_size; + if (pageout_size < 16UL << 20) + pageout_size =3D 16UL << 20; + if (pageout_size > 64UL << 20) + pageout_size =3D 64UL << 20; + pageout_area =3D mmap(NULL, pageout_size, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (pageout_area =3D=3D MAP_FAILED) + ksft_exit_fail_perror("mmap() pageout area"); + } + /* Populate so the first pass has something to collapse */ for (i =3D 0; i < nr_shared_areas * hpage_pmd_size / page_size; i++) *(unsigned int *)(region + i * page_size) =3D pattern(i); @@ -397,26 +507,18 @@ int main(int argc, char **argv) for (i =3D 0; i < nr_shared_areas * hpage_pmd_size / page_size; i++) check_page(i); =20 - ksft_test_result(!corrupted, - "%s/%s: %ds, %d steps, no corruption\n", - mode, holes ? "holes" : "strict", - duration_s, steps); + ksft_test_result(!corrupted, "%s: %ds, %d steps, no corruption\n", + label, duration_s, steps); =20 /* The next mode maps the same fixed address with its own settings */ munmap(region, nr_areas * hpage_pmd_size); + if (pageout_area) { + munmap(pageout_area, pageout_size); + pageout_area =3D NULL; + } thp_pop_settings(); stop =3D 0; steps =3D 0; - - if (corrupted) { - /* Memory is suspect; the rest would prove nothing */ - while (++run < nr_modes * nr_occupancies) - ksft_test_result_skip("%s/%s: skipped after corruption\n", - modes[run / nr_occupancies], - occupancies[run % nr_occupancies] ? - "holes" : "strict"); - break; - } } =20 ksft_finished(); --=20 2.54.0 From nobody Fri Sep 25 21:41:31 2026 Received: from fhigh-a2-smtp.messagingengine.com (fhigh-a2-smtp.messagingengine.com [103.168.172.153]) (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 247962D9ECA; Sat, 19 Sep 2026 00:25:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777537; cv=none; b=Ad/GZVDIWuna66Ued2JSIau2jDERA/UbZNXtVAALTmW0vjEJxHhpzYbOPR+9Uvw7oZ4gJ/30lmDT8RiRjPR0Q+VhD+tgFEVTUSqg0pfzicbicbAhf2JVzpxttr40oJK39+fcGhd2KqeAk1ivDdsAXgMlYpIMdLr8gtZZ8CHUvtE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789777537; c=relaxed/simple; bh=GHzb2sX1MYx0DA0jEequmqnv3k+ULP4AiYdtfrV97L8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WFPA9CMhDQezks+QynJTln/qPwwLcGMxQ9k/btrRMSvd05al0rYStXDBNhWB5V2OcZjdMYvdbfITELe5j7bFJxwZggnDjNEzPS6Lk7glBEcGJaG4/BbZXN5qttB+7YAPtazGNUN8PECi2N6ezNs1gjKW8fJpB+qCnHawCtQoaEk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name; spf=pass smtp.mailfrom=shutemov.name; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b=JTORV64X; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=NJfCtBuq; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=shutemov.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=shutemov.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=shutemov.name header.i=@shutemov.name header.b="JTORV64X"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="NJfCtBuq" Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailfhigh.phl.internal (Postfix) with ESMTP id 5DED1140016D; Fri, 18 Sep 2026 20:25:33 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Fri, 18 Sep 2026 20:25:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shutemov.name; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm2; t=1789777533; x= 1789863933; bh=ZsEX+0ruB8DSYOnav/6r+swke5RHnhh3EckcILtj0PU=; b=J TORV64XLJgBCCkzrwuTlkYSUGxEIV88/s4K2S3TWXPhU2afKbpCKqypA8RyMDPFp nz8AT2tEVVePtF4vM/HGihaX3p34vp92p/0duTObgRkjj4c04Qdud1xxd5ohpM9s STMw4LooBS2I0CLf/JL851GBDq+Ew3JGE82UTj0FTp5PUNtVWocrqfyOx+uiHL99 B/BhoPC/8agF/W0oqwwfUc1p7Y8wVpEh9edve0kFXOI+p9oc1ZzlxXF5yDjJhgC3 gE1Kkza/3ixLh4jENZCGWiqZaKUcCMNn9x4IDpJAQiMyxbmHMDgX+eAdcutanLuw ySqMmvKRshlH6kYgYjl4Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1789777533; x=1789863933; bh=Z sEX+0ruB8DSYOnav/6r+swke5RHnhh3EckcILtj0PU=; b=NJfCtBuqPjxHtCUF5 rA8X4eBVknkb76xvoX9WUnD0U4Eg2lvAB4IRZoueZM7VU6OBnXVJHtwYYGEsl+hb POz7J4FuQMVT6e24HbeyX0OMQsgyuIntNHkgsJJtuThv2mPIveojwc3/fBFjTt2W zbelc0ACznmSJ9n5/o8rjYYzN/C+P34PcUrnYAGgOaK8s3m0tkuiQiBjggsCj7UY WY0FkI6nhcHFN/abniVMd/12jlquIdpysPw/xhf0Eu5tXKUVzEffZaZagPQtSB9t 0Kqmzynla3sQiOWFh88Xg2NIvFrPK+UQt11NrAg84JvFGAylij2HZI7Wy1SrOhpg dtzKw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFyC+XeKYnZ766rqTYe4SsoatN0doBd7ADemiperjFlmE10ggdkgYpZeWmNOU4aBc lm02WEvCO2QGG+A0SGXMzCjVWjDSVCQ5WJ/xmSMbLZJLqVjt5aEnrGd0hUbHPJ/ejcqjFa xrmYY/YNxh9EpvRrTjNMqslNp6oZ1XKAjj0b9YUD/U+Umt4HJhNRFStrIx7jR3Gf+CAD8k /TwEvtSve0+WgA7utVqBt9LeXDUSIUkf7dn/1M9JWIyORT8Kp2cNKrwYutOzK/Z35sBm5S qWNICJAq9yYROUOkEgx1cQSYtjkPP2DMZwKGXS3JxTiE+xMdBmJUepOSBHs3/DvnVTIMEa MZHxhDKY0xlI1hrODY+2xppEEtaciMYpLIJfUlGrUvkY7nVYwYEAcgwwYVB4MdOWOT4+zn QUHtQxYd0JkjouR8IN9JCkskC6nPSkcQMYQkMbtjGp985VZy7s/Ivh8h/z80/05cYhrJQ7 k6eEdO+Qy2SD34yH4g0yfwfXsVYLzRF2iPpq21uB1ysg1zgQz5RHJe09YtftMgtktqW/lb 2bgEd7AJGhA6KOujiAqda3lcX/xvIxRZdBj0Q5EqwhmDShOybvaaLhAtwghRhD92V0/oBU 9t+3f2lmkmcziW5z7jmynBsylzhDqK4ZLEO8wje6DgwOmRIn/Gev8cSaIs3g X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 18 Sep 2026 20:25:32 -0400 (EDT) From: Kiryl Shutsemau To: Andrew Morton , "David Hildenbrand (Arm)" , "Lorenzo Stoakes (ARM)" , Mike Rapoport , Baolin Wang Cc: "Kiryl Shutsemau (Meta)" , linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Muhammad Usama Anjum , Usama Arif , "Nico Pache (Red Hat)" , Zi Yan , Barry Song , Dev Jain , Hugh Dickins , Lance Yang , "Liam R. Howlett" , Michal Hocko , Ryan Roberts , Shuah Khan , Suren Baghdasaryan , "Vlastimil Babka (SUSE)" , Alexander Gordeev , Jason Gunthorpe , Leon Romanovsky , kernel-team@meta.com Subject: [PATCH v6 19/19] selftests/mm: zap whole PTE tables in the khugepaged race harness Date: Sat, 19 Sep 2026 01:24:49 +0100 Message-ID: <20260919002451.496763-20-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260919002451.496763-1-kirill@shutemov.name> References: <20260919002451.496763-1-kirill@shutemov.name> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kiryl Shutsemau (Meta)" The harness's MADV_DONTNEED thread zaps 1 to 32 pages at a time, never a whole PMD-aligned area, and only a zap that covers a full table frees the table itself (CONFIG_PT_RECLAIM). Make the thread zap a whole PMD-aligned area about one iteration in 64, and keep the fine-grained zaps as the common case. The new case frees page tables, racing that against a collapse walking the same table. Assisted-by: LLM Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged_race.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged_race.c b/tools/testing/s= elftests/mm/khugepaged_race.c index 68046f0bf6d3..abb0678522cd 100644 --- a/tools/testing/selftests/mm/khugepaged_race.c +++ b/tools/testing/selftests/mm/khugepaged_race.c @@ -118,8 +118,21 @@ static void *dontneed_fn(void *arg) unsigned long page_idx =3D rand_page(&seed); unsigned long nr =3D 1UL << (rand_r(&seed) % 6); /* 1..32 pages */ =20 - madvise(region + page_idx * page_size, - room_from(page_idx, nr) * page_size, MADV_DONTNEED); + /* + * Now and then zap a whole PMD-aligned area: only a zap that + * covers the full table frees the table itself (CONFIG_PT_RECLAIM). + */ + if (!(rand_r(&seed) % 64)) { + unsigned long area =3D page_idx / + (hpage_pmd_size / page_size); + + madvise(region + area * hpage_pmd_size, + hpage_pmd_size, MADV_DONTNEED); + } else { + madvise(region + page_idx * page_size, + room_from(page_idx, nr) * page_size, + MADV_DONTNEED); + } usleep(rand_r(&seed) % 500); } return NULL; --=20 2.54.0