@@ -12,6 +12,8 @@ import (
1212 "strings"
1313 "sync"
1414
15+ "github.com/sirupsen/logrus"
16+
1517 "github.com/opencontainers/runc/libcontainer/configs"
1618)
1719
@@ -167,10 +169,17 @@ type IntelRdtManager struct {
167169 Config * configs.Config
168170 Id string
169171 Path string
172+ Type string
170173}
171174
172175const (
173- IntelRdtTasks = "tasks"
176+ IntelRdtTasks = "tasks"
177+ MonitoringGroupDirectoryName = "mon_groups"
178+
179+ // See "Resource alloc and monitor groups" part here:
180+ // https://www.kernel.org/doc/Documentation/x86/intel_rdt_ui.txt
181+ MonitoringGroupType = "MON"
182+ ControlGroupType = "CTRL_MON"
174183)
175184
176185var (
@@ -548,26 +557,47 @@ func GetIntelRdtPath(id string) (string, error) {
548557 return path , nil
549558}
550559
560+ // Get the 'container_id" path in Intel RDT "monitoring group" filesystem.
561+ func getMonGroupIntelRdtPath (id string ) (string , error ) {
562+ rootPath , err := getIntelRdtRoot ()
563+ if err != nil {
564+ return "" , err
565+ }
566+
567+ path := filepath .Join (rootPath , MonitoringGroupDirectoryName , id )
568+ return path , nil
569+ }
570+
551571// Applies Intel RDT configuration to the process with the specified pid
552572func (m * IntelRdtManager ) Apply (pid int ) (err error ) {
553- // If intelRdt is not specified in config, we do nothing
554- if m .Config .IntelRdt == nil {
573+ switch m .Type {
574+ case ControlGroupType :
575+ // If intelRdt is not specified in config, we do nothing
576+ if m .Config .IntelRdt == nil {
577+ return nil
578+ }
579+ rdtData , err := getIntelRdtData (m .Config , pid )
580+ if err != nil && ! IsNotFound (err ) {
581+ return err
582+ }
583+
584+ m .mu .Lock ()
585+ defer m .mu .Unlock ()
586+ path , err := rdtData .join (m .Id )
587+ if err != nil {
588+ return err
589+ }
590+
591+ m .Path = path
555592 return nil
556- }
557- d , err := getIntelRdtData (m .Config , pid )
558- if err != nil && ! IsNotFound (err ) {
559- return err
560- }
561593
562- m .mu .Lock ()
563- defer m .mu .Unlock ()
564- path , err := d .join (m .Id )
565- if err != nil {
566- return err
594+ case MonitoringGroupType :
595+ m .mu .Lock ()
596+ defer m .mu .Unlock ()
597+ return WriteIntelRdtTasks (m .Path , pid )
567598 }
568599
569- m .Path = path
570- return nil
600+ return fmt .Errorf ("couldn't recognize resctrl type: %v" , m .Type )
571601}
572602
573603// Destroys the Intel RDT 'container_id' group
@@ -584,94 +614,124 @@ func (m *IntelRdtManager) Destroy() error {
584614// Returns Intel RDT path to save in a state file and to be able to
585615// restore the object later
586616func (m * IntelRdtManager ) GetPath () string {
617+ var err error
587618 if m .Path == "" {
588- m .Path , _ = GetIntelRdtPath (m .Id )
619+ switch m .Type {
620+ case ControlGroupType :
621+ m .Path , err = GetIntelRdtPath (m .Id )
622+ if err != nil {
623+ logrus .Errorf ("couldn't obtain Resctrl control group path for manager with id %v: %v" , m .Id , err )
624+ }
625+ case MonitoringGroupType :
626+ flattedContainerID := strings .Replace (m .Id , "/" , "-" , - 1 )
627+ m .Path , err = getMonGroupIntelRdtPath (flattedContainerID )
628+ if err != nil {
629+ logrus .Errorf ("couldn't obtain Resctrl monitoring group path for manager with id %v: %v" , m .Id , err )
630+ }
631+ }
589632 }
590633 return m .Path
591634}
592635
593636// Returns statistics for Intel RDT
594637func (m * IntelRdtManager ) GetStats () (* Stats , error ) {
595- // If intelRdt is not specified in config
596- if m .Config .IntelRdt == nil {
597- return nil , nil
598- }
599-
600638 m .mu .Lock ()
601639 defer m .mu .Unlock ()
602640 stats := NewStats ()
603641
604- rootPath , err := getIntelRdtRoot ()
605- if err != nil {
606- return nil , err
607- }
608- // The read-only L3 cache and memory bandwidth schemata in root
609- tmpRootStrings , err := getIntelRdtParamString (rootPath , "schemata" )
610- if err != nil {
611- return nil , err
612- }
613- schemaRootStrings := strings .Split (tmpRootStrings , "\n " )
614-
615- // The L3 cache and memory bandwidth schemata in 'container_id' group
616- containerPath := m .GetPath ()
617- tmpStrings , err := getIntelRdtParamString (containerPath , "schemata" )
618- if err != nil {
619- return nil , err
620- }
621- schemaStrings := strings .Split (tmpStrings , "\n " )
642+ switch m .Type {
643+ case ControlGroupType :
644+ containerPath := m .GetPath ()
622645
623- if IsCatEnabled () {
624- // The read-only L3 cache information
625- l3CacheInfo , err := getL3CacheInfo ()
646+ err := getMonitoringStats (containerPath , stats )
626647 if err != nil {
627648 return nil , err
628649 }
629- stats .L3CacheInfo = l3CacheInfo
630650
631- // The read-only L3 cache schema in root
632- for _ , schemaRoot := range schemaRootStrings {
633- if strings . Contains ( schemaRoot , "L3" ) {
634- stats . L3CacheSchemaRoot = strings . TrimSpace ( schemaRoot )
651+ // If intelRdt is not specified in config
652+ if m . Config != nil {
653+ if m . Config . IntelRdt == nil {
654+ return nil , nil
635655 }
636- }
637656
638- // The L3 cache schema in 'container_id' group
639- for _ , schema := range schemaStrings {
640- if strings .Contains (schema , "L3" ) {
641- stats .L3CacheSchema = strings .TrimSpace (schema )
657+ rootPath , err := getIntelRdtRoot ()
658+ if err != nil {
659+ return nil , err
642660 }
643- }
644- }
661+ // The read-only L3 cache and memory bandwidth schemata in root
662+ tmpRootStrings , err := getIntelRdtParamString (rootPath , "schemata" )
663+ if err != nil {
664+ return nil , err
665+ }
666+ schemaRootStrings := strings .Split (tmpRootStrings , "\n " )
645667
646- if IsMbaEnabled () {
647- // The read-only memory bandwidth information
648- memBwInfo , err := getMemBwInfo ()
649- if err != nil {
650- return nil , err
651- }
652- stats .MemBwInfo = memBwInfo
668+ // The L3 cache and memory bandwidth schemata in 'container_id' group
653669
654- // The read-only memory bandwidth information
655- for _ , schemaRoot := range schemaRootStrings {
656- if strings .Contains (schemaRoot , "MB" ) {
657- stats .MemBwSchemaRoot = strings .TrimSpace (schemaRoot )
670+ tmpStrings , err := getIntelRdtParamString (containerPath , "schemata" )
671+ if err != nil {
672+ return nil , err
658673 }
659- }
674+ schemaStrings := strings .Split (tmpStrings , "\n " )
675+
676+ if IsCatEnabled () {
677+ // The read-only L3 cache information
678+ l3CacheInfo , err := getL3CacheInfo ()
679+ if err != nil {
680+ return nil , err
681+ }
682+ stats .L3CacheInfo = l3CacheInfo
660683
661- // The memory bandwidth schema in 'container_id' group
662- for _ , schema := range schemaStrings {
663- if strings .Contains (schema , "MB" ) {
664- stats .MemBwSchema = strings .TrimSpace (schema )
684+ // The read-only L3 cache schema in root
685+ for _ , schemaRoot := range schemaRootStrings {
686+ if strings .Contains (schemaRoot , "L3" ) {
687+ stats .L3CacheSchemaRoot = strings .TrimSpace (schemaRoot )
688+ }
689+ }
690+
691+ // The L3 cache schema in 'container_id' group
692+ for _ , schema := range schemaStrings {
693+ if strings .Contains (schema , "L3" ) {
694+ stats .L3CacheSchema = strings .TrimSpace (schema )
695+ }
696+ }
697+ }
698+
699+ if IsMbaEnabled () {
700+ // The read-only memory bandwidth information
701+ memBwInfo , err := getMemBwInfo ()
702+ if err != nil {
703+ return nil , err
704+ }
705+ stats .MemBwInfo = memBwInfo
706+
707+ // The read-only memory bandwidth information
708+ for _ , schemaRoot := range schemaRootStrings {
709+ if strings .Contains (schemaRoot , "MB" ) {
710+ stats .MemBwSchemaRoot = strings .TrimSpace (schemaRoot )
711+ }
712+ }
713+
714+ // The memory bandwidth schema in 'container_id' group
715+ for _ , schema := range schemaStrings {
716+ if strings .Contains (schema , "MB" ) {
717+ stats .MemBwSchema = strings .TrimSpace (schema )
718+ }
719+ }
665720 }
666721 }
667- }
668722
669- err = getMonitoringStats ( containerPath , stats )
670- if err != nil {
671- return nil , err
672- }
723+ return stats , nil
724+
725+ case MonitoringGroupType :
726+ path := m . GetPath ()
673727
674- return stats , nil
728+ err := getMonitoringStats (path , stats )
729+ if err != nil {
730+ return nil , err
731+ }
732+ return stats , nil
733+ }
734+ return nil , fmt .Errorf ("couldn't obtain stats from: %q resctrl manager of type: %q" , m .Id , m .Type )
675735}
676736
677737// Set Intel RDT "resource control" filesystem as configured.
@@ -721,34 +781,46 @@ func (m *IntelRdtManager) Set(container *configs.Config) error {
721781 // For example, on a two-socket machine, the schema line could be
722782 // "MB:0=5000;1=7000" which means 5000 MBps memory bandwidth limit on
723783 // socket 0 and 7000 MBps memory bandwidth limit on socket 1.
724- if container .IntelRdt != nil {
725- path := m .GetPath ()
726- l3CacheSchema := container .IntelRdt .L3CacheSchema
727- memBwSchema := container .IntelRdt .MemBwSchema
784+ switch m .Type {
785+ case ControlGroupType :
786+ if container .IntelRdt != nil {
787+ path := m .GetPath ()
788+ l3CacheSchema := container .IntelRdt .L3CacheSchema
789+ memBwSchema := container .IntelRdt .MemBwSchema
790+
791+ // Write a single joint schema string to schemata file
792+ if l3CacheSchema != "" && memBwSchema != "" {
793+ if err := writeFile (path , "schemata" , l3CacheSchema + "\n " + memBwSchema ); err != nil {
794+ return NewLastCmdError (err )
795+ }
796+ }
728797
729- // Write a single joint schema string to schemata file
730- if l3CacheSchema != "" && memBwSchema != "" {
731- if err := writeFile (path , "schemata" , l3CacheSchema + "\n " + memBwSchema ); err != nil {
732- return NewLastCmdError (err )
798+ // Write only L3 cache schema string to schemata file
799+ if l3CacheSchema != "" && memBwSchema == "" {
800+ if err := writeFile (path , "schemata" , l3CacheSchema ); err != nil {
801+ return NewLastCmdError (err )
802+ }
733803 }
734- }
735804
736- // Write only L3 cache schema string to schemata file
737- if l3CacheSchema != "" && memBwSchema == "" {
738- if err := writeFile (path , "schemata" , l3CacheSchema ); err != nil {
739- return NewLastCmdError (err )
805+ // Write only memory bandwidth schema string to schemata file
806+ if l3CacheSchema == "" && memBwSchema != "" {
807+ if err := writeFile (path , "schemata" , memBwSchema ); err != nil {
808+ return NewLastCmdError (err )
809+ }
740810 }
741811 }
742812
743- // Write only memory bandwidth schema string to schemata file
744- if l3CacheSchema == "" && memBwSchema != "" {
745- if err := writeFile (path , "schemata" , memBwSchema ); err != nil {
746- return NewLastCmdError (err )
747- }
813+ case MonitoringGroupType :
814+ if _ , err := os .Stat (m .GetPath ()); err == nil {
815+ return nil
816+ }
817+ if err := os .Mkdir (m .GetPath (), 0755 ); err != nil {
818+ return err
748819 }
820+ return nil
749821 }
750822
751- return nil
823+ return fmt . Errorf ( "couldn't set configuration for: %q resctrl manager of type: %q" , m . Id , m . Type )
752824}
753825
754826func (raw * intelRdtData ) join (id string ) (string , error ) {
0 commit comments