mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
tty: Re-evaluate ignored nodes on udev add events and session resume (#3651)
* tty: Re-evaluate ignored nodes on udev add events When a DRM device is removed and rescanned (e.g. during a dGPU suspend/resume cycle), the kernel may assign it a new device ID. Re-evaluating the config paths specifically on UdevEvent::Added ensures that symlinks like /dev/dri/by-path/... are resolved to their new underlying IDs, preventing niri from accidentally opening an ignored hotplugged device. This check is restricted to device additions to avoid unnecessary filesystem I/O on the hot path during bursts of other udev events. * fixes --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
This commit is contained in:
+23
-29
@@ -97,9 +97,6 @@ pub struct Tty {
|
|||||||
dmabuf_global: Option<DmabufGlobal>,
|
dmabuf_global: Option<DmabufGlobal>,
|
||||||
// The output config had changed, but the session is paused, so we need to update it on resume.
|
// The output config had changed, but the session is paused, so we need to update it on resume.
|
||||||
update_output_config_on_resume: bool,
|
update_output_config_on_resume: bool,
|
||||||
// The ignored nodes have changed, but the session is paused, so we need to update it on
|
|
||||||
// resume.
|
|
||||||
update_ignored_nodes_on_resume: bool,
|
|
||||||
// Whether the debug tinting is enabled.
|
// Whether the debug tinting is enabled.
|
||||||
debug_tint: bool,
|
debug_tint: bool,
|
||||||
ipc_outputs: Arc<Mutex<IpcOutputMap>>,
|
ipc_outputs: Arc<Mutex<IpcOutputMap>>,
|
||||||
@@ -495,11 +492,6 @@ impl Tty {
|
|||||||
}
|
}
|
||||||
info!("using as the render node: {node_path}");
|
info!("using as the render node: {node_path}");
|
||||||
|
|
||||||
let mut ignored_nodes = ignored_nodes_from_config(&config.borrow());
|
|
||||||
if ignored_nodes.remove(&primary_node) || ignored_nodes.remove(&primary_render_node) {
|
|
||||||
warn!("ignoring the primary node or render node is not allowed");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
config,
|
config,
|
||||||
session,
|
session,
|
||||||
@@ -508,11 +500,10 @@ impl Tty {
|
|||||||
gpu_manager,
|
gpu_manager,
|
||||||
primary_node,
|
primary_node,
|
||||||
primary_render_node,
|
primary_render_node,
|
||||||
ignored_nodes,
|
ignored_nodes: HashSet::new(),
|
||||||
devices: HashMap::new(),
|
devices: HashMap::new(),
|
||||||
dmabuf_global: None,
|
dmabuf_global: None,
|
||||||
update_output_config_on_resume: false,
|
update_output_config_on_resume: false,
|
||||||
update_ignored_nodes_on_resume: false,
|
|
||||||
debug_tint: false,
|
debug_tint: false,
|
||||||
ipc_outputs: Arc::new(Mutex::new(HashMap::new())),
|
ipc_outputs: Arc::new(Mutex::new(HashMap::new())),
|
||||||
})
|
})
|
||||||
@@ -527,6 +518,9 @@ impl Tty {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the ignored nodes.
|
||||||
|
self.ignored_nodes = self.compute_ignored_nodes();
|
||||||
|
|
||||||
let udev = self.udev_dispatcher.clone();
|
let udev = self.udev_dispatcher.clone();
|
||||||
let udev = udev.as_source_ref();
|
let udev = udev.as_source_ref();
|
||||||
|
|
||||||
@@ -566,6 +560,10 @@ impl Tty {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recompute ignored nodes to resolve symlinks (like /dev/dri/by-path/...) to their
|
||||||
|
// new underlying device IDs.
|
||||||
|
self.ignored_nodes = self.compute_ignored_nodes();
|
||||||
|
|
||||||
if let Err(err) = self.device_added(device_id, &path, niri) {
|
if let Err(err) = self.device_added(device_id, &path, niri) {
|
||||||
warn!("error adding device: {err:?}");
|
warn!("error adding device: {err:?}");
|
||||||
}
|
}
|
||||||
@@ -613,16 +611,9 @@ impl Tty {
|
|||||||
warn!("error resuming libinput");
|
warn!("error resuming libinput");
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.update_ignored_nodes_on_resume {
|
// While the session was suspended, GPUs could have been added, so
|
||||||
self.update_ignored_nodes_on_resume = false;
|
// /dev/dri/by-path/... symlinks need to be re-resolved.
|
||||||
let mut ignored_nodes = ignored_nodes_from_config(&self.config.borrow());
|
self.ignored_nodes = self.compute_ignored_nodes();
|
||||||
if ignored_nodes.remove(&self.primary_node)
|
|
||||||
|| ignored_nodes.remove(&self.primary_render_node)
|
|
||||||
{
|
|
||||||
warn!("ignoring the primary node or render node is not allowed");
|
|
||||||
}
|
|
||||||
self.ignored_nodes = ignored_nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut device_list = self
|
let mut device_list = self
|
||||||
.udev_dispatcher
|
.udev_dispatcher
|
||||||
@@ -2292,22 +2283,25 @@ impl Tty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_ignored_nodes_config(&mut self, niri: &mut Niri) {
|
fn compute_ignored_nodes(&self) -> HashSet<DrmNode> {
|
||||||
let _span = tracy_client::span!("Tty::update_ignored_nodes_config");
|
|
||||||
|
|
||||||
// If we're inactive, we can't do anything, so just set a flag for later.
|
|
||||||
if !self.session.is_active() {
|
|
||||||
self.update_ignored_nodes_on_resume = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ignored_nodes = ignored_nodes_from_config(&self.config.borrow());
|
let mut ignored_nodes = ignored_nodes_from_config(&self.config.borrow());
|
||||||
if ignored_nodes.remove(&self.primary_node)
|
if ignored_nodes.remove(&self.primary_node)
|
||||||
|| ignored_nodes.remove(&self.primary_render_node)
|
|| ignored_nodes.remove(&self.primary_render_node)
|
||||||
{
|
{
|
||||||
warn!("ignoring the primary node or render node is not allowed");
|
warn!("ignoring the primary node or render node is not allowed");
|
||||||
}
|
}
|
||||||
|
ignored_nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_ignored_nodes_config(&mut self, niri: &mut Niri) {
|
||||||
|
let _span = tracy_client::span!("Tty::update_ignored_nodes_config");
|
||||||
|
|
||||||
|
// If we're inactive, we can't do anything, but we'll recompute in ActivateSession.
|
||||||
|
if !self.session.is_active() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ignored_nodes = self.compute_ignored_nodes();
|
||||||
if ignored_nodes == self.ignored_nodes {
|
if ignored_nodes == self.ignored_nodes {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user