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

Improve UDEV rule performance #618

Open
benzea opened this issue Feb 16, 2022 · 3 comments
Open

Improve UDEV rule performance #618

benzea opened this issue Feb 16, 2022 · 3 comments
Assignees

Comments

@benzea
Copy link

benzea commented Feb 16, 2022

Hi, I was looking at libusb/libusb#237 and noticed that TLP is a huge offender with regard to USB device processing in udev.

The TLP udev rules need an extremely long time to process events. This is not really necessary, as there is no reason to block the rest of udev (and userspace!) in order to possibly enable USB autosuspend.

The obvious reason for it to go really horribly wrong is the sleep of 500ms in the codebase, see https://github.com/linrunner/TLP/blob/main/func.d/20-tlp-func-usb#L64. This sleep is probably just plain wrong, if subdevices are of such importance, you can also modify the parent device from a DEVTYPE=usb_interface rule.

But, equally bad is the fact that we even wait for this operation to complete. I am thinking the following solutions are possible (roughly in preferred order in my view):

  1. Have udev rules that do not require executing a long script. You can test for file existence in udev, so writing out a file to e.g. /run/tlp and testing for that you can enable/disable rules. Not sure if a RUN rule though, as autosuspend needs to be set on the parent device.
  2. Have a tiny daemon that monitors udev and reacts to the events.
  3. Push the script into a systemd (template) unit. i.e. add TAG+="systemd" and set ENV{SYSTEMD_WANTS}+="[email protected]". The service should be Type=oneshot with ExecStart=/lib/udev/tlp-usb-udev usb %I or something similar (did not test it).
    • To avoid the sleep, one could trigger it for each interface update. But, that is kind of ugly as it would create a lot of .device units.
    • I expect udevadm settle is enough though, so possibly just an ExecStartPre-=/usr/sbin/udevadm settle.
  4. Remove the sleep and run for usb_interface and update the parent; but that still means loading all the shell scripting.

So, 1. not sure, might be complicated. As for 2. (daemon), that seems kinda neat in a way. 3. may be a bit verbose in systemctl status, I imagine. And, 4. is simple, but I am not sure I like it that much :-)

@linrunner
Copy link
Owner

linrunner commented Nov 28, 2022

Hi,

thanks for your insights. I have (obviously) thought about your comments for a quite a time.

  1. Sounds very complicated and I don't have the same control over what happens as in a script. Logging is even more difficult.
  2. I would like to avoid implementing a daemon in general and in particular as a shell script
  3. This would allow TLP to be used only with systemd.
  4. Would mean backtracking down the whole tree searching for the parent multiple times, this also takes time.

I openly confess that my knowledge of the subject leaves a lot to be desired.

@benzea
Copy link
Author

benzea commented Oct 20, 2023

Or maybe it would be enough to fork into the background so that udev can continue to process rules?

@linrunner
Copy link
Owner

The udev manpage says:

Starting daemons or other long-running processes is not allowed; the forked processes, detached or not, will be unconditionally > killed after the event handling has finished.

I think I'll just give 4. a try as soon as I have time. The "backtracking" includes only one step to the direct parent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants