mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-25 16:31:13 +00:00
0bd7dfa3ed
Zram block devices have supported trim/discard for over six years, let's enable it. This allows the zram device to actually free up allocated memory when it's marked as unused in the filesystem metadata, as explained in more detail in the original commit message [1]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/drivers/block/zram/zram_drv.c?h=linux-4.14.y&id=f4659d8e620d08bd1a84a8aec5d2f5294a242764 Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com>
218 lines
6.1 KiB
Bash
Executable File
218 lines
6.1 KiB
Bash
Executable File
#!/bin/sh /etc/rc.common
|
|
|
|
START=15
|
|
|
|
EXTRA_COMMANDS="compact status"
|
|
EXTRA_HELP=" compact trigger compaction for all Z-RAM swap dev's
|
|
status print out status information & statistics about Z-RAM swap devices"
|
|
|
|
ram_getsize()
|
|
{
|
|
local line
|
|
|
|
while read line; do case "$line" in MemTotal:*) set $line; echo "$2"; break ;; esac; done </proc/meminfo
|
|
}
|
|
|
|
zram_getsize() # in megabytes
|
|
{
|
|
local zram_size="$( uci -q get system.@system[0].zram_size_mb )"
|
|
local ram_size="$( ram_getsize )"
|
|
|
|
if [ -z "$zram_size" ]; then
|
|
# e.g. 6mb for 16mb-routers or 61mb for 128mb-routers
|
|
echo $(( ram_size / 2048 ))
|
|
else
|
|
echo "$zram_size"
|
|
fi
|
|
}
|
|
|
|
zram_applicable()
|
|
{
|
|
local zram_dev="$1"
|
|
|
|
[ -e "$zram_dev" ] || {
|
|
logger -s -t zram_applicable -p daemon.crit "[ERROR] device '$zram_dev' not found"
|
|
return 1
|
|
}
|
|
|
|
which mkswap >/dev/null || {
|
|
logger -s -t zram_applicable -p daemon.err "[ERROR] 'mkswap' not installed"
|
|
return 1
|
|
}
|
|
|
|
which swapon >/dev/null || {
|
|
logger -s -t zram_applicable -p daemon.err "[ERROR] 'swapon' not installed"
|
|
return 1
|
|
}
|
|
|
|
which swapoff >/dev/null || {
|
|
logger -s -t zram_applicable -p daemon.err "[ERROR] 'swapoff' not installed"
|
|
return 1
|
|
}
|
|
}
|
|
|
|
zram_dev()
|
|
{
|
|
local idx="$1"
|
|
echo "/dev/zram${idx:-0}"
|
|
}
|
|
|
|
zram_reset()
|
|
{
|
|
local dev="$1"
|
|
local message="$2"
|
|
local proc_entry="/sys/block/$( basename "$dev" )/reset"
|
|
|
|
logger -s -t zram_reset -p daemon.debug "$message via $proc_entry"
|
|
echo "1" >"$proc_entry"
|
|
}
|
|
|
|
zram_getdev()
|
|
{
|
|
#get unallocated zram dev
|
|
local zdev=$( zram_dev )
|
|
|
|
if [ "$(mount | grep $zdev)" ]; then
|
|
local idx=$(cat /sys/class/zram-control/hot_add)
|
|
zdev="$( zram_dev $idx )"
|
|
fi
|
|
|
|
echo $zdev
|
|
}
|
|
|
|
zram_comp_algo()
|
|
{
|
|
local dev="$1"
|
|
local zram_comp_algo="$( uci -q get system.@system[0].zram_comp_algo )"
|
|
|
|
if [ -z "$zram_comp_algo" ] || [ ! -e /sys/block/$( basename $dev )/comp_algorithm ]; then
|
|
return 0
|
|
fi
|
|
|
|
if [ $(grep -c "$zram_comp_algo" /sys/block/$( basename $dev )/comp_algorithm) -ne 0 ]; then
|
|
logger -s -t zram_comp_algo -p daemon.debug "Set compression algorithm '$zram_comp_algo' for zram '$dev'"
|
|
echo $zram_comp_algo > "/sys/block/$( basename $dev )/comp_algorithm"
|
|
else
|
|
logger -s -t zram_comp_algo -p daemon.debug "Compression algorithm '$zram_comp_algo' is not supported for '$dev'"
|
|
fi
|
|
}
|
|
|
|
zram_comp_streams()
|
|
{
|
|
local dev="$1"
|
|
local logical_cpus=$( grep -ci "^processor" /proc/cpuinfo )
|
|
[ $logical_cpus -gt 1 ] || return 1
|
|
local zram_comp_streams="$( uci -q get system.@system[0].zram_comp_streams )"
|
|
[ -n "$zram_comp_streams" ] && [ "$zram_comp_streams" -le "$logical_cpus" ] || zram_comp_streams=$logical_cpus
|
|
if [ -e /sys/block/$( basename $dev )/max_comp_streams ]; then
|
|
logger -s -t zram_comp_streams -p daemon.debug "Set max compression streams to '$zram_comp_streams' for zram '$dev'"
|
|
echo $zram_comp_streams > /sys/block/$( basename $dev )/max_comp_streams
|
|
fi
|
|
}
|
|
|
|
#print various stats info about zram swap device
|
|
zram_stats()
|
|
{
|
|
local zdev="/sys/block/$( basename "$1" )"
|
|
|
|
printf "\nGathering stats info for zram device \"$( basename "$1" )\"\n\n"
|
|
|
|
printf "Z-RAM\n-----\n"
|
|
printf "%-25s - %s\n" "Block device" $zdev
|
|
awk '{ printf "%-25s - %d MiB\n", "Device size", $1/1024/1024 }' <$zdev/disksize
|
|
printf "%-25s - %s\n" "Compression algo" "$(cat $zdev/comp_algorithm)"
|
|
printf "%-25s - %s\n" "Compression streams" "$( cat $zdev/max_comp_streams)"
|
|
|
|
awk 'BEGIN { fmt = "%-25s - %.2f %s\n"
|
|
fmt2 = "%-25s - %d\n"
|
|
print "\nDATA\n----" }
|
|
{ printf fmt, "Original data size", $1/1024/1024, "MiB"
|
|
printf fmt, "Compressed data size", $2/1024/1024, "MiB"
|
|
printf fmt, "Compress ratio", $1/$2, ""
|
|
print "\nMEMORY\n------"
|
|
printf fmt, "Memory used, total", $3/1024/1024, "MiB"
|
|
printf fmt, "Allocator overhead", ($3-$2)/1024/1024, "MiB"
|
|
printf fmt, "Allocator efficiency", $2/$3*100, "%"
|
|
printf fmt, "Maximum memory ever used", $5/1024/1024, "MiB"
|
|
printf fmt, "Memory limit", $4/1024/1024, "MiB"
|
|
print "\nPAGES\n-----"
|
|
printf fmt2, "Same pages count", $6
|
|
printf fmt2, "Pages compacted", $7 }' <$zdev/mm_stat
|
|
|
|
awk '{ printf "%-25s - %d\n", "Free pages discarded", $4 }' <$zdev/io_stat
|
|
}
|
|
|
|
zram_compact()
|
|
{
|
|
# compact zram device (reduce memory allocation overhead)
|
|
local zdev="/sys/block/$( basename "$1" )"
|
|
|
|
local old_mem_used=$(awk '{print $3}' <$zdev/mm_stat)
|
|
local old_overhead=$(awk '{print $3-$2}' <$zdev/mm_stat)
|
|
|
|
echo 1 > $zdev/compact
|
|
|
|
# If not running interactively, than just return
|
|
[ -z "$PS1" ] && return 0
|
|
|
|
echo ""
|
|
echo "Compacting zram device $zdev"
|
|
awk -v old_mem="$old_mem_used" -v ovr="$old_overhead" 'BEGIN { fmt = "%-25s - %.1f %s\n" }
|
|
{ printf fmt, "Memory usage reduced by ", (old_mem-$3)/1024/1024, "MiB"
|
|
printf fmt, "Overhead reduced by", (ovr-($3-$2))/ovr*100, "%" }' <$zdev/mm_stat
|
|
}
|
|
|
|
start()
|
|
{
|
|
if [ $( grep -cs zram /proc/swaps ) -ne 0 ]; then
|
|
logger -s -t zram_start -p daemon.notice "[OK] zram swap is already mounted"
|
|
return 1
|
|
fi
|
|
|
|
local zram_size="$( zram_getsize )"
|
|
local zram_dev="$( zram_getdev )"
|
|
zram_applicable "$zram_dev" || return 1
|
|
local zram_priority="$( uci -q get system.@system[0].zram_priority )"
|
|
zram_priority=${zram_priority:+-p $zram_priority}
|
|
|
|
logger -s -t zram_start -p daemon.debug "activating '$zram_dev' for swapping ($zram_size MegaBytes)"
|
|
|
|
zram_reset "$zram_dev" "enforcing defaults"
|
|
zram_comp_algo "$zram_dev"
|
|
zram_comp_streams "$zram_dev"
|
|
echo $(( $zram_size * 1024 * 1024 )) >"/sys/block/$( basename "$zram_dev" )/disksize"
|
|
mkswap "$zram_dev"
|
|
swapon -d $zram_priority "$zram_dev"
|
|
}
|
|
|
|
stop()
|
|
{
|
|
local zram_dev
|
|
|
|
for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do {
|
|
logger -s -t zram_stop -p daemon.debug "deactivate swap $zram_dev"
|
|
swapoff "$zram_dev" && zram_reset "$zram_dev" "claiming memory back"
|
|
local dev_index="$( echo $zram_dev | grep -o "[0-9]*$" )"
|
|
if [ $dev_index -ne 0 ]; then
|
|
logger -s -t zram_stop -p daemon.debug "removing zram $zram_dev"
|
|
echo $dev_index > /sys/class/zram-control/hot_remove
|
|
fi
|
|
} done
|
|
}
|
|
|
|
# show memory stats for all zram swaps
|
|
status()
|
|
{
|
|
for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do {
|
|
zram_stats "$zram_dev"
|
|
} done
|
|
}
|
|
|
|
# trigger compaction for all zram swaps
|
|
compact()
|
|
{
|
|
for zram_dev in $( grep zram /proc/swaps |awk '{print $1}' ); do {
|
|
zram_compact "$zram_dev"
|
|
} done
|
|
}
|