details: Add new checkbox to control shared memory access

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@suse.com>
This commit is contained in:
Lin Ma 2021-08-01 20:36:42 +08:00 committed by Cole Robinson
parent b19f973f78
commit b4189a925b
3 changed files with 82 additions and 1 deletions

View File

@ -1816,6 +1816,20 @@
<property name="top_attach">2</property> <property name="top_attach">2</property>
</packing> </packing>
</child> </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> </object>
</child> </child>
</object> </object>

View File

@ -431,6 +431,7 @@ class vmmDetails(vmmGObjectUI):
"on_cpu_topology_enable_toggled": self._cpu_topology_enable_cb, "on_cpu_topology_enable_toggled": self._cpu_topology_enable_cb,
"on_mem_maxmem_changed": _e(EDIT_MEM), "on_mem_maxmem_changed": _e(EDIT_MEM),
"on_mem_memory_changed": self._curmem_changed_cb, "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_list_changed": self._boot_list_changed_cb,
"on_boot_moveup_clicked": self._boot_moveup_clicked_cb, "on_boot_moveup_clicked": self._boot_moveup_clicked_cb,
@ -1463,6 +1464,35 @@ class vmmDetails(vmmGObjectUI):
hotplug_args["memory"] = kwargs["memory"] hotplug_args["memory"] = kwargs["memory"]
hotplug_args["maxmem"] = kwargs["maxmem"] 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( return self._change_config(
self.vm.define_memory, kwargs, self.vm.define_memory, kwargs,
hotplug_args=hotplug_args) hotplug_args=hotplug_args)
@ -1965,6 +1995,28 @@ class vmmDetails(vmmGObjectUI):
curmem.set_value(int(round(vm_cur_mem))) curmem.set_value(int(round(vm_cur_mem)))
maxmem.set_value(int(round(vm_max_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): def _refresh_disk_page(self, disk):
path = disk.get_source_path() path = disk.get_source_path()
devtype = disk.device devtype = disk.device

View File

@ -626,7 +626,8 @@ class vmmDomain(vmmLibvirtObject):
def define_cpu(self, vcpus=_SENTINEL, def define_cpu(self, vcpus=_SENTINEL,
model=_SENTINEL, secure=_SENTINEL, sockets=_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() guest = self._make_xmlobj_to_define()
if vcpus != _SENTINEL: if vcpus != _SENTINEL:
@ -646,6 +647,11 @@ class vmmDomain(vmmLibvirtObject):
guest.cpu.set_special_mode(guest, model) guest.cpu.set_special_mode(guest, model)
else: else:
guest.cpu.set_model(guest, model) guest.cpu.set_model(guest, model)
if memAccess != _SENTINEL:
for cell in guest.cpu.cells:
cell.memAccess = memAccess
self._redefine_xmlobj(guest) self._redefine_xmlobj(guest)
def define_memory(self, memory=_SENTINEL, maxmem=_SENTINEL): def define_memory(self, memory=_SENTINEL, maxmem=_SENTINEL):
@ -657,6 +663,15 @@ class vmmDomain(vmmLibvirtObject):
guest.memory = int(maxmem) guest.memory = int(maxmem)
self._redefine_xmlobj(guest) 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, def define_overview(self, machine=_SENTINEL, description=_SENTINEL,
title=_SENTINEL, loader=_SENTINEL, title=_SENTINEL, loader=_SENTINEL,
nvram=_SENTINEL): nvram=_SENTINEL):