Skip to content

Commit 80a7821

Browse files
sameoSamuel Ortiz
authored and
Samuel Ortiz
committed
cgroup: Optionally add process and task to a subsystems subset
In some cases, one may want to add processes and task only to certain subsystems in a cgroup. For example, when a cgroup is created to only limit a given subsystem usage, but leaves all other subsystems unconstrained, there may be a need to move a process to only the contrained cgroup subsystem while leaving it in another cgroup for other subsystems. This commit makes the Control interface process and task addition functions variadic, in order to pass an optional list of subsystems that behave as s subsystems filter. Signed-off-by: Samuel Ortiz <samuel.e.ortiz@protonmail.com>
1 parent 4ff5113 commit 80a7821

File tree

3 files changed

+154
-17
lines changed

3 files changed

+154
-17
lines changed

cgroup.go

+39-11
Original file line numberDiff line numberDiff line change
@@ -150,22 +150,50 @@ func (c *cgroup) Subsystems() []Subsystem {
150150
return c.subsystems
151151
}
152152

153-
// Add moves the provided process into the new cgroup
154-
func (c *cgroup) Add(process Process) error {
155-
return c.add(process, cgroupProcs)
153+
func (c *cgroup) subsystemsFilter(subsystems ...Name) []Subsystem {
154+
if len(subsystems) == 0 {
155+
return c.subsystems
156+
}
157+
158+
var filteredSubsystems = []Subsystem{}
159+
for _, s := range c.subsystems {
160+
for _, f := range subsystems {
161+
if s.Name() == f {
162+
filteredSubsystems = append(filteredSubsystems, s)
163+
break
164+
}
165+
}
166+
}
167+
168+
return filteredSubsystems
156169
}
157170

158-
// AddProc moves the provided process id into the new cgroup
159-
func (c *cgroup) AddProc(pid uint64) error {
160-
return c.add(Process{Pid: int(pid)}, cgroupProcs)
171+
// Add moves the provided process into the new cgroup.
172+
// Without additional arguments, the process is added to all the cgroup subsystems.
173+
// When giving Add a list of subsystem names, the process is only added to those
174+
// subsystems, provided that they are active in the targeted cgroup.
175+
func (c *cgroup) Add(process Process, subsystems ...Name) error {
176+
return c.add(process, cgroupProcs, subsystems...)
161177
}
162178

163-
// AddTask moves the provided tasks (threads) into the new cgroup
164-
func (c *cgroup) AddTask(process Process) error {
165-
return c.add(process, cgroupTasks)
179+
// AddProc moves the provided process id into the new cgroup.
180+
// Without additional arguments, the process with the given id is added to all
181+
// the cgroup subsystems. When giving AddProc a list of subsystem names, the process
182+
// id is only added to those subsystems, provided that they are active in the targeted
183+
// cgroup.
184+
func (c *cgroup) AddProc(pid uint64, subsystems ...Name) error {
185+
return c.add(Process{Pid: int(pid)}, cgroupProcs, subsystems...)
166186
}
167187

168-
func (c *cgroup) add(process Process, pType procType) error {
188+
// AddTask moves the provided tasks (threads) into the new cgroup.
189+
// Without additional arguments, the task is added to all the cgroup subsystems.
190+
// When giving AddTask a list of subsystem names, the task is only added to those
191+
// subsystems, provided that they are active in the targeted cgroup.
192+
func (c *cgroup) AddTask(process Process, subsystems ...Name) error {
193+
return c.add(process, cgroupTasks, subsystems...)
194+
}
195+
196+
func (c *cgroup) add(process Process, pType procType, subsystems ...Name) error {
169197
if process.Pid <= 0 {
170198
return ErrInvalidPid
171199
}
@@ -174,7 +202,7 @@ func (c *cgroup) add(process Process, pType procType) error {
174202
if c.err != nil {
175203
return c.err
176204
}
177-
for _, s := range pathers(c.subsystems) {
205+
for _, s := range pathers(c.subsystemsFilter(subsystems...)) {
178206
p, err := c.path(s.Name())
179207
if err != nil {
180208
return err

cgroup_test.go

+99
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,63 @@ func TestAdd(t *testing.T) {
101101
}
102102
}
103103

104+
func TestAddFilteredSubsystems(t *testing.T) {
105+
mock, err := newMock()
106+
if err != nil {
107+
t.Fatal(err)
108+
}
109+
defer mock.delete()
110+
control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{})
111+
if err != nil {
112+
t.Error(err)
113+
return
114+
}
115+
116+
filteredSubsystems := []Name{"memory", "cpu"}
117+
if err := control.Add(Process{Pid: 1234}, filteredSubsystems...); err != nil {
118+
t.Error(err)
119+
return
120+
}
121+
122+
for _, s := range filteredSubsystems {
123+
if err := checkPid(mock, filepath.Join(string(s), "test"), 1234); err != nil {
124+
t.Error(err)
125+
return
126+
}
127+
}
128+
129+
if err := checkPid(mock, filepath.Join("devices", "test"), 1234); err == nil {
130+
t.Error("Pid should not be added to the devices subsystem")
131+
return
132+
}
133+
134+
bogusSubsystems := append(filteredSubsystems, "bogus")
135+
if err := control.Add(Process{Pid: 5678}, bogusSubsystems...); err != nil {
136+
t.Error(err)
137+
return
138+
}
139+
140+
for _, s := range filteredSubsystems {
141+
if err := checkPid(mock, filepath.Join(string(s), "test"), 5678); err != nil {
142+
t.Error(err)
143+
return
144+
}
145+
}
146+
147+
nilSubsystems := []Name{}
148+
if err := control.Add(Process{Pid: 9012}, nilSubsystems...); err != nil {
149+
t.Error(err)
150+
return
151+
}
152+
153+
for _, s := range Subsystems() {
154+
if err := checkPid(mock, filepath.Join(string(s), "test"), 9012); err != nil {
155+
t.Error(err)
156+
return
157+
}
158+
}
159+
}
160+
104161
func TestAddTask(t *testing.T) {
105162
mock, err := newMock()
106163
if err != nil {
@@ -124,6 +181,48 @@ func TestAddTask(t *testing.T) {
124181
}
125182
}
126183

184+
func TestAddTaskFilteredSubsystems(t *testing.T) {
185+
mock, err := newMock()
186+
if err != nil {
187+
t.Fatal(err)
188+
}
189+
defer mock.delete()
190+
control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{})
191+
if err != nil {
192+
t.Error(err)
193+
return
194+
}
195+
filteredSubsystems := []Name{"memory", "cpu"}
196+
if err := control.AddTask(Process{Pid: 1234}, filteredSubsystems...); err != nil {
197+
t.Error(err)
198+
return
199+
}
200+
for _, s := range filteredSubsystems {
201+
if err := checkTaskid(mock, filepath.Join(string(s), "test"), 1234); err != nil {
202+
t.Error(err)
203+
return
204+
}
205+
}
206+
207+
if err := checkTaskid(mock, filepath.Join("devices", "test"), 1234); err == nil {
208+
t.Error("Task should not be added to the devices subsystem")
209+
return
210+
}
211+
212+
bogusSubsystems := append(filteredSubsystems, "bogus")
213+
if err := control.AddTask(Process{Pid: 5678}, bogusSubsystems...); err != nil {
214+
t.Error(err)
215+
return
216+
}
217+
218+
for _, s := range filteredSubsystems {
219+
if err := checkTaskid(mock, filepath.Join(string(s), "test"), 5678); err != nil {
220+
t.Error(err)
221+
return
222+
}
223+
}
224+
}
225+
127226
func TestListPids(t *testing.T) {
128227
mock, err := newMock()
129228
if err != nil {

control.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,22 @@ type Task = Process
5454
type Cgroup interface {
5555
// New creates a new cgroup under the calling cgroup
5656
New(string, *specs.LinuxResources) (Cgroup, error)
57-
// Add adds a process to the cgroup (cgroup.procs)
58-
Add(Process) error
59-
// AddProc adds the process with the given id to the cgroup (cgroup.procs)
60-
AddProc(pid uint64) error
61-
// AddTask adds a process to the cgroup (tasks)
62-
AddTask(Process) error
57+
// Add adds a process to the cgroup (cgroup.procs). Without additional arguments,
58+
// the process is added to all the cgroup subsystems. When giving Add a list of
59+
// subsystem names, the process is only added to those subsystems, provided that
60+
// they are active in the targeted cgroup.
61+
Add(Process, ...Name) error
62+
// AddProc adds the process with the given id to the cgroup (cgroup.procs).
63+
// Without additional arguments, the process with the given id is added to all
64+
// the cgroup subsystems. When giving AddProc a list of subsystem names, the process
65+
// id is only added to those subsystems, provided that they are active in the targeted
66+
// cgroup.
67+
AddProc(uint64, ...Name) error
68+
// AddTask adds a process to the cgroup (tasks). Without additional arguments, the
69+
// task is added to all the cgroup subsystems. When giving AddTask a list of subsystem
70+
// names, the task is only added to those subsystems, provided that they are active in
71+
// the targeted cgroup.
72+
AddTask(Process, ...Name) error
6373
// Delete removes the cgroup as a whole
6474
Delete() error
6575
// MoveTo moves all the processes under the calling cgroup to the provided one

0 commit comments

Comments
 (0)