|
9 | 9 | "os" |
10 | 10 | "path/filepath" |
11 | 11 | "sort" |
| 12 | + "strconv" |
12 | 13 | "strings" |
13 | 14 | "sync" |
14 | 15 | "time" |
|
41 | 42 | flag int |
42 | 43 | } |
43 | 44 | complexFlags map[string]func(*configs.Mount) |
| 45 | + mpolModeMap map[specs.MemoryPolicyModeType]uint |
| 46 | + mpolModeFMap map[specs.MemoryPolicyFlagType]uint |
44 | 47 | ) |
45 | 48 |
|
46 | 49 | func initMaps() { |
@@ -148,6 +151,21 @@ func initMaps() { |
148 | 151 | m.IDMapping.Recursive = true |
149 | 152 | }, |
150 | 153 | } |
| 154 | + |
| 155 | + mpolModeMap = map[specs.MemoryPolicyModeType]uint{ |
| 156 | + specs.MpolDefault: 0, |
| 157 | + specs.MpolPreferred: 1, |
| 158 | + specs.MpolBind: 2, |
| 159 | + specs.MpolInterleave: 3, |
| 160 | + specs.MpolLocal: 4, |
| 161 | + specs.MpolWeightedInterleave: 6, |
| 162 | + } |
| 163 | + |
| 164 | + mpolModeFMap = map[specs.MemoryPolicyFlagType]uint{ |
| 165 | + specs.MpolFStaticNodes: 1 << 15, |
| 166 | + specs.MpolFRelativeNodes: 1 << 14, |
| 167 | + specs.MpolFNumaBalancing: 1 << 13, |
| 168 | + } |
151 | 169 | }) |
152 | 170 | } |
153 | 171 |
|
@@ -467,6 +485,32 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) { |
467 | 485 | MemBwSchema: spec.Linux.IntelRdt.MemBwSchema, |
468 | 486 | } |
469 | 487 | } |
| 488 | + if spec.Linux.MemoryPolicy != nil && |
| 489 | + (spec.Linux.MemoryPolicy.Mode != "" || |
| 490 | + spec.Linux.MemoryPolicy.Nodes != "" || |
| 491 | + len(spec.Linux.MemoryPolicy.Flags) > 0) { |
| 492 | + var ok bool |
| 493 | + specMp := spec.Linux.MemoryPolicy |
| 494 | + confMp := &configs.LinuxMemoryPolicy{} |
| 495 | + if confMp.Mode, ok = mpolModeMap[specMp.Mode]; !ok { |
| 496 | + return nil, fmt.Errorf("invalid memory policy mode %q", specMp.Mode) |
| 497 | + } |
| 498 | + // MAX_NODE is a sensibility check to user-provided |
| 499 | + // nodes, not reflecting currently onlined nodes. |
| 500 | + // set_mempolicy() accepts non-existent nodes. |
| 501 | + MAX_NODE := 1023 |
| 502 | + if confMp.Nodes, err = parseListSet(specMp.Nodes, 0, MAX_NODE); err != nil { |
| 503 | + return nil, fmt.Errorf("invalid memory policy nodes %q: %v", specMp.Nodes, err) |
| 504 | + } |
| 505 | + for _, specFlag := range specMp.Flags { |
| 506 | + confModeFlag, ok := mpolModeFMap[specFlag] |
| 507 | + if !ok { |
| 508 | + return nil, fmt.Errorf("invalid memory policy flag %q", specFlag) |
| 509 | + } |
| 510 | + confMp.Mode |= confModeFlag |
| 511 | + } |
| 512 | + config.MemoryPolicy = confMp |
| 513 | + } |
470 | 514 | if spec.Linux.Personality != nil { |
471 | 515 | if len(spec.Linux.Personality.Flags) > 0 { |
472 | 516 | logrus.Warnf("ignoring unsupported personality flags: %+v because personality flag has not supported at this time", spec.Linux.Personality.Flags) |
@@ -1127,6 +1171,53 @@ func parseMountOptions(options []string) *configs.Mount { |
1127 | 1171 | return &m |
1128 | 1172 | } |
1129 | 1173 |
|
| 1174 | +// parseListSet parses "list set" syntax ("0,61-63,2") into a list ([0, 61, 62, 63, 2]) |
| 1175 | +func parseListSet(listSet string, minValue, maxValue int) ([]int, error) { |
| 1176 | + var result []int |
| 1177 | + if listSet == "" { |
| 1178 | + return result, nil |
| 1179 | + } |
| 1180 | + parts := strings.Split(listSet, ",") |
| 1181 | + for _, part := range parts { |
| 1182 | + switch { |
| 1183 | + case part == "": |
| 1184 | + continue |
| 1185 | + case strings.Contains(part, "-"): |
| 1186 | + rangeParts := strings.Split(part, "-") |
| 1187 | + if len(rangeParts) != 2 { |
| 1188 | + return nil, fmt.Errorf("invalid range: %s", part) |
| 1189 | + } |
| 1190 | + start, err := strconv.Atoi(rangeParts[0]) |
| 1191 | + if err != nil { |
| 1192 | + return nil, err |
| 1193 | + } |
| 1194 | + end, err := strconv.Atoi(rangeParts[1]) |
| 1195 | + if err != nil { |
| 1196 | + return nil, err |
| 1197 | + } |
| 1198 | + if start > end { |
| 1199 | + return nil, fmt.Errorf("invalid range %s: start > end", part) |
| 1200 | + } |
| 1201 | + if start < minValue || end > maxValue { |
| 1202 | + return nil, fmt.Errorf("invalid range %s: not in %d-%d", part, minValue, maxValue) |
| 1203 | + } |
| 1204 | + for i := start; i <= end; i++ { |
| 1205 | + result = append(result, i) |
| 1206 | + } |
| 1207 | + default: |
| 1208 | + num, err := strconv.Atoi(part) |
| 1209 | + if err != nil { |
| 1210 | + return nil, err |
| 1211 | + } |
| 1212 | + if num < minValue || num > maxValue { |
| 1213 | + return nil, fmt.Errorf("invalid value %d: not in %d-%d", num, minValue, maxValue) |
| 1214 | + } |
| 1215 | + result = append(result, num) |
| 1216 | + } |
| 1217 | + } |
| 1218 | + return result, nil |
| 1219 | +} |
| 1220 | + |
1130 | 1221 | func SetupSeccomp(config *specs.LinuxSeccomp) (*configs.Seccomp, error) { |
1131 | 1222 | if config == nil { |
1132 | 1223 | return nil, nil |
|
0 commit comments