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 \
#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;
-I@top_srcdir@/daemon \
$(LIBXML_CFLAGS) \
$(LIBSSH2_CFLAGS) \
- $(XEN_CFLAGS) \
$(SELINUX_CFLAGS) \
$(DRIVER_MODULE_CFLAGS) \
-DLIBDIR=\""$(libdir)"\" \
# 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 = \
$(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
#include "test.h"
#endif
#ifdef WITH_XEN
-#include "xen_unified.h"
+#include "xen/xen_driver.h"
#endif
#ifdef WITH_REMOTE
#include "remote_internal.h"
#include <stdio.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
+#include <sys/un.h>
#if HAVE_SCHED_H
#include <sched.h>
#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"
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.
#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__ */
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/inotify.h>
+#include <sys/un.h>
#include "uml_driver.h"
#include "uml_conf.h"
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
#include "driver.h"
#include "proxy_internal.h"
#include "util.h"
-#include "xen_unified.h"
+#include "xen_driver.h"
#include "memory.h"
#define STANDALONE
/*
- * xen_unified.c: Unified Xen driver.
+ * xen_driver.c: Unified Xen driver.
*
* Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
*
#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"
#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"
#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"
#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"
#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"
#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
#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"
#include "stats_linux.h"
#include "internal.h"
-
+#include "xen/block_stats.h"
#include "testutils.h"
#if WITH_XEN
#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;
#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"
#include <unistd.h>
#include "internal.h"
-#include "xend_internal.h"
+#include "xen/xend_internal.h"
#include "testutils.h"
#include "testutilsxen.h"