Skip to content

Commit 7de7cf3

Browse files
committed
Cache block devices
1 parent cbb5601 commit 7de7cf3

1 file changed

Lines changed: 38 additions & 7 deletions

File tree

qubes/ext/block.py

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,8 @@ def _is_attached_to(self, vm):
233233

234234
for disk in xml_desc.findall("devices/disk[source][@type='block']"):
235235
backend_domain, port_id = _try_get_block_device_info(vm.app, disk)
236-
237236
if backend_domain.name != self.backend_domain.name:
238237
continue
239-
240238
if self.port_id == port_id:
241239
return True
242240
return False
@@ -307,6 +305,12 @@ def _try_get_block_device_info(app, disk):
307305

308306
class BlockDeviceExtension(qubes.ext.Extension):
309307

308+
def __init__(self):
309+
super().__init__()
310+
# TODO: ben: https://github.com/QubesOS/qubes-core-admin/pull/819#discussion_r3537683559
311+
self._attachments = {}
312+
self._attachments_with_options = {}
313+
310314
@qubes.ext.handler("domain-init", "domain-load")
311315
def on_domain_init_load(self, vm, event):
312316
"""Initialize watching for changes"""
@@ -327,6 +331,24 @@ def on_domain_init_load(self, vm, event):
327331
else:
328332
self.devices_cache[vm.name] = {}
329333

334+
@qubes.ext.handler("device-attach:block")
335+
def on_device_block_attach(self, vm, event, device, options):
336+
# pylint: disable=unused-argument
337+
self._attachments[device.port_id] = device.backend_domain
338+
339+
@qubes.ext.handler("device-detach:block")
340+
def on_device_block_detach(self, vm, event, port):
341+
# pylint: disable=unused-argument
342+
if port in self._attachments:
343+
self._attachments.pop(port)
344+
if vm not in self._attachments_with_options:
345+
return
346+
if port not in self._attachments_with_options[vm]:
347+
return
348+
for device, _options in self._attachments_with_options[vm].items():
349+
if device.port_id == port:
350+
self._attachments_with_options[vm].pop(device)
351+
330352
@qubes.ext.handler("domain-qdb-change:/qubes-block-devices")
331353
def on_qdb_change(self, vm, event, path):
332354
"""A change in QubesDB means a change in a device list."""
@@ -338,8 +360,7 @@ def on_qdb_change(self, vm, event, path):
338360
)
339361
utils.device_list_change(self, current_devices, vm, path, BlockDevice)
340362

341-
@staticmethod
342-
def get_device_attachments(vm_):
363+
def get_device_attachments(self, vm_):
343364
result = {}
344365
for vm in vm_.app.domains:
345366
if not vm.is_running() or isinstance(vm, RemoteVM):
@@ -348,7 +369,10 @@ def get_device_attachments(vm_):
348369
if vm.app.vmm.offline_mode:
349370
return result
350371

351-
# TODO: ben: cache
372+
if vm in self._attachments:
373+
result = self._attachments[vm]
374+
continue
375+
352376
xml_desc = lxml.etree.fromstring(vm.libvirt_domain.XMLDesc())
353377

354378
for disk in xml_desc.findall("devices/disk[source][@type='block']"):
@@ -359,6 +383,7 @@ def get_device_attachments(vm_):
359383
continue
360384

361385
result[port_id] = vm
386+
self._attachments[vm] = result
362387
return result
363388

364389
@staticmethod
@@ -422,10 +447,14 @@ def on_device_list_attached(self, vm, event, **kwargs):
422447
if not vm.is_running():
423448
return
424449

450+
if vm in self._attachments_with_options:
451+
yield from self._attachments_with_options[vm]
452+
return
453+
self._attachments_with_options[vm] = []
454+
425455
system_disks = SYSTEM_DISKS
426456
if getattr(vm, "kernel", None):
427457
system_disks = SYSTEM_DISKS_DOM0_KERNEL
428-
# TODO: ben: cache
429458
xml_desc = lxml.etree.fromstring(vm.libvirt_domain.XMLDesc())
430459

431460
for disk in xml_desc.findall(
@@ -450,7 +479,9 @@ def on_device_list_attached(self, vm, event, **kwargs):
450479
if devtype != "disk":
451480
options["devtype"] = devtype
452481

453-
yield BlockDevice(Port(backend_domain, port_id, "block")), options
482+
dev = BlockDevice(Port(backend_domain, port_id, "block")), options
483+
yield dev
484+
self._attachments_with_options[vm].append(dev)
454485

455486
@staticmethod
456487
def _is_block(vm, block: str) -> bool:

0 commit comments

Comments
 (0)