Skip to content

Commit 9ada639

Browse files
authored
Merge pull request #203 from sameo/topic/subsystem-filter
cgroup: Optionally add process and task to a subsystems subset
2 parents 4ff5113 + 80a7821 commit 9ada639

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)