[virt-tools-list] [virt-manager] [PATCH 7/7] details: Add new checkbox to control shared memory access

Lin Ma lma at suse.com
Sun Aug 1 12:36:42 UTC 2021


The virtiofs in domcapabilities is used as a proxy to tell us whether
libvirt is new enough to allow bare memory access mode=shared', So We
enable/disable this checkbox according to it.

When we configure shared memory access, If the 'memfd' is available in
domcaps, We configure VM to use it as memory backend because it doesn't
need addtional host setup for vhost-user devices, Otherwise use 'file'
as backend.

If all of numa nodes explicitly defined memAccess=shared, We mark this
checkbox as checked even if virtiofs isn't exposed in domcapabilities.
In this case:
- It doesn't matter what the value of access mode of memoryBacking is
  because access mode of memoryBacking will be overridden per numa node
  by memAccess attribute.
- Although the checkbox is disabled, the checked checkbox presents actual
  status about shared memory access to users.

Signed-off-by: Lin Ma <lma at suse.com>
---
 ui/details.ui                  | 14 +++++++++
 virtManager/details/details.py | 52 ++++++++++++++++++++++++++++++++++
 virtManager/object/domain.py   | 17 ++++++++++-
 3 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/ui/details.ui b/ui/details.ui
index fa5a209b..b687ac7f 100644
--- a/ui/details.ui
+++ b/ui/details.ui
@@ -1816,6 +1816,20 @@
                                     <property name="top_attach">2</property>
                                   </packing>
                                 </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="shared-memory">
+                                    <property name="label" translatable="yes">Shared memory access</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="draw_indicator">True</property>
+                                    <signal name="toggled" handler="on_mem_shared_access_toggled" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="top_attach">3</property>
+                                  </packing>
+                                </child>
                               </object>
                             </child>
                           </object>
diff --git a/virtManager/details/details.py b/virtManager/details/details.py
index 27f2ecb7..785c9099 100644
--- a/virtManager/details/details.py
+++ b/virtManager/details/details.py
@@ -439,6 +439,7 @@ class vmmDetails(vmmGObjectUI):
             "on_cpu_topology_enable_toggled": self._cpu_topology_enable_cb,
             "on_mem_maxmem_changed": _e(EDIT_MEM),
             "on_mem_memory_changed": self._curmem_changed_cb,
+            "on_mem_shared_access_toggled": _e(EDIT_MEM),
 
             "on_boot_list_changed": self._boot_list_changed_cb,
             "on_boot_moveup_clicked": self._boot_moveup_clicked_cb,
@@ -1471,6 +1472,35 @@ class vmmDetails(vmmGObjectUI):
             hotplug_args["memory"] = kwargs["memory"]
             hotplug_args["maxmem"] = kwargs["maxmem"]
 
+            if self.widget("shared-memory").get_sensitive():
+                guest = self.vm.xmlobj
+                if self.widget("shared-memory").get_active():
+                    if guest.cpu.has_private_memAccess_cells():
+                        embeded_kwargs = {}
+                        embeded_kwargs["memAccess"] = "shared"
+                        self._change_config(
+                                self.vm.define_cpu, embeded_kwargs)
+                    domcaps = self.vm.get_domain_capabilities()
+                    embeded_kwargs = {}
+                    if domcaps.supports_memorybacking_memfd():
+                        embeded_kwargs["source_type"] = "memfd"
+                    else:
+                        embeded_kwargs["source_type"] = "file"
+                    embeded_kwargs["access_mode"] = "shared"
+                    self._change_config(
+                            self.vm.define_memorybacking, embeded_kwargs)
+                else:
+                    if guest.cpu.all_shared_memAccess_cells():
+                        embeded_kwargs = {}
+                        embeded_kwargs["memAccess"] = None
+                        self._change_config(
+                                self.vm.define_cpu, embeded_kwargs)
+                    embeded_kwargs = {}
+                    embeded_kwargs["source_type"] = None
+                    embeded_kwargs["access_mode"] = None
+                    self._change_config(
+                            self.vm.define_memorybacking, embeded_kwargs)
+
         return self._change_config(
                 self.vm.define_memory, kwargs,
                 hotplug_args=hotplug_args)
@@ -1973,6 +2003,28 @@ class vmmDetails(vmmGObjectUI):
         curmem.set_value(int(round(vm_cur_mem)))
         maxmem.set_value(int(round(vm_max_mem)))
 
+        # If virtiofs support is reported via domcapabilities, It's seen as
+        # libvirt is new enough to allow setting shared memory access without
+        # hugepages or numa config.
+        domcaps = self.vm.get_domain_capabilities()
+        guest = self.vm.xmlobj
+        if not domcaps.supports_filesystem_virtiofs():
+            self.widget("shared-memory").set_active(
+                guest.cpu.all_shared_memAccess_cells())
+            self.widget("shared-memory").set_sensitive(False)
+            self.widget("shared-memory").set_tooltip_text(
+                _("Libvirt may not be new enough to support shared memory"))
+        else:
+            is_shared = (guest.memoryBacking.is_shared_access() or
+                         guest.cpu.all_shared_memAccess_cells())
+            # The access mode can be overridden per numa node by memAccess, So
+            # we need to check whether it has 'private' memAccess in numa node.
+            if guest.cpu.has_private_memAccess_cells():
+                is_shared = False
+                self.widget("shared-memory").set_tooltip_text(
+                    _("memory access mode 'private' is found in numa node"))
+            self.widget("shared-memory").set_active(is_shared)
+
     def _refresh_disk_page(self, disk):
         path = disk.get_source_path()
         devtype = disk.device
diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py
index 6c8469d4..99f1a85e 100644
--- a/virtManager/object/domain.py
+++ b/virtManager/object/domain.py
@@ -626,7 +626,8 @@ class vmmDomain(vmmLibvirtObject):
 
     def define_cpu(self, vcpus=_SENTINEL,
             model=_SENTINEL, secure=_SENTINEL, sockets=_SENTINEL,
-            cores=_SENTINEL, threads=_SENTINEL, clear_topology=_SENTINEL):
+            cores=_SENTINEL, threads=_SENTINEL, memAccess=_SENTINEL,
+            clear_topology=_SENTINEL):
         guest = self._make_xmlobj_to_define()
 
         if vcpus != _SENTINEL:
@@ -646,6 +647,11 @@ class vmmDomain(vmmLibvirtObject):
                 guest.cpu.set_special_mode(guest, model)
             else:
                 guest.cpu.set_model(guest, model)
+
+        if memAccess != _SENTINEL:
+            for cell in guest.cpu.cells:
+                cell.memAccess = memAccess
+
         self._redefine_xmlobj(guest)
 
     def define_memory(self, memory=_SENTINEL, maxmem=_SENTINEL):
@@ -657,6 +663,15 @@ class vmmDomain(vmmLibvirtObject):
             guest.memory = int(maxmem)
         self._redefine_xmlobj(guest)
 
+    def define_memorybacking(self, source_type=_SENTINEL, access_mode=_SENTINEL):
+        guest = self._make_xmlobj_to_define()
+
+        if source_type != _SENTINEL:
+            guest.memoryBacking.source_type = source_type
+        if access_mode != _SENTINEL:
+            guest.memoryBacking.access_mode = access_mode
+        self._redefine_xmlobj(guest)
+
     def define_overview(self, machine=_SENTINEL, description=_SENTINEL,
             title=_SENTINEL, loader=_SENTINEL,
             nvram=_SENTINEL):
-- 
2.26.2





More information about the virt-tools-list mailing list