selftests: mm: support shmem mTHP collapse testing

Add shmem mTHP collpase testing.  Similar to the anonymous page, users can
use the '-s' parameter to specify the shmem mTHP size for testing.

Link: https://lkml.kernel.org/r/fa44bfa20ca5b9fd6f9163a048f3d3c1e53cd0a8.1724140601.git.baolin.wang@linux.alibaba.com
Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <21cnbao@gmail.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Yang Shi <shy828301@gmail.com>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Baolin Wang 2024-08-20 17:49:17 +08:00 committed by Andrew Morton
parent 7de856ffd0
commit 2e6d88e9d4
3 changed files with 51 additions and 8 deletions

View File

@ -1095,7 +1095,7 @@ static void usage(void)
fprintf(stderr, "\n\tSupported Options:\n"); fprintf(stderr, "\n\tSupported Options:\n");
fprintf(stderr, "\t\t-h: This help message.\n"); fprintf(stderr, "\t\t-h: This help message.\n");
fprintf(stderr, "\t\t-s: mTHP size, expressed as page order.\n"); fprintf(stderr, "\t\t-s: mTHP size, expressed as page order.\n");
fprintf(stderr, "\t\t Defaults to 0. Use this size for anon allocations.\n"); fprintf(stderr, "\t\t Defaults to 0. Use this size for anon or shmem allocations.\n");
exit(1); exit(1);
} }
@ -1209,6 +1209,8 @@ int main(int argc, char **argv)
default_settings.khugepaged.pages_to_scan = hpage_pmd_nr * 8; default_settings.khugepaged.pages_to_scan = hpage_pmd_nr * 8;
default_settings.hugepages[hpage_pmd_order].enabled = THP_INHERIT; default_settings.hugepages[hpage_pmd_order].enabled = THP_INHERIT;
default_settings.hugepages[anon_order].enabled = THP_ALWAYS; default_settings.hugepages[anon_order].enabled = THP_ALWAYS;
default_settings.shmem_hugepages[hpage_pmd_order].enabled = SHMEM_INHERIT;
default_settings.shmem_hugepages[anon_order].enabled = SHMEM_ALWAYS;
save_settings(); save_settings();
thp_push_settings(&default_settings); thp_push_settings(&default_settings);

View File

