From 8ddd1d2984a5d61fd592bb510fbe3a6ffe44de9e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 16 Sep 2009 15:57:53 +0000 Subject: [PATCH] Save hwmon device paths and names in configuration file, and check them before starting any fan control operation. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@5770 7894878c-1315-0410-8ee3-d5d059ff63e0 --- CHANGES | 2 + prog/pwm/fancontrol | 68 ++++++++++++++++++++++- prog/pwm/fancontrol.8 | 18 ++++-- prog/pwm/pwmconfig | 125 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 197 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index 3d6f7842..afda7fbd 100644 --- a/CHANGES +++ b/CHANGES @@ -4,7 +4,9 @@ lm-sensors CHANGES file SVN-HEAD libsensors: Support upcoming sysfs path to i2c adapters fancontrol: Check that all referenced sysfs files exist + Check that all devices match the configuration file pwmconfig: Exit immediately if not root + Save device paths and names in configuration file sensors.conf.default: Encourage user to not modify this file sensors-detect: Refer to tmp401 driver if TMP411 is detected Clean up the discovery of i2c adapters diff --git a/prog/pwm/fancontrol b/prog/pwm/fancontrol index 88de1810..a15346b6 100755 --- a/prog/pwm/fancontrol +++ b/prog/pwm/fancontrol @@ -3,12 +3,12 @@ # Simple script implementing a temperature dependent fan speed control # Supported Linux kernel versions: 2.6.5 and later # -# Version 0.69 +# Version 0.70 # # Usage: fancontrol [CONFIGFILE] # # Dependencies: -# bash, egrep, sed, cut, sleep, lm_sensors :) +# bash, egrep, sed, cut, sleep, readlink, lm_sensors :) # # Please send any questions, comments or success stories to # marius.reiner@hdev.de @@ -55,6 +55,8 @@ function LoadConfig { # grep configuration from file INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'` + DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'` MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'` MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'` @@ -152,6 +154,57 @@ function LoadConfig { echo } +function DevicePath() +{ + if [ -h "$1/device" ] + then + readlink -f "$1/device" | sed -e 's/^\/sys\///' + fi +} + +function DeviceName() +{ + if [ -r "$1/name" ] + then + cat "$1/name" | sed -e 's/[[:space:]=]/_/g' + elif [ -r "$1/device/name" ] + then + cat "$1/device/name" | sed -e 's/[[:space:]=]/_/g' + fi +} + +function ValidateDevices() +{ + local OLD_DEVPATH="$1" OLD_DEVNAME="$2" outdated=0 + local entry device name path + + for entry in $OLD_DEVPATH + do + device=`echo "$entry" | sed -e 's/=[^=]*$//'` + path=`echo "$entry" | sed -e 's/^[^=]*=//'` + + if [ "`DevicePath "$device"`" != "$path" ] + then + echo "Device path of $device has changed" + outdated=1 + fi + done + + for entry in $OLD_DEVNAME + do + device=`echo "$entry" | sed -e 's/=[^=]*$//'` + name=`echo "$entry" | sed -e 's/^[^=]*=//'` + + if [ "`DeviceName "$device"`" != "$name" ] + then + echo "Device name of $device has changed" + outdated=1 + fi + done + + return $outdated +} + # Check that all referenced sysfs files exist function CheckFiles { local outdated=0 @@ -232,6 +285,17 @@ then fi cd $DIR +# Check for configuration change +if [ -z "$DEVPATH" -o -z "$DEVNAME" ] +then + echo "Configuration is too old, please run pwmconfig again" + exit 1 +fi +if ! ValidateDevices "$DEVPATH" "$DEVNAME" +then + echo "Configuration appears to be outdated, please run pwmconfig again" + exit 1 +fi CheckFiles || exit 1 if [ -f "$PIDFILE" ] diff --git a/prog/pwm/fancontrol.8 b/prog/pwm/fancontrol.8 index 106b44a4..8ccd5d3c 100644 --- a/prog/pwm/fancontrol.8 +++ b/prog/pwm/fancontrol.8 @@ -38,13 +38,21 @@ variables available for changing \fBfancontrol\fP's behaviour: This variable defines at which interval in seconds the main loop of \fBfancontrol\fP will be executed .TP +.B DEVPATH +Maps hwmon class devices to physical devices. This lets \fBfancontrol\fP +check that the configuration file is still up-to-date. +.TP +.B DEVNAME +Records hwmon class device names. This lets \fBfancontrol\fP check that +the configuration file is still up-to-date. +.TP .B FCTEMPS Maps PWM outputs to temperature sensors so \fBfancontrol\fP knows which temperature sensors should be used for calculation of new values for the corresponding PWM outputs. .TP .B FCFANS -FCFANS records the association between a PWM and a fan. +Records the association between a PWM output and a fan input. Then \fBfancontrol\fP can check the fan speed and restart it if it stops unexpectedly. .TP @@ -92,9 +100,11 @@ You have to play with the temperature values a bit to get happy. For initial setup I recommend using the \fBpwmconfig\fP script. Small changes can be made by editing the config file directly following the rules above. -Upon starting, fancontrol will make sure that all referenced sysfs files -do exist. If not, it will quit immediately, upon the assumption that the -configuration file may be out-of-sync with the loaded kernel drivers. +Upon starting, fancontrol will make sure that all referenced devices +do exist and match what they were at configuration time, and that all +referenced sysfs files do exist. If not, it will quit immediately, upon +the assumption that the configuration file may be out-of-sync with the +loaded kernel drivers. .SH THE ALGORITHM diff --git a/prog/pwm/pwmconfig b/prog/pwm/pwmconfig index ebbefe2b..2754bb53 100755 --- a/prog/pwm/pwmconfig +++ b/prog/pwm/pwmconfig @@ -539,6 +539,57 @@ then exit 1 fi +function DevicePath() +{ + if [ -h "$1/device" ] + then + readlink -f "$1/device" | sed -e 's/^\/sys\///' + fi +} + +function DeviceName() +{ + if [ -r "$1/name" ] + then + cat "$1/name" | sed -e 's/[[:space:]=]/_/g' + elif [ -r "$1/device/name" ] + then + cat "$1/device/name" | sed -e 's/[[:space:]=]/_/g' + fi +} + +function ValidateDevices() +{ + local OLD_DEVPATH="$1" OLD_DEVNAME="$2" outdated=0 + local entry device name path + + for entry in $OLD_DEVPATH + do + device=`echo "$entry" | sed -e 's/=[^=]*$//'` + path=`echo "$entry" | sed -e 's/^[^=]*=//'` + + if [ "`DevicePath "$device"`" != "$path" ] + then + echo "Device path of $device has changed" + outdated=1 + fi + done + + for entry in $OLD_DEVNAME + do + device=`echo "$entry" | sed -e 's/=[^=]*$//'` + name=`echo "$entry" | sed -e 's/^[^=]*=//'` + + if [ "`DeviceName "$device"`" != "$name" ] + then + echo "Device name of $device has changed" + outdated=1 + fi + done + + return $outdated +} + function AskPath() { echo -n 'What should be the path to your fancontrol config file (/etc/fancontrol)? ' @@ -566,6 +617,8 @@ function ClearConfig() function LoadConfig() { + local OLD_DEVPATH OLD_DEVNAME + # Nothing to do if [ ! -f "$1" ] then @@ -575,6 +628,8 @@ function LoadConfig() echo "Loading configuration from $1 ..." INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL= *//g'` + OLD_DEVPATH=`egrep '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g'` + OLD_DEVNAME=`egrep '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g'` FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS= *//g'` FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS= *//g'` MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP= *//g'` @@ -585,16 +640,12 @@ function LoadConfig() MAXPWM=`egrep '^MAXPWM=.*$' $1 | sed -e 's/MAXPWM= *//g'` # Check for configuration change - local item - for item in $FCFANS - do - if [ ! -f "`echo $item | sed -e 's/=.*$//'`" ] - then - echo "Configuration appears to be outdated, discarded" - ClearConfig - return 0 - fi - done + if ! ValidateDevices "$OLD_DEVPATH" "$OLD_DEVNAME" + then + echo "Configuration appears to be outdated, discarded" + ClearConfig + return 0 + fi } LoadConfig $FCCONFIG @@ -675,14 +726,68 @@ function TestMinStop() echo "OK, using $fanval" } +# Remember the path and name of each device with at least one +# reference (pwm, temp or fan) in the configuration file. +# This function sets globals DEVPATH and DEVNAME as a side effect. +function RememberDevices() +{ + local used entry device name path tempfandev pwmdev + DEVPATH="" + DEVNAME="" + + for device in $DEVICES + do + device=`echo "$device" | sed -e 's/\/.*$//'` + + used=0 + for entry in $1 $2 + do + pwmdev=`echo "$entry" | sed -e 's/\/.*$//'` + tempfandev=`echo "$entry" | sed -e 's/^[^=]*=//' -e 's/\/.*$//'` + + if [ "$device" = "$pwmdev" -o "$device" = "$tempfandev" ] + then + used=1 + fi + done + if [ "$used" -eq 0 ] + then + continue + fi + + # Record the device path and name. This lets the fancontrol + # script check that they didn't change. If they did, then the + # configuration file can no longer be trusted. + path=`DevicePath "$device"` + if [ -z "$DEVPATH" ] + then + DEVPATH="$device=$path" + else + DEVPATH="$DEVPATH $device=$path" + fi + + name=`DeviceName "$device"` + if [ -z "$DEVNAME" ] + then + DEVNAME="$device=$name" + else + DEVNAME="$DEVNAME $device=$name" + fi + done +} + function SaveConfig() { + RememberDevices "$FCTEMPS" "$FCFANS" + echo echo "Saving configuration to $FCCONFIG..." tmpfile=`mktemp -t pwmcfg.XXXXXXXXXX` || { echo "$0: Cannot create temporary file" >&2; exit 1; } trap " [ -f \"$tmpfile\" ] && /bin/rm -f -- \"$tmpfile\"" 0 1 2 3 13 15 echo "# Configuration file generated by pwmconfig, changes will be lost" >$tmpfile echo "INTERVAL=$INTERVAL" >>$tmpfile + echo "DEVPATH=$DEVPATH" >>$tmpfile + echo "DEVNAME=$DEVNAME" >>$tmpfile echo "FCTEMPS=$FCTEMPS" >>$tmpfile echo "FCFANS=$FCFANS" >>$tmpfile echo "MINTEMP=$MINTEMP" >>$tmpfile