1 #include <kvm/util.h>
2 #include <kvm/kvm-cmd.h>
3 #include <kvm/builtin-stat.h>
4 #include <kvm/kvm.h>
5 #include <kvm/parse-options.h>
6 #include <kvm/kvm-ipc.h>
7
8 #include <sys/select.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <signal.h>
12
13 #include <linux/virtio_balloon.h>
14
15 static bool mem;
16 static bool all;
17 static const char *instance_name;
18
19 static const char * const stat_usage[] = {
20 "lkvm stat [command] [--all] [-n name]",
21 NULL
22 };
23
24 static const struct option stat_options[] = {
25 OPT_GROUP("Commands options:"),
26 OPT_BOOLEAN('m', "memory", &mem, "Display memory statistics"),
27 OPT_GROUP("Instance options:"),
28 OPT_BOOLEAN('a', "all", &all, "All instances"),
29 OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
30 OPT_END()
31 };
32
parse_stat_options(int argc,const char ** argv)33 static void parse_stat_options(int argc, const char **argv)
34 {
35 while (argc != 0) {
36 argc = parse_options(argc, argv, stat_options, stat_usage,
37 PARSE_OPT_STOP_AT_NON_OPTION);
38 if (argc != 0)
39 kvm_stat_help();
40 }
41 }
42
kvm_stat_help(void)43 void kvm_stat_help(void)
44 {
45 usage_with_options(stat_usage, stat_options);
46 }
47
do_memstat(const char * name,int sock)48 static int do_memstat(const char *name, int sock)
49 {
50 struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
51 fd_set fdset;
52 struct timeval t = { .tv_sec = 1 };
53 int r;
54 u8 i;
55
56 FD_ZERO(&fdset);
57 FD_SET(sock, &fdset);
58 r = kvm_ipc__send(sock, KVM_IPC_STAT);
59 if (r < 0)
60 return r;
61
62 r = select(1, &fdset, NULL, NULL, &t);
63 if (r < 0) {
64 pr_err("Could not retrieve mem stats from %s", name);
65 return r;
66 }
67 r = read(sock, &stats, sizeof(stats));
68 if (r < 0)
69 return r;
70
71 printf("\n\n\t*** Guest memory statistics ***\n\n");
72 for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
73 switch (stats[i].tag) {
74 case VIRTIO_BALLOON_S_SWAP_IN:
75 printf("The amount of memory that has been swapped in (in bytes):");
76 break;
77 case VIRTIO_BALLOON_S_SWAP_OUT:
78 printf("The amount of memory that has been swapped out to disk (in bytes):");
79 break;
80 case VIRTIO_BALLOON_S_MAJFLT:
81 printf("The number of major page faults that have occurred:");
82 break;
83 case VIRTIO_BALLOON_S_MINFLT:
84 printf("The number of minor page faults that have occurred:");
85 break;
86 case VIRTIO_BALLOON_S_HTLB_PGALLOC:
87 printf("The number of successful HugeTLB allocations:");
88 break;
89 case VIRTIO_BALLOON_S_HTLB_PGFAIL:
90 printf("The number of failed HugeTLB allocations:");
91 break;
92 case VIRTIO_BALLOON_S_MEMFREE:
93 printf("The amount of memory not being used for any purpose (in bytes):");
94 break;
95 case VIRTIO_BALLOON_S_MEMTOT:
96 printf("The total amount of memory (in bytes):");
97 break;
98 case VIRTIO_BALLOON_S_AVAIL:
99 printf("The estimated available memory (in bytes):");
100 break;
101 case VIRTIO_BALLOON_S_CACHES:
102 printf("The amount of memory in use for file caching (in bytes):");
103 break;
104 default:
105 printf("Unknown memory statistic (ID %u): ", stats[i].tag);
106 break;
107 }
108 printf("%llu\n", (unsigned long long)stats[i].val);
109 }
110 printf("\n");
111
112 return 0;
113 }
114
kvm_cmd_stat(int argc,const char ** argv,const char * prefix)115 int kvm_cmd_stat(int argc, const char **argv, const char *prefix)
116 {
117 int instance;
118 int r = 0;
119
120 parse_stat_options(argc, argv);
121
122 if (!mem)
123 usage_with_options(stat_usage, stat_options);
124
125 if (mem && all)
126 return kvm__enumerate_instances(do_memstat);
127
128 if (instance_name == NULL)
129 kvm_stat_help();
130
131 instance = kvm__get_sock_by_instance(instance_name);
132
133 if (instance <= 0)
134 die("Failed locating instance");
135
136 if (mem)
137 r = do_memstat(instance_name, instance);
138
139 close(instance);
140
141 return r;
142 }
143