In part 1 Debian Buster was installed via debootstrap. Part 2 discussed how a suitable kernel can be compiled.
Getting the LED to work
Having looked at the wrong places, I finally got the LED control to work. The DTB configures all internal devices and exposes them at /proc/devices/platform.
Aparrently there ar four PWM devices, of which only #3 is enabled. By adjusting the duty cycle one can actually control the LED:
echo 0 > /sys/devices/platform/980070d0.pwm/dutyRate3 # LED off echo 100 > /sys/devices/platform/980070d0.pwm/dutyRate3 # LED 100% brightness
Digging deeper I found a kernel document describing how to add PWM controlled LEDs to the generic LED interface of the kernel. From there it was straight forward adding the required lines to the DTB (part of my kernel patches).
// linux-kernel/arch/arm64/boot/dts/realtek/wd-monarch-1GB.SATA.dts
pwmleds {
compatible = "pwm-leds";
pwm3{
label = "led";
pwms = <&pwm 3 37878>;
max-brightness = <255>;
};
};
Now the LED can be controlled via
echo 0 > /sys/class/leds/led/brightness # LED off echo 255 > /sys/class/leds/led/brightness # LED 100% brightness
The updated pre-compiled DTB matching my kernel can be found here. Have a look at part 2 on how to apply that in case you are wondering...
Below is a modified version of the monitorio script I use from my old MyBook Live. It's been modified to match the disks of the MCH. Additional required packages are hdparm and smartmontools.
The LED will now be turned off when the disk enters standby, and return to 100% brightness when the disk is active.
#!/bin/bash
#
# (c) 2011 Western Digital Technologies, Inc. All rights reserved.
#
# monitorio - Monitor disk activity, and put system into standby.
##
PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
. /lib/lsb/init-functions
MIN_SINCE_DISK_ACCESS=/tmp/minutes_since_disk_access
dataVolumeDevice=/dev/sataa24
currentRootDevice=/dev/sataa20
declare -i sleepcount
declare -i rootdisk_thresh
declare -i enterStandbyTime=0
rm -f /tmp/standby
source /usr/local/etc/standby.conf
resetSleepCount() {
sleepcount=0
source /usr/local/etc/standby.conf
rootdisk_thresh=$((standby_time-1))
}
rootDisk=`basename ${currentRootDevice}`
dataVolumeDisk=`basename ${dataVolumeDevice}`
drivelist=(${dataVolumeDevice})
echo "0" > ${MIN_SINCE_DISK_ACCESS}
echo 255 > /sys/class/leds/led/brightness
if [ "$1" == "debug" ]; then
echo "1" > /proc/sys/vm/block_dump
dmesg -c > /dev/null
fi
while :; do
for i in ${drivelist[@]}; do
smartctl -i -n standby /dev/sataa | grep -q "STANDBY"
standby_test=$?
[ "$standby_test" -eq "1" ] && break
done
if [ "$standby_test" -eq "0" ]; then
sleep 5
continue
else
if [ -f /tmp/standby ]; then
standby_since=`stat --format %z /tmp/standby`
rm -f /tmp/standby
# Turn on LED
echo 255 > /sys/class/leds/led/brightness
currentTime=`date +%s`
timeInStandby=`expr $currentTime - $enterStandbyTime`
echo "exit standby after $timeInStandby (since $standby_since)"
logger "exit standby after $timeInStandby (since $standby_since)"
if [ "$1" == "debug" ]; then
dmesg -c
fi
fi
resetSleepCount
echo $sleepcount > ${MIN_SINCE_DISK_ACCESS}
ior_root=`awk -v disk="${rootDisk}" '{if ($3==disk) print $6}' /proc/diskstats`
iow_root=`awk -v disk="${rootDisk}" '{if ($3==disk) print $10}' /proc/diskstats`
ior_datavol=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $6}' /proc/diskstats`
iow_datavol=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $10}' /proc/diskstats`
if [ "$1" == "debug" ]; then
echo "Init ior_datavol=$ior_datavol ior_datavol2=$ior_datavol2"
echo " iow_datavol=$iow_datavol iow_datavol2=$iow_datavol2"
echo " ior_root=$ior_root ior_root2=$ior_root2"
echo " iow_root=$iow_root iow_root2=$iow_root2"
dmesg -c
fi
while :; do
# Wait for 60 seconds
sleep 60
ior_root2=`awk -v disk="${rootDisk}" '{if ($3==disk) print $6}' /proc/diskstats`
iow_root2=`awk -v disk="${rootDisk}" '{if ($3==disk) print $10}' /proc/diskstats`
ior_datavol2=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $6}' /proc/diskstats`
iow_datavol2=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $10}' /proc/diskstats`
# use data volume writes until near sleep threshold, then check all disk writes
old_sleepcount=sleepcount
if [ $((sleepcount)) -eq $((rootdisk_thresh)) ] && [ "$ior_root" -eq "$ior_root2" ] && [ "$iow_root" -eq "$iow_root2" ]; then
sleepcount=$((sleepcount+1))
elif [ $((sleepcount)) -lt $((rootdisk_thresh)) ] && [ "$ior_datavol" -eq "$ior_datavol2" ] && [ "$iow_datavol" -eq "$iow_datavol2" ]; then
sleepcount=$((sleepcount+1))
else
resetSleepCount
fi
echo $sleepcount > ${MIN_SINCE_DISK_ACCESS}
if [ "$1" == "debug" ]; then
[ "$sleepcount" != "0" ] && echo "sleepcount: $sleepcount"
[ "$sleepcount" == "0" ] && echo "Disk activity:"
echo "... ior_datavol=$ior_datavol ior_datavol2=$ior_datavol2"
echo "... iow_datavol=$iow_datavol iow_datavol2=$iow_datavol2"
echo "... ior_root=$ior_root ior_root2=$ior_root2"
echo "... iow_root=$iow_root iow_root2=$iow_root2"
# dmesg -c
fi
ior_datavol=$ior_datavol2
iow_datavol=$iow_datavol2
ior_root=$ior_root2
iow_root=$iow_root2
if [ "$standby_enable" == "enabled" ] && [ "$sleepcount" -eq "$standby_time" ] ; then
touch /tmp/standby
enterStandbyTime=`date +%s`
echo "Enter standby"
if [ "$1" == "debug" ]; then
echo "`date`: Enter standby "
dmesg -c > /dev/null
fi
for i in ${drivelist[@]}; do
hdparm -y $i >/dev/null
done
# Turn off LED
echo 0 > /sys/class/leds/led/brightness
sleep 5
break
fi
done
fi
doneThe script requires an additional config file:
# /usr/local/etc/standby.conf standby_enable=enabled standby_time=17
Of course putting the disk to sleep only makes sense if regular write operations don't go to disk but to RAM. After having used a custom RamLog script before, folder2ram is the preferred solution I now use. My folder2ram.conf looks like this:
#<type> <mount point> <options>
tmpfs /var/log
tmpfs /var/tmp
tmpfs /var/spool
tmpfs /var/cache/samba
tmpfs /var/lib/smartmontools
tmpfs /var/lib/systemd
tmpfs /var/lib/samba
tmpfs /var/lib/dhcp
For Debian Bullseye make sure to remove the /var/log/journal folder!
Cool. What do you use it for?
AntwortenLöschenAs I understand, you can set the brightness to XX%
Does that mean it will permanently emit light at XX%?
Or can it be made to show what is going on in the system. Like when the HD is busy? Or flash when errors occur?
Could it be made flashing when someone tries to log in via SSH?
There is some LED trigger drivers:
Löschen* heartbeat
* transient
* oneshot
* timer
Neither the network driver nor the SATA driver support trigger actions. That means you'll have to write your own userspace program to manage the LED.
All I wanted to do is turn it off in order to save some power :D
I updated the post to demonstrate how the LED can be turned on/off by the monitorio script.
LöschenHello :)
AntwortenLöschenIt seems that i dont have the "/sys/class/leds/led/brightness" mine stops at "/sys/class/leds/" where did i go wrong ?
ty in advance
This is actually what the DTB change is supposed to do. Did you install the modified one from above?
LöschenSee "Installing the Kernel" here https://blog.loetzimmer.de/2021/01/debian-on-wd-my-cloud-home-single-bay.html
how to make the script run on boot ?
AntwortenLöschenIf you don't want to create a SystemD unit file for it
Löschen#/etc/systemd/system/monitorio.service
[Unit]
Description=Disk Sleep Daemon
After=local-fs.target
[Service]
ExecStart=/usr/local/sbin/monitorio.sh
ExecStop=/usr/bin/killall monitorio.sh
[Install]
WantedBy=multi-user.target
you could put it in /etc/rc.local