commit:     457f928e793cb1f6ef254935ad07f58b8762c72f
Author:     William Hubbs <w.d.hubbs <AT> gmail <DOT> com>
AuthorDate: Thu Sep 14 15:38:10 2017 +0000
Commit:     William Hubbs <williamh <AT> gentoo <DOT> org>
CommitDate: Thu Sep 14 15:38:10 2017 +0000
URL:        https://gitweb.gentoo.org/proj/openrc.git/commit/?id=457f928e

add support for control groups version 2

This is for #94.

 etc/rc.conf         |  45 +++++++++++++++++++----
 init.d/sysfs.in     | 100 +++++++++++++++++++++++++++++++++++++++++++---------
 sh/openrc-run.sh.in |  15 +++++---
 sh/rc-cgroup.sh.in  |  51 +++++++++++++++++++++++++++
 4 files changed, 182 insertions(+), 29 deletions(-)

diff --git a/etc/rc.conf b/etc/rc.conf
index 689e6be2..d9ad911d 100644
--- a/etc/rc.conf
+++ b/etc/rc.conf
@@ -191,13 +191,43 @@ rc_tty_number=12
 ##############################################################################
 # LINUX CGROUPS RESOURCE MANAGEMENT
 
-# If you have cgroups turned on in your kernel, this switch controls
-# whether or not a group for each controller is mounted under
-# /sys/fs/cgroup.
-# None of the other options in this section work if this is set to "NO".
+# This sets the mode used to mount cgroups.
+# "hybrid" mounts cgroups version 2 on /sys/fs/cgroup/unified and
+# cgroups version 1 on /sys/fs/cgroup.
+# "legacy" mounts cgroups version 1 on /sys/fs/cgroup
+# "unified" mounts cgroups version 2 on /sys/fs/cgroup
+#rc_cgroup_mode="hybrid"
+
+# This is a list of controllers which should be enabled for cgroups version 2.
+# If hybrid mode is being used, controllers listed here will not be
+# available for cgroups version 1.
+# This is a global setting.
+#rc_cgroup_controllers=""
+
+# This variable contains the cgroups version 2 settings for your services.
+# If this is set in this file, the settings will apply to all services.
+# If you want different settings for each service, place the settings in
+# /etc/conf.d/foo for service foo.
+# The format is to specify the setting and value followed by a newline.
+# Multiple settings and values can be specified.
+# For example, you would use this to set the maximum memory and maximum
+# number of pids for a service.
+#rc_cgroup_settings="
+#memory.max 10485760
+#pids.max max
+#"
+#
+# For more information about the adjustments that can be made with
+# cgroups version 2, see Documentation/cgroups-v2.txt in the linux kernel
+# source tree.
+#rc_cgroup_settings=""
+
+# This switch controls whether or not cgroups version 1 controllers are
+# individually mounted under
+# /sys/fs/cgroup in hybrid or legacy mode.
 #rc_controller_cgroups="YES"
 
-# The following settings allow you to set up values for the cgroup
+# The following settings allow you to set up values for the cgroups version 1
 # controllers for your services.
 # They can be set in this file;, however, if you do this, the settings
 # will apply to all of your services.
@@ -211,8 +241,9 @@ rc_tty_number=12
 # cpu.shares 512
 # "
 #
-#For more information about the adjustments that can be made with
-#cgroups, see Documentation/cgroups/* in the linux kernel source tree.
+# For more information about the adjustments that can be made with
+# cgroups version 1, see Documentation/cgroups-v1/* in the linux kernel
+# source tree.
 
 # Set the blkio controller settings for this service.
 #rc_cgroup_blkio=""

diff --git a/init.d/sysfs.in b/init.d/sysfs.in
index a2538114..9f39fb57 100644
--- a/init.d/sysfs.in
+++ b/init.d/sysfs.in
@@ -107,20 +107,16 @@ mount_misc()
        fi
 }
 
-mount_cgroups()
+cgroup1_base()
 {
-       # set up kernel support for cgroups
-       if [ -d /sys/fs/cgroup ] && ! mountinfo -q /sys/fs/cgroup; then
-               if grep -qs cgroup /proc/filesystems; then
-                       ebegin "Mounting cgroup filesystem"
-                       local 
opts="${sysfs_opts},mode=755,size=${rc_cgroupsize:-10m}"
-                       mount -n -t tmpfs -o ${opts} cgroup_root /sys/fs/cgroup
-                       eend $?
-               fi
+       grep -qw cgroup /proc/filesystems || return 0
+       if ! mountinfo -q /sys/fs/cgroup; then
+               ebegin "Mounting cgroup filesystem"
+               local opts="${sysfs_opts},mode=755,size=${rc_cgroupsize:-10m}"
+               mount -n -t tmpfs -o "${opts}" cgroup_root /sys/fs/cgroup
+               eend $?
        fi
 
-       mountinfo -q /sys/fs/cgroup || return 0
-
        if ! mountinfo -q /sys/fs/cgroup/openrc; then
                local agent="@LIBEXECDIR@/sh/cgroup-release-agent.sh"
                mkdir /sys/fs/cgroup/openrc
@@ -129,17 +125,87 @@ mount_cgroups()
                        openrc /sys/fs/cgroup/openrc
                printf 1 > /sys/fs/cgroup/openrc/notify_on_release
        fi
+       return 0
+}
 
-       yesno ${rc_controller_cgroups:-YES} && [ -e /proc/cgroups ] || return 0
-       while read name hier groups enabled rest; do
+cgroup1_controllers()
+{
+       yesno "${rc_controller_cgroups:-YES}" && [ -e /proc/cgroups ] || return 0
+       while read -r name _ _ enabled rest; do
                case "${enabled}" in
-                       1)      mountinfo -q /sys/fs/cgroup/${name} && continue
-                               mkdir /sys/fs/cgroup/${name}
-                               mount -n -t cgroup -o ${sysfs_opts},${name} \
-                                       ${name} /sys/fs/cgroup/${name}
+                       1)      mountinfo -q "/sys/fs/cgroup/${name}" && 
continue
+                               local x
+                               for x in $rc_cgroup_controllers; do
+                               [ "${name}" = "blkio" ] && [ "${x}" = "io" ] &&
+                                       continue 2
+                               [ "${name}" = "${x}" ] &&
+                               continue 2
+                               done
+                               mkdir "/sys/fs/cgroup/${name}"
+                               mount -n -t cgroup -o "${sysfs_opts},${name}" \
+                                       "${name}" "/sys/fs/cgroup/${name}"
                                ;;
                esac
        done < /proc/cgroups
+       return 0
+}
+
+cgroup2_controllers()
+{
+       local active cgroup_path x y
+       cgroup_path="$(cgroup2_find_path)"
+       [ -z "${cgroup_path}" ] && return 0
+       [ -e "${cgroup_path}/cgroup.controllers" ] &&
+       read -r active < "${cgroup_path}/cgroup.controllers"
+       for x in ${rc_cgroup_controllers}; do
+               for y in ${active}; do
+               [ "$x" = "$y" ] &&
+                       [ -e "${cgroup_path}/cgroup.subtree_control" ]&&
+                       echo "+${x}"  > "${cgroup_path}/cgroup.subtree_control"
+               done
+       done
+       return 0
+}
+
+cgroups_hybrid()
+{
+       grep -qw cgroup /proc/filesystems &&
+               grep -qw cgroup2 /proc/filesystems ||
+               return 0
+       cgroup1_base
+       mkdir /sys/fs/cgroup/unified
+       mount -t cgroup2 none -o "${sysfs_opts},nsdelegate" 
/sys/fs/cgroup/unified
+       cgroup2_controllers
+       cgroup1_controllers
+       return 0
+}
+
+cgroups_legacy()
+{
+       grep -qw cgroup /proc/filesystems || return 0
+       cgroup1_base
+       cgroup1_controllers
+       return 0
+}
+
+cgroups_unified()
+{
+       grep -qw cgroup2 /proc/filesystems || return 0
+       mount -t cgroup2 none -o "${sysfs_opts},nsdelegate" /sys/fs/cgroup
+       return 0
+}
+
+mount_cgroups()
+{
+       # set up kernel support for cgroups
+       if [ -d /sys/fs/cgroup ]; then
+               case "${rc_cgroup_mode:-hybrid}" in
+               hybrid) cgroups_hybrid ;;
+               legacy) cgroups_legacy ;;
+               unified) cgroups_unified ;;
+               esac
+       fi
+       return 0
 }
 
 restorecon_sys()

diff --git a/sh/openrc-run.sh.in b/sh/openrc-run.sh.in
index a38d46d6..e778bd09 100644
--- a/sh/openrc-run.sh.in
+++ b/sh/openrc-run.sh.in
@@ -258,8 +258,7 @@ for _cmd; do
                [ -n "${rc_ulimit:-$RC_ULIMIT}" ] && \
                        ulimit ${rc_ulimit:-$RC_ULIMIT}
                # Apply cgroups settings if defined
-               if [ "$(command -v cgroup_add_service)" = \
-                   "cgroup_add_service" ]
+               if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]
                then
                        if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then
                                eerror "No permission to apply cgroup settings"
@@ -268,9 +267,11 @@ for _cmd; do
                        cgroup_add_service /sys/fs/cgroup/openrc
                        cgroup_add_service /sys/fs/cgroup/systemd/system
                fi
-               [ "$(command -v cgroup_set_limits)" = \
-                   "cgroup_set_limits" ] && \
-                   cgroup_set_limits
+               [ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] &&
+                       cgroup_set_limits
+               [ "$(command -v cgroup2_set_limits)" = "cgroup2_set_limits" ] &&
+                       [ "$_cmd" = start ] &&
+                       cgroup2_set_limits
                break
        fi
 done
@@ -368,6 +369,10 @@ while [ -n "$1" ]; do
                                "$1" = "stop" ] && \
                                yesno "${rc_cgroup_cleanup}" && \
                                        cgroup_cleanup
+                               if [ "$(command -v cgroup2_remove)" = 
"cgroup2_remove" ]; then
+                                       [ "$1" = stop ] || [ -z "${command}" ] 
&&
+                                       cgroup2_remove
+                               fi
                                shift
                                continue 2
                        else

diff --git a/sh/rc-cgroup.sh.in b/sh/rc-cgroup.sh.in
index 5987f966..40501f22 100644
--- a/sh/rc-cgroup.sh.in
+++ b/sh/rc-cgroup.sh.in
@@ -152,3 +152,54 @@ cgroup_cleanup()
        kill -9 $pids
        eend $(cgroup_running && echo 1 || echo 0) "fail to stop all processes"
 }
+
+cgroup2_find_path()
+{
+       case "${rc_cgroup_mode:-hybrid}" in
+               hybrid) printf "/sys/fs/cgroup/unified" ;;
+               unified) printf "/sys/fs/cgroup" ;;
+               esac
+               return 0
+}
+
+cgroup2_remove()
+{
+       local cgroup_path="$(cgroup2_find_path)" rc_cgroup_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" &&
+               echo 0 > "${cgroup_path}/cgroup.procs"
+       local key populated vvalue
+       while read 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="$(cgroup2_find_path)"
+       [ -z "${cgroup_path}" ] && return 0
+       rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
+       local OIFS="$IFS"
+       IFS="
+"
+       [ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
+       echo 0 > "${rc_cgroup_path}/cgroup.procs"
+       echo "${rc_cgroup_settings}" | while IFS="$OIFS" read key value; do
+               [ -z "${key}" ] || [ -z "${value}" ] && continue
+               [ ! -e "${rc_cgroup_path}/${key}" ] && continue
+               veinfo "${RC_SVCNAME}: cgroups: ${key} ${value}"
+               echo "${value}" > "${rc_cgroup_path}/${key}"
+       done
+       IFS="$OIFS"
+       return 0
+}

Reply via email to