]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Move xen driver code into src/xen/ directory
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 15 Sep 2009 15:38:33 +0000 (16:38 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 21 Sep 2009 13:41:42 +0000 (14:41 +0100)
* src/Makefile.am, src/proxy_internal.c, src/proxy_internal.h
  src/sexpr.c, src/sexpr.h, src/xen_unified.c, src/xen_unified.h,
  src/xen_internal.c, src/xen_internal.h, src/xen_inotify.c,
  src/xen_inotify.h, src/xend_internal.c, src/xend_internal.h,
  src/xm_internal.c, src/xm_internal.h, src/xs_internal.c,
  src/xs_internal.h: Move to src/xen/ directory
* proxy/Makefile.am, proxy/libvirt_proxy.c, src/Makefile.am,
  src/libvirt.c, tests/sexpr2xmltest.c, tests/statstest.c,
  tests/xencapstest.c, tests/xmconfigtest.c, tests/xml2sexprtest.c:
  Adapt to changed xen location
* src/stats_linux.h, src/stats_linux.c: Remove xen specific block
  stats APIs
* src/qemu_driver.c, src/uml_driver.c: Add missing sys/un.h include
  uncovered after change to stats_linux.h
* src/xen/block_stats.h, src/xen/block_stats.c: Add xen specific
  block stats APIs

31 files changed:
proxy/Makefile.am
proxy/libvirt_proxy.c
src/Makefile.am
src/libvirt.c
src/qemu_driver.c
src/stats_linux.c
src/stats_linux.h
src/uml_driver.c
src/xen/block_stats.c [new file with mode: 0644]
src/xen/block_stats.h [new file with mode: 0644]
src/xen/proxy_internal.c [moved from src/proxy_internal.c with 99% similarity]
src/xen/proxy_internal.h [moved from src/proxy_internal.h with 100% similarity]
src/xen/sexpr.c [moved from src/sexpr.c with 100% similarity]
src/xen/sexpr.h [moved from src/sexpr.h with 100% similarity]
src/xen/xen_driver.c [moved from src/xen_unified.c with 99% similarity]
src/xen/xen_driver.h [moved from src/xen_unified.h with 100% similarity]
src/xen/xen_hypervisor.c [moved from src/xen_internal.c with 99% similarity]
src/xen/xen_hypervisor.h [moved from src/xen_internal.h with 100% similarity]
src/xen/xen_inotify.c [moved from src/xen_inotify.c with 99% similarity]
src/xen/xen_inotify.h [moved from src/xen_inotify.h with 100% similarity]
src/xen/xend_internal.c [moved from src/xend_internal.c with 99% similarity]
src/xen/xend_internal.h [moved from src/xend_internal.h with 100% similarity]
src/xen/xm_internal.c [moved from src/xm_internal.c with 99% similarity]
src/xen/xm_internal.h [moved from src/xm_internal.h with 100% similarity]
src/xen/xs_internal.c [moved from src/xs_internal.c with 99% similarity]
src/xen/xs_internal.h [moved from src/xs_internal.h with 100% similarity]
tests/sexpr2xmltest.c
tests/statstest.c
tests/xencapstest.c
tests/xmconfigtest.c
tests/xml2sexprtest.c

index 48678c3bab956fc5d18b1161fb7d217738b79b47..e92333ae1050a8ac0558935db2945d0d71f7d1da 100644 (file)
@@ -3,17 +3,17 @@
 if WITH_PROXY
 INCLUDES = -I$(top_srcdir)/gnulib/lib -I../gnulib/lib \
            -I$(top_builddir)/include -I@top_srcdir@/include \
-          -I@top_srcdir@/proxy -I@top_srcdir@/src @LIBXML_CFLAGS@ \
+          -I@top_srcdir@/proxy -I@top_srcdir@/src -I@top_srcdir@/src/xen @LIBXML_CFLAGS@ \
           -DPROXY  -DLOCALEBASEDIR=\""$(datadir)/locale"\" \
            -DGETTEXT_PACKAGE=\"$(PACKAGE)\" $(WARN_CFLAGS) $(XEN_CFLAGS)
 
 libexec_PROGRAMS = libvirt_proxy
 
-libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
-           @top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \
-           @top_srcdir@/src/sexpr.c  \
+libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xen/xend_internal.c \
+           @top_srcdir@/src/xen/xen_hypervisor.c @top_srcdir@/src/virterror.c \
+           @top_srcdir@/src/xen/sexpr.c  \
            @top_srcdir@/src/threads.c  \
-            @top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \
+            @top_srcdir@/src/xen/xs_internal.c @top_srcdir@/src/buf.c \
             @top_srcdir@/src/capabilities.c \
             @top_srcdir@/src/memory.c \
             @top_srcdir@/src/storage_encryption_conf.c \
index e008a7f4be107c4fc728dbbed372099d87b23a3e..aa20d2850feae9176f5cc6b6ba8a308518756359 100644 (file)
 #include "datatypes.h"
 #include "proxy_internal.h"
 #include "util.h"
-#include "xen_internal.h"
+#include "xen_hypervisor.h"
 #include "xend_internal.h"
 #include "xs_internal.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
 
 static int fdServer = -1;
 static int debug = 0;
index b1d01ba42fc2ca2ad52fbdc3cab1416e8ee7045b..52f0c24bf8ab59a2f1d86695c791a6bb91b3db9c 100644 (file)
@@ -7,7 +7,6 @@ INCLUDES = \
           -I@top_srcdir@/daemon \
           $(LIBXML_CFLAGS) \
           $(LIBSSH2_CFLAGS) \
-          $(XEN_CFLAGS) \
           $(SELINUX_CFLAGS) \
           $(DRIVER_MODULE_CFLAGS) \
           -DLIBDIR=\""$(libdir)"\" \
@@ -111,15 +110,16 @@ TEST_DRIVER_SOURCES =                                             \
 
 # Now the Hypervisor specific drivers
 XEN_DRIVER_SOURCES =                                           \
-               proxy_internal.c proxy_internal.h               \
-               sexpr.c sexpr.h                                 \
-               xen_internal.c xen_internal.h                   \
-               xen_unified.c xen_unified.h                     \
-               xend_internal.c xend_internal.h                 \
-               xm_internal.c xm_internal.h                     \
-               xs_internal.c xs_internal.h
+               xen/proxy_internal.c xen/proxy_internal.h       \
+               xen/sexpr.c xen/sexpr.h                         \
+               xen/block_stats.c xen/block_stats.h             \
+               xen/xen_hypervisor.c xen/xen_hypervisor.h       \
+               xen/xen_driver.c xen/xen_driver.h               \
+               xen/xend_internal.c xen/xend_internal.h         \
+               xen/xm_internal.c xen/xm_internal.h             \
+               xen/xs_internal.c xen/xs_internal.h
 if WITH_XEN_INOTIFY
-XEN_DRIVER_SOURCES += xen_inotify.c xen_inotify.h
+XEN_DRIVER_SOURCES += xen/xen_inotify.c xen/xen_inotify.h
 endif
 
 LXC_DRIVER_SOURCES =                                           \
@@ -261,8 +261,8 @@ libvirt_driver_la_SOURCES =                                 \
                $(NODE_DEVICE_CONF_SOURCES)                     \
                $(SECRET_CONF_SOURCES)
 
-libvirt_driver_la_CFLAGS = $(XEN_CFLAGS) $(NUMACTL_CFLAGS)
-libvirt_driver_la_LDFLAGS = $(XEN_LIBS) $(NUMACTL_LIBS)
+libvirt_driver_la_CFLAGS = $(NUMACTL_CFLAGS)
+libvirt_driver_la_LDFLAGS = $(NUMACTL_LIBS)
 
 USED_SYM_FILES = libvirt_private.syms
 
index 4a11688312021f7a635f3e38f349cd1affdb39e7..1139d8bc8f8fad370421d44b16a3a658b1d927bf 100644 (file)
@@ -47,7 +47,7 @@
 #include "test.h"
 #endif
 #ifdef WITH_XEN
-#include "xen_unified.h"
+#include "xen/xen_driver.h"
 #endif
 #ifdef WITH_REMOTE
 #include "remote_internal.h"
index 2ddcdc0f6e4d6af910d5618d9e851c82aee0842e..068b0642f3f2861956b3ece84900d7b0ef999b6b 100644 (file)
@@ -44,6 +44,7 @@
 #include <stdio.h>
 #include <sys/wait.h>
 #include <sys/ioctl.h>
+#include <sys/un.h>
 
 #if HAVE_SCHED_H
 #include <sched.h>
index eccda9466a7701f0a50aca24e09f221ac7f3d783..7d8a5f9e0ade7e7fa65e48f6de87196e30151443 100644 (file)
 #include <unistd.h>
 #include <regex.h>
 
-#ifdef WITH_XEN
-#include <xs.h>
-#endif
-
 #include "virterror_internal.h"
 #include "datatypes.h"
 #include "util.h"
-#include "xen_unified.h"
 #include "stats_linux.h"
 #include "memory.h"
 
@@ -63,315 +58,6 @@ statsErrorFunc (virConnectPtr conn,
                     value);
 }
 
