Linux – How does systemd-tmpfiles work

arch linuxsysfssystemd

I'm trying to change the value of /sys/bus/usb/devices/4-3/power/wakeup at every boot (4-3 according to my lsusb, it's the keyboard ID).

The default value is:

# cat /sys/bus/usb/devices/4-3/power/wakeup
enabled

The classic "online" editing works as expected:

# echo disabled > /sys/bus/usb/devices/4-3/power/wakeup
# cat /sys/bus/usb/devices/4-3/power/wakeup
disabled

I'm using a systemd distro so I'd like to use the systemd-way to edit "temp files"

I have created the following file:

# cat /etc/tmpfiles.d/disable-usb-wakeup.conf 
w /sys/bus/usb/devices/4-3/power/wakeup - - - - disabled

but after every boot I still have the default value in this file (i.e. enabled)

Am I doing something wrong?

EDIT:

Here another test:

# cat /etc/tmpfiles.d/scheduler.conf 
w /sys/block/sda/queue/scheduler - - - - deadline

and this one works fine! After booting I get:

# cat /sys/block/sda/queue/scheduler 
noop [deadline] cfq 

(the default one was the cfq scheduler)

So, why this one works and the other one doesn't?

  • Because /sys/bus/usb/devices/4-3/power/wakeup is a symlink to /sys/devices/pci0000:00/0000:00:12.1/usb4/4-3/ ?
  • Because /sys/bus/usb/devices/4-3/power/wakeup contains only one word? (i.e. no spaces)

Best Answer

I don't believe tmpfiles.d is the proper way to go here. You really should do the udev rules. Look:

udevadm info -a -p /sys/class/scsi_host/host*

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:11.0/ata1/host0/scsi_host/host0':
    KERNEL=="host0"
    SUBSYSTEM=="scsi_host"
    DRIVER==""
    ATTR{unchecked_isa_dma}=="0"
    ATTR{state}=="running"
    ATTR{cmd_per_lun}=="1"
...
    ATTR{ahci_host_version}=="10200"
    ATTR{prot_guard_type}=="0"
    ATTR{eh_deadline}=="off"
    ATTR{link_power_management_policy}=="max_performance"
    ATTR{host_busy}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:11.0/ata1/host0':
    KERNELS=="host0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""
...

And it goes on, walking up the parent device tree. But consider that, using just the information above, you can do:

KERNEL=="host[0-5]", SUBSYSTEM=="scsi_host", ATTR{link_power_management_policy}="min_power"

And I believe that does it for the majority of your script. You'll want to put the above after rule 60, I think. And really, you should do this for the rest - just the sleep bit in your script is reason enough - it implies a race condition. udev is the one adding and setting these parameters - it's the one that populates sysfs. Just ask it to do the work it is already doing.

And for your keyboard you should definitely do the same - and the backlight. Just get the information you need about these devices from udevadm, write some rules and udevadm test them.

Related Question