From 79d292b9ff79f71b8f561c0c3f1fb0fca875142d Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Mon, 26 Apr 2021 13:28:21 +0300 Subject: [PATCH] libcontainer/intelrdt: verify ClosID existence Check that the ClosID directory pre-exists if no L3 or MB schema has been specified. Conform with the following line from runtime-spec (config-linux): If closID is set, and neither of l3CacheSchema and memBwSchema are set, runtime MUST check if corresponding pre-configured directory closID is present in mounted resctrl. If such pre-configured directory closID exists, runtime MUST assign container to this closID and generate an error if directory does not exist. Add a TODO note for verifying existing schemata against L3/MB parameters. Signed-off-by: Markus Lehtonen --- libcontainer/intelrdt/intelrdt.go | 15 ++++++++++++- libcontainer/intelrdt/intelrdt_test.go | 31 ++++++++++++++++++++++++++ libcontainer/intelrdt/util_test.go | 4 ++-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/libcontainer/intelrdt/intelrdt.go b/libcontainer/intelrdt/intelrdt.go index 18d74f2b1..a12aca9b9 100644 --- a/libcontainer/intelrdt/intelrdt.go +++ b/libcontainer/intelrdt/intelrdt.go @@ -205,7 +205,6 @@ var ( ) type intelRdtData struct { - root string config *configs.Config } @@ -548,6 +547,14 @@ func (m *intelRdtManager) Apply(pid int) (err error) { m.mu.Lock() defer m.mu.Unlock() + if m.config.IntelRdt.ClosID != "" && m.config.IntelRdt.L3CacheSchema == "" && m.config.IntelRdt.MemBwSchema == "" { + // Check that the CLOS exists, i.e. it has been pre-configured to + // conform with the runtime spec + if _, err := os.Stat(path); err != nil { + return fmt.Errorf("clos dir not accessible (must be pre-created when l3CacheSchema and memBwSchema are empty): %w", err) + } + } + if err := os.MkdirAll(path, 0o755); err != nil { return newLastCmdError(err) } @@ -723,6 +730,12 @@ func (m *intelRdtManager) Set(container *configs.Config) error { l3CacheSchema := container.IntelRdt.L3CacheSchema memBwSchema := container.IntelRdt.MemBwSchema + // TODO: verify that l3CacheSchema and/or memBwSchema match the + // existing schemata if ClosID has been specified. This is a more + // involved than reading the file and doing plain string comparison as + // the value written in does not necessarily match what gets read out + // (leading zeros, cache id ordering etc). + // Write a single joint schema string to schemata file if l3CacheSchema != "" && memBwSchema != "" { if err := writeFile(path, "schemata", l3CacheSchema+"\n"+memBwSchema); err != nil { diff --git a/libcontainer/intelrdt/intelrdt_test.go b/libcontainer/intelrdt/intelrdt_test.go index 31df5186e..f1cff8f54 100644 --- a/libcontainer/intelrdt/intelrdt_test.go +++ b/libcontainer/intelrdt/intelrdt_test.go @@ -5,6 +5,8 @@ package intelrdt import ( "errors" "io" + "os" + "path/filepath" "strings" "testing" ) @@ -111,6 +113,35 @@ func TestIntelRdtSetMemBwScSchema(t *testing.T) { } } +func TestApply(t *testing.T) { + helper := NewIntelRdtTestUtil(t) + + const closID = "test-clos" + + helper.IntelRdtData.config.IntelRdt.ClosID = closID + intelrdt := NewManager(helper.IntelRdtData.config, "", helper.IntelRdtPath) + if err := intelrdt.Apply(1234); err == nil { + t.Fatal("unexpected success when applying pid") + } + if _, err := os.Stat(filepath.Join(helper.IntelRdtPath, closID)); err == nil { + t.Fatal("closid dir should not exist") + } + + // Dir should be created if some schema has been specified + intelrdt.(*intelRdtManager).config.IntelRdt.L3CacheSchema = "L3:0=f" + if err := intelrdt.Apply(1235); err != nil { + t.Fatalf("Apply() failed: %v", err) + } + + pids, err := getIntelRdtParamString(intelrdt.GetPath(), "tasks") + if err != nil { + t.Fatalf("failed to read tasks file: %v", err) + } + if pids != "1235" { + t.Fatalf("unexpected tasks file, expected '1235', got %q", pids) + } +} + const ( mountinfoValid = `18 40 0:18 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw 19 40 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw diff --git a/libcontainer/intelrdt/util_test.go b/libcontainer/intelrdt/util_test.go index ced12779f..a471c5e26 100644 --- a/libcontainer/intelrdt/util_test.go +++ b/libcontainer/intelrdt/util_test.go @@ -30,9 +30,9 @@ func NewIntelRdtTestUtil(t *testing.T) *intelRdtTestUtil { config: &configs.Config{ IntelRdt: &configs.IntelRdt{}, }, - root: t.TempDir(), } - testIntelRdtPath := filepath.Join(d.root, "resctrl") + intelRdtRoot = t.TempDir() + testIntelRdtPath := filepath.Join(intelRdtRoot, "resctrl") // Ensure the full mock Intel RDT "resource control" filesystem path exists if err := os.MkdirAll(testIntelRdtPath, 0o755); err != nil {