@cryptotaxi247 / netdata-1 / commits / c82f4a1df

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);