* [RFC PATCH v4 1/5] mm: make alloc_demote_folio externally invokable for migration
2024-05-12 17:54 [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory SeongJae Park
@ 2024-05-12 17:54 ` SeongJae Park
2024-05-13 12:03 ` Honggyu Kim
2024-05-12 17:54 ` [RFC PATCH v4 2/5] mm/damon/sysfs-schemes: add target_nid on sysfs-schemes SeongJae Park
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: SeongJae Park @ 2024-05-12 17:54 UTC (permalink / raw)
Cc: Honggyu Kim, Andrew Morton, linux-mm, damon, linux-kernel,
SeongJae Park
From: Honggyu Kim <honggyu.kim@sk.com>
The alloc_demote_folio can be used out of vmscan.c so it'd be better to
remove static keyword from it.
This function can also be used for both demotion and promotion so it'd
be better to rename it from alloc_demote_folio to alloc_migrate_folio.
Signed-off-by: Honggyu Kim <honggyu.kim@sk.com>
Reviewed-by: SeongJae Park <sj@kernel.org>
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/internal.h | 1 +
mm/vmscan.c | 3 +--
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index b2c75b12014e..b3ca996a4efc 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1052,6 +1052,7 @@ extern unsigned long __must_check vm_mmap_pgoff(struct file *, unsigned long,
unsigned long, unsigned long);
extern void set_pageblock_order(void);
+struct folio *alloc_demote_folio(struct folio *src, unsigned long private);
unsigned long reclaim_pages(struct list_head *folio_list);
unsigned int reclaim_clean_pages_from_list(struct zone *zone,
struct list_head *folio_list);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 6981a71c8ef0..27269bc2bcc5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -933,8 +933,7 @@ static void folio_check_dirty_writeback(struct folio *folio,
mapping->a_ops->is_dirty_writeback(folio, dirty, writeback);
}
-static struct folio *alloc_demote_folio(struct folio *src,
- unsigned long private)
+struct folio *alloc_demote_folio(struct folio *src, unsigned long private)
{
struct folio *dst;
nodemask_t *allowed_mask;
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [RFC PATCH v4 1/5] mm: make alloc_demote_folio externally invokable for migration
2024-05-12 17:54 ` [RFC PATCH v4 1/5] mm: make alloc_demote_folio externally invokable for migration SeongJae Park
@ 2024-05-13 12:03 ` Honggyu Kim
2024-05-15 16:10 ` SeongJae Park
0 siblings, 1 reply; 10+ messages in thread
From: Honggyu Kim @ 2024-05-13 12:03 UTC (permalink / raw)
To: SeongJae Park
Cc: Honggyu Kim, Andrew Morton, linux-mm, damon, linux-kernel,
kernel_team
On Sun, 12 May 2024 10:54:43 -0700 SeongJae Park <sj@kernel.org> wrote:
> From: Honggyu Kim <honggyu.kim@sk.com>
>
> The alloc_demote_folio can be used out of vmscan.c so it'd be better to
> remove static keyword from it.
>
> This function can also be used for both demotion and promotion so it'd
> be better to rename it from alloc_demote_folio to alloc_migrate_folio.
This description doesn't match with the changes below.
> Signed-off-by: Honggyu Kim <honggyu.kim@sk.com>
> Reviewed-by: SeongJae Park <sj@kernel.org>
> Signed-off-by: SeongJae Park <sj@kernel.org>
> ---
> mm/internal.h | 1 +
> mm/vmscan.c | 3 +--
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/mm/internal.h b/mm/internal.h
> index b2c75b12014e..b3ca996a4efc 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -1052,6 +1052,7 @@ extern unsigned long __must_check vm_mmap_pgoff(struct file *, unsigned long,
> unsigned long, unsigned long);
>
> extern void set_pageblock_order(void);
> +struct folio *alloc_demote_folio(struct folio *src, unsigned long private);
I still prefer to rename it to alloc_migrate_folio.
> unsigned long reclaim_pages(struct list_head *folio_list);
> unsigned int reclaim_clean_pages_from_list(struct zone *zone,
> struct list_head *folio_list);
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 6981a71c8ef0..27269bc2bcc5 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -933,8 +933,7 @@ static void folio_check_dirty_writeback(struct folio *folio,
> mapping->a_ops->is_dirty_writeback(folio, dirty, writeback);
> }
>
> -static struct folio *alloc_demote_folio(struct folio *src,
> - unsigned long private)
> +struct folio *alloc_demote_folio(struct folio *src, unsigned long private)
Here as well.
> {
> struct folio *dst;
> nodemask_t *allowed_mask;
> --
> 2.39.2
>
Thanks,
Honggyu
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFC PATCH v4 1/5] mm: make alloc_demote_folio externally invokable for migration
2024-05-13 12:03 ` Honggyu Kim
@ 2024-05-15 16:10 ` SeongJae Park
0 siblings, 0 replies; 10+ messages in thread
From: SeongJae Park @ 2024-05-15 16:10 UTC (permalink / raw)
To: Honggyu Kim
Cc: SeongJae Park, Andrew Morton, linux-mm, damon, linux-kernel,
kernel_team
On Mon, 13 May 2024 21:03:56 +0900 Honggyu Kim <honggyu.kim@sk.com> wrote:
> On Sun, 12 May 2024 10:54:43 -0700 SeongJae Park <sj@kernel.org> wrote:
> > From: Honggyu Kim <honggyu.kim@sk.com>
> >
> > The alloc_demote_folio can be used out of vmscan.c so it'd be better to
> > remove static keyword from it.
> >
> > This function can also be used for both demotion and promotion so it'd
> > be better to rename it from alloc_demote_folio to alloc_migrate_folio.
>
> This description doesn't match with the changes below.
You're right. Thank you for checking this.
>
> > Signed-off-by: Honggyu Kim <honggyu.kim@sk.com>
> > Reviewed-by: SeongJae Park <sj@kernel.org>
> > Signed-off-by: SeongJae Park <sj@kernel.org>
> > ---
> > mm/internal.h | 1 +
> > mm/vmscan.c | 3 +--
> > 2 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/mm/internal.h b/mm/internal.h
> > index b2c75b12014e..b3ca996a4efc 100644
> > --- a/mm/internal.h
> > +++ b/mm/internal.h
> > @@ -1052,6 +1052,7 @@ extern unsigned long __must_check vm_mmap_pgoff(struct file *, unsigned long,
> > unsigned long, unsigned long);
> >
> > extern void set_pageblock_order(void);
> > +struct folio *alloc_demote_folio(struct folio *src, unsigned long private);
>
> I still prefer to rename it to alloc_migrate_folio.
And I still have no objection at renaming. I didn't make the change here not
because I want the change removed, but just because I wrote this RFC v4 in hope
of seeing how minimum this patchset can be while addressing my comments.
Please feel free to add the change back on the next revision of this patch if
you write. Maybe keeping this patchset without the renaming change, and
discussing the renaming with a separate patch is also an option in my opinion.
>
> > unsigned long reclaim_pages(struct list_head *folio_list);
> > unsigned int reclaim_clean_pages_from_list(struct zone *zone,
> > struct list_head *folio_list);
> > diff --git a/mm/vmscan.c b/mm/vmscan.c
> > index 6981a71c8ef0..27269bc2bcc5 100644
> > --- a/mm/vmscan.c
> > +++ b/mm/vmscan.c
> > @@ -933,8 +933,7 @@ static void folio_check_dirty_writeback(struct folio *folio,
> > mapping->a_ops->is_dirty_writeback(folio, dirty, writeback);
> > }
> >
> > -static struct folio *alloc_demote_folio(struct folio *src,
> > - unsigned long private)
> > +struct folio *alloc_demote_folio(struct folio *src, unsigned long private)
>
> Here as well.
Ditto.
>
> > {
> > struct folio *dst;
> > nodemask_t *allowed_mask;
> > --
> > 2.39.2
> >
>
> Thanks,
> Honggyu
Thanks,
SJ
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC PATCH v4 2/5] mm/damon/sysfs-schemes: add target_nid on sysfs-schemes
2024-05-12 17:54 [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory SeongJae Park
2024-05-12 17:54 ` [RFC PATCH v4 1/5] mm: make alloc_demote_folio externally invokable for migration SeongJae Park
@ 2024-05-12 17:54 ` SeongJae Park
2024-05-12 17:54 ` [RFC PATCH v4 3/5] mm/migrate: add MR_DAMON to migrate_reason SeongJae Park
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: SeongJae Park @ 2024-05-12 17:54 UTC (permalink / raw)
Cc: Hyeongtak Ji, SeongJae Park, Andrew Morton, damon, linux-mm,
linux-kernel, Honggyu Kim
From: Hyeongtak Ji <hyeongtak.ji@sk.com>
This patch adds target_nid under
/sys/kernel/mm/damon/admin/kdamonds/<N>/contexts/<N>/schemes/<N>/
The 'target_nid' can be used as the destination node for DAMOS actions
such as DAMOS_MIGRATE_{HOT,COLD} in the follow up patches.
Signed-off-by: Hyeongtak Ji <hyeongtak.ji@sk.com>
Signed-off-by: Honggyu Kim <honggyu.kim@sk.com>
Signed-off-by: SeongJae Park <sj@kernel.org>
---
include/linux/damon.h | 11 ++++++++++-
mm/damon/core.c | 5 ++++-
mm/damon/dbgfs.c | 2 +-
mm/damon/lru_sort.c | 3 ++-
mm/damon/reclaim.c | 3 ++-
mm/damon/sysfs-schemes.c | 33 ++++++++++++++++++++++++++++++++-
6 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index f7da65e1ac04..21d6b69a015c 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -374,6 +374,7 @@ struct damos_access_pattern {
* @apply_interval_us: The time between applying the @action.
* @quota: Control the aggressiveness of this scheme.
* @wmarks: Watermarks for automated (in)activation of this scheme.
+ * @target_nid: Destination node if @action is "migrate_{hot,cold}".
* @filters: Additional set of &struct damos_filter for &action.
* @stat: Statistics of this scheme.
* @list: List head for siblings.
@@ -389,6 +390,10 @@ struct damos_access_pattern {
* monitoring context are inactive, DAMON stops monitoring either, and just
* repeatedly checks the watermarks.
*
+ * @target_nid is used to set the migration target node for migrate_hot or
+ * migrate_cold actions, which means it's only meaningful when @action is either
+ * "migrate_hot" or "migrate_cold".
+ *
* Before applying the &action to a memory region, &struct damon_operations
* implementation could check pages of the region and skip &action to respect
* &filters
@@ -410,6 +415,9 @@ struct damos {
/* public: */
struct damos_quota quota;
struct damos_watermarks wmarks;
+ union {
+ int target_nid;
+ };
struct list_head filters;
struct damos_stat stat;
struct list_head list;
@@ -726,7 +734,8 @@ struct damos *damon_new_scheme(struct damos_access_pattern *pattern,
enum damos_action action,
unsigned long apply_interval_us,
struct damos_quota *quota,
- struct damos_watermarks *wmarks);
+ struct damos_watermarks *wmarks,
+ int target_nid);
void damon_add_scheme(struct damon_ctx *ctx, struct damos *s);
void damon_destroy_scheme(struct damos *s);
diff --git a/mm/damon/core.c b/mm/damon/core.c
index e1a0c2a11007..32c261aeff88 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -364,7 +364,8 @@ struct damos *damon_new_scheme(struct damos_access_pattern *pattern,
enum damos_action action,
unsigned long apply_interval_us,
struct damos_quota *quota,
- struct damos_watermarks *wmarks)
+ struct damos_watermarks *wmarks,
+ int target_nid)
{
struct damos *scheme;
@@ -391,6 +392,8 @@ struct damos *damon_new_scheme(struct damos_access_pattern *pattern,
scheme->wmarks = *wmarks;
scheme->wmarks.activated = true;
+ scheme->target_nid = target_nid;
+
return scheme;
}
diff --git a/mm/damon/dbgfs.c b/mm/damon/dbgfs.c
index 2461cfe2e968..51a6f1cac385 100644
--- a/mm/damon/dbgfs.c
+++ b/mm/damon/dbgfs.c
@@ -281,7 +281,7 @@ static struct damos **str_to_schemes(const char *str, ssize_t len,
pos += parsed;
scheme = damon_new_scheme(&pattern, action, 0, "a,
- &wmarks);
+ &wmarks, NUMA_NO_NODE);
if (!scheme)
goto fail;
diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
index 3de2916a65c3..3775f0f2743d 100644
--- a/mm/damon/lru_sort.c
+++ b/mm/damon/lru_sort.c
@@ -163,7 +163,8 @@ static struct damos *damon_lru_sort_new_scheme(
/* under the quota. */
"a,
/* (De)activate this according to the watermarks. */
- &damon_lru_sort_wmarks);
+ &damon_lru_sort_wmarks,
+ NUMA_NO_NODE);
}
/* Create a DAMON-based operation scheme for hot memory regions */
diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c
index 9bd341d62b4c..a05ccb41749b 100644
--- a/mm/damon/reclaim.c
+++ b/mm/damon/reclaim.c
@@ -177,7 +177,8 @@ static struct damos *damon_reclaim_new_scheme(void)
/* under the quota. */
&damon_reclaim_quota,
/* (De)activate this according to the watermarks. */
- &damon_reclaim_wmarks);
+ &damon_reclaim_wmarks,
+ NUMA_NO_NODE);
}
static void damon_reclaim_copy_quota_status(struct damos_quota *dst,
diff --git a/mm/damon/sysfs-schemes.c b/mm/damon/sysfs-schemes.c
index bea5bc52846a..0632d28b67f8 100644
--- a/mm/damon/sysfs-schemes.c
+++ b/mm/damon/sysfs-schemes.c
@@ -6,6 +6,7 @@
*/
#include <linux/slab.h>
+#include <linux/numa.h>
#include "sysfs-common.h"
@@ -1445,6 +1446,7 @@ struct damon_sysfs_scheme {
struct damon_sysfs_scheme_filters *filters;
struct damon_sysfs_stats *stats;
struct damon_sysfs_scheme_regions *tried_regions;
+ int target_nid;
};
/* This should match with enum damos_action */
@@ -1470,6 +1472,7 @@ static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
scheme->kobj = (struct kobject){};
scheme->action = action;
scheme->apply_interval_us = apply_interval_us;
+ scheme->target_nid = NUMA_NO_NODE;
return scheme;
}
@@ -1692,6 +1695,28 @@ static ssize_t apply_interval_us_store(struct kobject *kobj,
return err ? err : count;
}
+static ssize_t target_nid_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_scheme *scheme = container_of(kobj,
+ struct damon_sysfs_scheme, kobj);
+
+ return sysfs_emit(buf, "%d\n", scheme->target_nid);
+}
+
+static ssize_t target_nid_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_scheme *scheme = container_of(kobj,
+ struct damon_sysfs_scheme, kobj);
+ int err = 0;
+
+ /* TODO: error handling for target_nid range. */
+ err = kstrtoint(buf, 0, &scheme->target_nid);
+
+ return err ? err : count;
+}
+
static void damon_sysfs_scheme_release(struct kobject *kobj)
{
kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
@@ -1703,9 +1728,13 @@ static struct kobj_attribute damon_sysfs_scheme_action_attr =
static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr =
__ATTR_RW_MODE(apply_interval_us, 0600);
+static struct kobj_attribute damon_sysfs_scheme_target_nid_attr =
+ __ATTR_RW_MODE(target_nid, 0600);
+
static struct attribute *damon_sysfs_scheme_attrs[] = {
&damon_sysfs_scheme_action_attr.attr,
&damon_sysfs_scheme_apply_interval_us_attr.attr,
+ &damon_sysfs_scheme_target_nid_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_scheme);
@@ -2031,7 +2060,8 @@ static struct damos *damon_sysfs_mk_scheme(
};
scheme = damon_new_scheme(&pattern, sysfs_scheme->action,
- sysfs_scheme->apply_interval_us, "a, &wmarks);
+ sysfs_scheme->apply_interval_us, "a, &wmarks,
+ sysfs_scheme->target_nid);
if (!scheme)
return NULL;
@@ -2068,6 +2098,7 @@ static void damon_sysfs_update_scheme(struct damos *scheme,
scheme->action = sysfs_scheme->action;
scheme->apply_interval_us = sysfs_scheme->apply_interval_us;
+ scheme->target_nid = sysfs_scheme->target_nid;
scheme->quota.ms = sysfs_quotas->ms;
scheme->quota.sz = sysfs_quotas->sz;
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH v4 3/5] mm/migrate: add MR_DAMON to migrate_reason
2024-05-12 17:54 [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory SeongJae Park
2024-05-12 17:54 ` [RFC PATCH v4 1/5] mm: make alloc_demote_folio externally invokable for migration SeongJae Park
2024-05-12 17:54 ` [RFC PATCH v4 2/5] mm/damon/sysfs-schemes: add target_nid on sysfs-schemes SeongJae Park
@ 2024-05-12 17:54 ` SeongJae Park
2024-05-12 17:54 ` [RFC PATCH v4 4/5] mm/damon/paddr: introduce DAMOS_MIGRATE_COLD action for demotion SeongJae Park
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: SeongJae Park @ 2024-05-12 17:54 UTC (permalink / raw)
Cc: Honggyu Kim, Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
linux-kernel, damon, linux-mm, linux-trace-kernel, SeongJae Park
From: Honggyu Kim <honggyu.kim@sk.com>
The current patch series introduces DAMON based migration across NUMA
nodes so it'd be better to have a new migrate_reason in trace events.
Signed-off-by: Honggyu Kim <honggyu.kim@sk.com>
Reviewed-by: SeongJae Park <sj@kernel.org>
Signed-off-by: SeongJae Park <sj@kernel.org>
---
include/linux/migrate_mode.h | 1 +
include/trace/events/migrate.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/linux/migrate_mode.h b/include/linux/migrate_mode.h
index f37cc03f9369..cec36b7e7ced 100644
--- a/include/linux/migrate_mode.h
+++ b/include/linux/migrate_mode.h
@@ -29,6 +29,7 @@ enum migrate_reason {
MR_CONTIG_RANGE,
MR_LONGTERM_PIN,
MR_DEMOTION,
+ MR_DAMON,
MR_TYPES
};
diff --git a/include/trace/events/migrate.h b/include/trace/events/migrate.h
index 0190ef725b43..cd01dd7b3640 100644
--- a/include/trace/events/migrate.h
+++ b/include/trace/events/migrate.h
@@ -22,7 +22,8 @@
EM( MR_NUMA_MISPLACED, "numa_misplaced") \
EM( MR_CONTIG_RANGE, "contig_range") \
EM( MR_LONGTERM_PIN, "longterm_pin") \
- EMe(MR_DEMOTION, "demotion")
+ EM( MR_DEMOTION, "demotion") \
+ EMe(MR_DAMON, "damon")
/*
* First define the enums in the above macros to be exported to userspace
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH v4 4/5] mm/damon/paddr: introduce DAMOS_MIGRATE_COLD action for demotion
2024-05-12 17:54 [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory SeongJae Park
` (2 preceding siblings ...)
2024-05-12 17:54 ` [RFC PATCH v4 3/5] mm/migrate: add MR_DAMON to migrate_reason SeongJae Park
@ 2024-05-12 17:54 ` SeongJae Park
2024-05-12 17:54 ` [RFC PATCH v4 5/5] mm/damon/paddr: introduce DAMOS_MIGRATE_HOT action for promotion SeongJae Park
2024-05-13 11:59 ` [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory Honggyu Kim
5 siblings, 0 replies; 10+ messages in thread
From: SeongJae Park @ 2024-05-12 17:54 UTC (permalink / raw)
Cc: Honggyu Kim, SeongJae Park, Andrew Morton, damon, linux-mm,
linux-kernel, Hyeongtak Ji
From: Honggyu Kim <honggyu.kim@sk.com>
This patch introduces DAMOS_MIGRATE_COLD action, which is similar to
DAMOS_PAGEOUT, but migrate folios to the given 'target_nid' in the sysfs
instead of swapping them out.
The 'target_nid' sysfs knob informs the migration target node ID.
Here is one of the example usage of this 'migrate_cold' action.
$ cd /sys/kernel/mm/damon/admin/kdamonds/<N>
$ cat contexts/<N>/schemes/<N>/action
migrate_cold
$ echo 2 > contexts/<N>/schemes/<N>/target_nid
$ echo commit > state
$ numactl -p 0 ./hot_cold 500M 600M &
$ numastat -c -p hot_cold
Per-node process memory usage (in MBs)
PID Node 0 Node 1 Node 2 Total
-------------- ------ ------ ------ -----
701 (hot_cold) 501 0 601 1101
Since there are some common routines with pageout, many functions have
similar logics between pageout and migrate cold.
damon_pa_migrate_folio_list() is a minimized version of
shrink_folio_list().
Signed-off-by: Honggyu Kim <honggyu.kim@sk.com>
Signed-off-by: Hyeongtak Ji <hyeongtak.ji@sk.com>
Signed-off-by: SeongJae Park <sj@kernel.org>
---
include/linux/damon.h | 2 +
mm/damon/paddr.c | 154 +++++++++++++++++++++++++++++++++++++++
mm/damon/sysfs-schemes.c | 1 +
3 files changed, 157 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 21d6b69a015c..56714b6eb0d7 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -105,6 +105,7 @@ struct damon_target {
* @DAMOS_NOHUGEPAGE: Call ``madvise()`` for the region with MADV_NOHUGEPAGE.
* @DAMOS_LRU_PRIO: Prioritize the region on its LRU lists.
* @DAMOS_LRU_DEPRIO: Deprioritize the region on its LRU lists.
+ * @DAMOS_MIGRATE_COLD: Migrate the regions prioritizing colder regions.
* @DAMOS_STAT: Do nothing but count the stat.
* @NR_DAMOS_ACTIONS: Total number of DAMOS actions
*
@@ -122,6 +123,7 @@ enum damos_action {
DAMOS_NOHUGEPAGE,
DAMOS_LRU_PRIO,
DAMOS_LRU_DEPRIO,
+ DAMOS_MIGRATE_COLD,
DAMOS_STAT, /* Do nothing but only record the stat */
NR_DAMOS_ACTIONS,
};
diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 18797c1b419b..a468792d9162 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -12,6 +12,9 @@
#include <linux/pagemap.h>
#include <linux/rmap.h>
#include <linux/swap.h>
+#include <linux/memory-tiers.h>
+#include <linux/migrate.h>
+#include <linux/mm_inline.h>
#include "../internal.h"
#include "ops-common.h"
@@ -325,6 +328,153 @@ static unsigned long damon_pa_deactivate_pages(struct damon_region *r,
return damon_pa_mark_accessed_or_deactivate(r, s, false);
}
+static unsigned int __damon_pa_migrate_folio_list(
+ struct list_head *migrate_folios, struct pglist_data *pgdat,
+ int target_nid)
+{
+ unsigned int nr_succeeded;
+ nodemask_t allowed_mask = NODE_MASK_NONE;
+ struct migration_target_control mtc = {
+ /*
+ * Allocate from 'node', or fail quickly and quietly.
+ * When this happens, 'page' will likely just be discarded
+ * instead of migrated.
+ */
+ .gfp_mask = (GFP_HIGHUSER_MOVABLE & ~__GFP_RECLAIM) |
+ __GFP_NOWARN | __GFP_NOMEMALLOC | GFP_NOWAIT,
+ .nid = target_nid,
+ .nmask = &allowed_mask
+ };
+
+ if (pgdat->node_id == target_nid || target_nid == NUMA_NO_NODE)
+ return 0;
+
+ if (list_empty(migrate_folios))
+ return 0;
+
+ /* Migration ignores all cpuset and mempolicy settings */
+ migrate_pages(migrate_folios, alloc_demote_folio, NULL,
+ (unsigned long)&mtc, MIGRATE_ASYNC, MR_DAMON,
+ &nr_succeeded);
+
+ return nr_succeeded;
+}
+
+static unsigned int damon_pa_migrate_folio_list(struct list_head *folio_list,
+ struct pglist_data *pgdat,
+ int target_nid)
+{
+ unsigned int nr_migrated = 0;
+ struct folio *folio;
+ LIST_HEAD(ret_folios);
+ LIST_HEAD(migrate_folios);
+
+ while (!list_empty(folio_list)) {
+ struct folio *folio;
+
+ cond_resched();
+
+ folio = lru_to_folio(folio_list);
+ list_del(&folio->lru);
+
+ if (!folio_trylock(folio))
+ goto keep;
+
+ /* Relocate its contents to another node. */
+ list_add(&folio->lru, &migrate_folios);
+ folio_unlock(folio);
+ continue;
+keep:
+ list_add(&folio->lru, &ret_folios);
+ }
+ /* 'folio_list' is always empty here */
+
+ /* Migrate folios selected for migration */
+ nr_migrated += __damon_pa_migrate_folio_list(
+ &migrate_folios, pgdat, target_nid);
+ /*
+ * Folios that could not be migrated are still in @migrate_folios. Add
+ * those back on @folio_list
+ */
+ if (!list_empty(&migrate_folios))
+ list_splice_init(&migrate_folios, folio_list);
+
+ try_to_unmap_flush();
+
+ list_splice(&ret_folios, folio_list);
+
+ while (!list_empty(folio_list)) {
+ folio = lru_to_folio(folio_list);
+ list_del(&folio->lru);
+ folio_putback_lru(folio);
+ }
+
+ return nr_migrated;
+}
+
+static unsigned long damon_pa_migrate_pages(struct list_head *folio_list,
+ int target_nid)
+{
+ int nid;
+ unsigned long nr_migrated = 0;
+ LIST_HEAD(node_folio_list);
+ unsigned int noreclaim_flag;
+
+ if (list_empty(folio_list))
+ return nr_migrated;
+
+ noreclaim_flag = memalloc_noreclaim_save();
+
+ nid = folio_nid(lru_to_folio(folio_list));
+ do {
+ struct folio *folio = lru_to_folio(folio_list);
+
+ if (nid == folio_nid(folio)) {
+ list_move(&folio->lru, &node_folio_list);
+ continue;
+ }
+
+ nr_migrated += damon_pa_migrate_folio_list(&node_folio_list,
+ NODE_DATA(nid),
+ target_nid);
+ nid = folio_nid(lru_to_folio(folio_list));
+ } while (!list_empty(folio_list));
+
+ nr_migrated += damon_pa_migrate_folio_list(&node_folio_list,
+ NODE_DATA(nid),
+ target_nid);
+
+ memalloc_noreclaim_restore(noreclaim_flag);
+
+ return nr_migrated;
+}
+
+static unsigned long damon_pa_migrate(struct damon_region *r, struct damos *s)
+{
+ unsigned long addr, applied;
+ LIST_HEAD(folio_list);
+
+ for (addr = r->ar.start; addr < r->ar.end; addr += PAGE_SIZE) {
+ struct folio *folio = damon_get_folio(PHYS_PFN(addr));
+
+ if (!folio)
+ continue;
+
+ if (damos_pa_filter_out(s, folio))
+ goto put_folio;
+
+ if (!folio_isolate_lru(folio))
+ goto put_folio;
+ list_add(&folio->lru, &folio_list);
+put_folio:
+ folio_put(folio);
+ }
+ applied = damon_pa_migrate_pages(&folio_list, s->target_nid);
+ cond_resched();
+ return applied * PAGE_SIZE;
+}
+
+
static unsigned long damon_pa_apply_scheme(struct damon_ctx *ctx,
struct damon_target *t, struct damon_region *r,
struct damos *scheme)
@@ -336,6 +486,8 @@ static unsigned long damon_pa_apply_scheme(struct damon_ctx *ctx,
return damon_pa_mark_accessed(r, scheme);
case DAMOS_LRU_DEPRIO:
return damon_pa_deactivate_pages(r, scheme);
+ case DAMOS_MIGRATE_COLD:
+ return damon_pa_migrate(r, scheme);
case DAMOS_STAT:
break;
default:
@@ -356,6 +508,8 @@ static int damon_pa_scheme_score(struct damon_ctx *context,
return damon_hot_score(context, r, scheme);
case DAMOS_LRU_DEPRIO:
return damon_cold_score(context, r, scheme);
+ case DAMOS_MIGRATE_COLD:
+ return damon_cold_score(context, r, scheme);
default:
break;
}
diff --git a/mm/damon/sysfs-schemes.c b/mm/damon/sysfs-schemes.c
index 0632d28b67f8..880015d5b5ea 100644
--- a/mm/damon/sysfs-schemes.c
+++ b/mm/damon/sysfs-schemes.c
@@ -1458,6 +1458,7 @@ static const char * const damon_sysfs_damos_action_strs[] = {
"nohugepage",
"lru_prio",
"lru_deprio",
+ "migrate_cold",
"stat",
};
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [RFC PATCH v4 5/5] mm/damon/paddr: introduce DAMOS_MIGRATE_HOT action for promotion
2024-05-12 17:54 [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory SeongJae Park
` (3 preceding siblings ...)
2024-05-12 17:54 ` [RFC PATCH v4 4/5] mm/damon/paddr: introduce DAMOS_MIGRATE_COLD action for demotion SeongJae Park
@ 2024-05-12 17:54 ` SeongJae Park
2024-05-13 11:59 ` [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory Honggyu Kim
5 siblings, 0 replies; 10+ messages in thread
From: SeongJae Park @ 2024-05-12 17:54 UTC (permalink / raw)
Cc: Hyeongtak Ji, SeongJae Park, Andrew Morton, damon, linux-mm,
linux-kernel, Honggyu Kim
From: Hyeongtak Ji <hyeongtak.ji@sk.com>
This patch introduces DAMOS_MIGRATE_HOT action, which is similar to
DAMOS_MIGRATE_COLD, but proritizes hot pages.
It migrates pages inside the given region to the 'target_nid' NUMA node
in the sysfs.
Here is one of the example usage of this 'migrate_hot' action.
$ cd /sys/kernel/mm/damon/admin/kdamonds/<N>
$ cat contexts/<N>/schemes/<N>/action
migrate_hot
$ echo 0 > contexts/<N>/schemes/<N>/target_nid
$ echo commit > state
$ numactl -p 2 ./hot_cold 500M 600M &
$ numastat -c -p hot_cold
Per-node process memory usage (in MBs)
PID Node 0 Node 1 Node 2 Total
-------------- ------ ------ ------ -----
701 (hot_cold) 501 0 601 1101
Signed-off-by: Hyeongtak Ji <hyeongtak.ji@sk.com>
Signed-off-by: Honggyu Kim <honggyu.kim@sk.com>
Signed-off-by: SeongJae Park <sj@kernel.org>
---
include/linux/damon.h | 2 ++
mm/damon/paddr.c | 3 +++
mm/damon/sysfs-schemes.c | 1 +
3 files changed, 6 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 56714b6eb0d7..3d62d98d6359 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -105,6 +105,7 @@ struct damon_target {
* @DAMOS_NOHUGEPAGE: Call ``madvise()`` for the region with MADV_NOHUGEPAGE.
* @DAMOS_LRU_PRIO: Prioritize the region on its LRU lists.
* @DAMOS_LRU_DEPRIO: Deprioritize the region on its LRU lists.
+ * @DAMOS_MIGRATE_HOT: Migrate the regions prioritizing warmer regions.
* @DAMOS_MIGRATE_COLD: Migrate the regions prioritizing colder regions.
* @DAMOS_STAT: Do nothing but count the stat.
* @NR_DAMOS_ACTIONS: Total number of DAMOS actions
@@ -123,6 +124,7 @@ enum damos_action {
DAMOS_NOHUGEPAGE,
DAMOS_LRU_PRIO,
DAMOS_LRU_DEPRIO,
+ DAMOS_MIGRATE_HOT,
DAMOS_MIGRATE_COLD,
DAMOS_STAT, /* Do nothing but only record the stat */
NR_DAMOS_ACTIONS,
diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index a468792d9162..81163206e70c 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -486,6 +486,7 @@ static unsigned long damon_pa_apply_scheme(struct damon_ctx *ctx,
return damon_pa_mark_accessed(r, scheme);
case DAMOS_LRU_DEPRIO:
return damon_pa_deactivate_pages(r, scheme);
+ case DAMOS_MIGRATE_HOT:
case DAMOS_MIGRATE_COLD:
return damon_pa_migrate(r, scheme);
case DAMOS_STAT:
@@ -508,6 +509,8 @@ static int damon_pa_scheme_score(struct damon_ctx *context,
return damon_hot_score(context, r, scheme);
case DAMOS_LRU_DEPRIO:
return damon_cold_score(context, r, scheme);
+ case DAMOS_MIGRATE_HOT:
+ return damon_hot_score(context, r, scheme);
case DAMOS_MIGRATE_COLD:
return damon_cold_score(context, r, scheme);
default:
diff --git a/mm/damon/sysfs-schemes.c b/mm/damon/sysfs-schemes.c
index 880015d5b5ea..66fccfa776d7 100644
--- a/mm/damon/sysfs-schemes.c
+++ b/mm/damon/sysfs-schemes.c
@@ -1458,6 +1458,7 @@ static const char * const damon_sysfs_damos_action_strs[] = {
"nohugepage",
"lru_prio",
"lru_deprio",
+ "migrate_hot",
"migrate_cold",
"stat",
};
--
2.39.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory
2024-05-12 17:54 [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory SeongJae Park
` (4 preceding siblings ...)
2024-05-12 17:54 ` [RFC PATCH v4 5/5] mm/damon/paddr: introduce DAMOS_MIGRATE_HOT action for promotion SeongJae Park
@ 2024-05-13 11:59 ` Honggyu Kim
2024-05-15 16:18 ` SeongJae Park
5 siblings, 1 reply; 10+ messages in thread
From: Honggyu Kim @ 2024-05-13 11:59 UTC (permalink / raw)
To: SeongJae Park
Cc: Andrew Morton, Masami Hiramatsu, Mathieu Desnoyers,
Steven Rostedt, damon, linux-kernel, linux-mm, linux-trace-kernel,
Honggyu Kim, Hyeongtak Ji, Rakie Kim, kernel_team
Hi SeongJae,
Thanks very much for your work! It got delayed due to the priority
changes in my workplace for building another heterogeneous memory
allocator.
https://github.com/skhynix/hmsdk/wiki/hmalloc
On Sun, 12 May 2024 10:54:42 -0700 SeongJae Park <sj@kernel.org> wrote:
> There was an RFC IDEA "DAMOS-based Tiered-Memory Management" previously
> posted at [1].
>
> It says there is no implementation of the demote/promote DAMOS action
> are made. This RFC is about its implementation for physical address
> space.
>
> Changes from RFC v3
> (https://lore.kernel.org/20240405060858.2818-1-honggyu.kim@sk.com):
This link cannot be opened. I will share the link again here.
https://lore.kernel.org/all/20240405060858.2818-1-honggyu.kim@sk.com
> 0. updated from v3 and posted by SJ on behalf of Hunggyu under his
> approval.
> 1. Do not reuse damon_pa_pageout() and drop 'enum migration_mode'
> 2. Drop vmstat change
I haven't checked whether I can collect useful information without
vmstat, but the changes look good in general except for that.
> 3. Drop unnecessary page reference check
I will compare this patch series with my previous v3 patchset and get
back to you later maybe next week. Sorry, I will have another break
this week.
Thanks,
Honggyu
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory
2024-05-13 11:59 ` [RFC PATCH v4 0/5] DAMON based tiered memory management for CXL memory Honggyu Kim
@ 2024-05-15 16:18 ` SeongJae Park
0 siblings, 0 replies; 10+ messages in thread
From: SeongJae Park @ 2024-05-15 16:18 UTC (permalink / raw)
To: Honggyu Kim
Cc: SeongJae Park, Andrew Morton, Masami Hiramatsu, Mathieu Desnoyers,
Steven Rostedt, damon, linux-kernel, linux-mm, linux-trace-kernel,
Hyeongtak Ji, Rakie Kim, kernel_team
Hi Honggyu,
On Mon, 13 May 2024 20:59:15 +0900 Honggyu Kim <honggyu.kim@sk.com> wrote:
> Hi SeongJae,
>
> Thanks very much for your work! It got delayed due to the priority
> changes in my workplace for building another heterogeneous memory
> allocator.
> https://github.com/skhynix/hmsdk/wiki/hmalloc
No problem at all. We all work on our own schedule and nobody can chase/push
anybody :)
>
> On Sun, 12 May 2024 10:54:42 -0700 SeongJae Park <sj@kernel.org> wrote:
> > There was an RFC IDEA "DAMOS-based Tiered-Memory Management" previously
> > posted at [1].
> >
> > It says there is no implementation of the demote/promote DAMOS action
> > are made. This RFC is about its implementation for physical address
> > space.
> >
> > Changes from RFC v3
> > (https://lore.kernel.org/20240405060858.2818-1-honggyu.kim@sk.com):
>
> This link cannot be opened. I will share the link again here.
> https://lore.kernel.org/all/20240405060858.2818-1-honggyu.kim@sk.com
Thank you for checking the link! It's weird though, since I can open the link
on my Chrome browser.
>
> > 0. updated from v3 and posted by SJ on behalf of Hunggyu under his
> > approval.
> > 1. Do not reuse damon_pa_pageout() and drop 'enum migration_mode'
> > 2. Drop vmstat change
>
> I haven't checked whether I can collect useful information without
> vmstat, but the changes look good in general except for that.
I was thinking you could use DAMOS stat[1] for the schemes and assuming no
reply to it as an agreement, but maybe I should made it clear. Do you think
DAMOS stat cannot be used instead? If so, what would be the limitation of
DAMOS stat for your usage?
>
> > 3. Drop unnecessary page reference check
>
> I will compare this patch series with my previous v3 patchset and get
> back to you later maybe next week.
Thank you very much! Unless I get a good enough test setup and results from it
on my own or from others' help, your test result would be the last requirement
for dropping RFC from this patchset.
> Sorry, I will have another break this week.
No problem, I hope you to have nice break. Nobody can chase/push others. We
all do this work voluntarily for our own fun and profit, right? ;)
[1] https://lore.kernel.org/damon/20240405060858.2818-1-honggyu.kim@sk.com
Thanks,
SJ
>
> Thanks,
> Honggyu
^ permalink raw reply [flat|nested] 10+ messages in thread