2

On Fedora 25, my laptop's hard drive has a very low APM level (power management), so I use the udev rules from this answer to adjust it with hdparm. However, after resuming from suspend, the APM level gets reset. Manually triggering the udev rules from the terminal works, so to automate it I tried using the following systemd service adapted from here and here:-

[Unit]
Description=Re-run udev power_supply rules after resuming from suspend
After=supend.target

[Service]
Type=oneshot
User=root
Group=root
ExecStart=+/bin/sh -c '/usr/sbin/udevadm trigger --subsystem-match="power_supply"'

[Install]
WantedBy=suspend.target

I also tried combinations of multi-user.target, default.target and sleep.target in the WantedBy= line, as well as Type=simple. None of this worked, so I tried placing a script in /etc/pm/sleep.d/, adapted from this. But this did not work either (nor did putting it in /usr/lib64/pm-utils/sleep.d/).

Finally, the man page for systemd-suspend.service says,

... scripts or binaries dropped in /usr/lib/systemd/system-sleep/ are intended for local use ... and should be considered hacks. If applications want to be notified of system suspend/hibernation and resume, there are much nicer interfaces available.

However, placing a script in /usr/lib/systemd/system-sleep/ actually works; but in any case, what are these "much nicer interfaces" and how do I use them to either run the udev trigger (preferable) or hdparm after resuming from suspend? Better still, is there a way to set the hard drive APM levels for on-battery and plugged-in states by means of some static configuration instead of udev rules?

Update - Fixed The systemd service is working now. I think I mistakenly used udevadm from the wrong directory while trying various combinations. I have posted an answer clarifying this. I apologise for any confusion caused. However, there is still the question of whether there is a way to do this statically (without udev rules).

  • 1
    User=root Group=root should not be required. Note that you are not an application. IMO the scripts are a nice method for local use, except that being in /usr confuses me. Also there's an "application" that will handle this, although the version in F25 doesn't. Ticket: github.com/storaged-project/udisks/issues/72 Code: github.com/storaged-project/udisks/pull/73 It listens for suspend events using a D-Bus interface that "logind" provides... don't ask me to justify that :). – sourcejedi Feb 26 '17 at 16:29
  • I had put in the root parts after I found that it didn't work; I think they do no harm anyway. Also, I had already gone through that storaged thread. It still seems to be a problem, and the problem seems to be more or less the same - APM level reset after resuming from suspend. Lastly, on Fedora (25) /lib is a link to /usr/lib, which is why the scripts are there; don't know if you meant something else. – Saurav Sengupta Feb 26 '17 at 17:25
  • If the storaged commit doesn't work, please file a bug - but the commit is dated 21st July, and storaged 2.6.2 is dated 16th June, so I don't believe the commit is in F25. – sourcejedi Feb 26 '17 at 17:33
  • The issue was reopened on 21st July, and the copr seems to be for F26. Still, I'll see if it works and follow your advice. Thanks. – Saurav Sengupta Feb 26 '17 at 17:38
2

It seems that I had initially used udevadm from the wrong directory (/bin/udevadm), and then got one or other combination wrong while trying things out. The udevadm program must be run from /sbin (or /usr/sbin). The following systemd service now suffices:-

[Unit]
Description=Re-run udev power_supply rules after resuming from suspend
After=supend.target

[Service]
Type=oneshot
ExecStart=/sbin/udevadm trigger --subsystem-match=power_supply

[Install]
WantedBy=suspend.target

I apologise for any confusion caused.

1

Writing a systemd service to be executed at resume

Works with After=suspend.target in Unit and WantedBy=multi-user.target sleep.target in Install.

In your case the second part would be WantedBy=sleep.target.

Apparently After=sleep.target worked for one person, but another had to use After=suspend.target. I have no idea why. The interface for using this to run units on resume does not seem to be documented, so I wouldn't really claim that it is nicer.

  • I had seen that line and tried it, to no avail. The sleep.target doesn't work either in After= or in WantedBy=. – Saurav Sengupta Feb 26 '17 at 17:30
  • I think we're being a bit unclear - just to be sure: for the unit to work properly it would need to include some line for both WantedBy= and After=. Anyway, are you seeing your unit being started if you look in sudo journalctl -b, is it that it starts at the wrong time, or is it that it doesn't start? You can press End, then search backwards in the pager by typing ?, and entering a search string, such as Re-run udev power_supply, Start, or systemd. – sourcejedi Feb 26 '17 at 17:43
  • Sorry for the confusion. I did set both After= and WantedBy= but no matter which combination of suspend.target and sleep.target I used for them, it didn't work. However, my original service (with just suspend.target in both After= and WantedBy=) is working now. I think it was my own mistake; I've put the reason in an answer. The service unit status shows up correctly in both systemctl status and journalctl. – Saurav Sengupta Feb 26 '17 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.