Skip to content

Instantly share code, notes, and snippets.

@Trucido
Created May 23, 2018 07:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Trucido/0a4c8e7ad7598f427e70874dbe0eeac3 to your computer and use it in GitHub Desktop.
Save Trucido/0a4c8e7ad7598f427e70874dbe0eeac3 to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# /etc/init.d/zswap || zswap.service || /usr/local/sbin/zswap || somethingsomething
#
# License: copyleft, copyup, copydown, copyright, do whatever the fuck you want.
### BEGIN INIT INFO
# Provides: zswap
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Zswap
# Description: Activate and tune Zswap compressed cache for swap pages
### END INIT INFO
# TODO: Optimize module detection instead of this utterly ridiculous trying to fail until we succeed strategy.
# TODO: Merge main init script with swap detection logic.
# : Also Merge Zram activation and optimization script -- use zram::foo() for zram stuff.
# TODO: Log to syslog or somewhere instead of nullifying output.
# : Any stdout breaks some init/startup scripts when called directly.
# TODO: Make this an actual lsb compliant service? Also test if works with systemd-sysv-generator
# TODO: More tunables. Compressor/Zpool/max_pool_percent etc. (external config file? upstart env style? or extra args?)
# Set upstart job for compatibility.
# Also useful for `logger -t "${JOB}" "foo"`
#JOB="ZSWAP" ##TODO
# Tunables
# max_pool_percent
[ -z "$ZSWAP_SIZE" ] && ZSWAP_SIZE="25"
zswap::set_params() {
# Set zswap sysfs params
local max_pool_size="${ZSWAP_SIZE}"
# TODO: add case for compressor, zpool, and max_pool_percent
# TODO: possibly add zswap_size_mb param with mb to percent math?
# Set Compressor
if [ -e "/sys/module/zswap/parameters/compressor" ]; then
# Try lz4
if ! echo lz4 > "/sys/module/zswap/parameters/compressor"; then
# Fallback: lzo
echo lzo > "/sys/module/zswap/parameters/compressor" || :
fi
fi
# Set Zpool
if [ -e "/sys/module/zswap/parameters/zpool" ]; then
# Try z3fold
if ! echo z3fold > "/sys/module/zswap/parameters/zpool"; then
# Fallback: zbud
echo zbud > "/sys/module/zswap/parameters/zpool" || :
fi
fi
# Set max_pool_percent
if [ -e "/sys/module/zswap/parameters/max_pool_percent" ]; then
# Try $ZSWAP_SIZE if set
if [ ! -z "$max_pool_size" ]; then
if echo "$max_pool_size" > "/sys/module/zswap/parameters/max_pool_percent"; then
return
else
# Fallback: Default 20%
echo 20 > "/sys/module/zswap/parameters/max_pool_percent" || :
fi
fi
else
# Fallback: Default 20% if $ZSWAP_SIZE unset
echo 20 > "/sys/module/zswap/parameters/max_pool_percent" || :
fi
}
zswap::load_depmods() {
# Load optimal compressor and zpool modules if available and not already loaded
# Modprobe $COMPRESSOR
# Try lz4
if ! grep -qE 'lz4|lz4_compress' "/proc/modules" || [ ! -e "/sys/module/lz4" ]; then
modprobe -q lz4 || :
fi
# Modprobe $ZPOOL
# Try z3fold
if ! grep -q "^z3fold " "/proc/modules" || [ ! -e "/sys/module/z3fold" ]; then
if modprobe -q z3fold; then
return
elif ! grep -q "^zbud " "/proc/modules" || [ ! -e "/sys/module/zbud" ]; then
if modprobe -q zbud; then
return
fi
fi
# Fallback: zbud
elif ! grep -q "^zbud " "/proc/modules" || [ ! -e "/sys/module/zbud" ]; then
modprobe -q zbud || :
fi
}
zswap::load_module() {
# Try and modprobe zswap with optimal zpool/compressor.
if ! grep -q "^zswap " "/proc/modules" || [ ! -e "/sys/module/zswap" ]; then
# Try z3fold/lz4
if modprobe -q zswap zpool=z3fold compressor=lz4 enabled=Y; then
return
# Try zbud/lz4
elif modprobe -q zswap zpool=zbud compressor=lz4 enabled=Y; then
return
# Try z3fold/lzo
elif modprobe -q zswap zpool=z3fold compressor=lzo enabled=Y; then
return
else
# Fallback: Default zbud/lzo
modprobe -q zswap zpool=zbud compressor=lzo enabled=Y || :
fi
fi
}
#zswap::start()
start() {
# Load or Reload Zswap modules.
if grep -q "^zswap " "/proc/modules" ; then
# Deactivate zswap module if loaded
if [ -e "/sys/module/zswap/parameters/enabled" ]; then
echo N > "/sys/module/zswap/parameters/enabled" || :
fi
# Remove zswap module before full reset
modprobe -rq zswap 2>/dev/null || :;
# Modprobe optimal compressor/zpool modules if available
zswap::load_depmods >/dev/null 2>&1 || :;
# Modprobe zswap with best available compressor/zpool
zswap::load_mod >/dev/null 2>&1 || :
elif [ -e /sys/module/zswap ]; then
# Else builtin? Then load any missing modules for optimal params
zswap::load_depmods >/dev/null 2>&1 || :
fi
# Reset Zswap state and tune params
if [ -e "/sys/module/zswap/parameters/enabled" ]; then
# Deactivate zswap
echo N > "/sys/module/zswap/parameters/enabled" || :;
# Set zswap sysfs parameters
zswap::set_params >/dev/null 2>&1 || :;
# Activate zswap
echo Y > "/sys/module/zswap/parameters/enabled" || :
fi
}
#zswap::stop()
stop() {
return 0
# Not really necessary to stop... but we could do:
#echo N > "/sys/module/zswap/parameters/enabled"
#local tries=0
#while [ ${tries} -le 6 ]; do
# modprobe -rq zswap 2>/dev/null && break
# : $(( tries += 1 ))
# sleep 0.5
#done
}
#zswap::status()
status() {
# Show general swap info first.
printf '\nswap block device(s):\n'
cat /proc/swaps
# Check if dir exists before we spam
local ddir="/sys/kernel/debug/zswap"
local mdir="/sys/module/zswap/parameters"
if [ ! -e "${mdir}" ] && [ ! -e "${ddir}" ]; then
printf "\nZswap module not loaded.\n"
return
else
# Spam various zswap settings.
# Spam Zswap module parameters
if [ -d "${mdir}" ]; then
printf '\nZswap parameters in %s:\n' "${mdir}"
cd "${mdir}" || return 1
# shellcheck disable=SC2035
grep -s '^' * || :
fi
# Spam Zswap debug stats
if [ -d "${ddir}" ]; then
printf '\nZswap debug stats in %s:\n' "${ddir}"
cd "${ddir}" || return 1
# shellcheck disable=SC2035
grep -s '^' * || :
fi
fi
}
#zswap::usage()
usage() {
cat <<EOF
Usage: $0 <start|stop|status>
Start, stop, or show the status of compressed swap cache.
EOF
exit "$1"
}
## MAIN ##
# TODO: set correct exit status after testing. For now return/exit 0.
main() {
set -e
# If we're called without any argument, just run it by default. #TODO
if [ $# -lt 1 ]; then
# Nullify any chatter (hopefully).
start >/dev/null 2>&1 || :
elif [ $# -gt 1 ]; then
usage 0
else
# If given argument, ensure it's one we can handle.
local cmd="$1"
shift
case "${cmd}" in
start|stop|status)
if [ $# -ne 0 ]; then
usage 0
fi
start >/dev/null 2>&1 || :
;;
*)
usage 0
;;
esac
# Just call the func directly if valid.
${cmd} "$@"
fi
}
#logger -t "${JOB}" "Starting Zswap compressed swap cache"
main "$@" || :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment