1) Ensure khugepaged defrag and defrag are turned off before
trying to fragment the memory
2) Make turning off/on feature work on RHEL and upstream
3) Add better logging of operations made
4) Test khugepaged while the test VM is booting on the background
5) Try to allocate only 80% of the total host memory in huge pages,
rather than 100%
6) Refactored some operations into functions, making code easier
to read
CC: Andrea Arcangeli <[email protected]>
CC: Yiqiao Pu <[email protected]>
Signed-off-by: Lucas Meneghel Rodrigues <[email protected]>
---
client/virt/tests/trans_hugepage_defrag.py | 140 +++++++++++++++++++++-------
1 files changed, 105 insertions(+), 35 deletions(-)
diff --git a/client/virt/tests/trans_hugepage_defrag.py
b/client/virt/tests/trans_hugepage_defrag.py
index e20d024..52e3aee 100644
--- a/client/virt/tests/trans_hugepage_defrag.py
+++ b/client/virt/tests/trans_hugepage_defrag.py
@@ -21,64 +21,134 @@ def run_trans_hugepage_defrag(test, params, env):
@param params: Dictionary with test parameters.
@param env: Dictionary with the test environment.
"""
- def get_mem_status(params):
+ def get_mem_stat(param):
+ """
+ Get the memory size for a given memory param.
+
+ @param param: Memory parameter.
+ """
for line in file('/proc/meminfo', 'r').readlines():
- if line.startswith("%s" % params):
+ if line.startswith("%s" % param):
output = re.split('\s+', line)[1]
- return output
+ return int(output)
def set_libhugetlbfs(number):
+ """
+ Set the number of hugepages on the system.
+
+ @param number: Number of pages (either string or numeric).
+ """
+ logging.info("Trying to setup %d hugepages on host", number)
f = file("/proc/sys/vm/nr_hugepages", "w+")
+ pre_ret = f.read()
+ logging.debug("Number of huge pages on libhugetlbfs (pre-write): %s" %
+ pre_ret.strip())
f.write(str(number))
f.seek(0)
ret = f.read()
- logging.info("Number of huge pages on libhugetlbfs: %s" % ret)
+ logging.debug("Number of huge pages on libhugetlbfs: (post-write): %s"
%
+ ret.strip())
return int(ret)
- test_config = virt_test_setup.TransparentHugePageConfig(test, params)
- # Test the defrag
- logging.info("Defrag test start")
- login_timeout = float(params.get("login_timeout", 360))
- vm = virt_test_utils.get_living_vm(env, params.get("main_vm"))
- session = virt_test_utils.wait_for_login(vm, timeout=login_timeout)
- mem_path = os.path.join("/tmp", "thp_space")
- try:
- test_config.setup()
- error.context("Fragmenting guest memory")
+ def change_feature_status(status, feature_path, test_config):
+ """
+ Turn on/off feature functionality.
+
+ @param status: String representing status, may be 'on' or 'off'.
+ @param relative_path: Path of the feature relative to THP config base.
+ @param test_config: Object that keeps track of THP config state.
+
+ @raise: error.TestFail, if can't change feature status
+ """
+ feature_path = os.path.join(test_config.thp_path, feature_path)
+ feature_file = open(feature_path, 'r')
+ feature_file_contents = feature_file.read()
+ feature_file.close()
+ possible_values = test_config.value_listed(feature_file_contents)
+
+ if 'yes' in possible_values:
+ on_action = 'yes'
+ off_action = 'no'
+ elif 'always' in possible_values:
+ on_action = 'always'
+ off_action = 'never'
+ elif '1' in possible_values or '0' in possible_values:
+ on_action = '1'
+ off_action = '0'
+ else:
+ raise ValueError("Uknown possible values for file %s: %s" %
+ (test_config.thp_path, possible_values))
+
+ if status == 'on':
+ action = on_action
+ elif status == 'off':
+ action = off_action
+
+ try:
+ feature_file = open(feature_path, 'w')
+ feature_file.write(action)
+ feature_file.close()
+ except IOError, e:
+ raise error.TestFail("Error writing %s to %s: %s" %
+ (action, feature_path, e))
+ time.sleep(1)
+
+
+ def fragment_host_memory(mem_path):
+ """
+ Attempt to fragment host memory.
+
+ It accomplishes that goal by spawning a large number of dd processes
+ on a tmpfs mount.
+
+ @param mem_path: tmpfs mount point.
+ """
+ error.context("Fragmenting host memory")
try:
logging.info("Prepare tmpfs in host")
if not os.path.isdir(mem_path):
os.makedirs(mem_path)
- if os.system("mount -t tmpfs none %s" % mem_path):
- raise error.TestError("Can not mount tmpfs")
-
- logging.info("Start using dd to fragment memory in host")
- # Try to fragment the memory a bit
+ utils.run("mount -t tmpfs none %s" % mem_path)
+ logging.info("Start using dd to fragment memory in guest")
cmd = ("for i in `seq 262144`; do dd if=/dev/urandom of=%s/$i "
"bs=4K count=1 & done" % mem_path)
utils.run(cmd)
finally:
utils.run("umount %s" % mem_path)
- total = int(get_mem_status('MemTotal'))
- hugepagesize = int(get_mem_status('Hugepagesize'))
- nr_full = str(total / hugepagesize)
- error.context("activating khugepaged defrag functionality")
- # Allocate hugepages for libhugetlbfs before and after enable defrag,
- # and check out the difference.
+ test_config = virt_test_setup.TransparentHugePageConfig(test, params)
+ logging.info("Defrag test start")
+ login_timeout = float(params.get("login_timeout", 360))
+ mem_path = os.path.join("/tmp", "thp_space")
+
+ try:
+ test_config.setup()
+ error.context("deactivating khugepaged defrag functionality")
+ change_feature_status("off", "khugepaged/defrag", test_config)
+ change_feature_status("off", "defrag", test_config)
+
+ vm = virt_test_utils.get_living_vm(env, params.get("main_vm"))
+ session = virt_test_utils.wait_for_login(vm, timeout=login_timeout)
+
+ fragment_host_memory(mem_path)
+
+ total = get_mem_stat('MemTotal')
+ hugepagesize = get_mem_stat('Hugepagesize')
+ nr_full = int(0.8 * (total / hugepagesize))
+
nr_hp_before = set_libhugetlbfs(nr_full)
- try:
- defrag_path = os.path.join(test_config.thp_path, 'khugepaged',
- 'defrag')
- file(str(defrag_path), 'w').write('yes')
- except IOError, e:
- raise error.TestFail("Can not start defrag on khugepaged: %s" % e)
- # TODO: Is sitting an arbitrary amount of time appropriate? Aren't
there
- # better ways to do this?
- time.sleep(1)
+
+ error.context("activating khugepaged defrag functionality")
+ change_feature_status("on", "khugepaged/defrag", test_config)
+ change_feature_status("on", "defrag", test_config)
+
+ sleep_time = 10
+ logging.debug("Sleeping %s s to settle things out" % sleep_time)
+ time.sleep(sleep_time)
+
nr_hp_after = set_libhugetlbfs(nr_full)
if nr_hp_before >= nr_hp_after:
@@ -89,6 +159,6 @@ def run_trans_hugepage_defrag(test, params, env):
logging.info("Defrag test succeeded")
session.close()
finally:
- # Clean up lib huge tlb fs in system
+ logging.debug("Cleaning up libhugetlbfs on host")
set_libhugetlbfs(0)
test_config.cleanup()
--
1.7.7.1
_______________________________________________
Autotest mailing list
[email protected]
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest