direct-io.hg

view tools/xenstat/libxenstat/src/xenstat.c @ 10567:ffbdd113c74b

Remove use of unlikely -- it's not defined on all systems.

Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
author chris@kneesaa.uk.xensource.com
date Fri Jun 30 14:15:12 2006 +0100 (2006-06-30)
parents 3edac4400459
children 7654157278f1
line source
1 /* libxenstat: statistics-collection library for Xen
2 * Copyright (C) International Business Machines Corp., 2005
3 * Authors: Josh Triplett <josht@us.ibm.com>
4 * Judy Fischbach <jfisch@us.ibm.com>
5 * David Hendricks <dhendrix@us.ibm.com>
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 */
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <linux/compiler.h>
24 #include <fcntl.h>
25 #include <dirent.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <xs.h>
29 #include "xenstat.h"
31 #include "xenctrl.h"
33 /*
34 * Types
35 */
36 #define SHORT_ASC_LEN 5 /* length of 65535 */
37 #define VERSION_SIZE (2 * SHORT_ASC_LEN + 1 + sizeof(xen_extraversion_t) + 1)
39 struct xenstat_handle {
40 int xc_handle;
41 struct xs_handle *xshandle; /* xenstore handle */
42 int page_size;
43 FILE *procnetdev;
44 DIR *sysfsvbd;
45 char xen_version[VERSION_SIZE]; /* xen version running on this node */
46 };
48 struct xenstat_node {
49 xenstat_handle *handle;
50 unsigned int flags;
51 unsigned long long cpu_hz;
52 unsigned int num_cpus;
53 unsigned long long tot_mem;
54 unsigned long long free_mem;
55 unsigned int num_domains;
56 xenstat_domain *domains; /* Array of length num_domains */
57 };
59 struct xenstat_domain {
60 unsigned int id;
61 char *name;
62 unsigned int state;
63 unsigned long long cpu_ns;
64 unsigned int num_vcpus; /* No. vcpus configured for domain */
65 xenstat_vcpu *vcpus; /* Array of length num_vcpus */
66 unsigned long long cur_mem; /* Current memory reservation */
67 unsigned long long max_mem; /* Total memory allowed */
68 unsigned int ssid;
69 unsigned int num_networks;
70 xenstat_network *networks; /* Array of length num_networks */
71 unsigned int num_vbds;
72 xenstat_vbd *vbds;
73 };
75 struct xenstat_vcpu {
76 unsigned int online;
77 unsigned long long ns;
78 };
80 struct xenstat_network {
81 unsigned int id;
82 /* Received */
83 unsigned long long rbytes;
84 unsigned long long rpackets;
85 unsigned long long rerrs;
86 unsigned long long rdrop;
87 /* Transmitted */
88 unsigned long long tbytes;
89 unsigned long long tpackets;
90 unsigned long long terrs;
91 unsigned long long tdrop;
92 };
94 struct xenstat_vbd {
95 unsigned int dev;
96 unsigned long long oo_reqs;
97 unsigned long long rd_reqs;
98 unsigned long long wr_reqs;
99 };
100 #define SYSFS_VBD_PATH "/sys/devices/xen-backend/"
103 /*
104 * Data-collection types
105 */
106 /* Called to collect the information for the node and all the domains on
107 * it. When called, the domain information has already been collected. */
108 typedef int (*xenstat_collect_func)(xenstat_node * node);
109 /* Called to free the information collected by the collect function. The free
110 * function will only be called on a xenstat_node if that node includes
111 * information collected by the corresponding collector. */
112 typedef void (*xenstat_free_func)(xenstat_node * node);
113 /* Called to free any information stored in the handle. Note the lack of a
114 * matching init function; the collect functions should initialize on first
115 * use. Also, the uninit function must handle the case that the collector has
116 * never been initialized. */
117 typedef void (*xenstat_uninit_func)(xenstat_handle * handle);
118 typedef struct xenstat_collector {
119 unsigned int flag;
120 xenstat_collect_func collect;
121 xenstat_free_func free;
122 xenstat_uninit_func uninit;
123 } xenstat_collector;
125 static int xenstat_collect_vcpus(xenstat_node * node);
126 static int xenstat_collect_networks(xenstat_node * node);
127 static int xenstat_collect_xen_version(xenstat_node * node);
128 static int xenstat_collect_vbds(xenstat_node * node);
129 static void xenstat_free_vcpus(xenstat_node * node);
130 static void xenstat_free_networks(xenstat_node * node);
131 static void xenstat_free_xen_version(xenstat_node * node);
132 static void xenstat_free_vbds(xenstat_node * node);
133 static void xenstat_uninit_vcpus(xenstat_handle * handle);
134 static void xenstat_uninit_networks(xenstat_handle * handle);
135 static void xenstat_uninit_xen_version(xenstat_handle * handle);
136 static void xenstat_uninit_vbds(xenstat_handle * handle);
137 static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
139 static xenstat_collector collectors[] = {
140 { XENSTAT_VCPU, xenstat_collect_vcpus,
141 xenstat_free_vcpus, xenstat_uninit_vcpus },
142 { XENSTAT_NETWORK, xenstat_collect_networks,
143 xenstat_free_networks, xenstat_uninit_networks },
144 { XENSTAT_XEN_VERSION, xenstat_collect_xen_version,
145 xenstat_free_xen_version, xenstat_uninit_xen_version },
146 { XENSTAT_VBD, xenstat_collect_vbds,
147 xenstat_free_vbds, xenstat_uninit_vbds }
148 };
150 #define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector))
152 /*
153 * libxenstat API
154 */
155 xenstat_handle *xenstat_init(void)
156 {
157 xenstat_handle *handle;
159 handle = (xenstat_handle *) calloc(1, sizeof(xenstat_handle));
160 if (handle == NULL)
161 return NULL;
163 #if defined(PAGESIZE)
164 handle->page_size = PAGESIZE;
165 #elif defined(PAGE_SIZE)
166 handle->page_size = PAGE_SIZE;
167 #else
168 handle->page_size = sysconf(_SC_PAGE_SIZE);
169 if (handle->page_size < 0) {
170 perror("Failed to retrieve page size.");
171 free(handle);
172 return NULL;
173 }
174 #endif
176 handle->xc_handle = xc_interface_open();
177 if (handle->xc_handle == -1) {
178 perror("xc_interface_open");
179 free(handle);
180 return NULL;
181 }
183 handle->xshandle = xs_daemon_open_readonly(); /* open handle to xenstore*/
184 if (handle->xshandle == NULL) {
185 perror("unable to open xenstore\n");
186 xc_interface_close(handle->xc_handle);
187 free(handle);
188 return NULL;
189 }
191 return handle;
192 }
194 void xenstat_uninit(xenstat_handle * handle)
195 {
196 unsigned int i;
197 if (handle) {
198 for (i = 0; i < NUM_COLLECTORS; i++)
199 collectors[i].uninit(handle);
200 xc_interface_close(handle->xc_handle);
201 xs_daemon_close(handle->xshandle);
202 free(handle);
203 }
204 }
206 xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
207 {
208 #define DOMAIN_CHUNK_SIZE 256
209 xenstat_node *node;
210 dom0_physinfo_t physinfo;
211 dom0_getdomaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
212 unsigned int num_domains, new_domains;
213 unsigned int i;
215 /* Create the node */
216 node = (xenstat_node *) calloc(1, sizeof(xenstat_node));
217 if (node == NULL)
218 return NULL;
220 /* Store the handle in the node for later access */
221 node->handle = handle;
223 /* Get information about the physical system */
224 if (xc_physinfo(handle->xc_handle, &physinfo) < 0) {
225 free(node);
226 return NULL;
227 }
229 node->cpu_hz = ((unsigned long long)physinfo.cpu_khz) * 1000ULL;
230 node->num_cpus =
231 (physinfo.threads_per_core * physinfo.cores_per_socket *
232 physinfo.sockets_per_node * physinfo.nr_nodes);
233 node->tot_mem = ((unsigned long long)physinfo.total_pages)
234 * handle->page_size;
235 node->free_mem = ((unsigned long long)physinfo.free_pages)
236 * handle->page_size;
238 /* malloc(0) is not portable, so allocate a single domain. This will
239 * be resized below. */
240 node->domains = malloc(sizeof(xenstat_domain));
241 if (node->domains == NULL) {
242 free(node);
243 return NULL;
244 }
246 num_domains = 0;
247 do {
248 xenstat_domain *domain, *tmp;
250 new_domains = xc_domain_getinfolist(handle->xc_handle,
251 num_domains, DOMAIN_CHUNK_SIZE, domaininfo);
253 tmp = realloc(node->domains,
254 (num_domains + new_domains)
255 * sizeof(xenstat_domain));
256 if (tmp == NULL) {
257 free(node->domains);
258 free(node);
259 return NULL;
260 }
261 node->domains = tmp;
263 domain = node->domains + num_domains;
265 for (i = 0; i < new_domains; i++) {
266 /* Fill in domain using domaininfo[i] */
267 domain->id = domaininfo[i].domain;
268 domain->name = xenstat_get_domain_name(handle, domaininfo[i].domain);
269 domain->state = domaininfo[i].flags;
270 domain->cpu_ns = domaininfo[i].cpu_time;
271 domain->num_vcpus = (domaininfo[i].max_vcpu_id+1);
272 domain->vcpus = NULL;
273 domain->cur_mem =
274 ((unsigned long long)domaininfo[i].tot_pages)
275 * handle->page_size;
276 domain->max_mem =
277 domaininfo[i].max_pages == UINT_MAX
278 ? (unsigned long long)-1
279 : (unsigned long long)(domaininfo[i].max_pages
280 * handle->page_size);
281 domain->ssid = domaininfo[i].ssidref;
282 domain->num_networks = 0;
283 domain->networks = NULL;
284 domain->num_vbds = 0;
285 domain->vbds = NULL;
287 domain++;
288 }
289 num_domains += new_domains;
290 } while (new_domains == DOMAIN_CHUNK_SIZE);
291 node->num_domains = num_domains;
293 /* Run all the extra data collectors requested */
294 node->flags = 0;
295 for (i = 0; i < NUM_COLLECTORS; i++) {
296 if ((flags & collectors[i].flag) == collectors[i].flag) {
297 node->flags |= collectors[i].flag;
298 if(collectors[i].collect(node) == 0) {
299 xenstat_free_node(node);
300 return NULL;
301 }
302 }
303 }
305 return node;
306 }
308 void xenstat_free_node(xenstat_node * node)
309 {
310 int i;
312 if (node) {
313 if (node->domains) {
314 for (i = 0; i < node->num_domains; i++)
315 free(node->domains[i].name);
317 for (i = 0; i < NUM_COLLECTORS; i++)
318 if((node->flags & collectors[i].flag)
319 == collectors[i].flag)
320 collectors[i].free(node);
321 free(node->domains);
322 }
323 free(node);
324 }
325 }
327 xenstat_domain *xenstat_node_domain(xenstat_node * node, unsigned int domid)
328 {
329 unsigned int i;
331 /* FIXME: binary search */
332 /* Find the appropriate domain entry in the node struct. */
333 for (i = 0; i < node->num_domains; i++) {
334 if (node->domains[i].id == domid)
335 return &(node->domains[i]);
336 }
337 return NULL;
338 }
340 xenstat_domain *xenstat_node_domain_by_index(xenstat_node * node,
341 unsigned int index)
342 {
343 if (0 <= index && index < node->num_domains)
344 return &(node->domains[index]);
345 return NULL;
346 }
348 const char *xenstat_node_xen_version(xenstat_node * node)
349 {
350 return node->handle->xen_version;
351 }
353 unsigned long long xenstat_node_tot_mem(xenstat_node * node)
354 {
355 return node->tot_mem;
356 }
358 unsigned long long xenstat_node_free_mem(xenstat_node * node)
359 {
360 return node->free_mem;
361 }
363 unsigned int xenstat_node_num_domains(xenstat_node * node)
364 {
365 return node->num_domains;
366 }
368 unsigned int xenstat_node_num_cpus(xenstat_node * node)
369 {
370 return node->num_cpus;
371 }
373 /* Get information about the CPU speed */
374 unsigned long long xenstat_node_cpu_hz(xenstat_node * node)
375 {
376 return node->cpu_hz;
377 }
379 /* Get the domain ID for this domain */
380 unsigned xenstat_domain_id(xenstat_domain * domain)
381 {
382 return domain->id;
383 }
385 /* Get the domain name for the domain */
386 char *xenstat_domain_name(xenstat_domain * domain)
387 {
388 return domain->name;
389 }
391 /* Get information about how much CPU time has been used */
392 unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain)
393 {
394 return domain->cpu_ns;
395 }
397 /* Find the number of VCPUs for a domain */
398 unsigned int xenstat_domain_num_vcpus(xenstat_domain * domain)
399 {
400 return domain->num_vcpus;
401 }
403 xenstat_vcpu *xenstat_domain_vcpu(xenstat_domain * domain, unsigned int vcpu)
404 {
405 if (0 <= vcpu && vcpu < domain->num_vcpus)
406 return &(domain->vcpus[vcpu]);
407 return NULL;
408 }
410 /* Find the current memory reservation for this domain */
411 unsigned long long xenstat_domain_cur_mem(xenstat_domain * domain)
412 {
413 return domain->cur_mem;
414 }
416 /* Find the maximum memory reservation for this domain */
417 unsigned long long xenstat_domain_max_mem(xenstat_domain * domain)
418 {
419 return domain->max_mem;
420 }
422 /* Find the domain's SSID */
423 unsigned int xenstat_domain_ssid(xenstat_domain * domain)
424 {
425 return domain->ssid;
426 }
428 /* Get domain states */
429 unsigned int xenstat_domain_dying(xenstat_domain * domain)
430 {
431 return (domain->state & DOMFLAGS_DYING) == DOMFLAGS_DYING;
432 }
434 unsigned int xenstat_domain_crashed(xenstat_domain * domain)
435 {
436 return ((domain->state & DOMFLAGS_SHUTDOWN) == DOMFLAGS_SHUTDOWN)
437 && (((domain->state >> DOMFLAGS_SHUTDOWNSHIFT)
438 & DOMFLAGS_SHUTDOWNMASK) == SHUTDOWN_crash);
439 }
441 unsigned int xenstat_domain_shutdown(xenstat_domain * domain)
442 {
443 return ((domain->state & DOMFLAGS_SHUTDOWN) == DOMFLAGS_SHUTDOWN)
444 && (((domain->state >> DOMFLAGS_SHUTDOWNSHIFT)
445 & DOMFLAGS_SHUTDOWNMASK) != SHUTDOWN_crash);
446 }
448 unsigned int xenstat_domain_paused(xenstat_domain * domain)
449 {
450 return (domain->state & DOMFLAGS_PAUSED) == DOMFLAGS_PAUSED;
451 }
453 unsigned int xenstat_domain_blocked(xenstat_domain * domain)
454 {
455 return (domain->state & DOMFLAGS_BLOCKED) == DOMFLAGS_BLOCKED;
456 }
458 unsigned int xenstat_domain_running(xenstat_domain * domain)
459 {
460 return (domain->state & DOMFLAGS_RUNNING) == DOMFLAGS_RUNNING;
461 }
463 /* Get the number of networks for a given domain */
464 unsigned int xenstat_domain_num_networks(xenstat_domain * domain)
465 {
466 return domain->num_networks;
467 }
469 /* Get the network handle to obtain network stats */
470 xenstat_network *xenstat_domain_network(xenstat_domain * domain,
471 unsigned int network)
472 {
473 if (domain->networks && 0 <= network && network < domain->num_networks)
474 return &(domain->networks[network]);
475 return NULL;
476 }
478 /* Get the number of VBDs for a given domain */
479 unsigned int xenstat_domain_num_vbds(xenstat_domain * domain)
480 {
481 return domain->num_vbds;
482 }
484 /* Get the VBD handle to obtain VBD stats */
485 xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain,
486 unsigned int vbd)
487 {
488 if (domain->vbds && 0 <= vbd && vbd < domain->num_vbds)
489 return &(domain->vbds[vbd]);
490 return NULL;
491 }
493 /*
494 * VCPU functions
495 */
496 /* Collect information about VCPUs */
497 static int xenstat_collect_vcpus(xenstat_node * node)
498 {
499 unsigned int i, vcpu;
501 /* Fill in VCPU information */
502 for (i = 0; i < node->num_domains; i++) {
503 node->domains[i].vcpus = malloc(node->domains[i].num_vcpus
504 * sizeof(xenstat_vcpu));
505 if (node->domains[i].vcpus == NULL)
506 return 0;
508 for (vcpu = 0; vcpu < node->domains[i].num_vcpus; vcpu++) {
509 /* FIXME: need to be using a more efficient mechanism*/
510 dom0_getvcpuinfo_t info;
512 if (xc_vcpu_getinfo(node->handle->xc_handle,
513 node->domains[i].id, vcpu, &info) != 0)
514 return 0;
516 node->domains[i].vcpus[vcpu].online = info.online;
517 node->domains[i].vcpus[vcpu].ns = info.cpu_time;
518 }
519 }
520 return 1;
521 }
523 /* Free VCPU information */
524 static void xenstat_free_vcpus(xenstat_node * node)
525 {
526 unsigned int i;
527 for (i = 0; i < node->num_domains; i++)
528 free(node->domains[i].vcpus);
529 }
531 /* Free VCPU information in handle - nothing to do */
532 static void xenstat_uninit_vcpus(xenstat_handle * handle)
533 {
534 }
536 /* Get VCPU online status */
537 unsigned int xenstat_vcpu_online(xenstat_vcpu * vcpu)
538 {
539 return vcpu->online;
540 }
542 /* Get VCPU usage */
543 unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu)
544 {
545 return vcpu->ns;
546 }
548 /*
549 * Network functions
550 */
552 /* Expected format of /proc/net/dev */
553 static const char PROCNETDEV_HEADER[] =
554 "Inter-| Receive |"
555 " Transmit\n"
556 " face |bytes packets errs drop fifo frame compressed multicast|"
557 "bytes packets errs drop fifo colls carrier compressed\n";
559 /* Collect information about networks */
560 static int xenstat_collect_networks(xenstat_node * node)
561 {
562 /* Open and validate /proc/net/dev if we haven't already */
563 if (node->handle->procnetdev == NULL) {
564 char header[sizeof(PROCNETDEV_HEADER)];
565 node->handle->procnetdev = fopen("/proc/net/dev", "r");
566 if (node->handle->procnetdev == NULL) {
567 perror("Error opening /proc/net/dev");
568 return 0;
569 }
571 /* Validate the format of /proc/net/dev */
572 if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1,
573 node->handle->procnetdev) != 1) {
574 perror("Error reading /proc/net/dev header");
575 return 0;
576 }
577 header[sizeof(PROCNETDEV_HEADER) - 1] = '\0';
578 if (strcmp(header, PROCNETDEV_HEADER) != 0) {
579 fprintf(stderr,
580 "Unexpected /proc/net/dev format\n");
581 return 0;
582 }
583 }
585 /* Fill in networks */
586 /* FIXME: optimize this */
587 fseek(node->handle->procnetdev, sizeof(PROCNETDEV_HEADER) - 1,
588 SEEK_SET);
589 while (1) {
590 xenstat_domain *domain;
591 xenstat_network net;
592 unsigned int domid;
593 int ret = fscanf(node->handle->procnetdev,
594 "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u"
595 "%llu%llu%llu%llu%*u%*u%*u%*u\n",
596 &domid, &net.id,
597 &net.tbytes, &net.tpackets, &net.terrs,
598 &net.tdrop,
599 &net.rbytes, &net.rpackets, &net.rerrs,
600 &net.rdrop);
601 if (ret == EOF)
602 break;
603 if (ret != 10) {
604 unsigned int c;
605 do {
606 c = fgetc(node->handle->procnetdev);
607 } while (c != '\n' && c != EOF);
608 if (c == EOF)
609 break;
610 continue;
611 }
613 /* FIXME: this does a search for the domid */
614 domain = xenstat_node_domain(node, domid);
615 if (domain == NULL) {
616 fprintf(stderr,
617 "Found interface vif%u.%u but domain %u"
618 " does not exist.\n", domid, net.id,
619 domid);
620 continue;
621 }
622 if (domain->networks == NULL) {
623 domain->num_networks = 1;
624 domain->networks = malloc(sizeof(xenstat_network));
625 } else {
626 struct xenstat_network *tmp;
627 domain->num_networks++;
628 tmp = realloc(domain->networks,
629 domain->num_networks *
630 sizeof(xenstat_network));
631 if (tmp == NULL)
632 free(domain->networks);
633 domain->networks = tmp;
634 }
635 if (domain->networks == NULL)
636 return 0;
637 domain->networks[domain->num_networks - 1] = net;
638 }
640 return 1;
641 }
643 /* Free network information */
644 static void xenstat_free_networks(xenstat_node * node)
645 {
646 unsigned int i;
647 for (i = 0; i < node->num_domains; i++)
648 free(node->domains[i].networks);
649 }
651 /* Free network information in handle */
652 static void xenstat_uninit_networks(xenstat_handle * handle)
653 {
654 if(handle->procnetdev)
655 fclose(handle->procnetdev);
656 }
658 /* Get the network ID */
659 unsigned int xenstat_network_id(xenstat_network * network)
660 {
661 return network->id;
662 }
664 /* Get the number of receive bytes */
665 unsigned long long xenstat_network_rbytes(xenstat_network * network)
666 {
667 return network->rbytes;
668 }
670 /* Get the number of receive packets */
671 unsigned long long xenstat_network_rpackets(xenstat_network * network)
672 {
673 return network->rpackets;
674 }
676 /* Get the number of receive errors */
677 unsigned long long xenstat_network_rerrs(xenstat_network * network)
678 {
679 return network->rerrs;
680 }
682 /* Get the number of receive drops */
683 unsigned long long xenstat_network_rdrop(xenstat_network * network)
684 {
685 return network->rdrop;
686 }
688 /* Get the number of transmit bytes */
689 unsigned long long xenstat_network_tbytes(xenstat_network * network)
690 {
691 return network->tbytes;
692 }
694 /* Get the number of transmit packets */
695 unsigned long long xenstat_network_tpackets(xenstat_network * network)
696 {
697 return network->tpackets;
698 }
700 /* Get the number of transmit errors */
701 unsigned long long xenstat_network_terrs(xenstat_network * network)
702 {
703 return network->terrs;
704 }
706 /* Get the number of transmit dropped packets */
707 unsigned long long xenstat_network_tdrop(xenstat_network * network)
708 {
709 return network->tdrop;
710 }
712 /*
713 * Xen version functions
714 */
716 /* Collect Xen version information */
717 static int xenstat_collect_xen_version(xenstat_node * node)
718 {
719 long vnum = 0;
720 xen_extraversion_t version;
722 /* Collect Xen version information if not already collected */
723 if (node->handle->xen_version[0] == '\0') {
724 /* Get the Xen version number and extraversion string */
725 vnum = xc_version(node->handle->xc_handle,
726 XENVER_version, NULL);
728 if (vnum < 0)
729 return 0;
731 if (xc_version(node->handle->xc_handle, XENVER_extraversion,
732 &version) < 0)
733 return 0;
734 /* Format the version information as a string and store it */
735 snprintf(node->handle->xen_version, VERSION_SIZE, "%ld.%ld%s",
736 ((vnum >> 16) & 0xFFFF), vnum & 0xFFFF, version);
737 }
739 return 1;
740 }
742 /* Free Xen version information in node - nothing to do */
743 static void xenstat_free_xen_version(xenstat_node * node)
744 {
745 }
747 /* Free Xen version information in handle - nothing to do */
748 static void xenstat_uninit_xen_version(xenstat_handle * handle)
749 {
750 }
752 /*
753 * VBD functions
754 */
756 static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap)
757 {
758 static char file_name[80];
759 int fd, num_read;
761 sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what);
762 fd = open(file_name, O_RDONLY, 0);
763 if (fd==-1) return -1;
764 num_read = read(fd, ret, cap - 1);
765 close(fd);
766 if (num_read<=0) return -1;
767 ret[num_read] = '\0';
768 return num_read;
769 }
771 /* Collect information about VBDs */
772 static int xenstat_collect_vbds(xenstat_node * node)
773 {
774 struct dirent *dp;
776 if (node->handle->sysfsvbd == NULL) {
777 node->handle->sysfsvbd = opendir(SYSFS_VBD_PATH);
778 if (node->handle->sysfsvbd == NULL) {
779 perror("Error opening " SYSFS_VBD_PATH);
780 return 0;
781 }
782 }
784 rewinddir(node->handle->sysfsvbd);
786 for(dp = readdir(node->handle->sysfsvbd); dp != NULL ;
787 dp = readdir(node->handle->sysfsvbd)) {
788 xenstat_domain *domain;
789 xenstat_vbd vbd;
790 unsigned int domid;
791 int ret;
792 char buf[256];
795 ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev);
796 if (ret != 2) {
797 continue;
798 }
799 printf("%s is VBD.\n",dp->d_name);
801 domain = xenstat_node_domain(node, domid);
802 if (domain == NULL) {
803 fprintf(stderr,
804 "Found interface vbd-%u-%u but domain %u"
805 " does not exist.\n",
806 domid, vbd.dev, domid);
807 continue;
808 }
810 if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0)
811 || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1))
812 {
813 continue;
814 }
816 if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0)
817 || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1))
818 {
819 continue;
820 }
822 if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0)
823 || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1))
824 {
825 continue;
826 }
829 if (domain->vbds == NULL) {
830 domain->num_vbds = 1;
831 domain->vbds = malloc(sizeof(xenstat_vbd));
832 } else {
833 domain->num_vbds++;
834 domain->vbds = realloc(domain->vbds,
835 domain->num_vbds *
836 sizeof(xenstat_vbd));
837 }
838 if (domain->vbds == NULL)
839 return 0;
840 domain->vbds[domain->num_vbds - 1] = vbd;
841 }
843 return 1;
844 }
846 /* Free VBD information */
847 static void xenstat_free_vbds(xenstat_node * node)
848 {
849 unsigned int i;
850 for (i = 0; i < node->num_domains; i++)
851 free(node->domains[i].vbds);
852 }
854 /* Free VBD information in handle */
855 static void xenstat_uninit_vbds(xenstat_handle * handle)
856 {
857 if (handle->sysfsvbd)
858 closedir(handle->sysfsvbd);
859 }
861 /* Get the major number of VBD device */
862 unsigned int xenstat_vbd_dev(xenstat_vbd * vbd)
863 {
864 return vbd->dev;
865 }
867 /* Get the number of OO(Out of) requests */
868 unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd)
869 {
870 return vbd->oo_reqs;
871 }
873 /* Get the number of READ requests */
874 unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd)
875 {
876 return vbd->rd_reqs;
877 }
879 /* Get the number of WRITE requests */
880 unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd)
881 {
882 return vbd->wr_reqs;
883 }
885 static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
886 {
887 char path[80];
888 char *name;
890 snprintf(path, sizeof(path),"/local/domain/%i/name", domain_id);
892 name = xs_read(handle->xshandle, XBT_NULL, path, NULL);
893 if (name == NULL)
894 name = strdup(" ");
896 return name;
897 }