-#ifdef WITH_XEN
-/*-------------------- Xen: block stats --------------------*/
-
-#include <linux/major.h>
-
-/* This is normally defined in <linux/major.h> but previously we
- * hard-coded it.  So if it's not defined, hard-code again.
- */
-#ifndef XENVBD_MAJOR
-#define XENVBD_MAJOR 202
-#endif
-
-static int
-xstrtoint64 (char const *s, int base, int64_t *result)
-{
-    long long int lli;
-    char *p;
-
-    errno = 0;
-    lli = strtoll (s, &p, base);
-    if (errno || !(*p == 0 || *p == '\n') || p == s || (int64_t) lli != lli)
-        return -1;
-    *result = lli;
-    return 0;
-}
-
-static int64_t
-read_stat (const char *path)
-{
-    char str[64];
-    int64_t r;
-    int i;
-    FILE *fp;
-
-    fp = fopen (path, "r");
-    if (!fp)
-      return -1;
-
-    /* read, but don't bail out before closing */
-    i = fread (str, 1, sizeof str - 1, fp);
-
-    if (fclose (fp) != 0        /* disk error */
-        || i < 1)               /* ensure we read at least one byte */
-        return -1;
-
-    str[i] = '\0';              /* make sure the string is nul-terminated */
-    if (xstrtoint64 (str, 10, &r) == -1)
-        return -1;
-
-    return r;
-}
-
-static int64_t
-read_bd_stat (int device, int domid, const char *str)
-{
-    char path[PATH_MAX];
-    int64_t r;
-
-    snprintf (path, sizeof path,
-              "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s",
-              domid, device, str);
-    r = read_stat (path);
-    if (r >= 0) return r;
-
-    snprintf (path, sizeof path,
-              "/sys/devices/xen-backend/tap-%d-%d/statistics/%s",
-              domid, device, str);
-    r = read_stat (path);
-    return r;
-}
-
-/* In Xenstore, /local/domain/0/backend/vbd/<domid>/<device>/state,
- * if available, must be XenbusStateConnected (= 4), otherwise there
- * is no connected device.
- */
-static int
-check_bd_connected (xenUnifiedPrivatePtr priv, int device, int domid)
-{
-    char s[256], *rs;
-    int r;
-    unsigned len = 0;
-
-    /* This code assumes we're connected if we can't get to
-     * xenstore, etc.
-     */
-    if (!priv->xshandle) return 1;
-    snprintf (s, sizeof s, "/local/domain/0/backend/vbd/%d/%d/state",
-              domid, device);
-    s[sizeof s - 1] = '\0';
-
-    rs = xs_read (priv->xshandle, 0, s, &len);
-    if (!rs) return 1;
-    if (len == 0) {
-        /* Hmmm ... we can get to xenstore but it returns an empty
-         * string instead of an error.  Assume it's not connected
-         * in this case.
-         */
-        free (rs);
-        return 0;
-    }
-
-    r = STREQ (rs, "4");
-    free (rs);
-    return r;
-}
-
-static int
-read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv,
-               int device, int domid, struct _virDomainBlockStats *stats)
-{
-    stats->rd_req   = read_bd_stat (device, domid, "rd_req");
-    stats->rd_bytes = read_bd_stat (device, domid, "rd_sect");
-    stats->wr_req   = read_bd_stat (device, domid, "wr_req");
-    stats->wr_bytes = read_bd_stat (device, domid, "wr_sect");
-    stats->errs     = read_bd_stat (device, domid, "oo_req");
-
-    /* None of the files were found - it's likely that this version
-     * of Xen is an old one which just doesn't support stats collection.
-     */
-    if (stats->rd_req == -1 && stats->rd_bytes == -1 &&
-        stats->wr_req == -1 && stats->wr_bytes == -1 &&
-        stats->errs == -1) {
-        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "Failed to read any block statistics", domid);
-        return -1;
-    }
-
-    /* If stats are all zero then either there really isn't any block
-     * device activity, or there is no connected front end device
-     * in which case there are no stats.
-     */
-    if (stats->rd_req == 0 && stats->rd_bytes == 0 &&
-        stats->wr_req == 0 && stats->wr_bytes == 0 &&
-        stats->errs == 0 &&
-        !check_bd_connected (priv, device, domid)) {
-        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                        "Frontend block device not connected", domid);
-        return -1;
-    }
-
-    /* 'Bytes' was really sectors when we read it.  Scale up by
-     * an assumed sector size.
-     */
-    if (stats->rd_bytes > 0) {
-        if (stats->rd_bytes >= ((unsigned long long)1)<<(63-9)) {
-            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                            "stats->rd_bytes would overflow 64 bit counter",
-                            domid);
-            return -1;
-        }
-        stats->rd_bytes *= 512;
-    }
-    if (stats->wr_bytes > 0) {
-        if (stats->wr_bytes >= ((unsigned long long)1)<<(63-9)) {
-            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
-                            "stats->wr_bytes would overflow 64 bit counter",
-                            domid);
-            return -1;
-        }
-        stats->wr_bytes *= 512;
-    }
-
-    return 0;
-}
-
-static int
-disk_re_match(const char *regex, const char *path, int *part)
-{
-    regex_t myreg;
-    int err;
-    int retval;
-    regmatch_t pmatch[3];
-
-    retval = 0;
-
-    err = regcomp(&myreg, regex, REG_EXTENDED);
-    if (err != 0)
-        return 0;
-
-    err = regexec(&myreg, path, 3, pmatch, 0);
-
-    if (err == 0) {
-        /* OK, we have a match; see if we have a partition */
-        *part = 0;
-        retval = 1;
-        if (pmatch[1].rm_so != -1) {
-            if (virStrToLong_i(path + pmatch[1].rm_so, NULL, 10, part) < 0)
-                retval = 0;
-        }
-    }
-
-    regfree(&myreg);
-
-    return retval;
-}
-
-int
-xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
-{
-    int major, minor;
-    int part;
-    int retval;
-    char *mod_path;
-
-    int const scsi_majors[] = { SCSI_DISK0_MAJOR, SCSI_DISK1_MAJOR,
-                                SCSI_DISK2_MAJOR, SCSI_DISK3_MAJOR,
-                                SCSI_DISK4_MAJOR, SCSI_DISK5_MAJOR,
-                                SCSI_DISK6_MAJOR, SCSI_DISK7_MAJOR,
-                                SCSI_DISK8_MAJOR, SCSI_DISK9_MAJOR,
-                                SCSI_DISK10_MAJOR, SCSI_DISK11_MAJOR,
-                                SCSI_DISK12_MAJOR, SCSI_DISK13_MAJOR,
-                                SCSI_DISK14_MAJOR, SCSI_DISK15_MAJOR };
-    int const ide_majors[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
-                               IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR,
-                               IDE8_MAJOR, IDE9_MAJOR };
-
-    /*
-     * Possible block device majors & partition ranges. This
-     * matches the ranges supported in Xend xen/util/blkif.py
-     *
-     * hdNM:  N=a-t, M=1-63, major={IDE0_MAJOR -> IDE9_MAJOR}
-     * sdNM:  N=a-z,aa-iv, M=1-15, major={SCSI_DISK0_MAJOR -> SCSI_DISK15_MAJOR}
-     * xvdNM: N=a-p M=1-15, major=XENVBD_MAJOR
-     * xvdNM: N=q-z,aa-iz M=1-15, major=(1<<28)
-     *
-     * The path for statistics will be
-     *
-     * /sys/devices/xen-backend/(vbd|tap)-{domid}-{devid}/statistics/{...}
-     */
-
-    if (strlen(path) >= 5 && STRPREFIX(path, "/dev/"))
-        retval = virAsprintf(&mod_path, "%s", path);
-    else
-        retval = virAsprintf(&mod_path, "/dev/%s", path);
-
-    if (retval < 0) {
-        virReportOOMError (conn);
-        return -1;
-    }
-
-    retval = -1;
-
-    if (disk_re_match("/dev/sd[a-z]([1-9]|1[0-5])?$", mod_path, &part)) {
-        major = scsi_majors[(mod_path[7] - 'a') / 16];
-        minor = ((mod_path[7] - 'a') % 16) * 16 + part;
-        retval = major * 256 + minor;
-    }
-    else if (disk_re_match("/dev/sd[a-h][a-z]([1-9]|1[0-5])?$",
-                           mod_path, &part) ||
-             disk_re_match("/dev/sdi[a-v]([1-9]|1[0-5])?$",
-                           mod_path, &part)) {
-        major = scsi_majors[((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) / 16];
-        minor = (((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) % 16)
-            * 16 + part;
-        retval = major * 256 + minor;
-    }
-    else if (disk_re_match("/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$",
-                           mod_path, &part)) {
-        major = ide_majors[(mod_path[7] - 'a') / 2];
-        minor = ((mod_path[7] - 'a') % 2) * 64 + part;
-        retval = major * 256 + minor;
-    }
-    else if (disk_re_match("/dev/xvd[a-p]([1-9]|1[0-5])?$", mod_path, &part))
-        retval = (202 << 8) + ((mod_path[8] - 'a') << 4) + part;
-    else if (disk_re_match("/dev/xvd[q-z]([1-9]|1[0-5])?$", mod_path, &part))
-        retval = (1 << 28) + ((mod_path[8] - 'a') << 8) + part;
-    else if (disk_re_match("/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$",
-                           mod_path, &part))
-        retval = (1 << 28) + (((mod_path[8] - 'a' + 1) * 26 + (mod_path[9] - 'a')) << 8) + part;
-    /*
-     * OK, we've now checked the common case (things that work); check the
-     * beginning of the strings for better error messages
-     */
-    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd"))
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid path, device names must be in the range sda[1-15] - sdiv[1-15]",
-                        domid);
-    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd"))
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid path, device names must be in the range hda[1-63] - hdt[1-63]",
-                        domid);
-    else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd"))
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "invalid path, device names must be in the range xvda[1-15] - xvdiz[1-15]",
-                        domid);
-    else
-        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
-                        "unsupported path, use xvdN, hdN, or sdN", domid);
-
-    VIR_FREE(mod_path);
-
-    return retval;
-}
-
-int
-xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
-                          virDomainPtr dom,
-                          const char *path,
-                          struct _virDomainBlockStats *stats)
-{
-    int device = xenLinuxDomainDeviceID(dom->conn, dom->id, path);
-
-    if (device < 0)
-        return -1;
-
-    return read_bd_stats (dom->conn, priv, device, dom->id, stats);
-}
-
-#endif /* WITH_XEN */
 
 /*-------------------- interface stats --------------------*/
 /* Just reads the named interface, so not Xen or QEMU-specific.
index 076ccd7c8a649e3eb5475e90d4f2aa9398a94d68..033a50b64399c55f23519169d00639423b2ae894 100644 (file)
 
 #ifdef __linux__
 
-#include "xen_unified.h"
+#include "internal.h"
 
-extern int xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
-                                     virDomainPtr dom, const char *path,
-                                     struct _virDomainBlockStats *stats);
 extern int linuxDomainInterfaceStats (virConnectPtr conn, const char *path,
                                       struct _virDomainInterfaceStats *stats);
 
-extern int xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *dev);
-
 #endif /* __linux__ */
 
 #endif /* __STATS_LINUX_H__ */
