[Devel] [PATCH vz9 24/27] vecalls: Introduce VZCTL_GET_CPU_STAT ioctl
Nikita Yushchenko
nikita.yushchenko at virtuozzo.com
Wed Oct 6 11:57:36 MSK 2021
From: Konstantin Khorenko <khorenko at virtuozzo.com>
This vzctl ioctl still used by vzstat utility and dispatcher/libvirt
statistics reporting.
>From one point of view almost all data can be get from cpu cgroup of a
Container (missing data can be exported additionally),
but statistics is gathered often and ioctl is faster and requires less
cpu power => let it be for now.
The current patch is based on following vz7 commits:
ecdce58b214c ("sched: Export per task_group statistics_work")
a58fb58bff1c ("Use ve init task's css instead of opening cgroup via vfs")
75fc174adc36 ("sched: Port cpustat related patches")
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
Reviewed-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
+++
sched: Uninline css_tg()
Compilation with custom config fails:
kernel/ve/ve.c: In function ‘ve_get_cpu_avenrun’:
kernel/ve/ve.c:1679:27: error: inlining failed in call to always_inline ‘css_tg’: function body not available
inline struct task_group *css_tg(struct cgroup_subsys_state *css);
^~~~~~
kernel/ve/ve.c:1690:7: note: called from here
tg = css_tg(css);
^~~~~~~~~~~
We may remove "inline" attribute, as compiler is clever enough
to make itself inlining in kernel/sched/sched.c.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
Reviewed-by: Evgenii Shatokhin <eshatokhin at virtuozzo.com>
(cherry-picked from vz8 commit e5e88546c0ab ("vecalls: Introduce
VZCTL_GET_CPU_STAT ioctl"))
Signed-off-by: Nikita Yushchenko <nikita.yushchenko at virtuozzo.com>
---
include/linux/ve.h | 2 ++
kernel/time/time.c | 1 +
kernel/ve/ve.c | 18 +++++++++++++
kernel/ve/vecalls.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+)
diff --git a/include/linux/ve.h b/include/linux/ve.h
index e7b5be193442..c9e823f2c5c0 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -201,10 +201,12 @@ struct seq_file;
#if defined(CONFIG_VE) && defined(CONFIG_CGROUP_SCHED)
int ve_show_cpu_stat(struct ve_struct *ve, struct seq_file *p);
int ve_show_loadavg(struct ve_struct *ve, struct seq_file *p);
+int ve_get_cpu_avenrun(struct ve_struct *ve, unsigned long *avenrun);
int ve_get_cpu_stat(struct ve_struct *ve, struct kernel_cpustat *kstat);
#else
static inline int ve_show_cpu_stat(struct ve_struct *ve, struct seq_file *p) { return -ENOSYS; }
static inline int ve_show_loadavg(struct ve_struct *ve, struct seq_file *p) { return -ENOSYS; }
+static inline int ve_get_cpu_avenrun(struct ve_struct *ve, unsigned long *avenrun) { return -ENOSYS; }
static inline int ve_get_cpu_stat(struct ve_struct *ve, struct kernel_cpustat *kstat) { return -ENOSYS; }
#endif
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 29923b20e0e4..f56853a94b5b 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -686,6 +686,7 @@ u64 nsec_to_clock_t(u64 x)
return div_u64(x * 9, (9ull * NSEC_PER_SEC + (USER_HZ / 2)) / USER_HZ);
#endif
}
+EXPORT_SYMBOL(nsec_to_clock_t);
u64 jiffies64_to_nsecs(u64 j)
{
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 105e4deae29b..47fbd6fd4d80 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -1492,6 +1492,24 @@ int ve_show_loadavg(struct ve_struct *ve, struct seq_file *p)
return err;
}
+struct task_group *css_tg(struct cgroup_subsys_state *css);
+int get_avenrun_tg(struct task_group *tg, unsigned long *loads,
+ unsigned long offset, int shift);
+
+int ve_get_cpu_avenrun(struct ve_struct *ve, unsigned long *avnrun)
+{
+ struct cgroup_subsys_state *css;
+ struct task_group *tg;
+ int err;
+
+ css = ve_get_init_css(ve, cpu_cgrp_id);
+ tg = css_tg(css);
+ err = get_avenrun_tg(tg, avnrun, 0, 0);
+ css_put(css);
+ return err;
+}
+EXPORT_SYMBOL(ve_get_cpu_avenrun);
+
int cpu_cgroup_get_stat(struct cgroup_subsys_state *cpu_css,
struct cgroup_subsys_state *cpuacct_css,
struct kernel_cpustat *kstat);
diff --git a/kernel/ve/vecalls.c b/kernel/ve/vecalls.c
index d4ae92505bc1..6bb9d477275d 100644
--- a/kernel/ve/vecalls.c
+++ b/kernel/ve/vecalls.c
@@ -24,6 +24,8 @@
#include <linux/seq_file.h>
#include <linux/rcupdate.h>
#include <linux/mount.h>
+#include <linux/jiffies.h>
+#include <linux/sched/loadavg.h>
#include <generated/utsrelease.h>
#include <linux/ve.h>
@@ -32,6 +34,62 @@
#include <linux/veowner.h>
#include <linux/device_cgroup.h>
+static int fill_cpu_stat(envid_t veid, struct vz_cpu_stat __user *buf)
+{
+ struct ve_struct *ve;
+ struct vz_cpu_stat *vstat;
+ int retval;
+ int i;
+ unsigned long tmp;
+ unsigned long avnrun[3];
+ struct kernel_cpustat kstat;
+
+ if (!ve_is_super(get_exec_env()) && (veid != get_exec_env()->veid))
+ return -EPERM;
+ ve = get_ve_by_id(veid);
+ if (!ve)
+ return -ESRCH;
+
+ retval = -ENOMEM;
+ vstat = kzalloc(sizeof(*vstat), GFP_KERNEL);
+ if (!vstat)
+ goto out_put_ve;
+
+ retval = ve_get_cpu_stat(ve, &kstat);
+ if (retval)
+ goto out_free;
+
+ retval = ve_get_cpu_avenrun(ve, avnrun);
+ if (retval)
+ goto out_free;
+
+ vstat->user_jif = (unsigned long)nsec_to_clock_t(
+ kstat.cpustat[CPUTIME_USER]);
+ vstat->nice_jif = (unsigned long)nsec_to_clock_t(
+ kstat.cpustat[CPUTIME_NICE]);
+ vstat->system_jif = (unsigned long)nsec_to_clock_t(
+ kstat.cpustat[CPUTIME_SYSTEM]);
+ vstat->idle_clk = kstat.cpustat[CPUTIME_IDLE];
+ vstat->uptime_clk = ve_get_uptime(ve);
+
+ vstat->uptime_jif = (unsigned long)jiffies_64_to_clock_t(
+ get_jiffies_64() - ve->start_jiffies);
+ for (i = 0; i < 3; i++) {
+ tmp = avnrun[i] + (FIXED_1/200);
+ vstat->avenrun[i].val_int = LOAD_INT(tmp);
+ vstat->avenrun[i].val_frac = LOAD_FRAC(tmp);
+ }
+
+ retval = 0;
+ if (copy_to_user(buf, vstat, sizeof(*vstat)))
+ retval = -EFAULT;
+out_free:
+ kfree(vstat);
+out_put_ve:
+ put_ve(ve);
+ return retval;
+}
+
/**********************************************************************
**********************************************************************
*
@@ -360,6 +418,14 @@ int vzcalls_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
err = -ENOTTY;
switch(cmd) {
+ case VZCTL_GET_CPU_STAT: {
+ struct vzctl_cpustatctl s;
+ err = -EFAULT;
+ if (copy_from_user(&s, (void __user *)arg, sizeof(s)))
+ break;
+ err = fill_cpu_stat(s.veid, s.cpustat);
+ }
+ break;
case VZCTL_VE_CONFIGURE:
err = ve_configure_ioctl((struct vzctl_ve_configure *)arg);
break;
--
2.30.2
More information about the Devel
mailing list