2024-04-26 19:53:07

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 0/7] mm/damon: add a DAMOS filter type for page granularity access recheck

Changes from RFC v2
(https://lore.kernel.org/r/[email protected])
- Add documentation
- Add Tested-by: Honggyu Kim <[email protected]>
- Wordsmith commit messages

Changes from RFC v1
(https://lore.kernel.org/r/[email protected])
- Mark the folio as old if it was young
- Rename __damon_pa_young() to damon_folio_young_one()

DAMON provides its best-effort accuracy-overhead tradeoff under the
user-defined ranges of acceptable level of the monitoring accuracy and
overhead. A recent discussion for tiered memory management support from
DAMON[1] concluded that finding memory regions of specific access
pattern with low overhead despite of low accuracy via DAMON first, and
then double checking the access of the region again in a finer (e.g.,
page) granularity could be a useful strategy for some DAMOS schemes.

Add a new type of DAMOS filter, namely 'young' for such a case. It
checks each page of DAMOS target region is accessed since the last
check, and filters it out or in if 'matching' parameter is 'true' or
'false', respectively.

Because this is a filter type that applied in page granularity, the
support depends on DAMON operations set, similar to 'anon' and 'memcg'
DAMOS filter types. Implement the support on the DAMON operations set
for the physical address space, 'paddr', since one of the expected
usages[1] is based on the physical address space.

[1] https://lore.kernel.org/r/[email protected]

SeongJae Park (7):
mm/damon/paddr: implement damon_folio_young()
mm/damon/paddr: implement damon_folio_mkold()
mm/damon: add DAMOS filter type YOUNG
mm/damon/paddr: implement DAMOS filter type YOUNG
Docs/mm/damon/design: document 'young page' type DAMOS filter
Docs/admin-guide/mm/damon/usage: update for young page type DAMOS
filter
Docs/ABI/damon: update for 'youg page' type DAMOS filter

.../ABI/testing/sysfs-kernel-mm-damon | 6 +-
Documentation/admin-guide/mm/damon/usage.rst | 26 ++++----
Documentation/mm/damon/design.rst | 20 +++---
include/linux/damon.h | 2 +
mm/damon/paddr.c | 64 ++++++++++++-------
mm/damon/sysfs-schemes.c | 1 +
6 files changed, 70 insertions(+), 49 deletions(-)


base-commit: 4b4dd809460911d6c406bb45d2c627a9e5734468
--
2.39.2



2024-04-26 19:53:12

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 1/7] mm/damon/paddr: implement damon_folio_young()

damon_pa_young() receives physical address, get the folio covering the
address, and show if the folio is accessed since the last check. A
following commit will reuse the internal logic for checking access to a
given folio. To avoid duplication of the code, split the internal
logic. Also, change the rmap walker function's name from
__damon_pa_young() to damon_folio_young_one(), following the change of
the caller's name and the naming rule that more commonly used by other
rmap walkers.

Signed-off-by: SeongJae Park <[email protected]>
Tested-by: Honggyu Kim <[email protected]>
---
mm/damon/paddr.c | 32 +++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 5e6dc312072cd..25c3ba2a9eaf4 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -79,8 +79,8 @@ static void damon_pa_prepare_access_checks(struct damon_ctx *ctx)
}
}

-static bool __damon_pa_young(struct folio *folio, struct vm_area_struct *vma,
- unsigned long addr, void *arg)
+static bool damon_folio_young_one(struct folio *folio,
+ struct vm_area_struct *vma, unsigned long addr, void *arg)
{
bool *accessed = arg;
DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0);
@@ -111,38 +111,44 @@ static bool __damon_pa_young(struct folio *folio, struct vm_area_struct *vma,
return *accessed == false;
}