index a2b949551d41206096852878776e4aa1e10b9b1e..c2898f72cbfb11cf2fc1f18fc624cd1b2b0344a2 100644 (file)
@@ -44,6 +44,7 @@
 #include <sys/wait.h>
 #include <sys/ioctl.h>
 #include <sys/inotify.h>
+#include <sys/un.h>
 
 #include "uml_driver.h"
 #include "uml_conf.h"
diff --git a/src/xen/block_stats.c b/src/xen/block_stats.c
new file mode 100644 (file)
index 0000000..73b94c1
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Linux block and network stats.
+ *
+ * Copyright (C) 2007-2009 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Richard W.M. Jones <rjones@redhat.com>
+ */
+
+#include <config.h>
+
+/* This file only applies on Linux. */
+#ifdef __linux__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <regex.h>
+
+#include <xs.h>
+
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "util.h"
+#include "block_stats.h"
+#include "memory.h"
+
+#define VIR_FROM_THIS VIR_FROM_STATS_LINUX
+
+/**
+ * statsErrorFunc:
+ * @conn: the connection
+ * @error: the error number
+ * @func: the function failing
+ * @info: extra information string
+ * @value: extra information number
+ *
+ * Handle a stats error.
+ */
+static void
+statsErrorFunc (virConnectPtr conn,
+                virErrorNumber error, const char *func, const char *info,
+                int value)
+{
+    char fullinfo[1000];
+    const char *errmsg;
+
+    errmsg = virErrorMsg(error, info);
+    if (func != NULL) {
+        snprintf(fullinfo, sizeof (fullinfo) - 1, "%s: %s", func, info);
+        fullinfo[sizeof (fullinfo) - 1] = 0;
+        info = fullinfo;
+    }
+    virRaiseError(conn, NULL, NULL, VIR_FROM_STATS_LINUX, error,
+                    VIR_ERR_ERROR,
+                    errmsg, info, NULL, value, 0, errmsg, info,
+                    value);
+}
+
+/*-------------------- Xen: block stats --------------------*/
+
+#include <linux/major.h>
+
+/* This is normally defined in <linux/major.h> but previously we
+ * hard-coded it.  So if it's not defined, hard-code again.
+ */
+#ifndef XENVBD_MAJOR
+#define XENVBD_MAJOR 202
+#endif
+
+static int
+xstrtoint64 (char const *s, int base, int64_t *result)
+{
+    long long int lli;
+    char *p;
+
+    errno = 0;
+    lli = strtoll (s, &p, base);
+    if (errno || !(*p == 0 || *p == '\n') || p == s || (int64_t) lli != lli)
+        return -1;
+    *result = lli;
+    return 0;
+}
+
+static int64_t
+read_stat (const char *path)
+{
+    char str[64];
+    int64_t r;
+    int i;
+    FILE *fp;
+
+    fp = fopen (path, "r");
+    if (!fp)
+      return -1;
+
+    /* read, but don't bail out before closing */
+    i = fread (str, 1, sizeof str - 1, fp);
+
+    if (fclose (fp) != 0        /* disk error */
+        || i < 1)               /* ensure we read at least one byte */
+        return -1;
+
+    str[i] = '\0';              /* make sure the string is nul-terminated */
+    if (xstrtoint64 (str, 10, &r) == -1)
+        return -1;
+
+    return r;
+}
+
+static int64_t
+read_bd_stat (int device, int domid, const char *str)
+{
+    char path[PATH_MAX];
+    int64_t r;
+
+    snprintf (path, sizeof path,
+              "/sys/devices/xen-backend/vbd-%d-%d/statistics/%s",
+              domid, device, str);
+    r = read_stat (path);
+    if (r >= 0) return r;
+
+    snprintf (path, sizeof path,
+              "/sys/devices/xen-backend/tap-%d-%d/statistics/%s",
+              domid, device, str);
+    r = read_stat (path);
+    return r;
+}
+
+/* In Xenstore, /local/domain/0/backend/vbd/<domid>/<device>/state,
+ * if available, must be XenbusStateConnected (= 4), otherwise there
+ * is no connected device.
+ */
+static int
+check_bd_connected (xenUnifiedPrivatePtr priv, int device, int domid)
+{
+    char s[256], *rs;
+    int r;
+    unsigned len = 0;
+
+    /* This code assumes we're connected if we can't get to
+     * xenstore, etc.
+     */
+    if (!priv->xshandle) return 1;
+    snprintf (s, sizeof s, "/local/domain/0/backend/vbd/%d/%d/state",
+              domid, device);
+    s[sizeof s - 1] = '\0';
+
+    rs = xs_read (priv->xshandle, 0, s, &len);
+    if (!rs) return 1;
+    if (len == 0) {
+        /* Hmmm ... we can get to xenstore but it returns an empty
+         * string instead of an error.  Assume it's not connected
+         * in this case.
+         */
+        free (rs);
+        return 0;
+    }
+
+    r = STREQ (rs, "4");
+    free (rs);
+    return r;
+}
+
+static int
+read_bd_stats (virConnectPtr conn, xenUnifiedPrivatePtr priv,
+               int device, int domid, struct _virDomainBlockStats *stats)
+{
+    stats->rd_req   = read_bd_stat (device, domid, "rd_req");
+    stats->rd_bytes = read_bd_stat (device, domid, "rd_sect");
+    stats->wr_req   = read_bd_stat (device, domid, "wr_req");
+    stats->wr_bytes = read_bd_stat (device, domid, "wr_sect");
+    stats->errs     = read_bd_stat (device, domid, "oo_req");
+
+    /* None of the files were found - it's likely that this version
+     * of Xen is an old one which just doesn't support stats collection.
+     */
+    if (stats->rd_req == -1 && stats->rd_bytes == -1 &&
+        stats->wr_req == -1 && stats->wr_bytes == -1 &&
+        stats->errs == -1) {
+        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "Failed to read any block statistics", domid);
+        return -1;
+    }
+
+    /* If stats are all zero then either there really isn't any block
+     * device activity, or there is no connected front end device
+     * in which case there are no stats.
+     */
+    if (stats->rd_req == 0 && stats->rd_bytes == 0 &&
+        stats->wr_req == 0 && stats->wr_bytes == 0 &&
+        stats->errs == 0 &&
+        !check_bd_connected (priv, device, domid)) {
+        statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                        "Frontend block device not connected", domid);
+        return -1;
+    }
+
+    /* 'Bytes' was really sectors when we read it.  Scale up by
+     * an assumed sector size.
+     */
+    if (stats->rd_bytes > 0) {
+        if (stats->rd_bytes >= ((unsigned long long)1)<<(63-9)) {
+            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                            "stats->rd_bytes would overflow 64 bit counter",
+                            domid);
+            return -1;
+        }
+        stats->rd_bytes *= 512;
+    }
+    if (stats->wr_bytes > 0) {
+        if (stats->wr_bytes >= ((unsigned long long)1)<<(63-9)) {
+            statsErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
+                            "stats->wr_bytes would overflow 64 bit counter",
+                            domid);
+            return -1;
+        }
+        stats->wr_bytes *= 512;
+    }
+
+    return 0;
+}
+
+static int
+disk_re_match(const char *regex, const char *path, int *part)
+{
+    regex_t myreg;
+    int err;
+    int retval;
+    regmatch_t pmatch[3];
+
+    retval = 0;
+
+    err = regcomp(&myreg, regex, REG_EXTENDED);
+    if (err != 0)
+        return 0;
+
+    err = regexec(&myreg, path, 3, pmatch, 0);
+
+    if (err == 0) {
+        /* OK, we have a match; see if we have a partition */
+        *part = 0;
+        retval = 1;
+        if (pmatch[1].rm_so != -1) {
+            if (virStrToLong_i(path + pmatch[1].rm_so, NULL, 10, part) < 0)
+                retval = 0;
+        }
+    }
+
+    regfree(&myreg);
+
+    return retval;
+}
+
+int
+xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *path)
+{
+    int major, minor;
+    int part;
+    int retval;
+    char *mod_path;
+
+    int const scsi_majors[] = { SCSI_DISK0_MAJOR, SCSI_DISK1_MAJOR,
+                                SCSI_DISK2_MAJOR, SCSI_DISK3_MAJOR,
+                                SCSI_DISK4_MAJOR, SCSI_DISK5_MAJOR,
+                                SCSI_DISK6_MAJOR, SCSI_DISK7_MAJOR,
+                                SCSI_DISK8_MAJOR, SCSI_DISK9_MAJOR,
+                                SCSI_DISK10_MAJOR, SCSI_DISK11_MAJOR,
+                                SCSI_DISK12_MAJOR, SCSI_DISK13_MAJOR,
+                                SCSI_DISK14_MAJOR, SCSI_DISK15_MAJOR };
+    int const ide_majors[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
+                               IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR,
+                               IDE8_MAJOR, IDE9_MAJOR };
+
+    /*
+     * Possible block device majors & partition ranges. This
+     * matches the ranges supported in Xend xen/util/blkif.py
+     *
+     * hdNM:  N=a-t, M=1-63, major={IDE0_MAJOR -> IDE9_MAJOR}
+     * sdNM:  N=a-z,aa-iv, M=1-15, major={SCSI_DISK0_MAJOR -> SCSI_DISK15_MAJOR}
+     * xvdNM: N=a-p M=1-15, major=XENVBD_MAJOR
+     * xvdNM: N=q-z,aa-iz M=1-15, major=(1<<28)
+     *
+     * The path for statistics will be
+     *
+     * /sys/devices/xen-backend/(vbd|tap)-{domid}-{devid}/statistics/{...}
+     */
+
+    if (strlen(path) >= 5 && STRPREFIX(path, "/dev/"))
+        retval = virAsprintf(&mod_path, "%s", path);
+    else
+        retval = virAsprintf(&mod_path, "/dev/%s", path);
+
+    if (retval < 0) {
+        virReportOOMError (conn);
+        return -1;
+    }
+
+    retval = -1;
+
+    if (disk_re_match("/dev/sd[a-z]([1-9]|1[0-5])?$", mod_path, &part)) {
+        major = scsi_majors[(mod_path[7] - 'a') / 16];
+        minor = ((mod_path[7] - 'a') % 16) * 16 + part;
+        retval = major * 256 + minor;
+    }
+    else if (disk_re_match("/dev/sd[a-h][a-z]([1-9]|1[0-5])?$",
+                           mod_path, &part) ||
+             disk_re_match("/dev/sdi[a-v]([1-9]|1[0-5])?$",
+                           mod_path, &part)) {
+        major = scsi_majors[((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) / 16];
+        minor = (((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) % 16)
+            * 16 + part;
+        retval = major * 256 + minor;
+    }
+    else if (disk_re_match("/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$",
+                           mod_path, &part)) {
+        major = ide_majors[(mod_path[7] - 'a') / 2];
+        minor = ((mod_path[7] - 'a') % 2) * 64 + part;
+        retval = major * 256 + minor;
+    }
+    else if (disk_re_match("/dev/xvd[a-p]([1-9]|1[0-5])?$", mod_path, &part))
+        retval = (202 << 8) + ((mod_path[8] - 'a') << 4) + part;
+    else if (disk_re_match("/dev/xvd[q-z]([1-9]|1[0-5])?$", mod_path, &part))
+        retval = (1 << 28) + ((mod_path[8] - 'a') << 8) + part;
+    else if (disk_re_match("/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$",
+                           mod_path, &part))
+        retval = (1 << 28) + (((mod_path[8] - 'a' + 1) * 26 + (mod_path[9] - 'a')) << 8) + part;
+    /*
+     * OK, we've now checked the common case (things that work); check the
+     * beginning of the strings for better error messages
+     */
+    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd"))
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid path, device names must be in the range sda[1-15] - sdiv[1-15]",
+                        domid);
+    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd"))
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid path, device names must be in the range hda[1-63] - hdt[1-63]",
+                        domid);
+    else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd"))
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "invalid path, device names must be in the range xvda[1-15] - xvdiz[1-15]",
+                        domid);
+    else
+        statsErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
+                        "unsupported path, use xvdN, hdN, or sdN", domid);
+
+    VIR_FREE(mod_path);
+
+    return retval;
+}
+
+int
+xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
+                          virDomainPtr dom,
+                          const char *path,
+                          struct _virDomainBlockStats *stats)
+{
+    int device = xenLinuxDomainDeviceID(dom->conn, dom->id, path);
+
+    if (device < 0)
+        return -1;
+
+    return read_bd_stats (dom->conn, priv, device, dom->id, stats);
+}
+
+#endif /* __linux__ */
diff --git a/src/xen/block_stats.h b/src/xen/block_stats.h
new file mode 100644 (file)
index 0000000..e29c0b5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Linux block and network stats.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Richard W.M. Jones <rjones@redhat.com>
+ */
+
+#ifndef __BLOCK_STATS_H__
+#define __BLOCK_STATS_H__
+
+#ifdef __linux__
+
+#include "xen_driver.h"
+
+extern int xenLinuxDomainBlockStats (xenUnifiedPrivatePtr priv,
+                                     virDomainPtr dom, const char *path,
+                                     struct _virDomainBlockStats *stats);
+
+extern int xenLinuxDomainDeviceID(virConnectPtr conn, int domid, const char *dev);
+
+#endif /* __linux__ */
+
+#endif /* __STATS_LINUX_H__ */
similarity index 99%
rename from src/proxy_internal.c
rename to src/xen/proxy_internal.c
index 5b92ad82529ac906aa0687febe650ba1168ae8c7..49127d7cf229bf779fac1f2186c42ef41c0be0f8 100644 (file)
@@ -28,7 +28,7 @@
 #include "driver.h"
 #include "proxy_internal.h"
 #include "util.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
 #include "memory.h"
 
 #define STANDALONE
