#!/bin/bash
#
#######################################################################
## This script is probably broken and obsoleted by set_disk_settings ##
#######################################################################
# Author Thomas Renninger (powersave@renninger.de)
#
# This script is thought to be invoked by the powersave daemon
# It adjusts the machine to the settings of a specfic scheme

# At the moment only hard disk issues are managed by this script
# (e.g. setting standby/suspend timouts and acoustic settings),
# but there maybe added more in future.
# 

# The script might take following parameters:
# 
# 1) The powersave daemon event that caused the script to be invoked 
# 2) The scheme which settings should be executed
#    Be careful. It is not the scheme name as specified in SCHEME_NAME
#    inside the scheme configuration file.
#    It is the name of the scheme configuration file, without leading path.
#    E.g. scheme_powersave should refer (by default) to the scheme configurations 
#    that are stored in /etc/sysconfig/powersave/scheme_powersave


# shameless rip from the laptop_mode script
laptop_mode_func() {

    DEBUG "do remounts?: $HD_DO_REMOUNTS   set no atime: $HD_NOATIME" INFO 
    if [ ! -w /proc/sys/vm/laptop_mode ]; then
	DEBUG "Kernel is not patched with laptop_mode patch or not enough privileges." WARN
        return 1
    fi
    local AGE DEV MP FST OPTS DUMP PASS ACTIVE
    local DEF_AGE DEF_UPDATE DEF_DIRTY_BACKGROUND_RATIO DEF_DIRTY_RATIO

    # kernel default dirty buffer age; no need to alter.
    DEF_AGE=30; DEF_UPDATE=5; DEF_DIRTY_BACKGROUND_RATIO=10; DEF_DIRTY_RATIO=40

    read ACTIVE < /proc/sys/vm/laptop_mode
    case "$1" in
	start)
	    if [ "$ACTIVE" -eq 0 ]; then
		AGE=$((100*$HD_MAX_AGE))
		DEBUG "Starting laptop_mode" DIAG
		case "$K_RELEASE" in
		    "2.4")
			echo "1"				> /proc/sys/vm/laptop_mode
			echo "30 500 0 0 $AGE $AGE 60 20 0"	> /proc/sys/vm/bdflush
			;;
		    "2.6")
			echo "1"				> /proc/sys/vm/laptop_mode
			echo "$AGE"				> /proc/sys/vm/dirty_writeback_centisecs
			echo "$AGE"				> /proc/sys/vm/dirty_expire_centisecs
			echo "$HD_DIRTY_RATIO"			> /proc/sys/vm/dirty_ratio
			echo "$HD_DIRTY_RATIO"			> /proc/sys/vm/dirty_background_ratio
			;;
		    *)  DEBUG "unhandled kernel release: '$K_RELEASE' in function laptop_mode_func" ERROR
			;;
		esac
		if [ "$HD_DO_REMOUNTS" = "yes" ]; then
		    while read DEV MP FST OPTS DUMP PASS ; do
			OPTS="${OPTS//commit=[0-9]*/}"
			OPTS=${OPTS//,,/,}
			case "$FST" in
			    "ext3")	mount $DEV -t $FST $MP -o remount,$OPTS,commit=$HD_MAX_AGE ;;
			    "reiserfs")	[ "$HD_NOATIME" = "yes" ] && OPTS="$OPTS,noatime"
					mount $DEV -t $FST $MP -o remount,$OPTS,commit=$HD_MAX_AGE ;;
			    "xfs")	mount $DEV -t $FST $MP -o remount,$OPTS,commit=$HD_MAX_AGE ;;
			esac
		    done < /etc/mtab
		fi
	    else
		DEBUG "laptop_mode already active, ignoring" DIAG
	    fi
	    ;;
        stop)
	    if [ "$ACTIVE" -eq 1 ]; then
		U_AGE=$((100*$DEF_UPDATE))
		B_AGE=$((100*$DEF_AGE))
		DEBUG "Stopping laptop_mode" DIAG
		case "$K_RELEASE" in
		    "2.4")
			echo "0"				> /proc/sys/vm/laptop_mode
			echo "30 500 0 0 $U_AGE $B_AGE 60 20 0"	> /proc/sys/vm/bdflush
			;;
		    "2.6")
			echo "0"				> /proc/sys/vm/laptop_mode
			echo "$U_AGE"				> /proc/sys/vm/dirty_writeback_centisecs
			echo "$B_AGE"				> /proc/sys/vm/dirty_expire_centisecs
			echo "$DEF_DIRTY_RATIO"			> /proc/sys/vm/dirty_ratio
			echo "$DEF_DIRTY_BACKGROUND_RATIO"	> /proc/sys/vm/dirty_background_ratio
			;;
		    *)  DEBUG "unhandled kernel release: '$K_RELEASE' in function laptop_mode_func" ERROR
			;;
	        esac
		if [ "$HD_DO_REMOUNTS" = "yes" ]; then
		    while read DEV MP FST OPTS DUMP PASS ; do
			OPTS="${OPTS//commit=[0-9]*/}"
			OPTS=${OPTS//,,/,}
			case "$FST" in
			    "ext3")	mount $DEV -t $FST $MP -o remount,$OPTS ;;
			    "reiserfs")	[ "$HD_NOATIME" = "yes" ] && OPTS="${OPTS//noatime/}"
					mount $DEV -t $FST $MP -o remount,$OPTS ;;
			    "xfs")	mount $DEV -t $FST $MP -o remount,$OPTS ;;
			esac
		    done < /etc/mtab
		fi
	    else
		DEBUG "laptop_mode already inactive, ignoring" DIAG
	    fi
	    ;;
	*)  DEBUG "wrong call of function laptop_mode_func with argument '$1'" ERROR 
	    return 1
	    ;;
    esac
    return 0
}

