@@ -12,6 +12,8 @@ import (
12
12
"strings"
13
13
"sync"
14
14
15
+ "github.com/sirupsen/logrus"
16
+
15
17
"github.com/opencontainers/runc/libcontainer/configs"
16
18
)
17
19
@@ -167,10 +169,17 @@ type IntelRdtManager struct {
167
169
Config * configs.Config
168
170
Id string
169
171
Path string
172
+ Type string
170
173
}
171
174
172
175
const (
173
- IntelRdtTasks = "tasks"
176
+ IntelRdtTasks = "tasks"
177
+ MonitoringGroupDirectoryName = "mon_groups"
178
+
179
+ // See "Resource alloc and monitor groups" part in:
180
+ // https://www.kernel.org/doc/Documentation/x86/intel_rdt_ui.txt
181
+ MonitoringGroupType = "MON"
182
+ ControlGroupType = "CTRL_MON"
174
183
)
175
184
176
185
var (
@@ -548,26 +557,47 @@ func GetIntelRdtPath(id string) (string, error) {
548
557
return path , nil
549
558
}
550
559
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
+
551
571
// Applies Intel RDT configuration to the process with the specified pid
552
572
func (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
555
592
return nil
556
- }
557
- d , err := getIntelRdtData (m .Config , pid )
558
- if err != nil && ! IsNotFound (err ) {
559
- return err
560
- }
561
593
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 )
567
598
}
568
599
569
- m .Path = path
570
- return nil
600
+ return fmt .Errorf ("couldn't recognize resctrl type: %v" , m .Type )
571
601
}
572
602
573
603
// Destroys the Intel RDT 'container_id' group
@@ -584,94 +614,124 @@ func (m *IntelRdtManager) Destroy() error {
584
614
// Returns Intel RDT path to save in a state file and to be able to
585
615
// restore the object later
586
616
func (m * IntelRdtManager ) GetPath () string {
617
+ var err error
587
618
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
+ }
589
632
}
590
633
return m .Path
591
634
}
592
635
593
636
// Returns statistics for Intel RDT
594
637
func (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
-
600
638
m .mu .Lock ()
601
639
defer m .mu .Unlock ()
602
640
stats := NewStats ()
603
641
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 ()
622
645
623
- if IsCatEnabled () {
624
- // The read-only L3 cache information
625
- l3CacheInfo , err := getL3CacheInfo ()
646
+ err := getMonitoringStats (containerPath , stats )
626
647
if err != nil {
627
648
return nil , err
628
649
}
629
- stats .L3CacheInfo = l3CacheInfo
630
650
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
635
655
}
636
- }
637
656
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
642
660
}
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 " )
645
667
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
653
669
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
658
673
}
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
660
683
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
+ }
665
720
}
666
721
}
667
- }
668
722
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 ()
673
727
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 )
675
735
}
676
736
677
737
// Set Intel RDT "resource control" filesystem as configured.
@@ -721,34 +781,46 @@ func (m *IntelRdtManager) Set(container *configs.Config) error {
721
781
// For example, on a two-socket machine, the schema line could be
722
782
// "MB:0=5000;1=7000" which means 5000 MBps memory bandwidth limit on
723
783
// 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
+ }
728
797
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
+ }
733
803
}
734
- }
735
804
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
+ }
740
810
}
741
811
}
742
812
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
748
819
}
820
+ return nil
749
821
}
750
822
751
- return nil
823
+ return fmt . Errorf ( "couldn't set configuration for: %q resctrl manager of type: %q" , m . Id , m . Type )
752
824
}
753
825
754
826
func (raw * intelRdtData ) join (id string ) (string , error ) {
0 commit comments