1*ec3a7a71SAlexandr Moshkov#!/usr/bin/env python3 2*ec3a7a71SAlexandr Moshkov# 3*ec3a7a71SAlexandr Moshkov# Functional test that check overcommit memlock options 4*ec3a7a71SAlexandr Moshkov# 5*ec3a7a71SAlexandr Moshkov# Copyright (c) Yandex Technologies LLC, 2025 6*ec3a7a71SAlexandr Moshkov# 7*ec3a7a71SAlexandr Moshkov# Author: 8*ec3a7a71SAlexandr Moshkov# Alexandr Moshkov <dtalexundeer@yandex-team.ru> 9*ec3a7a71SAlexandr Moshkov# 10*ec3a7a71SAlexandr Moshkov# SPDX-License-Identifier: GPL-2.0-or-later 11*ec3a7a71SAlexandr Moshkov 12*ec3a7a71SAlexandr Moshkovimport re 13*ec3a7a71SAlexandr Moshkov 14*ec3a7a71SAlexandr Moshkovfrom typing import Dict 15*ec3a7a71SAlexandr Moshkov 16*ec3a7a71SAlexandr Moshkovfrom qemu_test import QemuSystemTest 17*ec3a7a71SAlexandr Moshkovfrom qemu_test import skipLockedMemoryTest 18*ec3a7a71SAlexandr Moshkov 19*ec3a7a71SAlexandr Moshkov 20*ec3a7a71SAlexandr MoshkovSTATUS_VALUE_PATTERN = re.compile(r'^(\w+):\s+(\d+) kB', re.MULTILINE) 21*ec3a7a71SAlexandr Moshkov 22*ec3a7a71SAlexandr Moshkov 23*ec3a7a71SAlexandr Moshkov@skipLockedMemoryTest(2_097_152) # 2GB 24*ec3a7a71SAlexandr Moshkovclass MemlockTest(QemuSystemTest): 25*ec3a7a71SAlexandr Moshkov """ 26*ec3a7a71SAlexandr Moshkov Runs a guest with memlock options. 27*ec3a7a71SAlexandr Moshkov Then verify, that this options is working correctly 28*ec3a7a71SAlexandr Moshkov by checking the status file of the QEMU process. 29*ec3a7a71SAlexandr Moshkov """ 30*ec3a7a71SAlexandr Moshkov 31*ec3a7a71SAlexandr Moshkov def common_vm_setup_with_memlock(self, memlock): 32*ec3a7a71SAlexandr Moshkov self.vm.add_args('-overcommit', f'mem-lock={memlock}') 33*ec3a7a71SAlexandr Moshkov self.vm.launch() 34*ec3a7a71SAlexandr Moshkov 35*ec3a7a71SAlexandr Moshkov def test_memlock_off(self): 36*ec3a7a71SAlexandr Moshkov self.common_vm_setup_with_memlock('off') 37*ec3a7a71SAlexandr Moshkov 38*ec3a7a71SAlexandr Moshkov status = self.get_process_status_values(self.vm.get_pid()) 39*ec3a7a71SAlexandr Moshkov 40*ec3a7a71SAlexandr Moshkov self.assertTrue(status['VmLck'] == 0) 41*ec3a7a71SAlexandr Moshkov 42*ec3a7a71SAlexandr Moshkov def test_memlock_on(self): 43*ec3a7a71SAlexandr Moshkov self.common_vm_setup_with_memlock('on') 44*ec3a7a71SAlexandr Moshkov 45*ec3a7a71SAlexandr Moshkov status = self.get_process_status_values(self.vm.get_pid()) 46*ec3a7a71SAlexandr Moshkov 47*ec3a7a71SAlexandr Moshkov # VmLck > 0 kB and almost all memory is resident 48*ec3a7a71SAlexandr Moshkov self.assertTrue(status['VmLck'] > 0) 49*ec3a7a71SAlexandr Moshkov self.assertTrue(status['VmRSS'] >= status['VmSize'] * 0.70) 50*ec3a7a71SAlexandr Moshkov 51*ec3a7a71SAlexandr Moshkov def test_memlock_onfault(self): 52*ec3a7a71SAlexandr Moshkov self.common_vm_setup_with_memlock('on-fault') 53*ec3a7a71SAlexandr Moshkov 54*ec3a7a71SAlexandr Moshkov status = self.get_process_status_values(self.vm.get_pid()) 55*ec3a7a71SAlexandr Moshkov 56*ec3a7a71SAlexandr Moshkov # VmLck > 0 kB and only few memory is resident 57*ec3a7a71SAlexandr Moshkov self.assertTrue(status['VmLck'] > 0) 58*ec3a7a71SAlexandr Moshkov self.assertTrue(status['VmRSS'] <= status['VmSize'] * 0.30) 59*ec3a7a71SAlexandr Moshkov 60*ec3a7a71SAlexandr Moshkov def get_process_status_values(self, pid: int) -> Dict[str, int]: 61*ec3a7a71SAlexandr Moshkov result = {} 62*ec3a7a71SAlexandr Moshkov raw_status = self._get_raw_process_status(pid) 63*ec3a7a71SAlexandr Moshkov 64*ec3a7a71SAlexandr Moshkov for line in raw_status.split('\n'): 65*ec3a7a71SAlexandr Moshkov if m := STATUS_VALUE_PATTERN.match(line): 66*ec3a7a71SAlexandr Moshkov result[m.group(1)] = int(m.group(2)) 67*ec3a7a71SAlexandr Moshkov 68*ec3a7a71SAlexandr Moshkov return result 69*ec3a7a71SAlexandr Moshkov 70*ec3a7a71SAlexandr Moshkov def _get_raw_process_status(self, pid: int) -> str: 71*ec3a7a71SAlexandr Moshkov try: 72*ec3a7a71SAlexandr Moshkov with open(f'/proc/{pid}/status', 'r') as f: 73*ec3a7a71SAlexandr Moshkov return f.read() 74*ec3a7a71SAlexandr Moshkov except FileNotFoundError: 75*ec3a7a71SAlexandr Moshkov self.skipTest("Can't open status file of the process") 76*ec3a7a71SAlexandr Moshkov 77*ec3a7a71SAlexandr Moshkov 78*ec3a7a71SAlexandr Moshkovif __name__ == '__main__': 79*ec3a7a71SAlexandr Moshkov MemlockTest.main() 80