similarity index 100%
rename from src/sexpr.c
rename to src/xen/sexpr.c
similarity index 100%
rename from src/sexpr.h
rename to src/xen/sexpr.h
similarity index 99%
rename from src/xen_unified.c
rename to src/xen/xen_driver.c
index dfa9ca57c1d78de8b5b671ce976ed496ab3f83cf..3dd023756d1fbc6d718465e8f76b555a5935ea7f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * xen_unified.c: Unified Xen driver.
+ * xen_driver.c: Unified Xen driver.
  *
  * Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
  *
@@ -30,9 +30,9 @@
 #include "virterror_internal.h"
 #include "logging.h"
 #include "datatypes.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
 
-#include "xen_internal.h"
+#include "xen_hypervisor.h"
 #include "proxy_internal.h"
 #include "xend_internal.h"
 #include "xs_internal.h"
similarity index 100%
rename from src/xen_unified.h
rename to src/xen/xen_driver.h
similarity index 99%
rename from src/xen_internal.c
rename to src/xen/xen_hypervisor.c
index 30fd8bd1955d3da2124a6d85a838dd6783b092a9..9f3f5fe797ce8445b12626d004cbe8bde1058b1f 100644 (file)
 #include "datatypes.h"
 #include "driver.h"
 #include "util.h"
