Merge "mm, page_owner: track and print last migrate reason"
This commit is contained in:
commit
e8b8b04e8e
6 changed files with 50 additions and 3 deletions
|
@ -23,9 +23,13 @@ enum migrate_reason {
|
||||||
MR_SYSCALL, /* also applies to cpusets */
|
MR_SYSCALL, /* also applies to cpusets */
|
||||||
MR_MEMPOLICY_MBIND,
|
MR_MEMPOLICY_MBIND,
|
||||||
MR_NUMA_MISPLACED,
|
MR_NUMA_MISPLACED,
|
||||||
MR_CMA
|
MR_CMA,
|
||||||
|
MR_TYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* In mm/debug.c; also keep sync with include/trace/events/migrate.h */
|
||||||
|
extern char *migrate_reason_names[MR_TYPES];
|
||||||
|
|
||||||
#ifdef CONFIG_MIGRATION
|
#ifdef CONFIG_MIGRATION
|
||||||
|
|
||||||
extern void putback_movable_pages(struct list_head *l);
|
extern void putback_movable_pages(struct list_head *l);
|
||||||
|
|
|
@ -45,6 +45,7 @@ struct page_ext {
|
||||||
unsigned int order;
|
unsigned int order;
|
||||||
gfp_t gfp_mask;
|
gfp_t gfp_mask;
|
||||||
unsigned int nr_entries;
|
unsigned int nr_entries;
|
||||||
|
int last_migrate_reason;
|
||||||
unsigned long trace_entries[8];
|
unsigned long trace_entries[8];
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@ extern void __set_page_owner(struct page *page,
|
||||||
unsigned int order, gfp_t gfp_mask);
|
unsigned int order, gfp_t gfp_mask);
|
||||||
extern gfp_t __get_page_owner_gfp(struct page *page);
|
extern gfp_t __get_page_owner_gfp(struct page *page);
|
||||||
extern void __copy_page_owner(struct page *oldpage, struct page *newpage);
|
extern void __copy_page_owner(struct page *oldpage, struct page *newpage);
|
||||||
|
extern void __set_page_owner_migrate_reason(struct page *page, int reason);
|
||||||
|
|
||||||
static inline void reset_page_owner(struct page *page, unsigned int order)
|
static inline void reset_page_owner(struct page *page, unsigned int order)
|
||||||
{
|
{
|
||||||
|
@ -38,6 +39,11 @@ static inline void copy_page_owner(struct page *oldpage, struct page *newpage)
|
||||||
if (static_branch_unlikely(&page_owner_inited))
|
if (static_branch_unlikely(&page_owner_inited))
|
||||||
__copy_page_owner(oldpage, newpage);
|
__copy_page_owner(oldpage, newpage);
|
||||||
}
|
}
|
||||||
|
static inline void set_page_owner_migrate_reason(struct page *page, int reason)
|
||||||
|
{
|
||||||
|
if (static_branch_unlikely(&page_owner_inited))
|
||||||
|
__set_page_owner_migrate_reason(page, reason);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
static inline void reset_page_owner(struct page *page, unsigned int order)
|
static inline void reset_page_owner(struct page *page, unsigned int order)
|
||||||
{
|
{
|
||||||
|
@ -53,5 +59,8 @@ static inline gfp_t get_page_owner_gfp(struct page *page)
|
||||||
static inline void copy_page_owner(struct page *oldpage, struct page *newpage)
|
static inline void copy_page_owner(struct page *oldpage, struct page *newpage)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline void set_page_owner_migrate_reason(struct page *page, int reason)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* CONFIG_PAGE_OWNER */
|
#endif /* CONFIG_PAGE_OWNER */
|
||||||
#endif /* __LINUX_PAGE_OWNER_H */
|
#endif /* __LINUX_PAGE_OWNER_H */
|
||||||
|
|
11
mm/debug.c
11
mm/debug.c
|
@ -9,6 +9,17 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/trace_events.h>
|
#include <linux/trace_events.h>
|
||||||
#include <linux/memcontrol.h>
|
#include <linux/memcontrol.h>
|
||||||
|
#include <linux/migrate.h>
|
||||||
|
|
||||||
|
char *migrate_reason_names[MR_TYPES] = {
|
||||||
|
"compaction",
|
||||||
|
"memory_failure",
|
||||||
|
"memory_hotplug",
|
||||||
|
"syscall_or_cpuset",
|
||||||
|
"mempolicy_mbind",
|
||||||
|
"numa_misplaced",
|
||||||
|
"cma",
|
||||||
|
};
|
||||||
|
|
||||||
static const struct trace_print_flags pageflag_names[] = {
|
static const struct trace_print_flags pageflag_names[] = {
|
||||||
{1UL << PG_locked, "locked" },
|
{1UL << PG_locked, "locked" },
|
||||||
|
|
|
@ -1100,6 +1100,9 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = __unmap_and_move(page, newpage, force, mode);
|
rc = __unmap_and_move(page, newpage, force, mode);
|
||||||
|
if (rc == MIGRATEPAGE_SUCCESS) {
|
||||||
|
set_page_owner_migrate_reason(newpage, reason);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (rc != -EAGAIN) {
|
if (rc != -EAGAIN) {
|
||||||
|
@ -1182,7 +1185,7 @@ put_new:
|
||||||
static int unmap_and_move_huge_page(new_page_t get_new_page,
|
static int unmap_and_move_huge_page(new_page_t get_new_page,
|
||||||
free_page_t put_new_page, unsigned long private,
|
free_page_t put_new_page, unsigned long private,
|
||||||
struct page *hpage, int force,
|
struct page *hpage, int force,
|
||||||
enum migrate_mode mode)
|
enum migrate_mode mode, int reason)
|
||||||
{
|
{
|
||||||
int rc = -EAGAIN;
|
int rc = -EAGAIN;
|
||||||
int *result = NULL;
|
int *result = NULL;
|
||||||
|
@ -1240,6 +1243,7 @@ put_anon:
|
||||||
if (rc == MIGRATEPAGE_SUCCESS) {
|
if (rc == MIGRATEPAGE_SUCCESS) {
|
||||||
hugetlb_cgroup_migrate(hpage, new_hpage);
|
hugetlb_cgroup_migrate(hpage, new_hpage);
|
||||||
put_new_page = NULL;
|
put_new_page = NULL;
|
||||||
|
set_page_owner_migrate_reason(new_hpage, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_page(hpage);
|
unlock_page(hpage);
|
||||||
|
@ -1314,7 +1318,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
|
||||||
if (PageHuge(page))
|
if (PageHuge(page))
|
||||||
rc = unmap_and_move_huge_page(get_new_page,
|
rc = unmap_and_move_huge_page(get_new_page,
|
||||||
put_new_page, private, page,
|
put_new_page, private, page,
|
||||||
pass > 2, mode);
|
pass > 2, mode, reason);
|
||||||
else
|
else
|
||||||
rc = unmap_and_move(get_new_page, put_new_page,
|
rc = unmap_and_move(get_new_page, put_new_page,
|
||||||
private, page, pass > 2, mode,
|
private, page, pass > 2, mode,
|
||||||
|
@ -2004,6 +2008,7 @@ fail_putback:
|
||||||
set_page_memcg(new_page, page_memcg(page));
|
set_page_memcg(new_page, page_memcg(page));
|
||||||
set_page_memcg(page, NULL);
|
set_page_memcg(page, NULL);
|
||||||
page_remove_rmap(page);
|
page_remove_rmap(page);
|
||||||
|
set_page_owner_migrate_reason(new_page, MR_NUMA_MISPLACED);
|
||||||
|
|
||||||
spin_unlock(ptl);
|
spin_unlock(ptl);
|
||||||
mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
|
mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <linux/stacktrace.h>
|
#include <linux/stacktrace.h>
|
||||||
#include <linux/page_owner.h>
|
#include <linux/page_owner.h>
|
||||||
#include <linux/jump_label.h>
|
#include <linux/jump_label.h>
|
||||||
|
#include <linux/migrate.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static bool page_owner_disabled =
|
static bool page_owner_disabled =
|
||||||
|
@ -77,10 +78,18 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask)
|
||||||
page_ext->order = order;
|
page_ext->order = order;
|
||||||
page_ext->gfp_mask = gfp_mask;
|
page_ext->gfp_mask = gfp_mask;
|
||||||
page_ext->nr_entries = trace.nr_entries;
|
page_ext->nr_entries = trace.nr_entries;
|
||||||
|
page_ext->last_migrate_reason = -1;
|
||||||
|
|
||||||
__set_bit(PAGE_EXT_OWNER, &page_ext->flags);
|
__set_bit(PAGE_EXT_OWNER, &page_ext->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __set_page_owner_migrate_reason(struct page *page, int reason)
|
||||||
|
{
|
||||||
|
struct page_ext *page_ext = lookup_page_ext(page);
|
||||||
|
|
||||||
|
page_ext->last_migrate_reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
gfp_t __get_page_owner_gfp(struct page *page)
|
gfp_t __get_page_owner_gfp(struct page *page)
|
||||||
{
|
{
|
||||||
struct page_ext *page_ext = lookup_page_ext(page);
|
struct page_ext *page_ext = lookup_page_ext(page);
|
||||||
|
@ -155,6 +164,14 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
|
||||||
if (ret >= count)
|
if (ret >= count)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
if (page_ext->last_migrate_reason != -1) {
|
||||||
|
ret += snprintf(kbuf + ret, count - ret,
|
||||||
|
"Page has been migrated, last migrate reason: %s\n",
|
||||||
|
migrate_reason_names[page_ext->last_migrate_reason]);
|
||||||
|
if (ret >= count)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
ret += snprintf(kbuf + ret, count - ret, "\n");
|
ret += snprintf(kbuf + ret, count - ret, "\n");
|
||||||
if (ret >= count)
|
if (ret >= count)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
Loading…
Add table
Reference in a new issue