libcontainer: intelrdt: use init() to avoid race condition

This is the follow-up PR of #1279 to fix remaining issues:

Use init() to avoid race condition in IsIntelRdtEnabled().
Add also rename some variables and functions.

Signed-off-by: Xiaochen Shen <xiaochen.shen@intel.com>
This commit is contained in:
Xiaochen Shen 2017-09-08 16:58:28 +08:00
parent deb9d7fd96
commit 88d22fde40
6 changed files with 25 additions and 26 deletions

View File

@ -159,7 +159,7 @@ func (v *ConfigValidator) sysctl(config *configs.Config) error {
func (v *ConfigValidator) intelrdt(config *configs.Config) error { func (v *ConfigValidator) intelrdt(config *configs.Config) error {
if config.IntelRdt != nil { if config.IntelRdt != nil {
if !intelrdt.IsIntelRdtEnabled() { if !intelrdt.IsEnabled() {
return fmt.Errorf("intelRdt is specified in config, but Intel RDT feature is not supported or enabled") return fmt.Errorf("intelRdt is specified in config, but Intel RDT feature is not supported or enabled")
} }
if config.IntelRdt.L3CacheSchema == "" { if config.IntelRdt.L3CacheSchema == "" {

View File

@ -160,7 +160,7 @@ func TestGetContainerStats(t *testing.T) {
if stats.CgroupStats.MemoryStats.Usage.Usage != 1024 { if stats.CgroupStats.MemoryStats.Usage.Usage != 1024 {
t.Fatalf("expected memory usage 1024 but recevied %d", stats.CgroupStats.MemoryStats.Usage.Usage) t.Fatalf("expected memory usage 1024 but recevied %d", stats.CgroupStats.MemoryStats.Usage.Usage)
} }
if intelrdt.IsIntelRdtEnabled() { if intelrdt.IsEnabled() {
if stats.IntelRdtStats == nil { if stats.IntelRdtStats == nil {
t.Fatal("intel rdt stats are nil") t.Fatal("intel rdt stats are nil")
} }
@ -231,7 +231,7 @@ func TestGetContainerState(t *testing.T) {
if memPath := paths["memory"]; memPath != expectedMemoryPath { if memPath := paths["memory"]; memPath != expectedMemoryPath {
t.Fatalf("expected memory path %q but received %q", expectedMemoryPath, memPath) t.Fatalf("expected memory path %q but received %q", expectedMemoryPath, memPath)
} }
if intelrdt.IsIntelRdtEnabled() { if intelrdt.IsEnabled() {
intelRdtPath := state.IntelRdtPath intelRdtPath := state.IntelRdtPath
if intelRdtPath == "" { if intelRdtPath == "" {
t.Fatal("intel rdt path should not be empty") t.Fatal("intel rdt path should not be empty")

View File

@ -204,7 +204,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
cgroupManager: l.NewCgroupsManager(config.Cgroups, nil), cgroupManager: l.NewCgroupsManager(config.Cgroups, nil),
} }
c.intelRdtManager = nil c.intelRdtManager = nil
if intelrdt.IsIntelRdtEnabled() && c.config.IntelRdt != nil { if intelrdt.IsEnabled() && c.config.IntelRdt != nil {
c.intelRdtManager = l.NewIntelRdtManager(config, id, "") c.intelRdtManager = l.NewIntelRdtManager(config, id, "")
} }
c.state = &stoppedState{c: c} c.state = &stoppedState{c: c}
@ -245,7 +245,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
return nil, err return nil, err
} }
c.intelRdtManager = nil c.intelRdtManager = nil
if intelrdt.IsIntelRdtEnabled() && c.config.IntelRdt != nil { if intelrdt.IsEnabled() && c.config.IntelRdt != nil {
c.intelRdtManager = l.NewIntelRdtManager(&state.Config, id, state.IntelRdtPath) c.intelRdtManager = l.NewIntelRdtManager(&state.Config, id, state.IntelRdtPath)
} }
return c, nil return c, nil

View File

@ -130,7 +130,7 @@ var (
intelRdtRootLock sync.Mutex intelRdtRootLock sync.Mutex
// The flag to indicate if Intel RDT is supported // The flag to indicate if Intel RDT is supported
isIntelRdtEnabled bool isEnabled bool
) )
type intelRdtData struct { type intelRdtData struct {
@ -139,6 +139,21 @@ type intelRdtData struct {
pid int pid int
} }
// Check if Intel RDT is enabled in init()
func init() {
// 1. Check if hardware and kernel support Intel RDT/CAT feature
// "cat_l3" flag is set if supported
isFlagSet, err := parseCpuInfoFile("/proc/cpuinfo")
if !isFlagSet || err != nil {
isEnabled = false
return
}
// 2. Check if Intel RDT "resource control" filesystem is mounted
// The user guarantees to mount the filesystem
isEnabled = isIntelRdtMounted()
}
// Return the mount point path of Intel RDT "resource control" filesysem // Return the mount point path of Intel RDT "resource control" filesysem
func findIntelRdtMountpointDir() (string, error) { func findIntelRdtMountpointDir() (string, error) {
f, err := os.Open("/proc/self/mountinfo") f, err := os.Open("/proc/self/mountinfo")
@ -369,24 +384,8 @@ func WriteIntelRdtTasks(dir string, pid int) error {
} }
// Check if Intel RDT is enabled // Check if Intel RDT is enabled
func IsIntelRdtEnabled() bool { func IsEnabled() bool {
// We have checked the flag before return isEnabled
if isIntelRdtEnabled {
return true
}
// 1. Check if hardware and kernel support Intel RDT/CAT feature
// "cat_l3" flag is set if supported
isFlagSet, err := parseCpuInfoFile("/proc/cpuinfo")
if !isFlagSet || err != nil {
isIntelRdtEnabled = false
return false
}
// 2. Check if Intel RDT "resource control" filesystem is mounted
// The user guarantees to mount the filesystem
isIntelRdtEnabled = isIntelRdtMounted()
return isIntelRdtEnabled
} }
// Get the 'container_id' path in Intel RDT "resource control" filesystem // Get the 'container_id' path in Intel RDT "resource control" filesystem

View File

@ -8,7 +8,7 @@ import (
) )
func TestIntelRdtSetL3CacheSchema(t *testing.T) { func TestIntelRdtSetL3CacheSchema(t *testing.T) {
if !IsIntelRdtEnabled() { if !IsEnabled() {
return return
} }

View File

@ -43,7 +43,7 @@ func loadFactory(context *cli.Context) (libcontainer.Factory, error) {
return nil, fmt.Errorf("systemd cgroup flag passed, but systemd support for managing cgroups is not available") return nil, fmt.Errorf("systemd cgroup flag passed, but systemd support for managing cgroups is not available")
} }
} }
if intelrdt.IsIntelRdtEnabled() { if intelrdt.IsEnabled() {
intelRdtManager := libcontainer.IntelRdtFs intelRdtManager := libcontainer.IntelRdtFs
return libcontainer.New(abs, cgroupManager, intelRdtManager, libcontainer.CriuPath(context.GlobalString("criu"))) return libcontainer.New(abs, cgroupManager, intelRdtManager, libcontainer.CriuPath(context.GlobalString("criu")))
} }