Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

udev: Optimize uevent handling #384

Merged
merged 1 commit into from
Aug 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 37 additions & 44 deletions staslib/udev.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import os
import time
import logging
from functools import partial
import pyudev
from gi.repository import GLib
from staslib import defs, iputil, trid
Expand Down Expand Up @@ -387,55 +388,47 @@ def get_nvme_ioc_tids(self, transports):

def _process_udev_event(self, event_source, condition): # pylint: disable=unused-argument
if condition == GLib.IO_IN:
event_count = 0
while True:
try:
device = self._monitor.poll(timeout=0)
except EnvironmentError as ex:
device = None
# This event seems to happen in bursts. So, let's suppress
# logging for 2 seconds to avoid filling the syslog.
self._log_event_count += 1
now = time.time()
if now > self._log_event_soak_time:
logging.debug('Udev._process_udev_event() - %s [%s]', ex, self._log_event_count)
self._log_event_soak_time = now + 2
self._log_event_count = 0

if device is None:
break

event_count += 1
self._device_event(device, event_count)
try:
self.__handle_events()

except EnvironmentError as ex:
# Exceptions seem to happen in bursts. So, let's suppress
# logging for 2 seconds to avoid filling the syslog.
self._log_event_count += 1
now = time.time()
if now > self._log_event_soak_time:
logging.debug('Udev._process_udev_event() - %s [%s]', ex, self._log_event_count)
self._log_event_soak_time = now + 2
self._log_event_count = 0

return GLib.SOURCE_CONTINUE

@staticmethod
def __cback_names(action_cbacks, device_cback):
names = []
for cback in action_cbacks:
names.append(cback.__name__ + '()')
if device_cback:
names.append(device_cback.__name__ + '()')
return names

def _device_event(self, device, event_count):
action_cbacks = self._action_event_registry.get(device.action, set())
device_cback = self._device_event_registry.get(device.sys_name, None)

logging.debug(
'Udev._device_event() - %-8s %-6s %-8s %s',
f'{device.sys_name}:',
device.action,
f'{event_count:2}:{device.sequence_number}',
self.__cback_names(action_cbacks, device_cback),
)
def __handle_events(self):
event_count = 0
read_device = partial(self._monitor.poll, timeout=0)
for device in iter(read_device, None):
if device is None: # This should never happen,...
break # ...but better safe than sorry.

event_count += 1

action_cbacks = self._action_event_registry.get(device.action, None)
device_cback = self._device_event_registry.get(device.sys_name, None)
if action_cbacks or device_cback:
logging.debug(
'Udev.__handle_events() - %-7s %-6s %2s:%s',
device.sys_name,
device.action,
event_count,
device.sequence_number,
)

for action_cback in action_cbacks:
GLib.idle_add(action_cback, device)
if action_cbacks:
for action_cback in action_cbacks:
GLib.idle_add(action_cback, device)

if device_cback is not None:
GLib.idle_add(device_cback, device)
if device_cback is not None:
GLib.idle_add(device_cback, device)

@staticmethod
def _get_property(device, prop, default=''):
Expand Down
Loading