[PATCH v3 0/4] Make MIGRATE_ISOLATE a standalone bit

Zi Yan
2025-05-07T21:11:22Z

Hi Johannes,

I incorporated all your feedback on v2 (see Changelog below), except the
"decoupling enum migratetype from the pageblock bits" one[1], since all
5 migratetypes (not MIGRATE_ISOLATE) are just values and
"#define PB_migratetype_bits MIGRATE_TYPE_BITS" would take 5 bits
for migratetypes, which only requires 3 bits. Let me know if I
misunderstand your suggestion. Thanks.

Hi all,

This patchset moves MIGRATE_ISOLATE to a standalone bit to avoid
being overwritten during pageblock isolation process. Currently,
MIGRATE_ISOLATE is part of enum migratetype (in include/linux/mmzone.h),
thus, setting a pageblock to MIGRATE_ISOLATE overwrites its original
migratetype. This causes pageblock migratetype loss during
alloc_contig_range() and memory offline, especially when the process
fails due to a failed pageblock isolation and the code tries to undo the
finished pageblock isolations.

It is on top of mm-everything-2025-05-07-03-02.

In terms of performance for changing pageblock types, no performance
change is observed:

1. I used perf to collect stats of offlining and onlining all memory of a
40GB VM 10 times and see that get_pfnblock_flags_mask() and
set_pfnblock_flags_mask() take about 0.12% and 0.02% of the whole process
respectively with and without this patchset across 3 runs.

2. I used perf to collect stats of dd from /dev/random to a 40GB tmpfs file
and find get_pfnblock_flags_mask() takes about 0.05% of the process with and
without this patchset across 3 runs.

Changelog
===
From v2[2]:
1. Moved MIGRATETYPE_NO_ISO_MASK to Patch 2, where it is used.
2. Removed spurious changes in Patch 1.
3. Refactored code so that migratetype mask is passed properly for all
callers to {get,set}_pfnblock_flags_mask().
4. Added toggle_pageblock_isolate() for setting and clearing
MIGRATE_ISOLATE.
5. Changed get_pageblock_migratetype() when CONFIG_MEMORY_ISOLATION to
handle MIGRATE_ISOLATE case. It acts like a parsing layer for
get_pfnblock_flags_mask().

Design
===

Pageblock flags are read in words to achieve good performance and existing
pageblock flags take 4 bits per pageblock. To avoid a substantial change
to the pageblock flag code, pageblock flag bits are expanded to use 8
and MIGRATE_ISOLATE is moved to use the last bit (bit 7).

It might look like the pageblock flags have doubled the overhead, but in
reality, the overhead is only 1 byte per 2MB/4MB (based on pageblock config),
or 0.0000476 %.

Any comment and/or suggestion is welcome. Thanks.

[1] https://lore.kernel.org/linux-mm/20250214172032.GA241035@cmpxchg.org/
[2] https://lore.kernel.org/linux-mm/20250214154215.717537-1-ziy@nvidia.com/

Zi Yan (4):
mm/page_isolation: make page isolation a standalone bit.
mm/page_isolation: remove migratetype from
move_freepages_block_isolate()
mm/page_isolation: remove migratetype from undo_isolate_page_range()
mm/page_isolation: remove migratetype parameter from more functions.

drivers/virtio/virtio_mem.c | 3 +-
include/linux/gfp.h | 6 +-
include/linux/mmzone.h | 19 ++++--
include/linux/page-isolation.h | 24 ++++---
include/linux/pageblock-flags.h | 33 ++++++++-
include/trace/events/kmem.h | 14 ++--
mm/cma.c | 2 +-
mm/memory_hotplug.c | 5 +-
mm/page_alloc.c | 114 +++++++++++++++++++++++++-------
mm/page_isolation.c | 66 ++++++++----------
10 files changed, 197 insertions(+), 89 deletions(-)

--
2.47.2