Transparent hugepage test includes:
1)smoking test and stress test as basic test
Smoking test is test the transparent hugepage is used by kvm and guest.
Stress test test use a parallel dd to test the stability of transparent
hugepage
2)swapping test
Bootup a vm and verify that it can be swapped out and swapped in correctly
3)defrag test
Allocate hugepage for libhugetlbfs while defrag is on and off.
Than compare the result
And there is a script for env preparing named thp.py. It will set the
khugepaged to a active mode and it also including a simple test for
khugepaged.

Signed-off-by: Yiqiao Pu <[email protected]>
---
 client/tests/kvm/scripts/thp.py                   |  130 +++++++++++++++++++++
 client/tests/kvm/tests/trans_hugepage.py          |  120 +++++++++++++++++++
 client/tests/kvm/tests/trans_hugepage_defrag.py   |   72 ++++++++++++
 client/tests/kvm/tests/trans_hugepage_swapping.py |  104 ++++++++++++++++
 client/tests/kvm/tests_base.cfg.sample            |   18 +++
 5 files changed, 444 insertions(+), 0 deletions(-)
 create mode 100755 client/tests/kvm/scripts/thp.py
 create mode 100644 client/tests/kvm/tests/trans_hugepage.py
 create mode 100644 client/tests/kvm/tests/trans_hugepage_defrag.py
 create mode 100644 client/tests/kvm/tests/trans_hugepage_swapping.py

