Skip to content

Commit fdf411e

Browse files
authored
Merge pull request #696 from odinuge/hugetlb-fix
Fix cgroup hugetlb size prefix for kB
2 parents 095789d + be9f6f1 commit fdf411e

File tree

3 files changed

+68
-52
lines changed

3 files changed

+68
-52
lines changed

cgroups/cgroups_v1.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ type CgroupV1 struct {
1818
MountPath string
1919
}
2020

21+
// HugePageSizeUnitList is a list of the units used by the linux kernel when
22+
// naming the HugePage control files.
23+
// https://www.kernel.org/doc/Documentation/cgroup-v1/hugetlb.txt
24+
var HugePageSizeUnitList = []string{"B", "KB", "MB", "GB", "TB", "PB"}
25+
2126
func getDeviceID(id string) (int64, int64, error) {
2227
elem := strings.Split(id, ":")
2328
major, err := strconv.ParseInt(elem[0], 10, 64)
@@ -393,9 +398,11 @@ func inBytes(size string) (int64, error) {
393398
return int64(byteSize), nil
394399
}
395400

396-
func getHugePageSize() ([]string, error) {
401+
// GetHugePageSize returns a list of the supported Hugepage sizes on the same format as
402+
// opencontainers/runtime-spec (see pageSize): https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#huge-page-limits
403+
// eg. ["64KB", "2MB", "1GB"]
404+
func GetHugePageSize() ([]string, error) {
397405
var pageSizes []string
398-
sizeList := []string{"B", "kB", "MB", "GB", "TB", "PB"}
399406
files, err := ioutil.ReadDir("/sys/kernel/mm/hugepages")
400407
if err != nil {
401408
return pageSizes, err
@@ -409,12 +416,12 @@ func getHugePageSize() ([]string, error) {
409416
size := float64(pageSize)
410417
base := float64(1024.0)
411418
i := 0
412-
unitsLimit := len(sizeList) - 1
419+
unitsLimit := len(HugePageSizeUnitList) - 1
413420
for size >= base && i < unitsLimit {
414421
size = size / base
415422
i++
416423
}
417-
sizeString := fmt.Sprintf("%g%s", size, sizeList[i])
424+
sizeString := fmt.Sprintf("%g%s", size, HugePageSizeUnitList[i])
418425
pageSizes = append(pageSizes, sizeString)
419426
}
420427

@@ -433,7 +440,7 @@ func (cg *CgroupV1) GetHugepageLimitData(pid int, cgPath string) ([]rspec.LinuxH
433440
}
434441
}
435442
lh := []rspec.LinuxHugepageLimit{}
436-
pageSizes, err := getHugePageSize()
443+
pageSizes, err := GetHugePageSize()
437444
if err != nil {
438445
return lh, err
439446
}

validation/linux_cgroups_hugetlb/linux_cgroups_hugetlb.go

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,24 @@ func testHugetlbCgroups() error {
1515
t.Header(0)
1616
defer t.AutoPlan()
1717

18-
// limit =~ 100 * page size
19-
// NOTE: on some systems, pagesize "1GB" doesn't seem to work.
20-
// Ideally we should auto-detect the value.
21-
cases := []struct {
22-
page string
23-
limit uint64
24-
}{
25-
{"2MB", 100 * 2 * 1024 * 1024},
26-
{"1GB", 100 * 1024 * 1024 * 1024},
27-
{"2MB", 100 * 2 * 1024 * 1024},
28-
{"1GB", 100 * 1024 * 1024 * 1024},
18+
pageSizes, err := cgroups.GetHugePageSize()
19+
20+
if err != nil {
21+
t.Fail(fmt.Sprintf("error when getting hugepage sizes: %+v", err))
2922
}
3023

31-
for _, c := range cases {
24+
// When setting the limit just for checking if writing works, the amount of memory
25+
// requested does not matter, as all insigned integers will be accepted.
26+
// Use 2GiB as an example
27+
const limit = 2 * (1 << 30)
28+
29+
for _, pageSize := range pageSizes {
3230
g, err := util.GetDefaultGenerator()
3331
if err != nil {
3432
return err
3533
}
3634
g.SetLinuxCgroupsPath(cgroups.AbsCgroupPath)
37-
g.AddLinuxResourcesHugepageLimit(c.page, c.limit)
35+
g.AddLinuxResourcesHugepageLimit(pageSize, limit)
3836
err = util.RuntimeOutsideValidate(g, t, func(config *rspec.Spec, t *tap.T, state *rspec.State) error {
3937
cg, err := cgroups.FindCgroup()
4038
if err != nil {
@@ -45,11 +43,11 @@ func testHugetlbCgroups() error {
4543
return err
4644
}
4745
for _, lhl := range lhd {
48-
if lhl.Pagesize != c.page {
46+
if lhl.Pagesize != pageSize {
4947
continue
5048
}
51-
t.Ok(lhl.Limit == c.limit, "hugepage limit is set correctly")
52-
t.Diagnosticf("expect: %d, actual: %d", c.limit, lhl.Limit)
49+
t.Ok(lhl.Limit == limit, fmt.Sprintf("hugepage limit is set correctly for size: %s", pageSize))
50+
t.Diagnosticf("expect: %d, actual: %d", limit, lhl.Limit)
5351
}
5452
return nil
5553
})
@@ -63,7 +61,8 @@ func testHugetlbCgroups() error {
6361

6462
func testWrongHugetlb() error {
6563
// We deliberately set the page size to a wrong value, "3MB", to see
66-
// if the container really returns an error.
64+
// if the container really returns an error. Page sizes will always be a
65+
// on the format 2^(integer)
6766
page := "3MB"
6867
var limit uint64 = 100 * 3 * 1024 * 1024
6968

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,65 @@
11
package main
22

33
import (
4+
"fmt"
45
"github.com/mndrix/tap-go"
56
rspec "github.com/opencontainers/runtime-spec/specs-go"
67
"github.com/opencontainers/runtime-tools/cgroups"
78
"github.com/opencontainers/runtime-tools/validation/util"
89
)
910

1011
func main() {
11-
page := "1GB"
12-
var limit uint64 = 56892210544640
13-
1412
t := tap.New()
1513
t.Header(0)
1614
defer t.AutoPlan()
1715

18-
g, err := util.GetDefaultGenerator()
16+
pageSizes, err := cgroups.GetHugePageSize()
17+
1918
if err != nil {
20-
util.Fatal(err)
19+
t.Fail(fmt.Sprintf("error when getting hugepage sizes: %+v", err))
2120
}
22-
g.SetLinuxCgroupsPath(cgroups.RelCgroupPath)
23-
g.AddLinuxResourcesHugepageLimit(page, limit)
24-
err = util.RuntimeOutsideValidate(g, t, func(config *rspec.Spec, t *tap.T, state *rspec.State) error {
25-
cg, err := cgroups.FindCgroup()
26-
t.Ok((err == nil), "find hugetlb cgroup")
27-
if err != nil {
28-
t.Diagnostic(err.Error())
29-
return nil
30-
}
21+
// When setting the limit just for checking if writing works, the amount of memory
22+
// requested does not matter, as all insigned integers will be accepted.
23+
// Use 2GiB as an example
24+
const limit = 2 * (1 << 30)
3125

32-
lhd, err := cg.GetHugepageLimitData(state.Pid, config.Linux.CgroupsPath)
33-
t.Ok((err == nil), "get hugetlb cgroup data")
26+
for _, pageSize := range pageSizes {
27+
g, err := util.GetDefaultGenerator()
3428
if err != nil {
35-
t.Diagnostic(err.Error())
36-
return nil
29+
util.Fatal(err)
3730
}
31+
g.SetLinuxCgroupsPath(cgroups.RelCgroupPath)
32+
g.AddLinuxResourcesHugepageLimit(pageSize, limit)
33+
err = util.RuntimeOutsideValidate(g, t, func(config *rspec.Spec, t *tap.T, state *rspec.State) error {
34+
cg, err := cgroups.FindCgroup()
35+
t.Ok((err == nil), "find hugetlb cgroup")
36+
if err != nil {
37+
t.Diagnostic(err.Error())
38+
return nil
39+
}
3840

39-
found := false
40-
for _, lhl := range lhd {
41-
if lhl.Pagesize == page {
42-
found = true
43-
t.Ok(lhl.Limit == limit, "hugepage limit is set correctly")
44-
t.Diagnosticf("expect: %d, actual: %d", limit, lhl.Limit)
41+
lhd, err := cg.GetHugepageLimitData(state.Pid, config.Linux.CgroupsPath)
42+
t.Ok((err == nil), "get hugetlb cgroup data")
43+
if err != nil {
44+
t.Diagnostic(err.Error())
45+
return nil
4546
}
46-
}
47-
t.Ok(found, "hugepage limit found")
4847

49-
return nil
50-
})
48+
found := false
49+
for _, lhl := range lhd {
50+
if lhl.Pagesize == pageSize {
51+
found = true
52+
t.Ok(lhl.Limit == limit, fmt.Sprintf("hugepage limit is set correctly for size: %s", pageSize))
53+
t.Diagnosticf("expect: %d, actual: %d", limit, lhl.Limit)
54+
}
55+
}
56+
t.Ok(found, "hugepage limit found")
5157

52-
if err != nil {
53-
t.Fail(err.Error())
58+
return nil
59+
})
60+
61+
if err != nil {
62+
t.Fail(err.Error())
63+
}
5464
}
5565
}

0 commit comments

Comments
 (0)