[Devel] [PATCH hci-8.1 2/2] selftests/ve: check memory.numa_migrate keeps the folio order
no-reply at sashiko.virtuozzo.com
no-reply at sashiko.virtuozzo.com
Wed Oct 28 15:28:12 MSK 2026
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Medium] selftests/ve: numa_migrate test never checks that large folios were created
- [Medium] selftests/ve: strict numa_migrate pass threshold can fail on a correct kernel and leave the XFS mount behind
- [Medium] selftests/ve: mkfs.xfs skip probe checks fixed paths, not PATH
- [Low] selftests/ve: ve_numa_migrate_test binary missing from .gitignore
--
commit 53864b9544be735f4056fc53973030b5631878a2
Author: Konstantin Khorenko <khorenko at virtuozzo.com>
selftests/ve: check memory.numa_migrate keeps the folio order
This adds a selftest that writes a file on an XFS loop image from a
cgroup bound to one NUMA node, migrates the cgroup to a second node
with memory.numa_migrate, and reads the file back against the written
pattern. It is meant to catch memcg_numa_migrate_new_folio() allocating
an oversized destination for a large page cache folio. It skips when
root, two NUMA nodes, cgroup2 controllers or mkfs.xfs are missing.
Link: https://virtuozzo.atlassian.net/browse/VSTOR-151607
> diff --git a/tools/testing/selftests/ve/Makefile b/tools/testing/selftests/ve/Makefile
> index 51f9316beb99..e96320a18384 100644
> --- a/tools/testing/selftests/ve/Makefile
> +++ b/tools/testing/selftests/ve/Makefile
> @@ -6,6 +6,7 @@ TEST_GEN_PROGS += ve_ns_owner_test
> TEST_GEN_PROGS += ve_perms_test
> TEST_GEN_PROGS += ve_mount_accounting_test
> TEST_GEN_PROGS += ve_vtty_stress
> +TEST_GEN_PROGS += ve_numa_migrate_test
[Severity: Low]
Should tools/testing/selftests/ve/.gitignore get a matching entry?
The ignore list currently ends with ve_vtty_stress and has no entry for
ve_numa_migrate_test, which this line now builds. After a build the
binary will show up as untracked in git status, and the patch does not
touch .gitignore.
[ ... ]
> diff --git a/tools/testing/selftests/ve/ve_numa_migrate_test.c b/tools/testing/selftests/ve/ve_numa_migrate_test.c
> new file mode 100644
> index 000000000000..5fbf4af49f7f
> --- /dev/null
> +++ b/tools/testing/selftests/ve/ve_numa_migrate_test.c
[ ... ]
> + * Write a file on an XFS image (XFS allocates large folios for 64K writes)
> + * from a cgroup bound to one NUMA node, migrate the cgroup to another node
> + * and check that the data reads back intact.
[Severity: Medium]
Is it safe to assume large folios were actually created here?
Nothing in the test verifies it. mapping_max_folio_order() returns 0
when CONFIG_TRANSPARENT_HUGEPAGE is not set. Large folio allocation can
also fall back to order-0 under fragmentation or memory pressure.
In either case every folio is order-0, and the only precondition check
(ASSERT_GE on the node_to file bytes) is satisfied by order-0 folios as
well. The memcmp readback then succeeds because nothing was mis-migrated,
and the test reports PASS without covering the folio_test_large() branch
in memcg_numa_migrate_new_folio().
Could the test check for large folios, for example through
/proc/kpageflags or the THP counters, and SKIP when none are seen?
[ ... ]
> + if (access("/usr/sbin/mkfs.xfs", X_OK) && access("/sbin/mkfs.xfs", X_OK))
> + SKIP(return, "needs mkfs.xfs");
[Severity: Medium]
Can this probe cause a false skip?
It only looks in /usr/sbin and /sbin, while prepare() runs the tool
through run_cmd() and system(), which resolves it via PATH:
if (run_cmd("mkfs.xfs -q -f %s", self->img)) {
*why = "mkfs.xfs failed";
On a host where mkfs.xfs is in /usr/bin or /usr/local/sbin, the test
skips with "needs mkfs.xfs" before prepare() would have found the tool.
A mkfs failure in prepare() already turns into a SKIP, so would it be
simpler to drop this pre-probe?
[ ... ]
> + /* From here on a failure means eviction would crash the kernel. */
> + self->leave_mounted = 1;
> + snprintf(list, sizeof(list), "%d,%d", self->node_from, self->node_to);
> + ASSERT_EQ(write_file_at(self->cg_fd, "cpuset.mems", list), 0);
> + ASSERT_EQ(write_u64_at(self->cg_fd, "memory.numa_migrate",
> + self->node_to), 0);
> +
> + ASSERT_EQ(file_bytes_on_node(self->cg_fd, self->node_to,
> + &on_to_after), 0);
> + TH_LOG("file bytes on node %d: %llu -> %llu", self->node_to,
> + on_to_before, on_to_after);
> + ASSERT_GE(on_to_after, on_to_before + FILE_SIZE);
[Severity: Medium]
Can this strict threshold fail on a correct kernel and then leave the XFS
mount behind?
The assertion requires every byte of the 4MB file to have moved to
node_to. The memory.numa_migrate write does not guarantee that:
mm/memcontrol.c:__memcg_numa_migrate_pages() {
ret = migrate_pages(&pages, memcg_numa_migrate_new_folio,
NULL, (unsigned long)&ms, MIGRATE_ASYNC,
MR_SYSCALL, NULL);
putback_movable_pages(&pages);
if (ret < 0)
return ret;
...
}
Only a negative return is propagated. A positive count of folios that
failed to migrate is dropped, and __memcg_numa_migrate_write() returns
"ret ?: nbytes", so the ASSERT_EQ on the write passes on a partial
migration.
Large destination folios are allocated in memcg_numa_migrate_new_folio()
with:
if (folio_test_large(old_folio)) {
gfp_mask = GFP_TRANSHUGE_LIGHT | __GFP_THISNODE;
order = folio_order(old_folio);
}
That has no direct reclaim or compaction and no node fallback, so it can
fail on a fragmented node_to and leave the folio on node_from.
memcg_numa_isolate_pages() also skips folios that are not on the LRU:
/* Only take pages on LRU: a check now makes later tests safe */
if (!folio_test_lru(folio))
goto isolate_fail;
Folios still sitting in per-CPU LRU batches are skipped without a drain.
Any of these makes the ASSERT_GE fail without a kernel bug. Because
leave_mounted was set just above, FIXTURE_TEARDOWN then skips the unmount
and the loop mount and image stay on the host.
Would a tolerant check, such as requiring a meaningful fraction of the
file to have moved, work better? Could leave_mounted also be set only
after the data-integrity check has shown a problem, rather than before
the migration?
[ ... ]
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261028-b4-prep-khorenko-vstor-151607-numa-migrate-order-v1-0-268336526677@virtuozzo.com?part=2
More information about the Devel
mailing list