diff --git a/main/postmarketos-zram/APKBUILD b/main/postmarketos-zram/APKBUILD new file mode 100644 index 000000000..01bf442a2 --- /dev/null +++ b/main/postmarketos-zram/APKBUILD @@ -0,0 +1,32 @@ +maintainer="Clayton Craft " +pkgname=postmarketos-zram +pkgver=1 +pkgrel=0 +pkgdesc="zram swap configuration for postmarketOS" +url="https://postmarketos.org" +arch="noarch" +license="GPL-3.0-or-later" +depends="util-linux-misc" +subpackages="$pkgname-openrc $pkgname-systemd" +replaces="postmarketos-base" +options="!check" +source=" + postmarketos-zram-swap.initd + postmarketos-zram-swap.service + zramstart + zramstop +" + +package() { + install -Dm755 zramstart -t "$pkgdir"/usr/bin + install -Dm755 zramstop -t "$pkgdir"/usr/bin + install -Dm755 postmarketos-zram-swap.initd "$pkgdir"/etc/init.d/postmarketos-zram-swap + install -Dm644 postmarketos-zram-swap.service -t "$pkgdir"/usr/lib/systemd/system +} + +sha512sums=" +ca91be78a47c00f40f3e645f79a72b2cd7ba3f080e2feb256998bb121f64c0394041f2ed822ad307ac36e86398b8175b3284dc5097a7017947e520a304b0a37d postmarketos-zram-swap.initd +5c1787bc2d597726113aaf3ea59229b5a56b8fc3446c78406a202e163a0b37ac564a87b2acc1c1f1a7dcdc18ff863c45e13aa687b93fa537c5ef000b9e8d6d19 postmarketos-zram-swap.service +798e162f0393621144bfef843fa2f21f9cdfaaa4cd07d4d8b63499f8c3db27d6b9cbb901b43459e5378bd2bb6905f1e371ff915b8e439908944e8030eee7b48e zramstart +a70d2bcb26c1af42a71811a1c1cd2984808f5ce09d7af52b26824cf5c15c8a9c819691fc6290cf3028226fca39f6e7a495546c5573c582a14d5a8c7c65dbfe3e zramstop +" diff --git a/main/postmarketos-zram/postmarketos-zram-swap.initd b/main/postmarketos-zram/postmarketos-zram-swap.initd new file mode 100644 index 000000000..c664bbc23 --- /dev/null +++ b/main/postmarketos-zram/postmarketos-zram-swap.initd @@ -0,0 +1,25 @@ +#!/sbin/openrc-run +# SPDX-License-Identifier: GPL-2.0-only + +depend() { + need localmount + after bootmisc modules + provide swap +} + +start() { + ebegin "Starting zram swap" + if [ ! -f /usr/share/misc/source_deviceinfo ]; then + eend 1 "deviceinfo not found" + return 1 + fi + + zramstart + eend $? +} + +stop() { + ebegin "Stopping zram swap" + zramstop + eend $? +} diff --git a/main/postmarketos-zram/postmarketos-zram-swap.service b/main/postmarketos-zram/postmarketos-zram-swap.service new file mode 100644 index 000000000..cd8e79c54 --- /dev/null +++ b/main/postmarketos-zram/postmarketos-zram-swap.service @@ -0,0 +1,15 @@ +[Unit] +Description=Enable compressed swap in memory using zram +DefaultDependencies=no +Before=swap.target + +[Service] +Type=oneshot +RemainAfterExit=yes +TimeoutStartSec=30sec +ExecCondition=sh -c '. /usr/share/misc/source_deviceinfo' +ExecStart=/usr/bin/zramstart +ExecStop=/usr/bin/zramstop + +[Install] +WantedBy=swap.target diff --git a/main/postmarketos-zram/zramstart b/main/postmarketos-zram/zramstart new file mode 100644 index 000000000..55d5be6f1 --- /dev/null +++ b/main/postmarketos-zram/zramstart @@ -0,0 +1,71 @@ +#!/bin/sh +# shellcheck disable=SC3043 + +set -e + +# shellcheck disable=SC1091 +. /usr/share/misc/source_deviceinfo + +get_size() { + # Size defaults to: + # - 75% of RAM for devices with 2GB of RAM or less + # - 50% of RAM for devices with between 2GB and 6GB of RAM + # - 25% of RAM for devices with greater 6GB of RAM + # This is loosely based on some data here: + # https://gitlab.postmarketos.org/postmarketOS/pmaports/-/merge_requests/3752#note_1229631449 + + local mem_size_mb size_pct + mem_size_mb="$(LC_ALL=C free -m | awk '/^Mem:/{print $2}')" + + if [ "$mem_size_mb" -le 2048 ]; then + size_pct=75 + elif [ "$mem_size_mb" -gt 6144 ]; then + size_pct=25 + else + size_pct=50 + fi + + # Allow overriding the size as a percentage of RAM using a deviceinfo var, or + # disabling it completely + if [ -n "$deviceinfo_zram_swap_pct" ]; then + # 0% --> disable zram swap + if [ "$deviceinfo_zram_swap_pct" = "0" ]; then + echo 0 + return + fi + + size_pct="$deviceinfo_zram_swap_pct" + fi + + echo $((mem_size_mb * size_pct / 100)) +} + +get_algo() { + # Default to zstd compression, and allow overriding via deviceinfo + # TODO: Architecture-specific defaults? + # TODO: Ensure deviceinfo uses valid and usable algorithm for running + # kernel + echo "${deviceinfo_zram_swap_algo:-zstd}" +} + +size=$(get_size) +algo=$(get_algo) + +[ "$size" -eq 0 ] && exit 0 + +if swapon --show=NAME --noheadings | grep -q '^/dev/zram'; then + echo "ZRAM swap already active, skipping setup" + exit 0 +fi + +modprobe -q zram num_devices=1 +dev="$(zramctl -f -a "$algo" -s "${size}"M)" +mkswap "$dev" >/dev/null +swapon "$dev" >/dev/null + +# ZRAM-optimized sysctl settings +sysctl -w \ + vm.page-cluster=0 \ + vm.swappiness=180 >/dev/null + +echo "ZRAM swap device $dev activated using $algo and size $size MB" diff --git a/main/postmarketos-zram/zramstop b/main/postmarketos-zram/zramstop new file mode 100644 index 000000000..d45e1b644 --- /dev/null +++ b/main/postmarketos-zram/zramstop @@ -0,0 +1,6 @@ +#!/bin/sh + +for i in $(grep '^/dev/zram' /proc/swaps | awk '{ print $1 }'); do + swapoff "$i" && zramctl --reset "$i" + echo "Stopped ZRAM swap device $i" +done