#!/bin/sh
# Copyright 2011 Canonical, Inc
#           2014 Tianon Gravi
# Author: Serge Hallyn <serge.hallyn@canonical.com>
#         Tianon Gravi <tianon@debian.org>
set -e

# for simplicity this script provides no flexibility

# if cgroup is mounted by fstab, don't run
# don't get too smart - bail on any uncommented entry with 'cgroup' in it
if grep -v '^#' /etc/fstab | grep -q cgroup; then
	echo 'cgroups mounted from fstab, not mounting /sys/fs/cgroup'
	exit 0
fi

# kernel provides cgroups?
if [ ! -e /proc/cgroups ]; then
	exit 0
fi

# if we don't even have the directory we need, something else must be wrong
if [ ! -d /sys/fs/cgroup ]; then
	exit 0
fi

# mount /sys/fs/cgroup if not already done
if ! mountpoint -q /sys/fs/cgroup; then
	mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
fi

cd /sys/fs/cgroup

# It is necessary to wait for /sys/fs/cgroup/ to be populated to continue. It takes about 5 seconds. Why?
while [ "$(ls /sys/fs/cgroup/)" = "" ] ; do sleep 1 ; done

# group/permissions of cgroup.procs
if [ -e /sys/fs/cgroup/unified/cgroup.procs ] ; then
	chown :cgroup /sys/fs/cgroup/unified/cgroup.procs
	chmod g+w /sys/fs/cgroup/unified/cgroup.procs
fi

# get/mount list of enabled cgroup controllers
if [ -e /sys/fs/cgroup/unified/cgroup.controllers ] ; then
	if [ "$(cat /sys/fs/cgroup/unified/cgroup.controllers)" != "" ] ; then
		# https://docs.kernel.org/admin-guide/cgroup-v2.html#enabling-and-disabling
		cat /sys/fs/cgroup/unified/cgroup.controllers | tr " " "\n" | sed "s|^|+|g" | tr "\n" " " >> /sys/fs/cgroup/unified/cgroup.subtree_control
	fi
fi
for sys in $(echo $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups) $(ls /sys/fs/cgroup/ | grep unified || true) $(cat /sys/fs/cgroup/unified/cgroup.controllers 2>/dev/null || true) | sort -u); do
	mkdir -p $sys
	if ! mountpoint -q $sys; then
		if ! mount -n -t cgroup -o $sys cgroup $sys 2>/dev/null; then
			rmdir $sys || true
		fi
	fi
done

# Create systemd cgroup if not present
# https://bugs.devuan.org/426
# https://bugs.debian.org/939435
mkdir -p systemd
if ! mountpoint -q systemd; then
	if ! mount -n -t cgroup -o none,name=systemd cgroup systemd; then
		rmdir systemd || true
	fi
fi

# https://bugs.debian.org/940713
if [ -e /sys/fs/cgroup/memory/memory.use_hierarchy ]; then
    echo 1 > /sys/fs/cgroup/memory/memory.use_hierarchy
fi

# Create user's cgroup
for user in $(awk -F ':' '{print $1}' /etc/passwd) ; do
	for i in $(echo $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups) $(cat /sys/fs/cgroup/unified/cgroup.controllers 2>/dev/null || true) | sort -u) ; do
		cgcreate -a $(id -nu $user):$(id -ng $user) -t $(id -nu $user):$(id -ng $user) -g $i:$user || true
	done
	if [ -e /sys/fs/cgroup/unified/$user/cgroup.controllers ] ; then
		if [ "$(cat /sys/fs/cgroup/unified/$user/cgroup.controllers)" != "" ] ; then
			# https://docs.kernel.org/admin-guide/cgroup-v2.html#enabling-and-disabling
			cat /sys/fs/cgroup/unified/$user/cgroup.controllers | tr " " "\n" | sed "s|^|+|g" | tr "\n" " " >> /sys/fs/cgroup/unified/$user/cgroup.subtree_control
		fi
	fi
done

# example /proc/cgroups:
#  #subsys_name	hierarchy	num_cgroups	enabled
#  cpuset	2	3	1
#  cpu	3	3	1
#  cpuacct	4	3	1
#  memory	5	3	0
#  devices	6	3	1
#  freezer	7	3	1
#  blkio	8	3	1

exit 0