-#include "xen_unified.h"
-#include "xen_internal.h"
+#include "xen_driver.h"
+#include "xen_hypervisor.h"
 #include "xs_internal.h"
 #include "stats_linux.h"
+#include "block_stats.h"
 #include "xend_internal.h"
 #include "buf.h"
 #include "capabilities.h"
similarity index 100%
rename from src/xen_internal.h
rename to src/xen/xen_hypervisor.h
similarity index 99%
rename from src/xen_inotify.c
rename to src/xen/xen_inotify.c
index e312b9eb1c682cfd10357fb89c3780a3f04bcdde..7deb1dbe99eda06fd6033956e153fcf77e71eb5b 100644 (file)
@@ -31,7 +31,7 @@
 #include "driver.h"
 #include "memory.h"
 #include "event.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
 #include "conf.h"
 #include "domain_conf.h"
 #include "xen_inotify.h"
similarity index 100%
rename from src/xen_inotify.h
rename to src/xen/xen_inotify.h
similarity index 99%
rename from src/xend_internal.c
rename to src/xen/xend_internal.c
index 7f55116c74eb43d65c9a9d37bc8f8707389fdec7..350ef8ce1355935617da6f533d33f5314300436f 100644 (file)
@@ -41,8 +41,8 @@
 #include "sexpr.h"
 #include "buf.h"
 #include "uuid.h"
