All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Usama Arif" <usama.arif@linux.dev>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	david@kernel.org, chrisl@kernel.org, kasong@tencent.com,
	ljs@kernel.org, ziy@nvidia.com, linux-mm@kvack.org
Cc: chenhuacai@kernel.org, ying.huang@linux.alibaba.com,
	"Baoquan He" <baoquan.he@linux.dev>,
	willy@infradead.org, youngjun.park@lge.com, hannes@cmpxchg.org,
	riel@surriel.com, shakeel.butt@linux.dev, alex@ghiti.fr,
	kas@kernel.org, baohua@kernel.org, dev.jain@arm.com,
	baolin.wang@linux.alibaba.com,
	"Nico Pache" <nico.pache@linux.dev>,
	"Liam R. Howlett" <liam@infradead.org>,
	ryan.roberts@arm.com, "Vlastimil Babka" <vbabka@kernel.org>,
	lance.yang@linux.dev, nphamcs@gmail.com,
	shikemeng@huaweicloud.com, yosry@kernel.org, qi.zheng@linux.dev,
	luizcap@redhat.com, kernel-team@meta.com
Subject: Re: [PATCH v9 32/32] selftests/mm: add PMD swap entry tests
Date: Fri, 06 Nov 2026 18:43:15 +0000	[thread overview]
Message-ID: <sashiko-outbox-202087@kernel.org> (raw)
In-Reply-To: <20261105183940.2236717-33-usama.arif@linux.dev>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] selftests/mm: check_huge_anon() in swapoff test passes on
  swapped PMDs
- [Medium] selftests/mm: uffdio_move test fails UFFDIO_API when RWP is
  unsupported
--

commit 19ef341b36a063e4b63f435180149741746c0988
Author: Usama Arif <usama.arif@linux.dev>

selftests/mm: add PMD swap entry tests

This commit adds a selftest suite for PMD-level swap entries covering basic
fault-in, swapin_sync, fork, COW, mprotect, munmap, userfaultfd move/RWP,
mremap, pagemap, mincore, madvise, and swapoff operations. It also adds a
read_vmstat() helper to vm_util.c and wires the test into run_vmtests.sh.

> diff --git a/tools/testing/selftests/mm/pmd_swap.c b/tools/testing/selftests/mm/pmd_swap.c
> new file mode 100644
> index 0000000000000..8af94bd7e105d
> --- /dev/null
> +++ b/tools/testing/selftests/mm/pmd_swap.c
> @@ -0,0 +1,989 @@

[ ... ]

