1bc10d2c1SSasha Levin #include <kvm/util.h> 2bc10d2c1SSasha Levin #include <kvm/kvm-cmd.h> 3bc10d2c1SSasha Levin #include <kvm/builtin-stat.h> 4bc10d2c1SSasha Levin #include <kvm/kvm.h> 5bc10d2c1SSasha Levin #include <kvm/parse-options.h> 64b1addaeSSasha Levin #include <kvm/kvm-ipc.h> 7bc10d2c1SSasha Levin 8498746b9SSasha Levin #include <sys/select.h> 9bc10d2c1SSasha Levin #include <stdio.h> 10bc10d2c1SSasha Levin #include <string.h> 11bc10d2c1SSasha Levin #include <signal.h> 12bc10d2c1SSasha Levin 13498746b9SSasha Levin #include <linux/virtio_balloon.h> 14498746b9SSasha Levin 15bc10d2c1SSasha Levin static bool mem; 16bc10d2c1SSasha Levin static bool all; 17bc10d2c1SSasha Levin static const char *instance_name; 18bc10d2c1SSasha Levin 19bc10d2c1SSasha Levin static const char * const stat_usage[] = { 208d2ff5daSWanlong Gao "lkvm stat [command] [--all] [-n name]", 21bc10d2c1SSasha Levin NULL 22bc10d2c1SSasha Levin }; 23bc10d2c1SSasha Levin 24bc10d2c1SSasha Levin static const struct option stat_options[] = { 25bc10d2c1SSasha Levin OPT_GROUP("Commands options:"), 26bc10d2c1SSasha Levin OPT_BOOLEAN('m', "memory", &mem, "Display memory statistics"), 27bc10d2c1SSasha Levin OPT_GROUP("Instance options:"), 28bc10d2c1SSasha Levin OPT_BOOLEAN('a', "all", &all, "All instances"), 29bc10d2c1SSasha Levin OPT_STRING('n', "name", &instance_name, "name", "Instance name"), 30bc10d2c1SSasha Levin OPT_END() 31bc10d2c1SSasha Levin }; 32bc10d2c1SSasha Levin 33bc10d2c1SSasha Levin static void parse_stat_options(int argc, const char **argv) 34bc10d2c1SSasha Levin { 35bc10d2c1SSasha Levin while (argc != 0) { 36bc10d2c1SSasha Levin argc = parse_options(argc, argv, stat_options, stat_usage, 37bc10d2c1SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION); 38bc10d2c1SSasha Levin if (argc != 0) 39bc10d2c1SSasha Levin kvm_stat_help(); 40bc10d2c1SSasha Levin } 41bc10d2c1SSasha Levin } 42bc10d2c1SSasha Levin 43bc10d2c1SSasha Levin void kvm_stat_help(void) 44bc10d2c1SSasha Levin { 45bc10d2c1SSasha Levin usage_with_options(stat_usage, stat_options); 46bc10d2c1SSasha Levin } 47bc10d2c1SSasha Levin 484b1addaeSSasha Levin static int do_memstat(const char *name, int sock) 49bc10d2c1SSasha Levin { 50498746b9SSasha Levin struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; 51498746b9SSasha Levin fd_set fdset; 52498746b9SSasha Levin struct timeval t = { .tv_sec = 1 }; 534b1addaeSSasha Levin int r; 54498746b9SSasha Levin u8 i; 554b1addaeSSasha Levin 56498746b9SSasha Levin FD_ZERO(&fdset); 57498746b9SSasha Levin FD_SET(sock, &fdset); 58d0dc85a8SLai Jiangshan r = kvm_ipc__send(sock, KVM_IPC_STAT); 594b1addaeSSasha Levin if (r < 0) 604b1addaeSSasha Levin return r; 614b1addaeSSasha Levin 62498746b9SSasha Levin r = select(1, &fdset, NULL, NULL, &t); 63498746b9SSasha Levin if (r < 0) { 64599ed2a8SCyrill Gorcunov pr_err("Could not retrieve mem stats from %s", name); 65498746b9SSasha Levin return r; 66498746b9SSasha Levin } 67498746b9SSasha Levin r = read(sock, &stats, sizeof(stats)); 68498746b9SSasha Levin if (r < 0) 69498746b9SSasha Levin return r; 70498746b9SSasha Levin 71498746b9SSasha Levin printf("\n\n\t*** Guest memory statistics ***\n\n"); 72498746b9SSasha Levin for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) { 73498746b9SSasha Levin switch (stats[i].tag) { 74498746b9SSasha Levin case VIRTIO_BALLOON_S_SWAP_IN: 75498746b9SSasha Levin printf("The amount of memory that has been swapped in (in bytes):"); 76498746b9SSasha Levin break; 77498746b9SSasha Levin case VIRTIO_BALLOON_S_SWAP_OUT: 78498746b9SSasha Levin printf("The amount of memory that has been swapped out to disk (in bytes):"); 79498746b9SSasha Levin break; 80498746b9SSasha Levin case VIRTIO_BALLOON_S_MAJFLT: 81498746b9SSasha Levin printf("The number of major page faults that have occurred:"); 82498746b9SSasha Levin break; 83498746b9SSasha Levin case VIRTIO_BALLOON_S_MINFLT: 84498746b9SSasha Levin printf("The number of minor page faults that have occurred:"); 85498746b9SSasha Levin break; 86498746b9SSasha Levin case VIRTIO_BALLOON_S_MEMFREE: 87498746b9SSasha Levin printf("The amount of memory not being used for any purpose (in bytes):"); 88498746b9SSasha Levin break; 89498746b9SSasha Levin case VIRTIO_BALLOON_S_MEMTOT: 90498746b9SSasha Levin printf("The total amount of memory available (in bytes):"); 91498746b9SSasha Levin break; 92498746b9SSasha Levin } 93*69f50425SAndreas Herrmann printf("%llu\n", (unsigned long long)stats[i].val); 94498746b9SSasha Levin } 95498746b9SSasha Levin printf("\n"); 96498746b9SSasha Levin 974b1addaeSSasha Levin return 0; 98bc10d2c1SSasha Levin } 99bc10d2c1SSasha Levin 100bc10d2c1SSasha Levin int kvm_cmd_stat(int argc, const char **argv, const char *prefix) 101bc10d2c1SSasha Levin { 10228aadb17SLai Jiangshan int instance; 10328aadb17SLai Jiangshan int r = 0; 10428aadb17SLai Jiangshan 105bc10d2c1SSasha Levin parse_stat_options(argc, argv); 106bc10d2c1SSasha Levin 107bc10d2c1SSasha Levin if (!mem) 108bc10d2c1SSasha Levin usage_with_options(stat_usage, stat_options); 109bc10d2c1SSasha Levin 110bc10d2c1SSasha Levin if (mem && all) 111bc10d2c1SSasha Levin return kvm__enumerate_instances(do_memstat); 112bc10d2c1SSasha Levin 11328aadb17SLai Jiangshan if (instance_name == NULL) 114bc10d2c1SSasha Levin kvm_stat_help(); 115bc10d2c1SSasha Levin 1164b1addaeSSasha Levin instance = kvm__get_sock_by_instance(instance_name); 117bc10d2c1SSasha Levin 1184b1addaeSSasha Levin if (instance <= 0) 119bc10d2c1SSasha Levin die("Failed locating instance"); 120bc10d2c1SSasha Levin 1214b1addaeSSasha Levin if (mem) 12228aadb17SLai Jiangshan r = do_memstat(instance_name, instance); 123bc10d2c1SSasha Levin 12428aadb17SLai Jiangshan close(instance); 12528aadb17SLai Jiangshan 12628aadb17SLai Jiangshan return r; 127bc10d2c1SSasha Levin } 128