-static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz)
+static bool damon_folio_young(struct folio *folio)
{
- struct folio *folio = damon_get_folio(PHYS_PFN(paddr));
bool accessed = false;
struct rmap_walk_control rwc = {
.arg = &accessed,
- .rmap_one = __damon_pa_young,
+ .rmap_one = damon_folio_young_one,
.anon_lock = folio_lock_anon_vma_read,
};
bool need_lock;

- if (!folio)
- return false;
-
if (!folio_mapped(folio) || !folio_raw_mapping(folio)) {
if (folio_test_idle(folio))
- accessed = false;
+ return false;
else
- accessed = true;
- goto out;
+ return true;
}

need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
if (need_lock && !folio_trylock(folio))
- goto out;
+ return false;

rmap_walk(folio, &rwc);

if (need_lock)
folio_unlock(folio);

-out:
+ return accessed;
+}
+
+static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz)
+{
+ struct folio *folio = damon_get_folio(PHYS_PFN(paddr));
+ bool accessed;
+
+ if (!folio)
+ return false;
+
+ accessed = damon_folio_young(folio);
*folio_sz = folio_size(folio);
folio_put(folio);
return accessed;
--
2.39.2


2024-04-26 19:54:15

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 7/7] Docs/ABI/damon: update for 'youg page' type DAMOS filter

Update DAMON ABI document for the newly added DAMO filter type, 'young
page'.

Signed-off-by: SeongJae Park <[email protected]>
---
Documentation/ABI/testing/sysfs-kernel-mm-damon | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon
index dad4d5ffd7865..cef6e1d20b185 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -314,9 +314,9 @@ Date: Dec 2022
Contact: SeongJae Park <[email protected]>
Description: Writing to and reading from this file sets and gets the type of
the memory of the interest. 'anon' for anonymous pages,
- 'memcg' for specific memory cgroup, 'addr' for address range
- (an open-ended interval), or 'target' for DAMON monitoring
- target can be written and read.
+ 'memcg' for specific memory cgroup, 'young' for young pages,
+ 'addr' for address range (an open-ended interval), or 'target'
+ for DAMON monitoring target can be written and read.

What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/filters/<F>/memcg_path
Date: Dec 2022
--
2.39.2


2024-04-26 19:54:35

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 6/7] Docs/admin-guide/mm/damon/usage: update for young page type DAMOS filter

Update DAMON usage document for the newly added DAMOS filter type,
'young page'.

Signed-off-by: SeongJae Park <[email protected]>
---
Documentation/admin-guide/mm/damon/usage.rst | 26 ++++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
index 6fce035fdbf5c..69bc8fabf3781 100644
--- a/Documentation/admin-guide/mm/damon/usage.rst
+++ b/Documentation/admin-guide/mm/damon/usage.rst
@@ -410,19 +410,19 @@ in the numeric order.

Each filter directory contains six files, namely ``type``, ``matcing``,
``memcg_path``, ``addr_start``, ``addr_end``, and ``target_idx``. To ``type``
-file, you can write one of four special keywords: ``anon`` for anonymous pages,
-``memcg`` for specific memory cgroup, ``addr`` for specific address range (an
-open-ended interval), or ``target`` for specific DAMON monitoring target
-filtering. In case of the memory cgroup filtering, you can specify the memory
-cgroup of the interest by writing the path of the memory cgroup from the
-cgroups mount point to ``memcg_path`` file. In case of the address range
-filtering, you can specify the start and end address of the range to
-``addr_start`` and ``addr_end`` files, respectively. For the DAMON monitoring
-target filtering, you can specify the index of the target between the list of
-the DAMON context's monitoring targets list to ``target_idx`` file. You can
-write ``Y`` or ``N`` to ``matching`` file to filter out pages that does or does
-not match to the type, respectively. Then, the scheme's action will not be
-applied to the pages that specified to be filtered out.
+file, you can write one of five special keywords: ``anon`` for anonymous pages,
+``memcg`` for specific memory cgroup, ``young`` for young pages, ``addr`` for
+specific address range (an open-ended interval), or ``target`` for specific
+DAMON monitoring target filtering. In case of the memory cgroup filtering, you
+can specify the memory cgroup of the interest by writing the path of the memory
+cgroup from the cgroups mount point to ``memcg_path`` file. In case of the
+address range filtering, you can specify the start and end address of the range
+to ``addr_start`` and ``addr_end`` files, respectively. For the DAMON
+monitoring target filtering, you can specify the index of the target between
+the list of the DAMON context's monitoring targets list to ``target_idx`` file.
+You can write ``Y`` or ``N`` to ``matching`` file to filter out pages that does
+or does not match to the type, respectively. Then, the scheme's action will
+not be applied to the pages that specified to be filtered out.

