diff --git a/args-add-p-option.patch b/args-add-p-option.patch new file mode 100644 index 0000000000000000000000000000000000000000..7cc7e6e4b40f8982f59d46ef6908b2a95d4bd0ca --- /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 + 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 0000000000000000000000000000000000000000..f5b1c36489489b4f160d4d7a1d72f460097bf7bb --- /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 + diff --git a/codestyle-del-unused-var.patch b/codestyle-del-unused-var.patch new file mode 100644 index 0000000000000000000000000000000000000000..d69d65704b53f480c6ddb2cd1d43eec5d5046a50 --- /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 + 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 0000000000000000000000000000000000000000..c688885ef5bd01ce4c936d638db94bf4be862da3 --- /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 + 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 0000000000000000000000000000000000000000..eea72a7b84ed0370beddc4e4d8bac7b1085d7e4e --- /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 + 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 0000000000000000000000000000000000000000..b07b15478a143f9dda01dd9e27e0894904bafe0c --- /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 + diff --git a/proc-del-prc-pid-comm-read.patch b/proc-del-prc-pid-comm-read.patch new file mode 100644 index 0000000000000000000000000000000000000000..1fe00a49dd0bb681213739f598d077295f04aa4a --- /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 + 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 0000000000000000000000000000000000000000..d9b7d7cff00a92ebd07b82261a324ef811165eca --- /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 + 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 0000000000000000000000000000000000000000..30f6419d9f1e160397f1733ae9de32e111b40407 --- /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 + 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 0000000000000000000000000000000000000000..f47a57e8ef687552306dd656e1bf1f4e406711b2 --- /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 + diff --git a/vmtop.spec b/vmtop.spec index ce0503744db8eefa15dd79ad36c3bd1d94431529..094e1e031c2a698bf44cbf2cc6be12efc9504d7c 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 @@ -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