From 656bf1893910dc0d4015b8ad44ca1aeba32bca60 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Wed, 28 Oct 2020 15:58:04 +0800 Subject: [PATCH 01/12] vcpu_stat: add remaining kvm exits items to display Add remaining kvm exits items to display, include: EXTerr, EXTukn, EXTcp153, EXTcp156, EXTcp14m, EXTcp14l, EXTcp146, EXTsmc, EXTsve, EXTdbg, EXTfail Set dafault width to 10 space, and set these items default hidden. Signed-off-by: Jiajun Chen <1250062498@qq.com> --- ...remaining-kvm-exits-items-to-display.patch | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 vcpu_stat-add-remaining-kvm-exits-items-to-display.patch diff --git a/vcpu_stat-add-remaining-kvm-exits-items-to-display.patch b/vcpu_stat-add-remaining-kvm-exits-items-to-display.patch new file mode 100644 index 0000000..30f6419 --- /dev/null +++ b/vcpu_stat-add-remaining-kvm-exits-items-to-display.patch @@ -0,0 +1,127 @@ +From d39ba9500c4fd87d0aec74e61ee7ec5936bb7f1b Mon Sep 17 00:00:00 2001 +From: Jiajun Chen <1250062498@qq.com> +Date: Wed, 28 Oct 2020 15:58:04 +0800 +Subject: [PATCH] vcpu_stat: add remaining kvm exits items to display + +Add remaining kvm exits items to display, include: +EXTerr, EXTukn, EXTcp153, EXTcp156, EXTcp14m, +EXTcp14l, EXTcp146, EXTsmc, EXTsve, EXTdbg, EXTfail + +Set dafault width to 10 space, and set these items default hidden. + +Signed-off-by: Jiajun Chen <1250062498@qq.com> +--- + src/field.c | 49 ++++++++++++++++++++++++++++++------------------- + src/field.h | 11 +++++++++++ + src/vmtop.c | 13 ++++++++++++- + 3 files changed, 53 insertions(+), 20 deletions(-) + +diff --git a/src/field.c b/src/field.c +index 1fc2fee..8793977 100644 +--- a/src/field.c ++++ b/src/field.c +@@ -38,25 +38,36 @@ FID fields[] = { + #define GDF(f) (void *)GET_DELTA_NAME(f) + #define GF(f) (void *)GET_NAME(f) + /* name . flag . align */ +- {"DID", FIELDS_DISPLAY, 5, NULL }, +- {"VM/task-name", FIELDS_DISPLAY, 14, NULL }, +- {"PID", FIELDS_DISPLAY, 8, NULL }, +- {"%CPU", FIELDS_DISPLAY, 8, NULL }, +- {"EXThvc", FIELDS_DISPLAY, 10, GDF(hvc_exit_stat) }, +- {"EXTwfe", FIELDS_DISPLAY, 10, GDF(wfe_exit_stat) }, +- {"EXTwfi", FIELDS_DISPLAY, 10, GDF(wfi_exit_stat) }, +- {"EXTmmioU", FIELDS_DISPLAY, 10, GDF(mmio_exit_user) }, +- {"EXTmmioK", FIELDS_DISPLAY, 10, GDF(mmio_exit_kernel) }, +- {"EXTfp", FIELDS_DISPLAY, 10, GDF(fp_asimd_exit_stat)}, +- {"EXTirq", FIELDS_DISPLAY, 10, GDF(irq_exit_stat) }, +- {"EXTsys64", FIELDS_DISPLAY, 10, GDF(sys64_exit_stat) }, +- {"EXTmabt", FIELDS_DISPLAY, 10, GDF(mabt_exit_stat) }, +- {"EXTsum", FIELDS_DISPLAY, 10, GDF(exits) }, +- {"S", FIELDS_DISPLAY, 5, GF(state) }, +- {"P", FIELDS_DISPLAY, 5, GF(processor) }, +- {"%ST", FIELDS_DISPLAY, 8, GDF(steal) }, +- {"%GUE", FIELDS_DISPLAY, 8, GDF(gtime) }, +- {"%HYP", FIELDS_DISPLAY, 8, NULL} ++ {"DID", FIELDS_DISPLAY, 5, NULL }, ++ {"VM/task-name", FIELDS_DISPLAY, 14, NULL }, ++ {"PID", FIELDS_DISPLAY, 8, NULL }, ++ {"%CPU", FIELDS_DISPLAY, 8, NULL }, ++ {"EXThvc", FIELDS_DISPLAY, 10, GDF(hvc_exit_stat) }, ++ {"EXTwfe", FIELDS_DISPLAY, 10, GDF(wfe_exit_stat) }, ++ {"EXTwfi", FIELDS_DISPLAY, 10, GDF(wfi_exit_stat) }, ++ {"EXTmmioU", FIELDS_DISPLAY, 10, GDF(mmio_exit_user) }, ++ {"EXTmmioK", FIELDS_DISPLAY, 10, GDF(mmio_exit_kernel) }, ++ {"EXTfp", FIELDS_DISPLAY, 10, GDF(fp_asimd_exit_stat) }, ++ {"EXTirq", FIELDS_DISPLAY, 10, GDF(irq_exit_stat) }, ++ {"EXTsys64", FIELDS_DISPLAY, 10, GDF(sys64_exit_stat) }, ++ {"EXTmabt", FIELDS_DISPLAY, 10, GDF(mabt_exit_stat) }, ++ {"EXTsum", FIELDS_DISPLAY, 10, GDF(exits) }, ++ {"EXTerr", FIELDS_HIDDEN, 10, GDF(internal_error_exit_stat)}, ++ {"EXTukn", FIELDS_HIDDEN, 10, GDF(unknown_ec_exit_stat) }, ++ {"EXTcp153", FIELDS_HIDDEN, 10, GDF(cp15_32_exit_stat) }, ++ {"EXTcp156", FIELDS_HIDDEN, 10, GDF(cp15_64_exit_stat) }, ++ {"EXT14m", FIELDS_HIDDEN, 10, GDF(cp14_mr_exit_stat) }, ++ {"EXT14l", FIELDS_HIDDEN, 10, GDF(cp14_ls_exit_stat) }, ++ {"EXT146", FIELDS_HIDDEN, 10, GDF(cp14_64_exit_stat) }, ++ {"EXTsmc", FIELDS_HIDDEN, 10, GDF(smc_exit_stat) }, ++ {"EXTsve", FIELDS_HIDDEN, 10, GDF(sve_exit_stat) }, ++ {"EXTdbg", FIELDS_HIDDEN, 10, GDF(debug_exit_stat) }, ++ {"EXTfail", FIELDS_HIDDEN, 10, GDF(fail_entry_exit_stat) }, ++ {"S", FIELDS_DISPLAY, 5, GF(state) }, ++ {"P", FIELDS_DISPLAY, 5, GF(processor) }, ++ {"%ST", FIELDS_DISPLAY, 8, GDF(steal) }, ++ {"%GUE", FIELDS_DISPLAY, 8, GDF(gtime) }, ++ {"%HYP", FIELDS_DISPLAY, 8, NULL } + #undef GDF + }; + +diff --git a/src/field.h b/src/field.h +index 88808e7..1fc7182 100644 +--- a/src/field.h ++++ b/src/field.h +@@ -31,6 +31,17 @@ enum fields_type { + FD_EXTSYS64, + FD_EXTMABT, + FD_EXTSUM, ++ FD_EXTERR, ++ FD_EXTUKN, ++ FD_EXTCP153, ++ FD_EXTCP156, ++ FD_EXTCP14M, ++ FD_EXTCP14L, ++ FD_EXTCP146, ++ FD_EXTSMC, ++ FD_EXTSVE, ++ FD_EXTDBG, ++ FD_EXTFAIL, + FD_STATE, + FD_P, + FD_ST, +diff --git a/src/vmtop.c b/src/vmtop.c +index 12b073d..d22ddfd 100644 +--- a/src/vmtop.c ++++ b/src/vmtop.c +@@ -195,7 +195,18 @@ static void print_domain_field(struct domain *dom, int field) + case FD_EXTIRQ: + case FD_EXTSYS64: + case FD_EXTMABT: +- case FD_EXTSUM: { ++ case FD_EXTSUM: ++ case FD_EXTERR: ++ case FD_EXTUKN: ++ case FD_EXTCP153: ++ case FD_EXTCP156: ++ case FD_EXTCP14M: ++ case FD_EXTCP14L: ++ case FD_EXTCP146: ++ case FD_EXTSMC: ++ case FD_EXTSVE: ++ case FD_EXTDBG: ++ case FD_EXTFAIL: { + print_scr("%*llu", fields[i].align, *(u64 *)(*fields[i].get_fun)(dom)); + break; + } +-- +2.27.0 + -- Gitee From 8f996d323a941e27ac706570dc2b605d912231cc Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Wed, 28 Oct 2020 16:38:12 +0800 Subject: [PATCH 02/12] display: modify filter display to support more display fields items If display fields items is more than screen rows, some of fields items can't be displayed in screen. So, start another col to show fields items if screen can't show all content in one col. Signed-off-by: Jiajun Chen <1250062498@qq.com> --- ...ilter-display-to-support-more-displa.patch | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 display-modify-filter-display-to-support-more-displa.patch diff --git a/display-modify-filter-display-to-support-more-displa.patch b/display-modify-filter-display-to-support-more-displa.patch new file mode 100644 index 0000000..eea72a7 --- /dev/null +++ b/display-modify-filter-display-to-support-more-displa.patch @@ -0,0 +1,49 @@ +From 3cf4573472785b697b1e7b103f0792f21e4b63a1 Mon Sep 17 00:00:00 2001 +From: Jiajun Chen <1250062498@qq.com> +Date: Wed, 28 Oct 2020 16:38:12 +0800 +Subject: [PATCH] display: modify filter display to support more display fields + items + +If display fields items is more than screen rows, some of fields items +can't be displayed in screen. +So, start another col to show fields items if screen can't show all content in one col. + +Signed-off-by: Jiajun Chen <1250062498@qq.com> +--- + src/vmtop.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/src/vmtop.c b/src/vmtop.c +index d22ddfd..db5c4e0 100644 +--- a/src/vmtop.c ++++ b/src/vmtop.c +@@ -298,11 +298,24 @@ static void show_domains(struct domain_list *list) + */ + static void print_field(int high_light) + { +- int x = 3; /* display x local */ +- int y = 4; /* display y local */ ++ int x, y, x_local, y_local; + unsigned int attr_flag; + ++ getyx(stdscr, y_local, x_local); /* get cursor coordinates */ ++ y = y_local; ++ x = x_local + 3; /* leave 3 spaces in the beginning for beauty */ ++ + for (int i = 0; i < FD_END; i++) { ++ /* ++ * if y local is more than scr_row_size, fields list display will ++ * out of screen range. So start another col to show fields list ++ * with 20 intervals. ++ */ ++ if (y >= scr_row_size) { ++ y = y_local; ++ x = x + 20; ++ } ++ + attr_flag = A_NORMAL; + if (i == high_light) { + attr_flag |= A_REVERSE; /* high light chosen field */ +-- +2.27.0 + -- Gitee From 0a71cf4c48ca4e2a58cf2b76ecb19c640ba8b8a7 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 29 Oct 2020 14:08:47 +0800 Subject: [PATCH 03/12] vcp_stat: add Max Scheduling Delay time items to display Add WAITmax item to display, which represent "Max Scheduling Delay". Set default width to 9 spaces, and default hidden. And WAITmax unit is ms. Signed-off-by: Jiajun Chen <1250062498@qq.com> --- ...-Scheduling-Delay-time-items-to-disp.patch | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 vcp_stat-add-Max-Scheduling-Delay-time-items-to-disp.patch diff --git a/vcp_stat-add-Max-Scheduling-Delay-time-items-to-disp.patch b/vcp_stat-add-Max-Scheduling-Delay-time-items-to-disp.patch new file mode 100644 index 0000000..d9b7d7c --- /dev/null +++ b/vcp_stat-add-Max-Scheduling-Delay-time-items-to-disp.patch @@ -0,0 +1,75 @@ +From 870b3c407d4b590ed38a4563ce5eb4e650c17e46 Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Thu, 29 Oct 2020 14:08:47 +0800 +Subject: [PATCH] vcp_stat: add Max Scheduling Delay time items to display + +Add WAITmax item to display, which represent "Max Scheduling Delay". +Set default width to 9 spaces, and default hidden. +And WAITmax unit is ms. + +Signed-off-by: Jiajun Chen <1250062498@qq.com> +--- + src/field.c | 4 +++- + src/field.h | 1 + + src/vcpu_stat.c | 1 + + src/vmtop.c | 6 ++++++ + 4 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/field.c b/src/field.c +index 8793977..7ff0d44 100644 +--- a/src/field.c ++++ b/src/field.c +@@ -67,8 +67,10 @@ FID fields[] = { + {"P", FIELDS_DISPLAY, 5, GF(processor) }, + {"%ST", FIELDS_DISPLAY, 8, GDF(steal) }, + {"%GUE", FIELDS_DISPLAY, 8, GDF(gtime) }, +- {"%HYP", FIELDS_DISPLAY, 8, NULL } ++ {"%HYP", FIELDS_DISPLAY, 8, NULL }, ++ {"WAITmax", FIELDS_HIDDEN, 9, GF(st_max) } + #undef GDF ++#undef GF + }; + + int get_show_field_num(void) +diff --git a/src/field.h b/src/field.h +index 1fc7182..3a33008 100644 +--- a/src/field.h ++++ b/src/field.h +@@ -47,6 +47,7 @@ enum fields_type { + FD_ST, + FD_GUE, + FD_HYP, ++ FD_WAITMAX, + FD_END + }; + +diff --git a/src/vcpu_stat.c b/src/vcpu_stat.c +index 7ec2371..308e7bb 100644 +--- a/src/vcpu_stat.c ++++ b/src/vcpu_stat.c +@@ -115,4 +115,5 @@ void sum_vcpu_stat(struct domain *dom, struct domain *thread) + (*vcpu_stat_stab[i].sum_fun)(dom, thread); + } + } ++ dom->st_max += thread->st_max; + } +diff --git a/src/vmtop.c b/src/vmtop.c +index db5c4e0..d9cfb9f 100644 +--- a/src/vmtop.c ++++ b/src/vmtop.c +@@ -234,6 +234,12 @@ static void print_domain_field(struct domain *dom, int field) + print_scr("%*.1f", fields[i].align, justify_usage(usage, dom)); + break; + } ++ case FD_WAITMAX: { ++ u64 st_max = *(u64 *)(*fields[i].get_fun)(dom); ++ /* show Max Scheduling Delay time in ms unit */ ++ print_scr("%*.3f", fields[i].align, st_max / 1000000.0f); ++ break; ++ } + default: + break; + } +-- +2.27.0 + -- Gitee From fd364be2df587d30acee0c11ad31d88fcb3b2ba1 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 29 Oct 2020 14:18:42 +0800 Subject: [PATCH 04/12] args: add -p option Add -p option to specify a virtual machine that vmtop monitors. Usage: vmtop -p vmid vmid means domain's id. Signed-off-by: Jiajun Chen <1250062498@qq.com> --- args-add-p-option.patch | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 args-add-p-option.patch diff --git a/args-add-p-option.patch b/args-add-p-option.patch new file mode 100644 index 0000000..7cc7e6e --- /dev/null +++ b/args-add-p-option.patch @@ -0,0 +1,84 @@ +From 6a68b5f025cffaa1b729f4ec7e5452628dacca82 Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Thu, 29 Oct 2020 14:18:42 +0800 +Subject: [PATCH] args: add -p option + +Add -p option to specify a virtual machine that vmtop monitors. +Usage: +vmtop -p vmid +vmid means domain's id. + +Signed-off-by: Jiajun Chen <1250062498@qq.com> +--- + src/domain.c | 5 +++++ + src/domain.h | 2 ++ + src/vmtop.c | 7 ++++++- + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/src/domain.c b/src/domain.c +index ac15d53..8683115 100644 +--- a/src/domain.c ++++ b/src/domain.c +@@ -25,6 +25,8 @@ + #define CGROUP_PATH_SIZE 30 + #define TASK_STRING_SIZE 30 + ++int monitor_id; ++ + /* domain list operation */ + void init_domains(struct domain_list *list) + { +@@ -231,6 +233,9 @@ static int set_domain(struct domain *dom, const char *name) + if (dom->domain_id < 0) { + return -1; + } ++ if (monitor_id >= 0 && dom->domain_id != monitor_id) { ++ return -1; ++ } + dom->type = ISDOMAIN; + if (get_proc_stat(dom) < 0 || get_child_pid(dom) < 0) { + return -1; +diff --git a/src/domain.h b/src/domain.h +index da3b20b..f4ce86b 100644 +--- a/src/domain.h ++++ b/src/domain.h +@@ -24,4 +24,6 @@ struct domain_list { + int refresh_domains(struct domain_list *now, struct domain_list *pre); + void init_domains(struct domain_list *list); + int get_task_num(struct domain_list *list); ++ ++extern int monitor_id; + #endif +diff --git a/src/vmtop.c b/src/vmtop.c +index d9cfb9f..fd3893b 100644 +--- a/src/vmtop.c ++++ b/src/vmtop.c +@@ -65,12 +65,13 @@ static void init_parameter(void) + delay_time = 1; /* default delay 1s between display */ + scr_row_size = 2048; /* defualt size row */ + scr_col_size = 1024; /* default size col */ ++ monitor_id = -1; /* default monitor all domains */ + } + + static void parse_args(int argc, char *argv[]) + { + int opt; +- char *arg_ops = "hvHd:n:b"; ++ char *arg_ops = "hvHd:n:bp:"; + while ((opt = getopt(argc, argv, arg_ops)) != -1) { + switch (opt) { + case 'd': { +@@ -103,6 +104,10 @@ static void parse_args(int argc, char *argv[]) + scr_mode = TEXT_MODE; + break; + } ++ case 'p': { ++ monitor_id = atoi(optarg); ++ break; ++ } + default: + exit(1); /* exit vmtop when args are invalid */ + break; +-- +2.27.0 + -- Gitee From 1fd6c72628c69deab39c7b9290126dd69ca152ad Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 29 Oct 2020 15:35:37 +0800 Subject: [PATCH 05/12] key: add page up/down key response Add page up/down key response, move pagesize - 6 for beauty. Signed-off-by: Jiajun Chen <1250062498@qq.com> --- key-add-page-up-down-key-response.patch | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 key-add-page-up-down-key-response.patch diff --git a/key-add-page-up-down-key-response.patch b/key-add-page-up-down-key-response.patch new file mode 100644 index 0000000..b07b154 --- /dev/null +++ b/key-add-page-up-down-key-response.patch @@ -0,0 +1,56 @@ +From f6fd0a0c71ac6b26ccfb12dc14df185a2ba0e45c Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Thu, 29 Oct 2020 15:35:37 +0800 +Subject: [PATCH] key: add page up/down key response + +Add page up/down key response, move pagesize - 6 for beauty. + +Signed-off-by: Jiajun Chen <1250062498@qq.com> +--- + src/vmtop.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/vmtop.c b/src/vmtop.c +index fd3893b..66485c9 100644 +--- a/src/vmtop.c ++++ b/src/vmtop.c +@@ -392,6 +392,8 @@ static void show_filter(void) + + static void parse_keys(int key) + { ++ int scroll_size = 1; ++ + switch (key) { + case 'f': { + show_filter(); +@@ -401,17 +403,25 @@ static void parse_keys(int key) + quit_flag = !quit_flag; + break; + } ++ case KEY_NPAGE: { ++ /* move pagesize - 6 for beauty */ ++ scroll_size = scr_row_size - 6; ++ } + case KEY_UP: { + int task_num = thread_mode ? get_task_num(&scr_cur) : scr_cur.num; + +- begin_task++; ++ begin_task += scroll_size; + if (begin_task > task_num) { + begin_task = task_num; + } + break; + } ++ case KEY_PPAGE: { ++ /* move pagesize - 6 for beauty */ ++ scroll_size = scr_row_size - 6; ++ } + case KEY_DOWN: { +- begin_task--; ++ begin_task -= scroll_size; + if (begin_task < 1) { + begin_task = 1; + } +-- +2.27.0 + -- Gitee From 4e7cdaa8156942907cd4ae702eb8c50ec73ab8eb Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Mon, 2 Nov 2020 11:36:19 +0800 Subject: [PATCH 06/12] vcpu_stat: get vcpu stat list once per display instead of per vcpu Currently, every time you get vcpu data for vcpu thread, you have to open vcpu_stat file, which is very time-consuming. If the number of vcpus is large, the display delay will be obvious. So, save vcpu stat list before every display, and get vcpu stat from list in data refreshing. And then. the vcpu_stat file will only be opened once in every display. Signed-off-by: nocjj <1250062498@qq.com> --- ...pu-stat-list-once-per-display-instea.patch | 277 ++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 vcpu_stat-get-vcpu-stat-list-once-per-display-instea.patch diff --git a/vcpu_stat-get-vcpu-stat-list-once-per-display-instea.patch b/vcpu_stat-get-vcpu-stat-list-once-per-display-instea.patch new file mode 100644 index 0000000..f47a57e --- /dev/null +++ b/vcpu_stat-get-vcpu-stat-list-once-per-display-instea.patch @@ -0,0 +1,277 @@ +From 926a9273ce0d2e7f07ee2b8b210966f5d6c8018f Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Mon, 2 Nov 2020 11:36:19 +0800 +Subject: [PATCH] vcpu_stat: get vcpu stat list once per display instead of per + vcpu + +Currently, every time you get vcpu data for vcpu thread, you have to open vcpu_stat file, +which is very time-consuming. If the number of vcpus is large, the display delay will be obvious. +So, save vcpu stat list before every display, and get vcpu stat from list in data refreshing. +And then. the vcpu_stat file will only be opened once in every display. + +Signed-off-by: nocjj <1250062498@qq.com> +--- + src/domain.c | 11 +++--- + src/domain.h | 9 ++--- + src/type.h | 6 ++++ + src/vcpu_stat.c | 91 ++++++++++++++++++++++++++++++++----------------- + src/vcpu_stat.h | 3 +- + src/vmtop.c | 1 + + 6 files changed, 78 insertions(+), 43 deletions(-) + +diff --git a/src/domain.c b/src/domain.c +index 8683115..05f85dd 100644 +--- a/src/domain.c ++++ b/src/domain.c +@@ -26,6 +26,7 @@ + #define TASK_STRING_SIZE 30 + + int monitor_id; ++struct domain_list vcpu_list; + + /* domain list operation */ + void init_domains(struct domain_list *list) +@@ -47,7 +48,7 @@ void clear_domains(struct domain_list *list) + init_domains(list); + } + +-static struct domain *add_domains(struct domain_list *list) ++struct domain *add_domains(struct domain_list *list) + { + struct domain *new_list = malloc(sizeof(struct domain) * (list->num + 1)); + +@@ -193,8 +194,8 @@ static int get_child_pid(struct domain *dom) + get_proc_comm(&(dom->threads[i])) < 0) { + continue; + } +- if (strstr(dom->threads[i].vmname, "CPU") != NULL +- && get_vcpu_stat(&(dom->threads[i])) > 0) { ++ if (strstr(dom->threads[i].vmname, "CPU") != NULL && ++ get_vcpu_stat(&(dom->threads[i]), &vcpu_list) >= 0) { + dom->threads[i].type = ISVCPU; + dom->smp_vcpus++; + } +@@ -305,8 +306,10 @@ int refresh_domains(struct domain_list *now, struct domain_list *pre) + + copy_domains(now, pre); /* save last data int pre */ + clear_domains(now); ++ if (get_vcpu_list(&vcpu_list) < 0) { ++ return -1; ++ } + num = get_qemu_id(now); +- + for (int i = 0; i < now->num; i++) { + int id = now->domains[i].domain_id; + struct domain *old_domain = get_domain_from_id(id, pre); +diff --git a/src/domain.h b/src/domain.h +index f4ce86b..1bb6116 100644 +--- a/src/domain.h ++++ b/src/domain.h +@@ -16,14 +16,11 @@ + #include + #include "type.h" + +-struct domain_list { +- struct domain *domains; +- int num; +-}; +- + int refresh_domains(struct domain_list *now, struct domain_list *pre); + void init_domains(struct domain_list *list); ++void clear_domains(struct domain_list *list); ++struct domain *add_domains(struct domain_list *list); + int get_task_num(struct domain_list *list); +- + extern int monitor_id; ++extern struct domain_list vcpu_list; + #endif +diff --git a/src/type.h b/src/type.h +index ac00b0d..40b7287 100644 +--- a/src/type.h ++++ b/src/type.h +@@ -19,6 +19,7 @@ typedef unsigned long long u64; + + #define DOMAIN_NAME_MAX 256 + #define BUF_SIZE 1024 ++#define MAX_VCPU_NUM 1024 + + #define DELTA_VALUE(v) delta_ ## v + #define DFX_VALUE(v) v, DELTA_VALUE(v) +@@ -145,6 +146,11 @@ struct domain { + int smp_vcpus; + }; + ++struct domain_list { ++ struct domain *domains; ++ int num; ++}; ++ + enum process_type { + ISDOMAIN, + ISVCPU, +diff --git a/src/vcpu_stat.c b/src/vcpu_stat.c +index 308e7bb..7009d41 100644 +--- a/src/vcpu_stat.c ++++ b/src/vcpu_stat.c +@@ -14,46 +14,47 @@ + #include + #include "type.h" + #include "vcpu_stat.h" ++#include "domain.h" + + #define KVM_VCPU_STAT_PATH "/sys/kernel/debug/kvm/vcpu_stat" + + struct file_item vcpu_stat_stab[] = { + #define GDF(f) (void *)GET_NAME(f), (void *)DELTA_NAME(f), (void *)SUM_NAME(f) + #define GF(f) (void *)GET_NAME(f), NULL, NULL +- {"%*u", NULL, NULL, NULL}, +- {"%llu", GDF(hvc_exit_stat)}, +- {"%llu", GDF(wfe_exit_stat)}, +- {"%llu", GDF(wfi_exit_stat)}, +- {"%llu", GDF(mmio_exit_user)}, +- {"%llu", GDF(mmio_exit_kernel)}, +- {"%llu", GDF(exits)}, +- {"%llu", GDF(fp_asimd_exit_stat)}, +- {"%llu", GDF(irq_exit_stat)}, +- {"%llu", GDF(sys64_exit_stat)}, +- {"%llu", GDF(mabt_exit_stat)}, +- {"%llu", GDF(fail_entry_exit_stat)}, ++ {"%u", GF(pid) }, ++ {"%llu", GDF(hvc_exit_stat) }, ++ {"%llu", GDF(wfe_exit_stat) }, ++ {"%llu", GDF(wfi_exit_stat) }, ++ {"%llu", GDF(mmio_exit_user) }, ++ {"%llu", GDF(mmio_exit_kernel) }, ++ {"%llu", GDF(exits) }, ++ {"%llu", GDF(fp_asimd_exit_stat) }, ++ {"%llu", GDF(irq_exit_stat) }, ++ {"%llu", GDF(sys64_exit_stat) }, ++ {"%llu", GDF(mabt_exit_stat) }, ++ {"%llu", GDF(fail_entry_exit_stat) }, + {"%llu", GDF(internal_error_exit_stat)}, +- {"%llu", GDF(unknown_ec_exit_stat)}, +- {"%llu", GDF(cp15_32_exit_stat)}, +- {"%llu", GDF(cp15_64_exit_stat)}, +- {"%llu", GDF(cp14_mr_exit_stat)}, +- {"%llu", GDF(cp14_ls_exit_stat)}, +- {"%llu", GDF(cp14_64_exit_stat)}, +- {"%llu", GDF(smc_exit_stat)}, +- {"%llu", GDF(sve_exit_stat)}, +- {"%llu", GDF(debug_exit_stat)}, +- {"%llu", GDF(steal)}, +- {"%llu", GF(st_max)}, +- {"%llu", GDF(vcpu_utime)}, +- {"%llu", GDF(vcpu_stime)}, +- {"%llu", GDF(gtime)} ++ {"%llu", GDF(unknown_ec_exit_stat) }, ++ {"%llu", GDF(cp15_32_exit_stat) }, ++ {"%llu", GDF(cp15_64_exit_stat) }, ++ {"%llu", GDF(cp14_mr_exit_stat) }, ++ {"%llu", GDF(cp14_ls_exit_stat) }, ++ {"%llu", GDF(cp14_64_exit_stat) }, ++ {"%llu", GDF(smc_exit_stat) }, ++ {"%llu", GDF(sve_exit_stat) }, ++ {"%llu", GDF(debug_exit_stat) }, ++ {"%llu", GDF(steal) }, ++ {"%llu", GF(st_max) }, ++ {"%llu", GDF(vcpu_utime) }, ++ {"%llu", GDF(vcpu_stime) }, ++ {"%llu", GDF(gtime) } + #undef GF + #undef GDF + }; + + const int vcpu_stat_size = sizeof(vcpu_stat_stab) / sizeof(struct file_item); + +-int get_vcpu_stat(struct domain *dom) ++int get_vcpu_list(struct domain_list *list) + { + char buf[BUF_SIZE]; + unsigned int pid; +@@ -63,16 +64,17 @@ int get_vcpu_stat(struct domain *dom) + if (!fp) { + return -1; + } ++ clear_domains(list); + while (fgets(buf, BUF_SIZE - 1, fp)) { + char *p = NULL; + char *p_next = NULL; + int i = 0; + +- /* judge whether vcpu pid is match */ +- sscanf(buf, "%u", &pid); +- if (pid != dom->pid) { +- continue; ++ /* limit vcpu nums to MAX_VCPU_NUM */ ++ if (list->num >= MAX_VCPU_NUM) { ++ break; + } ++ struct domain *dom = add_domains(list); + for (p = strtok_r(buf, " \t\r\n", &p_next); p && i < vcpu_stat_size; + p = strtok_r(NULL, " \t\r\n", &p_next)) { + if (vcpu_stat_stab[i].get_fun) { +@@ -81,9 +83,34 @@ int get_vcpu_stat(struct domain *dom) + } + i++; + } +- break; + } + fclose(fp); ++ return list->num; ++} ++ ++int get_vcpu_stat(struct domain *dom, struct domain_list *vcpu_list) ++{ ++ struct domain *vcpu = NULL; ++ int i; ++ ++ if (!dom || !vcpu_list) { ++ return -1; ++ } ++ for (i = 0; i < vcpu_list->num; i++) { ++ vcpu = &(vcpu_list->domains[i]); ++ if (vcpu->pid == dom->pid) { ++ break; ++ } ++ } ++ if (i >= vcpu_list->num) { ++ return 0; ++ } ++ for (i = 1; i < vcpu_stat_size; i++) { ++ if (vcpu_stat_stab[i].get_fun) { ++ memcpy((*vcpu_stat_stab[i].get_fun)(dom), ++ (*vcpu_stat_stab[i].get_fun)(vcpu), sizeof(u64)); ++ } ++ } + return 1; + } + +diff --git a/src/vcpu_stat.h b/src/vcpu_stat.h +index 6cb665a..edbef86 100644 +--- a/src/vcpu_stat.h ++++ b/src/vcpu_stat.h +@@ -42,7 +42,8 @@ GET_DELTA_FUN(vcpu_utime) + GET_DELTA_FUN(vcpu_stime) + GET_DELTA_FUN(gtime) + +-int get_vcpu_stat(struct domain *dom); ++int get_vcpu_list(struct domain_list *list); ++int get_vcpu_stat(struct domain *dom, struct domain_list *vcpu_list); + void refresh_delta_vcpu_stat(struct domain *new, struct domain *old); + void sum_vcpu_stat(struct domain *dom, struct domain *thread); + #endif +diff --git a/src/vmtop.c b/src/vmtop.c +index 66485c9..693779c 100644 +--- a/src/vmtop.c ++++ b/src/vmtop.c +@@ -54,6 +54,7 @@ static void init_parameter(void) + { + init_domains(&scr_cur); + init_domains(&scr_pre); ++ init_domains(&vcpu_list); + begin_task = 1; + begin_field = 1; + thread_mode = 0; /* default not to show threads */ +-- +2.27.0 + -- Gitee From 139d510b9a01adbaf3012dd4732a910d15c4f2e5 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Mon, 2 Nov 2020 13:44:54 +0800 Subject: [PATCH 07/12] proc: del /prc/pid/comm read The content obtained from comm file can also be obtianed from the stat file, So there is no need to read comm file. Signed-off-by: nocjj <1250062498@qq.com> --- proc-del-prc-pid-comm-read.patch | 120 +++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 proc-del-prc-pid-comm-read.patch diff --git a/proc-del-prc-pid-comm-read.patch b/proc-del-prc-pid-comm-read.patch new file mode 100644 index 0000000..1fe00a4 --- /dev/null +++ b/proc-del-prc-pid-comm-read.patch @@ -0,0 +1,120 @@ +From 8f711370b2a10266afc9d8a2d35fac540be4a3bc Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Mon, 2 Nov 2020 13:44:54 +0800 +Subject: [PATCH] proc: del /prc/pid/comm read + +The content obtained from comm file can also be obtianed from the stat file, +So there is no need to read comm file. + +Signed-off-by: nocjj <1250062498@qq.com> +--- + src/domain.c | 16 ++++++++-------- + src/proc.c | 36 +++++++++++++++--------------------- + 2 files changed, 23 insertions(+), 29 deletions(-) + +diff --git a/src/domain.c b/src/domain.c +index 05f85dd..7f9173d 100644 +--- a/src/domain.c ++++ b/src/domain.c +@@ -190,8 +190,7 @@ static int get_child_pid(struct domain *dom) + } + dom->threads[i].type = ISTHREAD; + dom->threads[i].ppid = dom->pid; +- if (get_proc_stat(&(dom->threads[i])) < 0 || +- get_proc_comm(&(dom->threads[i])) < 0) { ++ if (get_proc_stat(&(dom->threads[i])) < 0) { + continue; + } + if (strstr(dom->threads[i].vmname, "CPU") != NULL && +@@ -213,12 +212,6 @@ static int set_domain(struct domain *dom, const char *name) + char pid[PID_STRING_MAX]; + char *end = NULL; + +- if (len >= DOMAIN_NAME_MAX - 1) { +- return -1; +- } +- strcpy(dom->vmname, name); +- dom->vmname[len - strlen(".pid")] = '\0'; +- + if (snprintf(path, BUF_SIZE, "%s/%s", VAR_RUN_QEMU_PATH, name) < 0) { + return -1; + } +@@ -241,6 +234,13 @@ static int set_domain(struct domain *dom, const char *name) + if (get_proc_stat(dom) < 0 || get_child_pid(dom) < 0) { + return -1; + } ++ ++ if (len >= DOMAIN_NAME_MAX - 1) { ++ return -1; ++ } ++ strcpy(dom->vmname, name); ++ dom->vmname[len - strlen(".pid")] = '\0'; ++ + return 1; + } + +diff --git a/src/proc.c b/src/proc.c +index 2200bf0..0263c67 100644 +--- a/src/proc.c ++++ b/src/proc.c +@@ -70,10 +70,12 @@ int get_proc_stat(struct domain *dom) + { + char buf[BUF_SIZE]; + char path[STAT_PATH_SIZE]; +- char *tmp = NULL; ++ char *tmp1 = NULL; ++ char *tmp2 = NULL; + char *p = NULL; + char *p_next = NULL; + int i = 0; ++ int len; + + if (dom->type == ISDOMAIN) { + if (snprintf(path, STAT_PATH_SIZE, "/proc/%u/stat", dom->pid) < 0) { +@@ -89,11 +91,19 @@ int get_proc_stat(struct domain *dom) + return -1; + } + +- /* read from state item of "...) S ..." */ +- tmp = strrchr(buf, ')'); +- tmp = tmp + 2; ++ /* read comm from "pid (comm) S" */ ++ tmp1 = strrchr(buf, '(') + 1; ++ tmp2 = strrchr(buf, ')'); ++ len = tmp2 - tmp1; ++ if (len >= DOMAIN_NAME_MAX || len < 0) { ++ return -1; ++ } ++ strncpy(dom->vmname, tmp1, len); ++ dom->vmname[len] = '\0'; + +- for (p = strtok_r(tmp, " \t\r\n", &p_next); p && i < stat_size; ++ /* read start from process state */ ++ tmp2 = tmp2 + 2; ++ for (p = strtok_r(tmp2, " \t\r\n", &p_next); p && i < stat_size; + p = strtok_r(NULL, " \t\r\n", &p_next)) { + if (proc_stab[i].get_fun != NULL) { + sscanf(p, proc_stab[i].format, (*proc_stab[i].get_fun)(dom)); +@@ -111,19 +121,3 @@ void refresh_delta_stat(struct domain *new, struct domain *old) + } + } + } +- +-int get_proc_comm(struct domain *dom) +-{ +- char path[STAT_PATH_SIZE]; +- int len; +- +- if (snprintf(path, STAT_PATH_SIZE, "/proc/%u/comm", dom->pid) < 0) { +- return -1; +- } +- +- len = read_file(dom->vmname, DOMAIN_NAME_MAX, path); +- if (len > 1) { +- dom->vmname[len - 1] = '\0'; +- } +- return len; +-} +-- +2.27.0 + -- Gitee From a964cd3e01df95c9f43394d814b5dc1488e79d5c Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Mon, 2 Nov 2020 13:47:22 +0800 Subject: [PATCH 08/12] display: del screen clear after key response Clear will cause display to refresh off, so del clear afer key response. Signed-off-by: nocjj <1250062498@qq.com> --- ...-del-screen-clear-after-key-response.patch | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 display-del-screen-clear-after-key-response.patch diff --git a/display-del-screen-clear-after-key-response.patch b/display-del-screen-clear-after-key-response.patch new file mode 100644 index 0000000..c688885 --- /dev/null +++ b/display-del-screen-clear-after-key-response.patch @@ -0,0 +1,27 @@ +From 45c478a8a42ebd9b1d5e0ca57f7595b416c70b48 Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Mon, 2 Nov 2020 13:47:22 +0800 +Subject: [PATCH] display: del screen clear after key response + +Clear will cause display to refresh off, so del clear afer key response. + +Signed-off-by: nocjj <1250062498@qq.com> +--- + src/vmtop.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/vmtop.c b/src/vmtop.c +index 693779c..0137fdd 100644 +--- a/src/vmtop.c ++++ b/src/vmtop.c +@@ -489,7 +489,6 @@ int main(int argc, char *argv[]) + key = getch(); + if (key != ERR) { + parse_keys(key); +- clear(); + } + } else { + usleep(delay_time * 1000000); /* wait delay time in text mode */ +-- +2.27.0 + -- Gitee From 24cc51f0736c20a485bee36e251d311671f84608 Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Mon, 7 Dec 2020 15:14:02 +0800 Subject: [PATCH 09/12] codestyle: del unused var del unused var in vcpu_stat.c Signed-off-by: nocjj <1250062498@qq.com> --- codestyle-del-unused-var.patch | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 codestyle-del-unused-var.patch diff --git a/codestyle-del-unused-var.patch b/codestyle-del-unused-var.patch new file mode 100644 index 0000000..d69d657 --- /dev/null +++ b/codestyle-del-unused-var.patch @@ -0,0 +1,27 @@ +From 48dd3e3f4fb7e7f7b46b4711ff7300641b6e6f6b Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Mon, 7 Dec 2020 15:14:02 +0800 +Subject: [PATCH] codestyle: del unused var + +del unused var in vcpu_stat.c + +Signed-off-by: nocjj <1250062498@qq.com> +--- + src/vcpu_stat.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/vcpu_stat.c b/src/vcpu_stat.c +index 7009d41..5705b9a 100644 +--- a/src/vcpu_stat.c ++++ b/src/vcpu_stat.c +@@ -57,7 +57,6 @@ const int vcpu_stat_size = sizeof(vcpu_stat_stab) / sizeof(struct file_item); + int get_vcpu_list(struct domain_list *list) + { + char buf[BUF_SIZE]; +- unsigned int pid; + FILE *fp = NULL; + + fp = fopen(KVM_VCPU_STAT_PATH, "r"); +-- +2.27.0 + -- Gitee From 221fbb34cde0a26dbef70fa3963f424b37c5ae9e Mon Sep 17 00:00:00 2001 From: "Huawei Technologies Co., Ltd" Date: Thu, 21 Jan 2021 10:57:09 +0800 Subject: [PATCH 10/12] bugfix: add check to avoid invalid ptr for strcmp If len of d_name is less than "pid", it will pass a invalid ptr to strcmp, which will cause crash. --- ...heck-to-avoid-invalid-ptr-for-strcmp.patch | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 bugfix-add-check-to-avoid-invalid-ptr-for-strcmp.patch diff --git a/bugfix-add-check-to-avoid-invalid-ptr-for-strcmp.patch b/bugfix-add-check-to-avoid-invalid-ptr-for-strcmp.patch new file mode 100644 index 0000000..f5b1c36 --- /dev/null +++ b/bugfix-add-check-to-avoid-invalid-ptr-for-strcmp.patch @@ -0,0 +1,29 @@ +From 5e4d32547342814d1df1b7fb81824a6ba94ab89b Mon Sep 17 00:00:00 2001 +From: nocjj <1250062498@qq.com> +Date: Thu, 21 Jan 2021 10:57:09 +0800 +Subject: [PATCH] bugfix: add check to avoid invalid ptr for strcmp + +If len of d_name is less than "pid", it will pass a invalid ptr +to strcmp, which will cause crash. +--- + src/domain.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/domain.c b/src/domain.c +index 7f9173d..f8dea48 100644 +--- a/src/domain.c ++++ b/src/domain.c +@@ -253,6 +253,10 @@ static int check_pid_file(const char *d_name) + int extern_len = strlen(extern_name); + int len = strlen(d_name); + ++ if (len <= extern_len) { ++ return -1; ++ } ++ + return strcmp(d_name + len - extern_len, extern_name); + } + +-- +2.27.0 + -- Gitee From 79c010668ff3f2f08485d8c6bee2e8ce06ebd636 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Tue, 26 Jan 2021 11:57:23 +0800 Subject: [PATCH 11/12] spec: Update patch and changelog with !18 vcpu_stat: add remaining kvm exits items to display display: modify filter display to support more display fields items vcp_stat: add Max Scheduling Delay time items to display args: add -p option key: add page up/down key response vcpu_stat: get vcpu stat list once per display instead of per vcpu proc: del /prc/pid/comm read display: del screen clear after key response codestyle: del unused var bugfix: add check to avoid invalid ptr for strcmp Signed-off-by: Jiajun Chen <1250062498@qq.com> Signed-off-by: nocjj <1250062498@qq.com> --- vmtop.spec | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/vmtop.spec b/vmtop.spec index ce05037..0ca62d9 100644 --- a/vmtop.spec +++ b/vmtop.spec @@ -17,6 +17,16 @@ Patch0006: vcpustat-modify-vcpu-info-acquirement-from-debugfs.patch Patch0007: display-expand-CPU-display.patch Patch0008: display-add-limit-to-usage-display.patch Patch0009: vmtop-simplify-print_domain_field.patch +Patch0010: vcpu_stat-add-remaining-kvm-exits-items-to-display.patch +Patch0011: display-modify-filter-display-to-support-more-displa.patch +Patch0012: vcp_stat-add-Max-Scheduling-Delay-time-items-to-disp.patch +Patch0013: args-add-p-option.patch +Patch0014: key-add-page-up-down-key-response.patch +Patch0015: vcpu_stat-get-vcpu-stat-list-once-per-display-instea.patch +Patch0016: proc-del-prc-pid-comm-read.patch +Patch0017: display-del-screen-clear-after-key-response.patch +Patch0018: codestyle-del-unused-var.patch +Patch0019: bugfix-add-check-to-avoid-invalid-ptr-for-strcmp.patch Requires: libvirt, ncurses @@ -57,6 +67,18 @@ install -m 550 vmtop ${RPM_BUILD_ROOT}/usr/bin/%{name} %{_bindir}/vmtop %changelog +* Thu Jan 21 2021 Huawei Technologies Co., Ltd +- vcpu_stat: add remaining kvm exits items to display +- display: modify filter display to support more display fields items +- vcp_stat: add Max Scheduling Delay time items to display +- args: add -p option +- key: add page up/down key response +- vcpu_stat: get vcpu stat list once per display instead of per vcpu +- proc: del /prc/pid/comm read +- display: del screen clear after key response +- codestyle: del unused var +- bugfix: add check to avoid invalid ptr for strcmp + * Sat Oct 10 2020 Jiajun Chen <1250062498@qq.com> -1.1-0 - spec: modify source url -- Gitee From 25263aed4f61e8c8c35dfc8e54830aeee552f9f4 Mon Sep 17 00:00:00 2001 From: Euler Robot Date: Tue, 26 Jan 2021 11:57:24 +0800 Subject: [PATCH 12/12] spec: Update release version with !18 increase release verison by one Signed-off-by: Euler Robot --- vmtop.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vmtop.spec b/vmtop.spec index 0ca62d9..094e1e0 100644 --- a/vmtop.spec +++ b/vmtop.spec @@ -1,6 +1,6 @@ Name: vmtop Version: 1.1 -Release: 0 +Release: 1 Summary: A tool for collecting and analyzing data of virtual machine License: Mulan PSL V2 Group: Application/System -- Gitee