-#include "xen_unified.h"
-#include "xen_internal.h"
+#include "xen_driver.h"
+#include "xen_hypervisor.h"
 #include "xs_internal.h" /* To extract VNC port & Serial console TTY */
 #include "memory.h"
 
similarity index 100%
rename from src/xend_internal.h
rename to src/xen/xend_internal.h
similarity index 99%
rename from src/xm_internal.c
rename to src/xen/xm_internal.c
index de3aca9e9d4e4a4e2fb6b7edd1acf8d543fc749d..960b17af3d09864e65e742c0303c8bce778c248d 100644 (file)
@@ -38,7 +38,7 @@
 #include "virterror_internal.h"
 #include "datatypes.h"
 #include "xm_internal.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
 #include "xend_internal.h"
 #include "hash.h"
 #include "buf.h"
similarity index 100%
rename from src/xm_internal.h
rename to src/xen/xm_internal.h
similarity index 99%
rename from src/xs_internal.c
rename to src/xen/xs_internal.c
index 1f54b1f0e7c70410ec5c0b176c1655ddfcf68186..494728d6390d0637bc4c345b17dce060d65ac673 100644 (file)
@@ -33,9 +33,9 @@
 #include "event.h"
 #include "logging.h"
 #include "uuid.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
 #include "xs_internal.h"