# first parameter which setting is affected:
# calls hdparm for all disks with the parameter given.
exec_hdparm() {
    # Is this setting save on all disks ?
    # get all ide disks, is this also working for 2.4.x?

    local ARGS TYPE ide
    ARGS="$*"
    # Is this setting safe on all disks ?
    # get all ide disks, is this also working for 2.4.x?
    for ide in /proc/ide/ide?/hd?; do
	TYPE=""
	read TYPE < $ide/media
	case "$TYPE" in
	    disk)
	        DEBUG "We have a disk: /dev/${ide##*/}" INFO
		DEBUG "running /sbin/hdparm $ARGS /dev/${ide##*/}" DIAG
		/sbin/hdparm $ARGS /dev/${ide##*/} &>/dev/null || \
			DEBUG "hdparm returned error $?" WARN
		;;
	    *) 
		DEBUG "This is not a disk: /dev/${ide##*/}" DEBUG
		;;
	esac
    done
    return 0
}

execute_disk_settings() {
    # when changing from AC to DC and back....
    DEBUG "process function: execute_scheme_settings" DEBUG
    local ARGS LAPTOP

    # ATA spec says it is valid to set both, Advanced Power Management
    # and standby timeout value, which will set the disk to stanby
    # will be managed by disk
    # note that the values for those modes can be tuned in
    # /etc/sysconfig/powersave/hdparm
    . /etc/sysconfig/powersave/scripts/hdparm
    ARGS=""; LAPTOP=""
    case "$DISK_STANDBY_MODE" in
	performance)
	    # disable all power saving
	    ARGS="$HD_STBY_PERF"
	    LAPTOP="stop" ;;
	powersave)
	    # APM: Intermediate power management levels with Standby (10)
	    # Standby timeout set to 30 seconds (see man hdparm)
	    ARGS="$HD_STBY_SAVE"
	    LAPTOP="start" ;;
	aggressiv_powersave)
	    # APM: Minimum power consumption with Standby (1)
	    # Standby timeout set to 10 seconds (see man hdparm)
	    ARGS="$HD_STBY_AGGR"
	    LAPTOP="start" ;;
	no|off)
	    ;;
	*)
	    DEBUG "unknown DISK_STANDBY_MODE 
		   Value: $DISK_STANDBY_MODE" ERROR ;;
    esac

    case "$DISK_ACOUSTIC" in
	performance)
	    ARGS="$ARGS $HD_ACOUSTIC_PERF" ;;
	low)
	    ARGS="$ARGS $HD_ACOUSTIC_LOW" ;;
	quiet)
	    ARGS="$ARGS $HD_ACOUSTIC_QUIET" ;;
	no|off)
	    ;;
	*)
	    DEBUG "unknown DISK_ACOUSTIC 
		   Value: '$DISK_ACOUSTIC'" ERROR ;;
    esac

    [ -n "$LAPTOP" ] && laptop_mode_func $LAPTOP
    [ -n "$ARGS" ]   && exec_hdparm $ARGS
    return 0
}

# first get helper functions (e.g. DEBUG, load_scheme, ...)
. "/etc/sysconfig/powersave/scripts/helper_functions"

# now get general settings:
. "/etc/sysconfig/powersave/common"

# then get scheme specific settings:
SCHEME_TO_EXECUTE=$2
if [ -n $SCHEME_TO_EXECUTE ];then
    load_scheme $SCHEME_TO_EXECUTE
else
    load_scheme
fi

if [ $? != 0 ]; then
    DEBUG "Could not execute scheme settings" ERROR
    exit 1
fi

execute_disk_settings

