[RFC] zswap for Precise, with script
John Moser
john.r.moser at gmail.com
Thu May 17 13:55:52 UTC 2012
Any thoughts on this? I wrote it on a whim after installing an SSD and
completely disabling all swap. Haven't checked to see if Ubuntu
supports hibernate to file yet (creating a hibernation file on demand
would be optimal for me...)
This works with kernel 3.2.0 ... 3.0 used num_devices as the parameter
for zram, while 2.6.32 used num (I think). They keep changing the
parameter name!
This init script (sorry, I have no clue how to write an upstart job)
will load zram, set one of its devices to a given size, create swap on
it, and turn that swap on. It'll also deactivate the swap and free the
associated RAM.
Accepted sizes are "half" and "quarter" of installed RAM as gotten by
MemTotal in /proc/meminfo; any size in bytes; or suffixed K, M, G sizes.
/etc/default/zswap can contain the following variables:
# Set to 1 to disable
ZSWAP_DISABLED=0
# Number of /dev/zramX devices
ZRAM_NUM_DEVICES=4
# Swap device is /dev/$ZSWAP_DEVICE
ZSWAP_DEVICE="zram0"
# Size
ZSWAP_SIZE="quarter"
-------------- next part --------------
#! /bin/sh
### BEGIN INIT INFO
# Provides: zswap
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Activate compressed swap
### END INIT INFO
#
#
# Version: 1.0 john.r.moser at gmail.com
#
#
# It's also possible to resize the zswap by device hopping, i.e.
# making a new one on /dev/zram1, swapon /dev/zram1, and then
# swapoff /dev/zram0. This would be CPU intensive...
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Sets up compressed swap"
NAME=zswap
SCRIPTNAME=/etc/init.d/$NAME
# Default value
ZRAM_NUM_DEVICES=4
ZSWAP_DEVICE="zram0"
ZSWAP_SIZE="quarter"
# Read config file if it is present.
if [ -r /etc/default/$NAME ]; then
. /etc/default/$NAME
fi
# Gracefully exit if disabled
[ "$ZSWAP_DISABLED" = "1" ] && exit 0
is_numeric() {
echo "$@" | grep -q -v "[^0-9]"
}
#Takes:
# zswap_to_bytes 524288
# zswap_to_bytes 512K
# zswap_to_bytes 128M
# zswap_to_bytes 2G
# otherwise formed parameters are errors.
zswap_to_bytes() {
MODIFIER="${1#${1%?}}"
ZR_SIZE="${1: -1}"
# Numeric: just pass as-is
if ( is_numeric ${1} ) ; then
echo ${1}
return 0
fi
# If size isn't a number,
if ! ( is_numeric ${ZR_SIZE} ) ; then
echo "0"
return 1
fi
if [ "${MODIFIER}" = "K" ]; then
ZR_SIZE=$(( ZR_SIZE * 1024 ))
elif [ "${MODIFIER}" = "M" ]; then
ZR_SIZE=$(( ZR_SIZE * 1024 * 1024 ))
elif [ "${MODIFIER}" = "G" ]; then
ZR_SIZE=$(( ZR_SIZE * 1024 * 1024 * 1024 ))
elif [ ! is_numeric "${MODIFIER}" ]; then
echo "0"
return 1
fi
echo $ZR_SIZE
}
#
# Function that starts the daemon/service.
#
d_start() {
ZSWAP_LOADED=0
swapon -s | cut -f 1 | grep "/dev/${ZSWAP_DEVICE}" && ZSWAP_LOADED=1
if [ "${ZSWAP_LOADED}" -eq "1" ]; then
echo "zswap already in use"
return 1
fi
# this parameter name keeps changing with new kernel versions
modprobe zram zram_num_devices=${ZRAM_NUM_DEVICES}
# Does it now exist?
if [ ! -b /dev/${ZSWAP_DEVICE} ]; then
echo "/dev/${ZSWAP_DEVICE} does not exist!"
return 1
fi
# half or quarter size
if [ "${ZSWAP_SIZE}" = "half" -o "${ZSWAP_SIZE}" = "quarter" ]; then
MEM_SZ=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}')
if [ "${ZSWAP_SIZE}" = "half" ]; then
ZSWAP_SIZE=$(( MEM_SZ * 512 ))
else
ZSWAP_SIZE=$(( MEM_SZ * 256 ))
fi
else
ZSWAP_SIZE=$( zswap_to_bytes $ZSWAP_SIZE )
if [ "${ZSWAP_SIZE}" = "0" ]; then
echo "Invalid ZSWAP_SIZE"
return 1
fi
fi
echo $ZSWAP_SIZE > /sys/block/${ZSWAP_DEVICE}/disksize
mkswap /dev/${ZSWAP_DEVICE}
swapon /dev/${ZSWAP_DEVICE}
}
#
# Function that stops the daemon/service.
#
d_stop() {
ZSWAP_LOADED=0
swapon -s | cut -f 1 | grep "/dev/${ZSWAP_DEVICE}" && ZSWAP_LOADED=1
if [ "${ZSWAP_LOADED}" != "1" ]; then
echo "zswap not in use"
return 1
fi
if ! ( swapoff /dev/${ZSWAP_DEVICE} ); then
echo "Cannot de-activate compressed swap /dev/${ZSWAP_DEVICE}!"
return 1
fi
# Double check this
ZSWAP_LOADED=0
swapon -s | cut -f 1 | grep "/dev/${ZSWAP_DEVICE}" && ZSWAP_LOADED=1
if [ "${ZSWAP_LOADED}" = "1" ]; then
echo "zswap /dev/${ZSWAP_DEVICE} did not de-activate!"
return 1
fi
# free the block device's memory
echo 1 > /sys/block/${ZSWAP_DEVICE}/reset
modprobe -r zram
}
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
d_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
d_stop
echo "."
;;
#reload)
#
# No reload target
#
#;;
restart|force-reload)
echo -n "Restarting $DESC: $NAME"
d_stop
#sleep 1
d_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
More information about the Ubuntu-devel-discuss
mailing list