From nobody Fri Sep 25 21:41:37 2026 Received: from fhigh-a5-smtp.messagingengine.com (fhigh-a5-smtp.messagingengine.com [103.168.172.156]) (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 A03BC377EDF; Tue, 8 Sep 2026 12:51:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.156 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871876; cv=none; b=SrHUU9HnIUHd5R35eug395Ag+h3t+IBowsXHh8YWJhrCz9Mvyw0oF13xKnQLaWBm/onxKy8/u9eGk7ZzPB3j695BfbxjNs76EyFlnq8yedBX1c/gLgULkJ6j4pwWv5cu0rj9ocGacpSmJw75tfTDT+ut00vRO2EiYpmKjYe1haA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871876; c=relaxed/simple; bh=2N5jyXQALvT6no1K5xyLE0WpHhffQTgA5guabPSVfUM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oC8RhRH+qcD5kv9F5NDpOY8IxtLbXFgGYhOVxySZvgjr/f5sQz2scavSTK/hQD1gXM1+mxcsdTJlPoAm2k+u6jEaPQaalO1WT8t3b9hFkO67W36rcgHohFsq6+TaCizRKI37R4In7NLFG6sQC6RO2M5WLs9kXzdGpW2eSmbOpZ4= 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=XilEwzkr; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=oY79WO9f; arc=none smtp.client-ip=103.168.172.156 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="XilEwzkr"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="oY79WO9f" Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailfhigh.phl.internal (Postfix) with ESMTP id 721171400094; Tue, 8 Sep 2026 08:51:13 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Tue, 08 Sep 2026 08:51:13 -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=1788871873; x= 1788958273; bh=/2nWSyfEPgqLKOnGOcfwH34Ldvg/Kp9mnGqErks5ETo=; b=X ilEwzkrENEYRRFEyV+yAMTVlvO5TJcVt3cA7Dcgm+5cdJ7QH1KYpP8D3YSinGoJG 7lvBxkmqAIBBaQeUxmZUvbe0fICSpxy+d3QaNl+LjvWk1tFgkA3Ugy5z5oZKPzN+ eu22wtnRyk5raXQCNmpvMUEq2gXXhTGLYZx/kMr78vW3Nsq8eNvkQV6vnN1iNl90 vqdOq9XF4csvyhqOha0q6UaXt39Y7G5QNoC8bXLEq6WOn8gz7hsZR4SpsqpiqJTG ZMmTdGg3uZ7Z5ejmvOFsxr4ZOX1w/U00etABfWs08R16yyxDCP6VbdTfHZommU8b g+6yVhwkUuDOcLKJGc4+w== 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=1788871873; x=1788958273; bh=/ 2nWSyfEPgqLKOnGOcfwH34Ldvg/Kp9mnGqErks5ETo=; b=oY79WO9fYBxdhDPXM lqRGhDi+Eb6yrjOT7un9vCsorGIgOWBhWxNlaBkoYg1J5V1t1XIDXCh1sgylApz+ TwMhy/3eC4+aaqOZSbzof9z9id4hCBm3ALZhRzFgbGJjbrsB9HDubf5VDVXuclFp jDjn1sgtVZvpgVNpSTH6ESwF7FX85duFLII97Xw57S5rMV/I3ubtCJRY9W86dTL+ InTmDyiRPqCyYOTGzXi5I3VhpDqSDlNi1p1wK/RZz8Is0qyvRVe9KgOqJhpttKaY JccXz2IRXPKMkzHwesW9a1nygc8b4eR0QfMYVqjDYf6IFcdNcdkFCZ6W7W4LQd0U THpGA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFCT83ts3xpHDuUgDdlzQtELcoAknrXBpsFepmdcEBLccwduWOOVyAuau0VlYvm49 objBvbnGefvuHsKXiB+MOl7qErn3M4/Q7Z72R+asBFni+WG6jRYqPjjJBv1F7ovmfnEZp3 uEJcbLADGcdxsWcYxdWct2wwV9KQaoOTpGWM7Il7/oKOILrVOp7MvqHbWAXdA0mgRBniUZ 2M+Su4Zoe9zFbzekNirjNltohahTSfzaLbYZTkGXD/hRQ+ajqkABo2HdEn2GJrc7g0w4Iu PhTUexE0AKZ4j2dsA7W9i19VnbZvZZgTTujH64lpg2nDW6KlKK63jDlRsrLETwVfJ8WCO+ yqPrlGo5qSZVhvzFOYFDGlQGrBJXzBqOW0CtEletXHyDAFOEoq/L4autahk7kMXlbsrpZ1 3YAvhSI0WXx9ywTvFb05cwzMsIl4IRUM9UEv/dq3Y46Xi1E/H0f9T1c1V9L8gScb78+3yf BuduosL+mHDfRlXi0kEOESFJsqKsWW/6ztI20LWRcOJENWpgXFYTnlSPe/2pFE3zhrqZRW I8Py5/kG+hpBYvnEkU9HxyIHSmeTPaGK0WXoHxN7RDIZD5Ko7Z4jP762+iNwb1yC9hdU++ t2qTrkDVR9PqYCTILPaNI2uFh0Ky5fg5SpypVF+t77k1iAB5J+aUM7MfDslg X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:12 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 01/19] selftests/mm: raise the khugepaged test-case cap Date: Tue, 8 Sep 2026 13:50:47 +0100 Message-ID: <20260908125105.1510704-2-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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) Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- 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 f82673f5f6b4..e57016bd96fb 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1285,7 +1285,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:37 2026 Received: from fhigh-a5-smtp.messagingengine.com (fhigh-a5-smtp.messagingengine.com [103.168.172.156]) (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 C016354281A; Tue, 8 Sep 2026 12:51:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.156 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871878; cv=none; b=DDC7LmtgjqWW5rhYYl6Yn3/gVyiabjN0LFdUGKpxDlNwxw/nbjMQgSTCSGTNMAc0eIs0FTp/928QswZKiKm3uLBBrTo1q6jHjKSEVuxLu/pnVHqQ+PrFsEyUP7/O0Auf7jJjQU0Rs5w/xxnOYYxqTatk9Ca+46gT7z47z7ITRMg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871878; c=relaxed/simple; bh=CSXMKC8Az4HfRsue6NIapBlAOU3y8TH3lkmLyPElzeY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GWITg0M0/URT8UuinYd3xyqDuXacOkXHMGdGeHiLdCqT0s9jaVPyehVGzIjxBqbuX+57VIBQJLDMJ3XrirqjpGKB4RBbHaCYTWtGBo/5W0NmlUw3FUZCHEmqyqhEKKJ9HLRCgYD6sdKRE7hJ/6JVw3VqIfguKIahP3WOnsv+wRE= 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=obd9qnwG; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=m7jwhF/m; arc=none smtp.client-ip=103.168.172.156 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="obd9qnwG"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="m7jwhF/m" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfhigh.phl.internal (Postfix) with ESMTP id D796C14000A1; Tue, 8 Sep 2026 08:51:15 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-06.internal (MEProxy); Tue, 08 Sep 2026 08:51:15 -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=1788871875; x= 1788958275; bh=iwxMgzeRWfdCSv6NSO8Zrqvha9AMlvjv8LhyEme61lQ=; b=o bd9qnwGe0nuhKHPDfRr4hBq3btiviPT7kiJwKHW/Na3lP4/RAhwuiSwAhZhH5sCi 3P4Zaj+i177qex+EhoCwv0RaOaOa1ZO/BqUfTapihfLpk9n9ZTP56ueGQdv2gQSy 5pUM57wp3w+dCmBwPWzRAZBnSMO4wnoXzZUUPchFrIIVln7apBrPU9x708iZZPxX lp6T2Y22OR68pw1dOOyWQE2TeRZW9riMXuZkeSzvBRgOkgrK+BsM+AYmkuzbSI3n 4EmLe+2L/QI6NvEKeaosO4bMCdSIPBeABIaBMrt+YLaGrmfxvd0R/ZiF4KFUeeST j/rUzaQNGO0+FuvofNRMA== 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=1788871875; x=1788958275; bh=i wxMgzeRWfdCSv6NSO8Zrqvha9AMlvjv8LhyEme61lQ=; b=m7jwhF/mSf/e8bYVw p3U8nCNtyIsPudps1FYdop7nvFYLnCMU/RwarpMCdvYuAztIh7GGeYzyPRbunifY 1RweJVoMAcr88IzxF5bI4Qv2RDKefXaRFTJ7MLuWn6B+fjRL+zvrL0dcGTSjbG28 yVW6w/ckbttMUK2V9TRl42YwtyN/Df/BJvPi6Z1TuS867/30eSS0fT3ji2bRr/gw hss0uNAhgvkE8pLpGNlOm+E0ueNmldZWmgIhwqVl3TNxYyA7IbKB+SRtc6FaZM2Y 4SFvxB1D8mhE0fA0aRFnQIK+y4Nma2+UTujrpjOt2c0hlHspT1rzgysrbU4fEb54 FvAwQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTGuvEMc9jYu2f0uyTmUF7l0J7NybVdULRlrJFmokmmiolg4yH1+7h97U05D2w+OYm AZhWoHmMPT2EsIB4AC7PxRFoqN+CF4x8etMK41ayTMd5Tw55ZxqvSYpb69cNUy0p/dfOGv 05P0JRk7g5kt5eTL1k2cO9e1oUb7lrROdNyUSbigYjG7Zs/tNKx+L8+9HHw+CSw5cJpWIQ j2DrX13NeCZvnLN36sWkEk/U0EX1Q1izKAtzdjMuXhus4PGMhEw3kJKafKZkgCRsnWRxXR Wv8osDa5aTh9mnjCTFnYcP83hQ8y7tmPYrDENim+Q79mFJR5sJUGN5QsCu80CUB5y6e4dK Z0E9GGivkeHG4X0HLGLbvvZrC5bnJqafe3JtujJDyZU0RMBh78hGImZdsp2+xaQaiezMm1 W/GxYA/8X81H1QVXDnrm7G9MmdnWthDp4bwQE5/Q0EdSY92qYkIEBt67B1nXGULa9l92XT H9EdurnNFjSVs+D0N5mfI+L0uLvVkI49ArxXJw6fWpDpyme1CL+vBTCCQ8iRE8baVUUqIG 5Q4v7N+9OtQl4udFlDE23Stsl524Vf+c3e0rJWn2aMdBmjTlm24pCumW9GZtDQTrD2kADC eCu+eSd4I4se6UGU1Y5GZn8BXiAdR+e8UnPIWACsfZMNOO+zGh7eufrimloA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:14 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 02/19] selftests/mm: skip collapse_compound_extreme() where the PMD is too large Date: Tue, 8 Sep 2026 13:50:48 +0100 Message-ID: <20260908125105.1510704-3-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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) Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- 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 e57016bd96fb..1ca7c6978571 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -935,6 +935,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:37 2026 Received: from fout-a7-smtp.messagingengine.com (fout-a7-smtp.messagingengine.com [103.168.172.150]) (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 A591F5437D0; Tue, 8 Sep 2026 12:51:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.150 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871880; cv=none; b=jD3673sErCQvO+c+jlDDNZvY1orUgo9oLv4NHnrkWiA5KYVlzq0N7x8nXGCqKFw2gL4RfLm+EKOhdYhwGIX1Y3vBbTKPOLEDRlskZLCNdlPGYZDan3POhyeJjq2Dz6LAxlsHdRWHNDtSFC+I1p9cZyiVAuY9bqq4OAJpI4wNfHY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871880; c=relaxed/simple; bh=m87rit2xZVxyYYGGBfTwQIb+3uHuiUcFoaOr9xj5OFc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=F3pp7zkbubX//bDv2NvlClJBkXksDUcxhw0Q9tXvNoKZKxsg0QZB+3K3ULlltIEbyx/A56gP92sen+TySsyrlLf6FoRLELj0d9y3T8qfnBhp9DjISv86jlubiSrZwedmDxKYj/0+jKCP45bizfHlFPRJhpfPdU0sjyOZh2TLBmQ= 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=BC6RTcgv; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=MGv3A5vu; arc=none smtp.client-ip=103.168.172.150 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="BC6RTcgv"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="MGv3A5vu" Received: from phl-compute-08.internal (phl-compute-08.internal [10.202.2.48]) by mailfout.phl.internal (Postfix) with ESMTP id BB4C2EC010E; Tue, 8 Sep 2026 08:51:17 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-08.internal (MEProxy); Tue, 08 Sep 2026 08:51: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=1788871877; x= 1788958277; bh=2hGlkwJH8rpVYNSw9dyCZihy+2pP4J7uKRwXxgbT84Y=; b=B C6RTcgvMZ+j0dLw/pV7afe7NzIFUram5k9kDBc2+D+gPWYmiYNXopP+2DxEgnUwz gmhL7JexHkSVLlTIvvAcfadHibeRFg9WvS+ryO6dGwybP5WKipfSr4Fqn2vXa98X wX7dxut8kVUfnu4y1iZ1Tw5zhQ2EdTph5SbKC1g0a3nFH5YUkKxCfxxaFTvD0i2I 4HFnJZXtIdvyybWadFDE6CkwsjK51eWdHosLUjfOkq0YKNdAzL3AJvHx4+S9rW/2 vG9NtMZm5D2NqwyLXrYuLObaLK2QWJ+6u8BPereNdrHQWy2p6KM8QcV2vg5WZMOp 9XtHH38QyEyns8o/aSb7w== 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=1788871877; x=1788958277; bh=2 hGlkwJH8rpVYNSw9dyCZihy+2pP4J7uKRwXxgbT84Y=; b=MGv3A5vuwwT/kKvXV ryQ/URKE2Xq1OvDZwW5m6ZtNn6p1Hkx0Qh21kxJKPlYKDStgjdcsv/U/xZ0+PJcV UD3ToQAdesS4T1mrlF9n4IYvrfmcC/2qnOl2wPGosVfr7J9izvNHQGcesoDRNhAn 69CeOjmSj7PhO+733sEIpCVyYp1O/EQitK7XDY8KX0z/Avsd/QMvGDW8w2EUKFU6 fRpyLl6rBlwQUZb9htZaGVDMfrBmlzdjY+0MwrK+5UWqDORV3z9QG/XdseZNQNA6 DMBHj+ZvyOoh16dPdfak4vHMFr8o4KsPhSd2e96aZDT6kbVwkK3JMo8ho63rg7p1 IUgAQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFCT83ts3xpHDuUgDdlzQtELcoAknrXBpsFepmdcEBLccwduWOOVyAuau0VlYvm49 objBvbnGefvuHsKXiB+MOl7qErn3M4/Q7Z72R+asBFni+WG6jRYqPjjJBv1F7ovmfnEZp3 uEJcbLADGcdxsWcYxdWct2wwV9KQaoOTpGWM7Il7/oKOILrVOp7MvqHbWAXdA0mgRBniUZ 2M+Su4Zoe9zFbzekNirjNltohahTSfzaLbYZTkGXD/hRQ+ajqkABo2HdEn2GJrc7g0w4Iu PhTUexE0AKZ4j2dsA7W9i19VnbZvZZgTTujH64lpg2nDW6KlKK63jDlRsrLETwVfJ8WCYT c+1thOoDewX31NDRvXFN4FzlTNJbNXxIxXZjZXhV04JGtGEMASGQE13zj3ov8UNJ4DV03c hgGHVSPpLeKSwMrclFT227P9uZgw/zASFm8T7kNC8oysJSwF7oz7DhskUil4s7vgqC0Ujg sbzjWvYrlaiDWtwWvVOPU4KY1M4TkgM2w/RNXl+09lrdc5Lm8OZVr28UpHrx4IPp2zJwYw 2Z6Z7FSPOdzUAx59/gI6YMrK/Lw5o55EpppddSmm8GWtF8Sk9hdqmGAGS+v9WjvJH2+eLN SOezize9leW/aI5FS2JtPvjb54u8YUaB5Lf/aK4j4I3ZC08E9OcMVz/o8gRw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:16 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 03/19] selftests/mm: scale khugepaged's collapse wait with the PMD size Date: Tue, 8 Sep 2026 13:50:49 +0100 Message-ID: <20260908125105.1510704-4-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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) Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- 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 1ca7c6978571..48e0040d53b4 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -556,8 +556,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:37 2026 Received: from fout-a7-smtp.messagingengine.com (fout-a7-smtp.messagingengine.com [103.168.172.150]) (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 CFBA5156661; Tue, 8 Sep 2026 12:51:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.150 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871882; cv=none; b=YHAbns4AISzUM8kY3BsXUT1UbLmGNQeNo0a3Zpk+ngYiKEjZ1xFTEbyoqLKJ9BSztVEUIOPKEMRhSwM7rrVUtbQLUrTF2fTo9b6fv4/plKvvXj8SAZKCFMR+i6ZGZLa4iM8QPdm3mI16584sgiRm9LAXDXwI3FVzoFw1RR3GpHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871882; c=relaxed/simple; bh=OxdiUezQx+9PR59DBA9umo/VW0TtXHh39ptAloZpNIA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=odme6ouSWc5mRsiDm33xyy48EiEwV2zy48SrmewPsD86PSr0sRiWcmUMzzHjZPCSgjKg6UIfbi81hfEayYcZVfq+goe0kIGH9XK0XoTSmicTnq4nk6ylOumD+B1fflTco3iK03WJocGNyeeLTYz3XaI+fgWAHjjHGNoiCPAD7M8= 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=l8YhARTz; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=MmQfNFUF; arc=none smtp.client-ip=103.168.172.150 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="l8YhARTz"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="MmQfNFUF" Received: from phl-compute-12.internal (phl-compute-12.internal [10.202.2.52]) by mailfout.phl.internal (Postfix) with ESMTP id CF38EEC013B; Tue, 8 Sep 2026 08:51:19 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-12.internal (MEProxy); Tue, 08 Sep 2026 08:51: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=1788871879; x= 1788958279; bh=Gl/sNwAk9MDF/uFMRp+A1/O8Ght2HDEnJQvn6SudLCk=; b=l 8YhARTz/DRsSj+CrFAs1wJ/EXnlByExmElqF5uPaJHdOMAobrey2H0mACB6haNFU Xcq8HUlQUX6UZcrfJ1VtA9pv9u0upbIbCFAr4+T/mw1nZxchO/mIvu6IVGilpgsQ 2qvcJ4BXvcJGH4i7RyrZbXeDqUVCrDBrDMMAedK97qDEYMA/ywP7e7imkL5NrT16 0yvfz8hErw9lh9ZAfOcU0F9mmFBOKuzEI8lcoZztJO5XWqISXlJC0wOc1KnoZVYj WPu4rY8M9eZto7uU1dCkppOyu+5poxT/ZFo5sbwS1nWD16IvTSq7sN9TFJlRWUfl 0nqkkX35wD2u6Dh6JK13g== 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=1788871879; x=1788958279; bh=G l/sNwAk9MDF/uFMRp+A1/O8Ght2HDEnJQvn6SudLCk=; b=MmQfNFUFVG2JY22t8 zHHX5aEyuUEqZYyracR+jrE5KqeB0O1/i4rwmNNH88JA4uzU7SbvBHalWRvpPoVb kmhgscquSUdD3EhSDuQ2utBMFoA+pqhcPmEQVD31AzDTWALWnBKoY8aIoWuIXl4W 3NbpAw2c7DhvmlI7kIxkaAJdXE2O4ToT0etioHXmwvd9krxi8IYb+SN3y1UYGHxD ScbatNeOvRbXj0XgryP7b+8t3UK/AwRQTsHjnXoAZ34lm9LDrIuEd6JZ6KNg7LAG l5Xo93bU2npS/scy2XhysDS0w+YdhZKtEw4UAd1yC+CfW6afdlBDnDFBsICYPy8v xyT3A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFCT83ts3xpHDuUgDdlzQtELcoAknrXBpsFepmdcEBLccwduWOOVyAuau0VlYvm49 objBvbnGefvuHsKXiB+MOl7qErn3M4/Q7Z72R+asBFni+WG6jRYqPjjJBv1F7ovmfnEZp3 uEJcbLADGcdxsWcYxdWct2wwV9KQaoOTpGWM7Il7/oKOILrVOp7MvqHbWAXdA0mgRBniUZ 2M+Su4Zoe9zFbzekNirjNltohahTSfzaLbYZTkGXD/hRQ+ajqkABo2HdEn2GJrc7g0w4Iu PhTUexE0AKZ4j2dsA7W9i19VnbZvZZgTTujH64lpg2nDW6KlKK63jDlRsrLETwVfJ8WCe2 Ngz4DLrgyUxY05wMYj52j8IakMHZKjkcWHX6PYSVhe3AlZy4M1ACV5EBxH4kd0H1Kc9DiY g9mfroPvWHQrJqix2WbYkh+0yw3iGjq9SlphS1vxYbmdZEneTbyhqQei7aqhOWMyHLLFN8 g+Puu43NWgy293fIhoqtx4EwnxenYlvaQCDmpdnFkZzd127+WZ5hnTIkuC0SWk6uwEYx7a FBkDe/N4MKWvuknNfVsRDKu5ZmgttCQMVyyugin78yj8cUpZ8YU80vnm0iDXsnJNB3Al5q Rw2Kn3tCM3rFQEhRtEi8tY31zTv8WWpjB8EBzKLVGQt5H6VCIXF+Hs+/E2RA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:18 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 04/19] selftests/mm: skip khugepaged page cache cases without a PMD folio Date: Tue, 8 Sep 2026 13:50:50 +0100 Message-ID: <20260908125105.1510704-5-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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) Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- .../testing/selftests/mm/hugepage_settings.h | 9 +++++++++ tools/testing/selftests/mm/khugepaged.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/tools/testing/selftests/mm/hugepage_settings.h b/tools/testing= /selftests/mm/hugepage_settings.h index 726c73c43c05..a1d12e2ffd62 100644 --- a/tools/testing/selftests/mm/hugepage_settings.h +++ b/tools/testing/selftests/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 48e0040d53b4..73bf07c39145 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1353,6 +1353,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:37 2026 Received: from fhigh-a5-smtp.messagingengine.com (fhigh-a5-smtp.messagingengine.com [103.168.172.156]) (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 5FFB85427E7; Tue, 8 Sep 2026 12:51:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.156 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871884; cv=none; b=WO9zXaoEPN/rPaWeUC3JBo6OsfJBkpQFN18JyXf2FSUoIDJuNshao+aZGidfXdu/SHM6iSMVUSy72/WSr853rjRigPVDmI0DuU/r6u0FflqHenskW1WV7fA6iKX8PnxdeCOHberu5+HVjMFtPxNu6/oUlSSA1qcQwBSXgO/kBto= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871884; c=relaxed/simple; bh=Ag3+sY9gqlDqpft3HY3iH8ORgalnQhAcipJiNJEWcPI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b1VQG73Uqy5SmrI+PuzzQsVjXlS6fsVBeORmi1fkJPvmRhG7rwVKWC2pZ9rYCbafHQntq4Q0Cd3ZVImnGIEIMKWck2AYEJw2Xl3lJ1B9pFR54RMXSXekbkmh/Te1aT+HAVGkVfcZuD0iQv6Z5IzGbn3M2F38+TsND/DiLls0rw0= 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=aiqeN73Q; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=nMNQkBF1; arc=none smtp.client-ip=103.168.172.156 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="aiqeN73Q"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="nMNQkBF1" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 741F91400094; Tue, 8 Sep 2026 08:51:21 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-05.internal (MEProxy); Tue, 08 Sep 2026 08:51: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=1788871881; x= 1788958281; bh=h96xKtx2qZMCWy32X4fzhVdoH1fDHGv4dS65yGYxxtY=; b=a iqeN73Q3dKFSnie6qlz9jWFOHG9/GFU3uqZz2jSA0DCs5kOK4d9KahljyVFG5tWa +9VtOPCTg7OBEE6eQlTtXY3+rIHGWdUbQXRnMJxnjVx+vHHfvMiWBpqHsb9ipiDR i+oFXrFOHEo1XDC8cgtFMdvxYg553WRP758fVzhZh7Q02TaHgm3iXug+IobbmNxz DpgsfoIawkN5x0IRb0sk/K5gCfzqMuRRmpkSF+AhqEHd4dOdT9Ep6K+zRI4gKtNr qn9K1tx4b2Jw4S8RQx9bPZwVelhsa2eLwDzMy7kRy2RYmw46H6piGQyfpd5T2pD5 pJtiEL+7BIL+BhyZc+jdA== 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=1788871881; x=1788958281; bh=h 96xKtx2qZMCWy32X4fzhVdoH1fDHGv4dS65yGYxxtY=; b=nMNQkBF1KFhBqwPO5 518Oshc+gkbjplnBAH/GmQddVYugrFDzFQNycNX3yvmHQADqlhm1N8K+vPiADFNe yqyk6y0TXVpA6VcTBnf8QLd3oq2cLM6x5ibOKUqAXQTK1CBHEV3TSKf+KG2GZ8qr /jnCEQ/cOBqKiBf3M8gZt4e1lAU1FdtXDkKCnsy/kQRAfnnGCz4lu4pbibc3Obta Ey4RDECzP4jhDc/1AhjhGh9hEj83dGG8xeRB+LgQonvpmbBJ687bvcTWq/hmzEbp NRFvgqOuF33nuFIx0ihHdLdhX7dLfmI9EzgsAlY2GMAXnX/BrXSVEzXd5RJG7Mu6 Ubv1A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTGuvEMc9jYu2f0uyTmUF7l0J7NybVdULRlrJFmokmmiolg4yH1+7h97U05D2w+OYm AZhWoHmMPT2EsIB4AC7PxRFoqN+CF4x8etMK41ayTMd5Tw55ZxqvSYpb69cNUy0p/dfOGv 05P0JRk7g5kt5eTL1k2cO9e1oUb7lrROdNyUSbigYjG7Zs/tNKx+L8+9HHw+CSw5cJpWIQ j2DrX13NeCZvnLN36sWkEk/U0EX1Q1izKAtzdjMuXhus4PGMhEw3kJKafKZkgCRsnWRxXR Wv8osDa5aTh9mnjCTFnYcP83hQ8y7tmPYrDENim+Q79mFJR5sJUGN5QsCu80CUB5y6e4LS xzIxbC5h6FEB304ULXKH+UdNg/3/VZNGLdFKJEhyuZ37YXfrIEJqhw4AEPtVdO1Fsq1uD1 ybowd4oDyqQgqXRwPMW9eRnmSHMA5yacNRdVo9Cg+0k5RhhScDbTnEfdtCCCT4sPsV5Kdt IEhRb1h68Nq4GbavNPr1vAL7gBeS/fUaJk5zyiN4layUtJDyU1apTBVeK2gcc2cG7LDEqm 0iuRDQfs/yUtPTbZbEXO5bjMbJRF0NRK8EU1Ps86KKLZXej3EcZncXDp5EMY7pW1vuKomO oE2dMwQmIg7E4HnI81C21OYaUO9ajEDCuvdfB4BmTco//t9BZQCTmPbVLGzA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:20 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 05/19] selftests/mm: make the swap cases' swapout reliable Date: Tue, 8 Sep 2026 13:50:51 +0100 Message-ID: <20260908125105.1510704-6-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- 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 73bf07c39145..398430c33872 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -220,6 +220,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; @@ -823,12 +846,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 @@ -849,12 +870,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 @@ -866,12 +885,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:37 2026 Received: from fhigh-a5-smtp.messagingengine.com (fhigh-a5-smtp.messagingengine.com [103.168.172.156]) (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 2FEDD5437F7; Tue, 8 Sep 2026 12:51:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.156 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871885; cv=none; b=ZdZkjUfr5tJCgjSaeYlFJiSyPvX5qmsq1u7jiJy+ocR8cbDnmbeiERr4MQK/gdb4VW2e//LFOuJ66fCXGeLwP6++3iS7U3VCqNeK5wh4AAFTapvrnND9AjZuO9uNLO5esAVNKnINLQh7LjnMZNHWL/4rwbLp7C48PVmrQVeJxHQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871885; c=relaxed/simple; bh=G3NYtLn1ZFmHTazdJtjkQt78Q3z19clqXZu643CVfnM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j+ZeD5/h9slyLP3IaRprJkXH7Xj9YM7GszVuEhJuTVAUfT3ikVnzStgXXt7MNEzb8d6c0GAajVv8sRx1mduj/w6juxJke+huiCxOjfI3mQ7kp2EQ+RdMeJCCyFiKsdw72PmJdsq7vcZ4AHukxEKyS40vyaOT9ygESgYMLXTbux4= 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=OHlOW9Fo; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=D+TmJw7y; arc=none smtp.client-ip=103.168.172.156 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="OHlOW9Fo"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="D+TmJw7y" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 3B58F14000A1; Tue, 8 Sep 2026 08:51:23 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-05.internal (MEProxy); Tue, 08 Sep 2026 08:51:23 -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=1788871883; x= 1788958283; bh=2NXsxc1jX9htzyVHYrKvKVtGcWKt3qidVIHJ/7B4Lgg=; b=O HlOW9FoPmv5SmA7W/80F/F5LXr0PBqsP2hgc7nWPGmTkhwme5n9kcJQTZQWhGAZm NphFC0KfvpsskTgU3LcpKTc5yXy3eM5qUwvDIz93gMxS1ZptIKnlKt1r9nA+UqM9 9PNfKTzCaNJIx5pamHDHEAixJiiIffpdsjf5zvZCC8elihH72G38TnenqmuNmE4e 8fJxbTE+Y0iYRbWRXZPHV2NkzaRPNF4BaOahYyKILb8vCzC0ppFy/iWk2tEk34Dn Ka+JbhqPhHm+hxzy3vgSNfd2+stVMTbyGPC5UVck2SLW54nLToYS6tL3CUTfrrA3 lSpEjketdIgfSeuQGa7VA== 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=1788871883; x=1788958283; bh=2 NXsxc1jX9htzyVHYrKvKVtGcWKt3qidVIHJ/7B4Lgg=; b=D+TmJw7yA9/y4DV9N iA1tBh9DIBHlfyIXtkM3me0AMveeoaXnNqmsAs/9i/6Sfsvyx8T2jdcxP+Fk4v9o wg/ISd+LfEKf9bXtoumvY/iBBqQSx0ck2r3GUBIOQCFRYQXsqzcf1S8cesAWkQZg VbOeI1XcvwMKIVtw+BkcXfoDur/irHh8QG8sf008n9kh5QSKUIwGXp1lz2PNBzKR /CLYZV0tGV/rK3VgOS9qd1ZpMl4qrLzH7rq1Kd5ljsroKGG66IPq+81ub5/SJ1H/ DGSfPDKw3phNrdPlhS7AKctzkjo8F0N5yRPJsBDWMLLdGZP8zub8XBNlkUXc7o1b sJ8FA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTGuvEMc9jYu2f0uyTmUF7l0J7NybVdULRlrJFmokmmiolg4yH1+7h97U05D2w+OYm AZhWoHmMPT2EsIB4AC7PxRFoqN+CF4x8etMK41ayTMd5Tw55ZxqvSYpb69cNUy0p/dfOGv 05P0JRk7g5kt5eTL1k2cO9e1oUb7lrROdNyUSbigYjG7Zs/tNKx+L8+9HHw+CSw5cJpWIQ j2DrX13NeCZvnLN36sWkEk/U0EX1Q1izKAtzdjMuXhus4PGMhEw3kJKafKZkgCRsnWRxXR Wv8osDa5aTh9mnjCTFnYcP83hQ8y7tmPYrDENim+Q79mFJR5sJUGN5QsCu80CUB5y6e4FH 2bU7+Z1C/ZBs95vtrfpBNs3fYgoa7TxgB+J4T7MnHULHrY3HKy5QG/NyXdQGKctluDNtCm eUSUl24PKe5TOi4Wa1oA5GZOBNaqq1b2z6QzlJFEwTl91ijbDGpXvkkxpFJrcPnfTBVpYW vpt2cD2n1OIRqQX2pWGGJvnOGq0XehYPEkvO5cytepuAkFC8GzVmHHsqDR4n6jxIbiOSas P8shOONYnFFmhKFTvYk0yuitB8jX1e3akpUlI7nPOk8xH2k9LKejsDXNuk55xKtVw3PPpF j2m99WZGHOkyNmkBh5fGqyj4Blnx9BI5f988Vuyw1L+IHdDSNxVej40fvDFg X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:22 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 06/19] selftests/mm: stop khugepaged during the MADV_COLLAPSE cases Date: Tue, 8 Sep 2026 13:50:52 +0100 Message-ID: <20260908125105.1510704-7-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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, setting them to "inherit" rather than "never": khugepaged honours the global never and stays out, while MADV_COLLAPSE on shmem still finds an order to build. Fixes: 9f0704eae8a4 ("selftests/mm/khugepaged: enlighten for multi-size THP= ") Assisted-by: LLM Signed-off-by: Kiryl Shutsemau (Meta) --- tools/testing/selftests/mm/khugepaged.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index 398430c33872..e9bc8fe8a1f8 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -533,8 +533,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 @@ -547,9 +547,16 @@ static void __madvise_collapse(const char *msg, char *= p, int nr_hpages, /* * Prevent khugepaged interference and tests that MADV_COLLAPSE * ignores /sys/kernel/mm/transparent_hugepage/enabled + * + * "inherit" rather than "never" so that MADV_COLLAPSE on shmem still + * finds an order to build. */ 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_INHERIT; + settings.shmem_hugepages[i].enabled =3D SHMEM_INHERIT; + } thp_push_settings(&settings); =20 /* Clear VM_NOHUGEPAGE */ --=20 2.54.0 From nobody Fri Sep 25 21:41:37 2026 Received: from fhigh-a5-smtp.messagingengine.com (fhigh-a5-smtp.messagingengine.com [103.168.172.156]) (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 424935448BB; Tue, 8 Sep 2026 12:51:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.156 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871888; cv=none; b=DfPcwaEV1P9hOofiP3JUuGKH+rJM0c/jf6OAZf3sLHU9N1DCvag8WaEczr6wehdXb8SYLZ7fT2EoLM/Byj1f+/K2udrkluuSEliT7YSbRFaRePSR+DxFABnRfeXW6xs2DR28+OldUdvPU63W89qjVpvjytHS97q+fjsHMGlindU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871888; c=relaxed/simple; bh=eI/+ZOLO3BqDj0EprNtq5XE75Rl/Q7bR6XxHYcz+g6w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PeKZvUENA9W5ZhE5swSQCAoBAuN+SrvspF+/Lf5C20LnM1JR5pvrNviGlAUTIwXfLfRtSqykBMUw/WJkffd8o6NtWhTNNUmeICEa+GX95dhjvx/VhBTpIFOFNDvAGwcCBjf3fUnKfDegrYN9vRSmET2SaSJLeEQ5fcQJDXAX/8I= 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=NsU2itKA; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=EuYNbeoz; arc=none smtp.client-ip=103.168.172.156 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="NsU2itKA"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="EuYNbeoz" Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfhigh.phl.internal (Postfix) with ESMTP id 29F9014000FA; Tue, 8 Sep 2026 08:51:25 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-02.internal (MEProxy); Tue, 08 Sep 2026 08:51:25 -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=1788871885; x= 1788958285; bh=U0YBLkbI0LHkxqjta9AIDEwH3CtLA9e8x9xPZXdAjJE=; b=N sU2itKAKWd+EuTEFp+MBfrLa3Ev857xAWFwM1H1vaR8x6gMu4EPAOmT/X760cTUD GeGcwd1nLR7QgmNzmdwq7WB9NtUpX8VUnNSnMzBBtxKhpWhzZWL31giZPEmAOeOV 6s0DycCAhiUWk0ScZvpNvYGAPTQ/Ljt/VKJzkCo43D75/v2QkPuLR+7AnMgPP8Af ztcme4beNB0szeinsmmvx4CtW7GhTCSwelWgxcIlyLIA+ga7B9F4XUdbfabnyuxp YsIu9rwCTSYTpZHHBAcHeNYnJ7k8+edAD35A7Oa/xiH0GUU9w5Mp0khI7Atm/uIB ky2lJsLHVJH0HU0NYdysw== 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=1788871885; x=1788958285; bh=U 0YBLkbI0LHkxqjta9AIDEwH3CtLA9e8x9xPZXdAjJE=; b=EuYNbeozRzz2MoSYq 8gxGE4Gx1ZIIdq4nTZ78Wxs7oNXAICb8UtBsfqfU+2qZQ4qCrEgtLWW/4UDMP2up cVSHRed3YYuLCdVgI+1iXxPnwaV4h9SjmhwrYKyJdUSeT1NTDsGhjHw4Q46Pi49V kJtZDAZds+IK0v/A9b5gUDpT10CYDU8Cral7IsbTrzUfTou5uVw6oTJg/mKGRbzh oA8QasxgXhLyBTAUC/P9nJrMon97IC+4TEDDkeoLyLQHi8G+pxWHdqM6H/4W5y4m 9BPjFV/SCTWkd27B9WRKsjes9K3DP4mb+DdNNE3sKzAooJ2VZylWPoAhCjgI0vNc OiSeg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTGuvEMc9jYu2f0uyTmUF7l0J7NybVdULRlrJFmokmmiolg4yH1+7h97U05D2w+OYm AZhWoHmMPT2EsIB4AC7PxRFoqN+CF4x8etMK41ayTMd5Tw55ZxqvSYpb69cNUy0p/dfOGv 05P0JRk7g5kt5eTL1k2cO9e1oUb7lrROdNyUSbigYjG7Zs/tNKx+L8+9HHw+CSw5cJpWIQ j2DrX13NeCZvnLN36sWkEk/U0EX1Q1izKAtzdjMuXhus4PGMhEw3kJKafKZkgCRsnWRxXR Wv8osDa5aTh9mnjCTFnYcP83hQ8y7tmPYrDENim+Q79mFJR5sJUGN5QsCu80CUB5y6e4pl rS2MddTK+RkN65CROPf5h/Hb5YbHbiCNRTiVKxlDAxSXeim+ipmXoINvh/pG24ZHJwjwYJ i6kEnAsMDSVuDJ0jNxiIIpjM0nJvb14BfXRSkXD3zDR4wesKMsUR8NJpaGhLA/VfY2rQWC bNbouAaduzGJfuaV6Jvi3zZORk+qlUo4npAiIvyMvLXYEM8I1zBApYZFp0BTcb1DWzO9r7 47yVzIzsj8CzVrdAhngKUkopAw8wLbGD1IVMwjpsZBBDNJ8yCdHqI/htY7lTluzf8yez/d jdzfB2sycOTka9P9hG1T9fxMG3QEgnb8x5/xHL9Z+kRJRwsLx+6b5XOxu5GQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:24 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 07/19] selftests/mm: move is_backed_by_folio() into vm_util Date: Tue, 8 Sep 2026 13:50:53 +0100 Message-ID: <20260908125105.1510704-8-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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) Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- .../selftests/mm/split_huge_page_test.c | 62 ------------------- tools/testing/selftests/mm/vm_util.c | 62 +++++++++++++++++++ tools/testing/selftests/mm/vm_util.h | 2 + 3 files changed, 64 insertions(+), 62 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 86a603692826..0adfe7dde7e5 100644 --- a/tools/testing/selftests/mm/split_huge_page_test.c +++ b/tools/testing/selftests/mm/split_huge_page_test.c @@ -42,68 +42,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"); - return false; -} - 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 4821a3563036..3ea42a7a2a3e 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -490,6 +490,68 @@ 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"); + return false; +} + /* 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 9a49af88702e..56a28ce7d029 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -97,6 +97,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:37 2026 Received: from fout-a6-smtp.messagingengine.com (fout-a6-smtp.messagingengine.com [103.168.172.149]) (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 E31A5545299; Tue, 8 Sep 2026 12:51:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.149 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871890; cv=none; b=WexgSvxUUvk4hSzV1l8W/WtjS61QxeigKgcvRFbeQmCvHaKzKesR7mzVfqUTMcPMr0BthXMKG2V98u/Pi6fT5bNOfCy9OIMoS8s2yrl7sBZRmYjoqpwn6ClhheNYlUUI3rJ3e2jAfQyUfagvwcIdo3UmE8LP5I1wVNLmTNjL1mY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871890; c=relaxed/simple; bh=T3gHY3mMw73rfa0S6yUq8a2Niu+B05dDxRPvBbHE5Vg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EainCDNwUKAYJoibW+iY0gAOcwo7SZ4OPQwUJfE084s3oL/2XPG+IzLRs2AUxAtXpNvdIQ1G9I1aZvsTtpNh6nzh6cik46R4gEMqt99Wi36SlGdiN4oSFJSnznnj7zuzFo7vMsLomjkS68bufn+4U2kvcU91YPZodg6z+pIZtEA= 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=IOaL/uKQ; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=gxk39QLf; arc=none smtp.client-ip=103.168.172.149 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="IOaL/uKQ"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="gxk39QLf" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfout.phl.internal (Postfix) with ESMTP id BF9C7EC001E; Tue, 8 Sep 2026 08:51:27 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Tue, 08 Sep 2026 08:51:27 -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=1788871887; x= 1788958287; bh=2jieyZvu2GUVPRHlo+y50ErCBwJJarJUK+qdeuIZ+mM=; b=I OaL/uKQHhb38ND4Bj0fSTpuOj4n2Q8B0stPgpRfDxQwrQZNw+Hlld+YSg/XUgG92 n4ogJ44fYmmh9c2sjiCQI1a2ohAIKcFEP5IOVYdU3tGSaXGFu3gpVCnTt5BDScL3 wW6gqasW3eNXu4N1MqQ5f9X2bMaSrHq++zm3ymOnt7AqBGWrPIN93iUG5QQqi6x5 vyALjW8hKPoAkXTcG+c5MEOPP3p0QLx2wcnwpcITrsqF6PT2qMhSGJOqZwhLioyr gYnoAGoVdg/JuDJMKfJHVw2tYZnsTWWiE2OT/U/UoFqwPuQEfFgJ2vbOC1eF32pr PcJ7MOZIUyRuLN+G/FL3Q== 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=1788871887; x=1788958287; bh=2 jieyZvu2GUVPRHlo+y50ErCBwJJarJUK+qdeuIZ+mM=; b=gxk39QLf6j5cT4DK+ BmFhseXOltswCp5Bq3WFvGkN6fJsCsjKwPG3335aIpIOSnmgR82ee5NA1Sg2VQuT O+5vEt85pNDlyOQCv+OQKG2Fnu66rUQXpIqWKQic04jWYrigcObQ4HC4bPfX0d4l kpcqlmc0W7PUjnqC2/wK8f6bvbNXuijuyjLyISGIvlexeYx8CiakmOznszGyrsrk EaLmcJr4hQPVkbuyZ0tLvRSmYfrx4Nlr75ppr6YYQ4XFR5449fruWT+CXrqNdvvK rvbk5uWtAHTTnGe/pKo9ZybpxO9RDAK6/EFw8CuLv209bn3+Y2GgkGfa6MjK7hMn /8Pwg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEqhwhdybusskt0pvIfnDHaUnU8VDm23OZYXtTM+3VchiC9Aeb+sVxnsk6fYrSw+D ThqYkrS5/6/vxmtuBdFXmhYIhVzzMwKM2h/EuTd0ioKo/SR7JG6qiZdpwqyCgxSw3ap0C4 BwVCwTZ6/NsCbeDdXy9FE5B58Xto5VjC3MUnB3djmw4ijxWpRXgLZG/TTGkjuz6Wl73hCN DLujar0Luemoo2GGzStZ/AivOKYRI2J4riPLZz79qeImA1Ygm/BltYdUhOJX4iOWEiQXMZ R5ImdiLN0us354rUC8gTNq0PrK6J11WLhxFnA56Lf/FdfG/G6OPaoDYxKnsgAlbq4sHOkT N0G0pi/5suIGZSmi0FemecDHkHN1Yj2podLNX+pqToFRRobanD5oKoy67YFsivieppLWWF ydp4XTVRVHbEp7D/Xv9RRxV+x79LmFPU5Q3P3B7hgDmvajcEEeddTBSgE7Fi3VkUINTW1r A0qn+d9UTBu7YWa8yRMmKi7b8Pbq6Ak4Y/dfFexRJ8qQ8M50dH3xwEiZ+C5RAHyhyKMelw NQosLsX7YYiIKZ5PdbdoL5CUOqO+7pvJLcXXqJRoxKFe2KY4jTK5SERkURY2zOVTzwyLQP LlxJKf0BKRJMrLuRmz9toZNlP7vo/mZ7vAlZZCBFcl6kt89kbJHze+qdidAA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:26 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 08/19] selftests/mm: add folio-order check for address ranges Date: Tue, 8 Sep 2026 13:50:54 +0100 Message-ID: <20260908125105.1510704-9-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 that today: is_backed_by_folio() classifies the folio behind a single page, and check_huge_anon() reads smaps AnonHugePages, which only accounts PMD mappings. 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 3ea42a7a2a3e..4947612e8b3d 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -552,6 +552,53 @@ bool is_backed_by_folio(char *vaddr, int order, int pa= gemap_fd, return false; } =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 56a28ce7d029..e509fc4012a5 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -99,6 +99,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:37 2026 Received: from fout-a6-smtp.messagingengine.com (fout-a6-smtp.messagingengine.com [103.168.172.149]) (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 84EA253FD40; Tue, 8 Sep 2026 12:51:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.149 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871892; cv=none; b=ma/PCGc5OVXBWtZkr7Gx4wUJ2rzz58ocdoLzBxF77scE0iQ3HMbjIu5zAQRxGNUEZSqvSLep2xZVrgF/lzFsghzpfjGBf2C/6q4pP8x/2dU4ucDCCAiJQPsIww7kj9OhtW3Z4x3DFMleI/7UUKNFyraBdGG19Xa4Yxz5W9Vrc+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871892; c=relaxed/simple; bh=h7r908rQliVqCKQWy5g8ADN0qvk0iRzzDg4qD4Im+C8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pqg4BC0NJF8Ar8W/ZbSMgUUKpZJ7l931bAJFiKPpu/FSMeiG+F9lrSP/Mw5TSHAtNZfBFKd/XVD2SDUK4nlnNdvLDzurvjCK5M7avwMT0UPNQEivCjoMFUZK3kzVvwZwZBdE1efq+YJEUMA2l119G8BtzHAC58AE/FhzCjieZbs= 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=kLxwheJb; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=BRWO2MQm; arc=none smtp.client-ip=103.168.172.149 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="kLxwheJb"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="BRWO2MQm" Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id 9A351EC0032; Tue, 8 Sep 2026 08:51:29 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Tue, 08 Sep 2026 08:51:29 -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=1788871889; x= 1788958289; bh=sIS6fNLbNyz8emwIgfidikiVHKPCia4QjSI19QX/P8g=; b=k LxwheJba5G3C6xh00NrzV0Uw6X7N4Gydxv8DHAKE13fNnSrzqRfFoahfUWpcgi5V QwUY/5qDPKSDAcTSJdQikZZXiGxSQyXzT6QE+dfXpGwRulqUNUC8cStxRXQVNZXF MDE64bjQxH3Gx1JUGF3WxYOYvxnDamqWPGJUQ+ZEQ0j92nXUMcApTlzFdv2w4KIN i6628kAo63k0hquSdysOjzRg6SU+QC8Zu5RuimrqEKnqXTI2Ex5zipb1itE4k/wN UI3Fl1y0VaRKB69peod5CQyWHwQRT4wAbZCKTd4J7xqQyI1c+0hJvR7lYBzlUcpT PSxd9pl5MXU8z0Hq+2LIA== 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=1788871889; x=1788958289; bh=s IS6fNLbNyz8emwIgfidikiVHKPCia4QjSI19QX/P8g=; b=BRWO2MQmDuQrRSa7f +JwtTMATBVzrm3voyzxuwGvd3K7PUAxMg+HMh8rX2eNgQJ2xHsuyHOpT6SZv2Ysb TlqaZYSn3vDCcPv3cpQyfZyUVgWtREB8xvgZflJUQuSsZOUzYoGjFup7DvK7oiZ0 dncULcTsOVM2jzDYu5RkkFEx9vXP6iWEheQCJpALW45kG2tcIl1ULrlkHTFAe0Rt 53taZFxCUyvjHWtF3wQJI20pbfvZJxFMxkkn2wRZ2Q1Li73f/DhZSsdGR1trfpnZ 8LQt4HKG+8Gk02Kyh1GmJoKlGuArlJEM7daFeSX7/P7rV87rYt1l2HbwOItLzYDB BeaEA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFCT83ts3xpHDuUgDdlzQtELcoAknrXBpsFepmdcEBLccwduWOOVyAuau0VlYvm49 objBvbnGefvuHsKXiB+MOl7qErn3M4/Q7Z72R+asBFni+WG6jRYqPjjJBv1F7ovmfnEZp3 uEJcbLADGcdxsWcYxdWct2wwV9KQaoOTpGWM7Il7/oKOILrVOp7MvqHbWAXdA0mgRBniUZ 2M+Su4Zoe9zFbzekNirjNltohahTSfzaLbYZTkGXD/hRQ+ajqkABo2HdEn2GJrc7g0w4Iu PhTUexE0AKZ4j2dsA7W9i19VnbZvZZgTTujH64lpg2nDW6KlKK63jDlRsrLETwVfJ8WCX6 WSN+HYjEFpoqT62XYb69m8N3bWF4E7LxK14kEgvviCmVPuHyhEkc3JMD+WicAP6/3dRBQN xi+2W80PS5RkYFCLbTMOdiI/2lgS/lm8JjCs0I4ZG1TQd40+C1Cs45KpE0Os/oUvfnlMuR Kt+srlzhA/YG2BELRtW8Gn2FSMnoLKByjqzbv72BURgBb7ET7xoA6jKcfMFk+l40EYSOii o58OEfLUVQurMS9J1Zcszd8f0WO193vq/Zb9LveVOtxLhXFL1MkY6u5aCVhpklNrIJnbHq 2iE/TK9qEMWk0cAspao+vMN6CqF1Pjrejwi2N3ZjXyk6xjfWY9qDzLW52SSw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:28 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 09/19] selftests/mm: add folio-order detection self-check Date: Tue, 8 Sep 2026 13:50:55 +0100 Message-ID: <20260908125105.1510704-10-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 2d5366196e30..2093fcf6e915 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -104,6 +104,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 =20 ifneq ($(ARCH),arm64) TEST_GEN_FILES +=3D soft-dirty 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..fa736c9f701a --- /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 "hugepage_settings.h" + +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 e2642eca0d02..df426f9218e7 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 f19d53c69576..fd35f8a7b5b8 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 d09f9f6a384e..2652a7920b80 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -402,6 +402,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 e509fc4012a5..3be430e01901 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -10,6 +10,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:37 2026 Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (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 833E95452A6; Tue, 8 Sep 2026 12:51:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871895; cv=none; b=pn9Zi0wmADKLQfbA/a7jeA7YFmpo4hAK3mE7WjQztPN5qC5OMvbxpray6O0CUAq1dUGZE8XIuenqRHNw2d/vWdOR5H5Rv0fDEnIm+sAwLV9cPMWQmfLfINk78BSxlcXJKIeifbFkykoBiTdpune1dlAp5xdK6mu/iLvjknuNoP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871895; c=relaxed/simple; bh=2wIb6zhUy+ISZXbffGgnknvcHNkYiwUI1qYhQa6r6o0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KFefON/jNMptRFPtmXt1xNRO9M1GsGSg9nNsROFxxOA5kjz96xAxKj82v/jojXDdcyCXFsDls8OQrPymFZ61i5ppQpkqtU0y3n9uNOhg9PbSJldmo4tQ8PseeBdIhXtEk0UIUHeaq9WyFrYwlwk0gt9RuMFdu02/0cL8tsyKl48= 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=eZo36fAT; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=mv/UO6PX; arc=none smtp.client-ip=103.168.172.157 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="eZo36fAT"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="mv/UO6PX" Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfhigh.phl.internal (Postfix) with ESMTP id 5A28B140002E; Tue, 8 Sep 2026 08:51:31 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Tue, 08 Sep 2026 08:51: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=1788871891; x= 1788958291; bh=uYuChwOH6ew6d87IvPSmlwr+N0kwHvlcJjHBLazstgw=; b=e Zo36fATQgMn+zXwD3MbBP1FAmS8Ii19fPt+CdoEDx9fGfbyDlzsW8xkHXBL2pWja 68dk+MRyYrA3NCUBfTD0ztRNTZwGSzx00Yaeim4OnsISi9zeWH2Uy9wimaf18e+w CHvQ6joD3fQdanXvzhIWFEqaqe4pJBGWTWBzoj4gsxM2Hx/yGYs64zuLLVvwfipu 5xWdUETW0vx/LVPQTAZAGXzYFIeVoILAd7imxlLxKQikX0MfAGoNPg1e0HoUgOrl KJ6OYVlEwMFbRo6EluUKiRE9j2WiglfhYZVscAAilEVClLWEHVXm0571h8WSZP/0 XFNlnH42jpBqJi88l5aww== 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=1788871891; x=1788958291; bh=u YuChwOH6ew6d87IvPSmlwr+N0kwHvlcJjHBLazstgw=; b=mv/UO6PX2y+6qNmXD /AW0LSdylC/oVJ+vFki+CiLYzGrLsDQmJdx1XC+gRlxdw6rFqqWgkPnQmp3FPhSK iI7pGiidSr0l/OhvNHQNj8Crb9F4pl2vcrTDO/FYhWFNGYID22NGFM9vWEcDA96x XzR/9eUtJIFc16jo+AzaIa69j++iLC6dIn2zV00G0/aNO3HrFs5DTfRVmUBqtSck JPjOIccGogtub/GIrFYoV2i2x0L2V9qjk3FjhD623y5nmR04b/uMyDbxIQK0s4Ae 0EB88O6wrEyY28Xs7OSI/u0ysgiR/YSwKrceXcZ0TR+2G3lAraw3oxT4lnlt4eqU Rlzvg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFCT83ts3xpHDuUgDdlzQtELcoAknrXBpsFepmdcEBLccwduWOOVyAuau0VlYvm49 objBvbnGefvuHsKXiB+MOl7qErn3M4/Q7Z72R+asBFni+WG6jRYqPjjJBv1F7ovmfnEZp3 uEJcbLADGcdxsWcYxdWct2wwV9KQaoOTpGWM7Il7/oKOILrVOp7MvqHbWAXdA0mgRBniUZ 2M+Su4Zoe9zFbzekNirjNltohahTSfzaLbYZTkGXD/hRQ+ajqkABo2HdEn2GJrc7g0w4Iu PhTUexE0AKZ4j2dsA7W9i19VnbZvZZgTTujH64lpg2nDW6KlKK63jDlRsrLETwVfJ8WCN3 +MwnMNKlyxvUtzgJResqXczwCWadQ6jU1lt/NFr9LVMmwtO45z/bD0abIHltz9TYHjDzgp tzxRu8BIqOseqELdQvOAghT7ZVTUm4SX7v8ugAsJzlfzsAmlWYj3VORfDIneiliZf4Xhrs wFxQll2g0zT3uTAkt/VKUh2MJyM5D4ukmzTG4TMsHHvIb67YJoPZ7lmgfPJM8sluNJHuOU rMTtUPcsKYnfwKtGXzsruC6CBCw0USjBUoVKq25IVR1cg7mzZxzMpgaxd5AXj27ReknwOf ja+O1ZIt+CCcU3z435RDhuMPTZsAv17wWQDc59fDOMrMjT36MyNzf7P5jumQ X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:30 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 10/19] selftests/mm: add khugepaged completion barrier helper Date: Tue, 8 Sep 2026 13:50:56 +0100 Message-ID: <20260908125105.1510704-11-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 Tested-by: Muhammad Usama Anjum Signed-off-by: Kiryl Shutsemau (Meta) Reviewed-by: Baolin Wang --- .../testing/selftests/mm/hugepage_settings.c | 60 ++++++++++++++++--- .../testing/selftests/mm/hugepage_settings.h | 2 + 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/mm/hugepage_settings.c b/tools/testing= /selftests/mm/hugepage_settings.c index d7917dce3aba..ca73f9ac8e9b 100644 --- a/tools/testing/selftests/mm/hugepage_settings.c +++ b/tools/testing/selftests/mm/hugepage_settings.c @@ -183,6 +183,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; @@ -198,15 +205,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]) write_num(dev_queue_read_ahead_path, settings->read_ahead_kb); @@ -230,6 +237,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/testing/selftests/mm/hugepage_settings.h b/tools/testing= /selftests/mm/hugepage_settings.h index a1d12e2ffd62..2ea169d11796 100644 --- a/tools/testing/selftests/mm/hugepage_settings.h +++ b/tools/testing/selftests/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:37 2026 Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (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 672D55452B1; Tue, 8 Sep 2026 12:51:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871896; cv=none; b=b+hsk5HzfLtq/ymvX+9BespcyyatMoFDw1aYblcyIsEoLjyYdAjt+P1LUhS+zZkL6lls40txoOR8EYyTf58m5auidy0ii9aLw1N2B/EcsTLUkFzyDtMIG/oMNJ2Qmn4K5ympKA1TDvY9ADYj9h+H1h98Wb2zO24QO5gU8MF3ILQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871896; c=relaxed/simple; bh=CRLPCESiGAEkj9k0/tVJTNS8YP0ZEgP/6LiY+drOhyI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SN92lnjV7G1UD5TPVlyGUDLaam4khwmn/TuN/xpPETYY60sIwukF1myqMFfULlCFl5Ke/YGzzXwlw5qY0w9y29PMzg44xRSWxoRHJnETKQhbvzIx5BZDg+rGJ3GdobCpZLv+bDkhjh1z9TYcXKMChZ28LIKdi03D9toBjsRuyJ4= 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=Mb78XkeA; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=hw1SwZL0; arc=none smtp.client-ip=103.168.172.157 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="Mb78XkeA"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="hw1SwZL0" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 4342F1400044; Tue, 8 Sep 2026 08:51:33 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-05.internal (MEProxy); Tue, 08 Sep 2026 08:51: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=1788871893; x= 1788958293; bh=zZdwyABOaNmEF1DzIgN++GAqrNvL2Pol9IuJicRUy5c=; b=M b78XkeAnXboPXQjTmvKBc03Twx79GMqtjyueOvDCw7zAWsEsBql7r0ENUqaLb40z K4Elz5yYzUAUJYuFRDk0qMrbFbUDcjqFmNNAlrYAbHYEty+fcv8VlqzUmjsrYi8Q bK9jRj9oBS2tPLfwRzNBQo3YhDQ5YiBIJAWHW9OdaUn1Oz7SJIFiXheMO+EN6KUF Sf1GynOCBUoAX6TTifGs90a/3vESuA5bMyERL5Mt00PyTeeBcJL36ALeFI8+kOzL eXTrUSoOEuV8Dz3QjaNaKsClZvsgOdr0+MCwQWcYoN3UnO9Vcw7zgsV+kIYxt6wl RfSLk6dfH+tcLotESXtAw== 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=1788871893; x=1788958293; bh=z ZdwyABOaNmEF1DzIgN++GAqrNvL2Pol9IuJicRUy5c=; b=hw1SwZL0PJF2OIctz p7ojpTWonQ1IpAh8GxmlodNHM9Wh7vxYijwlBTEUzkusFxh1bgEhGp0zTt11pkue NYF1FiB5Gfel26AByPnELaogPr6Hwz9MXE87aSdQMwTqxGOoHtwNiPk/ypJas6On LoISFuk7HWimKApQIWzVviDLxGnWE8dsq9tTTZisHE9XDafcauFXavU7tTJdZ+TD FpSAFOIsh8znnR/Zos/yIzZbErRH8i9rbmLX6ddhYeFu9sZPNXrgK0/EcVT7NAPs nmI7d0pftwEw+VcdASAozQsNfaJdaNiwbLw6XCzNQZKasJm/whPGB5V4C+RY0kwT QqG5w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTG2QNbEXtfY0NUH9lclFg4+7JIhiWYHukGkvnVSObSRwNQg1Sx7FYcKV3VpQKoNMX 4WQF58dhUXXs244+umMEX9jrGkMDwRzzMVgLkyqRYe3luiAtSdPaAslf0s6HAW42eLUNv6 Yph1/7mYlVaPCfn2xuWU60bwW6XHYPjfiiyNarJsdoAUaCUYZV71ky6dHMPGvGVuM8xvW4 m6EUOqtp7REAN37ZPBvE9zNKgCyv7ortpG0xd0B3rAc4044T4WY38XKdTr44RA10FWmQd5 JtVQe6/NLKa8+LTeK9YofjDIdR1CHuwVtlVlxJps7ZJJl3uGOhbQDTam1VDoGFqiJQ2gsh e39YrcQvUq6AYUDrO9sflBa9KyEDsXs89asHcGNvRuUrQ1LmHXFCAxVgEYhtAw6VUVxcWz dLhg1J2V2OGEMz7wwDo4lKPHRNRqEku4lCyl/N9v9Khjf1nonvSVZBO56v4OknNo+C7n69 HUdxgGWOZyzcfYVEUXi3FO+ss8/CTFx/bD2NczSg/G7LWN7BRqghdjpTIqwN4NkUo9Q0zf 295Bfqpf/YN8QzYJx7CsYum9LbB1y2YcdyBayR19vk+6ZWLG1vremh5qvb2fS2Rfd8G7B+ hq55TiTknTDV22aWsxOQtGI5CRE5gmfFJzo8yzAmYeFuMPuXTU69YiXH1oCg X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:32 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 11/19] selftests/mm: add order-parameterized khugepaged collapse cases Date: Tue, 8 Sep 2026 13:50:57 +0100 Message-ID: <20260908125105.1510704-12-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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) --- 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 e9bc8fe8a1f8..fb4efaf67c40 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -31,6 +31,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" @@ -1207,6 +1209,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"); @@ -1375,6 +1569,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 /* @@ -1425,6 +1633,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:37 2026 Received: from fout-a6-smtp.messagingengine.com (fout-a6-smtp.messagingengine.com [103.168.172.149]) (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 35EF7545D8A; Tue, 8 Sep 2026 12:51:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.149 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871898; cv=none; b=QOauZ1ZufAi2Q4wcbWoz1w9JVFYYPuihJa1l0zgXMfh1LJyX9Gu1CMBnu5E3aNsMDOVupYeV6J2jRao5pVpEzZng3locB2D/8PhmySb5PllE6Kz3wgC8JvF/15T8Yv47tDt4HQ8uVfhlVfWUeso4SifDBOOx8p9JHkz2e+6RDWw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871898; c=relaxed/simple; bh=M6Jf/V12XFKo186JFVDLx8ROkS5e8Zn0HYJm1WRgzrI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZbSWyv9QGoZRkCFEhqsEMLGzygcI1ZlF1agCPojooyQ76XZ1j1/nJeiCAX7f4OFB2IThIC5G/LQCsF9Q4u5SHyoE7v9QzTm0IpLc8fQMnzFxy9VE3odqIkov8/5v83v1Ad2reQUnJ5RP2eoE8Tpas3AXkVfVX8gjycqONiTQkhI= 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=TMV4cmol; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=iFYTl03s; arc=none smtp.client-ip=103.168.172.149 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="TMV4cmol"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="iFYTl03s" Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id 3A20EEC0032; Tue, 8 Sep 2026 08:51:35 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Tue, 08 Sep 2026 08:51:35 -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=1788871895; x= 1788958295; bh=aAoOR2JpHpeae+txrvqhct8oCjiMK1u+dO7P0yt7mGY=; b=T MV4cmoloJrwMWev3RQ9drw5GaSxGrwTGLJqzy8wDPst53OjD4n7sATPRu7Y59jhW KGUSMXMIFAKQSyQ0JhbBTT1/zQKipJ5szN3yGai4xryF3F5uYD6zat/fo509pQun +LVXHKDat2sXYDQ/0WDZe4wg8ifiytXcT9VPfhumlTK73+kAmYpom4wypkAQ3c9u ph+M4ui84MCPW3jJIjzWx4yuWUa3HQ0tvkM/O4j0AK/nArhbGpBCEQOCjw4ECzrT 5ogMDkyp0qNR1BSLckBpxBNiFZ3dwaoKCU/XgyqzRUyihqpNF+5Z9DBu5XkPMaF9 JGegXEKQUBoO8g8tkcU4Q== 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=1788871895; x=1788958295; bh=a AoOR2JpHpeae+txrvqhct8oCjiMK1u+dO7P0yt7mGY=; b=iFYTl03scM205lMti zu6nsqBavzBq2vot9GYPyOX1lNWHP1CX2u0WwoD3jYi7bYIP9eoqC3mYFFU+x59h gr49yKlvjlOtgFVTZfgwoB3QUo53oxfrBryZHdyRZMD1coag+yFEE6eJdLR3eM5D 1Uu8Xg7SHaglbkx6SRENp8anIJ2e0LQ2eYDcoZgb5r8hbP4KwINCrdQ4bIhR0ley kVp7fB19LPjWufW4sKkTzlTeK+YlaNkrEpi5RK0NYER9GyvSW/uXHHwrQ2y4kLHj V2AtfcHAeP4I0MrgrskmL4Cb2/0mO68doabZgP8RU9+8I4XH3FnYu3YXPxtY4IKi oFO6A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFWe/QI6m+ZXOiH25I14VSUcDEmQWvIJTkoHMAZtN2azwvxUv07K8nNahSlNeJ4Z9 6eHjxl/BiXM1vPYXBSjNJhxqwqvDDNYnCkPHmLCbq4adC57onKQLlqdPi/SM35ZhUSQuAt oRpyp7Ri3t8bYQcmJtPujCQbmd86G+mUWXXI2nu6Mtv09ASCHHJTlzhzeQpnnFQ07IodBo 3ooVqbRyu34Jvm9Dh+nNFu4XRDq6hWeQ2IW+S+nyO71TFsfO33MG2zd0J+TcVl9g/s7mL/ x93b/UdXcwtuY1HOdcGRsIdopKTGnoTNDXdbX9wz19n5nkOd3IsxnbGCKHISgqzDlIJpBD 7kpFqjWaHYh20TF1Po27X3IUf2hMX5WsY2ffOrBn8O33Q4PGlV+0eG26xYkEoVPjpLUQ7o K4Gw+1BIHrS6+Df0gszthr8DRxnMQoOSZO0zOGZCNfutMv443eaJo6WYdl2v4wMZGU6svH nRDQBsmPu/104D5jb6kvKPpcsMCDluEQBGgVtgI16Tk5ZZuiHVgXQpJO06zvlykLvd/xIU O59/TSCW7b4ZnRZQ8uEo0fjBLO2VaS3b6G5vQUvF41wiuhHQkX479nttXU3hp094FjYQbm fA2IsmO+3dizMZryokRV+4EP/gN9G0i1r9RtmCtB4HOw9ZiQ4bEiDJepkq9Q X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:34 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 12/19] selftests/mm: parameterize the mixed-source collapse case by source order Date: Tue, 8 Sep 2026 13:50:58 +0100 Message-ID: <20260908125105.1510704-13-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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. "-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) --- tools/testing/selftests/mm/khugepaged.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index fb4efaf67c40..b15cd07fc0b3 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1352,11 +1352,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; } @@ -1364,7 +1366,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); @@ -1374,10 +1376,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(); @@ -1387,7 +1388,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)) @@ -1418,6 +1420,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 --=20 2.54.0 From nobody Fri Sep 25 21:41:37 2026 Received: from fout-a6-smtp.messagingengine.com (fout-a6-smtp.messagingengine.com [103.168.172.149]) (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 0A41D545D9D; Tue, 8 Sep 2026 12:51:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.149 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871900; cv=none; b=hh9/lT811BfLlIfsSjuldpH5VnmZASBH4SnebqQnf3aZofGqLusfotgxJEYck31imMk4x6UYYmSRmZDtsu5I9OCfmLBnbwUooZYIguPxm2s/RglRhID+UfjWsmbmiFqGEHCrgsEWceBIZ5BIvJznZxsU9P9K4SzGH0CoN2A4Ams= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871900; c=relaxed/simple; bh=r9+Cf6caTI9Hz6eRErUCNLkEAdlGwaftdQQcpJytWO4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IdpKdWHe7cAyKB2bCpoIA7j/r+hIRH1ViLZfZA2ZCnQwWaO33zQ6VEC5R4moCz4elG5WtHZ99H2W0NnRfPp0x8y2go+mTJv/TdgPxmWyNPOjUyhHZkfIjzoPbWUcWcVsj/HGWJw8cAOke+oT1Yx4NKGfN01bJz9JkY52ilpYrfI= 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=PfewFF21; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=M0SqDjHV; arc=none smtp.client-ip=103.168.172.149 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="PfewFF21"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="M0SqDjHV" Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfout.phl.internal (Postfix) with ESMTP id 0DFEBEC006A; Tue, 8 Sep 2026 08:51:37 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-02.internal (MEProxy); Tue, 08 Sep 2026 08:51:37 -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=1788871897; x= 1788958297; bh=qldUBMROz+IaFvGXCDPIVYq1t0GWR0yhYtHQ48mvYkw=; b=P fewFF21Tpf2j/Miajfmjpz0sAc3frA2GCSQ8SBkZkCfL4InJR3UtpnFeI1OGcGOX Xn/W+sc9HEqxKdKTLSJonoR+uH3C6YU5EuDiqtNWBPYKo3c3JtZCT+cvpYItHnUx h8iq7/JK2bBSi1O3T1YtFMgS1nPRna0vENIUe82IajkdZCW0HTrwPmJCMpz3Gr2I HTAT2U2cRCz3W1wIXh21wd+5SmwZMnkMeB6Mj2LNGrs17w14Doja3JY9e1kYPJTl ePn9tBF27MBovGztsLjIkY8SiluJ/XNdaBveqy6sDC1vr943wbxguoinZMfjqRxR oYPpQpi5WiYsnbYAYUARw== 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=1788871897; x=1788958297; bh=q ldUBMROz+IaFvGXCDPIVYq1t0GWR0yhYtHQ48mvYkw=; b=M0SqDjHV7lLSHZh9v C3dB6okQNFvKDATjcGpgwrN5hc0+/0TB1T64huXrxaqcxZw+74uGQ21cFqdXy6Ir 4L1DNXkAcnaLxv6EVoXF2YtLRXPKt/r7GtzgrF6r3vyWYb4MGTteZLZQEMtMIPuf z8ZWF+ZT/m2bnbG4gZHsLfPJiyCWBr4VP7beRD95nibP3ouB4S/lup6yQs6KiECB NBiQc7RDWMAfRWY2FrbSIvx4cJ9hbw8ityxCIuLrTetNCAF6Hd6U1orauPjRrgXQ BDXB9Cm3aXZ2tktSQizqhSdRf6LFGP4eBB9GARtdjlSe8KDQoL3f+1cyG/C4UBRr DwW7A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEqhwhdybusskt0pvIfnDHaUnU8VDm23OZYXtTM+3VchiC9Aeb+sVxnsk6fYrSw+D ThqYkrS5/6/vxmtuBdFXmhYIhVzzMwKM2h/EuTd0ioKo/SR7JG6qiZdpwqyCgxSw3ap0C4 BwVCwTZ6/NsCbeDdXy9FE5B58Xto5VjC3MUnB3djmw4ijxWpRXgLZG/TTGkjuz6Wl73hCN DLujar0Luemoo2GGzStZ/AivOKYRI2J4riPLZz79qeImA1Ygm/BltYdUhOJX4iOWEiQXMZ R5ImdiLN0us354rUC8gTNq0PrK6J11WLhxFnA56Lf/FdfG/G6OPaoDYxKnsgAlbq4sHOi6 NvIbZOZEtiTeN/4yfCgIFcF+icU6YDIkjvjC7OzGF+dL3TObMZpwcq+9T1R4rMNvBcFFpW x6W2dA1MI1YePYX1GtDkVZ8RJKRjEFkXioma/ZMRUkJfs3jpt7OjI8S2c4tuhCMGoRav+D g2C2IZzaXd2WUOJATJ9JqgPY2CFu9qIu/JcmY7z+lFnu7SLI22fokcG8gC3ROeCoIfgf/8 9bXixF2v/IqACwPBfA/ngV84kuZYItqVUSDdYj3wCgFoTwujGtLtfuyEBaKLx4YD+Wdho5 ZZycM+hQSOG7Kr94EpSdZxGBpCS0OY50DXxG1ah89t9I3dC7ospaINBNnfnA X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:36 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 13/19] selftests/mm: cover a shared-source collapse write race Date: Tue, 8 Sep 2026 13:50:59 +0100 Message-ID: <20260908125105.1510704-14-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 | 100 ++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index b15cd07fc0b3..f5d4847c50cd 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -1164,6 +1164,103 @@ 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"); + + /* + * 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 (;;) { + if (i < n) + ip[i * stride] =3D i + 0xbeef0000; + i++; + usleep(10 * 1000); + if (waitpid(child, &wstatus, WNOHANG)) + break; + } + + /* 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) { @@ -1695,6 +1792,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:37 2026 Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (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 22CCF5476CC; Tue, 8 Sep 2026 12:51:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871903; cv=none; b=UNWR6wyOZm2Zignrt0egrP6nEINWxaooopB6Wk81f/eSRLP8IQUlqbUkOJEvY/MwFo/CrOTMLHrfOkvOWkOvw7ia42r4mILzMYy4hP7z975qut4+PV+iChKCD7bEP4AN8sqSg9cvQPN/LPL3ROnRET8uZhMIqf3U7EZPwOktfJY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871903; c=relaxed/simple; bh=pm0hmwK/Uvvrovqw2HZjHx3+LPRHpgmdT/En6hurEbE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jwtxGaOlRa4qbbIqrPvzGR4wPLqycuV0j1T1Fhp+ZysYTncohDtzxEU5DIbCrEjA6RPRnzOHVtWJHhJH5rywviKyMGzs2aek7eh4IFLZtYlbIr2Sy66wZLfbyqpvDKg8kAEH42IeGWcfUyIjq7lSlojjjtLBVqRk9RSJRV0wsL0= 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=HTpu1xQN; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=D4q1B/++; arc=none smtp.client-ip=103.168.172.157 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="HTpu1xQN"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="D4q1B/++" Received: from phl-compute-07.internal (phl-compute-07.internal [10.202.2.47]) by mailfhigh.phl.internal (Postfix) with ESMTP id 371D1140005E; Tue, 8 Sep 2026 08:51:39 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-07.internal (MEProxy); Tue, 08 Sep 2026 08:51:39 -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=1788871899; x= 1788958299; bh=JApbG+zgN459BPFaPp1XWqEKWXjju/uVB62sf4HaQ60=; b=H Tpu1xQNfJPjJcrMwnI5zC0euosdiHKzWh9LbQ9nJKv0lr9THAphvK+OauWaaIu25 sPS+1g8JKgURGBaZ13Fy393fm6xWesz5ku1hmdfQHJB9HNE+YR1KuwvAywqgH/kt vJGNrpZ9nSM8BD2nrCGXLTaJhqsO9gApq7yMd7lsjiUKPkd5Wa3CzuUZi0AhLSQv Qw3gTsF+Qzxl3GtC5YHH8cbwj1RWvpRuKWvQNzNF3rYKvluMrH5si+tI5IT5wNeg +RC4gw8bCrE0n1m3iFH55SILyhT6kYlbXrHzTS45SbALulDUChY6Aiu8Nv/8FLpG YUNH883l5WxKKpDquSD/g== 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=1788871899; x=1788958299; bh=J ApbG+zgN459BPFaPp1XWqEKWXjju/uVB62sf4HaQ60=; b=D4q1B/++hfBNlEX56 dsEwQAGIQf5czBRS6XBCiIZ2CHNEuhegMwsT+U+Jnr3R0jOCisPqx63ljrde1boh lxNWuRoJiH0tAut9Q/5uAdV3OxGoa4yqTgEVua1UsX5c0nTw1qyeHsKXxyTHbR+I KRIZ+qm8vYylB/R503dtgJM9Roh61tz/wkKpBtw8kXhkuLMHnI9Gig0vHGrErEpw SVNYRWaPg5ELJzwhCp4KG6fBxV5ypBf0tVssCR3VpKC22ShcMM0YBgycZbalHKpr 65sauOZDcR9mZqDrNaaMEbdGIInA+BcEHmzKzeO5aGnygDUcV4P8hN+0ITuxdmbS t7/6g== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTFCT83ts3xpHDuUgDdlzQtELcoAknrXBpsFepmdcEBLccwduWOOVyAuau0VlYvm49 objBvbnGefvuHsKXiB+MOl7qErn3M4/Q7Z72R+asBFni+WG6jRYqPjjJBv1F7ovmfnEZp3 uEJcbLADGcdxsWcYxdWct2wwV9KQaoOTpGWM7Il7/oKOILrVOp7MvqHbWAXdA0mgRBniUZ 2M+Su4Zoe9zFbzekNirjNltohahTSfzaLbYZTkGXD/hRQ+ajqkABo2HdEn2GJrc7g0w4Iu PhTUexE0AKZ4j2dsA7W9i19VnbZvZZgTTujH64lpg2nDW6KlKK63jDlRsrLETwVfJ8WCLQ UtmPZMHn5ay6tSoqiUnd6aERERueDUk7m1Mgai0xS1+/KuDn4S87fMT5aaKasKywkBgE6M 5mAQT7N7pXGr2zqzH4MUoTyBkuHaDOCs6jb4yma4TOqJS2Agge58jZ0eWBs0O4U041BCgp v3uVn2+sOHEEb0jzEkvs/X5aSPHcXSCFEzS+xuSKoWu4vPBUoRt2A4533btw9z4rbJ3vux AP7Ot8KS571U9VQFPuETi6D7vhJrqU+nDWHrFlRbU2lO3ukuxC6nlRKGG4SMeuZCm4VDea S3mVzB5nkhgLKRjG7R8N+1/8PJoC4wpvvNpB9I5aH+Su1LDqiLPEzyN1MBww X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:38 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 14/19] selftests/mm: run every supported collapse order by default Date: Tue, 8 Sep 2026 13:51:00 +0100 Message-ID: <20260908125105.1510704-15-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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. An order at or below the -s source order is skipped: the sources would already be the size being asked for. - 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 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 | 98 ++++++++++++++++++----- tools/testing/selftests/mm/run_vmtests.sh | 2 - 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/mm/khugepaged.c b/tools/testing/selfte= sts/mm/khugepaged.c index f5d4847c50cd..335f946eca61 100644 --- a/tools/testing/selftests/mm/khugepaged.c +++ b/tools/testing/selftests/mm/khugepaged.c @@ -31,6 +31,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 @@ -1517,12 +1520,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; @@ -1534,6 +1539,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: @@ -1541,12 +1547,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; @@ -1557,13 +1576,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 { @@ -1579,20 +1599,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(); } @@ -1614,6 +1634,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 @@ -1629,6 +1650,7 @@ static int nr_test_cases; .ops =3D o, \ .desc =3D #t, \ .fn =3D t, \ + .order =3D collapse_order, \ }; \ } \ } while (0) @@ -1669,10 +1691,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) { + 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); @@ -1721,7 +1768,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); @@ -1729,15 +1786,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); @@ -1810,7 +1860,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 2652a7920b80..8bf898b71350 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -412,8 +412,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:37 2026 Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (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 F3B915476DF; Tue, 8 Sep 2026 12:51:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871904; cv=none; b=nvA1ByVH5NIEcIQ7Oaqq8dm2P/6Fa6OWE6t15VnTsdUGTTqZtAcKo6ZJOKi8WhLdgbr0FYI0TfBlKerCJNQ0KquPFLEf4N+YA+o39FNBkM6TbgruDtC8k746QqxqmnPF2bxpl9POr+wCBCr+XCNChpxjWy3a8fW3BFBkXYhQ3rc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871904; c=relaxed/simple; bh=V42j0iX5pAWRXUMVVjzxfFEweY9WC13kbOlvn11gMYM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Xb2DO9X67LljduibUQfQEozKVnDT8KwJD1XDLcRo+OIV74PyCSEg+DApp+PdxbJTpJj77thOoS4CNVtZ6lKPVX5WdjrBcV99MJ1mfkiKnbT+yFvWRtTdiML8kQJkuOLMHNJDdqGFJfxCKGWFQY/Es/BQHIjRcZgsJi1aIMbcKjo= 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=YcoMIY5j; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=fqFNXSfR; arc=none smtp.client-ip=103.168.172.157 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="YcoMIY5j"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="fqFNXSfR" Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfhigh.phl.internal (Postfix) with ESMTP id E44D11400067; Tue, 8 Sep 2026 08:51:40 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-06.internal (MEProxy); Tue, 08 Sep 2026 08:51:40 -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=1788871900; x= 1788958300; bh=CZILZvAOGMjI41LtAL9Wja/r36L/47O7Yom6FYG5W74=; b=Y coMIY5jDzpE+KozJjskv28NmyDqqWiuYlVmDid/8n5cqvaLGv170vm8yXGEeFQH7 rj4NhyH+344fnqST65AmGAHJ7XMVmMyni8rTtY9Hs3yWG//iUxeYPpH+zuGYP2RS ls5GQVLnP/xMXm0RmpF1uHCtpMHXM2s8kM7nDbeXSDcmHVEyNYvUabWZKsYNMlVW a3/gDJ0wIslM39j8+ub+Bf791DjaxhCNZbjV5GvYrZ3FupuRb/vXb7FQuY5/vEeM CtqbFC6RZzkC9nM0RjJj1GpDsl5JaLAW7VwtvmT9Ei3e0oqqMUvgpPgZ4cERMK+9 GDlHvylMtiagzmuKZyh4g== 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=1788871900; x=1788958300; bh=C ZILZvAOGMjI41LtAL9Wja/r36L/47O7Yom6FYG5W74=; b=fqFNXSfRvbyByfW+0 TBviz3SLNeyttmM5UidxN627rG+HUtl4TAuM/NZEAExGehxhybdtjwjCadZtVz0D C3sxB7JMST/u8j2jsVxGIR7Bs94p1TZeKfa8MKm82o5zqaXSAyiCBNpM221QxHVy NY+bdxcRWbfqvdenSmxnCthdp40UTK8h594rIColX3VO1sxcp6iysNdzQ/6w58/a fztkrhrTS3TYDA5KDIWlq3ZPYzyIzIIEYJ1z4lkqMJxfyrEuGZopb6K+qLY5kAlj Jur2DCK81+bxVlJZpUBScTR5T+XrPuz/z0UY8FAXO4MWAw2Sf6gB+1TNI1HGMMKY iDxDw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTG2QNbEXtfY0NUH9lclFg4+7JIhiWYHukGkvnVSObSRwNQg1Sx7FYcKV3VpQKoNMX 4WQF58dhUXXs244+umMEX9jrGkMDwRzzMVgLkyqRYe3luiAtSdPaAslf0s6HAW42eLUNv6 Yph1/7mYlVaPCfn2xuWU60bwW6XHYPjfiiyNarJsdoAUaCUYZV71ky6dHMPGvGVuM8xvW4 m6EUOqtp7REAN37ZPBvE9zNKgCyv7ortpG0xd0B3rAc4044T4WY38XKdTr44RA10FWmQd5 JtVQe6/NLKa8+LTeK9YofjDIdR1CHuwVtlVlxJps7ZJJl3uGOhbQDTam1VDoGFqiJQ2gBw 3q0E4E8u/jFr3S2c7E8fpFGFLDLMP3UAVobp3kB7y+xUXlgv7Z+2RqgABE8sredu+CQLcX XkiT66AHNKtEqpidCF9nsBxMHPCBST8FEqrwWcSZc9FQmMoVi6ETcSbc4IcLSJMQ82xat9 3YxaeeRohVrx9KRjilfhhEaMQgyrDOaVXfOqdvzufo9JXFYYpO+2meAnW/G56EO2tMqHrh lLlK3gnVYRIvLDcHQqtdIXOa2qrkh4AwIaDT56h7SVI+NkHXPlOtVrpr4C2/d1hWgqCj9M liknTVqmIy9s8xPcKprZNA9EpzGNArecNC+dd5MqMB9OZYPjzwp5fVIbmRbw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:40 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 15/19] selftests/mm: check that one khugepaged pass collapses one window Date: Tue, 8 Sep 2026 13:51:01 +0100 Message-ID: <20260908125105.1510704-16-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 2093fcf6e915..b2d6e5c12934 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -105,6 +105,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 =20 ifneq ($(ARCH),arm64) TEST_GEN_FILES +=3D soft-dirty 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..1c1b942ac325 --- /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 "hugepage_settings.h" + +#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 8bf898b71350..c0f69da3fd3b 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -404,6 +404,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 4947612e8b3d..af8324e1e8f2 100644 --- a/tools/testing/selftests/mm/vm_util.c +++ b/tools/testing/selftests/mm/vm_util.c @@ -599,6 +599,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 3be430e01901..5a91b9676ec5 100644 --- a/tools/testing/selftests/mm/vm_util.h +++ b/tools/testing/selftests/mm/vm_util.h @@ -119,6 +119,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:37 2026 Received: from fout-a6-smtp.messagingengine.com (fout-a6-smtp.messagingengine.com [103.168.172.149]) (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 31DD05476DA; Tue, 8 Sep 2026 12:51:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.149 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871907; cv=none; b=WxUs4WzH5YU+vUCDO3OlTCgx/sqMftKaszdBDWOqg5tkDIV3zyhBBn0KW3STHykbC9P1GTiBopxnF22vxqirOcU0/xazSiEl1EP3oW1akm0ftHRE3Y4X3i2vkZ+8PofO0/bfUwGZcILXAt+F3bc55stCm5ZWLrqrldW4PT7vfnA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871907; c=relaxed/simple; bh=2V5GT1X3gyhuuY39MzDoLiOvH90LeQ2ZNYyUMuMpw7w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IskS1VeGC4tZbztaFb6a4g5I1qbyRretxwP+/YKU7GQGSLtSxYvt3UPRlmX9vNwpK81PUoN32uuVHFqx7FEEKw6j+dmbYb/2FZo73CRWevaqHa4REuN0QclGjdAA/XT4bcKTnuP0SZPsFfx6qQ6OVyJ77dMJvTtES7FlCmQkkXk= 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=eP+Ag2NR; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=E81WlkZP; arc=none smtp.client-ip=103.168.172.149 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="eP+Ag2NR"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="E81WlkZP" Received: from phl-compute-01.internal (phl-compute-01.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id 9471DEC006A; Tue, 8 Sep 2026 08:51:42 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-01.internal (MEProxy); Tue, 08 Sep 2026 08:51:42 -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=1788871902; x= 1788958302; bh=1unT87Lq7u+KlW9Co+t6ru/BE89W6ONlMNwMwp6MA8Q=; b=e P+Ag2NRIZMNyziFEN9mwwKvR/+V51pap20YIS89QVnGIMimoCWIkkWCTquTED3oF u2m6GzXYCAY1DwHJq/e8L4Tq6sCY45kz2x1w7WLvZeMZ2ruWySuCuD22ODRmmy0Q PnlPBUNzDmYsbNXEkrb9zv4P49ZVfJIRgGd3dpMHJOAWA9lnoQar9z5KnvFr89zV BkkG9t6a1OKFb1b4PH5bwYP/2QRigO0hSiZDNjpwBGZ8WP1O0aNGW4oZUv98rV8J 2vU3q08fv3ktSLFMiOrV3n6EvZwZit0bSl/YxsV5o0qDxEptOFgkW606Di0h+32l XaegD3+UxInPQWECCLVhA== 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=1788871902; x=1788958302; bh=1 unT87Lq7u+KlW9Co+t6ru/BE89W6ONlMNwMwp6MA8Q=; b=E81WlkZPALgUQPZOg F0iUxtMdXew8EETFfNpRVqVqKybwpLcSUXpo2RSozaqb2QAeZP+5Oj8S/ZH+XF+F sX9qf9qnByFlMZD6xN4S8C3vdHkS3is4lKyHiKnK76XQQXJlcF3irh+g9OTBrye0 rYbmSUIcWXD2pmLbMLVJQcA8LWM9CZ9ctx3Dgl0bqY/xAYlbL/UKTcNBFeVTiT8C aC+Ru4Tiv8N6p/T3wL30AsR6No8UnvI9mx5D4byL0CTawwEtZFZQqdDlJN+JVPf4 H7utQcEzMzImOVj61cvz7SpWNYvmBlAP2i9DEuSCme4GLabfumufI0HvxTjDi9ZB +FhCA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTGnwUGLVSeW1BZjwXwEzw+urlx3mhNN4Gat/Zr8Ko3PyRi/hbLWgybpr9vD6UiZtB ClgmaF+ewm3/RMVDG5HlNC86fy+pq7ADG2BzYUhbZNKO7wBVrMzlr3sUqSigFGZOoBtGTx gIvu2aAZGSG1tp9oBvzbgbiiOvG8y4h9kz65seWrJfEwnZ8Rc2pC1MQmnPT64gFUFWDzlM RiNFVZKD8mgg9fzzj8qOYTQFdG4jKe+gjSJLicGunwl1BDHVIlxYuc9XbgxMGsYndbdG+r SzwA5wdO/TxhNOptcwVG8cZe537iFTZCjrnNerCLGxDTvjjKWH9WqAatCO1tL0baXTf7GZ V4/1MI+BTYGky+EORQHNm/ZYYfA51lJIaz8iylC59cZlzuxyxRL5X4q1PzdsENX9BGsyx1 jjdke+FRHts/VsjgDXPJDGe/YqWek7MchK8FXjSWA7+9LG4b/EsdrzM+zEpEGQSrtL0o0h Qxk/szdej34GnhL65VVVASSQLvrd9JQvw/oiVAMQDuXX4dedh9uqETxPhcohwvRV1wQ0i9 4p0P3UzyN/u9e6d1vJLueLlufStargN8upWAycGtp+n5qGi8zw2PkoyZlrFxl7E5BeYfhp SXvRXQ3Je/bX9ERjacLe+1ZqxIhnEJPACPH0MJKzWjphP4lWjZ2dMcGfr/8g X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:41 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 16/19] selftests/mm: add khugepaged race harness Date: Tue, 8 Sep 2026 13:51:02 +0100 Message-ID: <20260908125105.1510704-17-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 | 410 +++++++++++++++++++ tools/testing/selftests/mm/run_vmtests.sh | 2 + 3 files changed, 413 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 b2d6e5c12934..308bbad73c11 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -106,6 +106,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 =20 ifneq ($(ARCH),arm64) TEST_GEN_FILES +=3D soft-dirty 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..448256704ef4 --- /dev/null +++ b/tools/testing/selftests/mm/khugepaged_race.c @@ -0,0 +1,410 @@ +// 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 "hugepage_settings.h" +#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"); + 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 c0f69da3fd3b..fc61907aa3b2 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -406,6 +406,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:37 2026 Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (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 DCD655427F0; Tue, 8 Sep 2026 12:51:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871908; cv=none; b=jp7cnM1RdPSwxQprJ197oCKCZ9nJjVFq6RjCR/5BtZWs7wwmwpD/Lbx6rW4K9lUg2ZqBvtv5K/DcuU3hxY5+00hVz6F6EzZH/+yNuzFZCbAHRulxSxKuq4+FHQp1N3cCVAmOKZDOcSBqsLPgGDwiZXPTpZiPbgpTk7Jx2gp1tMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871908; c=relaxed/simple; bh=sEDoyljbr1xNNULU2pd7wIPLaa6XceILZL9t8obyF5k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lgxWJqvRgpUu8TmWX+trZCr7BQs/tzAmjka95PAf3+0fEg7RMelpn5tYNo+6wKFQ8RtsTroeH3wrmGdYpG5yYjxXGqgvzJMVO3/8uMRD9FE2OLVDGS21FBYY/wbXSqidZsa1D9gcG1o3cicULVGejG0LBsZYVEh8c8kS3q8HfUg= 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=Cen3VCr9; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=srxBstZ/; arc=none smtp.client-ip=103.168.172.157 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="Cen3VCr9"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="srxBstZ/" Received: from phl-compute-07.internal (phl-compute-07.internal [10.202.2.47]) by mailfhigh.phl.internal (Postfix) with ESMTP id A38DD1400068; Tue, 8 Sep 2026 08:51:44 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-07.internal (MEProxy); Tue, 08 Sep 2026 08:51:44 -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=1788871904; x= 1788958304; bh=zbCvvEeTGNJUluvqL2n+kCyw5bEenmwnstQ3FSwOS9I=; b=C en3VCr9mXESspPmSzUs7MHT+mJvHcm6vgknu1Xu5L/YIItjs+W98YEnu6RtbWi9m FOx5327IK31dXKcjveHab/Ji8jDpeyWFqJV8fjlAVEiVXnxCA9bUpwOGKxAQa/ea I9r08baLelHbK1KX99lBEJYNzYlQhk3+imEnWWl0pyh3c4eBvUUjVz0XMAZbjSJn /A21txCc4+Q2umLOWBeXgw3jGKTU1Bge/xw7VydevjJvOQygDFRSVbmGHPY2azdo OjjNBWNNW5EJaEvxkJgMcwv1G/q08OwBvHfjLs6MNN+BEdnNQ3LEBRAOIsekYgHd M8kYJnd404soEtU8s0fiw== 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=1788871904; x=1788958304; bh=z bCvvEeTGNJUluvqL2n+kCyw5bEenmwnstQ3FSwOS9I=; b=srxBstZ/a5I3zrcpX CnX9UM8oNW7jIh+h9f2IPWcukw0AO8aC7fMcCzx3oCAraYT5fWZ0buEOhL9IbLp4 kyVZciL6mr2RXGJJVZIoQ1HcrLPwwrDN5fYoxCCH32J+NCX4KHshi4EtOAM0mA++ dnYz0Ui6bzMxtUWmQG25O9LjGTLPvMzjwmaEuhiUSY1kjcKrVd8vJv8fhX0I9ZVD k9T2gto/vZ57mEPTbiFChJOzf1XJISI3B6fhL+6rVaWvGjR9og0dA3cyHqrjSnhu UJx+y2PxqIVwCZFlyw+Wqug+mpvRxNjS8zuZhf6HbXi36Y741uKyh6Y2spuuzYhv YRicQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEFE5qoX+UuF24uzYsEDVhBj7K7PVNhp/QrdS9IridywNr6zbUVHRTwEJHEkegH78 2Q0FzpV7Ffbkv2IdJy+2X+gRr5j/GVU+OmQCyX7TrMKkR+B67hpV4qik2kuPcySyPVfL0N fjj0puKIPOVKC53VUKH1AFABHK+HgKXG4fFGTm0bttO6aht4AByKsMi5q5m3My1bWaIsHx VvWLDqNEgw9NR009yUV13rBPhKD5hG186SgbvLIVXWjVzTBDRGAi2tS1solDyldiLqdSzW Z7lbjekX5xhyyUWYdDppP3CJdHwaOTYUEqdi4pIet3xRU1rw2DJzUGF3Njycnc94ehWzmw R2sVtQqcjql9WndhmtChSoeg8JgqPt78nSih4/C1Mx3BlZ90urh9FBsiO6UWAUNJwRUGjc 8pZA9NVuO0gT2YokndUx/YfQS18X8XGNethIgxEH8zreKreLc/5QEgljrUNGtZJ/f9boOw wRcMCRaWqx3u9UU2hS4og0hmE3v1ab0++imJ7UI6HSA/ISHYzUecwxxqq/SvydyNBmHIFz hH/4J/13str7Xs52hP7vWlXtSeZ0hy4TIP77Wy6vvHRi2xUv9pzc6s88yXAWoav3Ojh8xW JAWrV9qOhpvWiPBqrPc4z6Va90tfBjV0yPSYDHGWPwyCfksm9cHADsVtfO7g X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:43 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 17/19] selftests/mm: race the collapse of windows with holes Date: Tue, 8 Sep 2026 13:51:03 +0100 Message-ID: <20260908125105.1510704-18-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 448256704ef4..f31f12fc0390 100644 --- a/tools/testing/selftests/mm/khugepaged_race.c +++ b/tools/testing/selftests/mm/khugepaged_race.c @@ -231,6 +231,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); @@ -298,7 +300,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); @@ -306,8 +308,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; @@ -317,12 +320,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; @@ -388,8 +393,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); @@ -399,9 +405,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:37 2026 Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (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 7FB71548549; Tue, 8 Sep 2026 12:51:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871909; cv=none; b=hOOdPgA2CrJJzglZ+e0B8ueGW8V22WkFci9u61G1dt6VxTVjmUAtse8E6+cohsGcdYK9Ef9nWGpvf4wUIbC8Hozc8nRBAywyKR0TsgrXUPANwyAk9u5qzwKrHLvb8mEFiKTSClRl+1hh7uOW4jdJpozkPkD/Uve77b/7sCUcfKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871909; c=relaxed/simple; bh=RsIVpZ5qbEkeqtMBGBz7qrrXun1dGGoYmUbBi6WCRjE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ajvn5XVCxD2ixJQutqo+tFwqxpTW7DeIN6J5RX7LxzRmRWDncvyi/ZLEWxruHzVieVfGPfs4pwzhlZIo1xZ9AuKlBbB8bZSBYEPg/neX3gC3J5tC2kApOPsPzgVLpLe8wyjUvBz2k8lmq7Oj3UzxRc59IP831rYJ4e+jGPhfo0A= 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=c9Y3CyAy; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=AvEJhTm2; arc=none smtp.client-ip=103.168.172.157 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="c9Y3CyAy"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="AvEJhTm2" Received: from phl-compute-12.internal (phl-compute-12.internal [10.202.2.52]) by mailfhigh.phl.internal (Postfix) with ESMTP id 85507140006E; Tue, 8 Sep 2026 08:51:46 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-12.internal (MEProxy); Tue, 08 Sep 2026 08:51:46 -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=1788871906; x= 1788958306; bh=zqvacDlN0e2w6egDKHKDWVi4bm/TZ7c4rTBepRvovoM=; b=c 9Y3CyAylZLS5kOC0oNs7ri1UFySi9umg5CeHU2uK4jLDC3R4j+IZN1zrsV/NBAt8 sjTk/mRcgNuuqqgS3W9rQn4N10sIsGQBElj0moQGUapZiVTgkGykyYgu115RX/xr 5QwP5ydVtCdBfs5Ui15qQNF7UJ9p5vWxjjvm+t4k3cKrEaB/+7jxaJftFGFnjXkV WxdOPuiBUXTHkWmw0mdGThKp/9U+7aF3VS9LeZDv28cvmoxhBnMEJbz1ulLA8/F5 PpvWwVvH0fnfs/YQUjzbdZ3iyLCD0waj0UKR+bezjMcqTlc/BdrF5+JETf/vtZAg ZftisHQhkXHacPhz4smug== 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=1788871906; x=1788958306; bh=z qvacDlN0e2w6egDKHKDWVi4bm/TZ7c4rTBepRvovoM=; b=AvEJhTm2JAnnieYVd k4g/vlDtlMCYLYcplvJ2DDpmxYlf/roP7IeJY/p7pFcQrA0E/Ih67pjKsfSbDRzn 134f0ZGRNwjiV/7kdQNrA+Z3BDP1zhcS8k0ipYnpCxqwFYTVQownIR2/VmzM8tvi xK1PTCSK6KtMlh8gk3CbTAD1CXMP/tYRNLMrSWVVWwUoZc7BRNFTwPN/xcHz0PZ1 DDLB6hg3nz5ghDh5iprLlY2BECTPUbjbfLxvpL8R+/EQnI9lzTsvgsAK9kJD2dg+ G8Ce+cv6Mi2R3UTAvikJ5yGioGNKhDNoBlQPSlxRLHbg5kdTzZNKvIPj95rjoiJU +y89Q== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTEFE5qoX+UuF24uzYsEDVhBj7K7PVNhp/QrdS9IridywNr6zbUVHRTwEJHEkegH78 2Q0FzpV7Ffbkv2IdJy+2X+gRr5j/GVU+OmQCyX7TrMKkR+B67hpV4qik2kuPcySyPVfL0N fjj0puKIPOVKC53VUKH1AFABHK+HgKXG4fFGTm0bttO6aht4AByKsMi5q5m3My1bWaIsHx VvWLDqNEgw9NR009yUV13rBPhKD5hG186SgbvLIVXWjVzTBDRGAi2tS1solDyldiLqdSzW Z7lbjekX5xhyyUWYdDppP3CJdHwaOTYUEqdi4pIet3xRU1rw2DJzUGF3Njycnc94ehWzPa vyAAOqe73Pl13+klFC5N/QOg1BhsXHpd+vVpfxLPxcnWMqyPAjq9YobTdfsrZ7COd/vDux AcdlwHGf6V6gdwGca+kLxFa4//EDlDVxr9FWn7d4CP+XYBPZRFx1Y5HpkUnEMvxYp8jn2v VMB2tnByHyvca8cjYMG2uRxTeArPeslgB1YFWCkOBLje8bLCFvxkQ1laerqKTxH5AUQYlh ldLdqHSvRU+u4z7McyHtiJwTtFIlJEWKTih1uh/MravE8iA21qbIxTnwg6VcYuj/RpZ27d Lj88J0kjUTocPL4rn5NVEXbn+olYGpziUqynafsRUsnixcqPM1XmZMqz2tHw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:45 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 18/19] selftests/mm: add memory-pressure threads to the khugepaged race harness Date: Tue, 8 Sep 2026 13:51:04 +0100 Message-ID: <20260908125105.1510704-19-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 f31f12fc0390..1f4aa23834db 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; @@ -199,6 +201,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; @@ -222,17 +287,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); @@ -241,6 +312,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; @@ -300,7 +374,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); @@ -308,9 +388,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; @@ -344,6 +440,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); @@ -392,26 +502,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:37 2026 Received: from fhigh-a6-smtp.messagingengine.com (fhigh-a6-smtp.messagingengine.com [103.168.172.157]) (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 4DD8A54855C; Tue, 8 Sep 2026 12:51:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871911; cv=none; b=NaWiABFDmzLktPbqrdSq4VGP4yxhZdW7Sp78KKih1tm4BcOyAqodF/ECgXWygH3+QmSbNVEE3xsL9CwCMgAz5eGNCyu5gv0t7P4sMMD2695Sa4PD57ZcPPk5go+W0AAROTZsTPxmQipYPM0WtIgVk4kydkuaX45DwYniUIrJI0s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788871911; c=relaxed/simple; bh=39Tc4T1jupVzAGe/wLAq9MZxJhYbNM++W9GWD2jQZB8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lA2wypFjgapd+gzmyb7YPCxBTe788fjHFsJ/msYbWZIOI7dZuCD7WzG2E2Dvd3nDme+JXLRWAy8ZGOI4Lx3ZjKwymeH069h2Xw7d99PclAr9aQyMlKvyZUpgnU13cfNpM3/7WQ5HkaAIo2CwNbBH1y9Ey6RIxuZLvMpOXZWgMLY= 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=bQphX6R+; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=EHwFmNFF; arc=none smtp.client-ip=103.168.172.157 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="bQphX6R+"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="EHwFmNFF" Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 4FF6E1400085; Tue, 8 Sep 2026 08:51:48 -0400 (EDT) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-05.internal (MEProxy); Tue, 08 Sep 2026 08:51:48 -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=1788871908; x= 1788958308; bh=QevT0gNhfb1/e5iwBM5FqG6u8eP9u0h4aKjgatgr0cQ=; b=b QphX6R+M0Nl+OyVvVdyGjVLXLG112HY5Fl1BjawRor878tYdDWUlossI0SWTjzud XtJtxcR03TgHGZuElnqr5kTmeEznm9csEzqtVzkp4TIR1YLJ1SgOzaPkycM5ZeZ7 vqnHzEioqwJXmGIcNmAP+WtijNA3lQND/XNGePw6siV6Z1DbQBEltcl9IrjeEUT7 xXxg8aEvx0TL7krBtd/X8mnoAynKOZrOzFeWy83o68SyYq/ypdUN8FQojM0l8STE KL93L9ogzWanCvCMGFTIqHSxeR7KcEw2VTfcadx6ASduSRyXETS/mtiHzB84mUB6 TTyGyCXDKcPPEUSHLSYjQ== 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=1788871908; x=1788958308; bh=Q evT0gNhfb1/e5iwBM5FqG6u8eP9u0h4aKjgatgr0cQ=; b=EHwFmNFFc/J5szbyr RwsXb0/sjKy1cgj3rGxFu8Q67pP8gJv0NyBl1AhEvNcfmUUiAABpPKhvYSRbw7vT 8X5rZOO1fKTt9wDUvpD0nE4//SqfJ45Bsxtjk6nGJe/LEs7lK2Jv+KHxziBC4Rjn xTtwrzw8N1/gptNoNjJXon2kmgmUvWN90ZT6GyLKL1zhWqCXOtAU8mW8hbitfPUY YFq2DuX0IPtetir0fMysbCz232FHQgqTDplKUb1+0ykOnBsIyZLPmjgTQb4dv0F6 UQNJWqs23tIAK+4dr/b6pXhxwkL0C9B/4veIc0yrx9893MaBG/kJuHPMCXbK66kh eKVqA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: dmFkZTGRBbZq0PN6yNJcYWtVb23sO8hvfZDBWhDTIpZzW37zIX45AJS+7LON/4Xm/DsuP7 98LWMNJ9EQApZevpiXRG4PtECFkYBq07HNHsbmmFqFvZsINLtRU27hF4Ez1zSV0tXKAKqs C6bKKyV7OM1sgQly7c8SX5vF/8ip2pY5lZQKXrVVPjM3l0q2o1FDhYukoyJ8Tn4JDDE8g4 UFy6VPwfY2dP93OAetWkyJVBUK9bZ6BB4d8UPJ6t2OdyQWriXopGbxrEAGUlJNHM3pyOqc Zu1M4nLcOUMvR6qUcWJFuCnVGbGfObbOdENALiH6zrKToG6Pox9htLH3ZXrBYcmcnQ2gmV eLg2HMCEwaDQFvR7ao6VTgYGmzSfgxO+jmZweEamOLo17pvBTzTIP6vKjHGwRqfnOtMgSN GA7w5TbaTBipdGpzsw2y0cPuM27YNmA69kS36BwfG7mz28Po2qxCfKKwXn1vOqv9TQ3s6S cLEpNqa7wjaC6juDm3m9KDm1uN/OP74TUJAKKi+e6S2Ro1ho8fNmUd+ik7cPlgzAqD2bMz ST+La5nk6Bxgc0AcuxcCtLtHsQu0x0UP5aqhXZhV6gCnZ3nXgbcT/d5gaa9i2IuYxvBZ84 nrSIkEkdAzC/kyYUIPPozN3LiSlcLcftIakPXmV+6+AFUiaZqEXCnWQ6SDxw X-ME-Proxy: Feedback-ID: ie3994620:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 8 Sep 2026 08:51:47 -0400 (EDT) From: Kiryl Shutsemau To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, rppt@kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, usama.anjum@arm.com, usama.arif@linux.dev, baolin.wang@linux.alibaba.com, nico.pache@linux.dev, ziy@nvidia.com, baohua@kernel.org, dev.jain@arm.com, hughd@google.com, lance.yang@linux.dev, liam@infradead.org, mhocko@suse.com, ryan.roberts@arm.com, shuah@kernel.org, surenb@google.com, vbabka@kernel.org, agordeev@linux.ibm.com, jgg@ziepe.ca, leon@kernel.org, kernel-team@meta.com, "Kiryl Shutsemau (Meta)" Subject: [PATCH v5 19/19] selftests/mm: zap whole PTE tables in the khugepaged race harness Date: Tue, 8 Sep 2026 13:51:05 +0100 Message-ID: <20260908125105.1510704-20-kirill@shutemov.name> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260908125105.1510704-1-kirill@shutemov.name> References: <20260908125105.1510704-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 1f4aa23834db..c3478b5123e2 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