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>
2023-12-12 19:48:06 +00:00
|
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
import os
|
|
|
|
|
2024-05-03 11:03:11 -07:00
|
|
|
ksft_skip=4
|
|
|
|
|
|
|
|
sysfs_root = None
|
|
|
|
with open('/proc/mounts', 'r') as f:
|
|
|
|
for line in f:
|
|
|
|
dev_name, mount_point, dev_fs = line.split()[:3]
|
|
|
|
if dev_fs == 'sysfs':
|
|
|
|
sysfs_root = '%s/kernel/mm/damon/admin' % mount_point
|
|
|
|
break
|
|
|
|
if sysfs_root is None:
|
|
|
|
print('Seems sysfs not mounted?')
|
|
|
|
exit(ksft_skip)
|
2023-12-12 19:48:07 +00:00
|
|
|
|
2025-05-31 17:39:37 +08:00
|
|
|
if not os.path.exists(sysfs_root):
|
|
|
|
print('Seems DAMON disabled?')
|
|
|
|
exit(ksft_skip)
|
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
def write_file(path, string):
|
|
|
|
"Returns error string if failed, or None otherwise"
|
|
|
|
string = '%s' % string
|
|
|
|
try:
|
|
|
|
with open(path, 'w') as f:
|
|
|
|
f.write(string)
|
|
|
|
except Exception as e:
|
|
|
|
return '%s' % e
|
|
|
|
return None
|
|
|
|
|
|
|
|
def read_file(path):
|
|
|
|
'''Returns the read content and error string. The read content is None if
|
|
|
|
the reading failed'''
|
|
|
|
try:
|
|
|
|
with open(path, 'r') as f:
|
|
|
|
return f.read(), None
|
|
|
|
except Exception as e:
|
|
|
|
return None, '%s' % e
|
|
|
|
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
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
|
|
|
|
|
2024-05-03 11:03:12 -07:00
|
|
|
if self.size is None:
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
self.size = [0, 2**64 - 1]
|
2024-05-03 11:03:12 -07:00
|
|
|
if self.nr_accesses is None:
|
2025-07-20 10:16:38 -07:00
|
|
|
self.nr_accesses = [0, 2**32 - 1]
|
2024-05-03 11:03:12 -07:00
|
|
|
if self.age is None:
|
2025-07-20 10:16:38 -07:00
|
|
|
self.age = [0, 2**32 - 1]
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.scheme.sysfs_dir(), 'access_pattern')
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'sz', 'min'), self.size[0])
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'sz', 'max'), self.size[1])
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'nr_accesses', 'min'),
|
|
|
|
self.nr_accesses[0])
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'nr_accesses', 'max'),
|
|
|
|
self.nr_accesses[1])
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'age', 'min'), self.age[0])
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'age', 'max'), self.age[1])
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
2024-05-02 10:27:17 -07:00
|
|
|
qgoal_metric_user_input = 'user_input'
|
|
|
|
qgoal_metric_some_mem_psi_us = 'some_mem_psi_us'
|
|
|
|
qgoal_metrics = [qgoal_metric_user_input, qgoal_metric_some_mem_psi_us]
|
|
|
|
|
|
|
|
class DamosQuotaGoal:
|
|
|
|
metric = None
|
|
|
|
target_value = None
|
|
|
|
current_value = None
|
2025-07-20 10:16:35 -07:00
|
|
|
nid = None
|
2024-05-02 10:27:17 -07:00
|
|
|
effective_bytes = None
|
|
|
|
quota = None # owner quota
|
|
|
|
idx = None
|
|
|
|
|
2025-07-20 10:16:35 -07:00
|
|
|
def __init__(self, metric, target_value=10000, current_value=0, nid=0):
|
2024-05-02 10:27:17 -07:00
|
|
|
self.metric = metric
|
|
|
|
self.target_value = target_value
|
|
|
|
self.current_value = current_value
|
2025-07-20 10:16:35 -07:00
|
|
|
self.nid = nid
|
2024-05-02 10:27:17 -07:00
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.quota.sysfs_dir(), 'goals', '%d' % self.idx)
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'target_metric'),
|
|
|
|
self.metric)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'target_value'),
|
|
|
|
self.target_value)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'current_value'),
|
|
|
|
self.current_value)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
2025-07-20 10:16:35 -07:00
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'nid'), self.nid)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
|
2024-05-02 10:27:17 -07:00
|
|
|
return None
|
|
|
|
|
2024-02-07 12:31:27 -08:00
|
|
|
class DamosQuota:
|
|
|
|
sz = None # size quota, in bytes
|
|
|
|
ms = None # time quota
|
2024-05-02 10:27:17 -07:00
|
|
|
goals = None # quota goals
|
2024-02-07 12:31:27 -08:00
|
|
|
reset_interval_ms = None # quota reset interval
|
2025-07-20 10:16:34 -07:00
|
|
|
weight_sz_permil = None
|
|
|
|
weight_nr_accesses_permil = None
|
|
|
|
weight_age_permil = None
|
2024-02-07 12:31:27 -08:00
|
|
|
scheme = None # owner scheme
|
|
|
|
|
2025-07-20 10:16:34 -07:00
|
|
|
def __init__(self, sz=0, ms=0, goals=None, reset_interval_ms=0,
|
|
|
|
weight_sz_permil=0, weight_nr_accesses_permil=0,
|
|
|
|
weight_age_permil=0):
|
2024-02-07 12:31:27 -08:00
|
|
|
self.sz = sz
|
|
|
|
self.ms = ms
|
|
|
|
self.reset_interval_ms = reset_interval_ms
|
2025-07-20 10:16:34 -07:00
|
|
|
self.weight_sz_permil = weight_sz_permil
|
|
|
|
self.weight_nr_accesses_permil = weight_nr_accesses_permil
|
|
|
|
self.weight_age_permil = weight_age_permil
|
2024-05-02 10:27:17 -07:00
|
|
|
self.goals = goals if goals is not None else []
|
|
|
|
for idx, goal in enumerate(self.goals):
|
|
|
|
goal.idx = idx
|
|
|
|
goal.quota = self
|
2024-02-07 12:31:27 -08:00
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.scheme.sysfs_dir(), 'quotas')
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'bytes'), self.sz)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2024-02-07 12:31:27 -08:00
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'ms'), self.ms)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2024-02-07 12:31:27 -08:00
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'reset_interval_ms'),
|
|
|
|
self.reset_interval_ms)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2024-02-07 12:31:27 -08:00
|
|
|
return err
|
|
|
|
|
2025-07-20 10:16:34 -07:00
|
|
|
err = write_file(os.path.join(
|
|
|
|
self.sysfs_dir(), 'weights', 'sz_permil'), self.weight_sz_permil)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(
|
|
|
|
self.sysfs_dir(), 'weights', 'nr_accesses_permil'),
|
|
|
|
self.weight_nr_accesses_permil)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(
|
|
|
|
self.sysfs_dir(), 'weights', 'age_permil'), self.weight_age_permil)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
|
2024-05-02 10:27:17 -07:00
|
|
|
nr_goals_file = os.path.join(self.sysfs_dir(), 'goals', 'nr_goals')
|
|
|
|
content, err = read_file(nr_goals_file)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
if int(content) != len(self.goals):
|
|
|
|
err = write_file(nr_goals_file, len(self.goals))
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
for goal in self.goals:
|
|
|
|
err = goal.stage()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
return None
|
|
|
|
|
2025-07-20 10:16:31 -07:00
|
|
|
class DamosWatermarks:
|
|
|
|
metric = None
|
|
|
|
interval = None
|
|
|
|
high = None
|
|
|
|
mid = None
|
|
|
|
low = None
|
|
|
|
scheme = None # owner scheme
|
|
|
|
|
|
|
|
def __init__(self, metric='none', interval=0, high=0, mid=0, low=0):
|
|
|
|
self.metric = metric
|
|
|
|
self.interval = interval
|
|
|
|
self.high = high
|
|
|
|
self.mid = mid
|
|
|
|
self.low = low
|
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.scheme.sysfs_dir(), 'watermarks')
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'metric'), self.metric)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'interval_us'),
|
|
|
|
self.interval)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'high'), self.high)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'mid'), self.mid)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'low'), self.low)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
|
2025-07-20 10:16:32 -07:00
|
|
|
class DamosFilter:
|
|
|
|
type_ = None
|
|
|
|
matching = None
|
|
|
|
allow = None
|
|
|
|
memcg_path = None
|
|
|
|
addr_start = None
|
|
|
|
addr_end = None
|
|
|
|
target_idx = None
|
|
|
|
min_ = None
|
|
|
|
max_ = None
|
|
|
|
idx = None
|
|
|
|
filters = None # owner filters
|
|
|
|
|
|
|
|
def __init__(self, type_='anon', matching=False, allow=False,
|
|
|
|
memcg_path='', addr_start=0, addr_end=0, target_idx=0, min_=0,
|
|
|
|
max_=0):
|
|
|
|
self.type_ = type_
|
|
|
|
self.matching = matching
|
|
|
|
self.allow = allow
|
|
|
|
self.memcg_path = memcg_path,
|
|
|
|
self.addr_start = addr_start
|
|
|
|
self.addr_end = addr_end
|
|
|
|
self.target_idx = target_idx
|
|
|
|
self.min_ = min_
|
|
|
|
self.max_ = max_
|
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.filters.sysfs_dir(), '%d' % self.idx)
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'type'), self.type_)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'matching'),
|
|
|
|
self.matching)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'allow'), self.allow)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'memcg_path'),
|
|
|
|
self.memcg_path)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'addr_start'),
|
|
|
|
self.addr_start)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'addr_end'),
|
|
|
|
self.addr_end)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'damon_target_idx'),
|
|
|
|
self.target_idx)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'min'), self.min_)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'max'), self.max_)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
return None
|
|
|
|
|
|
|
|
class DamosFilters:
|
|
|
|
name = None
|
|
|
|
filters = None
|
|
|
|
scheme = None # owner scheme
|
|
|
|
|
|
|
|
def __init__(self, name, filters=[]):
|
|
|
|
self.name = name
|
|
|
|
self.filters = filters
|
|
|
|
for idx, filter_ in enumerate(self.filters):
|
|
|
|
filter_.idx = idx
|
|
|
|
filter_.filters = self
|
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.scheme.sysfs_dir(), self.name)
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'nr_filters'),
|
|
|
|
len(self.filters))
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
for filter_ in self.filters:
|
|
|
|
err = filter_.stage()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
return None
|
|
|
|
|
2025-07-20 10:16:36 -07:00
|
|
|
class DamosDest:
|
|
|
|
id = None
|
|
|
|
weight = None
|
|
|
|
idx = None
|
|
|
|
dests = None # owner dests
|
|
|
|
|
|
|
|
def __init__(self, id=0, weight=0):
|
|
|
|
self.id = id
|
|
|
|
self.weight = weight
|
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.dests.sysfs_dir(), '%d' % self.idx)
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'id'), self.id)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'weight'), self.weight)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
return None
|
|
|
|
|
|
|
|
class DamosDests:
|
|
|
|
dests = None
|
|
|
|
scheme = None # owner scheme
|
|
|
|
|
|
|
|
def __init__(self, dests=[]):
|
|
|
|
self.dests = dests
|
|
|
|
for idx, dest in enumerate(self.dests):
|
|
|
|
dest.idx = idx
|
|
|
|
dest.dests = self
|
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.scheme.sysfs_dir(), 'dests')
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'nr_dests'),
|
|
|
|
len(self.dests))
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
for dest in self.dests:
|
|
|
|
err = dest.stage()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
return None
|
|
|
|
|
2024-02-07 12:31:28 -08:00
|
|
|
class DamosStats:
|
|
|
|
nr_tried = None
|
|
|
|
sz_tried = None
|
|
|
|
nr_applied = None
|
|
|
|
sz_applied = None
|
|
|
|
qt_exceeds = None
|
|
|
|
|
|
|
|
def __init__(self, nr_tried, sz_tried, nr_applied, sz_applied, qt_exceeds):
|
|
|
|
self.nr_tried = nr_tried
|
|
|
|
self.sz_tried = sz_tried
|
|
|
|
self.nr_applied = nr_applied
|
|
|
|
self.sz_applied = sz_applied
|
|
|
|
self.qt_exceeds = qt_exceeds
|
|
|
|
|
2024-06-25 11:05:32 -07:00
|
|
|
class DamosTriedRegion:
|
|
|
|
def __init__(self, start, end, nr_accesses, age):
|
|
|
|
self.start = start
|
|
|
|
self.end = end
|
|
|
|
self.nr_accesses = nr_accesses
|
|
|
|
self.age = age
|
|
|
|
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
class Damos:
|
|
|
|
action = None
|
|
|
|
access_pattern = None
|
2024-02-07 12:31:27 -08:00
|
|
|
quota = None
|
2025-07-20 10:16:31 -07:00
|
|
|
watermarks = None
|
2025-07-20 10:16:32 -07:00
|
|
|
core_filters = None
|
|
|
|
ops_filters = None
|
|
|
|
filters = None
|
2024-02-07 12:31:29 -08:00
|
|
|
apply_interval_us = None
|
2025-07-20 10:16:37 -07:00
|
|
|
target_nid = None
|
2025-07-20 10:16:36 -07:00
|
|
|
dests = None
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
idx = None
|
|
|
|
context = None
|
2023-12-12 19:48:08 +00:00
|
|
|
tried_bytes = None
|
2024-02-07 12:31:28 -08:00
|
|
|
stats = None
|
2024-06-25 11:05:32 -07:00
|
|
|
tried_regions = None
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
|
2024-02-07 12:31:27 -08:00
|
|
|
def __init__(self, action='stat', access_pattern=DamosAccessPattern(),
|
2025-07-20 10:16:31 -07:00
|
|
|
quota=DamosQuota(), watermarks=DamosWatermarks(),
|
2025-07-20 10:16:37 -07:00
|
|
|
core_filters=[], ops_filters=[], filters=[], target_nid=0,
|
2025-07-20 10:16:36 -07:00
|
|
|
dests=DamosDests(), apply_interval_us=0):
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
self.action = action
|
|
|
|
self.access_pattern = access_pattern
|
|
|
|
self.access_pattern.scheme = self
|
2024-02-07 12:31:27 -08:00
|
|
|
self.quota = quota
|
|
|
|
self.quota.scheme = self
|
2025-07-20 10:16:31 -07:00
|
|
|
self.watermarks = watermarks
|
|
|
|
self.watermarks.scheme = self
|
2025-07-20 10:16:32 -07:00
|
|
|
|
|
|
|
self.core_filters = DamosFilters(name='core_filters',
|
|
|
|
filters=core_filters)
|
|
|
|
self.core_filters.scheme = self
|
|
|
|
self.ops_filters = DamosFilters(name='ops_filters',
|
|
|
|
filters=ops_filters)
|
|
|
|
self.ops_filters.scheme = self
|
|
|
|
self.filters = DamosFilters(name='filters', filters=filters)
|
|
|
|
self.filters.scheme = self
|
|
|
|
|
2025-07-20 10:16:37 -07:00
|
|
|
self.target_nid = target_nid
|
2025-07-20 10:16:36 -07:00
|
|
|
self.dests = dests
|
|
|
|
self.dests.scheme = self
|
|
|
|
|
2024-02-07 12:31:29 -08:00
|
|
|
self.apply_interval_us = apply_interval_us
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(
|
|
|
|
self.context.sysfs_dir(), 'schemes', '%d' % self.idx)
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'action'), self.action)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = self.access_pattern.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
2024-02-07 12:31:29 -08:00
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'apply_interval_us'),
|
|
|
|
'%d' % self.apply_interval_us)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2024-02-07 12:31:29 -08:00
|
|
|
return err
|
|
|
|
|
2024-02-07 12:31:27 -08:00
|
|
|
err = self.quota.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
2025-07-20 10:16:31 -07:00
|
|
|
err = self.watermarks.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
2025-07-20 10:16:32 -07:00
|
|
|
err = self.core_filters.stage()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = self.ops_filters.stage()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = self.filters.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
2025-07-20 10:16:37 -07:00
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'target_nid'), '%d' %
|
|
|
|
self.target_nid)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
|
2025-07-20 10:16:36 -07:00
|
|
|
err = self.dests.stage()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
class DamonTarget:
|
|
|
|
pid = None
|
|
|
|
# todo: Support target regions if test is made
|
|
|
|
idx = None
|
|
|
|
context = None
|
|
|
|
|
|
|
|
def __init__(self, pid):
|
|
|
|
self.pid = pid
|
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(
|
|
|
|
self.context.sysfs_dir(), 'targets', '%d' % self.idx)
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'regions', 'nr_regions'), '0')
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
return write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'pid_target'), self.pid)
|
|
|
|
|
2025-07-20 10:16:33 -07:00
|
|
|
class IntervalsGoal:
|
|
|
|
access_bp = None
|
|
|
|
aggrs = None
|
|
|
|
min_sample_us = None
|
|
|
|
max_sample_us = None
|
|
|
|
attrs = None # owner DamonAttrs
|
|
|
|
|
|
|
|
def __init__(self, access_bp=0, aggrs=0, min_sample_us=0, max_sample_us=0):
|
|
|
|
self.access_bp = access_bp
|
|
|
|
self.aggrs = aggrs
|
|
|
|
self.min_sample_us = min_sample_us
|
|
|
|
self.max_sample_us = max_sample_us
|
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.attrs.interval_sysfs_dir(), 'intervals_goal')
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'access_bp'), self.access_bp)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'aggrs'), self.aggrs)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'min_sample_us'),
|
|
|
|
self.min_sample_us)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'max_sample_us'),
|
|
|
|
self.max_sample_us)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
return None
|
|
|
|
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
class DamonAttrs:
|
|
|
|
sample_us = None
|
|
|
|
aggr_us = None
|
2025-07-20 10:16:33 -07:00
|
|
|
intervals_goal = None
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
update_us = None
|
|
|
|
min_nr_regions = None
|
|
|
|
max_nr_regions = None
|
|
|
|
context = None
|
|
|
|
|
2025-07-20 10:16:33 -07:00
|
|
|
def __init__(self, sample_us=5000, aggr_us=100000,
|
|
|
|
intervals_goal=IntervalsGoal(), update_us=1000000,
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
min_nr_regions=10, max_nr_regions=1000):
|
|
|
|
self.sample_us = sample_us
|
|
|
|
self.aggr_us = aggr_us
|
2025-07-20 10:16:33 -07:00
|
|
|
self.intervals_goal = intervals_goal
|
|
|
|
self.intervals_goal.attrs = self
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
self.update_us = update_us
|
|
|
|
self.min_nr_regions = min_nr_regions
|
|
|
|
self.max_nr_regions = max_nr_regions
|
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
def interval_sysfs_dir(self):
|
|
|
|
return os.path.join(self.context.sysfs_dir(), 'monitoring_attrs',
|
|
|
|
'intervals')
|
|
|
|
|
|
|
|
def nr_regions_range_sysfs_dir(self):
|
|
|
|
return os.path.join(self.context.sysfs_dir(), 'monitoring_attrs',
|
|
|
|
'nr_regions')
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(os.path.join(self.interval_sysfs_dir(), 'sample_us'),
|
|
|
|
self.sample_us)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.interval_sysfs_dir(), 'aggr_us'),
|
|
|
|
self.aggr_us)
|
2025-07-20 10:16:33 -07:00
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = self.intervals_goal.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.interval_sysfs_dir(), 'update_us'),
|
|
|
|
self.update_us)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.nr_regions_range_sysfs_dir(), 'min'),
|
|
|
|
self.min_nr_regions)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.nr_regions_range_sysfs_dir(), 'max'),
|
|
|
|
self.max_nr_regions)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
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
|
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.kdamond.sysfs_dir(), 'contexts',
|
|
|
|
'%d' % self.idx)
|
|
|
|
|
|
|
|
def stage(self):
|
|
|
|
err = write_file(
|
|
|
|
os.path.join(self.sysfs_dir(), 'operations'), self.ops)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = self.monitoring_attrs.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
|
|
|
nr_targets_file = os.path.join(
|
|
|
|
self.sysfs_dir(), 'targets', 'nr_targets')
|
|
|
|
content, err = read_file(nr_targets_file)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
if int(content) != len(self.targets):
|
|
|
|
err = write_file(nr_targets_file, '%d' % len(self.targets))
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
for target in self.targets:
|
|
|
|
err = target.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
|
|
|
nr_schemes_file = os.path.join(
|
|
|
|
self.sysfs_dir(), 'schemes', 'nr_schemes')
|
|
|
|
content, err = read_file(nr_schemes_file)
|
2024-05-03 11:03:10 -07:00
|
|
|
if err is not None:
|
|
|
|
return err
|
2023-12-12 19:48:07 +00:00
|
|
|
if int(content) != len(self.schemes):
|
|
|
|
err = write_file(nr_schemes_file, '%d' % len(self.schemes))
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
for scheme in self.schemes:
|
|
|
|
err = scheme.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
return None
|
|
|
|
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
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
|
|
|
|
|
2023-12-12 19:48:07 +00:00
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(self.kdamonds.sysfs_dir(), '%d' % self.idx)
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
nr_contexts_file = os.path.join(self.sysfs_dir(),
|
|
|
|
'contexts', 'nr_contexts')
|
|
|
|
content, err = read_file(nr_contexts_file)
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
if int(content) != len(self.contexts):
|
|
|
|
err = write_file(nr_contexts_file, '%d' % len(self.contexts))
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
|
|
|
for context in self.contexts:
|
|
|
|
err = context.stage()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'state'), 'on')
|
2025-06-28 09:04:24 -07:00
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
self.pid, err = read_file(os.path.join(self.sysfs_dir(), 'pid'))
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
|
2024-06-25 11:05:35 -07:00
|
|
|
def stop(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'state'), 'off')
|
|
|
|
return err
|
|
|
|
|
2024-06-25 11:05:32 -07:00
|
|
|
def update_schemes_tried_regions(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'state'),
|
|
|
|
'update_schemes_tried_regions')
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
for context in self.contexts:
|
|
|
|
for scheme in context.schemes:
|
|
|
|
tried_regions = []
|
|
|
|
tried_regions_dir = os.path.join(
|
|
|
|
scheme.sysfs_dir(), 'tried_regions')
|
2025-05-12 17:27:14 -07:00
|
|
|
region_indices = []
|
2024-06-25 11:05:32 -07:00
|
|
|
for filename in os.listdir(
|
|
|
|
os.path.join(scheme.sysfs_dir(), 'tried_regions')):
|
|
|
|
tried_region_dir = os.path.join(tried_regions_dir, filename)
|
|
|
|
if not os.path.isdir(tried_region_dir):
|
|
|
|
continue
|
2025-05-12 17:27:14 -07:00
|
|
|
region_indices.append(int(filename))
|
|
|
|
for region_idx in sorted(region_indices):
|
|
|
|
tried_region_dir = os.path.join(tried_regions_dir,
|
|
|
|
'%d' % region_idx)
|
2024-06-25 11:05:32 -07:00
|
|
|
region_values = []
|
|
|
|
for f in ['start', 'end', 'nr_accesses', 'age']:
|
|
|
|
content, err = read_file(
|
|
|
|
os.path.join(tried_region_dir, f))
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
region_values.append(int(content))
|
|
|
|
tried_regions.append(DamosTriedRegion(*region_values))
|
|
|
|
scheme.tried_regions = tried_regions
|
|
|
|
|
2023-12-12 19:48:08 +00:00
|
|
|
def update_schemes_tried_bytes(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'state'),
|
|
|
|
'update_schemes_tried_bytes')
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:08 +00:00
|
|
|
return err
|
|
|
|
for context in self.contexts:
|
|
|
|
for scheme in context.schemes:
|
|
|
|
content, err = read_file(os.path.join(scheme.sysfs_dir(),
|
|
|
|
'tried_regions', 'total_bytes'))
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:08 +00:00
|
|
|
return err
|
|
|
|
scheme.tried_bytes = int(content)
|
|
|
|
|
2024-02-07 12:31:28 -08:00
|
|
|
def update_schemes_stats(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'state'),
|
|
|
|
'update_schemes_stats')
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2024-02-07 12:31:28 -08:00
|
|
|
return err
|
|
|
|
for context in self.contexts:
|
|
|
|
for scheme in context.schemes:
|
|
|
|
stat_values = []
|
|
|
|
for stat in ['nr_tried', 'sz_tried', 'nr_applied',
|
|
|
|
'sz_applied', 'qt_exceeds']:
|
|
|
|
content, err = read_file(
|
|
|
|
os.path.join(scheme.sysfs_dir(), 'stats', stat))
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2024-02-07 12:31:28 -08:00
|
|
|
return err
|
|
|
|
stat_values.append(int(content))
|
|
|
|
scheme.stats = DamosStats(*stat_values)
|
|
|
|
|
2024-05-02 10:27:17 -07:00
|
|
|
def update_schemes_effective_quotas(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'state'),
|
|
|
|
'update_schemes_effective_quotas')
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
for context in self.contexts:
|
|
|
|
for scheme in context.schemes:
|
|
|
|
for goal in scheme.quota.goals:
|
|
|
|
content, err = read_file(
|
|
|
|
os.path.join(scheme.quota.sysfs_dir(),
|
|
|
|
'effective_bytes'))
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
goal.effective_bytes = int(content)
|
|
|
|
return None
|
|
|
|
|
2024-06-25 11:05:37 -07:00
|
|
|
def commit(self):
|
|
|
|
nr_contexts_file = os.path.join(self.sysfs_dir(),
|
|
|
|
'contexts', 'nr_contexts')
|
|
|
|
content, err = read_file(nr_contexts_file)
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
if int(content) != len(self.contexts):
|
|
|
|
err = write_file(nr_contexts_file, '%d' % len(self.contexts))
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
|
|
|
|
for context in self.contexts:
|
|
|
|
err = context.stage()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'state'), 'commit')
|
|
|
|
return err
|
|
|
|
|
|
|
|
|
2024-05-02 10:27:17 -07:00
|
|
|
def commit_schemes_quota_goals(self):
|
|
|
|
for context in self.contexts:
|
|
|
|
for scheme in context.schemes:
|
|
|
|
for goal in scheme.quota.goals:
|
|
|
|
err = goal.stage()
|
|
|
|
if err is not None:
|
|
|
|
print('commit_schemes_quota_goals failed stagign: %s'%
|
|
|
|
err)
|
|
|
|
exit(1)
|
|
|
|
return write_file(os.path.join(self.sysfs_dir(), 'state'),
|
|
|
|
'commit_schemes_quota_goals')
|
|
|
|
|
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>
2023-12-12 19:48:06 +00:00
|
|
|
class Kdamonds:
|
|
|
|
kdamonds = []
|
|
|
|
|
|
|
|
def __init__(self, kdamonds=[]):
|
|
|
|
self.kdamonds = kdamonds
|
|
|
|
for idx, kdamond in enumerate(self.kdamonds):
|
|
|
|
kdamond.idx = idx
|
|
|
|
kdamond.kdamonds = self
|
2023-12-12 19:48:07 +00:00
|
|
|
|
|
|
|
def sysfs_dir(self):
|
|
|
|
return os.path.join(sysfs_root, 'kdamonds')
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
err = write_file(os.path.join(self.sysfs_dir(), 'nr_kdamonds'),
|
|
|
|
'%s' % len(self.kdamonds))
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
for kdamond in self.kdamonds:
|
|
|
|
err = kdamond.start()
|
2024-05-03 11:03:12 -07:00
|
|
|
if err is not None:
|
2023-12-12 19:48:07 +00:00
|
|
|
return err
|
|
|
|
return None
|
2024-06-25 11:05:35 -07:00
|
|
|
|
|
|
|
def stop(self):
|
|
|
|
for kdamond in self.kdamonds:
|
|
|
|
err = kdamond.stop()
|
|
|
|
if err is not None:
|
|
|
|
return err
|
|
|
|
return None
|