| From: SeongJae Park <sj@kernel.org> |
| Subject: selftests/damon: implement a python module for test-purpose DAMON sysfs controls |
| Date: Tue, 12 Dec 2023 19:48:06 +0000 |
| |
| Patch series "selftests/damon: add Python-written DAMON functionality |
| tests", v2. |
| |
| DAMON exports most of its functionality via its sysfs interface. Hence |
| most DAMON functionality tests could be implemented using the interface. |
| However, because the interfaces require simple but multiple operations for |
| many controls, writing all such tests from the scratch could be repetitive |
| and time consuming. |
| |
| Implement a minimum DAMON sysfs control module, and a couple of DAMON |
| functionality tests using the control module. The first test is for |
| ensuring minimum accuracy of data access monitoring, and the second test |
| is for finding if a previously found and fixed bug is introduced again. |
| |
| Note that the DAMON sysfs control module is only for avoiding duplicating |
| code in tests. For convenient and general control of DAMON, users should |
| use DAMON user-space tools that developed for the purpose, such as |
| damo[1]. |
| |
| [1] https://github.com/damonitor/damo |
| |
| Patches Sequence |
| ---------------- |
| |
| This patchset is constructed with five patches. The first three patches |
| implement a Python-written test implementation-purpose DAMON sysfs control |
| module. The implementation is incrementally done in the sequence of the |
| basic data structure (first patch) first, kdamonds start command (second |
| patch) next, and finally DAMOS tried bytes update command (third patch). |
| |
| Then two patches for implementing selftests using the module follows. The |
| fourth patch implements a basic functionality test of DAMON for working |
| set estimation accuracy. Finally, the fifth patch implements a corner |
| case test for a previously found bug. |
| |
| |
| This patch (of 5): |
| |
| Implement a python module for DAMON sysfs controls. The module is aimed |
| to be useful for writing DAMON functionality tests in future. |
| Nonetheless, this module is only representing a subset of DAMON sysfs |
| files. Following commits will implement more DAMON sysfs controls. |
| |
| Link: https://lkml.kernel.org/r/20231212194810.54457-1-sj@kernel.org |
| Link: https://lkml.kernel.org/r/20231212194810.54457-2-sj@kernel.org |
| Signed-off-by: SeongJae Park <sj@kernel.org> |
| Cc: Shuah Khan <shuah@kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| tools/testing/selftests/damon/_damon_sysfs.py | 102 ++++++++++++++++ |
| 1 file changed, 102 insertions(+) |
| |
| --- /dev/null |
| +++ a/tools/testing/selftests/damon/_damon_sysfs.py |
| @@ -0,0 +1,102 @@ |
| +# SPDX-License-Identifier: GPL-2.0 |
| + |
| +class DamosAccessPattern: |
| + size = None |
| + nr_accesses = None |
| + age = None |
| + scheme = None |
| + |
| + def __init__(self, size=None, nr_accesses=None, age=None): |
| + self.size = size |
| + self.nr_accesses = nr_accesses |
| + self.age = age |
| + |
| + if self.size == None: |
| + self.size = [0, 2**64 - 1] |
| + if self.nr_accesses == None: |
| + self.nr_accesses = [0, 2**64 - 1] |
| + if self.age == None: |
| + self.age = [0, 2**64 - 1] |
| + |
| +class Damos: |
| + action = None |
| + access_pattern = None |
| + # todo: Support quotas, watermarks, stats, tried_regions |
| + idx = None |
| + context = None |
| + |
| + def __init__(self, action='stat', access_pattern=DamosAccessPattern()): |
| + self.action = action |
| + self.access_pattern = access_pattern |
| + self.access_pattern.scheme = self |
| + |
| +class DamonTarget: |
| + pid = None |
| + # todo: Support target regions if test is made |
| + idx = None |
| + context = None |
| + |
| + def __init__(self, pid): |
| + self.pid = pid |
| + |
| +class DamonAttrs: |
| + sample_us = None |
| + aggr_us = None |
| + update_us = None |
| + min_nr_regions = None |
| + max_nr_regions = None |
| + context = None |
| + |
| + def __init__(self, sample_us=5000, aggr_us=100000, update_us=1000000, |
| + min_nr_regions=10, max_nr_regions=1000): |
| + self.sample_us = sample_us |
| + self.aggr_us = aggr_us |
| + self.update_us = update_us |
| + self.min_nr_regions = min_nr_regions |
| + self.max_nr_regions = max_nr_regions |
| + |
| +class DamonCtx: |
| + ops = None |
| + monitoring_attrs = None |
| + targets = None |
| + schemes = None |
| + kdamond = None |
| + idx = None |
| + |
| + def __init__(self, ops='paddr', monitoring_attrs=DamonAttrs(), targets=[], |
| + schemes=[]): |
| + self.ops = ops |
| + self.monitoring_attrs = monitoring_attrs |
| + self.monitoring_attrs.context = self |
| + |
| + self.targets = targets |
| + for idx, target in enumerate(self.targets): |
| + target.idx = idx |
| + target.context = self |
| + |
| + self.schemes = schemes |
| + for idx, scheme in enumerate(self.schemes): |
| + scheme.idx = idx |
| + scheme.context = self |
| + |
| +class Kdamond: |
| + state = None |
| + pid = None |
| + contexts = None |
| + idx = None # index of this kdamond between siblings |
| + kdamonds = None # parent |
| + |
| + def __init__(self, contexts=[]): |
| + self.contexts = contexts |
| + for idx, context in enumerate(self.contexts): |
| + context.idx = idx |
| + context.kdamond = self |
| + |
| +class Kdamonds: |
| + kdamonds = [] |
| + |
| + def __init__(self, kdamonds=[]): |
| + self.kdamonds = kdamonds |
| + for idx, kdamond in enumerate(self.kdamonds): |
| + kdamond.idx = idx |
| + kdamond.kdamonds = self |
| _ |