From patchwork Mon Jun 27 02:38:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lucas Meneghel Rodrigues X-Patchwork-Id: 919822 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p5R2ifxS017944 for ; Mon, 27 Jun 2011 02:44:41 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756237Ab1F0Ciz (ORCPT ); Sun, 26 Jun 2011 22:38:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60097 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756111Ab1F0CiV (ORCPT ); Sun, 26 Jun 2011 22:38:21 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p5R2cHCm027471 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sun, 26 Jun 2011 22:38:17 -0400 Received: from freedom.redhat.com (vpn-8-43.rdu.redhat.com [10.11.8.43]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p5R2cFQO015263; Sun, 26 Jun 2011 22:38:16 -0400 From: Lucas Meneghel Rodrigues To: autotest@test.kernel.org Cc: kvm@vger.kernel.org, ypu@redhat.com, Lucas Meneghel Rodrigues Subject: [PATCH 1/3] virt: Add Transparent Hugepages setup v4 Date: Sun, 26 Jun 2011 23:38:13 -0300 Message-Id: <1309142293-28670-1-git-send-email-lookkas@gmail.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 27 Jun 2011 02:44:41 +0000 (UTC) From: Yiqiao Pu This class configures khugepaged to active mode, with functions to restore original guest configuration. Changes from v1: * Rather than a pre/post script, config is now part of the framework * No need to store configuration in files anymore to restore host khugepaged original behavior Changes from v2: * Walk through the thp config directory. And test khugepaged with the default value in system. * Add 5s sleep time in khugepaged test Changes from v3: * Replace custom function is_writeable with trying to open the file for writing. * Remove some intermediate assignmentes of class attributes. Signed-off-by: Yiqiao Pu Signed-off-by: Lucas Meneghel Rodrigues --- client/virt/virt_test_setup.py | 186 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 185 insertions(+), 1 deletions(-) diff --git a/client/virt/virt_test_setup.py b/client/virt/virt_test_setup.py index 3e1f5b5..2717014 100644 --- a/client/virt/virt_test_setup.py +++ b/client/virt/virt_test_setup.py @@ -1,11 +1,195 @@ """ Library to perform pre/post test setup for KVM autotest. """ -import os, logging +import os, logging, time, re, sre, random from autotest_lib.client.common_lib import error from autotest_lib.client.bin import utils +class THPError(Exception): + """ + Base exception for Transparent Hugepage setup. + """ + pass + + +class THPNotSupportedError(THPError): + """ + Thrown when host does not support tansparent hugepages. + """ + pass + + +class THPWriteConfigError(THPError): + """ + Thrown when host does not support tansparent hugepages. + """ + pass + + +class THPKhugepagedError(THPError): + """ + Thrown when khugepaged is not behaving as expected. + """ + pass + + +class TransparentHugePageConfig(object): + def __init__(self, test, params): + """ + Find paths for transparent hugepages and kugepaged configuration. Also, + back up original host configuration so it can be restored during + cleanup. + """ + self.params = params + + RH_THP_PATH = "/sys/kernel/mm/redhat_transparent_hugepage" + UPSTREAM_THP_PATH = "/sys/kernel/mm/transparent_hugepage" + if os.path.isdir(RH_THP_PATH): + self.thp_path = RH_THP_PATH + elif os.path.isdir(UPSTREAM_THP_PATH): + self.thp_path = UPSTREAM_THP_PATH + else: + raise THPNotSupportedError("System doesn't support transparent " + "hugepages") + + tmp_list = [] + test_cfg = {} + test_config = self.params.get("test_config", None) + if test_config is not None: + tmp_list = re.split(';', test_config) + while len(tmp_list) > 0: + tmp_cfg = tmp_list.pop() + test_cfg[re.split(":", tmp_cfg)[0]] = sre.split(":", tmp_cfg)[1] + # Save host current config, so we can restore it during cleanup + # We will only save the writeable part of the config files + original_config = {} + # List of files that contain string config values + self.file_list_str = [] + # List of files that contain integer config values + self.file_list_num = [] + for f in os.walk(self.thp_path): + base_dir = f[0] + if f[2]: + for name in f[2]: + f_dir = os.path.join(base_dir, name) + parameter = file(f_dir, 'r').read() + try: + # Verify if the path in question is writable + f = open(f_dir, 'w') + f.close() + if re.findall("\[(.*)\]", parameter): + original_config[f_dir] = re.findall("\[(.*)\]", + parameter)[0] + self.file_list_str.append(f_dir) + else: + original_config[f_dir] = int(parameter) + self.file_list_num.append(f_dir) + except IOError: + pass + + self.test_config = test_cfg + self.original_config = original_config + + + def set_env(self): + """ + Applies test configuration on the host. + """ + if self.test_config: + for path in self.test_config.keys(): + file(path, 'w').write(self.test_config[path]) + + + def value_listed(self, value): + """ + Get a parameters list from a string + """ + value_list = [] + for i in re.split("\[|\]|\n+|\s+", value): + if i: + value_list.append(i) + return value_list + + + def khugepaged_test(self): + """ + Start, stop and frequency change test for khugepaged. + """ + def check_status_with_value(action_list, file_name): + """ + Check the status of khugepaged when set value to specify file. + """ + for (a, r) in action_list: + open(file_name, "w").write(a) + time.sleep(5) + try: + utils.run('pgrep khugepaged') + if r != 0: + raise THPKhugepagedError("Khugepaged still alive when" + "transparent huge page is " + "disabled") + except error.CmdError: + if r == 0: + raise THPKhugepagedError("Khugepaged could not be set to" + "status %s" % a) + + + for file_path in self.file_list_str: + action_list = [] + if re.findall("enabled", file_path): + # Start and stop test for khugepaged + value_list = self.value_listed(open(file_path,"r").read()) + for i in value_list: + if re.match("n", i, re.I): + action_stop = (i, 256) + for i in value_list: + if re.match("[^n]", i, re.I): + action = (i, 0) + action_list += [action_stop, action, action_stop] + action_list += [action] + + check_status_with_value(action_list, file_path) + else: + value_list = self.value_listed(open(file_path,"r").read()) + for i in value_list: + action = (i, 0) + action_list.append(action) + check_status_with_value(action_list, file_path) + + for file_path in self.file_list_num: + action_list = [] + value = int(open(file_path, "r").read()) + if value != 0 and value != 1: + new_value = random.random() + action_list.append((str(int(value * new_value)),0)) + action_list.append((str(int(value * ( new_value + 1))),0)) + else: + action_list.append(("0", 0)) + action_list.append(("1", 0)) + + check_status_with_value(action_list, file_path) + + + def setup(self): + """ + Configure host for testing. Also, check that khugepaged is working as + expected. + """ + self.set_env() + self.khugepaged_test() + + + def cleanup(self): + """: + Restore the host's original configuration after test + """ + for path in self.original_config: + p_file = open(path, 'w') + p_file.write(str(self.original_config[path])) + p_file.close() + + class HugePageConfig(object): def __init__(self, params): """