For example, below restricts a DAMOS action to be applied to only non-anonymous
pages of all memory cgroups except ``/having_care_already``.::
--
2.39.2


2024-04-26 20:03:04

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 5/7] Docs/mm/damon/design: document 'young page' type DAMOS filter

Update DAMON design document for the newly added DAMOS filter type,
'young page'.

Signed-off-by: SeongJae Park <[email protected]>
---
Documentation/mm/damon/design.rst | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst
index 5620aab9b3850..f2baf617184d0 100644
--- a/Documentation/mm/damon/design.rst
+++ b/Documentation/mm/damon/design.rst
@@ -461,15 +461,17 @@ number of filters for each scheme. Each filter specifies the type of target
memory, and whether it should exclude the memory of the type (filter-out), or
all except the memory of the type (filter-in).

-Currently, anonymous page, memory cgroup, address range, and DAMON monitoring
-target type filters are supported by the feature. Some filter target types
-require additional arguments. The memory cgroup filter type asks users to
-specify the file path of the memory cgroup for the filter. The address range
-type asks the start and end addresses of the range. The DAMON monitoring
-target type asks the index of the target from the context's monitoring targets
-list. Hence, users can apply specific schemes to only anonymous pages,
-non-anonymous pages, pages of specific cgroups, all pages excluding those of
-specific cgroups, pages in specific address range, pages in specific DAMON
+Currently, anonymous page, memory cgroup, young page, address range, and DAMON
+monitoring target type filters are supported by the feature. Some filter
+target types require additional arguments. The memory cgroup filter type asks
+users to specify the file path of the memory cgroup for the filter. The
+address range type asks the start and end addresses of the range. The DAMON
+monitoring target type asks the index of the target from the context's
+monitoring targets list. Hence, users can apply specific schemes to only
+anonymous pages, non-anonymous pages, pages of specific cgroups, all pages
+excluding those of specific cgroups, pages that not accessed after the last
+access check from the scheme, pages that accessed after the last access check
+from the scheme, pages in specific address range, pages in specific DAMON
monitoring targets, and any combination of those.

To handle filters efficiently, the address range and DAMON monitoring target
--
2.39.2


2024-04-26 20:04:10

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 2/7] mm/damon/paddr: implement damon_folio_mkold()

damon_pa_mkold() receives physical address, get the folio covering the
address, and makes the folio as old. A following commit will reuse the
internal logic for marking a given folio as old. To avoid duplication
of the code, split the internal logic. Also, change the rmap walker
function's name from __damon_pa_mkold() to damon_folio_mkold_one(),
following the change of the caller's name and the naming rule that more
commonly used by other rmap walkers.

Signed-off-by: SeongJae Park <[email protected]>
Tested-by: Honggyu Kim <[email protected]>
---
mm/damon/paddr.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 25c3ba2a9eaf4..310b803c62779 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -16,8 +16,8 @@
#include "../internal.h"
#include "ops-common.h"

-static bool __damon_pa_mkold(struct folio *folio, struct vm_area_struct *vma,
- unsigned long addr, void *arg)
+static bool damon_folio_mkold_one(struct folio *folio,
+ struct vm_area_struct *vma, unsigned long addr, void *arg)
{
DEFINE_FOLIO_VMA_WALK(pvmw, folio, vma, addr, 0);

@@ -31,33 +31,38 @@ static bool __damon_pa_mkold(struct folio *folio, struct vm_area_struct *vma,
return true;
}

-static void damon_pa_mkold(unsigned long paddr)
+static void damon_folio_mkold(struct folio *folio)
{
- struct folio *folio = damon_get_folio(PHYS_PFN(paddr));
struct rmap_walk_control rwc = {
- .rmap_one = __damon_pa_mkold,
+ .rmap_one = damon_folio_mkold_one,
.anon_lock = folio_lock_anon_vma_read,
};
bool need_lock;

- if (!folio)
- return;
-
if (!folio_mapped(folio) || !folio_raw_mapping(folio)) {
folio_set_idle(folio);
- goto out;
+ return;
}

need_lock = !folio_test_anon(folio) || folio_test_ksm(folio);
if (need_lock && !folio_trylock(folio))
- goto out;
+ return;

rmap_walk(folio, &rwc);

if (need_lock)
folio_unlock(folio);

-out:
+}
+
+static void damon_pa_mkold(unsigned long paddr)
+{
+ struct folio *folio = damon_get_folio(PHYS_PFN(paddr));
+
+ if (!folio)
+ return;
+
+ damon_folio_mkold(folio);
folio_put(folio);
}

--
2.39.2


2024-04-26 20:04:40

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 4/7] mm/damon/paddr: implement DAMOS filter type YOUNG

