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 154b1addaeSSasha Levin struct stat_cmd { 164b1addaeSSasha Levin u32 type; 174b1addaeSSasha Levin u32 len; 184b1addaeSSasha Levin }; 194b1addaeSSasha Levin 20bc10d2c1SSasha Levin static bool mem; 21bc10d2c1SSasha Levin static bool all; 22bc10d2c1SSasha Levin static const char *instance_name; 23bc10d2c1SSasha Levin 24bc10d2c1SSasha Levin static const char * const stat_usage[] = { 258d2ff5daSWanlong Gao "lkvm stat [command] [--all] [-n name]", 26bc10d2c1SSasha Levin NULL 27bc10d2c1SSasha Levin }; 28bc10d2c1SSasha Levin 29bc10d2c1SSasha Levin static const struct option stat_options[] = { 30bc10d2c1SSasha Levin OPT_GROUP("Commands options:"), 31bc10d2c1SSasha Levin OPT_BOOLEAN('m', "memory", &mem, "Display memory statistics"), 32bc10d2c1SSasha Levin OPT_GROUP("Instance options:"), 33bc10d2c1SSasha Levin OPT_BOOLEAN('a', "all", &all, "All instances"), 34bc10d2c1SSasha Levin OPT_STRING('n', "name", &instance_name, "name", "Instance name"), 35bc10d2c1SSasha Levin OPT_END() 36bc10d2c1SSasha Levin }; 37bc10d2c1SSasha Levin 38bc10d2c1SSasha Levin static void parse_stat_options(int argc, const char **argv) 39bc10d2c1SSasha Levin { 40bc10d2c1SSasha Levin while (argc != 0) { 41bc10d2c1SSasha Levin argc = parse_options(argc, argv, stat_options, stat_usage, 42bc10d2c1SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION); 43bc10d2c1SSasha Levin if (argc != 0) 44bc10d2c1SSasha Levin kvm_stat_help(); 45bc10d2c1SSasha Levin } 46bc10d2c1SSasha Levin } 47bc10d2c1SSasha Levin 48bc10d2c1SSasha Levin void kvm_stat_help(void) 49bc10d2c1SSasha Levin { 50bc10d2c1SSasha Levin usage_with_options(stat_usage, stat_options); 51bc10d2c1SSasha Levin } 52bc10d2c1SSasha Levin 534b1addaeSSasha Levin static int do_memstat(const char *name, int sock) 54bc10d2c1SSasha Levin { 554b1addaeSSasha Levin struct stat_cmd cmd = {KVM_IPC_STAT, 0}; 56498746b9SSasha Levin struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; 57498746b9SSasha Levin fd_set fdset; 58498746b9SSasha Levin struct timeval t = { .tv_sec = 1 }; 594b1addaeSSasha Levin int r; 60498746b9SSasha Levin u8 i; 614b1addaeSSasha Levin 62498746b9SSasha Levin FD_ZERO(&fdset); 63498746b9SSasha Levin FD_SET(sock, &fdset); 644b1addaeSSasha Levin r = write(sock, &cmd, sizeof(cmd)); 654b1addaeSSasha Levin if (r < 0) 664b1addaeSSasha Levin return r; 674b1addaeSSasha Levin 68498746b9SSasha Levin r = select(1, &fdset, NULL, NULL, &t); 69498746b9SSasha Levin if (r < 0) { 70599ed2a8SCyrill Gorcunov pr_err("Could not retrieve mem stats from %s", name); 71498746b9SSasha Levin return r; 72498746b9SSasha Levin } 73498746b9SSasha Levin r = read(sock, &stats, sizeof(stats)); 74498746b9SSasha Levin if (r < 0) 75498746b9SSasha Levin return r; 76498746b9SSasha Levin 77498746b9SSasha Levin printf("\n\n\t*** Guest memory statistics ***\n\n"); 78498746b9SSasha Levin for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) { 79498746b9SSasha Levin switch (stats[i].tag) { 80498746b9SSasha Levin case VIRTIO_BALLOON_S_SWAP_IN: 81498746b9SSasha Levin printf("The amount of memory that has been swapped in (in bytes):"); 82498746b9SSasha Levin break; 83498746b9SSasha Levin case VIRTIO_BALLOON_S_SWAP_OUT: 84498746b9SSasha Levin printf("The amount of memory that has been swapped out to disk (in bytes):"); 85498746b9SSasha Levin break; 86498746b9SSasha Levin case VIRTIO_BALLOON_S_MAJFLT: 87498746b9SSasha Levin printf("The number of major page faults that have occurred:"); 88498746b9SSasha Levin break; 89498746b9SSasha Levin case VIRTIO_BALLOON_S_MINFLT: 90498746b9SSasha Levin printf("The number of minor page faults that have occurred:"); 91498746b9SSasha Levin break; 92498746b9SSasha Levin case VIRTIO_BALLOON_S_MEMFREE: 93498746b9SSasha Levin printf("The amount of memory not being used for any purpose (in bytes):"); 94498746b9SSasha Levin break; 95498746b9SSasha Levin case VIRTIO_BALLOON_S_MEMTOT: 96498746b9SSasha Levin printf("The total amount of memory available (in bytes):"); 97498746b9SSasha Levin break; 98498746b9SSasha Levin } 99498746b9SSasha Levin printf("%llu\n", stats[i].val); 100498746b9SSasha Levin } 101498746b9SSasha Levin printf("\n"); 102498746b9SSasha Levin 1034b1addaeSSasha Levin return 0; 104bc10d2c1SSasha Levin } 105bc10d2c1SSasha Levin 106bc10d2c1SSasha Levin int kvm_cmd_stat(int argc, const char **argv, const char *prefix) 107bc10d2c1SSasha Levin { 108*28aadb17SLai Jiangshan int instance; 109*28aadb17SLai Jiangshan int r = 0; 110*28aadb17SLai Jiangshan 111bc10d2c1SSasha Levin parse_stat_options(argc, argv); 112bc10d2c1SSasha Levin 113bc10d2c1SSasha Levin if (!mem) 114bc10d2c1SSasha Levin usage_with_options(stat_usage, stat_options); 115bc10d2c1SSasha Levin 116bc10d2c1SSasha Levin if (mem && all) 117bc10d2c1SSasha Levin return kvm__enumerate_instances(do_memstat); 118bc10d2c1SSasha Levin 119*28aadb17SLai Jiangshan if (instance_name == NULL) 120bc10d2c1SSasha Levin kvm_stat_help(); 121bc10d2c1SSasha Levin 1224b1addaeSSasha Levin instance = kvm__get_sock_by_instance(instance_name); 123bc10d2c1SSasha Levin 1244b1addaeSSasha Levin if (instance <= 0) 125bc10d2c1SSasha Levin die("Failed locating instance"); 126bc10d2c1SSasha Levin 1274b1addaeSSasha Levin if (mem) 128*28aadb17SLai Jiangshan r = do_memstat(instance_name, instance); 129bc10d2c1SSasha Levin 130*28aadb17SLai Jiangshan close(instance); 131*28aadb17SLai Jiangshan 132*28aadb17SLai Jiangshan return r; 133bc10d2c1SSasha Levin } 134