[RHEL8,COMMIT] ve/vestat: Introduce /proc/vz/vestat

Submitted by Konstantin Khorenko on Nov. 3, 2020, 1:12 p.m.

Details

Message ID 202011031312.0A3DC0EJ2050659@finist-co8.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Konstantin Khorenko Nov. 3, 2020, 1:12 p.m.
The commit is pushed to "branch-rh8-4.18.0-193.6.3.vz8.4.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-193.6.3.vz8.4.15
------>
commit 9644a237d401cdf127046eda0f4d71107e341008
Author: Konstantin Khorenko <khorenko@virtuozzo.com>
Date:   Fri Oct 30 16:03:05 2020 +0300

    ve/vestat: Introduce /proc/vz/vestat
    
    The patch is based on following vz7 commits:
    
      f997bf6c613a ("ve: initial patch")
      75fc174adc36 ("sched: Port cpustat related patches")
      09e1cb4a7d4d ("ve/proc: restricted proc-entries scope")
      a58fb58bff1c ("Use ve init task's css instead of opening cgroup via vfs")
    
    Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
    Reviewed-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 kernel/ve/vecalls.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

Patch hide | download patch | download mbox

diff --git a/kernel/ve/vecalls.c b/kernel/ve/vecalls.c
index 78773c21b8db..3258b49b15b2 100644
--- a/kernel/ve/vecalls.c
+++ b/kernel/ve/vecalls.c
@@ -30,6 +30,11 @@ 
 #include <linux/veowner.h>
 #include <linux/device_cgroup.h>
 
+static u64 ve_get_uptime(struct ve_struct *ve)
+{
+	return ktime_get_boot_ns() - ve->real_start_time;
+}
+
 /**********************************************************************
  **********************************************************************
  *
@@ -38,6 +43,74 @@ 
  **********************************************************************
  **********************************************************************/
 #ifdef CONFIG_PROC_FS
+#if BITS_PER_LONG == 32
+#define VESTAT_LINE_WIDTH (6 * 11 + 6 * 21)
+#define VESTAT_LINE_FMT "%10s %10lu %10lu %10lu %10Lu %20Lu %20Lu %20Lu %20Lu %20Lu %20Lu %10lu\n"
+#define VESTAT_HEAD_FMT "%10s %10s %10s %10s %10s %20s %20s %20s %20s %20s %20s %10s\n"
+#else
+#define VESTAT_LINE_WIDTH (12 * 21)
+#define VESTAT_LINE_FMT "%20s %20lu %20lu %20lu %20Lu %20Lu %20Lu %20Lu %20Lu %20Lu %20Lu %20lu\n"
+#define VESTAT_HEAD_FMT "%20s %20s %20s %20s %20s %20s %20s %20s %20s %20s %20s %20s\n"
+#endif
+
+static int vestat_seq_show(struct seq_file *m, void *v)
+{
+	struct list_head *entry;
+	struct ve_struct *ve;
+	struct ve_struct *curve;
+	int ret;
+	unsigned long user_ve, nice_ve, system_ve;
+	unsigned long long uptime;
+	u64 uptime_cycles, idle_time, strv_time, used;
+	struct kernel_cpustat kstat;
+
+	entry = (struct list_head *)v;
+	ve = list_entry(entry, struct ve_struct, ve_list);
+
+	curve = get_exec_env();
+	if (entry == ve_list_head.next ||
+	    (!ve_is_super(curve) && ve == curve)) {
+		/* print header */
+		seq_printf(m, "%-*s\n",
+			   VESTAT_LINE_WIDTH - 1,
+			   "Version: 2.2");
+		seq_printf(m, VESTAT_HEAD_FMT, "VEID",
+			   "user", "nice", "system",
+			   "uptime", "idle",
+			   "strv", "uptime", "used",
+			   "maxlat", "totlat", "numsched");
+	}
+
+	if (ve == get_ve0())
+		return 0;
+
+	ret = ve_get_cpu_stat(ve, &kstat);
+	if (ret)
+		return ret;
+
+	strv_time	= 0;
+	user_ve		= nsecs_to_jiffies(kstat.cpustat[CPUTIME_USER]);
+	nice_ve		= nsecs_to_jiffies(kstat.cpustat[CPUTIME_NICE]);
+	system_ve	= nsecs_to_jiffies(kstat.cpustat[CPUTIME_SYSTEM]);
+	used		= kstat.cpustat[CPUTIME_USED];
+	idle_time	= kstat.cpustat[CPUTIME_IDLE];
+
+	uptime_cycles = ve_get_uptime(ve);
+	uptime = get_jiffies_64() - ve->start_jiffies;
+
+	seq_printf(m, VESTAT_LINE_FMT, ve_name(ve),
+		   user_ve, nice_ve, system_ve,
+		   (unsigned long long)uptime,
+		   (unsigned long long)idle_time,
+		   (unsigned long long)strv_time,
+		   (unsigned long long)uptime_cycles,
+		   (unsigned long long)used,
+		   (unsigned long long)ve->sched_lat_ve.last.maxlat,
+		   (unsigned long long)ve->sched_lat_ve.last.totlat,
+		   ve->sched_lat_ve.last.count);
+	return 0;
+}
+
 static void *ve_seq_start(struct seq_file *m, loff_t *pos)
 {
 	struct ve_struct *curve;
@@ -66,6 +139,25 @@  static void ve_seq_stop(struct seq_file *m, void *v)
 	mutex_unlock(&ve_list_lock);
 }
 
+static struct seq_operations vestat_seq_op = {
+	.start	= ve_seq_start,
+	.next	= ve_seq_next,
+	.stop	= ve_seq_stop,
+	.show	= vestat_seq_show
+};
+
+static int vestat_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &vestat_seq_op);
+}
+
+static struct file_operations proc_vestat_operations = {
+	.open	= vestat_open,
+	.read	= seq_read,
+	.llseek	= seq_lseek,
+	.release = seq_release
+};
+
 static int devperms_seq_show(struct seq_file *m, void *v)
 {
 	struct ve_struct *ve = list_entry(v, struct ve_struct, ve_list);
@@ -181,6 +273,11 @@  static int __init init_vecalls_proc(void)
 {
 	struct proc_dir_entry *de;
 
+	de = proc_create("vestat", S_IFREG | S_IRUSR | S_ISVTX, proc_vz_dir,
+			&proc_vestat_operations);
+	if (!de)
+		printk(KERN_WARNING "VZMON: can't make vestat proc entry\n");
+
 	de = proc_create("devperms", S_IFREG | S_IRUSR, proc_vz_dir,
 			&proc_devperms_ops);
 	if (!de)
@@ -203,6 +300,7 @@  static void __exit fini_vecalls_proc(void)
 {
 	remove_proc_entry("devperms", proc_vz_dir);
 	remove_proc_entry("version", proc_vz_dir);
+	remove_proc_entry("vestat", proc_vz_dir);
 	remove_proc_entry("veinfo", proc_vz_dir);
 }
 #else