fix(backlight): stop per-tick filesystem re-enumeration / I/O flooding
The backlight udev worker thread called enumerate_devices() on every epoll_wait timeout, i.e. once per polling interval. enumerate_devices() runs udev_enumerate_scan_devices(), which walks the entire /sys/class/backlight and /sys/class/leds trees and opens/closes the sysfs root and every device path. With no `interval` configured the module polls on its default cadence, so this full re-scan ran continuously even when brightness never changed, flooding the filesystem (observed via fatrace as constant open/close of `/`). Raising `interval` only lowered the cadence, which is why the reporter's `interval: 10` workaround reduced the flood. The full re-enumeration is redundant: the udev monitor already delivers change/add/remove events for the backlight and leds subsystems. On the timeout path, re-read only the sysfs attributes of the devices already tracked (via udev_device_new_from_subsystem_sysname) instead of re-scanning the whole tree. This keeps periodic refresh working for firmware backlights such as acpi_video that may not emit udev change events, while eliminating the tree-wide scan. Device discovery of new/removed devices continues through the udev monitor. Fixes #5020.
This commit is contained in:
@@ -230,9 +230,21 @@ BacklightBackend::BacklightBackend(std::chrono::milliseconds interval,
|
||||
upsert_device(devices, dev.get());
|
||||
}
|
||||
|
||||
// Refresh state if timed out
|
||||
// Refresh state if timed out. Only re-read the sysfs attributes of the
|
||||
// devices we already track instead of re-enumerating the whole udev tree
|
||||
// (udev_enumerate_scan_devices), which walks all of /sys/class/backlight
|
||||
// and /sys/class/leds and floods the filesystem with open/close syscalls
|
||||
// on every polling tick (#5020). Device add/remove is already delivered
|
||||
// by the udev monitor above, so a periodic full re-scan is redundant.
|
||||
if (event_count == 0) {
|
||||
enumerate_devices(devices, udev.get());
|
||||
for (const auto& device : devices) {
|
||||
std::unique_ptr<udev_device, UdevDeviceDeleter> dev{
|
||||
udev_device_new_from_subsystem_sysname(udev.get(), device.subsystem().c_str(),
|
||||
device.name().c_str())};
|
||||
if (dev) {
|
||||
upsert_device(devices, dev.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(udev_thread_mutex_);
|
||||
|
||||
Reference in New Issue
Block a user