1import logging, time, commands, os, string, re
2from autotest_lib.client.common_lib import error
3from autotest_lib.client.bin import utils
4from autotest_lib.client.virt import virt_test_utils, virt_test_setup
5
6
7@error.context_aware
8def run_trans_hugepage_defrag(test, params, env):
9    """
10    KVM khugepage userspace side test:
11    1) Verify that the host supports kernel hugepages.
12        If it does proceed with the test.
13    2) Verify that the kernel hugepages can be used in host.
14    3) Verify that the kernel hugepages can be used in guest.
15    4) Migrate guest while using hugepages.
16
17    @param test: KVM test object.
18    @param params: Dictionary with test parameters.
19    @param env: Dictionary with the test environment.
20    """
21    def get_mem_status(params):
22        for line in file('/proc/meminfo', 'r').readlines():
23            if line.startswith("%s" % params):
24                output = re.split('\s+', line)[1]
25        return output
26
27
28    def set_libhugetlbfs(number):
29        f = file("/proc/sys/vm/nr_hugepages", "w+")
30        f.write(number)
31        f.seek(0)
32        ret = f.read()
33        return int(ret)
34
35    test_config = virt_test_setup.TransparentHugePageConfig(test, params)
36    # Test the defrag
37    logging.info("Defrag test start")
38    login_timeout = float(params.get("login_timeout", 360))
39    vm = virt_test_utils.get_living_vm(env, params.get("main_vm"))
40    session = virt_test_utils.wait_for_login(vm, timeout=login_timeout)
41    mem_path = os.path.join("/tmp", "thp_space")
42
43    try:
44        test_config.setup()
45        error.context("Fragmenting guest memory")
46        try:
47            if not os.path.isdir(mem_path):
48                os.makedirs(mem_path)
49            if os.system("mount -t tmpfs none %s" % mem_path):
50                raise error.TestError("Can not mount tmpfs")
51
52            # Try to fragment the memory a bit
53            cmd = ("for i in `seq 262144`; do dd if=/dev/urandom of=%s/$i "
54                   "bs=4K count=1 & done" % mem_path)
55            utils.run(cmd)
56        finally:
57            utils.run("umount %s" % mem_path)
58
59        total = int(get_mem_status('MemTotal'))
60        hugepagesize = int(get_mem_status('Hugepagesize'))
61        nr_full = str(total / hugepagesize)
62
63        error.context("activating khugepaged defrag functionality")
64        # Allocate hugepages for libhugetlbfs before and after enable defrag,
65        # and check out the difference.
66        nr_hp_before = set_libhugetlbfs(nr_full)
67        try:
68            defrag_path = os.path.join(test_config.thp_path, 'khugepaged',
69                                       'defrag')
70            file(str(defrag_path), 'w').write('yes')
71        except IOError, e:
72            raise error.TestFail("Can not start defrag on khugepaged: %s" % e)
73        # TODO: Is sitting an arbitrary amount of time appropriate? Aren't there
74        # better ways to do this?
75        time.sleep(1)
76        nr_hp_after = set_libhugetlbfs(nr_full)
77
78        if nr_hp_before >= nr_hp_after:
79            raise error.TestFail("There was no memory defragmentation on host: "
80                                 "%s huge pages allocated before turning "
81                                 "khugepaged defrag on, %s allocated after it" %
82                                 (nr_hp_before, nr_hp_after))
83        logging.info("Defrag test succeeded")
84        session.close()
85    finally:
86        test_config.cleanup()
87