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
xenstat_get_node(xenstat_handle * handle,unsigned int flags)134 xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
135 {
136 #define DOMAIN_CHUNK_SIZE 256
137 xenstat_node *node;
138 xc_physinfo_t physinfo = { 0 };
139 xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
140 int new_domains;
141 unsigned int i;
142
143 /* Create the node */
144 node = (xenstat_node *) calloc(1, sizeof(xenstat_node));
145 if (node == NULL)
146 return NULL;
147
148 /* Store the handle in the node for later access */
149 node->handle = handle;
150
151 /* Get information about the physical system */
152 if (xc_physinfo(handle->xc_handle, &physinfo) < 0) {
153 free(node);
154 return NULL;
155 }
156
157
158 node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL;
159 node->num_cpus = physinfo.nr_cpus;
160 node->tot_mem = ((unsigned long long)physinfo.total_pages)
161 * handle->page_size;
162 node->free_mem = ((unsigned long long)physinfo.free_pages)
163 * handle->page_size;
164
165 node->freeable_mb = 0;
166 /* malloc(0) is not portable, so allocate a single domain. This will
167 * be resized below. */
168 node->domains = malloc(sizeof(xenstat_domain));
169 if (node->domains == NULL) {
170 free(node);
171 return NULL;
172 }
173
174 node->num_domains = 0;
175 do {
176 xenstat_domain *domain, *tmp;
177
178 new_domains = xc_domain_getinfolist(handle->xc_handle,
179 node->num_domains,
180 DOMAIN_CHUNK_SIZE,
181 domaininfo);
182 if (new_domains < 0)
183 goto err;
184
185 tmp = realloc(node->domains,
186 (node->num_domains + new_domains)
187 * sizeof(xenstat_domain));
188 if (tmp == NULL)
189 goto err;
190
191 node->domains = tmp;
192
193 domain = node->domains + node->num_domains;
194
195 /* zero out newly allocated memory in case error occurs below */
196 memset(domain, 0, new_domains * sizeof(xenstat_domain));
197
198 for (i = 0; i < new_domains; i++) {
199 /* Fill in domain using domaininfo[i] */
200 domain->id = domaininfo[i].domain;
201 domain->name = xenstat_get_domain_name(handle,
202 domain->id);
203 if (domain->name == NULL) {
204 if (errno == ENOMEM) {
205 /* fatal error */
206 xenstat_free_node(node);
207 return NULL;
208 }
209 else {
210 /* failed to get name -- this means the
211 domain is being destroyed so simply
212 ignore this entry */
213 continue;
214 }
215 }
216 domain->state = domaininfo[i].flags;
217 domain->cpu_ns = domaininfo[i].cpu_time;
218 domain->num_vcpus = (domaininfo[i].max_vcpu_id+1);
219 domain->vcpus = NULL;
220 domain->cur_mem =
221 ((unsigned long long)domaininfo[i].tot_pages)
222 * handle->page_size;
223 domain->max_mem =
224 domaininfo[i].max_pages == UINT_MAX
225 ? (unsigned long long)-1
226 : (unsigned long long)(domaininfo[i].max_pages
227 * handle->page_size);
228 domain->ssid = domaininfo[i].ssidref;
229 domain->num_networks = 0;
230 domain->networks = NULL;
231 domain->num_vbds = 0;
232 domain->vbds = NULL;
233
234 domain++;
235 node->num_domains++;
236 }
237 } while (new_domains == DOMAIN_CHUNK_SIZE);
238
239
240 /* Run all the extra data collectors requested */
241 node->flags = 0;
242 for (i = 0; i < NUM_COLLECTORS; i++) {
243 if ((flags & collectors[i].flag) == collectors[i].flag) {
244 node->flags |= collectors[i].flag;
245 if(collectors[i].collect(node) == 0) {
246 xenstat_free_node(node);
247 return NULL;
248 }
249 }
250 }
251
252 return node;
253 err:
254 free(node->domains);
255 free(node);
256 return NULL;
257 }
258
xenstat_free_node(xenstat_node * node)259 void xenstat_free_node(xenstat_node * node)
260 {
261 int i;
262
263 if (node) {
264 if (node->domains) {
265 for (i = 0; i < node->num_domains; i++)
266 free(node->domains[i].name);
267
268 for (i = 0; i < NUM_COLLECTORS; i++)
269 if((node->flags & collectors[i].flag)
270 == collectors[i].flag)
271 collectors[i].free(node);
272 free(node->domains);
273 }
274 free(node);
275 }
276 }
277
xenstat_node_domain(xenstat_node * node,unsigned int domid)278 xenstat_domain *xenstat_node_domain(xenstat_node * node, unsigned int domid)
279 {
280 unsigned int i;
281
282 /* FIXME: binary search */
283 /* Find the appropriate domain entry in the node struct. */
284 for (i = 0; i < node->num_domains; i++) {
285 if (node->domains[i].id == domid)
286 return &(node->domains[i]);
287 }
288 return NULL;
289 }
290
xenstat_node_domain_by_index(xenstat_node * node,unsigned int index)291 xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node,
292 unsigned int index)
293 {
294 if (index < node->num_domains)
295 return &(node->domains[index]);
296 return NULL;
297 }
298
xenstat_node_xen_version(xenstat_node * node)299 const char *xenstat_node_xen_version(xenstat_node * node)
300 {
301 return node->handle->xen_version;
302 }
303
xenstat_node_tot_mem(xenstat_node * node)304 unsigned long long xenstat_node_tot_mem(xenstat_node * node)
305 {
306 return node->tot_mem;
307 }
308
xenstat_node_free_mem(xenstat_node * node)309 unsigned long long xenstat_node_free_mem(xenstat_node * node)
310 {
311 return node->free_mem;
312 }
313
xenstat_node_freeable_mb(xenstat_node * node)314 long xenstat_node_freeable_mb(xenstat_node * node)
315 {
316 return node->freeable_mb;
317 }
318
xenstat_node_num_domains(xenstat_node * node)319 unsigned int xenstat_node_num_domains(xenstat_node * node)
320 {
321 return node->num_domains;
322 }
323
xenstat_node_num_cpus(xenstat_node * node)324 unsigned int xenstat_node_num_cpus(xenstat_node * node)
325 {
326 return node->num_cpus;
327 }
328
329 /* Get information about the CPU speed */
xenstat_node_cpu_hz(xenstat_node * node)330 unsigned long long xenstat_node_cpu_hz(xenstat_node * node)
331 {
332 return node->cpu_hz;
333 }
334
335 /* Get the domain ID for this domain */
xenstat_domain_id(xenstat_domain * domain)336 unsigned xenstat_domain_id(xenstat_domain * domain)
337 {
338 return domain->id;
339 }
340
341 /* Get the domain name for the domain */
xenstat_domain_name(xenstat_domain * domain)342 char *xenstat_domain_name(xenstat_domain * domain)
343 {
344 return domain->name;
345 }
346
347 /* Get information about how much CPU time has been used */
xenstat_domain_cpu_ns(xenstat_domain * domain)348 unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain)
349 {
350 return domain->cpu_ns;
351 }
352
353 /* Find the number of VCPUs for a domain */
xenstat_domain_num_vcpus(xenstat_domain * domain)354 unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain)
355 {
356 return domain->num_vcpus;
357 }
358
xenstat_domain_vcpu(xenstat_domain * domain,unsigned int vcpu)359 xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, unsigned int vcpu)
360 {
361 if (vcpu < domain->num_vcpus)
362 return &(domain->vcpus[vcpu]);
363 return NULL;
364 }
365
366 /* Find the current memory reservation for this domain */
xenstat_domain_cur_mem(xenstat_domain * domain)367 unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain)
368 {
369 return domain->cur_mem;
370 }
371
372 /* Find the maximum memory reservation for this domain */
xenstat_domain_max_mem(xenstat_domain * domain)373 unsigned long long xenstat_domain_max_mem(xenstat_domain * domain)
374 {
375 return domain->max_mem;
376 }
377
378 /* Find the domain's SSID */
xenstat_domain_ssid(xenstat_domain * domain)379 unsigned int xenstat_domain_ssid(xenstat_domain * domain)
380 {
381 return domain->ssid;
382 }
383
384 /* Get domain states */
xenstat_domain_dying(xenstat_domain * domain)385 unsigned int xenstat_domain_dying(xenstat_domain * domain)
386 {
387 return (domain->state & XEN_DOMINF_dying) == XEN_DOMINF_dying;
388 }
389
xenstat_domain_crashed(xenstat_domain * domain)390 unsigned int xenstat_domain_crashed(xenstat_domain * domain)
391 {
392 return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
393 && (((domain->state >> XEN_DOMINF_shutdownshift)
394 & XEN_DOMINF_shutdownmask) == SHUTDOWN_crash);
395 }
396
xenstat_domain_shutdown(xenstat_domain * domain)397 unsigned int xenstat_domain_shutdown(xenstat_domain * domain)
398 {
399 return ((domain->state & XEN_DOMINF_shutdown) == XEN_DOMINF_shutdown)
400 && (((domain->state >> XEN_DOMINF_shutdownshift)
401 & XEN_DOMINF_shutdownmask) != SHUTDOWN_crash);
402 }
403
xenstat_domain_paused(xenstat_domain * domain)404 unsigned int xenstat_domain_paused(xenstat_domain * domain)
405 {
406 return (domain->state & XEN_DOMINF_paused) == XEN_DOMINF_paused;
407 }
408
xenstat_domain_blocked(xenstat_domain * domain)409 unsigned int xenstat_domain_blocked(xenstat_domain * domain)
410 {
411 return (domain->state & XEN_DOMINF_blocked) == XEN_DOMINF_blocked;
412 }
413
xenstat_domain_running(xenstat_domain * domain)414 unsigned int xenstat_domain_running(xenstat_domain * domain)
415 {
416 return (domain->state & XEN_DOMINF_running) == XEN_DOMINF_running;
417 }
418
419 /* Get the number of networks for a given domain */
xenstat_domain_num_networks(xenstat_domain * domain)420 unsigned int xenstat_domain_num_networks(xenstat_domain * domain)
421 {
422 return domain->num_networks;
423 }
424
425 /* Get the network handle to obtain network stats */
xenstat_domain_network(xenstat_domain * domain,unsigned int network)426 xenstat_network *xenstat_domain_network(xenstat_domain * domain,
427 unsigned int network)
428 {
429 if (domain->networks && network < domain->num_networks)
430 return &(domain->networks[network]);
431 return NULL;
432 }
433
434 /* Get the number of VBDs for a given domain */
xenstat_domain_num_vbds(xenstat_domain * domain)435 unsigned int xenstat_domain_num_vbds(xenstat_domain * domain)
436 {
437 return domain->num_vbds;
438 }
439
440 /* Get the VBD handle to obtain VBD stats */
xenstat_domain_vbd(xenstat_domain * domain,unsigned int vbd)441 xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain,
442 unsigned int vbd)
443 {
444 if (domain->vbds && vbd < domain->num_vbds)
445 return &(domain->vbds[vbd]);
446 return NULL;
447 }
448
449 /*
450 * VCPU functions
451 */
452 /* Collect information about VCPUs */
xenstat_collect_vcpus(xenstat_node * node)453 static int xenstat_collect_vcpus(xenstat_node * node)
454 {
455 unsigned int i, vcpu, inc_index;
456
457 /* Fill in VCPU information */
458 for (i = 0; i < node->num_domains; i+=inc_index) {
459 inc_index = 1; /* default is to increment to next domain */
460
461 node->domains[i].vcpus = malloc(node->domains[i].num_vcpus
462 * sizeof(xenstat_vcpu));
463 if (node->domains[i].vcpus == NULL)
464 return 0;
465
466 for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) {
467 /* FIXME: need to be using a more efficient mechanism*/
468 xc_vcpuinfo_t info;
469
470 if (xc_vcpu_getinfo(node->handle->xc_handle,
471 node->domains[i].id, vcpu, &info) != 0) {
472 if (errno == ENOMEM) {
473 /* fatal error */
474 return 0;
475 }
476 else {
477 /* domain is in transition - remove
478 from list */
479 xenstat_prune_domain(node, i);
480
481 /* remember not to increment index! */
482 inc_index = 0;
483 break;
484 }
485 }
486 else {
487 node->domains[i].vcpus[vcpu].online = info.online;
488 node->domains[i].vcpus[vcpu].ns = info.cpu_time;
489 }
490 }
491 }
492 return 1;
493 }
494
495 /* Free VCPU information */
xenstat_free_vcpus(xenstat_node * node)496 static void xenstat_free_vcpus(xenstat_node * node)
497 {
498 unsigned int i;
499 for (i = 0; i < node->num_domains; i++)
500 free(node->domains[i].vcpus);
501 }
502
503 /* Free VCPU information in handle - nothing to do */
xenstat_uninit_vcpus(xenstat_handle * handle)504 static void xenstat_uninit_vcpus(xenstat_handle * handle)
505 {
506 }
507
508 /* Get VCPU online status */
xenstat_vcpu_online(xenstat_vcpu * vcpu)509 unsigned int xenstat_vcpu_online(xenstat_vcpu * vcpu)
510 {
511 return vcpu->online;
512 }
513
514 /* Get VCPU usage */
xenstat_vcpu_ns(xenstat_vcpu * vcpu)515 unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu)
516 {
517 return vcpu->ns;
518 }
519
520 /*
521 * Network functions
522 */
523
524 /* Free network information */
xenstat_free_networks(xenstat_node * node)525 static void xenstat_free_networks(xenstat_node * node)
526 {
527 unsigned int i;
528 for (i = 0; i < node->num_domains; i++)
529 free(node->domains[i].networks);
530 }
531
532 /* Get the network ID */
xenstat_network_id(xenstat_network * network)533 unsigned int xenstat_network_id(xenstat_network * network)
534 {
535 return network->id;
536 }
537
538 /* Get the number of receive bytes */
xenstat_network_rbytes(xenstat_network * network)539 unsigned long long xenstat_network_rbytes(xenstat_network * network)
540 {
541 return network->rbytes;
542 }
543
544 /* Get the number of receive packets */
xenstat_network_rpackets(xenstat_network * network)545 unsigned long long xenstat_network_rpackets(xenstat_network * network)
546 {
547 return network->rpackets;
548 }
549
550 /* Get the number of receive errors */
xenstat_network_rerrs(xenstat_network * network)551 unsigned long long xenstat_network_rerrs(xenstat_network * network)
552 {
553 return network->rerrs;
554 }
555
556 /* Get the number of receive drops */
xenstat_network_rdrop(xenstat_network * network)557 unsigned long long xenstat_network_rdrop(xenstat_network * network)
558 {
559 return network->rdrop;
560 }
561
562 /* Get the number of transmit bytes */
xenstat_network_tbytes(xenstat_network * network)563 unsigned long long xenstat_network_tbytes(xenstat_network * network)
564 {
565 return network->tbytes;
566 }
567
568 /* Get the number of transmit packets */
xenstat_network_tpackets(xenstat_network * network)569 unsigned long long xenstat_network_tpackets(xenstat_network * network)
570 {
571 return network->tpackets;
572 }
573
574 /* Get the number of transmit errors */
xenstat_network_terrs(xenstat_network * network)575 unsigned long long xenstat_network_terrs(xenstat_network * network)
576 {
577 return network->terrs;
578 }
579
580 /* Get the number of transmit dropped packets */
xenstat_network_tdrop(xenstat_network * network)581 unsigned long long xenstat_network_tdrop(xenstat_network * network)
582 {
583 return network->tdrop;
584 }
585
586 /*
587 * Xen version functions
588 */
589
590 /* Collect Xen version information */
xenstat_collect_xen_version(xenstat_node * node)591 static int xenstat_collect_xen_version(xenstat_node * node)
592 {
593 long vnum = 0;
594 xen_extraversion_t version;
595
596 /* Collect Xen version information if not already collected */
597 if (node->handle->xen_version[0] == '\0') {
598 /* Get the Xen version number and extraversion string */
599 vnum = xc_version(node->handle->xc_handle,
600 XENVER_version, NULL);
601
602 if (vnum < 0)
603 return 0;
604
605 if (xc_version(node->handle->xc_handle, XENVER_extraversion,
606 &version) < 0)
607 return 0;
608 /* Format the version information as a string and store it */
609 snprintf(node->handle->xen_version, VERSION_SIZE, "%ld.%ld%s",
610 ((vnum >> 16) & 0xFFFF), vnum & 0xFFFF, version);
611 }
612
613 return 1;
614 }
615
616 /* Free Xen version information in node - nothing to do */
xenstat_free_xen_version(xenstat_node * node)617 static void xenstat_free_xen_version(xenstat_node * node)
618 {
619 }
620
621 /* Free Xen version information in handle - nothing to do */
xenstat_uninit_xen_version(xenstat_handle * handle)622 static void xenstat_uninit_xen_version(xenstat_handle * handle)
623 {
624 }
625
626 /*
627 * VBD functions
628 */
629
630 /* Save VBD information */
xenstat_save_vbd(xenstat_domain * domain,xenstat_vbd * vbd)631 xenstat_vbd *xenstat_save_vbd(xenstat_domain *domain, xenstat_vbd *vbd)
632 {
633 xenstat_vbd *vbds = domain->vbds;
634
635 domain->num_vbds++;
636 domain->vbds = realloc(domain->vbds,
637 domain->num_vbds *
638 sizeof(xenstat_vbd));
639
640 if (domain->vbds == NULL) {
641 domain->num_vbds = 0;
642 free(vbds);
643 }
644 else {
645 domain->vbds[domain->num_vbds - 1] = *vbd;
646 }
647
648 return domain->vbds;
649 }
650
651 /* Free VBD information */
xenstat_free_vbds(xenstat_node * node)652 static void xenstat_free_vbds(xenstat_node * node)
653 {
654 unsigned int i;
655 for (i = 0; i < node->num_domains; i++)
656 free(node->domains[i].vbds);
657 }
658
659 /* Get the back driver type for Virtual Block Device */
xenstat_vbd_type(xenstat_vbd * vbd)660 unsigned int xenstat_vbd_type(xenstat_vbd * vbd)
661 {
662 return vbd->back_type;
663 }
664
665 /* Get the major number of VBD device */
xenstat_vbd_dev(xenstat_vbd * vbd)666 unsigned int xenstat_vbd_dev(xenstat_vbd * vbd)
667 {
668 return vbd->dev;
669 }
670
671 /* Get the number of OO(Out of) requests */
xenstat_vbd_oo_reqs(xenstat_vbd * vbd)672 unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd)
673 {
674 return vbd->oo_reqs;
675 }
676
677 /* Get the number of READ requests */
xenstat_vbd_rd_reqs(xenstat_vbd * vbd)678 unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd)
679 {
680 return vbd->rd_reqs;
681 }
682
683 /* Get the number of WRITE requests */
xenstat_vbd_wr_reqs(xenstat_vbd * vbd)684 unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd)
685 {
686 return vbd->wr_reqs;
687 }
688
689 /* Get the number of READ sectors */
xenstat_vbd_rd_sects(xenstat_vbd * vbd)690 unsigned long long xenstat_vbd_rd_sects(xenstat_vbd * vbd)
691 {
692 return vbd->rd_sects;
693 }
694
695 /* Get the number of WRITE sectors */
xenstat_vbd_wr_sects(xenstat_vbd * vbd)696 unsigned long long xenstat_vbd_wr_sects(xenstat_vbd * vbd)
697 {
698 return vbd->wr_sects;
699 }
700
701 /* Returns error while getting stats (1 if error happened, 0 otherwise) */
xenstat_vbd_error(xenstat_vbd * vbd)702 bool xenstat_vbd_error(xenstat_vbd * vbd)
703 {
704 return vbd->error;
705 }
706
xenstat_get_domain_name(xenstat_handle * handle,unsigned int domain_id)707 static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
708 {
709 char path[80];
710
711 snprintf(path, sizeof(path),"/local/domain/%i/name", domain_id);
712
713 return xs_read(handle->xshandle, XBT_NULL, path, NULL);
714 }
715
716 /* Remove specified entry from list of domains */
xenstat_prune_domain(xenstat_node * node,unsigned int entry)717 static void xenstat_prune_domain(xenstat_node *node, unsigned int entry)
718 {
719 /* nothing to do if array is empty or entry is beyond end */
720 if (node->num_domains == 0 || entry >= node->num_domains)
721 return;
722
723 /* decrement count of domains */
724 node->num_domains--;
725
726 /* shift entries following specified entry up by one */
727 if (entry < node->num_domains) {
728 xenstat_domain *domain = &node->domains[entry];
729 memmove(domain,domain+1,(node->num_domains - entry) * sizeof(xenstat_domain) );
730 }
731
732 /* zero out original last entry from node -- not
733 strictly necessary but safer! */
734 memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain));
735 }
736