DAMOS filter of type YOUNG is defined, but not yet implemented by any
DAMON operations set. Add the implementation on 'paddr', the DAMON
operations set for the physical address space.

Signed-off-by: SeongJae Park <[email protected]>
Tested-by: Honggyu Kim <[email protected]>
---
mm/damon/paddr.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 310b803c62779..5685ba485097d 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -214,6 +214,11 @@ static bool __damos_pa_filter_out(struct damos_filter *filter,
matched = filter->memcg_id == mem_cgroup_id(memcg);
rcu_read_unlock();
break;
+ case DAMOS_FILTER_TYPE_YOUNG:
+ matched = damon_folio_young(folio);
+ if (matched)
+ damon_folio_mkold(folio);
+ break;
default:
break;
}
--
2.39.2


2024-04-26 20:05:53

by SeongJae Park

[permalink] [raw]
Subject: [PATCH 3/7] mm/damon: add DAMOS filter type YOUNG

Define yet another DAMOS filter type, YOUNG. Like anon and memcg, the
type of filter will be applied to each page in the memory region, and
see if the page is accessed since the last check. Based on the
'matching' parameter, the page is filtered out or in.

Note that this commit is adding only the type definition. The
implementation should be made by DAMON operations sets. A commit for
the implementation on 'paddr' DAMON operations set will follow.

Signed-off-by: SeongJae Park <[email protected]>
Tested-by: Honggyu Kim <[email protected]>
---
include/linux/damon.h | 2 ++
mm/damon/sysfs-schemes.c | 1 +
2 files changed, 3 insertions(+)

diff --git a/include/linux/damon.h b/include/linux/damon.h
index 886d07294f4e7..f7da65e1ac041 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -297,6 +297,7 @@ struct damos_stat {
* enum damos_filter_type - Type of memory for &struct damos_filter
* @DAMOS_FILTER_TYPE_ANON: Anonymous pages.
* @DAMOS_FILTER_TYPE_MEMCG: Specific memcg's pages.
+ * @DAMOS_FILTER_TYPE_YOUNG: Recently accessed pages.
* @DAMOS_FILTER_TYPE_ADDR: Address range.
* @DAMOS_FILTER_TYPE_TARGET: Data Access Monitoring target.
* @NR_DAMOS_FILTER_TYPES: Number of filter types.
@@ -315,6 +316,7 @@ struct damos_stat {
enum damos_filter_type {
DAMOS_FILTER_TYPE_ANON,
DAMOS_FILTER_TYPE_MEMCG,
+ DAMOS_FILTER_TYPE_YOUNG,
DAMOS_FILTER_TYPE_ADDR,
DAMOS_FILTER_TYPE_TARGET,
NR_DAMOS_FILTER_TYPES,
diff --git a/mm/damon/sysfs-schemes.c b/mm/damon/sysfs-schemes.c
index 53a90ac678fb9..bea5bc52846a6 100644
--- a/mm/damon/sysfs-schemes.c
+++ b/mm/damon/sysfs-schemes.c
@@ -343,6 +343,7 @@ static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
static const char * const damon_sysfs_scheme_filter_type_strs[] = {
"anon",
"memcg",
+ "young",
"addr",
"target",
};
--
2.39.2