-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Intel RDT: updates according to proposed spec changes. #3832
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -146,10 +146,11 @@ import ( | |
*/ | ||
|
||
type Manager struct { | ||
mu sync.Mutex | ||
config *configs.Config | ||
id string | ||
path string | ||
mu sync.Mutex | ||
config *configs.Config | ||
id string | ||
path string | ||
directoryCreated bool | ||
} | ||
|
||
// NewManager returns a new instance of Manager, or nil if the Intel RDT | ||
|
@@ -170,9 +171,10 @@ func NewManager(config *configs.Config, id string, path string) *Manager { | |
// is actually available. Used by unit tests that mock intelrdt paths. | ||
func newManager(config *configs.Config, id string, path string) *Manager { | ||
return &Manager{ | ||
config: config, | ||
id: id, | ||
path: path, | ||
config: config, | ||
id: id, | ||
path: path, | ||
directoryCreated: false, | ||
} | ||
} | ||
|
||
|
@@ -466,6 +468,14 @@ func (m *Manager) Apply(pid int) (err error) { | |
} | ||
} | ||
|
||
// If the directory doesn't exist we need to create it -> it means we also need | ||
// to clean it up afterwards. Make a note to the manager. | ||
if _, err := os.Stat(path); err != nil { | ||
if os.IsNotExist(err) { | ||
m.directoryCreated = true | ||
} | ||
} | ||
|
||
if err := os.MkdirAll(path, 0o755); err != nil { | ||
return newLastCmdError(err) | ||
} | ||
|
@@ -482,8 +492,9 @@ func (m *Manager) Apply(pid int) (err error) { | |
func (m *Manager) Destroy() error { | ||
// Don't remove resctrl group if closid has been explicitly specified. The | ||
// group is likely externally managed, i.e. by some other entity than us. | ||
// There are probably other containers/tasks sharing the same group. | ||
if m.config.IntelRdt != nil && m.config.IntelRdt.ClosID == "" { | ||
// There are probably other containers/tasks sharing the same group. Also | ||
// only remove the directory if it was created by us. | ||
if m.config.IntelRdt != nil && m.config.IntelRdt.ClosID == "" && m.directoryCreated { | ||
m.mu.Lock() | ||
defer m.mu.Unlock() | ||
if err := os.RemoveAll(m.GetPath()); err != nil { | ||
|
@@ -589,6 +600,28 @@ func (m *Manager) GetStats() (*Stats, error) { | |
return stats, nil | ||
} | ||
|
||
func combineSchemas(l3CacheSchema, memBwSchema string) string { | ||
// If both l3CacheSchema and memBwSchema are set and | ||
// l3CacheSchema contains a line beginning with "MB:", the | ||
// value written to schemata file MUST be the non-"MB:" | ||
// line(s) from l3CacheSchema and the line from memBWSchema. | ||
Comment on lines
+604
to
+607
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, can you elaborate on that requirement? In particular, why we allow a user to include My other question is -- what happens if we write both values as they are (i.e. without filtering)? Is this a security risk? Or is it just a convenience feature that allows There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One other thought. Let's say that we have
Does it make a difference for the kernel, if we write
or just
? (I mean, except the additional line parsing done in the kernel) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To answer your other question: I tried this out now and having two MB values for the same domain in the same
So we know that there is nobody trying to set overlapping |
||
|
||
validLines := make([]string, 0) | ||
|
||
// Split the l3CacheSchema to lines. | ||
lines := strings.Split(l3CacheSchema, "\n") | ||
|
||
// Remove the "MB:" lines. | ||
for _, line := range lines { | ||
if strings.HasPrefix(line, "MB:") { | ||
continue | ||
} | ||
validLines = append(validLines, line) | ||
} | ||
|
||
return strings.Join(validLines, "\n") + "\n" + memBwSchema | ||
Comment on lines
+604
to
+622
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not very efficient in terms of resources. We split the strings and then we combine them, creating two slices in the process. I'm not sure if there's a better solution (except than a slight optimization of reusing the same slice -- see https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating). |
||
} | ||
|
||
// Set Intel RDT "resource control" filesystem as configured. | ||
func (m *Manager) Set(container *configs.Config) error { | ||
// About L3 cache schema: | ||
|
@@ -649,7 +682,8 @@ func (m *Manager) Set(container *configs.Config) error { | |
|
||
// Write a single joint schema string to schemata file | ||
if l3CacheSchema != "" && memBwSchema != "" { | ||
if err := writeFile(path, "schemata", l3CacheSchema+"\n"+memBwSchema); err != nil { | ||
schemata := combineSchemas(l3CacheSchema, memBwSchema) | ||
if err := writeFile(path, "schemata", schemata); err != nil { | ||
return err | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not really about this PR, but this can benefit from
cgroups.RemovePath
, as here we only want to remove directories, not files.