#!/bin/bash
#
# Copyright (c) Authors: http://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.

# Functions:
#
# activate_zram_swap
# activate_ramlog_partition
# activate_compressed_tmp


# Read in basic OS image information
. /etc/fenix-release
# and script configuration
#. /usr/lib/fenix/fenix-common
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Log=/var/log/armhwinfo.log

# It's possible to override ZRAM_PERCENTAGE, ZRAM_MAX_DEVICES, SWAP_ALGORITHM,
# RAMLOG_ALGORITHM and TMP_ALGORITHM here:
[ -f /etc/default/fenix-zram-config ] && . /etc/default/fenix-zram-config

activate_zram_swap() {
	# Do not interfere with already present config-zram package
	dpkg -l | grep -q 'zram-config' && exit 0

	[[ "$ENABLED" != "true" ]] && exit 0

	# Load zram module with n instances (one per CPU core, $ZRAM_MAX_DEVICES are the max)
	zram_max_devs=${ZRAM_MAX_DEVICES:=4}
	cpu_cores=$(grep -c '^processor' /proc/cpuinfo | sed 's/^0$/1/')
	[[ ${cpu_cores} -gt ${zram_max_devs} ]] && zram_devices=${zram_max_devs} || zram_devices=${cpu_cores}
	module_args="$(modinfo zram | awk -F" " '/num_devices/ {print $2}' | cut -f1 -d:)"
	[[ -n ${module_args} ]] && modprobe zram ${module_args}=$(( ${zram_devices} + 2 )) || return

	# Expose 50% of real memory as swap space by default
	zram_percent=${ZRAM_PERCENTAGE:=50}
	mem_info=$(LC_ALL=C free -w 2>/dev/null | grep "^Mem" || LC_ALL=C free | grep "^Mem")
	memory_total=$(awk '{printf("%d",$2*1024)}' <<<${mem_info})
	mem_per_zram_device=$(( ${memory_total} / ${zram_devices} * ${zram_percent} / 100 ))

	# Limit memory available to zram to 50% by default
	mem_limit_percent=${MEM_LIMIT_PERCENTAGE:=50}
	mem_limit_per_zram_device=$(( ${memory_total} / ${zram_devices} * ${mem_limit_percent} / 100 ))

	swap_algo=${SWAP_ALGORITHM:=lzo}
	for (( i=1; i<=zram_devices; i++ )); do
		[[ -f /sys/block/zram${i}/comp_algorithm ]] && echo ${swap_algo} >/sys/block/zram${i}/comp_algorithm 2>/dev/null
		echo -n ${mem_per_zram_device} > /sys/block/zram${i}/disksize
		echo -n ${mem_limit_per_zram_device} > /sys/block/zram${i}/mem_limit
		mkswap /dev/zram${i}
		swapon -p 5 /dev/zram${i}
	done

	# Swapping to HDDs is stupid so switch to settings made for flash memory and zram/zswap
	echo 0 > /proc/sys/vm/page-cluster

	echo -e "\n### Activated ${zram_devices} ${swap_algo} zram swap devices with $(( ${mem_per_zram_device} / 1048576 )) MB each\n" >>${Log}
} # activate_zram_swap

activate_ramlog_partition() {
	# /dev/zram0 will be used as a compressed /var/log partition in RAM if
	# ENABLED=true in /etc/default/fenix-ramlog is set
	ENABLED=$(awk -F"=" '/^ENABLED/ {print $2}' /etc/default/fenix-ramlog)
	[[ "$ENABLED" != "true" ]] && return

	# read size also from /etc/default/fenix-ramlog
	ramlogsize=$(awk -F"=" '/^SIZE/ {print $2}' /etc/default/fenix-ramlog)
	disksize=$(sed -e 's/M$/*1048576/' -e 's/K$/*1024/' <<<${ramlogsize:=50M} | bc)

	# choose RAMLOG_ALGORITHM if defined in /etc/default/fenix-zram-config
	# otherwise try to choose most efficient compression scheme available.
	# See https://patchwork.kernel.org/patch/9918897/
	if [ "X${RAMLOG_ALGORITHM}" = "X" ]; then
		for algo in lz4 lz4hc quicklz zlib brotli zstd ; do
			echo ${algo} >/sys/block/zram0/comp_algorithm 2>/dev/null
		done
	else
		echo ${RAMLOG_ALGORITHM} >/sys/block/zram0/comp_algorithm 2>/dev/null
	fi
	echo -n ${disksize} > /sys/block/zram0/disksize

	# if it fails, select $swap_algo. Workaround for some older kernels
	if [[ $? == 1 ]]; then
		echo ${swap_algo} > /sys/block/zram0/comp_algorithm 2>/dev/null
		echo -n ${disksize} > /sys/block/zram0/disksize
	fi

	mkfs.ext4 -O ^has_journal -s 1024 -L log2ram /dev/zram0
	algo=$(sed 's/.*\[\([^]]*\)\].*/\1/g' </sys/block/zram0/comp_algorithm)
} # activate_ramlog_partition

activate_compressed_tmp() {
	# create /tmp not as tmpfs but zram compressed if no fstab entry exists
	grep -q '/tmp' /etc/fstab && return

	tmp_device=$(( ${zram_devices} + 1 ))
	if [[ -f /sys/block/zram${tmp_device}/comp_algorithm ]]; then
		if [ "X${TMP_ALGORITHM}" = "X" ]; then
			echo ${swap_algo} >/sys/block/zram${tmp_device}/comp_algorithm 2>/dev/null
		else
			echo ${TMP_ALGORITHM} >/sys/block/zram${tmp_device}/comp_algorithm 2>/dev/null
		fi
	fi
	echo -n $(( ${memory_total} / 2 )) > /sys/block/zram${tmp_device}/disksize
	mkfs.ext4 -O ^has_journal -s 1024 -L tmp /dev/zram${tmp_device}
	mount -o nosuid,discard /dev/zram${tmp_device} /tmp
	chmod 777 /tmp
	algo=$(sed 's/.*\[\([^]]*\)\].*/\1/g' </sys/block/zram${tmp_device}/comp_algorithm)
	echo -e "\n### Activated ${algo} compressed /tmp" >>${Log}
} # activate_compressed_tmp

case $1 in
	*start*)
		activate_zram_swap
#		activate_ramlog_partition
#		activate_compressed_tmp
		;;
esac