> +TEST_F(pmd_swap, uffdio_move)
> +{
> +	struct uffdio_register reg = {};
> +	struct uffdio_move move = {};
> +	struct uffdio_api api = {};
> +	bool rwp;
> +
> +	self->aux = mmap_pmd_aligned(self->pmd_size);
> +	if (self->aux == MAP_FAILED)
> +		SKIP(return, "Could not mmap aligned dst\n");
> +	ASSERT_EQ(madvise(self->aux, self->pmd_size, MADV_HUGEPAGE), 0);
> +
> +	self->uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
> +	if (self->uffd < 0)
> +		SKIP(return, "userfaultfd unavailable\n");
> +
> +	api.api = UFFD_API;
> +	api.features = UFFD_FEATURE_MOVE | UFFD_FEATURE_RWP;
> +	if (ioctl(self->uffd, UFFDIO_API, &api) ||
> +	    !(api.features & UFFD_FEATURE_MOVE))
> +		SKIP(return, "UFFD_FEATURE_MOVE unsupported\n");
> +	rwp = api.features & UFFD_FEATURE_RWP;

[Severity: Medium]
In TEST_F(pmd_swap, uffdio_move) in tools/testing/selftests/mm/pmd_swap.c,
will requesting UFFD_FEATURE_MOVE | UFFD_FEATURE_RWP in a single UFFDIO_API
ioctl cause the test to skip whenever UFFD_FEATURE_RWP is unsupported?

In mm/userfaultfd.c, userfaultfd_api() rejects the call with -EINVAL if any
requested feature bit is unavailable rather than masking off unsupported bits:

mm/userfaultfd.c:userfaultfd_api() {
	...
	uffdio_api.features = uffd_api_available_features(ctx, features);
	ret = -EINVAL;
	if (features & ~uffdio_api.features)
		goto err_out;
	...
}

On architectures or configurations where UFFD_FEATURE_MOVE is supported but
UFFD_FEATURE_RWP is cleared by uffd_api_available_features() (because
VM_UFFD_RWP == VM_NONE || !pgtable_supports_uffd()), ioctl(self->uffd,
UFFDIO_API, &api) fails with -EINVAL, skipping the test with "UFFD_FEATURE_MOVE
unsupported" and leaving the !rwp fallback path unreachable.

[ ... ]

> +TEST_F(pmd_swap, swapoff)
> +{
> +	int ret, err;
> +
> +	self->swap_dev = getenv("PMD_SWAP_DEVICE");
> +	if (!self->swap_dev)
> +		SKIP(return, "PMD_SWAP_DEVICE env var not set\n");
> +	/*
> +	 * Otherwise a higher-priority device may have taken the PMD swap
> +	 * entry and swapoff() would operate on the wrong backend.
> +	 */
> +	if (!swap_device_is_only_active(self->swap_dev, &self->swap_prio))
> +		SKIP(return, "PMD_SWAP_DEVICE must be the only active swap device\n");
> +
> +	self->uffd = register_rwp(self->mem, self->pmd_size, true);
> +
> +	ret = swapoff(self->swap_dev);
> +	err = errno;
> +	if (!ret)
> +		self->swap_disabled = true;
> +	ASSERT_EQ(ret, 0) {
> +		TH_LOG("swapoff(%s) failed: %s", self->swap_dev, strerror(err));
> +	}
> +
> +	/*
> +	 * Check residency before touching the memory. If we read
> +	 * first, a bug that left a PMD swap entry in place after swapoff
> +	 * would silently trigger do_huge_pmd_swap_page() and reinstall a
> +	 * PMD mapping, masking the regression.
> +	 */
> +	if (self->zswap_enabled)
> +		ksft_print_msg("zswap enabled: PMD restoration not checked\n");
> +	else
> +		ASSERT_TRUE(check_huge_anon(self->mem, self->pmd_size, 1,
> +					    self->pmd_size));

[Severity: Medium]
Does check_huge_anon() in TEST_F(pmd_swap, swapoff) in
tools/testing/selftests/mm/pmd_swap.c actually verify that the PMD swap entry
is no longer swapped out before the test reads self->mem?

In tools/testing/selftests/mm/vm_util.c, check_huge_anon() calls
__check_huge() followed by __check_type():

tools/testing/selftests/mm/vm_util.c:__check_huge() {
	...
	for (; start < end; start += hpage_size) {
		categories = pagemap_scan_get_categories(pagemap_fd, start);
		if (categories & PAGE_IS_HUGE)
			nr_pmd_mappings++;
	}
	...
}

tools/testing/selftests/mm/vm_util.c:__check_type() {
	...
	for (; start < end; start += page_size) {
		categories = pagemap_scan_get_categories(pagemap_fd, start);
		if ((categories & PAGE_IS_PRESENT) != PAGE_IS_PRESENT)
			continue;

		if ((type == CHECK_TYPE_FILE) != !!(categories & PAGE_IS_FILE))
			goto out;
	}

	ret = true;
	...
}

In fs/proc/task_mmu.c, pagemap_scan_thp_entry()->pagemap_thp_category() sets
PAGE_IS_HUGE | PAGE_IS_SWAPPED on a non-present PMD swap entry. Because
__check_huge() only tests PAGE_IS_HUGE without PAGE_IS_PRESENT, and
__check_type() skips non-present entries via continue, check_huge_anon()
returns true even if swapoff() left the non-present PMD swap entry in place.

Additionally, when self->zswap_enabled is true, no residency or swap check is
performed at all before expect_rwp_fault() and verify_pattern() read
self->mem. Would checking that none of the pages in the range remain swapped
in pagemap (or checking residency directly) before reading self->mem catch a
left-behind swap entry in both cases?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261105183940.2236717-1-usama.arif@linux.dev?part=32


      reply	other threads:[~2026-11-06 18:43 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05 18:38 [PATCH v9 00/32] mm: PMD-level swap entries for anonymous THPs Usama Arif
2026-11-05 18:38 ` [PATCH v9 01/32] mm: rename pmd_to_softleaf_folio() to pmd_softleaf_to_folio() Usama Arif
2026-11-05 18:38 ` [PATCH v9 02/32] arm64: mm: add PMD swap-exclusive helpers Usama Arif
2026-11-05 18:38 ` [PATCH v9 03/32] loongarch: " Usama Arif
2026-11-05 18:38 ` [PATCH v9 04/32] powerpc: " Usama Arif
2026-11-05 18:38 ` [PATCH v9 05/32] riscv: " Usama Arif
2026-11-05 18:38   ` Usama Arif
2026-11-05 18:38 ` [PATCH v9 06/32] s390: " Usama Arif
2026-11-06 18:43   ` sashiko-bot
2026-11-10 17:17   ` Gerald Schaefer
2026-11-05 18:38 ` [PATCH v9 07/32] x86: " Usama Arif
2026-11-05 18:38 ` [PATCH v9 08/32] mm: recognize PMD swap entries in the softleaf layer Usama Arif
2026-11-05 18:38 ` [PATCH v9 09/32] mm/debug_vm_pgtable: test PMD swap-exclusive helpers Usama Arif
2026-11-05 18:38 ` [PATCH v9 10/32] mm/migrate_device: avoid leaking folio references during THP splitting Usama Arif
2026-11-05 18:38 ` [PATCH v9 11/32] mm: make PMD migration-entry splitting explicit Usama Arif
2026-11-05 18:38 ` [PATCH v9 12/32] mm: split PMD swap entries into PTE swap entries Usama Arif
2026-11-05 18:38 ` [PATCH v9 13/32] mm/swap: allow duplicating a range of " Usama Arif
2026-11-05 18:38 ` [PATCH v9 14/32] mm: handle PMD swap entries in fork path Usama Arif
2026-11-05 18:38 ` [PATCH v9 15/32] mm: swap: share swap-cache allocation error cleanup Usama Arif
2026-11-06 21:10   ` Yosry Ahmed
2026-11-06 21:39   ` Nhat Pham
2026-11-05 18:39 ` [PATCH v9 16/32] mm: zswap: reject high-order swap cache allocations backed by zswap Usama Arif
2026-11-06 16:26   ` Nhat Pham
2026-11-06 21:16   ` Yosry Ahmed
2026-11-05 18:39 ` [PATCH v9 17/32] mm: swap in PMD swap entries as whole THPs during swapoff Usama Arif
2026-11-06 18:43   ` sashiko-bot
2026-11-05 18:39 ` [PATCH v9 18/32] fs/proc: account PMD swap entries in smaps Usama Arif
2026-11-05 18:39 ` [PATCH v9 19/32] mm: handle soft-dirty and uffd-wp on PMD swap entries Usama Arif
2026-11-05 18:39 ` [PATCH v9 20/32] mm/hmm: fault PMD swap entries on demand Usama Arif
2026-11-05 18:39 ` [PATCH v9 21/32] mm: free PMD swap entries in zap_huge_pmd() Usama Arif
2026-11-05 18:39 ` [PATCH v9 22/32] mm/madvise: free PMD swap entries with MADV_FREE Usama Arif
2026-11-05 18:39 ` [PATCH v9 23/32] mm/madvise: skip PMD swap entries for MADV_COLD and MADV_PAGEOUT Usama Arif
2026-11-05 18:39 ` [PATCH v9 24/32] mm/madvise: keep PMD swap entries whole for MADV_GUARD_INSTALL/REMOVE Usama Arif
2026-11-05 18:39 ` [PATCH v9 25/32] mm/mincore: report PMD swap-cache residency Usama Arif
2026-11-05 18:39 ` [PATCH v9 26/32] mm/khugepaged: treat PMD swap entries as mapped THPs Usama Arif
2026-11-05 18:39 ` [PATCH v9 27/32] mm: handle PMD swap entries in MADV_WILLNEED Usama Arif
2026-11-06 18:43   ` sashiko-bot
2026-11-05 18:39 ` [PATCH v9 28/32] mm: handle PMD swap entries in UFFDIO_MOVE Usama Arif
2026-11-06 18:43   ` sashiko-bot
2026-11-05 18:39 ` [PATCH v9 29/32] mm: don't PTE-batch a swap-in over a hardware-poisoned subpage Usama Arif
2026-11-05 18:39 ` [PATCH v9 30/32] mm: handle PMD swap entry faults on swap-in Usama Arif
2026-11-06 18:43   ` sashiko-bot
2026-11-05 18:39 ` [PATCH v9 31/32] mm: install PMD swap entries on swap-out Usama Arif
2026-11-06 18:43   ` sashiko-bot
2026-11-05 18:39 ` [PATCH v9 32/32] selftests/mm: add PMD swap entry tests Usama Arif
2026-11-06 18:43   ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-202087@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=alex@ghiti.fr \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=baoquan.he@linux.dev \
    --cc=chenhuacai@kernel.org \
    --cc=chrisl@kernel.org \
    --cc=david@kernel.org \
    --cc=dev.jain@arm.com \
    --cc=hannes@cmpxchg.org \
    --cc=kas@kernel.org \
    --cc=kasong@tencent.com \
    --cc=kernel-team@meta.com \
    --cc=lance.yang@linux.dev \
    --cc=liam@infradead.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=luizcap@redhat.com \
    --cc=nico.pache@linux.dev \
    --cc=nphamcs@gmail.com \
    --cc=qi.zheng@linux.dev \
    --cc=riel@surriel.com \
    --cc=ryan.roberts@arm.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=shikemeng@huaweicloud.com \
    --cc=usama.arif@linux.dev \
    --cc=vbabka@kernel.org \
    --cc=willy@infradead.org \
    --cc=ying.huang@linux.alibaba.com \
    --cc=yosry@kernel.org \
    --cc=youngjun.park@lge.com \
    --cc=ziy@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.