* [PATCH v2] mm: remove PageTransCompound()
@ 2026-06-18 11:35 Kefeng Wang
2026-06-18 12:40 ` David Hildenbrand (Arm)
2026-06-18 15:01 ` xu.xin16
0 siblings, 2 replies; 3+ messages in thread
From: Kefeng Wang @ 2026-06-18 11:35 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-mm, David Hildenbrand, Xu Xin, Chengming Zhou, Kefeng Wang
Remove the last user of PageTransCompound() in ksm and
get rid of PageTransCompound().
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
---
v2:
- use more folio in cmp_and_merge_page(), suggested by David
include/linux/page-flags.h | 14 --------------
mm/ksm.c | 17 +++++++++--------
2 files changed, 9 insertions(+), 22 deletions(-)
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 7223f6f4e2b4..7a863572adce 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -879,20 +879,6 @@ FOLIO_FLAG_FALSE(partially_mapped)
#define PG_head_mask ((1UL << PG_head))
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-/*
- * PageTransCompound returns true for both transparent huge pages
- * and hugetlbfs pages, so it should only be called when it's known
- * that hugetlbfs pages aren't involved.
- */
-static inline int PageTransCompound(const struct page *page)
-{
- return PageCompound(page);
-}
-#else
-TESTPAGEFLAG_FALSE(TransCompound, transcompound)
-#endif
-
#if defined(CONFIG_MEMORY_FAILURE) && defined(CONFIG_TRANSPARENT_HUGEPAGE)
/*
* PageHasHWPoisoned indicates that at least one subpage is hwpoisoned in the
diff --git a/mm/ksm.c b/mm/ksm.c
index 7d5b76478f0b..41ab25aa2a82 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -2327,23 +2327,24 @@ static void cmp_and_merge_page(struct page *page, struct ksm_rmap_item *rmap_ite
tree_rmap_item =
unstable_tree_search_insert(rmap_item, page, &tree_page);
if (tree_rmap_item) {
+ struct folio *tree_folio;
bool split;
kfolio = try_to_merge_two_pages(rmap_item, page,
tree_rmap_item, tree_page);
+ tree_folio = page_folio(tree_page);
/*
- * If both pages we tried to merge belong to the same compound
- * page, then we actually ended up increasing the reference
- * count of the same compound page twice, and split_huge_page
- * failed.
+ * If both pages we tried to merge belong to the same (large)
+ * folio, then we actually ended up increasing the reference
+ * count of the same folio twice, and split_huge_page failed.
+ *
* Here we set a flag if that happened, and we use it later to
- * try split_huge_page again. Since we call put_page right
+ * try split_huge_page again. Since we call folio_put() right
* afterwards, the reference count will be correct and
* split_huge_page should succeed.
*/
- split = PageTransCompound(page)
- && compound_head(page) == compound_head(tree_page);
- put_page(tree_page);
+ split = folio == tree_folio;
+ folio_put(tree_folio);
if (kfolio) {
/*
* The pages were successfully merged: insert new
--
2.27.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] mm: remove PageTransCompound()
2026-06-18 11:35 [PATCH v2] mm: remove PageTransCompound() Kefeng Wang
@ 2026-06-18 12:40 ` David Hildenbrand (Arm)
2026-06-18 15:01 ` xu.xin16
1 sibling, 0 replies; 3+ messages in thread
From: David Hildenbrand (Arm) @ 2026-06-18 12:40 UTC (permalink / raw)
To: Kefeng Wang, Andrew Morton; +Cc: linux-mm, Xu Xin, Chengming Zhou
On 6/18/26 13:35, Kefeng Wang wrote:
> Remove the last user of PageTransCompound() in ksm and
> get rid of PageTransCompound().
>
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
> ---
> v2:
> - use more folio in cmp_and_merge_page(), suggested by David
>
> include/linux/page-flags.h | 14 --------------
> mm/ksm.c | 17 +++++++++--------
> 2 files changed, 9 insertions(+), 22 deletions(-)
>
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 7223f6f4e2b4..7a863572adce 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -879,20 +879,6 @@ FOLIO_FLAG_FALSE(partially_mapped)
>
> #define PG_head_mask ((1UL << PG_head))
>
> -#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> -/*
> - * PageTransCompound returns true for both transparent huge pages
> - * and hugetlbfs pages, so it should only be called when it's known
> - * that hugetlbfs pages aren't involved.
> - */
> -static inline int PageTransCompound(const struct page *page)
> -{
> - return PageCompound(page);
> -}
> -#else
> -TESTPAGEFLAG_FALSE(TransCompound, transcompound)
> -#endif
> -
> #if defined(CONFIG_MEMORY_FAILURE) && defined(CONFIG_TRANSPARENT_HUGEPAGE)
> /*
> * PageHasHWPoisoned indicates that at least one subpage is hwpoisoned in the
> diff --git a/mm/ksm.c b/mm/ksm.c
> index 7d5b76478f0b..41ab25aa2a82 100644
> --- a/mm/ksm.c
> +++ b/mm/ksm.c
> @@ -2327,23 +2327,24 @@ static void cmp_and_merge_page(struct page *page, struct ksm_rmap_item *rmap_ite
> tree_rmap_item =
> unstable_tree_search_insert(rmap_item, page, &tree_page);
> if (tree_rmap_item) {
> + struct folio *tree_folio;
> bool split;
>
> kfolio = try_to_merge_two_pages(rmap_item, page,
> tree_rmap_item, tree_page);
> + tree_folio = page_folio(tree_page);
> /*
> - * If both pages we tried to merge belong to the same compound
> - * page, then we actually ended up increasing the reference
> - * count of the same compound page twice, and split_huge_page
> - * failed.
> + * If both pages we tried to merge belong to the same (large)
> + * folio, then we actually ended up increasing the reference
> + * count of the same folio twice, and split_huge_page failed.
> + *
> * Here we set a flag if that happened, and we use it later to
> - * try split_huge_page again. Since we call put_page right
> + * try split_huge_page again. Since we call folio_put() right
> * afterwards, the reference count will be correct and
> * split_huge_page should succeed.
> */
> - split = PageTransCompound(page)
> - && compound_head(page) == compound_head(tree_page);
> - put_page(tree_page);
> + split = folio == tree_folio;
> + folio_put(tree_folio);
> if (kfolio) {
> /*
> * The pages were successfully merged: insert new
Thanks!
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] mm: remove PageTransCompound()
2026-06-18 11:35 [PATCH v2] mm: remove PageTransCompound() Kefeng Wang
2026-06-18 12:40 ` David Hildenbrand (Arm)
@ 2026-06-18 15:01 ` xu.xin16
1 sibling, 0 replies; 3+ messages in thread
From: xu.xin16 @ 2026-06-18 15:01 UTC (permalink / raw)
To: wangkefeng.wang, akpm, david; +Cc: linux-mm, chengming.zhou, wangkefeng.wang
> diff --git a/mm/ksm.c b/mm/ksm.c
> index 7d5b76478f0b..41ab25aa2a82 100644
> --- a/mm/ksm.c
> +++ b/mm/ksm.c
> @@ -2327,23 +2327,24 @@ static void cmp_and_merge_page(struct page *page, struct ksm_rmap_item *rmap_ite
> tree_rmap_item =
> unstable_tree_search_insert(rmap_item, page, &tree_page);
> if (tree_rmap_item) {
> + struct folio *tree_folio;
> bool split;
>
> kfolio = try_to_merge_two_pages(rmap_item, page,
> tree_rmap_item, tree_page);
> + tree_folio = page_folio(tree_page);
> /*
> - * If both pages we tried to merge belong to the same compound
> - * page, then we actually ended up increasing the reference
> - * count of the same compound page twice, and split_huge_page
> - * failed.
> + * If both pages we tried to merge belong to the same (large)
> + * folio, then we actually ended up increasing the reference
> + * count of the same folio twice, and split_huge_page failed.
> + *
> * Here we set a flag if that happened, and we use it later to
> - * try split_huge_page again. Since we call put_page right
> + * try split_huge_page again. Since we call folio_put() right
> * afterwards, the reference count will be correct and
> * split_huge_page should succeed.
> */
> - split = PageTransCompound(page)
> - && compound_head(page) == compound_head(tree_page);
> - put_page(tree_page);
> + split = folio == tree_folio;
> + folio_put(tree_folio);
> if (kfolio) {
> /*
> * The pages were successfully merged: insert new
> --
> 2.27.0
LGTM.
Reviewed-by: Xu Xin <xu.xin16@zte.com.cn>
Tested-by: Xu Xin <xu.xin16@zte.com.cn>
and I test it with a reproducer about commit 77da2ba064 ("mm/ksm: fix interaction with THP")
and Test result shows OK.
Happy to share my testing program:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#define THP_SIZE (1UL << 21) /* 2MB */
#define WAIT_SECONDS 10 /* time for KSM scans */
/*
* Read a single integer from a sysfs file.
*/
static int read_sysfs_int(const char *path)
{
FILE *fp;
int val;
fp = fopen(path, "r");
if (!fp)
return -1;
if (fscanf(fp, "%d", &val) != 1) {
fclose(fp);
return -1;
}
fclose(fp);
return val;
}
/*
* Print KSM global counters.
*/
static void print_ksm_counters(int need_verify)
{
int pages_shared, pages_sharing;
pages_shared = read_sysfs_int("/sys/kernel/mm/ksm/pages_shared");
pages_sharing = read_sysfs_int("/sys/kernel/mm/ksm/pages_sharing");
if (pages_shared >= 0 && pages_sharing >= 0) {
printf("KSM counters: pages_shared = %d, pages_sharing = %d\n",
pages_shared, pages_sharing);
} else {
printf("Failed to read KSM counters\n");
}
if (need_verify) {
if (pages_sharing != 510)
printf("\n Test result: Failed\n");
else
printf("\n Test result: Passed\n");
}
}
/*
* Print relevant fields from /proc/self/smaps for the VMA covering @addr.
*/
static void print_smaps_info(unsigned long addr)
{
FILE *fp;
char line[256];
unsigned long start, end;
int found = 0;
int AnonHugePages_val = 0;
fp = fopen("/proc/self/smaps", "r");
if (!fp) {
perror("fopen /proc/self/smaps");
return;
}
while (fgets(line, sizeof(line), fp)) {
if (sscanf(line, "%lx-%lx", &start, &end) == 2) {
if (addr >= start && addr < end) {
found = 1;
printf("\n[VMA] 0x%lx-0x%lx\n", start, end);
/* Read subsequent lines until next VMA */
while (fgets(line, sizeof(line), fp)) {
unsigned long dummy_start, dummy_end;
if (sscanf(line, "%lx-%lx",
&dummy_start, &dummy_end) == 2)
break; /* next VMA */
if (strstr(line, "Rss:") ||
strstr(line, "AnonHugePages:") ||
strstr(line, "Shared_Clean:") ||
strstr(line, "Shared_Dirty:") ||
strstr(line, "Private_Clean:") ||
strstr(line, "Private_Dirty:") ||
strstr(line, "MMUPageSize:"))
printf("%s", line);
if (strstr(line, "AnonHugePages:")) {
if (sscanf(line, "AnonHugePages:%d kB", &AnonHugePages_val) != 1) {
printf("error: read AnonHugePages\n");
exit(1);
}
}
}
break;
}
}
}
if (!found) {
printf("Address 0x%lx not found in smaps\n", addr);
exit(1);
}
if (AnonHugePages_val != 2048) {
printf("AnonHugePages is not 2048 kb, not Huge page\n");
}
fclose(fp);
}
static int thp_is_enabled(void)
{
FILE *fp;
char buf[256];
int ret = 0;
fp = fopen("/sys/kernel/mm/transparent_hugepage/enabled", "r");
if (!fp)
return 0;
if (fgets(buf, sizeof(buf), fp)) {
if (strstr(buf, "[always]") || strstr(buf, "[madvise]"))
ret = 1;
}
fclose(fp);
return ret;
}
int main(void)
{
void *p;
int ret;
if (!thp_is_enabled()) {
fprintf(stderr, "Warning: THP seems disabled.\n");
fprintf(stderr, "Enable with 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled'\n");
}
if (read_sysfs_int("/sys/kernel/mm/ksm/run") != 1) {
fprintf(stderr, "KSM is not running. Start with 'echo 1 > /sys/kernel/mm/ksm/run'\n");
return 1;
}
ret = posix_memalign(&p, THP_SIZE, THP_SIZE);
if (ret) {
fprintf(stderr, "posix_memalign failed: %s\n", strerror(ret));
return 1;
}
if (madvise(p, THP_SIZE, MADV_HUGEPAGE) != 0)
perror("madvise MADV_HUGEPAGE");
printf("Allocated %zu bytes at %p (aligned to %zu) with madvise(MADV_HUGEPAGE)\n",
THP_SIZE, p, THP_SIZE);
memset(p, 0x42, THP_SIZE);
printf("Filled with 0x42\n");
printf("\n=== Before madvise(MADV_MERGEABLE) ===\n");
print_smaps_info((unsigned long)p);
print_ksm_counters(0);
if (madvise(p, THP_SIZE, MADV_MERGEABLE) != 0) {
perror("madvise MADV_MERGEABLE");
free(p);
return 1;
}
printf("madvise(MADV_MERGEABLE) succeeded.\n");
printf("Waiting %d seconds for KSM to scan...\n", WAIT_SECONDS);
sleep(WAIT_SECONDS);
printf("\n=== After waiting for KSM ===\n");
print_smaps_info((unsigned long)p);
print_ksm_counters(1);
free(p);
return 0;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-06-18 15:02 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18 11:35 [PATCH v2] mm: remove PageTransCompound() Kefeng Wang
2026-06-18 12:40 ` David Hildenbrand (Arm)
2026-06-18 15:01 ` xu.xin16
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox