WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Implement VBD and VIF handling on Solaris for libxenstat
From: john.levon@xxxxxxx
Date: Mon, 19 Feb 2007 20:44:56 -0700
Delivery-date: Mon, 19 Feb 2007 20:44:51 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User john.levon@xxxxxxx
# Date 1171946682 28800
# Node ID 24a6bc1d1b93405558741a2a8fa7ba2f7c44964a
# Parent  17420cbf640df753ee2efa8f55b89bf375bef3e7
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

<Prev in Thread] Current Thread [Next in Thread>