Skip to content

Commit 30a7d9b

Browse files
authored
Merge pull request #4186 from kolyshkin/multi-line
libct/cg: write unified resources line by line
2 parents 30b7b63 + 7719036 commit 30a7d9b

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

libcontainer/cgroups/file.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,40 @@ func WriteFile(dir, file, data string) error {
5757
return nil
5858
}
5959

60+
// WriteFileByLine is the same as WriteFile, except if data contains newlines,
61+
// it is written line by line.
62+
func WriteFileByLine(dir, file, data string) error {
63+
i := strings.Index(data, "\n")
64+
if i == -1 {
65+
return WriteFile(dir, file, data)
66+
}
67+
68+
fd, err := OpenFile(dir, file, unix.O_WRONLY)
69+
if err != nil {
70+
return err
71+
}
72+
defer fd.Close()
73+
start := 0
74+
for {
75+
var line string
76+
if i == -1 {
77+
line = data[start:]
78+
} else {
79+
line = data[start : start+i+1]
80+
}
81+
_, err := fd.WriteString(line)
82+
if err != nil {
83+
return fmt.Errorf("failed to write %q: %w", line, err)
84+
}
85+
if i == -1 {
86+
break
87+
}
88+
start += i + 1
89+
i = strings.Index(data[start:], "\n")
90+
}
91+
return nil
92+
}
93+
6094
const (
6195
cgroupfsDir = "/sys/fs/cgroup"
6296
cgroupfsPrefix = cgroupfsDir + "/"

libcontainer/cgroups/file_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,25 @@ func TestOpenat2(t *testing.T) {
7373
fd.Close()
7474
}
7575
}
76+
77+
func BenchmarkWriteFile(b *testing.B) {
78+
TestMode = true
79+
defer func() { TestMode = false }()
80+
81+
dir := b.TempDir()
82+
tc := []string{
83+
"one",
84+
"one\ntwo\nthree",
85+
"10:200 foo=bar boo=far\n300:1200 something=other\ndefault 45000\n",
86+
"\n\n\n\n\n\n\n\n",
87+
}
88+
89+
b.ResetTimer()
90+
for i := 0; i < b.N; i++ {
91+
for _, val := range tc {
92+
if err := WriteFileByLine(dir, "file", val); err != nil {
93+
b.Fatal(err)
94+
}
95+
}
96+
}
97+
}

libcontainer/cgroups/fs2/fs2.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func (m *Manager) setUnified(res map[string]string) error {
238238
if strings.Contains(k, "/") {
239239
return fmt.Errorf("unified resource %q must be a file name (no slashes)", k)
240240
}
241-
if err := cgroups.WriteFile(m.dirPath, k, v); err != nil {
241+
if err := cgroups.WriteFileByLine(m.dirPath, k, v); err != nil {
242242
// Check for both EPERM and ENOENT since O_CREAT is used by WriteFile.
243243
if errors.Is(err, os.ErrPermission) || errors.Is(err, os.ErrNotExist) {
244244
// Check if a controller is available,

tests/integration/cgroups.bats

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,38 @@ function setup() {
187187
[[ "$weights" == *"$major:$minor 444"* ]]
188188
}
189189

190+
@test "runc run (per-device multiple iops via unified)" {
191+
requires root cgroups_v2
192+
193+
dd if=/dev/zero of=backing1.img bs=4096 count=1
194+
dev1=$(losetup --find --show backing1.img) || skip "unable to create a loop device"
195+
196+
# Second device.
197+
dd if=/dev/zero of=backing2.img bs=4096 count=1
198+
dev2=$(losetup --find --show backing2.img) || skip "unable to create a loop device"
199+
200+
set_cgroups_path
201+
202+
IFS=$' \t:' read -r major1 minor1 <<<"$(lsblk -nd -o MAJ:MIN "$dev1")"
203+
IFS=$' \t:' read -r major2 minor2 <<<"$(lsblk -nd -o MAJ:MIN "$dev2")"
204+
update_config ' .linux.devices += [
205+
{path: "'"$dev1"'", type: "b", major: '"$major1"', minor: '"$minor1"'},
206+
{path: "'"$dev2"'", type: "b", major: '"$major2"', minor: '"$minor2"'}
207+
]
208+
| .linux.resources.unified |=
209+
{"io.max": "'"$major1"':'"$minor1"' riops=333 wiops=444\n'"$major2"':'"$minor2"' riops=555 wiops=666\n"}'
210+
runc run -d --console-socket "$CONSOLE_SOCKET" test_dev_weight
211+
[ "$status" -eq 0 ]
212+
213+
# The loop devices are no longer needed.
214+
losetup -d "$dev1"
215+
losetup -d "$dev2"
216+
217+
weights=$(get_cgroup_value "io.max")
218+
grep "^$major1:$minor1 .* riops=333 wiops=444$" <<<"$weights"
219+
grep "^$major2:$minor2 .* riops=555 wiops=666$" <<<"$weights"
220+
}
221+
190222
@test "runc run (cpu.idle)" {
191223
requires cgroups_cpu_idle
192224
[ $EUID -ne 0 ] && requires rootless_cgroup

0 commit comments

Comments
 (0)