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"
#! /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.mo...@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
-- 
Ubuntu-devel-discuss mailing list
Ubuntu-devel-discuss@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/ubuntu-devel-discuss

Reply via email to