diff --git a/proxy/Makefile.am b/proxy/Makefile.am index 48678c3bab..e92333ae10 100644 --- a/proxy/Makefile.am +++ b/proxy/Makefile.am @@ -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 \ diff --git a/proxy/libvirt_proxy.c b/proxy/libvirt_proxy.c index e008a7f4be..aa20d2850f 100644 --- a/proxy/libvirt_proxy.c +++ b/proxy/libvirt_proxy.c @@ -27,10 +27,10 @@ #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; diff --git a/src/Makefile.am b/src/Makefile.am index b1d01ba42f..52f0c24bf8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/libvirt.c b/src/libvirt.c index 4a11688312..1139d8bc8f 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -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" diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 2ddcdc0f6e..068b0642f3 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -44,6 +44,7 @@ #include #include #include +#include #if HAVE_SCHED_H #include diff --git a/src/stats_linux.c b/src/stats_linux.c index eccda9466a..7d8a5f9e0a 100644 --- a/src/stats_linux.c +++ b/src/stats_linux.c @@ -20,14 +20,9 @@ #include #include -#ifdef WITH_XEN -#include -#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 - -/* This is normally defined in 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///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. diff --git a/src/stats_linux.h b/src/stats_linux.h index 076ccd7c8a..033a50b643 100644 --- a/src/stats_linux.h +++ b/src/stats_linux.h @@ -13,16 +13,11 @@ #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__ */ diff --git a/src/uml_driver.c b/src/uml_driver.c index a2b949551d..c2898f72cb 100644 --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -44,6 +44,7 @@ #include #include #include +#include #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 index 0000000000..73b94c161f --- /dev/null +++ b/src/xen/block_stats.c @@ -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 + */ + +#include + +/* This file only applies on Linux. */ +#ifdef __linux__ + +#include +#include +#include +#include +#include +#include + +#include + +#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 + +/* This is normally defined in 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///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 index 0000000000..e29c0b55c5 --- /dev/null +++ b/src/xen/block_stats.h @@ -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 + */ + +#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__ */ diff --git a/src/proxy_internal.c b/src/xen/proxy_internal.c similarity index 99% rename from src/proxy_internal.c rename to src/xen/proxy_internal.c index 5b92ad8252..49127d7cf2 100644 --- a/src/proxy_internal.c +++ b/src/xen/proxy_internal.c @@ -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 diff --git a/src/proxy_internal.h b/src/xen/proxy_internal.h similarity index 100% rename from src/proxy_internal.h rename to src/xen/proxy_internal.h diff --git a/src/sexpr.c b/src/xen/sexpr.c similarity index 100% rename from src/sexpr.c rename to src/xen/sexpr.c diff --git a/src/sexpr.h b/src/xen/sexpr.h similarity index 100% rename from src/sexpr.h rename to src/xen/sexpr.h diff --git a/src/xen_unified.c b/src/xen/xen_driver.c similarity index 99% rename from src/xen_unified.c rename to src/xen/xen_driver.c index dfa9ca57c1..3dd023756d 100644 --- a/src/xen_unified.c +++ b/src/xen/xen_driver.c @@ -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" diff --git a/src/xen_unified.h b/src/xen/xen_driver.h similarity index 100% rename from src/xen_unified.h rename to src/xen/xen_driver.h diff --git a/src/xen_internal.c b/src/xen/xen_hypervisor.c similarity index 99% rename from src/xen_internal.c rename to src/xen/xen_hypervisor.c index 30fd8bd195..9f3f5fe797 100644 --- a/src/xen_internal.c +++ b/src/xen/xen_hypervisor.c @@ -56,10 +56,11 @@ #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" diff --git a/src/xen_internal.h b/src/xen/xen_hypervisor.h similarity index 100% rename from src/xen_internal.h rename to src/xen/xen_hypervisor.h diff --git a/src/xen_inotify.c b/src/xen/xen_inotify.c similarity index 99% rename from src/xen_inotify.c rename to src/xen/xen_inotify.c index e312b9eb1c..7deb1dbe99 100644 --- a/src/xen_inotify.c +++ b/src/xen/xen_inotify.c @@ -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" diff --git a/src/xen_inotify.h b/src/xen/xen_inotify.h similarity index 100% rename from src/xen_inotify.h rename to src/xen/xen_inotify.h diff --git a/src/xend_internal.c b/src/xen/xend_internal.c similarity index 99% rename from src/xend_internal.c rename to src/xen/xend_internal.c index 7f55116c74..350ef8ce13 100644 --- a/src/xend_internal.c +++ b/src/xen/xend_internal.c @@ -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" diff --git a/src/xend_internal.h b/src/xen/xend_internal.h similarity index 100% rename from src/xend_internal.h rename to src/xen/xend_internal.h diff --git a/src/xm_internal.c b/src/xen/xm_internal.c similarity index 99% rename from src/xm_internal.c rename to src/xen/xm_internal.c index de3aca9e9d..960b17af3d 100644 --- a/src/xm_internal.c +++ b/src/xen/xm_internal.c @@ -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" diff --git a/src/xm_internal.h b/src/xen/xm_internal.h similarity index 100% rename from src/xm_internal.h rename to src/xen/xm_internal.h diff --git a/src/xs_internal.c b/src/xen/xs_internal.c similarity index 99% rename from src/xs_internal.c rename to src/xen/xs_internal.c index 1f54b1f0e7..494728d639 100644 --- a/src/xs_internal.c +++ b/src/xen/xs_internal.c @@ -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 diff --git a/src/xs_internal.h b/src/xen/xs_internal.h similarity index 100% rename from src/xs_internal.h rename to src/xen/xs_internal.h diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c index 7b834a9200..1196e23468 100644 --- a/tests/sexpr2xmltest.c +++ b/tests/sexpr2xmltest.c @@ -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" diff --git a/tests/statstest.c b/tests/statstest.c index 5b7d35a58c..82c0daa395 100644 --- a/tests/statstest.c +++ b/tests/statstest.c @@ -6,7 +6,7 @@ #include "stats_linux.h" #include "internal.h" - +#include "xen/block_stats.h" #include "testutils.h" #if WITH_XEN diff --git a/tests/xencapstest.c b/tests/xencapstest.c index c01efc0544..8f3fb3eb65 100644 --- a/tests/xencapstest.c +++ b/tests/xencapstest.c @@ -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; diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c index 2255984248..f6aea5a433 100644 --- a/tests/xmconfigtest.c +++ b/tests/xmconfigtest.c @@ -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" diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c index b4ee4e0b23..d83b37cc81 100644 --- a/tests/xml2sexprtest.c +++ b/tests/xml2sexprtest.c @@ -9,7 +9,7 @@ #include #include "internal.h" -#include "xend_internal.h" +#include "xen/xend_internal.h" #include "testutils.h" #include "testutilsxen.h"