Implement unified cgroup cpu limit (#5895)
* WiP unified cgroup support * add cpu usage support and disk iops support * memory limits * WIP working memory charts * detailed memory chart * docs change * cpu limit function * review changes
skrzyp1 committed
May 10, 2019 at 09:58 UTC
c82f4a1df3dd4f7997073d1c4dd7f92b9c39ce50
1 file changed
+61
-9
collectors/cgroups.plugin/sys_fs_cgroup.c
+61
-9
@@ -1699,7 +1699,8 @@ static inline void find_all_cgroups() {
1699
cg->cpuacct_stat.enabled = cgroup_enable_cpuacct_stat;
1700
cg->filename_cpuset_cpus = NULL;
1701
cg->filename_cpu_cfs_period = NULL;
1702
- cg->filename_cpu_cfs_quota = NULL;
1702
+ snprintfz(filename, FILENAME_MAX, "%s%s/cpu.max", cgroup_unified_base, cg->id);
1703
+ cg->filename_cpu_cfs_quota = strdupz(filename);
1704
debug(D_CGROUP, "cpu.stat filename for unified cgroup '%s': '%s'", cg->id, cg->cpuacct_stat.filename);
1705
}
1706
else
@@ -2612,6 +2613,47 @@ static inline void update_cpu_limits(char **filename, unsigned long long *value,
2613
}
2614
}
2615
2616
+static inline void update_cpu_limits2(struct cgroup *cg) {
2617
+ if(cg->filename_cpu_cfs_quota){
2618
+ static procfile *ff = NULL;
2619
+
2620
+ ff = procfile_reopen(ff, cg->filename_cpu_cfs_quota, NULL, PROCFILE_FLAG_DEFAULT);
2621
+ if(unlikely(!ff)) {
2622
+ goto cpu_limits2_err;
2623
+ }
2624
+
2625
+ ff = procfile_readall(ff);
2626
+ if(unlikely(!ff)) {
2627
+ goto cpu_limits2_err;
2628
+ }
2629
+
2630
+ unsigned long lines = procfile_lines(ff);
2631
+
2632
+ if (unlikely(lines < 1)) {
2633
+ error("CGROUP: file '%s' should have 1 lines.", cg->filename_cpu_cfs_quota);
2634
+ return;
2635
+ }
2636
+
2637
+ cg->cpu_cfs_period = str2ull(procfile_lineword(ff, 0, 1));
2638
+ cg->cpuset_cpus = get_system_cpus();
2639
+
2640
+ char *s = "max\n\0";
2641
+ if(strsame(s, procfile_lineword(ff, 0, 0)) == 0){
2642
+ cg->cpu_cfs_quota = cg->cpu_cfs_period * cg->cpuset_cpus;
2643
+ } else {
2644
+ cg->cpu_cfs_quota = str2ull(procfile_lineword(ff, 0, 0));
2645
+ }
2646
+ debug(D_CGROUP, "CPU limits values: %llu %llu %llu", cg->cpu_cfs_period, cg->cpuset_cpus, cg->cpu_cfs_quota);
2647
+ return;
2648
+
2649
+cpu_limits2_err:
2650
+ error("Cannot refresh cgroup %s cpu limit by reading '%s'. Will not update its limit anymore.", cg->id, cg->filename_cpu_cfs_quota);
2651
+ freez(cg->filename_cpu_cfs_quota);
2652
+ cg->filename_cpu_cfs_quota = NULL;
2653
+
2654
+ }
2655
+}
2656
+
2657
static inline int update_memory_limits(char **filename, RRDSETVAR **chart_var, unsigned long long *value, const char *chart_var_name, struct cgroup *cg) {
2658
if(*filename) {
2659
if(unlikely(!*chart_var)) {
@@ -2735,26 +2777,31 @@ void update_cgroup_charts(int update_every) {
2777
rrdset_done(cg->st_cpu);
2778
2779
if(likely(cg->filename_cpuset_cpus || cg->filename_cpu_cfs_period || cg->filename_cpu_cfs_quota)) {
2738
- update_cpu_limits(&cg->filename_cpuset_cpus, &cg->cpuset_cpus, cg);
2739
- update_cpu_limits(&cg->filename_cpu_cfs_period, &cg->cpu_cfs_period, cg);
2740
- update_cpu_limits(&cg->filename_cpu_cfs_quota, &cg->cpu_cfs_quota, cg);
2780
+ if(!(cg->options & CGROUP_OPTIONS_IS_UNIFIED)) {
2781
+ update_cpu_limits(&cg->filename_cpuset_cpus, &cg->cpuset_cpus, cg);
2782
+ update_cpu_limits(&cg->filename_cpu_cfs_period, &cg->cpu_cfs_period, cg);
2783
+ update_cpu_limits(&cg->filename_cpu_cfs_quota, &cg->cpu_cfs_quota, cg);
2784
+ } else {
2785
+ update_cpu_limits2(cg);
2786
+ }
2787
2788
if(unlikely(!cg->chart_var_cpu_limit)) {
2789
cg->chart_var_cpu_limit = rrdsetvar_custom_chart_variable_create(cg->st_cpu, "cpu_limit");
2790
if(!cg->chart_var_cpu_limit) {
2791
error("Cannot create cgroup %s chart variable 'cpu_limit'. Will not update its limit anymore.", cg->id);
2746
- freez(cg->filename_cpuset_cpus);
2792
+ if(cg->filename_cpuset_cpus) freez(cg->filename_cpuset_cpus);
2793
cg->filename_cpuset_cpus = NULL;
2748
- freez(cg->filename_cpu_cfs_period);
2794
+ if(cg->filename_cpu_cfs_period) freez(cg->filename_cpu_cfs_period);
2795
cg->filename_cpu_cfs_period = NULL;
2750
- freez(cg->filename_cpu_cfs_quota);
2796
+ if(cg->filename_cpu_cfs_quota) freez(cg->filename_cpu_cfs_quota);
2797
cg->filename_cpu_cfs_quota = NULL;
2798
}
2799
}
2800
else {
2801
calculated_number value = 0, quota = 0;
2802
2757
- if(likely(cg->filename_cpuset_cpus || (cg->filename_cpu_cfs_period && cg->filename_cpu_cfs_quota))) {
2803
+ if(likely( ((!(cg->options & CGROUP_OPTIONS_IS_UNIFIED)) && (cg->filename_cpuset_cpus || (cg->filename_cpu_cfs_period && cg->filename_cpu_cfs_quota)))
2804
+ || ((cg->options & CGROUP_OPTIONS_IS_UNIFIED) && cg->filename_cpu_cfs_quota))) {
2805
if(unlikely(cg->cpu_cfs_quota > 0))
2806
quota = (calculated_number)cg->cpu_cfs_quota / (calculated_number)cg->cpu_cfs_period;
2807
@@ -2789,7 +2836,12 @@ void update_cgroup_charts(int update_every) {
2836
else
2837
rrdset_next(cg->st_cpu_limit);
2838
2792
- calculated_number cpu_usage = (calculated_number)(cg->cpuacct_stat.user + cg->cpuacct_stat.system) * 100 / system_hz;
2839
+ calculated_number cpu_usage = 0;
2840
+ if(!(cg->options & CGROUP_OPTIONS_IS_UNIFIED))
2841
+ cpu_usage = (calculated_number)(cg->cpuacct_stat.user + cg->cpuacct_stat.system) * 100 / system_hz;
2842
+ else
2843
+ cpu_usage = (calculated_number)(cg->cpuacct_stat.user + cg->cpuacct_stat.system) * 100 / 1000000;
2844
+
2845
calculated_number cpu_used = 100 * (cpu_usage - cg->prev_cpu_usage) / (value * update_every);
2846
2847
rrdset_isnot_obsolete(cg->st_cpu_limit);