#!/bin/sh die() { printf '%s: Error: %s\n' "$0" "$*" >&2 exit 1 } get_age() { local mtime now mtime=$(stat --format=%Y "$1") || return now=$(date +%s) || return echo $(( now - mtime )) } get_filesystem() { echo / } get_total_memory() { free -b | { read _ read _ total _ echo $total } } root_write() { $AS_ROOT sh -c 'cat > "$1"' sh "$1" || true } join_group() { GROUP_DIR="$1" [ -d "$GROUP_DIR" ] || $AS_ROOT mkdir "$GROUP_DIR" echo $$ | root_write "$GROUP_DIR"/cgroup.procs } add_subtree_controller() { local group="$1" controller="$2" control_file control_file="$group/cgroup.subtree_control" [ "$group" ] && [ "$controller" ] && [ -d "$group" ] && [ -e "$control_file" ] || return case "$group" in /sys/fs/cgroup) ;; *) add_subtree_controller "$(realpath "$group/..")" "$2" ;; esac if ! grep -qe "\\b${controller}\\b" "$control_file" then echo +"$controller" | root_write "$control_file" fi } set_max() { max_file=$group/$2.max if [ ! -e "$max_file" ] then add_subtree_controller "$1"/.. "$2" [ -e "$max_file" ] || return fi printf '%s\n' "$3" | root_write "$max_file" } set_max_ratio() { local group="$1" controller="$2" ratio="$3" limit total=$(get_total_$controller) n=${ratio%%/*} d=${ratio#$n/} [ "$d" = "${d%/*}" ] || return limit=$(( total * n / d )) [ "$limit" ] || return [ "$limit" -gt 0 ] || return case "$controller" in io) fsroot=$(get_filesystem "$IO_ROOT_DIR") || return # TODO: Do not use lsblk, because it fails to report the correct # MOUNTPOINT when a bind mount is present. majmin=$(lsblk -o 'MOUNTPOINT,MAJ:MIN' | sed -ne "s?^$fsroot *??p") || return case "$majmin" in *:*) ;; *) echo "Error: majmin=$majmin" >&2; return 1 ;; esac set_max "$group" "$controller" "$majmin wbps=$limit rbps=$limit" ;; *) set_max "$group" "$controller" "$limit" esac } get_uid() { ( if [ "$SUDO_USER" ] then IFS=: set -- $(getent passwd "${SUDO_USER}") || return echo $3 else id -u fi ) } get_firefox_cgroup_procs() { uid=$(get_uid) [ "$uid" ] || return [ "$DISPLAY" ] || return echo /sys/fs/cgroup/user.slice/user-$uid.slice/user@$uid.service/app.slice/app-firefox.slice/firefox@$DISPLAY.service/cgroup.procs } get_current_group() { read g < /proc/$$/cgroup echo /sys/fs/cgroup/${g#0::/} }