selftests/damon: implement a python module for test-purpose DAMON sysfs controls

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>
This commit is contained in:
SeongJae Park 2023-12-12 19:48:06 +00:00 committed by Andrew Morton
parent d5f6057cf0
commit 306abb63a8

View File

@ -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