Skip to content

Commit

Permalink
q-dev: fix block device removing
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrbartman committed Oct 24, 2024
1 parent 5b38d7f commit 4a16de5
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 17 deletions.
22 changes: 14 additions & 8 deletions qubes/ext/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,8 @@ async def on_domain_shutdown(self, vm, event, **_kwargs):
if front_vm is None:
continue
dev = BlockDevice(vm, dev_id)
await self._detach_and_notify(vm, dev, options=None)
vm.fire_event(f"device-removed:block", port=dev.port)
await self.detach_and_notify(front_vm, dev.port)
continue
for dev_id, front_vm in self.devices_cache[domain.name].items():
if front_vm == vm:
Expand All @@ -657,14 +658,19 @@ async def on_domain_shutdown(self, vm, event, **_kwargs):
new_cache[domain.name][dev_id] = front_vm
self.devices_cache = new_cache.copy()

async def _detach_and_notify(self, vm, device, options):
def ensure_detach(self, vm, port):
"""
Run this method if device is no longer detected.
If usb device which exposes block device is removed a zombie block
device may remain in vm xml, so we ensure that it will be removed too.
"""
self.on_device_pre_detached_block(vm, "device-pre-detach:block", port)

async def detach_and_notify(self, vm, port):
# bypass DeviceCollection logic preventing double attach
self.on_device_pre_detached_block(
vm, "device-pre-detach:block", device.port
)
await vm.fire_event_async(
"device-detach:block", port=device.port, options=options
)
self.on_device_pre_detached_block(vm, "device-pre-detach:block", port)
await vm.fire_event_async("device-detach:block", port=port)

@qubes.ext.handler("qubes-close", system=True)
def on_qubes_close(self, app, event):
Expand Down
21 changes: 12 additions & 9 deletions qubes/ext/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def device_list_change(
# send events about devices detached/attached outside by themselves
for port_id, front_vm in detached.items():
dev = device_class(vm, port_id)
ext.ensure_detach(front_vm, dev.port)
asyncio.ensure_future(
front_vm.fire_event_async(
f"device-detach:{devclass}", port=dev.port
Expand All @@ -63,8 +64,8 @@ def device_list_change(
for port_id in added:
device = device_class(vm, port_id)
vm.fire_event(f"device-added:{devclass}", device=device)
for dev_ident, front_vm in attached.items():
dev = device_class(vm, dev_ident)
for port_id, front_vm in attached.items():
dev = device_class(vm, port_id)
# options are unknown, device already attached
asyncio.ensure_future(
front_vm.fire_event_async(
Expand Down Expand Up @@ -167,6 +168,7 @@ async def confirm_device_attachment(device, frontends) -> str:
print(str(exc.__class__.__name__) + ":", str(exc), file=sys.stderr)
return ""


async def _do_confirm_device_attachment(device, frontends):
socket = "device-agent.GUI"

Expand All @@ -189,23 +191,24 @@ async def _do_confirm_device_attachment(device, frontends):
"targets": front_names,
"default_target": front_names[0] if number_of_targets == 1 else "",
"icons": {
dom.name
if dom.klass != "DispVM" else f'@dispvm:{dom.name}':
dom.icon for dom in doms.values()
(
dom.name if dom.klass != "DispVM" else f"@dispvm:{dom.name}"
): dom.icon
for dom in doms.values()
},
}

socked_call = asyncio.create_task(call_socket_service(
guivm, socket, "dom0", params, SOCKET_PATH
))
socked_call = asyncio.create_task(
call_socket_service(guivm, socket, "dom0", params, SOCKET_PATH)
)

while not socked_call.done():
await asyncio.sleep(0.1)

ask_response = await socked_call

if ask_response.startswith("allow:"):
chosen = ask_response[len("allow:"):]
chosen = ask_response[len("allow:") :]
if chosen in front_names:
return chosen
return ""

0 comments on commit 4a16de5

Please sign in to comment.