diff --git a/client/tests/kvm/scripts/thp.py b/client/tests/kvm/scripts/thp.py
new file mode 100755
index 0000000..a1cf288
--- /dev/null
+++ b/client/tests/kvm/scripts/thp.py
@@ -0,0 +1,130 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import os, sys, time, commands, string, re, stat, shelve
+
+"""
+script to save and restore environment in transparent hugepage test
+and khuagepaged test
+"""
+
+class THPError(Exception):
+    """
+    Exception from transparent hugepage preparing scripts
+    """
+    pass
+
+class THP:
+    def __init__(self):
+        """
+        Get the configuration path of transparent hugepage, ksm,
+        libhugetlbfs and etc. And the option config parameters from user
+        """
+        if os.path.isdir("/sys/kernel/mm/redhat_transparent_hugepage"):
+            self.thp_path = '/sys/kernel/mm/redhat_transparent_hugepage'
+        elif os.path.isdir("/sys/kernel/mm/transparent_hugepage"):
+            self.thp_path = '/sys/kernel/mm/transparent_hugepage'
+        else:
+            raise THPError("System don't support transparent hugepage")
+
+        self.default_config_file = '/tmp/thp_default_config'
+        # Update the test config dict from environment
+        test_cfg={"%s/defrag" % self.thp_path:"yes",
+                "%s/enabled" % self.thp_path:"always",
+                "%s/khugepaged/defrag" % self.thp_path:"yes",
+                "%s/khugepaged/scan_sleep_millisecs" % self.thp_path:"100",
+                "%s/khugepaged/pages_to_scan" % self.thp_path:"4096",
+                "%s/khugepaged/alloc_sleep_millisecs" % self.thp_path:"100",
+                "/sys/kernel/mm/ksm/run":"1",
+                "/proc/sys/vm/nr_hugepages":"0"
+                }
+        if os.path.isfile("%s/khugepaged/enabled" % self.thp_path):
+            test_cfg["%s/khugepaged/enabled" % self.thp_path] = "always"
+        if os.path.isfile("%s/khugepaged/max_ptes_none" % self.thp_path):
+            test_cfg["%s/khugepaged/max_ptes_none" % self.thp_path] = "511"
+            test_cfg["%s/defrag" % self.thp_path] = "always"
+
+        tmp_list = []
+        test_config = str(os.environ['KVM_TEST_thp_test_config'])
+        if len(test_config) > 0:
+            tmp_list = re.split(';', test_config)
+        while len(tmp_list) > 0:
+            tmp_cfg = tmp_list.pop()
+            test_cfg[re.split(":", tmp_cfg)[0]] = \
+                                           re.split(":", tmp_cfg)[1]
+        self.test_config = test_cfg
+
+    def save_env(self):
+        """
+        Save and set the environment including related parts in kernel.
+        Such as ksm and libhugetlbfs.
+        """
+        fd_default = shelve.open(str(self.default_config_file))
+        for f in self.test_config.keys():
+            parameter = file(f,'r').read()
+            if string.find(f, "enabled") > 0 or string.find(f, "defrag") > 0:
+                parameter = re.split("\[|\]", parameter)[1] + '\n'
+        fd_default[f] = parameter
+        fd_default.close()
+
+    def set_env(self):
+        """
+        After khugepaged test inuse_config is already set to an active mode of
+        transparent hugepage. Get some special config of sub test and set it.
+        """
+        if len(self.test_config) > 0:
+            for path in self.test_config.keys():
+                file(path, 'w').write(self.test_config[path])
+
+    def set_params(self, path_dict={}, filename="", value=""):
+        """
+        Set the value of a config files in one path which is
+        store in a path dict
+        @param path_dict: Dict of files' pathes {path : value}
+        @param filename: Name of file to setup
+        @param value: Value set to the configuration files
+        """
+        for path in path_dict.keys():
+            if string.find(path, filename) > 0:
+                try:
+                    file(path, "w").write(value)
+                except IOError, e:
+                    raise THPError("Can not set %s to %s: %s" % \
+                                   (value, filename, e))
+
+    def khugepaged_test(self):
+        """
+        Start, stop and frequency change test for khugepaged
+        """
+        action_list = [("never", 256),("always", 0),("never", 256)]
+        # ret is the (status, value)
+        ret = [self.set_params(self.test_config, "enabled", a) or\
+         commands.getstatusoutput('pgrep khugepaged') for (a, r) in 
action_list]
+        for i in range(len(action_list)):
+            if ret[i][0] != action_list[i][1]:
+                raise THPError("khugepaged can not set to status %s" %\
+                                action_list[i][0])
+
+
+    def restore_default_config(self):
+        """:
+        Restore the default configuration to host after test
+        """
+        fd = shelve.open(self.default_config_file)
+        for path in fd.keys():
+            file(path, 'w').write(fd[path])
+        fd.close()
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        raise THPError("Please use -s for set and -r for restore")
+
+    run_time = sys.argv[1][1:]
+    trans_hugepage = THP()
+    if run_time == "s":
+        trans_hugepage.save_env()
+        trans_hugepage.khugepaged_test()
+        trans_hugepage.set_env()
+    elif run_time == "r":
+        trans_hugepage.restore_default_config()
+    else:
+        raise THPError("Please use -s for set and -r for restore")
diff --git a/client/tests/kvm/tests/trans_hugepage.py 
b/client/tests/kvm/tests/trans_hugepage.py
new file mode 100644
index 0000000..5cd3ef9
--- /dev/null
+++ b/client/tests/kvm/tests/trans_hugepage.py
@@ -0,0 +1,120 @@
+import logging, time, commands, os, string, re
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.virt import virt_test_utils, aexpect
+
+def run_trans_hugepage(test, params, env):
+    """
+    KVM khugepage user side test:
+    1) Smoking test
+    2) Stress test
+
+    @param test: kvm test object.
+    @param params: Dictionary with test parameters.
+    @param env: Dictionary with the test environment.
+    """
+    def get_mem_status(params, type):
+        if type == "host":
+            s, info = commands.getstatusoutput("cat /proc/meminfo")
+        else:
+            s, info = session.get_command_status_output("cat /proc/meminfo")
+        if s != 0:
+            raise error.TestError("Can not get memory info in guest")
+        for h in re.split("\n+", info):
+            if h.startswith("%s" % params):
+                output = re.split('\s+', h)[1]
+        return output
+    # Check khugepage is used by guest
+    dd_timeout = float(params.get("dd_timeout", 900))
+    fail = 0
+    nr_ah = []
+    mem = params['mem']
+
+    debugfs_flag = 1
+    if not os.path.ismount('/mnt/debugfs'):
+        if not os.path.isdir('/mnt/debugfs'):
+            os.makedirs('/mnt/debugfs')
+        s, o = commands.getstatusoutput("mount -t debugfs none /mnt/debugfs")
+        if s != 0:
+            debugfs_flag = 0
+            logging.info("Warning: debugfs is unusable")
+
+    logging.info("Smoking test start")
+    login_timeout = float(params.get("login_timeout", "3600"))
+    vm = virt_test_utils.get_living_vm(env, params.get("main_vm"))
+    session = virt_test_utils.wait_for_login(vm, timeout=login_timeout)
+
+    nr_ah.append(get_mem_status('AnonHugePages', 'host'))
+    if nr_ah[0] <= 0:
+        raise error.TestFail("VM is not using transparent hugepage")
+
+    # Protect system from oom killer
+    if int(get_mem_status('MemFree', 'guest')) / 1024 < mem :
+        mem = int(get_mem_status('MemFree', 'guest')) / 1024
+    cmd = "ls -d /space"
+    status = session.get_command_status(cmd)
+    if status != 0:
+        cmd = "mkdir /space &> /dev/null"
+        status = session.get_command_status(cmd)
+        if status != 0:
+            raise error.TestError("Can not mkdir in guest")
+
+    cmd = "mount -t tmpfs -o size=%sM none /space" % str(mem)
+    status = session.get_command_status(cmd)
+    if status != 0:
+        raise error.TestError("Can not mount tmpfs in guest")
+
+    count = mem / 4
+    cmd = "dd if=/dev/zero of=/space/1 bs=4000000 count=%s" % count
+    try:
+        status = session.get_command_status(cmd, timeout=dd_timeout)
+    except aexpect.ShellStatusError, e:
+        logging.debug(e)
+        raise error.TestFail("Could not get exit status of command %s" % cmd)
+    except Exception, e:
+        logging.debug(e)
+        raise error.TestFail("Fail command: %s. Please check debug log!" % cmd)
+
+    if status != 0:
+        raise error.TestError("dd failed in guest")
+
+    nr_ah.append(get_mem_status('AnonHugePages', 'host'))
+
+    if nr_ah[1] <= nr_ah[0]:
+        logging.info("WARNING: VM don't use transparent hugepage when dd")
+
+    if debugfs_flag == 1:
+        if int(open('/mnt/debugfs/kvm/largepages', 'r').read()) <= 0:
+            raise error.TestFail("KVM doesn't use transparenthugepage")
+
+    logging.info("Smoking test finished")
+
+    # Use parallel dd as stress for memory
+    count = count / 3
+    logging.info("Stress test start")
+    cmd = "for i in `seq %s`;do dd if=/dev/zero of=/space/$i" % count \
+           + " bs=4000000 count=1& done "
+    try:
+        status, output = session.get_command_status_output(cmd,
+                                                           timeout=dd_timeout)
+    except aexpect.ShellStatusError, e:
+        logging.debug(e)
+        raise error.TestFail("Could not get exit status of command %s" % cmd)
+    except Exception, e:
+        logging.debug(e)
+        raise error.TestFail("Fail command: %s. Please check debug log!" % cmd)
+
+    if len(re.findall("No space", output)) > count * 0.05:
+        raise error.TestFail("Too many dd failed in guest")
+
+    s, o = session.get_command_status_output('pidof dd')
+    if s == 0 :
+        for i in re.split('\n+', o):
+            session.get_command_status_output('kill -9 %s' % i)
+
+    cmd = "umount /space"
+    status, output = session.get_command_status_output(cmd)
+    if status != 0:
+        raise error.TestFail("Can not umount tmpfs after stress test%s"% 
output)
+    logging.info("Stress test finished")
+
+    session.close()
diff --git a/client/tests/kvm/tests/trans_hugepage_defrag.py 
b/client/tests/kvm/tests/trans_hugepage_defrag.py
new file mode 100644
index 0000000..14ce546
--- /dev/null
+++ b/client/tests/kvm/tests/trans_hugepage_defrag.py
@@ -0,0 +1,72 @@
+
+import logging, time, commands, os, string, re
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.virt import virt_test_utils
+
+def run_trans_hugepage_defrag(test, params, env):
+    """
+    KVM khugepage user side test:
+    1) Verify that the host supports khugepahe. If it does proceed with the 
test.
+    2) Verify that the khugepage can be used in host
+    3) Verify that the khugepage can be used in guest
+    4) Migration while using khuge page
+
+    @param test: kvm test object.
+    @param params: Dictionary with test parameters.
+    @param env: Dictionary with the test environment.
+    """
+    def get_mem_status(params):
+        for line in file('/proc/meminfo', 'r').readlines():
+            if line.startswith("%s" % params):
+                output = re.split('\s+', line)[1]
+        return output
+
+    def set_libhugetlbfs(number):
+        fd = file("/proc/sys/vm/nr_hugepages", "w+")
+        fd.write(number)
+        fd.seek(0)
+        ret = fd.read()
+        return int(ret)
+
+    # 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)
+
+    try:
+        if not os.path.isdir('/space'):
+            os.makedirs('/space')
+        if os.system("mount -t tmpfs none /space"):
+            raise error.TestError("Can not mount tmpfs")
+
+        # Try to make some fragment in memory, the total size of fragments is 
1G
+        cmd = "for i in `seq 262144`; do dd if=/dev/urandom of=/space/$i bs=4K 
count=1 & done"
+        s, o = commands.getstatusoutput(cmd)
+        if s != 0:
+            raise error.TestError("Can not dd in host")
+    finally:
+        s, o = commands.getstatusoutput("umount /space")
+        if s != 0:
+            raise error.TestError("Can not free tmpfs")
+
+    total = int(get_mem_status('MemTotal'))
+    hugepagesize = int(get_mem_status('Hugepagesize'))
+    nr_full = str(total / hugepagesize)
+    # Allocate hugepage for libhugetlbfs before and after enable defrag.
+    # And see the different
+    nr = []
+    nr.append(set_libhugetlbfs(nr_full))
+    try:
+        defrag_path = 
'/sys/kernel/mm/redhat_transparent_hugepage/khugepaged/defrag'
+        file(str(defrag_path),'w').write('yes')
+    except IOError, e:
+        raise error.TestFail("Can not start defrag:%s" % e)
+
+    time.sleep(1)
+    nr.append(set_libhugetlbfs(nr_full))
+
+    if nr[0] >= nr[1]:
+        raise error.TestFail("Do not defrag in the system %s" % nr)
+    session.close()
+    logging.info("Defrag test succeed")
diff --git a/client/tests/kvm/tests/trans_hugepage_swapping.py 
b/client/tests/kvm/tests/trans_hugepage_swapping.py
new file mode 100644
index 0000000..a58ee6b
--- /dev/null
+++ b/client/tests/kvm/tests/trans_hugepage_swapping.py
@@ -0,0 +1,104 @@
+import logging, time, commands, os, string, re
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.virt import virt_test_utils
+
+def run_trans_hugepage_swapping(test, params, env):
+    """
+    KVM khugepage user side test:
+    1) Verify that the hugepages can be swapped in/out.
+
+    @param test: kvm test object.
+    @param params: Dictionary with test parameters.
+    @param env: Dictionary with the test environment.
+    """
+    def get_args(args_list):
+        """
+        Get the memory arguments from system
+        """
+        args_list_tmp = args_list.copy()
+        for line in file('/proc/meminfo', 'r').readlines():
+            for key in args_list_tmp.keys():
+                if line.startswith("%s" % args_list_tmp[key]):
+                    args_list_tmp[key] = int(re.split('\s+', line)[1])
+        return args_list_tmp
+
+    # Swapping test
+    logging.info("Swapping test start")
+    # Parameters of memory information
+    # @total: Memory size
+    # @free: Free memory size
+    # @swap_size: Swap size
+    # @swap_free: Free swap size
+    # @hugepage_size: Page size of one hugepage
+    # @page_size: The biggest page size that app can ask for
+    args_dict_check = {"free" : "MemFree", "swap_size" : "SwapTotal",
+                        "swap_free" : "SwapFree", "total" : "MemTotal",
+                       "hugepage_size" : "Hugepagesize",}
+    args_dict = get_args(args_dict_check)
+    swap_free = []
+    total = int(args_dict['total']) / 1024
+    free = int(args_dict['free']) / 1024
+    swap_size = int(args_dict['swap_size']) / 1024
+    swap_free.append(int(args_dict['swap_free'])/1024)
+    hugepage_size = int(args_dict['hugepage_size']) / 1024
+    dd_timeout = float(params.get("dd_timeout", 900))
+    login_timeout = float(params.get("login_timeout", 360))
+    check_cmd_timeout = float(params.get("check_cmd_timeout", 900))
+    # If swap is enough fill all memory with dd
+    if swap_free > (total - free):
+        count = total / hugepage_size
+        tmpfs_size = total
+    else:
+        count = free / hugepage_size
+        tmpfs_size = free
+
+    if swap_size <= 0:
+        raise logging.info("Host don't have swap")
+    try:
+        if not os.path.isdir('/space'):
+            os.makedirs('/space')
+        if os.system("mount -t tmpfs  -o size=%sM none /space" % tmpfs_size):
+            raise error.TestError("Can not mount tmpfs")
+
+        # Set the memory size of vm
+        # To ignore the oom killer set it to the free swap size
+        vm = virt_test_utils.get_living_vm(env, params.get("main_vm"))
+        if int(params['mem']) > swap_free[0]:
+            vm.destroy()
+            vm_name = 'vmsw'
+            vm0 =  params.get("main_vm")
+            vm0_key = virt_utils.env_get_vm(env, vm0)
+            params['vms'] = params['vms'] + " " + vm_name
+            params['mem'] = str(swap_free[0])
+            vm_key = vm0_key.clone(vm0, params)
+            virt_utils.env_register_vm(env, vm_name, vm_key)
+            virt_env_preprocessing.preprocess_vm(test, params, env, vm_name)
+            vm_key.create()
+            session = virt_utils.wait_for(vm_key.remote_login, 
timeout=login_timeout)
+        else:
+            session = virt_test_utils.wait_for_login(vm, timeout=login_timeout)
+
+        cmd = "dd if=/dev/zero of=/space/zero bs=%s000000 count=%s" % \
+                (hugepage_size, count)
+        s, o = commands.getstatusoutput(cmd)
+        if s != 0:
+            raise error.TestError("dd failed in host: %s" % o)
+
+        args_dict = get_args(args_dict_check)
+        swap_free.append(int(args_dict['swap_free'])/1024)
+
+        if swap_free[1] - swap_free[0] >= 0:
+            raise error.TestFail("Nothing is swapped")
+
+        # Check the vm still alive
+        s = session.get_command_status("find / -name \"*\"",
+                                        timeout=check_cmd_timeout)
+        if s != 0 :
+            raise error.TestFail("There is something wrong after swap")
+    finally:
+        s, o = commands.getstatusoutput("umount /space")
+        if s != 0:
+            logging.warning("Can not umount tmpfs after swap")
+        logging.info("Swapping test succeed")
+
+    session.close()
diff --git a/client/tests/kvm/tests_base.cfg.sample 
b/client/tests/kvm/tests_base.cfg.sample
index 78c84c6..3c8e552 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -965,6 +965,24 @@ variants:
         kill_vm_gracefully = no
     # Do not define test variants below shutdown
 
+    - trans_hugepage:
+        pre_command = python scripts/thp.py -s
+        post_command = python scripts/thp.py -r
+        thp_default_config = "/tmp/thp_default_config"
+        thp_test_config = ""
+        kill_vm = yes
+        login_timeout = 360
+        variants:
+            - base:
+                type = trans_hugepage
+                dd_timeout = 900
+            - defrag:
+                type = trans_hugepage_defrag
+            - swapping:
+                type = trans_hugepage_swapping
+                dd_timeout = 900
+                check_cmd_timeout = 900
+
 
 # NICs
 variants:
-- 
1.7.1

_______________________________________________
Autotest mailing list
[email protected]
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

Reply via email to