@ -33,10 +33,11 @@ static const char * const thp_defrag_strings[] = {
}; };
static const char * const shmem_enabled_strings[] = { static const char * const shmem_enabled_strings[] = {
"never",
"always", "always",
"within_size", "within_size",
"advise", "advise",
"never", "inherit",
"deny", "deny",
"force", "force",
NULL NULL
@ -200,6 +201,7 @@ void thp_write_num(const char *name, unsigned long num)
void thp_read_settings(struct thp_settings *settings) void thp_read_settings(struct thp_settings *settings)
{ {
unsigned long orders = thp_supported_orders(); unsigned long orders = thp_supported_orders();
unsigned long shmem_orders = thp_shmem_supported_orders();
char path[PATH_MAX]; char path[PATH_MAX];
int i; int i;
@ -234,12 +236,24 @@ void thp_read_settings(struct thp_settings *settings)
settings->hugepages[i].enabled = settings->hugepages[i].enabled =
thp_read_string(path, thp_enabled_strings); thp_read_string(path, thp_enabled_strings);
} }
for (i = 0; i < NR_ORDERS; i++) {
if (!((1 << i) & shmem_orders)) {
settings->shmem_hugepages[i].enabled = SHMEM_NEVER;
continue;
}
snprintf(path, PATH_MAX, "hugepages-%ukB/shmem_enabled",
(getpagesize() >> 10) << i);
settings->shmem_hugepages[i].enabled =
thp_read_string(path, shmem_enabled_strings);
}
} }
void thp_write_settings(struct thp_settings *settings) void thp_write_settings(struct thp_settings *settings)
{ {
struct khugepaged_settings *khugepaged = &settings->khugepaged; struct khugepaged_settings *khugepaged = &settings->khugepaged;
unsigned long orders = thp_supported_orders(); unsigned long orders = thp_supported_orders();
unsigned long shmem_orders = thp_shmem_supported_orders();
char path[PATH_MAX]; char path[PATH_MAX];
int enabled; int enabled;
int i; int i;
@ -271,6 +285,15 @@ void thp_write_settings(struct thp_settings *settings)
enabled = settings->hugepages[i].enabled; enabled = settings->hugepages[i].enabled;
thp_write_string(path, thp_enabled_strings[enabled]); thp_write_string(path, thp_enabled_strings[enabled]);
} }
for (i = 0; i < NR_ORDERS; i++) {
if (!((1 << i) & shmem_orders))
continue;
snprintf(path, PATH_MAX, "hugepages-%ukB/shmem_enabled",
(getpagesize() >> 10) << i);
enabled = settings->shmem_hugepages[i].enabled;
thp_write_string(path, shmem_enabled_strings[enabled]);
}
} }
struct thp_settings *thp_current_settings(void) struct thp_settings *thp_current_settings(void)
@ -324,17 +347,18 @@ void thp_set_read_ahead_path(char *path)
dev_queue_read_ahead_path[sizeof(dev_queue_read_ahead_path) - 1] = '\0'; dev_queue_read_ahead_path[sizeof(dev_queue_read_ahead_path) - 1] = '\0';
} }
unsigned long thp_supported_orders(void) static unsigned long __thp_supported_orders(bool is_shmem)
{ {
unsigned long orders = 0; unsigned long orders = 0;
char path[PATH_MAX]; char path[PATH_MAX];
char buf[256]; char buf[256];
int ret; int ret, i;
int i; char anon_dir[] = "enabled";
char shmem_dir[] = "shmem_enabled";
for (i = 0; i < NR_ORDERS; i++) { for (i = 0; i < NR_ORDERS; i++) {
ret = snprintf(path, PATH_MAX, THP_SYSFS "hugepages-%ukB/enabled", ret = snprintf(path, PATH_MAX, THP_SYSFS "hugepages-%ukB/%s",
(getpagesize() >> 10) << i); (getpagesize() >> 10) << i, is_shmem ? shmem_dir : anon_dir);
if (ret >= PATH_MAX) { if (ret >= PATH_MAX) {
printf("%s: Pathname is too long\n", __func__); printf("%s: Pathname is too long\n", __func__);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -347,3 +371,13 @@ unsigned long thp_supported_orders(void)
return orders; return orders;
} }
unsigned long thp_supported_orders(void)
{
return __thp_supported_orders(false);
}
unsigned long thp_shmem_supported_orders(void)
{
return __thp_supported_orders(true);
}

View File

@ -22,10 +22,11 @@ enum thp_defrag {
}; };
enum shmem_enabled { enum shmem_enabled {
SHMEM_NEVER,
SHMEM_ALWAYS, SHMEM_ALWAYS,
SHMEM_WITHIN_SIZE, SHMEM_WITHIN_SIZE,
SHMEM_ADVISE, SHMEM_ADVISE,
SHMEM_NEVER, SHMEM_INHERIT,
SHMEM_DENY, SHMEM_DENY,
SHMEM_FORCE, SHMEM_FORCE,
}; };
@ -46,6 +47,10 @@ struct khugepaged_settings {
unsigned long pages_to_scan; unsigned long pages_to_scan;
}; };
struct shmem_hugepages_settings {
enum shmem_enabled enabled;
};
struct thp_settings { struct thp_settings {
enum thp_enabled thp_enabled; enum thp_enabled thp_enabled;
enum thp_defrag thp_defrag; enum thp_defrag thp_defrag;
@ -54,6 +59,7 @@ struct thp_settings {
struct khugepaged_settings khugepaged; struct khugepaged_settings khugepaged;
unsigned long read_ahead_kb; unsigned long read_ahead_kb;
struct hugepages_settings hugepages[NR_ORDERS]; struct hugepages_settings hugepages[NR_ORDERS];
struct shmem_hugepages_settings shmem_hugepages[NR_ORDERS];
}; };
int read_file(const char *path, char *buf, size_t buflen); int read_file(const char *path, char *buf, size_t buflen);
@ -76,5 +82,6 @@ void thp_save_settings(void);
void thp_set_read_ahead_path(char *path); void thp_set_read_ahead_path(char *path);
unsigned long thp_supported_orders(void); unsigned long thp_supported_orders(void);
unsigned long thp_shmem_supported_orders(void);
#endif /* __THP_SETTINGS_H__ */ #endif /* __THP_SETTINGS_H__ */