[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Implement VBD and VIF handling on Solaris for libxenstat



# HG changeset patch
# User john.levon@xxxxxxx
# Date 1170985988 28800
# Node ID c2eb82b28b7d685cca993fd3fb2865051006ffc8
# Parent  546eef87339a3864af25a390457801dad737bf68
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@xxxxxxx>

diff --git a/tools/xenstat/libxenstat/Makefile 
b/tools/xenstat/libxenstat/Makefile
--- 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 @@ LIB=src/libxenstat.a
 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
--- 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>
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
 #include <stdlib.h>
+#include <string.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
- */
-#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 "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 * han
                        collectors[i].uninit(handle);
                xc_interface_close(handle->xc_handle);
                xs_daemon_close(handle->xshandle);
+               free(handle->priv);
                free(handle);
        }
 }
@@ -586,110 +511,12 @@ unsigned long long xenstat_vcpu_ns(xenst
  * 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)
 {
        unsigned int i;
        for (i = 0; i < node->num_domains; i++)
                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 */
@@ -790,109 +617,12 @@ static void xenstat_uninit_xen_version(x
  * 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)
 {
        unsigned int i;
        for (i = 0; i < node->num_domains; i++)
                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 */
@@ -948,4 +678,3 @@ static void xenstat_prune_domain(xenstat
           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
--- a/tools/xenstat/libxenstat/src/xenstat.h
+++ b/tools/xenstat/libxenstat/src/xenstat.h
@@ -16,6 +16,9 @@
  */
 
 /* libxenstat API */
+
+#ifndef XENSTAT_H
+#define XENSTAT_H
 
 /* Opaque handles */
 typedef struct xenstat_handle xenstat_handle;
@@ -176,3 +179,5 @@ unsigned long long xenstat_vbd_oo_reqs(x
 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
--- /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@xxxxxxxxxx>
+ *          Judy Fischbach <jfisch@xxxxxxxxxx>
+ *          David Hendricks <dhendrix@xxxxxxxxxx>
+ *
+ * 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
--- /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@xxxxxxxxxx>
+ *          Judy Fischbach <jfisch@xxxxxxxxxx>
+ *          David Hendricks <dhendrix@xxxxxxxxxx>
+ *
+ * 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
--- /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
--- a/tools/xenstat/xentop/xentop.c
+++ b/tools/xenstat/xentop/xentop.c
@@ -52,7 +52,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 *
@@ -924,7 +928,7 @@ void do_vbd(xenstat_domain *domain)
                      xenstat_vbd_rd_reqs(vbd),
                      xenstat_vbd_wr_reqs(vbd));
 #else
-               print("VBD %4u OO: %8llu   RD: %8llu   WR: %8llu\n",
+               print("VBD %4d OO: %8llu   RD: %8llu   WR: %8llu\n",
                      xenstat_vbd_dev(vbd),
                      xenstat_vbd_oo_reqs(vbd),
                      xenstat_vbd_rd_reqs(vbd),

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.