1 /* libxenstat: statistics-collection library for Xen
2 * Copyright (C) International Business Machines Corp., 2005
3 * Authors: Josh Triplett <josh@kernel.org>
4 * Judy Fischbach <jfisch@cs.pdx.edu>
5 * David Hendricks <cro_marmot@comcast.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 */
17
18 /*
19 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
20 * Use is subject to license terms.
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <unistd.h>
27
28 #include "xenstat_priv.h"
29
30 /*
31 * Data-collection types
32 */
33 /* Called to collect the information for the node and all the domains on
34 * it. When called, the domain information has already been collected.
35 * Return status is 0 if fatal error occurs, 1 for success. Collectors
36 * may prune a domain from the list if it has been deleted between the
37 * time the list was setup and the time the colector is called */
38 typedef int (*xenstat_collect_func)(xenstat_node * node);
39 /* Called to free the information collected by the collect function. The free
40 * function will only be called on a xenstat_node if that node includes
41 * information collected by the corresponding collector. */
42 typedef void (*xenstat_free_func)(xenstat_node * node);
43 /* Called to free any information stored in the handle. Note the lack of a
44 * matching init function; the collect functions should initialize on first
45 * use. Also, the uninit function must handle the case that the collector has
46 * never been initialized. */
47 typedef void (*xenstat_uninit_func)(xenstat_handle * handle);
48 typedef struct xenstat_collector {
49 unsigned int flag;
50 xenstat_collect_func collect;
51 xenstat_free_func free;
52 xenstat_uninit_func uninit;
53 } xenstat_collector;
54
55 static int xenstat_collect_vcpus(xenstat_node * node);
56 static int xenstat_collect_xen_version(xenstat_node * node);
57 static void xenstat_free_vcpus(xenstat_node * node);
58 static void xenstat_free_networks(xenstat_node * node);
59 static void xenstat_free_xen_version(xenstat_node * node);
60 static void xenstat_free_vbds(xenstat_node * node);
61 static void xenstat_uninit_vcpus(xenstat_handle * handle);
62 static void xenstat_uninit_xen_version(xenstat_handle * handle);
63 static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
64 static void xenstat_prune_domain(xenstat_node *node, unsigned int entry);
65
66 static xenstat_collector collectors[] = {
67 { XENSTAT_VCPU, xenstat_collect_vcpus,
68 xenstat_free_vcpus, xenstat_uninit_vcpus },
69 { XENSTAT_NETWORK, xenstat_collect_networks,
70 xenstat_free_networks, xenstat_uninit_networks },
71 { XENSTAT_XEN_VERSION, xenstat_collect_xen_version,
72 xenstat_free_xen_version, xenstat_uninit_xen_version },
73 { XENSTAT_VBD, xenstat_collect_vbds,
74 xenstat_free_vbds, xenstat_uninit_vbds }
75 };
76
77 #define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector))
78
79 /*
80 * libxenstat API
81 */
xenstat_init(void)82 xenstat_handle *xenstat_init(void)
83 {
84 xenstat_handle *handle;
85
86 handle = (xenstat_handle *) calloc(1, sizeof(xenstat_handle));
87 if (handle == NULL)
88 return NULL;
89
90 #if defined(PAGESIZE)
91 handle->page_size = PAGESIZE;
92 #elif defined(PAGE_SIZE)
93 handle->page_size = PAGE_SIZE;
94 #else
95 handle->page_size = sysconf(_SC_PAGE_SIZE);
96 if (handle->page_size < 0) {
97 perror("Failed to retrieve page size.");
98 free(handle);
99 return NULL;
100 }
101 #endif
102
103 handle->xc_handle = xc_interface_open(0,0,0);
104 if (!handle->xc_handle) {
105 perror("xc_interface_open");
106 free(handle);
107 return NULL;
108 }
109
110 handle->xshandle = xs_daemon_open_readonly(); /* open handle to xenstore*/
111 if (handle->xshandle == NULL) {
112 perror("unable to open xenstore");
113 xc_interface_close(handle->xc_handle);
114 free(handle);
115 return NULL;
116 }
117
118 return handle;
119 }
120
xenstat_uninit(xenstat_handle * handle)121 void xenstat_uninit(xenstat_handle * handle)
122 {
123 unsigned int i;
124 if (handle) {
125 for (i = 0; i < NUM_COLLECTORS; i++)
126 collectors[i].uninit(handle);
127 xc_interface_close(handle->xc_handle);
128 xs_daemon_close(handle->xshandle);
129 free(handle->priv);
130 free(handle);
131 }
132 }
133
parse(char * s,char * match)134 static inline unsigned long long parse(char *s, char *match)
135 {
136 char *s1 = strstr(s,match);
137 unsigned long long ret;
138
139 if ( s1 == NULL )
140 return 0LL;
141 s1 += 2;
142 if ( *s1++ != ':' )
143 return 0LL;
144 sscanf(s1,"%llu",&ret);
145 return ret;
146 }
147
domain_get_tmem_stats(xenstat_handle * handle,xenstat_domain * domain)148 void domain_get_tmem_stats(xenstat_handle * handle, xenstat_domain * domain)
149 {
150 char buffer[4096];
151
152 if (xc_tmem_control(handle->xc_handle,-1,XEN_SYSCTL_TMEM_OP_LIST,domain->id,
153 sizeof(buffer),-1,buffer) < 0)
154 return;
155 domain->tmem_stats.curr_eph_pages = parse(buffer,"Ec");
156 domain->tmem_stats.succ_eph_gets = parse(buffer,"Ge");
157 domain->tmem_stats.succ_pers_puts = parse(buffer,"Pp");
158 domain->tmem_stats.succ_pers_gets = parse(buffer,"Gp");
159 }
160
xenstat_get_node(xenstat_handle * handle,unsigned int flags)161 xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
162 {
163 #define DOMAIN_CHUNK_SIZE 256
164 xenstat_node *node;
165 xc_physinfo_t physinfo = { 0 };
166 xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
167 int new_domains;
168 unsigned int i;
169 int rc;
170
171 /* Create the node */
172 node = (xenstat_node *) calloc(1, sizeof(xenstat_node));
173 if (node == NULL)
174 return NULL;
175
176 /* Store the handle in the node for later access */
177 node->handle = handle;
178
179 /* Get information about the physical system */
180 if (xc_physinfo(handle->xc_handle, &physinfo) < 0) {
181 free(node);
182 return NULL;
183 }
184
185
186 node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL;
187 node->num_cpus = physinfo.nr_cpus;
188 node->tot_mem = ((unsigned long long)physinfo.total_pages)
189 * handle->page_size;
190 node->free_mem = ((unsigned long long)physinfo.free_pages)
191 * handle->page_size;
192
193 rc = xc_tmem_control(handle->xc_handle, -1,
194 XEN_SYSCTL_TMEM_OP_QUERY_FREEABLE_MB, -1, 0, 0, NULL);
195 node->freeable_mb = (rc < 0) ? 0 : rc;
196 /* malloc(0) is not portable, so allocate a single domain. This will
197 * be resized below. */
198 node->domains = malloc(sizeof(xenstat_domain));
199 if (node->domains == NULL) {
200 free(node);
201 return NULL;
202 }
203
204 node->num_domains = 0;
205 do {
206 xenstat_domain *domain, *tmp;
207
208 new_domains = xc_domain_getinfolist(handle->xc_handle,
209 node->num_domains,
210 DOMAIN_CHUNK_SIZE,
211 domaininfo);
212 if (new_domains < 0)
213 goto err;
214
215 tmp = realloc(node->domains,
216 (node->num_domains + new_domains)
217 * sizeof(xenstat_domain));
218 if (tmp == NULL)
219 goto err;
220
221 node->domains = tmp;
222
223 domain = node->domains + node->num_domains;
224
225 /* zero out newly allocated memory in case error occurs below */
226 memset(domain, 0, new_domains * sizeof(xenstat_domain));
227
228 for (i = 0; i < new_domains; i++) {
229 /* Fill in domain using domaininfo[i] */
230 domain->id = domaininfo[i].domain;
231 domain->name = xenstat_get_domain_name(handle,
232 domain->id);
233 if (domain->name == NULL) {
234 if (errno == ENOMEM) {
235 /* fatal error */
236 xenstat_free_node(node);
237 return NULL;
238 }
239 else {
240 /* failed to get name -- this means the
241 domain is being destroyed so simply
242 ignore this entry */
243 continue;
244 }
245 }
246 domain->state = domaininfo[i].flags;
247 domain->cpu_ns = domaininfo[i].cpu_time;
248 domain->num_vcpus = (domaininfo[i].max_vcpu_id+1);
249 domain->vcpus = NULL;
250 domain->cur_mem =
251 ((unsigned long long)domaininfo[i].tot_pages)
252 * handle->page_size;
253 domain->max_mem =
254 domaininfo[i].max_pages == UINT_MAX
255 ? (unsigned long long)-1
256 : (unsigned long long)(domaininfo[i].max_pages
257 * handle->page_size);
258 domain->ssid = domaininfo[i].ssidref;
259 domain->num_networks = 0;
260 domain->networks = NULL;
261 domain->num_vbds = 0;
262 domain->vbds = NULL;
263 domain_get_tmem_stats(handle,domain);
264
265 domain++;
266 node->num_domains++;
267 }
268 } while (new_domains == DOMAIN_CHUNK_SIZE);
269
270
271 /* Run all the extra data collectors requested */
272 node->flags = 0;
273 for (i = 0; i < NUM_COLLECTORS; i++) {
274 if ((flags & collectors[i].flag) == collectors[i].flag) {
275 node->flags |= collectors[i].flag;
276 if(collectors[i].collect(node) == 0) {
277 xenstat_free_node(node);
278 return NULL;
279 }
280 }
281 }
282
283 return node;
284 err:
285 free(node->domains);
286 free(node);
287 return NULL;
288 }
289
xenstat_free_node(xenstat_node * node)290 void xenstat_free_node(xenstat_node * node)
291 {
292 int i;
293
294 if (node) {
295 if (node->domains) {
296 for (i = 0; i < node->num_domains; i++)
297 free(node->domains[i].name);
298
299 for (i = 0; i < NUM_COLLECTORS; i++)
300 if((node->flags & collectors[i].flag)
301 == collectors[i].flag)
302 collectors[i].free(node);
303 free(node->domains);
304 }
305 free(node);
306 }
307 }
308
xenstat_node_domain(xenstat_node * node,unsigned int domid)309 xenstat_domain *xenstat_node_domain(xenstat_node * node, unsigned int domid)
310 {
311 unsigned int i;
312
313 /* FIXME: binary search */
314 /* Find the appropriate domain entry in the node struct. */
315 for (i = 0; i < node->num_domains; i++) {
316 if (node->domains[i].id == domid)
317 return &(node->domains[i]);
318 }
319 return NULL;
320 }
321
xenstat_node_domain_by_index(xenstat_node * node,unsigned int index)322 xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node,
323 unsigned int index)
324 {
325 if (index < node->num_domains)
326 return &(node->domains[index]);
327 return NULL;
328 }
329
xenstat_node_xen_version(xenstat_node * node)330 const char *xenstat_node_xen_version(xenstat_node * node)
331 {
332 return node->handle->xen_version;
333 }
334
xenstat_node_tot_mem(xenstat_node * node)335 unsigned long long xenstat_node_tot_mem(xenstat_node * node)
336 {
337 return node->tot_mem;
338 }
339
xenstat_node_free_mem(xenstat_node * node)340 unsigned long long xenstat_node_free_mem(xenstat_node * node)
341 {
342 return node->free_mem;
343 }
344
xenstat_node_freeable_mb(xenstat_node * node)345 long xenstat_node_freeable_mb(xenstat_node * node)
346 {
347 return node->freeable_mb;
348 }
349
xenstat_node_num_domains(xenstat_node * node)350 unsigned int xenstat_node_num_domains(xenstat_node * node)
351 {
352 return node->num_domains;
353 }
354
xenstat_node_num_cpus(xenstat_node * node)355 unsigned int xenstat_node_num_cpus(xenstat_node * node)
356 {
357 return node->num_cpus;
358 }
359
360 /* Get information about the CPU speed */
xenstat_node_cpu_hz(xenstat_node * node)361 unsigned long long xenstat_node_cpu_hz(xenstat_node * node)
362 {
363 return node->cpu_hz;
364 }
365
366 /* Get the domain ID for this domain */
xenstat_domain_id(xenstat_domain * domain)367 unsigned xenstat_domain_id(xenstat_domain * domain)
368 {
369 return domain->id;
370 }
371
372 /* Get the domain name for the domain */
xenstat_domain_name(xenstat_domain * domain)373 char *xenstat_domain_name(xenstat_domain * domain)
374 {
375 return domain->name;
376 }
377
378 /* Get information about how much CPU time has been used */
xenstat_domain_cpu_ns(xenstat_domain * domain)379 unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain)
380 {
381 return domain->cpu_ns;
382 }
383
384 /* Find the number of VCPUs for a domain */
xenstat_domain_num_vcpus(xenstat_domain * domain)385 unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain)
386 {
387 return domain->num_vcpus;
388 }
389
xenstat_domain_vcpu(xenstat_domain * domain,unsigned int vcpu)390 xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, unsigned int vcpu)
391 {
392 if (vcpu < domain->num_vcpus)
393 return &(domain->vcpus[vcpu]);
394 return NULL;
395 }
396
397 /* Find the current memory reservation for this domain */
xenstat_domain_cur_mem(xenstat_domain * domain)398 unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain)
399 {
400 return domain->cur_mem;
401 }
402
403 /* Find the maximum memory reservation for this domain */
xenstat_domain_max_mem(xenstat_domain * domain)404 unsigned long long xenstat_domain_max_mem(xenstat_domain * domain)
405 {
406 return domain->max_mem;
407 }
408
409 /* Find the domain's SSID */
xenstat_domain_ssid(xenstat_domain * domain)410 unsigned int xenstat_domain_ssid(xenstat_domain * domain)
411 {
412 return domain->ssid;
413 }
414
415 /* Get domain states */
xenstat_domain_dying(xenstat_domain * domain)416 unsigned int xenstat_domain_dying(xenstat_domain * domain)
417 {
418 return (domain->state & XEN_DOMINF_dying) == XEN_DOMINF_dying;
419 }
420
xenstat_domain_crashed(xenstat_domain * domain)421 unsigned int xenstat_domain_crashed(xenstat_domain * domain)
422 {
423 return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
424 && (((domain->state >> XEN_DOMINF_shutdownshift)
425 & XEN_DOMINF_shutdownmask) == SHUTDOWN_crash);
426 }
427
xenstat_domain_shutdown(xenstat_domain * domain)428 unsigned int xenstat_domain_shutdown(xenstat_domain * domain)
429 {
430 return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
431 && (((domain->state >> XEN_DOMINF_shutdownshift)
432 & XEN_DOMINF_shutdownmask) != SHUTDOWN_crash);
433 }
434
xenstat_domain_paused(xenstat_domain * domain)435 unsigned int xenstat_domain_paused(xenstat_domain * domain)
436 {
437 return (domain->state & XEN_DOMINF_paused) == XEN_DOMINF_paused;
438 }
439
xenstat_domain_blocked(xenstat_domain * domain)440 unsigned int xenstat_domain_blocked(xenstat_domain * domain)
441 {
442 return (domain->state & XEN_DOMINF_blocked) == XEN_DOMINF_blocked;
443 }
444
xenstat_domain_running(xenstat_domain * domain)445 unsigned int xenstat_domain_running(xenstat_domain * domain)
446 {
447 return (domain->state & XEN_DOMINF_running) == XEN_DOMINF_running;
448 }
449
450 /* Get the number of networks for a given domain */
xenstat_domain_num_networks(xenstat_domain * domain)451 unsigned int xenstat_domain_num_networks(xenstat_domain * domain)
452 {
453 return domain->num_networks;
454 }
455
456 /* Get the network handle to obtain network stats */
xenstat_domain_network(xenstat_domain * domain,unsigned int network)457 xenstat_network *xenstat_domain_network(xenstat_domain * domain,
458 unsigned int network)
459 {
460 if (domain->networks && network < domain->num_networks)
461 return &(domain->networks[network]);
462 return NULL;
463 }
464
465 /* Get the number of VBDs for a given domain */
xenstat_domain_num_vbds(xenstat_domain * domain)466 unsigned int xenstat_domain_num_vbds(xenstat_domain * domain)
467 {
468 return domain->num_vbds;
469 }
470
471 /* Get the VBD handle to obtain VBD stats */
xenstat_domain_vbd(xenstat_domain * domain,unsigned int vbd)472 xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain,
473 unsigned int vbd)
474 {
475 if (domain->vbds && vbd < domain->num_vbds)
476 return &(domain->vbds[vbd]);
477 return NULL;
478 }
479
480 /*
481 * VCPU functions
482 */
483 /* Collect information about VCPUs */
xenstat_collect_vcpus(xenstat_node * node)484 static int xenstat_collect_vcpus(xenstat_node * node)
485 {
486 unsigned int i, vcpu, inc_index;
487
488 /* Fill in VCPU information */
489 for (i = 0; i < node->num_domains; i+=inc_index) {
490 inc_index = 1; /* default is to increment to next domain */
491
492 node->domains[i].vcpus = malloc(node->domains[i].num_vcpus
493 * sizeof(xenstat_vcpu));
494 if (node->domains[i].vcpus == NULL)
495 return 0;
496
497 for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) {
498 /* FIXME: need to be using a more efficient mechanism*/
499 xc_vcpuinfo_t info;
500
501 if (xc_vcpu_getinfo(node->handle->xc_handle,
502 node->domains[i].id, vcpu, &info) != 0) {
503 if (errno == ENOMEM) {
504 /* fatal error */
505 return 0;
506 }
507 else {
508 /* domain is in transition - remove
509 from list */
510 xenstat_prune_domain(node, i);
511
512 /* remember not to increment index! */
513 inc_index = 0;
514 break;
515 }
516 }
517 else {
518 node->domains[i].vcpus[vcpu].online = info.online;
519 node->domains[i].vcpus[vcpu].ns = info.cpu_time;
520 }
521 }
522 }
523 return 1;
524 }
525
526 /* Free VCPU information */
xenstat_free_vcpus(xenstat_node * node)527 static void xenstat_free_vcpus(xenstat_node * node)
528 {
529 unsigned int i;
530 for (i = 0; i < node->num_domains; i++)
531 free(node->domains[i].vcpus);
532 }
533
534 /* Free VCPU information in handle - nothing to do */
xenstat_uninit_vcpus(xenstat_handle * handle)535 static void xenstat_uninit_vcpus(xenstat_handle * handle)
536 {
537 }
538
539 /* Get VCPU online status */
xenstat_vcpu_online(xenstat_vcpu * vcpu)540 unsigned int xenstat_vcpu_online(xenstat_vcpu * vcpu)
541 {
542 return vcpu->online;
543 }
544
545 /* Get VCPU usage */
xenstat_vcpu_ns(xenstat_vcpu * vcpu)546 unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu)
547 {
548 return vcpu->ns;
549 }
550
551 /*
552 * Network functions
553 */
554
555 /* Free network information */
xenstat_free_networks(xenstat_node * node)556 static void xenstat_free_networks(xenstat_node * node)
557 {
558 unsigned int i;
559 for (i = 0; i < node->num_domains; i++)
560 free(node->domains[i].networks);
561 }
562
563 /* Get the network ID */
xenstat_network_id(xenstat_network * network)564 unsigned int xenstat_network_id(xenstat_network * network)
565 {
566 return network->id;
567 }
568
569 /* Get the number of receive bytes */
xenstat_network_rbytes(xenstat_network * network)570 unsigned long long xenstat_network_rbytes(xenstat_network * network)
571 {
572 return network->rbytes;
573 }
574
575 /* Get the number of receive packets */
xenstat_network_rpackets(xenstat_network * network)576 unsigned long long xenstat_network_rpackets(xenstat_network * network)
577 {
578 return network->rpackets;
579 }
580
581 /* Get the number of receive errors */
xenstat_network_rerrs(xenstat_network * network)582 unsigned long long xenstat_network_rerrs(xenstat_network * network)
583 {
584 return network->rerrs;
585 }
586
587 /* Get the number of receive drops */
xenstat_network_rdrop(xenstat_network * network)588 unsigned long long xenstat_network_rdrop(xenstat_network * network)
589 {
590 return network->rdrop;
591 }
592
593 /* Get the number of transmit bytes */
xenstat_network_tbytes(xenstat_network * network)594 unsigned long long xenstat_network_tbytes(xenstat_network * network)
595 {
596 return network->tbytes;
597 }
598
599 /* Get the number of transmit packets */
xenstat_network_tpackets(xenstat_network * network)600 unsigned long long xenstat_network_tpackets(xenstat_network * network)
601 {
602 return network->tpackets;
603 }
604
605 /* Get the number of transmit errors */
xenstat_network_terrs(xenstat_network * network)606 unsigned long long xenstat_network_terrs(xenstat_network * network)
607 {
608 return network->terrs;
609 }
610
611 /* Get the number of transmit dropped packets */
xenstat_network_tdrop(xenstat_network * network)612 unsigned long long xenstat_network_tdrop(xenstat_network * network)
613 {
614 return network->tdrop;
615 }
616
617 /*
618 * Xen version functions
619 */
620
621 /* Collect Xen version information */
xenstat_collect_xen_version(xenstat_node * node)622 static int xenstat_collect_xen_version(xenstat_node * node)
623 {
624 long vnum = 0;
625 xen_extraversion_t version;
626
627 /* Collect Xen version information if not already collected */
628 if (node->handle->xen_version[0] == '\0') {
629 /* Get the Xen version number and extraversion string */
630 vnum = xc_version(node->handle->xc_handle,
631 XENVER_version, NULL);
632
633 if (vnum < 0)
634 return 0;
635
636 if (xc_version(node->handle->xc_handle, XENVER_extraversion,
637 &version) < 0)
638 return 0;
639 /* Format the version information as a string and store it */
640 snprintf(node->handle->xen_version, VERSION_SIZE, "%ld.%ld%s",
641 ((vnum >> 16) & 0xFFFF), vnum & 0xFFFF, version);
642 }
643
644 return 1;
645 }
646
647 /* Free Xen version information in node - nothing to do */
xenstat_free_xen_version(xenstat_node * node)648 static void xenstat_free_xen_version(xenstat_node * node)
649 {
650 }
651
652 /* Free Xen version information in handle - nothing to do */
xenstat_uninit_xen_version(xenstat_handle * handle)653 static void xenstat_uninit_xen_version(xenstat_handle * handle)
654 {
655 }
656
657 /*
658 * VBD functions
659 */
660
661 /* Save VBD information */
xenstat_save_vbd(xenstat_domain * domain,xenstat_vbd * vbd)662 xenstat_vbd *xenstat_save_vbd(xenstat_domain *domain, xenstat_vbd *vbd)
663 {
664 xenstat_vbd *vbds = domain->vbds;
665
666 domain->num_vbds++;
667 domain->vbds = realloc(domain->vbds,
668 domain->num_vbds *
669 sizeof(xenstat_vbd));
670
671 if (domain->vbds == NULL) {
672 domain->num_vbds = 0;
673 free(vbds);
674 }
675 else {
676 domain->vbds[domain->num_vbds - 1] = *vbd;
677 }
678
679 return domain->vbds;
680 }
681
682 /* Free VBD information */
xenstat_free_vbds(xenstat_node * node)683 static void xenstat_free_vbds(xenstat_node * node)
684 {
685 unsigned int i;
686 for (i = 0; i < node->num_domains; i++)
687 free(node->domains[i].vbds);
688 }
689
690 /* Get the back driver type for Virtual Block Device */
xenstat_vbd_type(xenstat_vbd * vbd)691 unsigned int xenstat_vbd_type(xenstat_vbd * vbd)
692 {
693 return vbd->back_type;
694 }
695
696 /* Get the major number of VBD device */
xenstat_vbd_dev(xenstat_vbd * vbd)697 unsigned int xenstat_vbd_dev(xenstat_vbd * vbd)
698 {
699 return vbd->dev;
700 }
701
702 /* Get the number of OO(Out of) requests */
xenstat_vbd_oo_reqs(xenstat_vbd * vbd)703 unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd)
704 {
705 return vbd->oo_reqs;
706 }
707
708 /* Get the number of READ requests */
xenstat_vbd_rd_reqs(xenstat_vbd * vbd)709 unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd)
710 {
711 return vbd->rd_reqs;
712 }
713
714 /* Get the number of WRITE requests */
xenstat_vbd_wr_reqs(xenstat_vbd * vbd)715 unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd)
716 {
717 return vbd->wr_reqs;
718 }
719
720 /* Get the number of READ sectors */
xenstat_vbd_rd_sects(xenstat_vbd * vbd)721 unsigned long long xenstat_vbd_rd_sects(xenstat_vbd * vbd)
722 {
723 return vbd->rd_sects;
724 }
725
726 /* Get the number of WRITE sectors */
xenstat_vbd_wr_sects(xenstat_vbd * vbd)727 unsigned long long xenstat_vbd_wr_sects(xenstat_vbd * vbd)
728 {
729 return vbd->wr_sects;
730 }
731
732 /*
733 * Tmem functions
734 */
735
xenstat_domain_tmem(xenstat_domain * domain)736 xenstat_tmem *xenstat_domain_tmem(xenstat_domain * domain)
737 {
738 return &domain->tmem_stats;
739 }
740
741 /* Get the current number of ephemeral pages */
xenstat_tmem_curr_eph_pages(xenstat_tmem * tmem)742 unsigned long long xenstat_tmem_curr_eph_pages(xenstat_tmem *tmem)
743 {
744 return tmem->curr_eph_pages;
745 }
746
747 /* Get the number of successful ephemeral gets */
xenstat_tmem_succ_eph_gets(xenstat_tmem * tmem)748 unsigned long long xenstat_tmem_succ_eph_gets(xenstat_tmem *tmem)
749 {
750 return tmem->succ_eph_gets;
751 }
752
753 /* Get the number of successful persistent puts */
xenstat_tmem_succ_pers_puts(xenstat_tmem * tmem)754 unsigned long long xenstat_tmem_succ_pers_puts(xenstat_tmem *tmem)
755 {
756 return tmem->succ_pers_puts;
757 }
758
759 /* Get the number of successful persistent gets */
xenstat_tmem_succ_pers_gets(xenstat_tmem * tmem)760 unsigned long long xenstat_tmem_succ_pers_gets(xenstat_tmem *tmem)
761 {
762 return tmem->succ_pers_gets;
763 }
764
765
xenstat_get_domain_name(xenstat_handle * handle,unsigned int domain_id)766 static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
767 {
768 char path[80];
769
770 snprintf(path, sizeof(path),"/local/domain/%i/name", domain_id);
771
772 return xs_read(handle->xshandle, XBT_NULL, path, NULL);
773 }
774
775 /* Remove specified entry from list of domains */
xenstat_prune_domain(xenstat_node * node,unsigned int entry)776 static void xenstat_prune_domain(xenstat_node *node, unsigned int entry)
777 {
778 /* nothing to do if array is empty or entry is beyond end */
779 if (node->num_domains == 0 || entry >= node->num_domains)
780 return;
781
782 /* decrement count of domains */
783 node->num_domains--;
784
785 /* shift entries following specified entry up by one */
786 if (entry < node->num_domains) {
787 xenstat_domain *domain = &node->domains[entry];
788 memmove(domain,domain+1,(node->num_domains - entry) * sizeof(xenstat_domain) );
789 }
790
791 /* zero out original last entry from node -- not
792 strictly necessary but safer! */
793 memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain));
794 }
795