From nobody Sat Jun 13 14:05:19 2026 Received: from mail-pg1-f196.google.com (mail-pg1-f196.google.com [209.85.215.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DAAFC31E841 for ; Thu, 7 May 2026 07:06:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778137572; cv=none; b=qr9SQ3vhVr/rhQFjqxO5VhJEfUt8qkaXw9QuOFMVDwo2ECbqhrC9t+FW9Wfd58+DKdY2I/tiOTQbf8T+K+eBKplV9fPbPbO0eOgSwAOmTjE4P66BuyiQ6ZXWzroIiV6a5MQWZ8bsMiQT0WurPEfeD5pSgbcB6n25DRzctpW4oKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778137572; c=relaxed/simple; bh=iSva+MRtXTCg/dBOqxHocreKEH5HxjlggZ+FzIndonQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f70N91kQG0xmqf4RnYmt7D+J7wYWmXvt6eJlrKyncgXkkq+ymnR8gxw/hQk1NhNqvJZ2lheTcIpNLrpjiLlk+ejbBTSRAdHhow0K4V7qw3N/hvAFNdQnbL22TsZASbAQICL85Sc5kQDgcnkCvHXggy4k0pCqirRhtuCA0OT41/Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ik6PFhb4; arc=none smtp.client-ip=209.85.215.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ik6PFhb4" Received: by mail-pg1-f196.google.com with SMTP id 41be03b00d2f7-c7ffe8eeaf2so208527a12.0 for ; Thu, 07 May 2026 00:06:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778137570; x=1778742370; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BO67I+tc6fpB9njFQMIo7PJhrH5oEFtHvkZxfrMXbW4=; b=ik6PFhb44z0ncgr7J6LqQ0vVQ3MvMTOeYC9Ma1wFtakWZ8lyCN4CElFj+uJQ8ycDy0 TBXQWrzb85TjCwOSGXzcDpuIU3tGcnuVFfplc+UqwvsmVkJqfmOWCcen4ZwmX1TOIxr+ 3d7doXPYwlk7L2rCn9CgzlxqCWpFSAJymI1L62oOTOpXCNGjD9gps0HTFCVssdf3czvQ mNL8C7LkV2rp8bhG25aRiOjwkmRAQglTXlqVO5kEUerm3epfN7H9f3OQ00l5SERWUlEY htf8dCfhxlY33awhwRmimoHVaOPsxGYEG3tb3apqp6G3p7Twm5G6LartWWUZg3CASVjT uYcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778137570; x=1778742370; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=BO67I+tc6fpB9njFQMIo7PJhrH5oEFtHvkZxfrMXbW4=; b=JVgNY26tqnnAqCM4NQuVodF7+zYDNRDabg7stapDsW24mVEuTO/RNspRkoSB+kPYYq in3HdtBCjlmvr5lz4W6vmbqJsdHIMB5/IEnp8r65y6ddlJuK7nUT1rNBAyDWkPACr49+ wMvb0LXqY9bx+MG8c4YatiJGMjyaFNYBzCJkpB4aZEcvLXm9VmcOMdbUi7KLUozVdi2+ kf9MMw3wJJJglVKz6yttFnXr4sIdx2yOZ0OC3ut7hc3Sp1ZSCT6Kb/wCFNpoITSpqfiY NiJ1F8rpmDy9TQWFQaHWjnYtvKHlao2iVZY4BGVHFlq6s7Pnu5lIdQECa2ediNXmU1D9 GeTQ== X-Gm-Message-State: AOJu0YxnCFxLU8eEgyNvpH5oDq2XHDvHqAd1BgtPW0mEuGJ1jH0wVkVO zKL8QzOr/7UDgz3wlhDGxkH4+hBQlkJ/OKoDTmocx1aU1A9mOaLIHRyLYX/Q/yWvgxM= X-Gm-Gg: AeBDieug2l2t/eqzeLz192R7m74Nbd7UI7KskL0LQn05YRmd+IuHLamlv68ilvCF2Hq ju2IgRPKkz5qwUHuN6/foeFpHmEW/78+Czojv3Zeg7O7GjJdWa3GI06xqJW1ED2Hx86j5VSAeox CxHEFyCv8JKWoLlo7rfGpGO6ooEI0l8IzSPWykgjNhGThE7QJM5l7ii47Bjokx917jKxPKqdrMx OPlPSVEOdMlN3RsB5PhnyBjx25cmyD5j+pHkHwa7j2483HEd6wltkj1lfk8lN92G70qNUjNge5t 1dE7AqFgjnCpjkN0yQLFg3u1XZcm4mUIhJorBq5i4Ocic9PaWnpD48aGvl3Wh2QnkM+Ef0gEFih 96iSjDtg1IwF0AUxGRqtx4E2ltpUP/oMouh8BZhyBlKmR096e+XLxd9R9youothVofmnOSfEYRS 1a1a1vpDeUE1pIH7e6YIO5w/zFrPModBf4bGJ1K6d7mfOK/DFeW3W/95x/rKEAWju9uRCgBA== X-Received: by 2002:a05:6a21:33a7:b0:39b:edcd:d92f with SMTP id adf61e73a8af0-3aa5a9056dfmr7399916637.11.1778137570265; Thu, 07 May 2026 00:06:10 -0700 (PDT) Received: from intel.company.local ([210.184.73.204]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c825379099bsm1200164a12.14.2026.05.07.00.06.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 May 2026 00:06:09 -0700 (PDT) From: Chen Wandun X-Google-Original-From: Chen Wandun To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, shuah@kernel.org, zokeefe@google.com Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org Subject: [PATCH 1/2] mm/khugepaged: fix spurious -EINVAL from sub-PMD MADV_COLLAPSE range Date: Thu, 7 May 2026 15:05:57 +0800 Message-ID: <20260507070558.3064142-2-chenwandun@lixiang.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260507070558.3064142-1-chenwandun@lixiang.com> References: <20260507070558.3064142-1-chenwandun@lixiang.com> 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" madvise_collapse() computes the THP-aligned window: hstart =3D (start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK /* round up */ hend =3D end & HPAGE_PMD_MASK /* round down */ Previously this was done after kmalloc_obj(), so problem arose when the range contained no complete PMD-aligned window (hstart >=3D hend). When hstart > hend, (hend - hstart) wraps unsigned to a huge value, the final comparison fails and -EINVAL is returned instead of 0. Consider two single-page calls on a 2 MiB-aligned address: /* hstart =3D=3D hend =3D=3D aligned -> 0 =3D=3D 0 -> returns 0 */ madvise(aligned, PAGE_SIZE, MADV_COLLAPSE); /* hstart =3D aligned + 2MiB, hend =3D aligned * (hend - hstart) wraps unsigned -> returns -EINVAL */ madvise(aligned + PAGE_SIZE, PAGE_SIZE, MADV_COLLAPSE); Both calls cover less than one THP and collapse nothing; both should return 0. In addition, kmalloc_obj(), mmgrab() and lru_add_drain_all() were all called before discovering there was nothing to do, only for the code to kfree() and return immediately after. Fix both by computing hstart/hend after thp_vma_allowable_order() but before kmalloc_obj(), and returning 0 early when hstart >=3D hend. Fixes: 7d8faaf15545 ("mm/madvise: introduce MADV_COLLAPSE sync hugepage col= lapse") Signed-off-by: Chen Wandun --- mm/khugepaged.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mm/khugepaged.c b/mm/khugepaged.c index b8452dbdb043..92473d93e837 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -2836,6 +2836,12 @@ int madvise_collapse(struct vm_area_struct *vma, uns= igned long start, if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_FORCED_COLLAPSE, PMD= _ORDER)) return -EINVAL; =20 + hstart =3D (start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK; + hend =3D end & HPAGE_PMD_MASK; + + if (hstart >=3D hend) + return 0; + cc =3D kmalloc_obj(*cc); if (!cc) return -ENOMEM; @@ -2845,9 +2851,6 @@ int madvise_collapse(struct vm_area_struct *vma, unsi= gned long start, mmgrab(mm); lru_add_drain_all(); =20 - hstart =3D (start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK; - hend =3D end & HPAGE_PMD_MASK; - for (addr =3D hstart; addr < hend; addr +=3D HPAGE_PMD_SIZE) { enum scan_result result =3D SCAN_FAIL; =20 --=20 2.43.0 From nobody Sat Jun 13 14:05:19 2026 Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37E1C31E841 for ; Thu, 7 May 2026 07:06:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.194 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778137576; cv=none; b=hrSc4JBTpGa8YVdTuXRqaPo2j6ts8H/6tTPBJ8seTnxMqHIa5ISDeKlFAGSRHN1yX4NKnrhFtjOYG6bqfhq8IAgJHZMPHvcxXgpQUg30pNf4AOKDmXItGXrVdA4orXCqEB4I1vWiTE/KJSkOLr3vJPV3HPxnXLWAam15zjcokHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778137576; c=relaxed/simple; bh=qPX7yyUZJCtm7bSS8AuOTkkokV46Y9uiDvYp6mJERV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kwJVgin6DnTP7T5B9RvWZNslm+y29DArE8/TDtHQ2W0mJ5T771xha+He978yknVanZXn7Y7qNpXxZ7Ev+hKw6J8IDq+R1G2uPMqRSNYx/LUYUGIUbWemRMD+y2xzL91rfJ3Kdrv9cK1syg5m4I//ITzVARXYfdhO/cMuYMTw4QE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=EkNSey+A; arc=none smtp.client-ip=209.85.215.194 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="EkNSey+A" Received: by mail-pg1-f194.google.com with SMTP id 41be03b00d2f7-c8021c8c42fso149361a12.3 for ; Thu, 07 May 2026 00:06:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778137575; x=1778742375; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Dgv2EkYfGFbvZ1PGx8KpTzNURorGBePyogLOLYsqDZY=; b=EkNSey+ADPCnfBAxhH93pgW3lEdItSu/TISol3OEa94kLQHBQ4uqk7FwwodVovPWdE 8HUcpe9okV6+myWxJJS2kZ7uO8xmbSdkCZbmo9RkAI4E4Gv4z5/5BeGXc3xmRF9Oeo6W NP7BIZDl3vdApJ6kxAebTu55coSisTiBNUNm/cxjTFhTybz+3c4JGBCcqQEgiPG/0JEU BZNHHVKp9icvix5zakAVvj7WT5j2Fj8hfRnKqituxCmlztvB1P3dBgLlKLEcJPDIByXN HghxodNGKe506wS2xXD1nEtnJGsdWkKVBQCOikL4di1xO7s1YlLfLeXJWOY5iEaosl8f KbOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778137575; x=1778742375; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Dgv2EkYfGFbvZ1PGx8KpTzNURorGBePyogLOLYsqDZY=; b=ZrUYoy5u2unTrlrCsBgoB5O8+epeV5bFXKI9I27HrLnpS7gb04FfortlhiSN+Y+Gx8 wWYCH9ESlrnXz4FTjhX/R6nMzc5WVW5gF0uBafwJxatJ6vY3Q7hxRA5YgaLS6qE0lDPd dAi90xsf+almbpTtpI1PQrGB734ZXYaBZAVZ+hwxeZRXQk+25C9ylB7DF0MNz60qRPy6 TYdMFqIIRgiWO0s5vjEv90EbjuQIpd9WDMEAsh+v0H7XJV0Hvk73W/mg66BEurSn5Ipi zzNR3k7hHbD85XzmMikJ3bQcXOwKBxZLZNkPSgRzhlrMtulHi/7tiEeh72ovlcbOrW84 P8Uw== X-Gm-Message-State: AOJu0YyYNJmyR+1vYGr9WL0H6QLgpNUHI+1yU1SHCJpCIIeiJpZRvxR5 iortdQ411hAipCHyLG2SYUcbkPam7vtdJEeMSGN7+ibOeIVqDOt9vwPe X-Gm-Gg: AeBDieuvfJ8RmM6xL1xauUsXhEc1MQTXblsfg8NC2U4DgAx0G/hP1C8QZIAmd8vbU5h DPhyj3bzqsyRyav4f5T/I/e1LM0kk0+wfpZMg1Xw+Y8QJQuvwCyCiP6mGqtNkUDbM9PE0ZS6gNB 9uNvpO9nDpPsWixDdCa3JejSENa67nHJDu3ZXKLFuAQiKvg5oKZmfB6IfxsSeWvvdypxhYx63Ke FaMHSftGxFZBKRF0XD8pOmcvrUg6Os54qoTWt8EKuvcED/zXQRnMwvB39vNuETszveqhP77tkrB /4L04UiBV8dg9rhIZLQx8bPcD79OdGUPpi6sLpXlJRm1vMkEsd6Z+YCM44ai8jdA8WkIATxWITY 9XiZ2dCI4Sn0+CqrY6ZBIoPjs/Oy1Cjiz+pKirwaUdf2dRHYzXN6aDnxb9PMBV6oM86Dr/rKTTP YSJF1JipL2cdxyy6f3NjXTR5sRkVWDas7F8EwjUW/ENxd3BYwX X-Received: by 2002:a05:6a20:258c:b0:3a8:9dd:75c6 with SMTP id adf61e73a8af0-3aa5ac5fca1mr7408664637.51.1778137574565; Thu, 07 May 2026 00:06:14 -0700 (PDT) Received: from intel.company.local ([210.184.73.204]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c825379099bsm1200164a12.14.2026.05.07.00.06.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 May 2026 00:06:14 -0700 (PDT) From: Chen Wandun X-Google-Original-From: Chen Wandun To: akpm@linux-foundation.org, david@kernel.org, ljs@kernel.org, shuah@kernel.org, zokeefe@google.com Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org Subject: [PATCH 2/2] selftests/mm: add MADV_COLLAPSE sub-PMD range tests Date: Thu, 7 May 2026 15:05:58 +0800 Message-ID: <20260507070558.3064142-3-chenwandun@lixiang.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260507070558.3064142-1-chenwandun@lixiang.com> References: <20260507070558.3064142-1-chenwandun@lixiang.com> 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" Add madv_collapse_range to verify the fix for the spurious -EINVAL returned by madvise_collapse() when the madvised range contains no complete PMD-aligned window. madvise_collapse() rounds the caller range inward to PMD boundaries: hstart =3D (start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK // round up hend =3D end & HPAGE_PMD_MASK // round down When hstart >=3D hend there is no PMD window to collapse. Previously the final expression computed (hend - hstart) without guarding against hstart > hend, causing unsigned wrap-around and a spurious -EINVAL. Both tests expect 0: "no PMD window to collapse" is a successful no-op. Test 1 - aligned start (hstart =3D=3D hend): start =3D 2MiB-aligned, len =3D PAGE_SIZE Both hstart and hend round to the same 2MiB boundary. Was already correct; included as a regression reference. Test 2 - unaligned start (hstart > hend): start =3D aligned + PAGE_SIZE, len =3D PAGE_SIZE hstart rounds up past the next 2MiB boundary while hend rounds down below start. (hend - hstart) wrapped unsigned, causing the final comparison to fail and return -EINVAL instead of 0. Signed-off-by: Chen Wandun --- tools/testing/selftests/mm/.gitignore | 1 + tools/testing/selftests/mm/Makefile | 2 + .../selftests/mm/ksft_madv_collapse.sh | 4 + .../selftests/mm/madv_collapse_range.c | 141 ++++++++++++++++++ tools/testing/selftests/mm/run_vmtests.sh | 5 + 5 files changed, 153 insertions(+) create mode 100755 tools/testing/selftests/mm/ksft_madv_collapse.sh create mode 100644 tools/testing/selftests/mm/madv_collapse_range.c diff --git a/tools/testing/selftests/mm/.gitignore b/tools/testing/selftest= s/mm/.gitignore index b0c30c5ee9e3..a24f8c3cf3dc 100644 --- a/tools/testing/selftests/mm/.gitignore +++ b/tools/testing/selftests/mm/.gitignore @@ -28,6 +28,7 @@ protection_keys protection_keys_32 protection_keys_64 madv_populate +madv_collapse_range uffd-stress uffd-unit-tests uffd-wp-mremap diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/= mm/Makefile index cd24596cdd27..758639f8ae8e 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -68,6 +68,7 @@ TEST_GEN_FILES +=3D hugepage-mremap TEST_GEN_FILES +=3D hugepage-shm TEST_GEN_FILES +=3D hugepage-vmemmap TEST_GEN_FILES +=3D khugepaged +TEST_GEN_FILES +=3D madv_collapse_range TEST_GEN_FILES +=3D madv_populate TEST_GEN_FILES +=3D map_fixed_noreplace TEST_GEN_FILES +=3D map_hugetlb @@ -153,6 +154,7 @@ TEST_PROGS +=3D ksft_hugetlb.sh TEST_PROGS +=3D ksft_hugevm.sh TEST_PROGS +=3D ksft_ksm.sh TEST_PROGS +=3D ksft_ksm_numa.sh +TEST_PROGS +=3D ksft_madv_collapse.sh TEST_PROGS +=3D ksft_madv_guard.sh TEST_PROGS +=3D ksft_madv_populate.sh TEST_PROGS +=3D ksft_memfd_secret.sh diff --git a/tools/testing/selftests/mm/ksft_madv_collapse.sh b/tools/testi= ng/selftests/mm/ksft_madv_collapse.sh new file mode 100755 index 000000000000..0d0b0356cbd0 --- /dev/null +++ b/tools/testing/selftests/mm/ksft_madv_collapse.sh @@ -0,0 +1,4 @@ +#!/bin/sh -e +# SPDX-License-Identifier: GPL-2.0 + +./run_vmtests.sh -t madv_collapse diff --git a/tools/testing/selftests/mm/madv_collapse_range.c b/tools/testi= ng/selftests/mm/madv_collapse_range.c new file mode 100644 index 000000000000..11850be80dd8 --- /dev/null +++ b/tools/testing/selftests/mm/madv_collapse_range.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Tests for MADV_COLLAPSE behavior when the madvise range contains no + * complete PMD-aligned window (range smaller than 2 MiB). + * + * madvise_collapse() rounds the caller range inward to PMD boundaries: + * + * hstart =3D (start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK // round up + * hend =3D end & HPAGE_PMD_MASK // round down + * + * When hstart >=3D hend the collapsing loop is not entered. Previously, + * the final return expression computed (hend - hstart) without guarding + * against hstart > hend, causing unsigned wrap-around and a spurious + * -EINVAL. Both tests expect 0: "no PMD window to collapse" is a + * successful no-op, not an error. + * + * Test 1: aligned start (hstart =3D=3D hend): + * start =3D 2MiB-aligned, len =3D PAGE_SIZE + * hstart =3D aligned, hend =3D aligned -> 0 =3D=3D 0 -> 0 (was alr= eady correct) + * + * Test 2: unaligned start (hstart > hend): + * start =3D aligned + PAGE_SIZE, len =3D PAGE_SIZE + * hstart =3D aligned + 2MiB, hend =3D aligned + * (hend - hstart) wraps unsigned -> was -EINVAL, fixed to 0 + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include "kselftest.h" +#include "vm_util.h" + +#ifndef MADV_COLLAPSE +#define MADV_COLLAPSE 25 +#endif + +static unsigned long page_size; +static unsigned long hpage_size; + +/* + * Test 1: 2MiB-aligned start, len =3D PAGE_SIZE. + * hstart =3D=3D hend -> 0 + */ +static void test_subpmd_aligned(char *aligned) +{ + int ret; + + ksft_print_msg("[RUN] sub-PMD: 2MiB-aligned start, len=3DPAGE_SIZE\n"); + ret =3D madvise(aligned, page_size, MADV_COLLAPSE); + ksft_test_result(ret =3D=3D 0, + "sub-PMD aligned start returns 0 (ret=3D%d errno=3D%d)\n", + ret, ret ? errno : 0); +} + +/* + * Test 2: start =3D aligned + PAGE_SIZE, len =3D PAGE_SIZE. + * hstart =3D aligned + hpage_size > hend =3D aligned + * unsigned wrap was -EINVAL; correct answer is 0. + */ +static void test_subpmd_unaligned(char *aligned) +{ + int ret; + + ksft_print_msg("[RUN] sub-PMD: unaligned start (aligned+PAGE), len=3DPAGE= _SIZE\n"); + ksft_print_msg(" hstart=3D%p > hend=3D%p\n", + (void *)(aligned + hpage_size), (void *)aligned); + + ret =3D madvise(aligned + page_size, page_size, MADV_COLLAPSE); + if (ret && errno =3D=3D EINVAL) + ksft_print_msg(" got -EINVAL: unsigned-wrap bug not fixed\n"); + ksft_test_result(ret =3D=3D 0, + "sub-PMD unaligned start returns 0 (ret=3D%d errno=3D%d)\n", + ret, ret ? errno : 0); +} + +int main(void) +{ + char *base, *aligned; + unsigned long map_size; + int probe_ret; + + ksft_print_header(); + ksft_set_plan(2); + + page_size =3D (unsigned long)getpagesize(); + hpage_size =3D (unsigned long)read_pmd_pagesize(); + if (!hpage_size) + ksft_exit_skip("transparent hugepages not available\n"); + + /* + * Probe: map one hpage-sized region, touch all pages, and attempt a + * real collapse to confirm MADV_COLLAPSE is supported. EAGAIN is a + * transient resource failure and still counts as "available". + */ + map_size =3D 2 * hpage_size; + base =3D mmap(NULL, map_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (base =3D=3D MAP_FAILED) + ksft_exit_fail_msg("probe mmap failed: %s\n", strerror(errno)); + + aligned =3D (char *)(((unsigned long)base + hpage_size - 1) + & ~(hpage_size - 1)); + + for (unsigned long i =3D 0; i < hpage_size; i +=3D page_size) + aligned[i] =3D 0; + + probe_ret =3D madvise(aligned, hpage_size, MADV_COLLAPSE); + munmap(base, map_size); + if (probe_ret && errno !=3D EAGAIN) + ksft_exit_skip("MADV_COLLAPSE not available: %s\n", + strerror(errno)); + + /* + * Both sub-PMD tests share a single 2 * hpage mapping so that + * every test range falls within the same VMA. + */ + map_size =3D 2 * hpage_size; + base =3D mmap(NULL, map_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (base =3D=3D MAP_FAILED) + ksft_exit_fail_msg("mmap failed: %s\n", strerror(errno)); + + for (unsigned long i =3D 0; i < map_size; i +=3D page_size) + base[i] =3D 0; + + aligned =3D (char *)(((unsigned long)base + hpage_size - 1) + & ~(hpage_size - 1)); + + test_subpmd_aligned(aligned); + test_subpmd_unaligned(aligned); + + munmap(base, map_size); + + if (ksft_get_fail_cnt()) + ksft_exit_fail_msg("%d out of %d tests failed\n", + ksft_get_fail_cnt(), ksft_test_num()); + ksft_exit_pass(); +} diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/self= tests/mm/run_vmtests.sh index d8468451b3a3..58402f8261e0 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -53,6 +53,8 @@ separated by spaces: test madvise(2) MADV_GUARD_INSTALL and MADV_GUARD_REMOVE options - madv_populate test memadvise(2) MADV_POPULATE_{READ,WRITE} options +- madv_collapse + test madvise(2) MADV_COLLAPSE sub-PMD range handling - memfd_secret test memfd_secret(2) - process_mrelease @@ -422,6 +424,9 @@ CATEGORY=3D"madv_guard" run_test ./guard-regions # MADV_POPULATE_READ and MADV_POPULATE_WRITE tests CATEGORY=3D"madv_populate" run_test ./madv_populate =20 +# MADV_COLLAPSE sub-PMD range tests +CATEGORY=3D"madv_collapse" run_test ./madv_collapse_range + # PROCESS_MADV test CATEGORY=3D"process_madv" run_test ./process_madv =20 --=20 2.43.0