Skip to content

Commit 526fa26

Browse files
committed
Add memory policy support
Signed-off-by: Antti Kervinen <[email protected]>
1 parent 3c27840 commit 526fa26

File tree

6 files changed

+144
-2
lines changed

6 files changed

+144
-2
lines changed

cmd/oci-runtime-tool/generate.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
"github.com/opencontainers/runtime-tools/generate"
1717
"github.com/opencontainers/runtime-tools/generate/seccomp"
1818
"github.com/urfave/cli"
19+
20+
mpolCheck "github.com/opencontainers/runtime-tools/validate/memorypolicy"
1921
)
2022

2123
var generateFlags = []cli.Flag{
@@ -64,6 +66,9 @@ var generateFlags = []cli.Flag{
6466
cli.StringFlag{Name: "linux-mems", Usage: "list of memory nodes in the cpuset (default is to use any available memory node)"},
6567
cli.Uint64Flag{Name: "linux-mem-swap", Usage: "total memory limit (memory + swap) (in bytes)"},
6668
cli.Uint64Flag{Name: "linux-mem-swappiness", Usage: "how aggressive the kernel will swap memory pages (Range from 0 to 100)"},
69+
cli.StringFlag{Name: "linux-memorypolicy-mode", Usage: "memory policy defines from which nodes memory is allocated by default, e.g MPOL_INTERLEAVE"},
70+
cli.StringFlag{Name: "linux-memorypolicy-nodes", Usage: "memory nodes related to the linux-memorypolicy-mode, e.g 0-3,7"},
71+
cli.StringSliceFlag{Name: "linux-memorypolicy-flags", Usage: "optional memory policy mode flags, e.g MPOL_F_STATIC_NODES"},
6772
cli.StringFlag{Name: "linux-mount-label", Usage: "selinux mount context label"},
6873
cli.StringSliceFlag{Name: "linux-namespace-add", Usage: "adds a namespace to the set of namespaces to create or join of the form 'ns[:path]'"},
6974
cli.StringSliceFlag{Name: "linux-namespace-remove", Usage: "removes a namespace from the set of namespaces to create or join of the form 'ns'"},
@@ -782,6 +787,35 @@ func setupSpec(g *generate.Generator, context *cli.Context) error {
782787
g.SetLinuxResourcesMemorySwappiness(context.Uint64("linux-mem-swappiness"))
783788
}
784789

790+
if context.IsSet("linux-memorypolicy-mode") {
791+
mpolMode := context.String("linux-memorypolicy-mode")
792+
if err := mpolCheck.MpolModeValid(mpolMode); err != nil {
793+
return err
794+
}
795+
g.SetLinuxMemoryPolicyMode(mpolMode)
796+
}
797+
798+
if context.IsSet("linux-memorypolicy-nodes") {
799+
g.SetLinuxMemoryPolicyNodes(context.String("linux-memorypolicy-nodes"))
800+
}
801+
802+
if context.IsSet("linux-memorypolicy-flags") {
803+
mpolFlags := context.StringSlice("linux-memorypolicy-flags")
804+
for _, flag := range mpolFlags {
805+
if err := mpolCheck.MpolFlagValid(flag); err != nil {
806+
return err
807+
}
808+
}
809+
g.SetLinuxMemoryPolicyFlags(mpolFlags)
810+
}
811+
812+
if g.Config.Linux.MemoryPolicy != nil {
813+
// Validating memory policy nodes needs mode as a context.
814+
if err := mpolCheck.MpolModeNodesValid(g.Config.Linux.MemoryPolicy.Mode, g.Config.Linux.MemoryPolicy.Nodes); err != nil {
815+
return err
816+
}
817+
}
818+
785819
if context.IsSet("linux-network-classid") {
786820
g.SetLinuxResourcesNetworkClassID(uint32(context.Int("linux-network-classid")))
787821
}

generate/config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ func (g *Generator) initConfigLinuxResourcesMemory() {
109109
}
110110
}
111111

112+
func (g *Generator) initConfigLinuxMemoryPolicy() {
113+
g.initConfigLinux()
114+
if g.Config.Linux.MemoryPolicy == nil {
115+
g.Config.Linux.MemoryPolicy = &rspec.LinuxMemoryPolicy{}
116+
}
117+
}
118+
112119
func (g *Generator) initConfigLinuxResourcesNetwork() {
113120
g.initConfigLinuxResources()
114121
if g.Config.Linux.Resources.Network == nil {

generate/generate.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,26 @@ func (g *Generator) SetLinuxResourcesMemorySwappiness(swappiness uint64) {
932932
g.Config.Linux.Resources.Memory.Swappiness = &swappiness
933933
}
934934

935+
// SetLinuxMemoryPolicyMode sets g.Config.Linux.MemoryPolicy.Mode
936+
func (g *Generator) SetLinuxMemoryPolicyMode(mode string) {
937+
g.initConfigLinuxMemoryPolicy()
938+
g.Config.Linux.MemoryPolicy.Mode = rspec.MemoryPolicyModeType(mode)
939+
}
940+
941+
// SetLinuxMemoryPolicyNodes sets g.Config.Linux.MemoryPolicy.Nodes
942+
func (g *Generator) SetLinuxMemoryPolicyNodes(nodes string) {
943+
g.initConfigLinuxMemoryPolicy()
944+
g.Config.Linux.MemoryPolicy.Nodes = nodes
945+
}
946+
947+
// SetLinuxMemoryPolicyFlags sets g.Config.Linux.MemoryPolicy.Flags
948+
func (g *Generator) SetLinuxMemoryPolicyFlags(flags []string) {
949+
g.initConfigLinuxMemoryPolicy()
950+
for _, flag := range flags {
951+
g.Config.Linux.MemoryPolicy.Flags = append(g.Config.Linux.MemoryPolicy.Flags, rspec.MemoryPolicyFlagType(flag))
952+
}
953+
}
954+
935955
// SetLinuxResourcesMemoryDisableOOMKiller sets g.Config.Linux.Resources.Memory.DisableOOMKiller.
936956
func (g *Generator) SetLinuxResourcesMemoryDisableOOMKiller(disable bool) {
937957
g.initConfigLinuxResourcesMemory()

validate/memorypolicy/validate.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package memorypolicy
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
rspec "github.com/opencontainers/runtime-spec/specs-go"
8+
)
9+
10+
var (
11+
knownModes map[rspec.MemoryPolicyModeType]struct{} = map[rspec.MemoryPolicyModeType]struct{}{
12+
rspec.MpolDefault: {},
13+
rspec.MpolBind: {},
14+
rspec.MpolInterleave: {},
15+
rspec.MpolWeightedInterleave: {},
16+
rspec.MpolPreferred: {},
17+
rspec.MpolPreferredMany: {},
18+
rspec.MpolLocal: {},
19+
}
20+
21+
knownModeFlags map[rspec.MemoryPolicyFlagType]struct{} = map[rspec.MemoryPolicyFlagType]struct{}{
22+
rspec.MpolFNumaBalancing: {},
23+
rspec.MpolFRelativeNodes: {},
24+
rspec.MpolFStaticNodes: {},
25+
}
26+
)
27+
28+
// MpolModeValid checks if the provided memory policy mode is valid.
29+
func MpolModeValid(mode string) error {
30+
if !strings.HasPrefix(mode, "MPOL_") {
31+
return fmt.Errorf("memory policy mode %q must start with 'MPOL_'", mode)
32+
}
33+
if _, ok := knownModes[rspec.MemoryPolicyModeType(mode)]; !ok {
34+
return fmt.Errorf("invalid memory policy mode %q", mode)
35+
}
36+
return nil
37+
}
38+
39+
// MpolModeNodesValid checks if the nodes specification is valid for the given memory policy mode.
40+
func MpolModeNodesValid(mode rspec.MemoryPolicyModeType, nodes string) error {
41+
switch mode {
42+
case rspec.MpolDefault, rspec.MpolLocal:
43+
if nodes != "" {
44+
return fmt.Errorf("memory policy mode %q must not have nodes specified", mode)
45+
}
46+
case rspec.MpolBind, rspec.MpolInterleave, rspec.MpolWeightedInterleave, rspec.MpolPreferred, rspec.MpolPreferredMany:
47+
if nodes == "" {
48+
return fmt.Errorf("memory policy mode %q must have nodes specified", mode)
49+
}
50+
case "":
51+
return fmt.Errorf("memory policy mode must be specified")
52+
default:
53+
return fmt.Errorf("unknown memory policy mode %q ", mode)
54+
}
55+
return nil
56+
}
57+
58+
// MpolFlagValid checks if the provided memory policy flag is valid.
59+
func MpolFlagValid(flag string) error {
60+
if !strings.HasPrefix(flag, "MPOL_F_") {
61+
return fmt.Errorf("memory policy flag %q must start with 'MPOL_F_'", flag)
62+
}
63+
if _, ok := knownModeFlags[rspec.MemoryPolicyFlagType(flag)]; !ok {
64+
return fmt.Errorf("invalid memory policy flag %q", flag)
65+
}
66+
return nil
67+
}

validate/validate_linux.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
rspec "github.com/opencontainers/runtime-spec/specs-go"
1515
osFilepath "github.com/opencontainers/runtime-tools/filepath"
1616
"github.com/opencontainers/runtime-tools/specerror"
17+
mpolCheck "github.com/opencontainers/runtime-tools/validate/memorypolicy"
1718
"github.com/opencontainers/selinux/go-selinux/label"
1819
"github.com/sirupsen/logrus"
1920
)
@@ -220,5 +221,18 @@ func (v *Validator) CheckLinux() (errs error) {
220221
}
221222
}
222223

224+
if v.spec.Linux.MemoryPolicy != nil {
225+
if err := mpolCheck.MpolModeValid(string(v.spec.Linux.MemoryPolicy.Mode)); err != nil {
226+
errs = multierror.Append(errs, err)
227+
} else if err := mpolCheck.MpolModeNodesValid(v.spec.Linux.MemoryPolicy.Mode, v.spec.Linux.MemoryPolicy.Nodes); err != nil {
228+
errs = multierror.Append(errs, err)
229+
}
230+
for _, flag := range v.spec.Linux.MemoryPolicy.Flags {
231+
if err := mpolCheck.MpolFlagValid(string(flag)); err != nil {
232+
errs = multierror.Append(errs, err)
233+
}
234+
}
235+
}
236+
223237
return
224238
}

vendor/github.com/opencontainers/runtime-spec/specs-go/version.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)