aboutsummaryrefslogtreecommitdiff
path: root/sh/rc-cgroup.sh
diff options
context:
space:
mode:
Diffstat (limited to 'sh/rc-cgroup.sh')
-rw-r--r--sh/rc-cgroup.sh225
1 files changed, 225 insertions, 0 deletions
diff --git a/sh/rc-cgroup.sh b/sh/rc-cgroup.sh
new file mode 100644
index 00000000..5d24344d
--- /dev/null
+++ b/sh/rc-cgroup.sh
@@ -0,0 +1,225 @@
+# Copyright (c) 2012-2015 The OpenRC Authors.
+# See the Authors file at the top-level directory of this distribution and
+# https://github.com/OpenRC/openrc/blob/master/AUTHORS
+#
+# This file is part of OpenRC. It is subject to the license terms in
+# the LICENSE file found in the top-level directory of this
+# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
+# This file may not be copied, modified, propagated, or distributed
+# except according to the terms contained in the LICENSE file.
+
+extra_stopped_commands="${extra_stopped_commands} cgroup_cleanup"
+description_cgroup_cleanup="Kill all processes in the cgroup"
+
+cgroup_find_path()
+{
+ local OIFS name dir result
+ [ -n "$1" ] || return 0
+ OIFS="$IFS"
+ IFS=":"
+ while read -r _ name dir; do
+ [ "$name" = "$1" ] && result="$dir"
+ done < /proc/1/cgroup
+ IFS="$OIFS"
+ printf "%s" "${result}"
+}
+
+cgroup_get_pids()
+{
+ local cgroup_procs p pids
+ cgroup_procs="$(cgroup2_find_path)"
+ [ -n "${cgroup_procs}" ] &&
+ cgroup_procs="${cgroup_procs}/${RC_SVCNAME}/cgroup.procs" ||
+ cgroup_procs="/sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks"
+ [ -f "${cgroup_procs}" ] || return 0
+ while read -r p; do
+ [ "$p" -eq $$ ] || pids="${pids} ${p}"
+ done < "${cgroup_procs}"
+ printf "%s" "${pids}"
+ return 0
+}
+
+cgroup_running()
+{
+ [ -d "/sys/fs/cgroup/unified/${RC_SVCNAME}" ] ||
+ [ -d "/sys/fs/cgroup/${RC_SVCNAME}" ] ||
+ [ -d "/sys/fs/cgroup/openrc/${RC_SVCNAME}" ]
+}
+
+cgroup_set_values()
+{
+ [ -n "$1" ] && [ -n "$2" ] && [ -d "/sys/fs/cgroup/$1" ] || return 0
+
+ local controller h
+ controller="$1"
+ h=$(cgroup_find_path "$1")
+ cgroup="/sys/fs/cgroup/${1}${h}openrc_${RC_SVCNAME}"
+ [ -d "$cgroup" ] || mkdir -p "$cgroup"
+
+ set -- $2
+ local name val
+ while [ -n "$1" ] && [ "$controller" != "cpuacct" ]; do
+ case "$1" in
+ $controller.*)
+ if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
+ [ -n "${val}" ]; then
+ veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
+ printf "%s" "$val" > "$cgroup/$name"
+ fi
+ name=$1
+ val=
+ ;;
+ *)
+ [ -n "$val" ] &&
+ val="$val $1" ||
+ val="$1"
+ ;;
+ esac
+ shift
+ done
+ if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] && [ -n "${val}" ]; then
+ veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
+ printf "%s" "$val" > "$cgroup/$name"
+ fi
+
+ if [ -w "$cgroup/tasks" ]; then
+ veinfo "$RC_SVCNAME: adding to $cgroup/tasks"
+ printf "%d" 0 > "$cgroup/tasks"
+ fi
+
+ return 0
+}
+
+cgroup_add_service()
+{
+ # relocate starting process to the top of the cgroup
+ # it prevents from unwanted inheriting of the user
+ # cgroups. But may lead to a problems where that inheriting
+ # is needed.
+ for d in /sys/fs/cgroup/* ; do
+ [ -w "${d}"/tasks ] && printf "%d" 0 > "${d}"/tasks
+ done
+
+ openrc_cgroup=/sys/fs/cgroup/openrc
+ if [ -d "$openrc_cgroup" ]; then
+ cgroup="$openrc_cgroup/$RC_SVCNAME"
+ mkdir -p "$cgroup"
+ [ -w "$cgroup/tasks" ] && printf "%d" 0 > "$cgroup/tasks"
+ fi
+}
+
+cgroup_set_limits()
+{
+ local blkio="${rc_cgroup_blkio:-$RC_CGROUP_BLKIO}"
+ [ -n "$blkio" ] && cgroup_set_values blkio "$blkio"
+
+ local cpu="${rc_cgroup_cpu:-$RC_CGROUP_CPU}"
+ [ -n "$cpu" ] && cgroup_set_values cpu "$cpu"
+
+ local cpuacct="${rc_cgroup_cpuacct:-$RC_CGROUP_CPUACCT}"
+ [ -n "$cpuacct" ] && cgroup_set_values cpuacct "$cpuacct"
+
+ local cpuset="${rc_cgroup_cpuset:-$RC_CGROUP_cpuset}"
+ [ -n "$cpuset" ] && cgroup_set_values cpuset "$cpuset"
+
+ local devices="${rc_cgroup_devices:-$RC_CGROUP_DEVICES}"
+ [ -n "$devices" ] && cgroup_set_values devices "$devices"
+
+ local hugetlb="${rc_cgroup_hugetlb:-$RC_CGROUP_HUGETLB}"
+ [ -n "$hugetlb" ] && cgroup_set_values hugetlb "$hugetlb"
+
+ local memory="${rc_cgroup_memory:-$RC_CGROUP_MEMORY}"
+ [ -n "$memory" ] && cgroup_set_values memory "$memory"
+
+ local net_cls="${rc_cgroup_net_cls:-$RC_CGROUP_NET_CLS}"
+ [ -n "$net_cls" ] && cgroup_set_values net_cls "$net_cls"
+
+ local net_prio="${rc_cgroup_net_prio:-$RC_CGROUP_NET_PRIO}"
+ [ -n "$net_prio" ] && cgroup_set_values net_prio "$net_prio"
+
+ local pids="${rc_cgroup_pids:-$RC_CGROUP_PIDS}"
+ [ -n "$pids" ] && cgroup_set_values pids "$pids"
+
+ return 0
+}
+
+cgroup2_find_path()
+{
+ if grep -qw cgroup2 /proc/filesystems; then
+ case "${rc_cgroup_mode:-hybrid}" in
+ hybrid) printf "/sys/fs/cgroup/unified" ;;
+ unified) printf "/sys/fs/cgroup" ;;
+ esac
+ fi
+ return 0
+}
+
+cgroup2_remove()
+{
+ local cgroup_path rc_cgroup_path
+ cgroup_path="$(cgroup2_find_path)"
+ [ -z "${cgroup_path}" ] && return 0
+ rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
+ [ ! -d "${rc_cgroup_path}" ] ||
+ [ ! -e "${rc_cgroup_path}"/cgroup.events ] &&
+ return 0
+ grep -qx "$$" "${rc_cgroup_path}/cgroup.procs" &&
+ printf "%d" 0 > "${cgroup_path}/cgroup.procs"
+ local key populated vvalue
+ while read -r key value; do
+ case "${key}" in
+ populated) populated=${value} ;;
+ *) ;;
+ esac
+ done < "${rc_cgroup_path}/cgroup.events"
+ [ "${populated}" = 1 ] && return 0
+ rmdir "${rc_cgroup_path}"
+ return 0
+}
+
+cgroup2_set_limits()
+{
+ local cgroup_path
+ cgroup_path="$(cgroup2_find_path)"
+ [ -d "${cgroup_path}" ] || return 0
+ rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
+ [ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
+ [ -f "${rc_cgroup_path}"/cgroup.procs ] &&
+ printf 0 > "${rc_cgroup_path}"/cgroup.procs
+ [ -z "${rc_cgroup_settings}" ] && return 0
+ echo "${rc_cgroup_settings}" | while read -r key value; do
+ [ -z "${key}" ] && continue
+ [ -z "${value}" ] && continue
+ [ ! -f "${rc_cgroup_path}/${key}" ] && continue
+ veinfo "${RC_SVCNAME}: cgroups: setting ${key} to ${value}"
+ printf "%s\n" "${value}" > "${rc_cgroup_path}/${key}"
+ done
+ return 0
+}
+
+cgroup_cleanup()
+{
+ cgroup_running || return 0
+ ebegin "starting cgroups cleanup"
+ local pids loops=0
+ pids="$(cgroup_get_pids)"
+ if [ -n "${pids}" ]; then
+ kill -s CONT ${pids} 2> /dev/null
+ kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
+ yesno "${rc_send_sighup:-no}" &&
+ kill -s HUP ${pids} 2> /dev/null
+ kill -s "${stopsig:-TERM}" ${pids} 2> /dev/null
+ while [ -n "$(cgroup_get_pids)" ] &&
+ [ "${loops}" -lt "${rc_timeout_stopsec:-90}" ]; do
+ loops=$((loops+1))
+ sleep 1
+ done
+ pids="$(cgroup_get_pids)"
+ [ -n "${pids}" ] && yesno "${rc_send_sigkill:-yes}" &&
+ kill -s KILL ${pids} 2> /dev/null
+ fi
+ cgroup2_remove
+ [ -z "$(cgroup_get_pids)" ]
+ eend $? "Unable to stop all processes"
+ return 0
+}