[PATCH] virt-test: Add a class NumaNode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dynamically checking hardware, use a dict to record the pin status,
pin process to single cpu by 'taskset' command.

Guest memory pining is already implemented in framework.
process pining needs to be done in the testcases.

Example:
|  numa_node = -1 # last node
|  p = virt_utils.NumaNode(numa_node)
|  vhost_threads = commands.getoutput("ps aux |grep '\[vhost-.*\]'
|                  |grep -v grep|awk '{print $2}'")
|  for i in vhost_threads.split():
|      logging.debug("pin vhost_net thread(%s) to host cpu node" % i)
|      p.pin_cpu(i)
|  o = vm.monitor.info("cpus")
|  for i in re.findall("thread_id=(\d+)", o):
|      logging.debug("pin vcpu thread(%s) to host cpu node" % i)
|      p.pin_cpu(i)
|  p.show()

Signed-off-by: Amos Kong <akong@xxxxxxxxxx>
---
 client/tests/kvm/base.cfg.sample |    5 ++++
 client/virt/kvm_vm.py            |    8 ++++++
 client/virt/virt_utils.py        |   50 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/client/tests/kvm/base.cfg.sample b/client/tests/kvm/base.cfg.sample
index c99add6..0e8555e 100644
--- a/client/tests/kvm/base.cfg.sample
+++ b/client/tests/kvm/base.cfg.sample
@@ -146,6 +146,11 @@ shell_port = 22
 used_cpus = 1
 used_mem = 512
 
+# Numa pin params
+# pin guest memory to 1th numa node
+# pin processes to host cpu of 1th node
+# numa_node = 1
+
 # Port redirections
 redirs = remote_shell
 guest_port_remote_shell = 22
diff --git a/client/virt/kvm_vm.py b/client/virt/kvm_vm.py
index 6747c2b..fa258c3 100644
--- a/client/virt/kvm_vm.py
+++ b/client/virt/kvm_vm.py
@@ -473,6 +473,14 @@ class VM(virt_vm.BaseVM):
             qemu_cmd += "LD_LIBRARY_PATH=%s " % library_path
         if params.get("qemu_audio_drv"):
             qemu_cmd += "QEMU_AUDIO_DRV=%s " % params.get("qemu_audio_drv")
+        # Add numa memory cmd to pin guest memory to numa node
+        if params.get("numa_node"):
+            numa_node = int(params.get("numa_node"))
+            if numa_node < 0:
+                p = virt_utils.NumaNode(numa_node)
+                qemu_cmd += "numactl -m %s " % (int(p.get_node_num()) + numa_node)
+            else:
+                qemu_cmd += "numactl -m %s " % (numa_node - 1)
         # Add the qemu binary
         qemu_cmd += qemu_binary
         # Add the VM's name
diff --git a/client/virt/virt_utils.py b/client/virt/virt_utils.py
index 7759b2d..7ef0c0b 100644
--- a/client/virt/virt_utils.py
+++ b/client/virt/virt_utils.py
@@ -3445,3 +3445,53 @@ def virt_test_assistant(test_name, test_dir, base_dir, default_userspace_paths,
     logging.info("Autotest prints the results dir, so you can look at DEBUG "
                  "logs if something went wrong")
     logging.info("You can also edit the test config files")
+
+
+class NumaNode():
+    """ Numa node to control the processes and shared memory """
+    def __init__(self, i=-1):
+        self.num = self.get_node_num()
+        if i < 0:
+            self.cpus = self.get_node_cpus(int(self.num)+i).split()
+        else:
+            self.cpus = self.get_node_cpus(i-1).split()
+        self.dict = {}
+        for i in self.cpus:
+            self.dict[i] = "free"
+
+    def get_node_num(self):
+        """ Get the nodes number of host """
+        output = commands.getoutput("numactl --hardware")
+        return re.findall("available: (\d+) nodes", output)[0]
+
+    def get_node_cpus(self, i):
+        """ Get cpus of one node """
+        output = commands.getoutput("numactl --hardware")
+        return re.findall("node %s cpus: (.*)" % i, output)[0]
+
+    def free_cpu(self, i):
+        """ Release pin flag """
+        self.dict[i] = "free"
+
+    def _flush_pin(self):
+        """ Flush pin dict, remove the record of exited process """
+        o = commands.getoutput("ps -eLf |awk '{print $4}'")
+        for i in self.cpus:
+            if self.dict[i] != "free" and self.dict[i] not in o:
+                self.free_cpu(i)
+
+    def pin_cpu(self, process):
+        """ Pin one process to a single cpu """
+        self._flush_pin()
+        for i in self.cpus:
+            if self.dict[i] == "free":
+                self.dict[i] = str(process)
+                cmd = "taskset -p %s %s" % (hex(2**int(i)), process)
+                logging.debug("NumaNode (%s): " % i + cmd)
+                commands.getoutput(cmd)
+                return i
+
+    def show(self):
+        """ Display the record dict """
+        for i in self.cpus:
+            print "%s: %s" % (i, self.dict[i])

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux