From 8f63a741975fdae535bb187a8cd7159e8b9655ce Mon Sep 17 00:00:00 2001 From: Mats Karrman Date: Fri, 15 Apr 2016 11:41:10 +0200 Subject: [PATCH] Added new package icgroupd, refs #2521 The icgroupd contains a simple shell script daemon and an procd enabled init script for configuring cgroups according to uci configuration and launching the daemon. The daemon will periodically look for new processes in the root cgroup and move them to sub-groups according to configuration. --- icgroupd/Makefile | 46 +++++++++++++++++ icgroupd/files/cgroupd | 76 ++++++++++++++++++++++++++++ icgroupd/files/cgroups.config | 48 ++++++++++++++++++ icgroupd/files/cgroups.init | 93 +++++++++++++++++++++++++++++++++++ 4 files changed, 263 insertions(+) create mode 100644 icgroupd/Makefile create mode 100755 icgroupd/files/cgroupd create mode 100644 icgroupd/files/cgroups.config create mode 100755 icgroupd/files/cgroups.init diff --git a/icgroupd/Makefile b/icgroupd/Makefile new file mode 100644 index 000000000..7692d2b4c --- /dev/null +++ b/icgroupd/Makefile @@ -0,0 +1,46 @@ +# +# Copyright (C) 2016 Inteno Broadband AB +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=icgroupd +PKG_VERSION:=1.0 +PKG_RELEASE:=0 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=Inteno Broadband AB + +include $(INCLUDE_DIR)/package.mk + +define Package/icgroupd + SECTION:=base + CATEGORY:=Base system + TITLE:=Inteno cgroup daemon + DEPENDS:=+uci +busybox +endef + +define Package/icgroupd/description + This package contains Intenos cgroup daemon and associated + configuration and startup scripts. +endef + +define Build/Compile + true +endef + +define Package/icgroupd/install + $(INSTALL_DIR) $(1)/sbin $(1)/etc/init.d $(1)/etc/config + + $(INSTALL_CONF) ./files/cgroups.config $(1)/etc/config/cgroups + $(INSTALL_BIN) ./files/cgroups.init $(1)/etc/init.d/cgroups + $(INSTALL_BIN) ./files/cgroupd $(1)/sbin/ +endef + +$(eval $(call BuildPackage,icgroupd)) + diff --git a/icgroupd/files/cgroupd b/icgroupd/files/cgroupd new file mode 100755 index 000000000..90da0e95d --- /dev/null +++ b/icgroupd/files/cgroupd @@ -0,0 +1,76 @@ +#!/bin/sh + +CGBASEDIR=$1 +CGCONFIG=$2 +[ -n "$CGBASEDIR" -a -n "$CGCONFIG" ] || exit 1 + +[ -r /lib/functions.sh ] || exit 1 +. /lib/functions.sh + +CGPROCMAP=/tmp/cgprocmap +CGPERIOD=3s + +DBGLOG=/tmp/cgroupd.log +DEBUG=0 + + +add_to_procmap () { + local name_grp=$1 + local name grp + + name=$(echo $name_grp |awk -F= '{print $1}') + grp=$(echo $name_grp |awk -F= '{print $2}') + + echo "($name) $grp" >> $CGPROCMAP +} + +# Read configuration file and create process:group look-up table +# in /tmp file +read_config () { + local enab + + config_load $CGCONFIG + + config_get enab cgroups enabled "1" + [ $enab -eq 0 ] && exit 1 + + config_get CGDEFGROUP cgroups defgroup "_undef_" + [ "$CGDEFGROUP" == "_undef_" ] && exit 1 + [ "$DEBUG" == "1" ] && echo "default $CGDEFGROUP" >> $DBGLOG + + echo -n '' > $CGPROCMAP + config_list_foreach procmap procmap add_to_procmap + [ "$DEBUG" == "1" ] && cat $CGPROCMAP >> $DBGLOG +} + +# Move all process except init from cgroup root to cgroups according +# to /tmp look-up table +move_wild_procs () { + local wild_procs=$(cat $CGBASEDIR/cgroup.procs) + local pid name grp + + for pid in $wild_procs; do + + [ $pid -eq 1 ] && continue + if [ -d /proc/$pid ]; then + + name=$(awk '{print $2}' /proc/$pid/stat) + grp=$(awk "\$1==\"$name\" {print \$2}" $CGPROCMAP) + + [ "$grp" == "." ] && continue + [ -n "$grp" ] || grp=$CGDEFGROUP + + [ "$DEBUG" == "1" ] && \ + echo "Moving proc $pid $name to $grp" >> $DBGLOG + echo $pid > $CGBASEDIR/$grp/cgroup.procs + fi + done +} + + +[ "$DEBUG" == "1" ] && echo "$0 started $(date)" >> $DBGLOG +read_config +while true; do + move_wild_procs + sleep $CGPERIOD +done diff --git a/icgroupd/files/cgroups.config b/icgroupd/files/cgroups.config new file mode 100644 index 000000000..e52a5beb0 --- /dev/null +++ b/icgroupd/files/cgroups.config @@ -0,0 +1,48 @@ +config cgroups cgroups + option enabled 1 + option defgroup iopsys/normal + +config cgroup _root_ + list option cpu.rt_runtime_us=50000 + list option memory.move_charge_at_immigrate=1 + +config cgroup iopsys + list option cpu.shares=4096 + list option cpu.rt_runtime_us=40000 + list option memory.limit_in_bytes=-1 + list option memory.move_charge_at_immigrate=1 + +config cgroup iopsys_normal + list option cpu.shares=1024 + list option cpu.rt_runtime_us=10000 + list option memory.limit_in_bytes=-1 + list option memory.move_charge_at_immigrate=1 + +config cgroup iopsys_high + list option cpu.shares=4096 + list option cpu.rt_runtime_us=30000 + list option memory.limit_in_bytes=-1 + list option memory.move_charge_at_immigrate=1 + +config cgroup 3prt + list option cpu.shares=1024 + list option cpu.rt_runtime_us=10000 + list option memory.limit_in_bytes=75M + list option memory.move_charge_at_immigrate=1 + +config cgroup 3prt_normal + list option cpu.shares=1024 + list option cpu.rt_runtime_us=2500 + list option memory.limit_in_bytes=75M + list option memory.move_charge_at_immigrate=1 + +config cgroup 3prt_high + list option cpu.shares=4096 + list option cpu.rt_runtime_us=7500 + list option memory.limit_in_bytes=75M + list option memory.move_charge_at_immigrate=1 + +config procmap procmap + list procmap kthreadd=. + list procmap minidlna=3prt/normal + diff --git a/icgroupd/files/cgroups.init b/icgroupd/files/cgroups.init new file mode 100755 index 000000000..7834e2b30 --- /dev/null +++ b/icgroupd/files/cgroups.init @@ -0,0 +1,93 @@ +#!/bin/sh /etc/rc.common + +START=01 +USE_PROCD=1 +PROCD_DEBUG=1 +NAME=cgroupd + +CGBASEDIR=/sys/fs/cgroup +CGCONFIG="cgroups" + +DBGLOG=/tmp/cginit.log +DEBUG=0 + + +cgroupinit_set_knob_value () { + local knob_val=$1 + local dir=$2 + local knob val + + knob=$(echo $knob_val |awk -F= '{print $1}') + val=$(echo $knob_val |awk -F= '{print $2}') + /bin/echo $val > $CGBASEDIR/$dir/$knob + [ "$DEBUG" == "1" ] && \ + echo "/bin/echo $val > $CGBASEDIR/$dir/$knob (ret=$?)" >> $DBGLOG +} + +cgroupinit_create_group () { + local cgrp=$1 + local dir + + [ "$DEBUG" == "1" ] && echo "Create group $cgrp:" >> $DBGLOG + if [ "$cgrp" == "_root_" ]; then + dir=. + else + dir=$(echo $cgrp |tr '_' '/') + + if [ ! -d $CGBASEDIR/$dir ]; then + mkdir $CGBASEDIR/$dir + [ "$DEBUG" == "1" ] && \ + echo "mkdir $CGBASEDIR/$dir (ret=$?)" >> $DBGLOG + fi + fi + + config_list_foreach $cgrp option cgroupinit_set_knob_value $dir +} + +cgroupinit_configure_cgroups () { + local enab defgrp + + [ "$DEBUG" == "1" ] && echo "$0 started $(date)" >> $DBGLOG + config_load $CGCONFIG + + config_get enab cgroups enabled "1" + [ $enab -eq 0 ] && return 1 + + config_get defgrp cgroups defgroup "_undef_" + [ "$defgrp" == "_undef_" ] && return 1 + + if ! grep -q " $CGBASEDIR cgroup " /proc/mounts; then + mount -t cgroup -o nodev,noexec,nosuid cgroup $CGBASEDIR + [ $? -eq 0 ] || return 1 + fi + + config_foreach cgroupinit_create_group cgroup + return 0 +} + +start_service () { + cgroupinit_configure_cgroups + [ $? -eq 0 ] || return + + procd_open_instance + procd_set_param command /sbin/cgroupd $CGBASEDIR $CGCONFIG + procd_set_param respawn + procd_close_instance +} + +stop_service () { + local cgdir procs prc + + for cgdir in $(find $CGBASEDIR -type d -mindepth 1 -depth); do + procs=$(cat $cgdir/cgroup.procs) + for prc in $procs; do + echo $prc > $CGBASEDIR/cgroup.procs + done + rmdir $cgdir + done +} + +service_triggers() { + procd_add_reload_trigger $CGCONFIG +} +