Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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)

I'm doing something wrong?

EDIT:

I have done another test:

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

and this one works fine! After boot I have:

# 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 not?

  • 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)
share|improve this question

3 Answers 3

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.

share|improve this answer

I learned recently the hard way that /etc/tmpfiles.d is processed before /sys is populated so you have to create the proper udev rules so they are enable whenever the devices shows up or... go the dirty way (but if you ask me, a more flexible one) and create a service that runs an script with the commands to write into /sys. Take a look here for an example on how to create such script, https://bbs.archlinux.org/viewtopic.php?id=148170 which you can fill with something like:

#!/bin/sh

sleep 2

# Enforce energy tweaks provided by PowerTop

echo min_power > /sys/class/scsi_host/host0/link_power_management_policy; echo min_power > /sys/class/scsi_host/host1/link_power_management_policy; echo min_power > /sys/class/scsi_host/host2/link_power_management_policy; echo min_power > /sys/class/scsi_host/host3/link_power_management_policy; echo min_power > /sys/class/scsi_host/host4/link_power_management_policy; echo min_power > /sys/class/scsi_host/host5/link_power_management_policy; echo 1 > /sys/module/snd_hda_intel/parameters/power_save; echo auto > /sys/bus/pci/devices/0000:7f:00.1/power/control; echo auto > /sys/bus/pci/devices/0000:01:00.1/power/control;

...

echo 4880 > /sys/class/backlight/intel_backlight/brightness

...

share|improve this answer

[ My original idea that this could be because systemd-tmpfiles uses stream I/O and was not intended to be used with proc or sys is wrong. My 2nd hypothesis, about the significance of a newline, was also wrong... ]

I just looked at /usr/lib/systemd/system/systemd-tmpfiles-setup.service and there's a couple of bits in there that may be of interest:

[Unit]
Description=Recreate Volatile Files and Directories
Documentation=man:tmpfiles.d(5)
DefaultDependencies=no
Wants=local-fs.target
After=systemd-readahead-collect.service systemd-readahead-replay.service local-fs.target
Before=sysinit.target shutdown.target

[...]

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-tmpfiles --create --remove

The 'Wants', 'After', and 'Before' give some information about when this happens; I would think your device is registered by this point, but there could be something subsequent that resets the sysfs value.

The most helpful bit is the ExecStart line, because that's the actual command that accounts for this service. This is actually mentioned in man systemd-tmpfiles:

For example, during boot the following command line is executed to ensure that all temporary and volatile directories are removed and created according to the configuration file:

systemd-tmpfiles --remove --create

So, to test this, set the sysfs value to "enabled" and then try running systemd-tmpfiles --create which will process your 'w' directive in /etc/tmpfiles.d. If that works (it should!), then you know that the systemd-tmpfile method is fine, just you have to do it later in the boot process, perhaps with:

Requires=multi-user.target
After=multi-user.target

Which means writing your own service file; if for some reason it doesn't work, you can always write a service file for a script to do it with echo.

share|improve this answer
    
I don't think that systemd can't write on virtual file systems. Using tmpfiles on /proc/acpi/wakeup works fine, for example (wiki.archlinux.org/index.php/Systemd#Temporary_files) –  ital Jan 14 '13 at 8:49
    
@ital : I was probably wrong about that, but if you are still frustrated try my second hypothesis above. –  goldilocks Jan 14 '13 at 12:46
    
Using echo -n disabled > /sys/... works, so probably the newline presence doesn't care in this case. But tmpfiles is still not working, I've tried both disabled\n and "disabled\n" –  ital Jan 14 '13 at 16:50
    
I have edited the first post with another test and some hypothesis. –  ital Jan 14 '13 at 17:58
    
@ital Sheesh. Okay, pretty sure my 3rd guess is the lucky one, so I edited that in above again, lol. If after that you need the basics for writing and registering a systemd service, ask a new question and maybe reference this one; I can explain it without all this clutter, we will get some input from others, and the question can stand for posterity (I don't see any here yet that address this very well). –  goldilocks Jan 14 '13 at 19:07

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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