aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenstat
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-02-23 10:47:55 +0000
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-02-23 10:47:55 +0000
commit684c5a8948324f182941dc2d66fea715f7ac80b2 (patch)
tree34d2ebd7597677fdb9be344db50b863f35bc6f37 /tools/xenstat
parent2b1b3844b2392e06e91488612d5bc7976e3fb24b (diff)
downloadxen-684c5a8948324f182941dc2d66fea715f7ac80b2.tar.gz
xen-684c5a8948324f182941dc2d66fea715f7ac80b2.tar.bz2
xen-684c5a8948324f182941dc2d66fea715f7ac80b2.zip
Implement VBD and VIF handling on Solaris for libxenstat.
Also, fix up a confusion with ERR that was breaking xentop. Signed-off-by: John Levon <john.levon@sun.com>
Diffstat (limited to 'tools/xenstat')
-rw-r--r--tools/xenstat/libxenstat/Makefile31
-rw-r--r--tools/xenstat/libxenstat/src/xenstat.c287
-rw-r--r--tools/xenstat/libxenstat/src/xenstat.h5
-rw-r--r--tools/xenstat/libxenstat/src/xenstat_linux.c265
-rw-r--r--tools/xenstat/libxenstat/src/xenstat_priv.h101
-rw-r--r--tools/xenstat/libxenstat/src/xenstat_solaris.c431
-rw-r--r--tools/xenstat/xentop/xentop.c8
7 files changed, 838 insertions, 290 deletions
diff --git a/tools/xenstat/libxenstat/Makefile b/tools/xenstat/libxenstat/Makefile
index 8cb77f17bc..fbfcb4dc38 100644
--- a/tools/xenstat/libxenstat/Makefile
+++ b/tools/xenstat/libxenstat/Makefile
@@ -14,7 +14,6 @@
XEN_ROOT=../../..
include $(XEN_ROOT)/tools/Rules.mk
-LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse
prefix=/usr
includedir=$(prefix)/include
@@ -29,26 +28,40 @@ MINOR=0
LIB=src/libxenstat.a
SHLIB=src/libxenstat.so.$(MAJOR).$(MINOR)
SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so
-OBJECTS=src/xenstat.o
+OBJECTS-y=src/xenstat.o
+OBJECTS-$(CONFIG_Linux) += src/xenstat_linux.o
+OBJECTS-$(CONFIG_SunOS) += src/xenstat_solaris.o
SONAME_FLAGS=-Wl,$(SONAME_LDFLAG) -Wl,libxenstat.so.$(MAJOR)
WARN_FLAGS=-Wall -Werror
CFLAGS+=-Isrc -I$(XEN_LIBXC) -I$(XEN_XENSTORE)
LDFLAGS+=-Lsrc -L$(XEN_XENSTORE)/ -L$(XEN_LIBXC)/
+LDLIBS-y = -lxenstore -lxenctrl
+LDLIBS-$(CONFIG_SunOS) += -lkstat
+ARLIBS-y = $(XEN_XENSTORE)/libxenstore.so $(XEN_LIBXC)/libxenctrl.so
+ARLIBS-x86_64 = /usr/lib/amd64/libkstat.so
+ARLIBS-x86_32 = /usr/lib/libkstat.so
+ARLIBS-$(CONFIG_SunOS) += $(ARLIBS-$(XEN_TARGET_ARCH))
.PHONY: all
all: $(LIB)
-$(LIB): $(OBJECTS)
- $(AR) rc $@ $^ $(XEN_XENSTORE)/libxenstore.so $(XEN_LIBXC)/libxenctrl.so
+$(LIB): $(OBJECTS-y)
+ $(AR) rc $@ $^ $(ARLIBS-y)
$(RANLIB) $@
-$(SHLIB): $(OBJECTS)
- $(CC) $(CFLAGS) $(LDFLAGS) $(SONAME_FLAGS) $(SHLIB_CFLAGS) -o $@ $(OBJECTS) \
- -lxenstore -lxenctrl
+$(SHLIB): $(OBJECTS-y)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(SONAME_FLAGS) $(SHLIB_CFLAGS) -o $@ \
+ $(OBJECTS-y) $(LDLIBS-y)
-src/xenstat.o: src/xenstat.c src/xenstat.h
+src/xenstat.o: src/xenstat.c src/xenstat.h src/xenstat_priv.h
+ $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $<
+
+src/xenstat_linux.o: src/xenstat_linux.c src/xenstat_priv.h
+ $(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $<
+
+src/xenstat_solaris.o: src/xenstat_solaris.c src/xenstat_priv.h
$(CC) $(CFLAGS) $(WARN_FLAGS) -c -o $@ $<
src/libxenstat.so.$(MAJOR): $(LIB)
@@ -140,5 +153,5 @@ endif
.PHONY: clean
clean:
- rm -f $(LIB) $(SHLIB) $(SHLIB_LINKS) $(OBJECTS) \
+ rm -f $(LIB) $(SHLIB) $(SHLIB_LINKS) $(OBJECTS-y) \
$(BINDINGS) $(BINDINGSRC)
diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c
index 8857bd1c27..ca81a99cd9 100644
--- a/tools/xenstat/libxenstat/src/xenstat.c
+++ b/tools/xenstat/libxenstat/src/xenstat.c
@@ -15,89 +15,17 @@
* Lesser General Public License for more details.
*/
-#include <limits.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <xs.h>
-#include "xenstat.h"
-
-#include "xenctrl.h"
-
/*
- * Types
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
-#define SHORT_ASC_LEN 5 /* length of 65535 */
-#define VERSION_SIZE (2 * SHORT_ASC_LEN + 1 + sizeof(xen_extraversion_t) + 1)
-
-struct xenstat_handle {
- int xc_handle;
- struct xs_handle *xshandle; /* xenstore handle */
- int page_size;
- FILE *procnetdev;
- DIR *sysfsvbd;
- char xen_version[VERSION_SIZE]; /* xen version running on this node */
-};
-
-struct xenstat_node {
- xenstat_handle *handle;
- unsigned int flags;
- unsigned long long cpu_hz;
- unsigned int num_cpus;
- unsigned long long tot_mem;
- unsigned long long free_mem;
- unsigned int num_domains;
- xenstat_domain *domains; /* Array of length num_domains */
-};
-struct xenstat_domain {
- unsigned int id;
- char *name;
- unsigned int state;
- unsigned long long cpu_ns;
- unsigned int num_vcpus; /* No. vcpus configured for domain */
- xenstat_vcpu *vcpus; /* Array of length num_vcpus */
- unsigned long long cur_mem; /* Current memory reservation */
- unsigned long long max_mem; /* Total memory allowed */
- unsigned int ssid;
- unsigned int num_networks;
- xenstat_network *networks; /* Array of length num_networks */
- unsigned int num_vbds;
- xenstat_vbd *vbds;
-};
-
-struct xenstat_vcpu {
- unsigned int online;
- unsigned long long ns;
-};
-
-struct xenstat_network {
- unsigned int id;
- /* Received */
- unsigned long long rbytes;
- unsigned long long rpackets;
- unsigned long long rerrs;
- unsigned long long rdrop;
- /* Transmitted */
- unsigned long long tbytes;
- unsigned long long tpackets;
- unsigned long long terrs;
- unsigned long long tdrop;
-};
-
-struct xenstat_vbd {
- unsigned int dev;
- unsigned long long oo_reqs;
- unsigned long long rd_reqs;
- unsigned long long wr_reqs;
-};
-#define SYSFS_VBD_PATH "/sys/devices/xen-backend/"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "xenstat_priv.h"
/*
* Data-collection types
@@ -125,17 +53,13 @@ typedef struct xenstat_collector {
} xenstat_collector;
static int xenstat_collect_vcpus(xenstat_node * node);
-static int xenstat_collect_networks(xenstat_node * node);
static int xenstat_collect_xen_version(xenstat_node * node);
-static int xenstat_collect_vbds(xenstat_node * node);
static void xenstat_free_vcpus(xenstat_node * node);
static void xenstat_free_networks(xenstat_node * node);
static void xenstat_free_xen_version(xenstat_node * node);
static void xenstat_free_vbds(xenstat_node * node);
static void xenstat_uninit_vcpus(xenstat_handle * handle);
-static void xenstat_uninit_networks(xenstat_handle * handle);
static void xenstat_uninit_xen_version(xenstat_handle * handle);
-static void xenstat_uninit_vbds(xenstat_handle * handle);
static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
static void xenstat_prune_domain(xenstat_node *node, unsigned int entry);
@@ -202,6 +126,7 @@ void xenstat_uninit(xenstat_handle * handle)
collectors[i].uninit(handle);
xc_interface_close(handle->xc_handle);
xs_daemon_close(handle->xshandle);
+ free(handle->priv);
free(handle);
}
}
@@ -586,97 +511,6 @@ unsigned long long xenstat_vcpu_ns(xenstat_vcpu * vcpu)
* Network functions
*/
-/* Expected format of /proc/net/dev */
-static const char PROCNETDEV_HEADER[] =
- "Inter-| Receive |"
- " Transmit\n"
- " face |bytes packets errs drop fifo frame compressed multicast|"
- "bytes packets errs drop fifo colls carrier compressed\n";
-
-/* Collect information about networks */
-static int xenstat_collect_networks(xenstat_node * node)
-{
- /* Open and validate /proc/net/dev if we haven't already */
- if (node->handle->procnetdev == NULL) {
- char header[sizeof(PROCNETDEV_HEADER)];
- node->handle->procnetdev = fopen("/proc/net/dev", "r");
- if (node->handle->procnetdev == NULL) {
- perror("Error opening /proc/net/dev");
- return 0;
- }
-
- /* Validate the format of /proc/net/dev */
- if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1,
- node->handle->procnetdev) != 1) {
- perror("Error reading /proc/net/dev header");
- return 0;
- }
- header[sizeof(PROCNETDEV_HEADER) - 1] = '\0';
- if (strcmp(header, PROCNETDEV_HEADER) != 0) {
- fprintf(stderr,
- "Unexpected /proc/net/dev format\n");
- return 0;
- }
- }
-
- /* Fill in networks */
- /* FIXME: optimize this */
- fseek(node->handle->procnetdev, sizeof(PROCNETDEV_HEADER) - 1,
- SEEK_SET);
- while (1) {
- xenstat_domain *domain;
- xenstat_network net;
- unsigned int domid;
- int ret = fscanf(node->handle->procnetdev,
- "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u"
- "%llu%llu%llu%llu%*u%*u%*u%*u\n",
- &domid, &net.id,
- &net.tbytes, &net.tpackets, &net.terrs,
- &net.tdrop,
- &net.rbytes, &net.rpackets, &net.rerrs,
- &net.rdrop);
- if (ret == EOF)
- break;
- if (ret != 10) {
- unsigned int c;
- do {
- c = fgetc(node->handle->procnetdev);
- } while (c != '\n' && c != EOF);
- if (c == EOF)
- break;
- continue;
- }
-
- /* FIXME: this does a search for the domid */
- domain = xenstat_node_domain(node, domid);
- if (domain == NULL) {
- fprintf(stderr,
- "Found interface vif%u.%u but domain %u"
- " does not exist.\n", domid, net.id,
- domid);
- continue;
- }
- if (domain->networks == NULL) {
- domain->num_networks = 1;
- domain->networks = malloc(sizeof(xenstat_network));
- } else {
- struct xenstat_network *tmp;
- domain->num_networks++;
- tmp = realloc(domain->networks,
- domain->num_networks *
- sizeof(xenstat_network));
- if (tmp == NULL)
- free(domain->networks);
- domain->networks = tmp;
- }
- if (domain->networks == NULL)
- return 0;
- domain->networks[domain->num_networks - 1] = net;
- }
-
- return 1;
-}
-
/* Free network information */
static void xenstat_free_networks(xenstat_node * node)
{
@@ -685,13 +519,6 @@ static void xenstat_free_networks(xenstat_node * node)
free(node->domains[i].networks);
}
-/* Free network information in handle */
-static void xenstat_uninit_networks(xenstat_handle * handle)
-{
- if(handle->procnetdev)
- fclose(handle->procnetdev);
-}
-
/* Get the network ID */
unsigned int xenstat_network_id(xenstat_network * network)
{
@@ -790,96 +617,6 @@ static void xenstat_uninit_xen_version(xenstat_handle * handle)
* VBD functions
*/
-static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap)
-{
- static char file_name[80];
- int fd, num_read;
-
- sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what);
- fd = open(file_name, O_RDONLY, 0);
- if (fd==-1) return -1;
- num_read = read(fd, ret, cap - 1);
- close(fd);
- if (num_read<=0) return -1;
- ret[num_read] = '\0';
- return num_read;
-}
-
-/* Collect information about VBDs */
-static int xenstat_collect_vbds(xenstat_node * node)
-{
- struct dirent *dp;
-
- if (node->handle->sysfsvbd == NULL) {
- node->handle->sysfsvbd = opendir(SYSFS_VBD_PATH);
- if (node->handle->sysfsvbd == NULL) {
- perror("Error opening " SYSFS_VBD_PATH);
- return 0;
- }
- }
-
- rewinddir(node->handle->sysfsvbd);
-
- for(dp = readdir(node->handle->sysfsvbd); dp != NULL ;
- dp = readdir(node->handle->sysfsvbd)) {
- xenstat_domain *domain;
- xenstat_vbd vbd;
- unsigned int domid;
- int ret;
- char buf[256];
-
-
- ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev);
- if (ret != 2) {
- continue;
- }
- printf("%s is VBD.\n",dp->d_name);
-
- domain = xenstat_node_domain(node, domid);
- if (domain == NULL) {
- fprintf(stderr,
- "Found interface vbd-%u-%u but domain %u"
- " does not exist.\n",
- domid, vbd.dev, domid);
- continue;
- }
-
- if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0)
- || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1))
- {
- continue;
- }
-
- if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0)
- || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1))
- {
- continue;
- }
-
- if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0)
- || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1))
- {
- continue;
- }
-
-
- if (domain->vbds == NULL) {
- domain->num_vbds = 1;
- domain->vbds = malloc(sizeof(xenstat_vbd));
- } else {
- domain->num_vbds++;
- domain->vbds = realloc(domain->vbds,
- domain->num_vbds *
- sizeof(xenstat_vbd));
- }
- if (domain->vbds == NULL)
- return 0;
- domain->vbds[domain->num_vbds - 1] = vbd;
- }
-
- return 1;
-}
-
/* Free VBD information */
static void xenstat_free_vbds(xenstat_node * node)
{
@@ -888,13 +625,6 @@ static void xenstat_free_vbds(xenstat_node * node)
free(node->domains[i].vbds);
}
-/* Free VBD information in handle */
-static void xenstat_uninit_vbds(xenstat_handle * handle)
-{
- if (handle->sysfsvbd)
- closedir(handle->sysfsvbd);
-}
-
/* Get the major number of VBD device */
unsigned int xenstat_vbd_dev(xenstat_vbd * vbd)
{
@@ -948,4 +678,3 @@ static void xenstat_prune_domain(xenstat_node *node, unsigned int entry)
strictly necessary but safer! */
memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain));
}
-
diff --git a/tools/xenstat/libxenstat/src/xenstat.h b/tools/xenstat/libxenstat/src/xenstat.h
index 0a946042a1..0d791650b2 100644
--- a/tools/xenstat/libxenstat/src/xenstat.h
+++ b/tools/xenstat/libxenstat/src/xenstat.h
@@ -17,6 +17,9 @@
/* libxenstat API */
+#ifndef XENSTAT_H
+#define XENSTAT_H
+
/* Opaque handles */
typedef struct xenstat_handle xenstat_handle;
typedef struct xenstat_domain xenstat_domain;
@@ -176,3 +179,5 @@ unsigned int xenstat_vbd_dev(xenstat_vbd * vbd);
unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd);
unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd);
unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd);
+
+#endif /* XENSTAT_H */
diff --git a/tools/xenstat/libxenstat/src/xenstat_linux.c b/tools/xenstat/libxenstat/src/xenstat_linux.c
new file mode 100644
index 0000000000..cc94dbadd3
--- /dev/null
+++ b/tools/xenstat/libxenstat/src/xenstat_linux.c
@@ -0,0 +1,265 @@
+/* libxenstat: statistics-collection library for Xen
+ * Copyright (C) International Business Machines Corp., 2005
+ * Authors: Josh Triplett <josht@us.ibm.com>
+ * Judy Fischbach <jfisch@us.ibm.com>
+ * David Hendricks <dhendrix@us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xenstat_priv.h"
+
+#define SYSFS_VBD_PATH "/sys/devices/xen-backend/"
+
+struct priv_data {
+ FILE *procnetdev;
+ DIR *sysfsvbd;
+};
+
+static struct priv_data *
+get_priv_data(xenstat_handle *handle)
+{
+ if (handle->priv != NULL)
+ return handle->priv;
+
+ handle->priv = malloc(sizeof(struct priv_data));
+ if (handle->priv == NULL)
+ return (NULL);
+
+ ((struct priv_data *)handle->priv)->procnetdev = NULL;
+ ((struct priv_data *)handle->priv)->sysfsvbd = NULL;
+
+ return handle->priv;
+}
+
+/* Expected format of /proc/net/dev */
+static const char PROCNETDEV_HEADER[] =
+ "Inter-| Receive |"
+ " Transmit\n"
+ " face |bytes packets errs drop fifo frame compressed multicast|"
+ "bytes packets errs drop fifo colls carrier compressed\n";
+
+/* Collect information about networks */
+int xenstat_collect_networks(xenstat_node * node)
+{
+ struct priv_data *priv = get_priv_data(node->handle);
+
+ if (priv == NULL) {
+ perror("Allocation error");
+ return 0;
+ }
+
+ /* Open and validate /proc/net/dev if we haven't already */
+ if (priv->procnetdev == NULL) {
+ char header[sizeof(PROCNETDEV_HEADER)];
+ priv->procnetdev = fopen("/proc/net/dev", "r");
+ if (priv->procnetdev == NULL) {
+ perror("Error opening /proc/net/dev");
+ return 0;
+ }
+
+ /* Validate the format of /proc/net/dev */
+ if (fread(header, sizeof(PROCNETDEV_HEADER) - 1, 1,
+ priv->procnetdev) != 1) {
+ perror("Error reading /proc/net/dev header");
+ return 0;
+ }
+ header[sizeof(PROCNETDEV_HEADER) - 1] = '\0';
+ if (strcmp(header, PROCNETDEV_HEADER) != 0) {
+ fprintf(stderr,
+ "Unexpected /proc/net/dev format\n");
+ return 0;
+ }
+ }
+
+ /* Fill in networks */
+ /* FIXME: optimize this */
+ fseek(priv->procnetdev, sizeof(PROCNETDEV_HEADER) - 1,
+ SEEK_SET);
+ while (1) {
+ xenstat_domain *domain;
+ xenstat_network net;
+ unsigned int domid;
+ int ret = fscanf(priv->procnetdev,
+ "vif%u.%u:%llu%llu%llu%llu%*u%*u%*u%*u"
+ "%llu%llu%llu%llu%*u%*u%*u%*u\n",
+ &domid, &net.id,
+ &net.tbytes, &net.tpackets, &net.terrs,
+ &net.tdrop,
+ &net.rbytes, &net.rpackets, &net.rerrs,
+ &net.rdrop);
+ if (ret == EOF)
+ break;
+ if (ret != 10) {
+ unsigned int c;
+ do {
+ c = fgetc(priv->procnetdev);
+ } while (c != '\n' && c != EOF);
+ if (c == EOF)
+ break;
+ continue;
+ }
+
+ /* FIXME: this does a search for the domid */
+ domain = xenstat_node_domain(node, domid);
+ if (domain == NULL) {
+ fprintf(stderr,
+ "Found interface vif%u.%u but domain %u"
+ " does not exist.\n", domid, net.id,
+ domid);
+ continue;
+ }
+ if (domain->networks == NULL) {
+ domain->num_networks = 1;
+ domain->networks = malloc(sizeof(xenstat_network));
+ } else {
+ struct xenstat_network *tmp;
+ domain->num_networks++;
+ tmp = realloc(domain->networks,
+ domain->num_networks *
+ sizeof(xenstat_network));
+ if (tmp == NULL)
+ free(domain->networks);
+ domain->networks = tmp;
+ }
+ if (domain->networks == NULL)
+ return 0;
+ domain->networks[domain->num_networks - 1] = net;
+ }
+
+ return 1;
+}
+
+/* Free network information in handle */
+void xenstat_uninit_networks(xenstat_handle * handle)
+{
+ struct priv_data *priv = get_priv_data(handle);
+ if (priv != NULL && priv->procnetdev != NULL)
+ fclose(priv->procnetdev);
+}
+
+static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap)
+{
+ static char file_name[80];
+ int fd, num_read;
+
+ sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what);
+ fd = open(file_name, O_RDONLY, 0);
+ if (fd==-1) return -1;
+ num_read = read(fd, ret, cap - 1);
+ close(fd);
+ if (num_read<=0) return -1;
+ ret[num_read] = '\0';
+ return num_read;
+}
+
+/* Collect information about VBDs */
+int xenstat_collect_vbds(xenstat_node * node)
+{
+ struct dirent *dp;
+ struct priv_data *priv = get_priv_data(node->handle);
+
+ if (priv == NULL) {
+ perror("Allocation error");
+ return 0;
+ }
+
+ if (priv->sysfsvbd == NULL) {
+ priv->sysfsvbd = opendir(SYSFS_VBD_PATH);
+ if (priv->sysfsvbd == NULL) {
+ perror("Error opening " SYSFS_VBD_PATH);
+ return 0;
+ }
+ }
+
+ rewinddir(priv->sysfsvbd);
+
+ for(dp = readdir(priv->sysfsvbd); dp != NULL ;
+ dp = readdir(priv->sysfsvbd)) {
+ xenstat_domain *domain;
+ xenstat_vbd vbd;
+ unsigned int domid;
+ int ret;
+ char buf[256];
+
+
+ ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev);
+ if (ret != 2) {
+ continue;
+ }
+ printf("%s is VBD.\n",dp->d_name);
+
+ domain = xenstat_node_domain(node, domid);
+ if (domain == NULL) {
+ fprintf(stderr,
+ "Found interface vbd-%u-%u but domain %u"
+ " does not exist.\n",
+ domid, vbd.dev, domid);
+ continue;
+ }
+
+ if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0)
+ || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1))
+ {
+ continue;
+ }
+
+ if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0)
+ || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1))
+ {
+ continue;
+ }
+
+ if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0)
+ || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1))
+ {
+ continue;
+ }
+
+
+ if (domain->vbds == NULL) {
+ domain->num_vbds = 1;
+ domain->vbds = malloc(sizeof(xenstat_vbd));
+ } else {
+ domain->num_vbds++;
+ domain->vbds = realloc(domain->vbds,
+ domain->num_vbds *
+ sizeof(xenstat_vbd));
+ }
+ if (domain->vbds == NULL)
+ return 0;
+ domain->vbds[domain->num_vbds - 1] = vbd;
+ }
+
+ return 1;
+}
+
+/* Free VBD information in handle */
+void xenstat_uninit_vbds(xenstat_handle * handle)
+{
+ struct priv_data *priv = get_priv_data(handle);
+ if (priv != NULL && priv->sysfsvbd != NULL)
+ closedir(priv->sysfsvbd);
+}
diff --git a/tools/xenstat/libxenstat/src/xenstat_priv.h b/tools/xenstat/libxenstat/src/xenstat_priv.h
new file mode 100644
index 0000000000..980e0925bc
--- /dev/null
+++ b/tools/xenstat/libxenstat/src/xenstat_priv.h
@@ -0,0 +1,101 @@
+/* libxenstat: statistics-collection library for Xen
+ * Copyright (C) International Business Machines Corp., 2005
+ * Authors: Josh Triplett <josht@us.ibm.com>
+ * Judy Fischbach <jfisch@us.ibm.com>
+ * David Hendricks <dhendrix@us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef XENSTAT_PRIV_H
+#define XENSTAT_PRIV_H
+
+#include <sys/types.h>
+#include <xs.h>
+#include "xenstat.h"
+
+#include "xenctrl.h"
+
+#define SHORT_ASC_LEN 5 /* length of 65535 */
+#define VERSION_SIZE (2 * SHORT_ASC_LEN + 1 + sizeof(xen_extraversion_t) + 1)
+
+struct xenstat_handle {
+ int xc_handle;
+ struct xs_handle *xshandle; /* xenstore handle */
+ int page_size;
+ void *priv;
+ char xen_version[VERSION_SIZE]; /* xen version running on this node */
+};
+
+struct xenstat_node {
+ xenstat_handle *handle;
+ unsigned int flags;
+ unsigned long long cpu_hz;
+ unsigned int num_cpus;
+ unsigned long long tot_mem;
+ unsigned long long free_mem;
+ unsigned int num_domains;
+ xenstat_domain *domains; /* Array of length num_domains */
+};
+
+struct xenstat_domain {
+ unsigned int id;
+ char *name;
+ unsigned int state;
+ unsigned long long cpu_ns;
+ unsigned int num_vcpus; /* No. vcpus configured for domain */
+ xenstat_vcpu *vcpus; /* Array of length num_vcpus */
+ unsigned long long cur_mem; /* Current memory reservation */
+ unsigned long long max_mem; /* Total memory allowed */
+ unsigned int ssid;
+ unsigned int num_networks;
+ xenstat_network *networks; /* Array of length num_networks */
+ unsigned int num_vbds;
+ xenstat_vbd *vbds;
+};
+
+struct xenstat_vcpu {
+ unsigned int online;
+ unsigned long long ns;
+};
+
+struct xenstat_network {
+ unsigned int id;
+ /* Received */
+ unsigned long long rbytes;
+ unsigned long long rpackets;
+ unsigned long long rerrs;
+ unsigned long long rdrop;
+ /* Transmitted */
+ unsigned long long tbytes;
+ unsigned long long tpackets;
+ unsigned long long terrs;
+ unsigned long long tdrop;
+};
+
+struct xenstat_vbd {
+ unsigned int dev;
+ unsigned long long oo_reqs;
+ unsigned long long rd_reqs;
+ unsigned long long wr_reqs;
+};
+
+extern int xenstat_collect_networks(xenstat_node * node);
+extern void xenstat_uninit_networks(xenstat_handle * handle);
+extern int xenstat_collect_vbds(xenstat_node * node);
+extern void xenstat_uninit_vbds(xenstat_handle * handle);
+
+#endif /* XENSTAT_PRIV_H */
diff --git a/tools/xenstat/libxenstat/src/xenstat_solaris.c b/tools/xenstat/libxenstat/src/xenstat_solaris.c
new file mode 100644
index 0000000000..719c30d8ac
--- /dev/null
+++ b/tools/xenstat/libxenstat/src/xenstat_solaris.c
@@ -0,0 +1,431 @@
+/* libxenstat: statistics-collection library for Xen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <strings.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <kstat.h>
+
+#include "xenstat_priv.h"
+
+#define DEVICE_NIC 1
+#define DEVICE_XDB 2
+
+typedef struct stdevice {
+ int domid;
+ int used;
+ int type;
+ char name[256];
+ int instance;
+ uint64_t stats[2][8];
+ struct stdevice *next;
+} stdevice_t;
+
+typedef struct priv_data {
+ kstat_ctl_t *kc;
+ stdevice_t *devs;
+} priv_data_t;
+
+static priv_data_t *get_priv_data(xenstat_handle *handle)
+{
+ priv_data_t *priv = handle->priv;
+
+ if (priv == NULL) {
+ priv = malloc(sizeof (priv_data_t));
+ if (priv == NULL)
+ return NULL;
+ priv->devs = NULL;
+ priv->kc = NULL;
+ }
+
+ if (priv->kc == NULL) {
+ if ((priv->kc = kstat_open()) == NULL) {
+ free(priv);
+ return NULL;
+ }
+ }
+
+ handle->priv = priv;
+ return handle->priv;
+}
+
+static int kstat_get(kstat_t *ksp, const char *name, uint64_t *val)
+{
+ kstat_named_t *ksn = kstat_data_lookup(ksp, (char *)name);
+ if (ksn == NULL)
+ return 0;
+ *val = ksn->value.ui64;
+ return 1;
+}
+
+static void gc_devs(priv_data_t *priv, int type)
+{
+ stdevice_t *start = NULL;
+ stdevice_t *dev;
+ stdevice_t *tmp;
+
+ for (dev = priv->devs; dev != NULL; dev = tmp) {
+ tmp = dev->next;
+
+ if (dev->used || dev->type != type) {
+ dev->next = start;
+ start = dev;
+ } else {
+ free(dev);
+ }
+ }
+
+ priv->devs = start;
+}
+
+static void xenstat_uninit_devs(xenstat_handle *handle, int type)
+{
+ priv_data_t *priv = get_priv_data(handle);
+ stdevice_t *dev;
+
+ if (priv == NULL)
+ return;
+
+ for (dev = priv->devs; dev != NULL; dev = dev->next)
+ dev->used = 0;
+
+ gc_devs(priv, type);
+
+ if (priv->kc != NULL)
+ kstat_close(priv->kc);
+ priv->kc = NULL;
+}
+
+static int parse_nic(const char *nic, char *module, int *instance)
+{
+ const char *c;
+
+ for (c = &nic[strlen(nic) - 1]; c != nic && isdigit(*c); c--)
+ ;
+
+ if (c == nic)
+ return 0;
+
+ c++;
+
+ if (sscanf(c, "%d", instance) != 1)
+ return 0;
+
+ strncpy(module, nic, c - nic);
+ module[c - nic] = '\0';
+ return 1;
+}
+
+static int update_dev_stats(priv_data_t *priv, stdevice_t *dev)
+{
+ char mod[256];
+ const char *name;
+ int inst;
+ kstat_t *ksp;
+
+ if (dev->type == DEVICE_NIC) {
+ if (!parse_nic(dev->name, mod, &inst))
+ return 0;
+ name = "mac";
+ } else {
+ strcpy(mod, "xdb");
+ inst = dev->instance;
+ name = "req_statistics";
+ }
+
+ if (kstat_chain_update(priv->kc) == -1)
+ return 0;
+
+ ksp = kstat_lookup(priv->kc, mod, inst, (char *)name);
+ if (ksp == NULL)
+ return 0;
+ if (kstat_read(priv->kc, ksp, NULL) == -1)
+ return 0;
+
+ dev->used = 1;
+
+ bcopy(&(dev->stats[1][0]), &(dev->stats[0][0]), sizeof(dev->stats[0]));
+
+ if (dev->type == DEVICE_NIC) {
+ if (!kstat_get(ksp, "rbytes64", &dev->stats[1][0]) ||
+ !kstat_get(ksp, "ipackets64", &dev->stats[1][1]) ||
+ !kstat_get(ksp, "ierrors", &dev->stats[1][2]) ||
+ !kstat_get(ksp, "obytes64", &dev->stats[1][3]) ||
+ !kstat_get(ksp, "opackets64", &dev->stats[1][4]) ||
+ !kstat_get(ksp, "oerrors", &dev->stats[1][5]))
+ return 0;
+
+ dev->stats[1][6] = 0;
+ dev->stats[1][7] = 0;
+ } else {
+ if (!kstat_get(ksp, "rd_reqs", &dev->stats[1][0]) ||
+ !kstat_get(ksp, "wr_reqs", &dev->stats[1][1]) ||
+ !kstat_get(ksp, "oo_reqs", &dev->stats[1][2]))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int init_dev(priv_data_t *priv, int type, const char *name,
+ int instance, int domid)
+{
+ stdevice_t *dev;
+
+ if (!(dev = malloc(sizeof(*dev))))
+ return 0;
+
+ bzero(dev, sizeof(*dev));
+ dev->type = type;
+ if (name != NULL)
+ strcpy(dev->name, name);
+ dev->instance = instance;
+ dev->domid = domid;
+ dev->next = priv->devs;
+ priv->devs = dev;
+
+ /*
+ * Update twice to avoid delta-since-boot.
+ */
+ if (!update_dev_stats(priv, dev))
+ return 0;
+ return update_dev_stats(priv, dev);
+}
+
+static int update_nic(priv_data_t *priv, xenstat_domain *dom,
+ xenstat_network *net, const char *name)
+{
+ stdevice_t *dev;
+
+ for (dev = priv->devs; dev != NULL; dev = dev->next) {
+ if (dev->type == DEVICE_NIC && dev->domid == dom->id &&
+ strcmp(name, dev->name) == 0) {
+ if (!update_dev_stats(priv, dev))
+ return 0;
+ net->rbytes = dev->stats[1][0] - dev->stats[0][0];
+ net->rpackets = dev->stats[1][1] - dev->stats[0][1];
+ net->rerrs = dev->stats[1][2] - dev->stats[0][2];
+ net->tbytes = dev->stats[1][3] - dev->stats[0][3];
+ net->tpackets = dev->stats[1][4] - dev->stats[0][4];
+ net->terrs = dev->stats[1][5] - dev->stats[0][5];
+ net->rdrop = dev->stats[1][6] - dev->stats[0][6];
+ net->tdrop = dev->stats[1][7] - dev->stats[0][7];
+ return 1;
+ }
+ }
+
+ return init_dev(priv, DEVICE_NIC, name, 0, dom->id);
+}
+
+static int
+collect_dom_networks(xenstat_node *node, priv_data_t *priv, xenstat_domain *dom)
+{
+ char path[PATH_MAX];
+ char **vifs;
+ int ret = 1;
+ int nr;
+ int i;
+
+ snprintf(path, sizeof(path), "/local/domain/%d/device/vif", dom->id);
+
+ dom->num_networks = 0;
+ free(dom->networks);
+ dom->networks = NULL;
+
+ vifs = xs_directory(node->handle->xshandle, XBT_NULL, path, &nr);
+ if (vifs == NULL)
+ goto out;
+
+ dom->num_networks = nr;
+ dom->networks = calloc(nr, sizeof(xenstat_network));
+
+ for (i = 0; i < dom->num_networks; i++) {
+ char *tmp;
+
+ snprintf(path, sizeof(path),
+ "/local/domain/%d/device/vif/%d/backend", dom->id, i);
+
+ tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL);
+
+ if (tmp == NULL)
+ goto out;
+
+ snprintf(path, sizeof(path), "%s/nic", tmp);
+ free(tmp);
+
+ tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL);
+
+ if (tmp == NULL || tmp[0] == '\0') {
+ free(tmp);
+ goto out;
+ }
+
+ if (!(ret = update_nic(priv, dom, &dom->networks[i], tmp))) {
+ free(tmp);
+ goto out;
+ }
+
+ free(tmp);
+ }
+
+ ret = 1;
+out:
+ free(vifs);
+ return ret;
+}
+
+int xenstat_collect_networks(xenstat_node * node)
+{
+ int i;
+ priv_data_t *priv = get_priv_data(node->handle);
+ stdevice_t *dev;
+
+ if (priv == NULL)
+ return 0;
+
+ for (dev = priv->devs; dev != NULL; dev = dev->next)
+ dev->used = 0;
+
+ for (i = 0; i < node->num_domains; i++) {
+ if (node->domains[i].id == 0)
+ continue;
+ if (!collect_dom_networks(node, priv, &node->domains[i]))
+ return 0;
+ }
+
+ gc_devs(priv, DEVICE_NIC);
+
+ return 1;
+}
+
+void xenstat_uninit_networks(xenstat_handle *handle)
+{
+ xenstat_uninit_devs(handle, DEVICE_NIC);
+}
+
+static int update_xdb(priv_data_t *priv, xenstat_domain *dom,
+ xenstat_vbd *vbd, int instance)
+{
+ stdevice_t *dev;
+
+ for (dev = priv->devs; dev != NULL; dev = dev->next) {
+ if (dev->type == DEVICE_XDB && dev->domid == dom->id &&
+ dev->instance == instance) {
+ if (!update_dev_stats(priv, dev))
+ return 0;
+ vbd->dev = dev->instance;
+ vbd->rd_reqs = dev->stats[1][0] - dev->stats[0][0];
+ vbd->wr_reqs = dev->stats[1][1] - dev->stats[0][1];
+ vbd->oo_reqs = dev->stats[1][2] - dev->stats[0][2];
+ return 1;
+ }
+ }
+
+ return init_dev(priv, DEVICE_XDB, NULL, instance, dom->id);
+}
+
+static int
+collect_dom_vbds(xenstat_node *node, priv_data_t *priv, xenstat_domain *dom)
+{
+ char path[PATH_MAX];
+ char **vbds;
+ int ret = 1;
+ int nr;
+ int i;
+
+ snprintf(path, sizeof(path), "/local/domain/%d/device/vbd", dom->id);
+
+ dom->num_vbds = 0;
+ free(dom->vbds);
+ dom->vbds = NULL;
+
+ vbds = xs_directory(node->handle->xshandle, XBT_NULL, path, &nr);
+ if (vbds == NULL)
+ goto out;
+
+ dom->num_vbds = nr;
+ dom->vbds = calloc(nr, sizeof(xenstat_vbd));
+
+ for (i = 0; i < dom->num_vbds; i++) {
+ char *tmp;
+ int inst;
+
+ snprintf(path, sizeof(path),
+ "/local/domain/%d/device/vbd/%s/backend", dom->id, vbds[i]);
+
+ tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL);
+
+ if (tmp == NULL)
+ goto out;
+
+ snprintf(path, sizeof(path), "%s/instance", tmp);
+ free(tmp);
+
+ tmp = xs_read(node->handle->xshandle, XBT_NULL, path, NULL);
+
+ /*
+ * Fails when connection is not completed; mark it clearly with
+ * a -1.
+ */
+ if (tmp == NULL || sscanf(tmp, "%d", &inst) != 1) {
+ dom->vbds[i].dev = -1;
+ free(tmp);
+ goto out;
+ }
+
+ free(tmp);
+
+ if (!(ret = update_xdb(priv, dom, &dom->vbds[i], inst)))
+ goto out;
+ }
+
+out:
+ free(vbds);
+ return ret;
+}
+
+int xenstat_collect_vbds(xenstat_node * node)
+{
+ int i;
+ priv_data_t *priv = get_priv_data(node->handle);
+ stdevice_t *dev;
+
+ if (priv == NULL)
+ return 0;
+
+ for (dev = priv->devs; dev != NULL; dev = dev->next)
+ dev->used = 0;
+
+ for (i = 0; i < node->num_domains; i++) {
+ if (node->domains[i].id == 0)
+ continue;
+ if (!collect_dom_vbds(node, priv, &node->domains[i]))
+ return 0;
+ }
+
+ gc_devs(priv, DEVICE_XDB);
+
+ return 1;
+}
+
+void xenstat_uninit_vbds(xenstat_handle * handle)
+{
+ xenstat_uninit_devs(handle, DEVICE_XDB);
+}
diff --git a/tools/xenstat/xentop/xentop.c b/tools/xenstat/xentop/xentop.c
index 3bc7860349..170b5c4caa 100644
--- a/tools/xenstat/xentop/xentop.c
+++ b/tools/xenstat/xentop/xentop.c
@@ -50,7 +50,11 @@
#define KEY_ESCAPE '\x1B'
#ifdef HOST_SunOS
-/* Old curses library on Solaris takes non-const strings. */
+/* Old curses library on Solaris takes non-const strings. Also, ERR interferes
+ * with curse's definition.
+ */
+#undef ERR
+#define ERR (-1)
#define curses_str_t char *
#else
#define curses_str_t const char *
@@ -914,7 +918,7 @@ void do_vbd(xenstat_domain *domain)
for (i=0 ; i< num_vbds; i++) {
vbd = xenstat_domain_vbd(domain,i);
- print("VBD %4u [%2x:%2x] OO: %8llu RD: %8llu WR: %8llu\n",
+ print("VBD %4d [%2x:%2x] OO: %8llu RD: %8llu WR: %8llu\n",
xenstat_vbd_dev(vbd),
MAJOR(xenstat_vbd_dev(vbd)), MINOR(xenstat_vbd_dev(vbd)),
xenstat_vbd_oo_reqs(vbd),