|
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 |
| 47 | +) |
| 48 | + |
| 49 | +const ( |
| 50 | + // maxNumaNode is the maximum NUMA node number supported. |
| 51 | + // Must be large enough to cover what the kernel supports. |
| 52 | + maxNumaNode = 4095 |
44 | 53 | )
|
45 | 54 |
|
46 | 55 | func initMaps() {
|
@@ -148,6 +157,22 @@ func initMaps() {
|
148 | 157 | m.IDMapping.Recursive = true
|
149 | 158 | },
|
150 | 159 | }
|
| 160 | + |
| 161 | + mpolModeMap = map[specs.MemoryPolicyModeType]uint{ |
| 162 | + specs.MpolDefault: 0, |
| 163 | + specs.MpolPreferred: 1, |
| 164 | + specs.MpolBind: 2, |
| 165 | + specs.MpolInterleave: 3, |
| 166 | + specs.MpolLocal: 4, |
| 167 | + specs.MpolPreferredMany: 5, |
| 168 | + specs.MpolWeightedInterleave: 6, |
| 169 | + } |
| 170 | + |
| 171 | + mpolModeFMap = map[specs.MemoryPolicyFlagType]uint{ |
| 172 | + specs.MpolFStaticNodes: 1 << 15, |
| 173 | + specs.MpolFRelativeNodes: 1 << 14, |
| 174 | + specs.MpolFNumaBalancing: 1 << 13, |
| 175 | + } |
151 | 176 | })
|
152 | 177 | }
|
153 | 178 |
|
@@ -184,6 +209,30 @@ func KnownMountOptions() []string {
|
184 | 209 | return res
|
185 | 210 | }
|
186 | 211 |
|
| 212 | +// KnownMemoryPolicyModes returns the list of the known memory policy modes. |
| 213 | +// Used by `runc features`. |
| 214 | +func KnownMemoryPolicyModes() []string { |
| 215 | + initMaps() |
| 216 | + var res []string |
| 217 | + for k := range mpolModeMap { |
| 218 | + res = append(res, string(k)) |
| 219 | + } |
| 220 | + sort.Strings(res) |
| 221 | + return res |
| 222 | +} |
| 223 | + |
| 224 | +// KnownMemoryPolicyFlags returns the list of the known memory policy mode flags. |
| 225 | +// Used by `runc features`. |
| 226 | +func KnownMemoryPolicyFlags() []string { |
| 227 | + initMaps() |
| 228 | + var res []string |
| 229 | + for k := range mpolModeFMap { |
| 230 | + res = append(res, string(k)) |
| 231 | + } |
| 232 | + sort.Strings(res) |
| 233 | + return res |
| 234 | +} |
| 235 | + |
187 | 236 | // AllowedDevices is the set of devices which are automatically included for
|
188 | 237 | // all containers.
|
189 | 238 | //
|
@@ -467,6 +516,28 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) {
|
467 | 516 | MemBwSchema: spec.Linux.IntelRdt.MemBwSchema,
|
468 | 517 | }
|
469 | 518 | }
|
| 519 | + if !isEmptyMemoryPolicy(spec.Linux.MemoryPolicy) { |
| 520 | + var ok bool |
| 521 | + var err error |
| 522 | + specMp := spec.Linux.MemoryPolicy |
| 523 | + confMp := &configs.LinuxMemoryPolicy{} |
| 524 | + confMp.Mode, ok = mpolModeMap[specMp.Mode] |
| 525 | + if !ok { |
| 526 | + return nil, fmt.Errorf("invalid memory policy mode %q", specMp.Mode) |
| 527 | + } |
| 528 | + confMp.Nodes, err = parseListSet(specMp.Nodes, 0, maxNumaNode) |
| 529 | + if err != nil { |
| 530 | + return nil, fmt.Errorf("invalid memory policy nodes %q: %w", specMp.Nodes, err) |
| 531 | + } |
| 532 | + for _, specFlag := range specMp.Flags { |
| 533 | + confModeFlag, ok := mpolModeFMap[specFlag] |
| 534 | + if !ok { |
| 535 | + return nil, fmt.Errorf("invalid memory policy flag %q", specFlag) |
| 536 | + } |
| 537 | + confMp.Mode |= confModeFlag |
| 538 | + } |
| 539 | + config.MemoryPolicy = confMp |
| 540 | + } |
470 | 541 | if spec.Linux.Personality != nil {
|
471 | 542 | if len(spec.Linux.Personality.Flags) > 0 {
|
472 | 543 | logrus.Warnf("ignoring unsupported personality flags: %+v because personality flag has not supported at this time", spec.Linux.Personality.Flags)
|
@@ -1135,6 +1206,67 @@ func parseMountOptions(options []string) *configs.Mount {
|
1135 | 1206 | return &m
|
1136 | 1207 | }
|
1137 | 1208 |
|
| 1209 | +// parseListSet parses "list set" syntax ("0,61-63,2") into a list ([0, 61, 62, 63, 2]). |
| 1210 | +func parseListSet(listSet string, minValue, maxValue int) ([]int, error) { |
| 1211 | + var result []int |
| 1212 | + parts := strings.Split(listSet, ",") |
| 1213 | + for _, part := range parts { |
| 1214 | + switch { |
| 1215 | + case part == "": |
| 1216 | + continue |
| 1217 | + case strings.Contains(part, "-"): |
| 1218 | + rangeParts := strings.Split(part, "-") |
| 1219 | + if len(rangeParts) != 2 { |
| 1220 | + return nil, fmt.Errorf("invalid range: %s", part) |
| 1221 | + } |
| 1222 | + start, err := strconv.Atoi(rangeParts[0]) |
| 1223 | + if err != nil { |
| 1224 | + return nil, err |
| 1225 | + } |
| 1226 | + end, err := strconv.Atoi(rangeParts[1]) |
| 1227 | + if err != nil { |
| 1228 | + return nil, err |
| 1229 | + } |
| 1230 | + if start > end { |
| 1231 | + return nil, fmt.Errorf("invalid range %s: start > end", part) |
| 1232 | + } |
| 1233 | + if start < minValue || end > maxValue { |
| 1234 | + return nil, fmt.Errorf("invalid range %s: out of range %d-%d", part, minValue, maxValue) |
| 1235 | + } |
| 1236 | + for i := start; i <= end; i++ { |
| 1237 | + result = append(result, i) |
| 1238 | + } |
| 1239 | + default: |
| 1240 | + num, err := strconv.Atoi(part) |
| 1241 | + if err != nil { |
| 1242 | + return nil, err |
| 1243 | + } |
| 1244 | + if num < minValue || num > maxValue { |
| 1245 | + return nil, fmt.Errorf("invalid value %d: out of range %d-%d", num, minValue, maxValue) |
| 1246 | + } |
| 1247 | + result = append(result, num) |
| 1248 | + } |
| 1249 | + } |
| 1250 | + return result, nil |
| 1251 | +} |
| 1252 | + |
| 1253 | +// isEmptyMemoryPolicy checks if a LinuxMemoryPolicy is empty (nil or all zero values). |
| 1254 | +func isEmptyMemoryPolicy(mp *specs.LinuxMemoryPolicy) bool { |
| 1255 | + if mp == nil { |
| 1256 | + return true |
| 1257 | + } |
| 1258 | + if mp.Mode != "" { |
| 1259 | + return false |
| 1260 | + } |
| 1261 | + if mp.Nodes != "" { |
| 1262 | + return false |
| 1263 | + } |
| 1264 | + if len(mp.Flags) > 0 { |
| 1265 | + return false |
| 1266 | + } |
| 1267 | + return true |
| 1268 | +} |
| 1269 | + |
1138 | 1270 | func SetupSeccomp(config *specs.LinuxSeccomp) (*configs.Seccomp, error) {
|
1139 | 1271 | if config == nil {
|
1140 | 1272 | return nil, nil
|
|
0 commit comments