From 05cca69cc6f8ae3bafecb654e8e3b6a7d3ad39fa Mon Sep 17 00:00:00 2001 From: luytan Date: Mon, 11 May 2026 17:51:21 +0200 Subject: [PATCH 1/4] fix: avoid infinite loop on gpu blocking --- crates/cardwire-core/src/gpu/ebpf.rs | 65 +++++++++++++--------------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/crates/cardwire-core/src/gpu/ebpf.rs b/crates/cardwire-core/src/gpu/ebpf.rs index a69712c..eae3e9e 100644 --- a/crates/cardwire-core/src/gpu/ebpf.rs +++ b/crates/cardwire-core/src/gpu/ebpf.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; use crate::{errors::Error as CardwireError, gpu::models::GpuDevice, pci::PciDevice}; use cardwire_ebpf::EbpfBlocker; +use log::{info, warn}; pub struct GpuBlocker { inner: EbpfBlocker, @@ -74,7 +75,7 @@ pub fn block_gpu( if block { blocker.inner.block_card(card_id)?; blocker.inner.block_render(render_id)?; - recursive_block_pci(blocker, gpu, pci_list)?; + chain_block_pci(blocker, gpu, pci_list)?; if gpu.nvidia() { blocker.inner.block_nvidia(gpu.nvidia_minor().unwrap())? } @@ -82,7 +83,7 @@ pub fn block_gpu( } else { blocker.inner.unblock_card(card_id)?; blocker.inner.unblock_render(render_id)?; - recursive_unblock_pci(blocker, gpu, pci_list)?; + chain_unblock_pci(blocker, gpu, pci_list)?; if gpu.nvidia() { blocker.inner.unblock_nvidia(gpu.nvidia_minor().unwrap())? } @@ -90,44 +91,42 @@ pub fn block_gpu( } } -fn recursive_block_pci( +fn chain_block_pci( blocker: &mut GpuBlocker, gpu: &GpuDevice, pci_list: &BTreeMap, ) -> Result<(), CardwireError> { // Block the gpu pci blocker.inner.block_pci(gpu.pci.pci_address())?; + info!("blocking pci: {}", gpu.pci.pci_address()); // also block audio card if gpu.pci.pci_address().ends_with(".0") { - let gpu_audio_adress = gpu.pci.pci_address().to_string().replace(".0", ".1"); + let gpu_audio_adress = gpu.pci.pci_address().replace(".0", ".1"); blocker.inner.block_pci(&gpu_audio_adress)?; } // Check if gpu has a parent pci - if gpu.pci.parent_pci().is_some() { - // first pci to block - let mut parent_pci: String = gpu.pci.parent_pci().clone().unwrap(); - loop { - // Also block the parent pci - if let Some(pci_device) = pci_list.get(&parent_pci) { - blocker.inner.block_pci(pci_device.pci_address())?; - if pci_device.parent_pci().is_some() { - // if the device contain a parent, continue the loop - parent_pci = pci_device.parent_pci().clone().unwrap() - } else { - // if no parent. exit the loop - break; - } - } + // first pci to block + let mut current_parent = gpu.pci.parent_pci().clone(); + + while let Some(parent_pci) = current_parent { + if let Some(pci_device) = pci_list.get(&parent_pci) { + info!("chain blocking pci: {}", gpu.pci.pci_address()); + blocker.inner.block_pci(pci_device.pci_address())?; + current_parent = pci_device.parent_pci().clone(); + } else { + warn!("expected parent pci {} not found in pci_list", parent_pci); + break; } } Ok(()) } -fn recursive_unblock_pci( +fn chain_unblock_pci( blocker: &mut GpuBlocker, gpu: &GpuDevice, pci_list: &BTreeMap, ) -> Result<(), CardwireError> { // Unblock the gpu pci + info!("unblocking pci: {}", gpu.pci.pci_address()); blocker.inner.unblock_pci(gpu.pci.pci_address())?; // also unblock audio card if gpu.pci.pci_address().ends_with(".0") { @@ -135,21 +134,17 @@ fn recursive_unblock_pci( blocker.inner.block_pci(&gpu_audio_adress)?; } // Check if gpu has a parent pci - if gpu.pci.parent_pci().is_some() { - // first pci to block - let mut parent_pci: String = gpu.pci.parent_pci().clone().unwrap(); - loop { - // Also block the parent pci - if let Some(pci_device) = pci_list.get(&parent_pci) { - blocker.inner.unblock_pci(pci_device.pci_address())?; - if pci_device.parent_pci().is_some() { - // if the device contain a parent, continue the loop - parent_pci = pci_device.parent_pci().clone().unwrap() - } else { - // if no parent. exit the loop - break; - } - } + // first pci to block + let mut current_parent = gpu.pci.parent_pci().clone(); + + while let Some(parent_pci) = current_parent { + if let Some(pci_device) = pci_list.get(&parent_pci) { + info!("chain unblocking pci: {}", gpu.pci.pci_address()); + blocker.inner.unblock_pci(pci_device.pci_address())?; + current_parent = pci_device.parent_pci().clone(); + } else { + warn!("expected parent pci {} not found in pci_list", parent_pci); + break; } } Ok(()) From f563c4eecacfe3619b27364dc96a877d90420659 Mon Sep 17 00:00:00 2001 From: luytan Date: Mon, 11 May 2026 17:56:45 +0200 Subject: [PATCH 2/4] fix: wrong variable used in chain blocking info --- crates/cardwire-core/src/gpu/ebpf.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cardwire-core/src/gpu/ebpf.rs b/crates/cardwire-core/src/gpu/ebpf.rs index eae3e9e..8015534 100644 --- a/crates/cardwire-core/src/gpu/ebpf.rs +++ b/crates/cardwire-core/src/gpu/ebpf.rs @@ -110,7 +110,7 @@ fn chain_block_pci( while let Some(parent_pci) = current_parent { if let Some(pci_device) = pci_list.get(&parent_pci) { - info!("chain blocking pci: {}", gpu.pci.pci_address()); + info!("chain blocking pci: {}", pci_device.pci_address()); blocker.inner.block_pci(pci_device.pci_address())?; current_parent = pci_device.parent_pci().clone(); } else { @@ -139,7 +139,7 @@ fn chain_unblock_pci( while let Some(parent_pci) = current_parent { if let Some(pci_device) = pci_list.get(&parent_pci) { - info!("chain unblocking pci: {}", gpu.pci.pci_address()); + info!("chain unblocking pci: {}", pci_device.pci_address()); blocker.inner.unblock_pci(pci_device.pci_address())?; current_parent = pci_device.parent_pci().clone(); } else { From abc5d013f135bef533af7cfa7a7070e11b0c8512 Mon Sep 17 00:00:00 2001 From: luytan Date: Mon, 11 May 2026 18:02:05 +0200 Subject: [PATCH 3/4] fix: save mode after applying it --- crates/cardwire-daemon/src/dbus.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/cardwire-daemon/src/dbus.rs b/crates/cardwire-daemon/src/dbus.rs index bf77a4a..bf4a8e5 100644 --- a/crates/cardwire-daemon/src/dbus.rs +++ b/crates/cardwire-daemon/src/dbus.rs @@ -18,9 +18,6 @@ impl Daemon { // Valide inputs and turn into a Modes let mode = Modes::parse(&mode)?; let mut current_mode = self.state.mode_state.write().await; - if let Err(e) = current_mode.save_state(mode).await { - warn!("mode couldn't be saved to config: {e}"); - } let mut blocker = self.state.ebpf_blocker.write().await; let pci_list = &self.state.pci_devices; @@ -74,6 +71,9 @@ impl Daemon { } } } + if let Err(e) = current_mode.save_state(mode).await { + warn!("mode couldn't be saved to config: {e}"); + } info!("Switched to {}", mode); Ok(()) } From cd8678553342bb8b5695553ad72b618fbf08ff76 Mon Sep 17 00:00:00 2001 From: luytan Date: Mon, 11 May 2026 18:04:05 +0200 Subject: [PATCH 4/4] chore: bump version to v0.7.1 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- packages/arch-linux/cardwire-PKGBUILD | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef08a95..64bc431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,7 +304,7 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cardwire-cli" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "clap", @@ -317,7 +317,7 @@ dependencies = [ [[package]] name = "cardwire-core" -version = "0.7.0" +version = "0.7.1" dependencies = [ "cardwire-ebpf", "log", @@ -328,7 +328,7 @@ dependencies = [ [[package]] name = "cardwire-daemon" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "cardwire-core", @@ -346,7 +346,7 @@ dependencies = [ [[package]] name = "cardwire-ebpf" -version = "0.7.0" +version = "0.7.1" dependencies = [ "aya", "thiserror 2.0.18", diff --git a/Cargo.toml b/Cargo.toml index 5823168..2a1b495 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ ] [workspace.package] -version = "0.7.0" +version = "0.7.1" authors = ["luytan "] repository = "https://github.com/OpenGamingCollective/cardwire" edition = "2024" diff --git a/packages/arch-linux/cardwire-PKGBUILD b/packages/arch-linux/cardwire-PKGBUILD index ed03e0f..82e93d1 100644 --- a/packages/arch-linux/cardwire-PKGBUILD +++ b/packages/arch-linux/cardwire-PKGBUILD @@ -3,7 +3,7 @@ pkgbase=cardwire pkgname=cardwire -pkgver=0.7.0 +pkgver=0.7.1 pkgrel=1 pkgdesc='GPU manager for Linux using eBPF LSM hooks' arch=('x86_64')