summaryrefslogtreecommitdiff
blob: 72bc9fe2281166861a4138e229be38a6998c229b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/sbin/runscript
#
# Control Groups Configuration Startup
#
# This script runs the cgconfigparser utility to parse and setup
# the control group filesystem. It uses ${CONFIG_FILE}
# and parses the configuration specified in there.
#
CGCONFIGPARSER="/usr/sbin/cgconfigparser"
CGROUP_FS="cgroup"
CONFIG_FILE=${CONFIG_FILE:-"/etc/cgroup/cgconfig.conf"}
MOUNTS_FILE="/proc/mounts"
RULES_FILE="/etc/cgroup/cgrules.conf"

# Support multiple mount points
MAX_INDEX=0
declare -a MOUNT_POINTS MOUNT_OPTIONS

move_all_to_init_class() {
	local i
	for i in $(seq 1 ${MAX_INDEX}); do
		cd ${MOUNT_POINTS[$i]}

		if grep -qw ${MOUNT_POINTS[$i]} ${MOUNTS_FILE}; then
			local directory
			for directory in $(find . -depth -type d); do
				if [[ ${directory} != "." ]]; then
					# cat fails with "Argument list too long" error
					sed -nu p < ${directory}/tasks > tasks
					rmdir ${directory}
				fi
			done
		else
			ewarn "Resource control filesystem not mounted"
		fi

		cd - >/dev/null
	done
}

parse_mounts() {
	local device mount_point fs_type options other
	while read device mount_point fs_type options other; do
		if grep -q ${device} <<< ${CGROUP_FS}; then
			let MAX_INDEX++
			MOUNT_POINTS[${MAX_INDEX}]=${mount_point}
			MOUNT_OPTIONS[${MAX_INDEX}]=${options}
		fi
	done < ${MOUNTS_FILE}
}

umount_fs() {
	local i
	for i in $(seq 1 ${MAX_INDEX}); do
		umount ${MOUNT_POINTS[$i]}
		rmdir ${MOUNT_POINTS[$i]}
	done
}

depend() {
	need local
}

start() {
	ebegin "Starting cgconfig service"

	# Mount filesystem and create cgroups
	if ! ${CGCONFIGPARSER} -l ${CONFIG_FILE} >/dev/null; then
		eend 1 "Failed to parse ${CONFIG_FILE}"
		return 1
	fi

	parse_mounts

	# Find default cgroup name in rules file
	local default_cgroup
	if [[ -f ${RULES_FILE} ]]; then
		local user controller
		read user controller default_cgroup <<< $(grep -m1 ^\* ${RULES_FILE})
		if [[ $default_cgroup == "*" ]]; then
			ewarn "${RULES_FILE} incorrect"
			ewarn "Overriding it"
			default_cgroup=
		fi
	fi
	# Use predefined name if none was found
	if [[ -z ${default_cgroup} ]]; then
		default_cgroup=sysdefault
	fi

	# Create a default cgroup for tasks to return back to
	local i
	for i in $(seq 1 ${MAX_INDEX}); do
		# Ignore if directory already exists
		mkdir -p ${MOUNT_POINTS[$i]}/${default_cgroup}
		find ${MOUNT_POINTS[$i]}/ -name tasks | xargs  chmod a+rw
		chmod go-w ${MOUNT_POINTS[$i]}/tasks

		# Special rule for cpusets
		if grep -qw cpuset <<< ${MOUNT_OPTIONS[$i]}; then
			cat ${MOUNT_POINTS[$i]}/cpuset.cpus > ${MOUNT_POINTS[$i]}/${default_cgroup}/cpuset.cpus
			cat ${MOUNT_POINTS[$i]}/cpuset.mems > ${MOUNT_POINTS[$i]}/${default_cgroup}/cpuset.mems
		fi

		# Classify everything to default cgroup
		local j
		for j in $(ps --no-headers -eL o tid); do
			echo $j > ${MOUNT_POINTS[$i]}/${default_cgroup}/tasks 2>/dev/null
		done
	done

	eend 0
}

stop() {
	ebegin "Stopping cgconfig service"
	parse_mounts
	move_all_to_init_class
	umount_fs
	eend 0
}