* [PATCH v4 0/2] tests/functional: add memlock tests
@ 2025-04-17 7:22 Alexandr Moshkov
2025-04-17 7:22 ` [PATCH v4 1/2] tests/functional: add skipLockedMemoryTest decorator Alexandr Moshkov
2025-04-17 7:22 ` [PATCH v4 2/2] tests/functional: add memlock tests Alexandr Moshkov
0 siblings, 2 replies; 4+ messages in thread
From: Alexandr Moshkov @ 2025-04-17 7:22 UTC (permalink / raw)
To: qemu-devel
Cc: Cleber Rosa, yc-core @ yandex-team . ru, Paolo Bonzini,
Daniel P . Berrangé, Alexandr Moshkov
Add new tests to check the correctness of the `-overcommit memlock`
option (possible values: off, on, on-fault) by using
`/proc/{qemu_pid}/smaps` file to check in Size, Rss and Locked fields of
anonymous segments:
* if `memlock=off`, then Locked = 0 on every anonymous smaps;
* if `memlock=on`, then Size, Rss and Locked values must be equal for
every anon smaps where Rss is not 0;
* if `memlock=on-fault`, then Rss and Locked must be equal on every anon
smaps and anonymous segment with Rss < Size must exists.
---
v3 -> v4:
* add skipLockedMemoryTest decorator to skip test if system's locked
memory limit is below the required threashold;
* add to MemlockTest skipLockedMemoryTest decorator with 2 GB limit.
v2 -> v3:
Move tests to tests/functional dir, as the tests/avocado dir is being phased out.
v2 was [PATCH v2] tests/avocado: add memlock tests.
Supersedes: <20250414075702.9248-1-dtalexundeer@yandex-team.ru>
v1 -> v2:
In the previous send, i forgot to specify new patch version (v2)
So i resend previous patch with version specified.
Alexandr Moshkov (2):
tests/functional: add skipLockedMemoryTest decorator
tests/functional: add memlock tests
tests/functional/meson.build | 1 +
tests/functional/qemu_test/__init__.py | 2 +-
tests/functional/qemu_test/decorators.py | 19 +++++
tests/functional/test_memlock.py | 102 +++++++++++++++++++++++
4 files changed, 123 insertions(+), 1 deletion(-)
create mode 100644 tests/functional/test_memlock.py
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v4 1/2] tests/functional: add skipLockedMemoryTest decorator
2025-04-17 7:22 [PATCH v4 0/2] tests/functional: add memlock tests Alexandr Moshkov
@ 2025-04-17 7:22 ` Alexandr Moshkov
2025-04-17 9:43 ` Daniel P. Berrangé
2025-04-17 7:22 ` [PATCH v4 2/2] tests/functional: add memlock tests Alexandr Moshkov
1 sibling, 1 reply; 4+ messages in thread
From: Alexandr Moshkov @ 2025-04-17 7:22 UTC (permalink / raw)
To: qemu-devel
Cc: Cleber Rosa, yc-core @ yandex-team . ru, Paolo Bonzini,
Daniel P . Berrangé, Alexandr Moshkov
Used in future commit to skipping execution of a tests if the system's
locked memory limit is below the required threshold.
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
---
tests/functional/qemu_test/__init__.py | 2 +-
tests/functional/qemu_test/decorators.py | 19 +++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/tests/functional/qemu_test/__init__.py b/tests/functional/qemu_test/__init__.py
index af41c2c6a2..6e666a059f 100644
--- a/tests/functional/qemu_test/__init__.py
+++ b/tests/functional/qemu_test/__init__.py
@@ -15,6 +15,6 @@
from .linuxkernel import LinuxKernelTest
from .decorators import skipIfMissingCommands, skipIfNotMachine, \
skipFlakyTest, skipUntrustedTest, skipBigDataTest, skipSlowTest, \
- skipIfMissingImports, skipIfOperatingSystem
+ skipIfMissingImports, skipIfOperatingSystem, skipLockedMemoryTest
from .archive import archive_extract
from .uncompress import uncompress
diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qemu_test/decorators.py
index 50d29de533..9f3062d020 100644
--- a/tests/functional/qemu_test/decorators.py
+++ b/tests/functional/qemu_test/decorators.py
@@ -5,6 +5,7 @@
import importlib
import os
import platform
+import subprocess
from unittest import skipIf, skipUnless
from .cmd import which
@@ -131,3 +132,21 @@ def skipIfMissingImports(*args):
return skipUnless(has_imports, 'required import(s) "%s" not installed' %
", ".join(args))
+
+'''
+Decorator to skip execution of a test if the system's
+locked memory limit is below the required threshold.
+Takes required locked memory threshold in kB.
+Example:
+
+ @skipLockedMemoryTest(2_097_152)
+'''
+def skipLockedMemoryTest(locked_memory):
+ ulimit_memory = subprocess.run(
+ ['bash', '-c', 'ulimit -l'],
+ capture_output=True,
+ text=True,
+ ).stdout
+
+ return skipUnless(ulimit_memory == 'unlimited' or int(ulimit_memory) >= locked_memory,
+ f'Test required {locked_memory} kB of available locked memory')
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v4 2/2] tests/functional: add memlock tests
2025-04-17 7:22 [PATCH v4 0/2] tests/functional: add memlock tests Alexandr Moshkov
2025-04-17 7:22 ` [PATCH v4 1/2] tests/functional: add skipLockedMemoryTest decorator Alexandr Moshkov
@ 2025-04-17 7:22 ` Alexandr Moshkov
1 sibling, 0 replies; 4+ messages in thread
From: Alexandr Moshkov @ 2025-04-17 7:22 UTC (permalink / raw)
To: qemu-devel
Cc: Cleber Rosa, yc-core @ yandex-team . ru, Paolo Bonzini,
Daniel P . Berrangé, Alexandr Moshkov
Add new tests to check the correctness of the `-overcommit memlock`
option (possible values: off, on, on-fault) by using
`/proc/{qemu_pid}/smaps` file to check in Size, Rss and Locked fields of
anonymous segments:
* if `memlock=off`, then Locked = 0 on every anonymous smaps;
* if `memlock=on`, then Size, Rss and Locked values must be equal for
every anon smaps where Rss is not 0;
* if `memlock=on-fault`, then Rss and Locked must be equal on every anon
smaps and anonymous segment with Rss < Size must exists.
Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
---
tests/functional/meson.build | 1 +
tests/functional/test_memlock.py | 102 +++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+)
create mode 100755 tests/functional/test_memlock.py
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 0f8be30fe2..339af7835f 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -61,6 +61,7 @@ tests_generic_system = [
'empty_cpu_model',
'info_usernet',
'version',
+ 'memlock',
]
tests_generic_linuxuser = [
diff --git a/tests/functional/test_memlock.py b/tests/functional/test_memlock.py
new file mode 100755
index 0000000000..b62f12a715
--- /dev/null
+++ b/tests/functional/test_memlock.py
@@ -0,0 +1,102 @@
+# Functional test that check overcommit memlock options
+#
+# Copyright (c) Yandex Technologies LLC, 2025
+#
+# Author:
+# Alexandr Moshkov <dtalexundeer@yandex-team.ru>
+#
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
+
+import re
+
+from typing import List, Dict
+
+from qemu_test import QemuSystemTest
+from qemu_test import skipLockedMemoryTest
+
+
+SMAPS_HEADER_PATTERN = re.compile(r'^\w+-\w+', re.MULTILINE)
+SMAPS_VALUE_PATTERN = re.compile(r'^(\w+):\s+(\d+) kB', re.MULTILINE)
+
+
+@skipLockedMemoryTest(2_097_152) # 2GB
+class MemlockTest(QemuSystemTest):
+ """
+ Boots a Linux system with memlock options.
+ Then verify, that this options is working correctly
+ by checking the smaps of the QEMU proccess.
+ """
+
+ def common_vm_setup_with_memlock(self, memlock):
+ self.vm.add_args('-overcommit', f'mem-lock={memlock}')
+ self.vm.launch()
+
+ def get_anon_smaps_by_pid(self, pid):
+ smaps_raw = self._get_raw_smaps_by_pid(pid)
+ return self._parse_anonymous_smaps(smaps_raw)
+
+ def test_memlock_off(self):
+ self.common_vm_setup_with_memlock('off')
+
+ anon_smaps = self.get_anon_smaps_by_pid(self.vm.get_pid())
+
+ # locked = 0 on every smap
+ for smap in anon_smaps:
+ self.assertEqual(smap['Locked'], 0)
+
+ def test_memlock_on(self):
+ self.common_vm_setup_with_memlock('on')
+
+ anon_smaps = self.get_anon_smaps_by_pid(self.vm.get_pid())
+
+ # size = rss = locked on every smap where rss not 0
+ for smap in anon_smaps:
+ if smap['Rss'] == 0:
+ continue
+ self.assertTrue(smap['Size'] == smap['Rss'] == smap['Locked'])
+
+ def test_memlock_onfault(self):
+ self.common_vm_setup_with_memlock('on-fault')
+
+ anon_smaps = self.get_anon_smaps_by_pid(self.vm.get_pid())
+
+ # rss = locked on every smap and segment with rss < size exists
+ exists = False
+ for smap in anon_smaps:
+ self.assertTrue(smap['Rss'] == smap['Locked'])
+ if smap['Rss'] < smap['Size']:
+ exists = True
+ self.assertTrue(exists)
+
+ def _parse_anonymous_smaps(self, smaps_raw: str) -> List[Dict[str, int]]:
+ result_segments = []
+ current_segment = {}
+ is_anonymous = False
+
+ for line in smaps_raw.split('\n'):
+ if SMAPS_HEADER_PATTERN.match(line):
+ if current_segment and is_anonymous:
+ result_segments.append(current_segment)
+ current_segment = {}
+ # anonymous segment header looks like this:
+ # 7f3b8d3f0000-7f3b8d3f3000 rw-s 00000000 00:0f 1052
+ # and non anonymous header looks like this:
+ # 7f3b8d3f0000-7f3b8d3f3000 rw-s 00000000 00:0f 1052 [stack]
+ is_anonymous = len(line.split()) == 5
+ elif m := SMAPS_VALUE_PATTERN.match(line):
+ current_segment[m.group(1)] = int(m.group(2))
+
+ if current_segment and is_anonymous:
+ result_segments.append(current_segment)
+
+ return result_segments
+
+ def _get_raw_smaps_by_pid(self, pid: int) -> str:
+ with open(f'/proc/{pid}/smaps', 'r') as f:
+ return f.read()
+
+
+if __name__ == '__main__':
+ MemlockTest.main()
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v4 1/2] tests/functional: add skipLockedMemoryTest decorator
2025-04-17 7:22 ` [PATCH v4 1/2] tests/functional: add skipLockedMemoryTest decorator Alexandr Moshkov
@ 2025-04-17 9:43 ` Daniel P. Berrangé
0 siblings, 0 replies; 4+ messages in thread
From: Daniel P. Berrangé @ 2025-04-17 9:43 UTC (permalink / raw)
To: Alexandr Moshkov
Cc: qemu-devel, Cleber Rosa, yc-core @ yandex-team . ru,
Paolo Bonzini
On Thu, Apr 17, 2025 at 12:22:45PM +0500, Alexandr Moshkov wrote:
> Used in future commit to skipping execution of a tests if the system's
> locked memory limit is below the required threshold.
>
> Signed-off-by: Alexandr Moshkov <dtalexundeer@yandex-team.ru>
> ---
> tests/functional/qemu_test/__init__.py | 2 +-
> tests/functional/qemu_test/decorators.py | 19 +++++++++++++++++++
> 2 files changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/tests/functional/qemu_test/__init__.py b/tests/functional/qemu_test/__init__.py
> index af41c2c6a2..6e666a059f 100644
> --- a/tests/functional/qemu_test/__init__.py
> +++ b/tests/functional/qemu_test/__init__.py
> @@ -15,6 +15,6 @@
> from .linuxkernel import LinuxKernelTest
> from .decorators import skipIfMissingCommands, skipIfNotMachine, \
> skipFlakyTest, skipUntrustedTest, skipBigDataTest, skipSlowTest, \
> - skipIfMissingImports, skipIfOperatingSystem
> + skipIfMissingImports, skipIfOperatingSystem, skipLockedMemoryTest
> from .archive import archive_extract
> from .uncompress import uncompress
> diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qemu_test/decorators.py
> index 50d29de533..9f3062d020 100644
> --- a/tests/functional/qemu_test/decorators.py
> +++ b/tests/functional/qemu_test/decorators.py
> @@ -5,6 +5,7 @@
> import importlib
> import os
> import platform
> +import subprocess
> from unittest import skipIf, skipUnless
>
> from .cmd import which
> @@ -131,3 +132,21 @@ def skipIfMissingImports(*args):
>
> return skipUnless(has_imports, 'required import(s) "%s" not installed' %
> ", ".join(args))
> +
> +'''
> +Decorator to skip execution of a test if the system's
> +locked memory limit is below the required threshold.
> +Takes required locked memory threshold in kB.
> +Example:
> +
> + @skipLockedMemoryTest(2_097_152)
> +'''
> +def skipLockedMemoryTest(locked_memory):
> + ulimit_memory = subprocess.run(
> + ['bash', '-c', 'ulimit -l'],
> + capture_output=True,
> + text=True,
> + ).stdout
You should be able to use resource.getrlimit() rather than spawning
a process.
> +
> + return skipUnless(ulimit_memory == 'unlimited' or int(ulimit_memory) >= locked_memory,
> + f'Test required {locked_memory} kB of available locked memory')
> --
> 2.34.1
>
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-04-17 9:43 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-17 7:22 [PATCH v4 0/2] tests/functional: add memlock tests Alexandr Moshkov
2025-04-17 7:22 ` [PATCH v4 1/2] tests/functional: add skipLockedMemoryTest decorator Alexandr Moshkov
2025-04-17 9:43 ` Daniel P. Berrangé
2025-04-17 7:22 ` [PATCH v4 2/2] tests/functional: add memlock tests Alexandr Moshkov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.