-#include "xen_internal.h"
+#include "xen_hypervisor.h"
 
 #define VIR_FROM_THIS VIR_FROM_XEN
 
similarity index 100%
rename from src/xs_internal.h
rename to src/xen/xs_internal.h
index 7b834a92002712a8f956380886741397e01aa47b..1196e234686dcff4a3cfd3d1817b41dd45620eb6 100644 (file)
@@ -7,8 +7,8 @@
 #include "internal.h"
 #include "xml.h"
 #include "datatypes.h"
-#include "xen_unified.h"
-#include "xend_internal.h"
+#include "xen/xen_driver.h"
+#include "xen/xend_internal.h"
 #include "testutils.h"
 #include "testutilsxen.h"
 
index 5b7d35a58c0cd1b6885feb5c9996ddbbea76542b..82c0daa3951ebabd6485b5d38720cc4123f6857a 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "stats_linux.h"
 #include "internal.h"
-
+#include "xen/block_stats.h"
 #include "testutils.h"
 
 #if WITH_XEN
index c01efc0544b495cbc05db7b9b5c1decd6241fd56..8f3fb3eb6523ea424ef54b169e09c383cca37831 100644 (file)
@@ -8,7 +8,7 @@
 #include "internal.h"
 #include "xml.h"
 #include "testutils.h"
-#include "xen_internal.h"
+#include "xen/xen_hypervisor.h"
 
 static char *progname;
 static char *abs_srcdir;
index 2255984248f696aa41915cdfaee7f37abb6e0e51..f6aea5a433d73d962c2740f336b4e5b43b54a487 100644 (file)
@@ -29,8 +29,8 @@
 
 #include "internal.h"
 #include "datatypes.h"
-#include "xen_unified.h"
-#include "xm_internal.h"
+#include "xen/xen_driver.h"
+#include "xen/xm_internal.h"
 #include "testutils.h"
 #include "testutilsxen.h"
 #include "memory.h"
index b4ee4e0b2368e4fa37273f10a459638de4b703be..d83b37cc815432d54152b83de8eac5e4c11db81e 100644 (file)
@@ -9,7 +9,7 @@
 #include <unistd.h>
 
 #include "internal.h"
-#include "xend_internal.h"
+#include "xen/xend_internal.h"
 #include "testutils.h"
 #include "testutilsxen.h"