Skip to content

device busy attribute to prevent attaching devices whose children are in use - #144

Open
piotrbartman wants to merge 4 commits into
QubesOS:mainfrom
piotrbartman:qdev/busy
Open

piotrbartman wants to merge 4 commits into
QubesOS:mainfrom
piotrbartman:qdev/busy

Conversation

@piotrbartman

Copy link
Copy Markdown
Member

add busy attribute handling so a device that's in use (attached or used locally) stays visible in QubesDB with a busy=True marker instead of disappearing entirely, and propagates that marker up to the parent disk and the USB ancestor.

  • xs_mark_busy, xs_mark_usb_busy set busy on the device and on the USB parent.
  • local-use detection (is_used) on the device itself still removes it from QDB entirely, but now also marks the USB ancestor busy.
  • usb_parent_still_in_use scans all sibling devices for either attachment or local use, to decide if the USB busy marker can be cleared.
  • new RPC qubes.RefreshBlockDevices re-triggers udev change events for it and its partitions after detach to force a state refresh from the one place that actually knows the truth (backend's sysfs + mount table), instead of guessing from cache.

Open items:

  • mount/umount generate zero block uevents so this whole busy-tracking mechanism refreshed only on the next unrelated udev event (device rescan, another partition's change event, an explicit udevadm trigger). We can consider mount-table watcher; not sure if it's worth it.

…tries

previous udev script just deleted the parent entry when a partition was busy
we keep this behavior for local use
the "busy marker" is propagated to USB parent
if one of subdevices are locally used (e.g. in sys-usb) the parent is considered busy.
@codecov-commenter

codecov-commenter commented Jul 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.27%. Comparing base (0dc52ab) to head (c32fb32).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #144      +/-   ##
==========================================
+ Coverage   71.24%   71.27%   +0.02%     
==========================================
  Files           6        6              
  Lines         991      992       +1     
==========================================
+ Hits          706      707       +1     
  Misses        285      285              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@qubesos-bot

qubesos-bot commented Jul 18, 2026 •

Copy link
Copy Markdown

OpenQA test summary

Complete test suite and dependencies: https://openqa.qubes-os.org/tests/overview?distri=qubesos&version=4.3&build=2026091923-devel&flavor=pull-requests

Test run included the following:

New failures, excluding unstable

Compared to: https://openqa.qubes-os.org/tests/overview?distri=qubesos&version=4.3&build=2026050504-devel&flavor=update

  • system_tests_dispvm

  • system_tests_gpu_passthrough@hw13

    • gpu_passthrough: Failed (test died)
      # Test died: command 'ansible-playbook -i inventory -e pci_devices=...
  • system_tests_qwt_win10@hw13

    • windows_install: wait_serial (wait serial expected)
      # wait_serial expected: qr/install-complete-\d+-/...

Failed tests

9 failures
  • system_tests_whonix

    • [unstable] whonixcheck: fail (unknown)
      Whonixcheck for anon-whonix failed...

    • [unstable] whonixcheck: Failed (test died)
      # Test died: systemcheck failed at qubesos/tests/whonixcheck.pm lin...

  • system_tests_network_updates

    • [unstable] TC_11_QvmTemplateMgmtVM_whonix-gateway-18: test_000_template_list (error)
      subprocess.CalledProcessError: Command 'timeout=120; while ! tor-ci...
  • system_tests_dispvm

  • system_tests_gpu_passthrough@hw13

    • gpu_passthrough: Failed (test died)
      # Test died: command 'ansible-playbook -i inventory -e pci_devices=...
  • system_tests_whonix@hw1

    • [unstable] whonixcheck: fail (unknown)
      Whonixcheck for whonix-workstation-18 failed...

    • [unstable] whonixcheck: Failed (test died)
      # Test died: systemcheck failed at qubesos/tests/whonixcheck.pm lin...

  • system_tests_qwt_win10@hw13

    • windows_install: wait_serial (wait serial expected)
      # wait_serial expected: qr/install-complete-\d+-/...

    • windows_install: Failed (test died + timed out)
      # Test died: Install timed out at qubesos/tests/windows_install.pm ...

Fixed failures

Compared to: https://openqa.qubes-os.org/tests/176874#dependencies

37 fixed
  • system_tests_pvgrub_salt_storage

    • system_tests: Fail (unknown)
      Tests qubes.tests.integ.grub failed (exit code 1), details reported...

    • system_tests: Failed (test died)
      # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...

    • TC_41_HVMGrub_debian-13-xfce: test_000_standalone_vm (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

    • TC_41_HVMGrub_debian-13-xfce: test_001_standalone_vm_dracut (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

    • TC_41_HVMGrub_debian-13-xfce: test_010_template_based_vm (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

    • TC_41_HVMGrub_debian-13-xfce: test_011_template_based_vm_dracut (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

    • TC_41_HVMGrub_fedora-43-xfce: test_010_template_based_vm (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

  • system_tests_extra

    • system_tests: Fail (unknown)
      Tests qubes.tests.extra failed (exit code 1), details reported sepa...

    • system_tests: Failed (test died)
      # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...

    • TC_01_InputProxyExclude_debian-13-xfce: test_000_qemu_tablet (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

    • TC_01_InputProxyExclude_fedora-43-xfce: test_000_qemu_tablet (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

    • TC_00_QVCTest_fedora-43-xfce: test_010_screenshare (failure + cleanup)
      ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^... AssertionError: 1179648 != 0

    • TC_00_QVCTest_whonix-gateway-18: test_010_screenshare (failure + cleanup)
      AssertionError: 2.3156185715769593 not less than 2.0

    • TC_00_PDFConverter_fedora-43-xfce: test_004_cancel_stops_conversion (failure)
      AssertionError: DispVM not cleaned up 10s after cancel: {<DispVM at...

  • system_tests_usbproxy

    • system_tests: Fail (unknown)
      Tests qubes.tests.extra failed (exit code 1), details reported sepa...

    • system_tests: Failed (test died)
      # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...

    • system_tests: wait_serial (wait serial expected)
      # wait_serial expected: qr/h3uXO-\d+-/...

    • TC_20_USBProxy_core3_fedora-43-xfce: test_090_attach_stubdom (error)
      qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...

  • system_tests_network_ipv6

    • system_tests: Fail (unknown)
      Tests qubes.tests.integ.network_ipv6 failed (exit code 1), details ...

    • system_tests: Failed (test died)
      # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...

    • VmIPv6Networking_fedora-43-xfce: test_001_simple_networking_paused_from_none_to_existent (error)
      raise TimeoutError from exc_val... TimeoutError

  • system_tests_audio

  • system_tests_audio@hw1

    • system_tests: Fail (unknown)
      Tests qubes.tests.integ.audio failed (exit code 1), details reporte...

    • system_tests: Failed (test died)
      # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...

    • TC_20_AudioVM_Pulse_debian-13-xfce: test_222_audio_rec_unmuted_pulseaudio (failure)
      AssertionError: only silence detected, no useful audio data

  • system_tests_guivm_gpu_gui_interactive@hw13

    • shutdown: unnamed test (unknown)
    • shutdown: Failed (test died)
      # Test died: no candidate needle with tag(s) 'text-logged-in-root' ...
  • system_tests_qwt_win10_seamless@hw13

    • windows_clipboard_and_filecopy: unnamed test (unknown)
    • windows_clipboard_and_filecopy: Failed (test died)
      # Test died: no candidate needle with tag(s) 'windows-Edge-address-...
  • system_tests_qwt_win11@hw13

    • windows_install: Failed (test died)
      # Test died: Install failed with code 1 at qubesos/tests/windows_in...

Unstable tests

Details
  • system_tests_whonix

    whonixcheck/Failed (1/5 times with errors)
    • job 195438 # Test died: command 'qvm-run -ap anon-whonix 'LC_ALL=C whonixcheck...
    whonixcheck/Failed (1/5 times with errors)
    • job 196176 # Test died: systemcheck failed at qubesos/tests/whonixcheck.pm lin...
    whonixcheck/fail (1/5 times with errors)
    • job 196176 Whonixcheck for anon-whonix failed...
    whonixcheck/fail (1/5 times with errors)
    whonixcheck/wait_serial (1/5 times with errors)
    • job 195438 # Command: qvm-run -ap anon-whonix 'LC_ALL=C whonixcheck --verbose ...
  • system_tests_gui_tools

    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/Failed (1/5 times with errors)
    • job 196597 # Test died: no candidate needle with tag(s) 'new-qube-remove-firef...
    desktop_linux_manager_create_qube/Failed (1/5 times with errors)
    • job 196628 # Test died: no candidate needle with tag(s) 'new-qube-createtest-s...
  • system_tests_basic_vm_qrexec_gui

    system_tests/Fail (1/5 times with errors)
    • job 195163 Tests qubes.tests.integ.basic failed (exit code 1), details reporte...
    system_tests/Failed (1/5 times with errors)
    • job 195163 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_30_Gui_daemon/test_002_clipboard_300k (1/5 times with errors)
    • job 195163 : Clipboard copy operation failed - content...
  • system_tests_extra

    system_tests/Fail (2/5 times with errors)
    • job 195463 Tests qubes.tests.extra failed (exit code 1), details reported sepa...
    • job 196201 Tests qubes.tests.extra failed (exit code 1), details reported sepa...
    system_tests/Failed (1/5 times with errors)
    • job 195170 # Test died: command 'testfunc qubes.tests.extra' timed out...
    system_tests/Failed (2/5 times with errors)
    • job 195463 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    • job 196201 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_00_PDFConverter_debian-13-xfce/test_004_cancel_stops_conversion (1/5 times with errors)
    • job 196201 AssertionError: DispVM not cleaned up 10s after cancel: {<DispVM at...
    TC_00_PDFConverter_fedora-43-xfce/test_004_cancel_stops_conversion (1/5 times with errors)
    • job 196201 AssertionError: DispVM not cleaned up 10s after cancel: {<DispVM at...
    TC_00_PDFConverter_fedora-44-xfce/test_004_cancel_stops_conversion (1/5 times with errors)
    • job 195463 AssertionError: DispVM not cleaned up 10s after cancel: {<DispVM at...
    system_tests/wait_serial (1/5 times with errors)
    • job 195170 # Command: testfunc qubes.tests.extra...
  • system_tests_guivm_gui_interactive

    simple_gui_apps/ (1/5 times with errors)
    simple_gui_apps/ (1/5 times with errors)
    simple_gui_apps/Failed (1/5 times with errors)
    • job 196598 # Test died: no candidate needle with tag(s) 'vm-settings-app-xterm...
  • system_tests_usbproxy

    system_tests/Fail (2/5 times with errors)
    • job 195144 Tests qubes.tests.extra failed (exit code 1), details reported sepa...
    • job 195437 Tests qubes.tests.extra failed (exit code 1), details reported sepa...
    system_tests/Failed (2/5 times with errors)
    • job 195144 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    • job 195437 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_00_USBProxy_fedora-44-xfce/test_020_detach_on_remove (1/5 times with errors)
    • job 195437 AssertionError: 0 != 1 : Device not cleaned up
    TC_20_USBProxy_core3_fedora-44-xfce/test_030_detach (1/5 times with errors)
    • job 195144 qubesusbproxy.core3ext.QubesUSBException: Device detach failed: 20...
  • system_tests_qrexec

    system_tests/Fail (1/5 times with errors)
    • job 196474 Tests qubes.tests.integ.qrexec failed (exit code 1), details report...
    system_tests/Failed (1/5 times with errors)
    • job 196474 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_00_Qrexec_whonix-workstation-18/test_055_qrexec_dom0_service_abort (1/5 times with errors)
    • job 196474 AssertionError: Timeout, probably stdout wasn't closed
  • system_tests_network_updates

    system_tests/Fail (3/5 times with errors)
    • job 195727 Tests qubes.tests.integ.dom0_update failed (exit code 1), details r...
    • job 196207 Tests qubes.tests.integ.dom0_update failed (exit code 1), details r...
    • job 196250 Tests qubes.tests.integ.dom0_update failed (exit code 1), details r...
    system_tests/Failed (1/5 times with errors)
    • job 195469 # Test died: command 'curl --form upload=@tests-qubes.tests.integ.d...
    system_tests/Failed (3/5 times with errors)
    • job 195727 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    • job 196207 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    • job 196250 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_11_QvmTemplateMgmtVM_whonix-gateway-18/test_000_template_list (1/5 times with errors)
    • job 195727 subprocess.CalledProcessError: Command 'timeout=120; while ! tor-ci...
    TC_00_Dom0Upgrade_whonix-gateway-18/test_000_update (1/5 times with errors)
    • job 196207 Error: Failed to download metadata for repo 'test': Cannot download...
    TC_00_Dom0Upgrade_whonix-gateway-18/test_005_update_flag_clear (1/5 times with errors)
    • job 196250 subprocess.CalledProcessError: Command 'timeout=120; while ! tor-ci...
    TC_00_Dom0Upgrade_whonix-gateway-18/test_006_update_flag_clear (1/5 times with errors)
    • job 196207 subprocess.CalledProcessError: Command 'timeout=120; while ! tor-ci...
    TC_00_Dom0Upgrade_whonix-gateway-18/test_010_instal (1/5 times with errors)
    • job 195727 Error: Failed to download metadata for repo 'test': Yum repo downlo...
    TC_00_Dom0Upgrade_whonix-gateway-18/test_010_instal (1/5 times with errors)
    • job 196250 Error: Failed to download metadata for repo 'test': Cannot download...
    TC_11_QvmTemplateMgmtVM_fedora-43-xfce/test_010_template_install (1/5 times with errors)
    • job 196250 AssertionError: qvm-template failed: [Qrexec] ERROR: dnf command is...
  • system_tests_basic_vm_qrexec_gui_zfs

    switch_pool/Failed (2/5 times with errors)
    • job 196241 # Test died: command 'qvm-start --skip-if-running sys-firewall sys-...
    • job 196592 # Test died: command 'qvm-start --skip-if-running sys-firewall sys-...
  • system_tests_guivm_vnc_gui_interactive

    clipboard_and_web/ (1/5 times with errors)
    guivm_manager/ (1/5 times with errors)
    guivm_manager/ (1/5 times with errors)
    simple_gui_apps/ (1/5 times with errors)
    simple_gui_apps/ (1/5 times with errors)
    clipboard_and_web/Failed (1/5 times with errors)
    • job 196265 # Test died: no candidate needle with tag(s) 'personal-firefox' mat...
    guivm_manager/Failed (1/5 times with errors)
    • job 196631 # Test died: no candidate needle with tag(s) 'vm-settings-applicati...
    guivm_manager/Failed (1/5 times with errors)
    • job 196578 # Test died: no candidate needle with tag(s) 'desktop-clear' matche...
    guivm_startup/Failed (1/5 times with errors)
    • job 196449 # Test died: command 'qvm-start --skip-if-running sys-gui-vnc' time...
    simple_gui_apps/Failed (1/5 times with errors)
    • job 196659 # Test died: no candidate needle with tag(s) 'desktop' matched...
    guivm_startup/wait_serial (1/5 times with errors)
    • job 196449 # Command: qvm-start --skip-if-running sys-gui-vnc...
    guivm_startup/wait_serial (1/5 times with errors)
    • job 196449 # Command: qvm-run --no-gui -p -u root sys-gui-vnc 'cat /home/user/...
  • system_tests_whonix@hw1

    whonixcheck/Failed (1/5 times with errors)
    • job 195438 # Test died: command 'qvm-run -ap anon-whonix 'LC_ALL=C whonixcheck...
    whonixcheck/Failed (1/5 times with errors)
    • job 196176 # Test died: systemcheck failed at qubesos/tests/whonixcheck.pm lin...
    whonixcheck/fail (1/5 times with errors)
    • job 196176 Whonixcheck for anon-whonix failed...
    whonixcheck/fail (1/5 times with errors)
    whonixcheck/wait_serial (1/5 times with errors)
    • job 195438 # Command: qvm-run -ap anon-whonix 'LC_ALL=C whonixcheck --verbose ...
  • system_tests_basic_vm_qrexec_gui_btrfs

    system_tests/Failed (1/5 times with errors)
    • job 195457 # Test died: command 'curl --form upload=@tests-qubes.tests.integ.b...
  • system_tests_basic_vm_qrexec_gui_ext4

    system_tests/Fail (1/5 times with errors)
    • job 195165 Tests qubes.tests.integ.vm_qrexec_gui failed (exit code 1), details...
    system_tests/Failed (1/5 times with errors)
    • job 195165 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_20_NonAudio_fedora-44-xfce-pool/test_500_gui_agent_env_sync (1/5 times with errors)
    • job 195165 qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...
  • system_tests_basic_vm_qrexec_gui_xfs

    startup/ (1/5 times with errors)
    system_tests/Fail (1/5 times with errors)
    • job 196591 Tests qubes.tests.integ.vm_qrexec_gui failed (exit code 1), details...
    startup/Failed (1/5 times with errors)
    • job 196462 # Test died: no candidate needle with tag(s) 'luks-prompt, login-pr...
    system_tests/Failed (1/5 times with errors)
    • job 196591 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_20_NonAudio_fedora-44-xfce-pool/test_140_qrexec_filecopy_unsafe_name (1/5 times with errors)
    • job 196591 qubes.exc.QubesVMError: Cannot connect to qrexec agent for 120 seco...
    startup/wait_serial (1/5 times with errors)
    • job 196462 # wait_serial expected: qr/login:\s*$|root@.*#\s*$/ui...
    startup/wait_serial (1/5 times with errors)
    • job 196462 # wait_serial expected: qr/PS1="root# "/u...
  • system_tests_basic_vm_qrexec_gui@hw7

    system_tests/Fail (1/5 times with errors)
    • job 195163 Tests qubes.tests.integ.basic failed (exit code 1), details reporte...
    system_tests/Failed (1/5 times with errors)
    • job 195163 # Test died: Some tests failed at qubesos/tests/system_tests.pm lin...
    TC_30_Gui_daemon/test_002_clipboard_300k (1/5 times with errors)
    • job 195163 : Clipboard copy operation failed - content...
  • system_tests_gui_tools@hw7

    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/ (1/5 times with errors)
    desktop_linux_manager_create_qube/Failed (1/5 times with errors)
    • job 196597 # Test died: no candidate needle with tag(s) 'new-qube-remove-firef...
    desktop_linux_manager_create_qube/Failed (1/5 times with errors)
    • job 196628 # Test died: no candidate needle with tag(s) 'new-qube-createtest-s...

Performance Tests

Performance degradation:

No issues

Remaining performance tests:

111 tests
  • debian-13-xfce_exec: 8.57
  • debian-13-xfce_exec-root: 27.60
  • debian-13-xfce_socket: 8.39
  • debian-13-xfce_socket-root: 8.66
  • debian-13-xfce_exec-data-simplex: 65.23
  • debian-13-xfce_exec-data-duplex: 67.09
  • debian-13-xfce_exec-data-duplex-root: 82.61
  • debian-13-xfce_socket-data-duplex: 88.24
  • fedora-44-xfce_exec: 9.13
  • fedora-44-xfce_exec-root: 73.38
  • fedora-44-xfce_socket: 8.86
  • fedora-44-xfce_socket-root: 8.74
  • fedora-44-xfce_exec-data-simplex: 66.49
  • fedora-44-xfce_exec-data-duplex: 70.02
  • fedora-44-xfce_exec-data-duplex-root: 108.92
  • fedora-44-xfce_socket-data-duplex: 95.49
  • whonix-gateway-18_exec: 7.14
  • whonix-gateway-18_exec-root: 152.26
  • whonix-gateway-18_socket: 9.27
  • whonix-gateway-18_socket-root: 8.62
  • whonix-gateway-18_exec-data-simplex: 67.38
  • whonix-gateway-18_exec-data-duplex: 66.53
  • whonix-gateway-18_exec-data-duplex-root: 147.44
  • whonix-gateway-18_socket-data-duplex: 101.71
  • whonix-workstation-18_exec: 7.40
  • whonix-workstation-18_exec-root: 173.18
  • whonix-workstation-18_socket: 10.71
  • whonix-workstation-18_socket-root: 11.40
  • whonix-workstation-18_exec-data-simplex: 73.82
  • whonix-workstation-18_exec-data-duplex: 72.15
  • whonix-workstation-18_exec-data-duplex-root: 156.67
  • whonix-workstation-18_socket-data-duplex: 94.07
  • dom0_root_seq1m_q8t1_read 3:read_bandwidth_kb: 500752.00
  • dom0_root_seq1m_q8t1_write 3:write_bandwidth_kb: 237556.00
  • dom0_root_seq1m_q1t1_read 3:read_bandwidth_kb: 436724.00
  • dom0_root_seq1m_q1t1_write 3:write_bandwidth_kb: 209967.00
  • dom0_root_rnd4k_q32t1_read 3:read_bandwidth_kb: 102656.00
  • dom0_root_rnd4k_q32t1_write 3:write_bandwidth_kb: 11271.00
  • dom0_root_rnd4k_q1t1_read 3:read_bandwidth_kb: 8647.00
  • dom0_root_rnd4k_q1t1_write 3:write_bandwidth_kb: 4096.00
  • dom0_varlibqubes_seq1m_q8t1_read 3:read_bandwidth_kb: 510753.00
  • dom0_varlibqubes_seq1m_q8t1_write 3:write_bandwidth_kb: 335436.00
  • dom0_varlibqubes_seq1m_q1t1_read 3:read_bandwidth_kb: 387643.00
  • dom0_varlibqubes_seq1m_q1t1_write 3:write_bandwidth_kb: 202958.00
  • dom0_varlibqubes_rnd4k_q32t1_read 3:read_bandwidth_kb: 109114.00
  • dom0_varlibqubes_rnd4k_q32t1_write 3:write_bandwidth_kb: 10153.00
  • dom0_varlibqubes_rnd4k_q1t1_read 3:read_bandwidth_kb: 7178.00
  • dom0_varlibqubes_rnd4k_q1t1_write 3:write_bandwidth_kb: 3288.00
  • fedora-44-xfce_root_seq1m_q8t1_read 3:read_bandwidth_kb: 192051.00
  • fedora-44-xfce_root_seq1m_q8t1_write 3:write_bandwidth_kb: 128023.00
  • fedora-44-xfce_root_seq1m_q1t1_read 3:read_bandwidth_kb: 282940.00
  • fedora-44-xfce_root_seq1m_q1t1_write 3:write_bandwidth_kb: 44371.00
  • fedora-44-xfce_root_rnd4k_q32t1_read 3:read_bandwidth_kb: 93660.00
  • fedora-44-xfce_root_rnd4k_q32t1_write 3:write_bandwidth_kb: 1910.00
  • fedora-44-xfce_root_rnd4k_q1t1_read 3:read_bandwidth_kb: 8795.00
  • fedora-44-xfce_root_rnd4k_q1t1_write 3:write_bandwidth_kb: 287.00
  • fedora-44-xfce_private_seq1m_q8t1_read 3:read_bandwidth_kb: 348017.00
  • fedora-44-xfce_private_seq1m_q8t1_write 3:write_bandwidth_kb: 148858.00
  • fedora-44-xfce_private_seq1m_q1t1_read 3:read_bandwidth_kb: 296291.00
  • fedora-44-xfce_private_seq1m_q1t1_write 3:write_bandwidth_kb: 56434.00
  • fedora-44-xfce_private_rnd4k_q32t1_read 3:read_bandwidth_kb: 91766.00
  • fedora-44-xfce_private_rnd4k_q32t1_write 3:write_bandwidth_kb: 1354.00
  • fedora-44-xfce_private_rnd4k_q1t1_read 3:read_bandwidth_kb: 8919.00
  • fedora-44-xfce_private_rnd4k_q1t1_write 3:write_bandwidth_kb: 1228.00
  • fedora-44-xfce_volatile_seq1m_q8t1_read 3:read_bandwidth_kb: 400525.00
  • fedora-44-xfce_volatile_seq1m_q8t1_write 3:write_bandwidth_kb: 86755.00
  • fedora-44-xfce_volatile_seq1m_q1t1_read 3:read_bandwidth_kb: 318813.00
  • fedora-44-xfce_volatile_seq1m_q1t1_write 3:write_bandwidth_kb: 23516.00
  • fedora-44-xfce_volatile_rnd4k_q32t1_read 3:read_bandwidth_kb: 14496.00
  • fedora-44-xfce_volatile_rnd4k_q32t1_write 3:write_bandwidth_kb: 2847.00
  • fedora-44-xfce_volatile_rnd4k_q1t1_read 3:read_bandwidth_kb: 8407.00
  • fedora-44-xfce_volatile_rnd4k_q1t1_write 3:write_bandwidth_kb: 1148.00
  • debian-13-xfce_dom0-dispvm-api (mean:8.325): 99.90
  • debian-13-xfce_dom0-dispvm-gui-api (mean:10.548): 126.57
  • debian-13-xfce_dom0-dispvm-preload-2-api (mean:5.628): 67.54
  • debian-13-xfce_dom0-dispvm-preload-2-delay-0-api (mean:5.193): 62.31
  • debian-13-xfce_dom0-dispvm-preload-2-delay-minus-1d2-api (mean:5.904): 70.85
  • debian-13-xfce_dom0-dispvm-preload-4-api (mean:5.512): 66.14
  • debian-13-xfce_dom0-dispvm-preload-4-delay-0-api (mean:5.512): 66.14
  • debian-13-xfce_dom0-dispvm-preload-4-delay-minus-1d2-api (mean:4.946): 59.35
  • debian-13-xfce_dom0-dispvm-preload-2-gui-api (mean:6.993): 83.92
  • debian-13-xfce_dom0-dispvm-preload-4-gui-api (mean:6.401): 76.81
  • debian-13-xfce_dom0-dispvm-preload-6-gui-api (mean:6.497): 77.96
  • debian-13-xfce_dom0-vm-api (mean:0.027): 0.32
  • debian-13-xfce_dom0-vm-gui-api (mean:0.032): 0.38
  • fedora-44-xfce_dom0-dispvm-api (mean:10.499): 125.99
  • fedora-44-xfce_dom0-dispvm-gui-api (mean:12.382): 148.59
  • fedora-44-xfce_dom0-dispvm-preload-2-api (mean:6.238): 74.86
  • fedora-44-xfce_dom0-dispvm-preload-2-delay-0-api (mean:6.019): 72.23
  • fedora-44-xfce_dom0-dispvm-preload-2-delay-minus-1d2-api (mean:6.766): 81.19
  • fedora-44-xfce_dom0-dispvm-preload-4-api (mean:5.631): 67.57
  • fedora-44-xfce_dom0-dispvm-preload-4-delay-0-api (mean:6.046): 72.55
  • fedora-44-xfce_dom0-dispvm-preload-4-delay-minus-1d2-api (mean:5.451): 65.41
  • fedora-44-xfce_dom0-dispvm-preload-2-gui-api (mean:8.003): 96.04
  • fedora-44-xfce_dom0-dispvm-preload-4-gui-api (mean:6.87): 82.44
  • fedora-44-xfce_dom0-dispvm-preload-6-gui-api (mean:6.937): 83.25
  • fedora-44-xfce_dom0-vm-api (mean:0.016): 0.19
  • fedora-44-xfce_dom0-vm-gui-api (mean:0.039): 0.47
  • whonix-workstation-18_dom0-dispvm-api (mean:11.94): 143.28
  • whonix-workstation-18_dom0-dispvm-gui-api (mean:14.203): 170.44
  • whonix-workstation-18_dom0-dispvm-preload-2-api (mean:7.214): 86.57
  • whonix-workstation-18_dom0-dispvm-preload-2-delay-0-api (mean:7.036): 84.43
  • whonix-workstation-18_dom0-dispvm-preload-2-delay-minus-1d2-api (mean:7.605): 91.26
  • whonix-workstation-18_dom0-dispvm-preload-4-api (mean:6.491): 77.90
  • whonix-workstation-18_dom0-dispvm-preload-4-delay-0-api (mean:6.632): 79.59
  • whonix-workstation-18_dom0-dispvm-preload-4-delay-minus-1d2-api (mean:6.168): 74.01
  • whonix-workstation-18_dom0-dispvm-preload-2-gui-api (mean:8.566): 102.80
  • whonix-workstation-18_dom0-dispvm-preload-4-gui-api (mean:7.305): 87.67
  • whonix-workstation-18_dom0-dispvm-preload-6-gui-api (mean:7.663): 91.96
  • whonix-workstation-18_dom0-vm-api (mean:0.029): 0.35
  • whonix-workstation-18_dom0-vm-gui-api (mean:0.054): 0.65

A device that is used (mounted etc.) locally by backend VM must not be handed to another one. This exposes them as a `used` ones. The marker means that the device, or it's child in use *locally*. Based on this marker and current attachment we discover if device is `busy`. Only backend VM writes to QubesDB and only about internal state. For this reason `busy` was renamed to `used` in QubesDB path.

Mounting generates no block uevent, so qubes-block-mount-watcher polls
the mount table and re-triggers the affected devices.

`/qubes-device-usage-tracking` tells if a qube reports usage.
`udev-qubes-vbd` handles detach
`qubes.RefreshBlockDevices` handles attach
for different drivers previous solution does not work and we end up with garbage in qubesDB.
@@ -0,0 +1,75 @@
#!/usr/bin/python3

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really happy about yet another long-running python process in every VM due to memory usage... This one looks to take about 18MB.
IIUC there is no passive place to plug a hook into. Can this be in C, or maybe Rust? I'd expect a process like this should really need just a couple of kilobytes of memory, definitely below 1MB...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I think C is the better fit here since there aren't many reasons to introduce rust: poll() needs an unsafe extern regardless, and the only mountinfo field we parse is major:minor, which comes before the mount point, so no malicious string ever reaches the parser.

About "another resident process": the used markers only matter on lists or attaches, so qubesd could just call qubes.RefreshBlockDevices before a listing and we could drop the watcher. Drawbacks: a qrexec call per listing (the widget lists often), listing turning into a blocking call (not great) instead of a QubesDB read, and potentially stale state in the GUI (cache issues). So I decided to build a watcher.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's nice for the VM to send this info on its own, so I agree this is a useful thing to have (given lack of passive alternatives).

This branch was successfully deployed

1 active deployment
qa — c32fb32b Deployed Sep 19, 2026 by qubesos-qa[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants