[libvirt] [PATCH] Remove redundant trailing slash in user dir paths
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Callers of virGetUser{Config,Runtime,Cache}Directory all
append further path component. We should not be
adding a trailing slash in the return path otherwise we
get paths containing '//'
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/util/util.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/util/util.c b/src/util/util.c
index ec55118..ee48504 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2320,10 +2320,10 @@ static char *virGetXDGDirectory(uid_t uid, const char *xdgenvname, const char *x
path = getenv(xdgenvname);
if (path && path[0]) {
- if (virAsprintf(&ret, "%s/libvirt/", path) < 0)
+ if (virAsprintf(&ret, "%s/libvirt", path) < 0)
goto no_memory;
} else {
- if (virAsprintf(&ret, "%s/%s/libvirt/", home, xdgdefdir) < 0)
+ if (virAsprintf(&ret, "%s/%s/libvirt", home, xdgdefdir) < 0)
goto no_memory;
}
@@ -2357,7 +2357,7 @@ char *virGetUserRuntimeDirectory(uid_t uid)
} else {
char *ret;
- if (virAsprintf(&ret, "%s/libvirt/", path) < 0) {
+ if (virAsprintf(&ret, "%s/libvirt", path) < 0) {
virReportOOMError();
return NULL;
}
--
1.7.10.1
12 years, 6 months
[libvirt] [PATCH] Add openvz_util.c to POTFILES
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Pushed this under build-breaker fix rule
---
po/POTFILES.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4ea544b..cfa9d44 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -59,6 +59,7 @@ src/nwfilter/nwfilter_gentech_driver.c
src/nwfilter/nwfilter_learnipaddr.c
src/openvz/openvz_conf.c
src/openvz/openvz_driver.c
+src/openvz/openvz_util.c
src/phyp/phyp_driver.c
src/qemu/qemu_agent.c
src/qemu/qemu_bridge_filter.c
--
1.7.10.1
12 years, 6 months
[libvirt] [PATCH] Fix logic for assigning PCI addresses to USB2 companion controllers
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Currently each USB2 companion controller gets put on a separate
PCI slot. Not only is this wasteful of PCI slots, but it is not
in compliance with the spec for USB2 controllers. The master
echi1 and all companion controllers should be in the same slot,
with echi1 in function 7, and uhci1-3 in functions 0-2 respectively.
* src/qemu/qemu_command.c: Special case handling of USB2 controllers
to apply correct pci slot assignment
* tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args,
tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.xml: Expand
test to cover automatic slot assignment
---
src/qemu/qemu_command.c | 107 ++++++++++++++++----
.../qemuxml2argv-usb-ich9-ehci-addr.args | 15 ++-
.../qemuxml2argv-usb-ich9-ehci-addr.xml | 37 ++++++-
3 files changed, 138 insertions(+), 21 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 117542f..1ec5a92 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1168,8 +1168,7 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
}
-int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
- virDomainDeviceInfoPtr dev)
+static int qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs)
{
int i;
int iteration;
@@ -1196,20 +1195,10 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
continue;
}
- VIR_DEBUG("Allocating PCI addr %s", addr);
+ VIR_DEBUG("Found free PCI addr %s", addr);
VIR_FREE(addr);
- if (qemuDomainPCIAddressReserveSlot(addrs, i) < 0)
- return -1;
-
- dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
- dev->addr.pci = maybe.addr.pci;
-
- addrs->nextslot = i + 1;
- if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
- addrs->nextslot = 0;
-
- return 0;
+ return i;
}
qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1217,6 +1206,38 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
return -1;
}
+int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
+ virDomainDeviceInfoPtr dev)
+{
+ int slot = qemuDomainPCIAddressGetNextSlot(addrs);
+
+ if (slot < 0)
+ return -1;
+
+ if (qemuDomainPCIAddressReserveSlot(addrs, slot) < 0)
+ return -1;
+
+ dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+ dev->addr.pci.bus = 0;
+ dev->addr.pci.domain = 0;
+ dev->addr.pci.slot = slot;
+ dev->addr.pci.function = 0;
+
+ addrs->nextslot = slot + 1;
+ if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
+ addrs->nextslot = 0;
+
+ return 0;
+}
+
+
+#define IS_USB2_CONTROLLER(ctrl) \
+ (((ctrl)->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) && \
+ ((ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1 || \
+ (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1 || \
+ (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2 || \
+ (ctrl)->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3))
+
/*
* This assigns static PCI slots to all configured devices.
* The ordering here is chosen to match the ordering used
@@ -1252,7 +1273,7 @@ int qemuDomainPCIAddressSetNextAddr(qemuDomainPCIAddressSetPtr addrs,
int
qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
{
- int i;
+ size_t i, j;
bool reservedIDE = false;
bool reservedUSB = false;
int function;
@@ -1396,7 +1417,7 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
goto error;
}
- /* Disk controllers (SCSI only for now) */
+ /* Device controllers (SCSI, USB, but not IDE, FDC or CCID) */
for (i = 0; i < def->ncontrollers ; i++) {
/* FDC lives behind the ISA bridge; CCID is a usb device */
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC ||
@@ -1413,8 +1434,58 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
continue;
if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
continue;
- if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0)
- goto error;
+
+ /* USB2 needs special handling to put all companions in the same slot */
+ if (IS_USB2_CONTROLLER(def->controllers[i])) {
+ virDomainDevicePCIAddress addr = { 0, 0, 0, 0, false };
+ for (j = 0 ; j < i ; j++) {
+ if (IS_USB2_CONTROLLER(def->controllers[j]) &&
+ def->controllers[j]->idx == def->controllers[i]->idx) {
+ addr = def->controllers[j]->info.addr.pci;
+ break;
+ }
+ }
+
+ switch (def->controllers[i]->model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
+ addr.function = 7;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
+ addr.function = 0;
+ addr.multi = VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
+ addr.function = 1;
+ break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
+ addr.function = 2;
+ break;
+ }
+
+ if (addr.slot == 0) {
+ /* This is the first part of the controller, so need
+ * to find a free slot & then reserve a function */
+ int slot = qemuDomainPCIAddressGetNextSlot(addrs);
+ if (slot < 0)
+ goto error;
+
+ addr.slot = slot;
+ addrs->nextslot = addr.slot + 1;
+ if (QEMU_PCI_ADDRESS_LAST_SLOT < addrs->nextslot)
+ addrs->nextslot = 0;
+ }
+ /* Finally we can reserve the slot+function */
+ if (qemuDomainPCIAddressReserveFunction(addrs,
+ addr.slot,
+ addr.function) < 0)
+ goto error;
+
+ def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+ def->controllers[i]->info.addr.pci = addr;
+ } else {
+ if (qemuDomainPCIAddressSetNextAddr(addrs, &def->controllers[i]->info) < 0)
+ goto error;
+ }
}
/* Disks (VirtIO only for now) */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args
index babd4f8..cf070a1 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args
@@ -2,5 +2,16 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
-M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \
-mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
--device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x4.0x7 \
--device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
+-device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x3.0x7 \
+-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x3 \
+-device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x3.0x2 \
+-device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x3.0x1 \
+-device ich9-usb-ehci1,id=usb1,bus=pci.0,addr=0x4.0x7 \
+-device ich9-usb-uhci1,masterbus=usb1.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4 \
+-device ich9-usb-uhci3,masterbus=usb1.0,firstport=4,bus=pci.0,addr=0x4.0x2 \
+-device ich9-usb-uhci2,masterbus=usb1.0,firstport=2,bus=pci.0,addr=0x4.0x1 \
+-device ich9-usb-ehci1,id=usb2,bus=pci.0,addr=0x5.0x7 \
+-device ich9-usb-uhci1,masterbus=usb2.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5 \
+-device ich9-usb-uhci3,masterbus=usb2.0,firstport=4,bus=pci.0,addr=0x5.0x2 \
+-device ich9-usb-uhci2,masterbus=usb2.0,firstport=2,bus=pci.0,addr=0x5.0x1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.xml
index 09633ae..8eff1d7 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.xml
@@ -10,8 +10,43 @@
</os>
<devices>
<emulator>/usr/bin/qemu</emulator>
+ <!-- Intentionally mixed up ordering to check we assign
+ addresses to the correct matching companions -->
<controller type='usb' index='0' model='ich9-ehci1'>
- <address type='pci' domain='0' bus='0' slot='4' function='7'/>
+ </controller>
+ <controller type='usb' index='2' model='ich9-ehci1'>
+ </controller>
+ <controller type='usb' index='1' model='ich9-ehci1'>
+ </controller>
+
+ <controller type='usb' index='0' model='ich9-uhci1'>
+ <master startport='0'/>
+ </controller>
+ <controller type='usb' index='1' model='ich9-uhci1'>
+ <master startport='0'/>
+ </controller>
+ <controller type='usb' index='2' model='ich9-uhci1'>
+ <master startport='0'/>
+ </controller>
+
+ <controller type='usb' index='0' model='ich9-uhci3'>
+ <master startport='4'/>
+ </controller>
+ <controller type='usb' index='1' model='ich9-uhci3'>
+ <master startport='4'/>
+ </controller>
+ <controller type='usb' index='2' model='ich9-uhci3'>
+ <master startport='4'/>
+ </controller>
+
+ <controller type='usb' index='2' model='ich9-uhci2'>
+ <master startport='2'/>
+ </controller>
+ <controller type='usb' index='1' model='ich9-uhci2'>
+ <master startport='2'/>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci2'>
+ <master startport='2'/>
</controller>
<memballoon model='virtio'/>
</devices>
--
1.7.10.1
12 years, 6 months
[libvirt] [PATCH v2] Allow stack traces to be included with log messages
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Sometimes it is useful to see the callpath for log messages.
This change enhances the log filter syntax so that stack traces
can be show by setting '1:+NAME' instead of '1:NAME'.
This results in output like:
2012-05-09 14:18:45.136+0000: 13314: debug : virInitialize:414 : register drivers
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(virInitialize+0xd6)[0x7f89188ebe86]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x431921]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3a21e21735]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x40a279]
2012-05-09 14:18:45.136+0000: 13314: debug : virRegisterDriver:775 : driver=0x7f8918d02760 name=Test
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(virRegisterDriver+0x6b)[0x7f89188ec717]
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(+0x11b3ad)[0x7f891891e3ad]
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(virInitialize+0xf3)[0x7f89188ebea3]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x431921]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3a21e21735]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x40a279]
* docs/logging.html.in: Document new syntax
* configure.ac: Check for execinfo.h
* src/util/logging.c, src/util/logging.h: Add support for
stack traces
* tests/testutils.c: Adapt to API change
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
configure.ac | 2 +-
docs/logging.html.in | 6 +++--
src/util/logging.c | 73 ++++++++++++++++++++++++++++++++++++++++++--------
src/util/logging.h | 9 ++++++-
tests/testutils.c | 4 +++
5 files changed, 79 insertions(+), 15 deletions(-)
diff --git a/configure.ac b/configure.ac
index a6894ae..9c356c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -158,7 +158,7 @@ dnl Availability of various common headers (non-fatal if missing).
AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/un.h \
sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h \
sys/un.h sys/syscall.h netinet/tcp.h ifaddrs.h libtasn1.h \
- net/if.h])
+ net/if.h execinfo.h])
AC_MSG_CHECKING([for struct ifreq in net/if.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
diff --git a/docs/logging.html.in b/docs/logging.html.in
index 22b5422..87e2292 100644
--- a/docs/logging.html.in
+++ b/docs/logging.html.in
@@ -114,8 +114,10 @@
</h3>
<p>The syntax for filters and outputs is the same for both types of
variables.</p>
- <p>The format for a filter is:</p>
- <pre>x:name</pre>
+ <p>The format for a filter is one of:</p>
+ <pre>
+ x:name (log message only)
+ x:+name (log message + stack trace)</pre>
<p>where <code>name</code> is a match string e.g. <code>remote</code> or
<code>qemu</code> and the x is the minimal level where matching messages
should be logged:</p>
diff --git a/src/util/logging.c b/src/util/logging.c
index 48a056d..110ad7e 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -34,6 +34,9 @@
#if HAVE_SYSLOG_H
# include <syslog.h>
#endif
+#ifdef HAVE_EXECINFO_H
+# include <execinfo.h>
+#endif
#include "ignore-value.h"
#include "virterror_internal.h"
@@ -64,6 +67,7 @@ static int virLogEnd = 0;
struct _virLogFilter {
const char *match;
int priority;
+ unsigned int flags;
};
typedef struct _virLogFilter virLogFilter;
typedef virLogFilter *virLogFilterPtr;
@@ -99,7 +103,9 @@ static int virLogResetFilters(void);
static int virLogResetOutputs(void);
static int virLogOutputToFd(const char *category, int priority,
const char *funcname, long long linenr,
- const char *timestamp, const char *str,
+ const char *timestamp,
+ unsigned int flags,
+ const char *str,
void *data);
/*
@@ -472,7 +478,7 @@ static int virLogResetFilters(void) {
* virLogDefineFilter:
* @match: the pattern to match
* @priority: the priority to give to messages matching the pattern
- * @flags: extra flag, currently unused
+ * @flags: extra flags, see virLogFilterFlags enum
*
* Defines a pattern used for log filtering, it allow to select or
* reject messages independently of the default priority.
@@ -487,7 +493,7 @@ int virLogDefineFilter(const char *match, int priority,
int i;
char *mdup = NULL;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_LOG_STACK_TRACE, -1);
if ((match == NULL) || (priority < VIR_LOG_DEBUG) ||
(priority > VIR_LOG_ERROR))
@@ -514,6 +520,7 @@ int virLogDefineFilter(const char *match, int priority,
}
virLogFilters[i].match = mdup;
virLogFilters[i].priority = priority;
+ virLogFilters[i].flags = flags;
virLogNbFilters++;
cleanup:
virLogUnlock();
@@ -530,7 +537,8 @@ cleanup:
*
* Returns 0 if not matched or the new priority if found.
*/
-static int virLogFiltersCheck(const char *input) {
+static int virLogFiltersCheck(const char *input,
+ unsigned int *flags) {
int ret = 0;
int i;
@@ -538,6 +546,7 @@ static int virLogFiltersCheck(const char *input) {
for (i = 0;i < virLogNbFilters;i++) {
if (strstr(input, virLogFilters[i].match)) {
ret = virLogFilters[i].priority;
+ *flags = virLogFilters[i].flags;
break;
}
}
@@ -691,6 +700,7 @@ void virLogMessage(const char *category, int priority, const char *funcname,
int saved_errno = errno;
int emit = 1;
va_list ap;
+ unsigned int filterflags = 0;
if (!virLogInitialized)
virLogStartup();
@@ -701,7 +711,7 @@ void virLogMessage(const char *category, int priority, const char *funcname,
/*
* check against list of specific logging patterns
*/
- fprio = virLogFiltersCheck(category);
+ fprio = virLogFiltersCheck(category, &filterflags);
if (fprio == 0) {
if (priority < virLogDefaultPriority)
emit = 0;
@@ -753,13 +763,14 @@ void virLogMessage(const char *category, int priority, const char *funcname,
if (virLogVersionString(&ver) >= 0)
virLogOutputs[i].f(category, VIR_LOG_INFO,
__func__, __LINE__,
- timestamp, ver,
+ timestamp, 0, ver,
virLogOutputs[i].data);
VIR_FREE(ver);
virLogOutputs[i].logVersion = false;
}
virLogOutputs[i].f(category, priority, funcname, linenr,
- timestamp, msg, virLogOutputs[i].data);
+ timestamp, filterflags,
+ msg, virLogOutputs[i].data);
}
}
if ((virLogNbOutputs == 0) && (flags != 1)) {
@@ -768,13 +779,14 @@ void virLogMessage(const char *category, int priority, const char *funcname,
if (virLogVersionString(&ver) >= 0)
virLogOutputToFd(category, VIR_LOG_INFO,
__func__, __LINE__,
- timestamp, ver,
+ timestamp, 0, ver,
(void *) STDERR_FILENO);
VIR_FREE(ver);
logVersionStderr = false;
}
virLogOutputToFd(category, priority, funcname, linenr,
- timestamp, msg, (void *) STDERR_FILENO);
+ timestamp, filterflags,
+ msg, (void *) STDERR_FILENO);
}
virLogUnlock();
@@ -783,11 +795,34 @@ cleanup:
errno = saved_errno;
}
+
+static void virLogStackTraceToFd(int fd)
+{
+#ifdef HAVE_EXECINFO_H
+ void *array[100];
+ int size;
+
+# define STRIP_DEPTH 3
+
+ size = backtrace(array, ARRAY_CARDINALITY(array));
+ backtrace_symbols_fd(array + STRIP_DEPTH, size - STRIP_DEPTH, fd);
+ ignore_value(safewrite(fd, "\n", 1));
+#else
+ static bool doneWarning = false;
+ const char *msg = "Stack trace not available on this platform\n";
+ if (!doneWarning) {
+ ignore_value(safewrite(fd, msg, strlen(msg)));
+ doneWarning = true;
+ }
+#endif
+}
+
static int virLogOutputToFd(const char *category ATTRIBUTE_UNUSED,
int priority ATTRIBUTE_UNUSED,
const char *funcname ATTRIBUTE_UNUSED,
long long linenr ATTRIBUTE_UNUSED,
const char *timestamp,
+ unsigned int flags,
const char *str,
void *data)
{
@@ -804,6 +839,9 @@ static int virLogOutputToFd(const char *category ATTRIBUTE_UNUSED,
ret = safewrite(fd, msg, strlen(msg));
VIR_FREE(msg);
+ if (flags & VIR_LOG_STACK_TRACE)
+ virLogStackTraceToFd(fd);
+
return ret;
}
@@ -841,11 +879,14 @@ static int virLogOutputToSyslog(const char *category ATTRIBUTE_UNUSED,
const char *funcname ATTRIBUTE_UNUSED,
long long linenr ATTRIBUTE_UNUSED,
const char *timestamp ATTRIBUTE_UNUSED,
+ unsigned int flags,
const char *str,
void *data ATTRIBUTE_UNUSED)
{
int prio;
+ virCheckFlags(VIR_LOG_STACK_TRACE, -1);
+
switch (priority) {
case VIR_LOG_DEBUG:
prio = LOG_DEBUG;
@@ -1024,12 +1065,17 @@ int virLogParseFilters(const char *filters) {
virSkipSpaces(&cur);
while (*cur != 0) {
+ unsigned int flags = 0;
prio= virParseNumber(&cur);
if ((prio < VIR_LOG_DEBUG) || (prio > VIR_LOG_ERROR))
goto cleanup;
if (*cur != ':')
goto cleanup;
cur++;
+ if (*cur == '+') {
+ flags |= VIR_LOG_STACK_TRACE;
+ cur++;
+ }
str = cur;
while ((*cur != 0) && (!IS_SPACE(cur)))
cur++;
@@ -1038,7 +1084,7 @@ int virLogParseFilters(const char *filters) {
name = strndup(str, cur - str);
if (name == NULL)
goto cleanup;
- if (virLogDefineFilter(name, prio, 0) >= 0)
+ if (virLogDefineFilter(name, prio, flags) >= 0)
count++;
VIR_FREE(name);
virSkipSpaces(&cur);
@@ -1072,7 +1118,12 @@ char *virLogGetFilters(void) {
virLogLock();
for (i = 0; i < virLogNbFilters; i++) {
- virBufferAsprintf(&filterbuf, "%d:%s ", virLogFilters[i].priority,
+ const char *sep = ":";
+ if (virLogFilters[i].flags & VIR_LOG_STACK_TRACE)
+ sep = ":+";
+ virBufferAsprintf(&filterbuf, "%d%s%s ",
+ virLogFilters[i].priority,
+ sep,
virLogFilters[i].match);
}
virLogUnlock();
diff --git a/src/util/logging.h b/src/util/logging.h
index 2343de0..a6fa63e 100644
--- a/src/util/logging.h
+++ b/src/util/logging.h
@@ -79,6 +79,7 @@ typedef enum {
* @funcname: the function emitting the message
* @linenr: line where the message was emitted
* @timestamp: zero terminated string with timestamp of the message
+ * @flags: flags associated with the message
* @str: the message to log, preformatted and zero terminated
* @data: extra output logging data
*
@@ -88,7 +89,9 @@ typedef enum {
*/
typedef int (*virLogOutputFunc) (const char *category, int priority,
const char *funcname, long long linenr,
- const char *timestamp, const char *str,
+ const char *timestamp,
+ unsigned int flags,
+ const char *str,
void *data);
/**
@@ -99,6 +102,10 @@ typedef int (*virLogOutputFunc) (const char *category, int priority,
*/
typedef void (*virLogCloseFunc) (void *data);
+typedef enum {
+ VIR_LOG_STACK_TRACE = (1 << 0),
+} virLogFlags;
+
extern int virLogGetNbFilters(void);
extern int virLogGetNbOutputs(void);
extern char *virLogGetFilters(void);
diff --git a/tests/testutils.c b/tests/testutils.c
index 6eb40ed..98595ad 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -44,6 +44,8 @@
# include <paths.h>
#endif
+#define VIR_FROM_THIS VIR_FROM_NONE
+
#define GETTIMEOFDAY(T) gettimeofday(T, NULL)
#define DIFF_MSEC(T, U) \
((((int) ((T)->tv_sec - (U)->tv_sec)) * 1000000.0 + \
@@ -469,10 +471,12 @@ virtTestLogOutput(const char *category ATTRIBUTE_UNUSED,
const char *funcname ATTRIBUTE_UNUSED,
long long lineno ATTRIBUTE_UNUSED,
const char *timestamp,
+ unsigned int flags,
const char *str,
void *data)
{
struct virtTestLogData *log = data;
+ virCheckFlags(VIR_LOG_STACK_TRACE, -1);
virBufferAsprintf(&log->buf, "%s: %s", timestamp, str);
return strlen(timestamp) + 2 + strlen(str);
}
--
1.7.10.1
12 years, 6 months
[libvirt] [PATCH] Add bundled(gnulib) to RPM specfile
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
According to Fedora guidelines, because we bundle gnulib we
need to add a virtual Provides: bundled(gnulib).
https://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries#Requirement...
---
libvirt.spec.in | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 2e08abb..eef8ce1 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -460,6 +460,8 @@ BuildRequires: scrub
BuildRequires: numad
%endif
+Provides: bundled(gnulib)
+
%description
Libvirt is a C toolkit to interact with the virtualization capabilities
of recent versions of Linux (and other OSes). The main package includes
--
1.7.10.1
12 years, 6 months
[libvirt] [libvirt-glib 1/3] API to get capabilities from connection
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
---
libvirt-gconfig/libvirt-gconfig-capabilities.c | 4 ---
libvirt-gobject/libvirt-gobject-connection.c | 32 ++++++++++++++++++++++++
libvirt-gobject/libvirt-gobject-connection.h | 3 ++
libvirt-gobject/libvirt-gobject.sym | 1 +
4 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/libvirt-gconfig/libvirt-gconfig-capabilities.c b/libvirt-gconfig/libvirt-gconfig-capabilities.c
index 4c4df68..3d9d036 100644
--- a/libvirt-gconfig/libvirt-gconfig-capabilities.c
+++ b/libvirt-gconfig/libvirt-gconfig-capabilities.c
@@ -54,8 +54,6 @@ GVirConfigCapabilities *gvir_config_capabilities_new(void)
{
GVirConfigObject *object;
- /* FIXME: what is the XML root of the capability node? I suspect it is
- * either 'guest' or 'host' */
object = gvir_config_object_new(GVIR_CONFIG_TYPE_CAPABILITIES,
"capabilities",
DATADIR "/libvirt/schemas/capability.rng");
@@ -67,8 +65,6 @@ GVirConfigCapabilities *gvir_config_capabilities_new_from_xml(const gchar *xml,
{
GVirConfigObject *object;
- /* FIXME: what is the XML root of the capability node? I suspect it is
- * either 'guest' or 'host' */
object = gvir_config_object_new_from_xml(GVIR_CONFIG_TYPE_CAPABILITIES,
"capabilities",
DATADIR "/libvirt/schemas/capability.rng",
diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
index baeeb1c..4f04f98 100644
--- a/libvirt-gobject/libvirt-gobject-connection.c
+++ b/libvirt-gobject/libvirt-gobject-connection.c
@@ -1387,3 +1387,35 @@ GVirNodeInfo *gvir_connection_get_node_info(GVirConnection *conn,
return ret;
}
+
+/**
+ * gvir_connection_get_capabilities:
+ * @conn: the connection
+ * @err: return location for any #GError
+ *
+ * Return value: (transfer full): a #GVirConfigCapabilities or NULL
+ */
+GVirConfigCapabilities *gvir_connection_get_capabilities(GVirConnection *conn,
+ GError **err)
+{
+ GVirConfigCapabilities *caps;
+ char *caps_xml;
+
+ g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
+ g_return_val_if_fail(err == NULL || *err == NULL, NULL);
+ g_return_val_if_fail(conn->priv->conn, NULL);
+
+ caps_xml = virConnectGetCapabilities(conn->priv->conn);
+ if (caps_xml == NULL) {
+ gvir_set_error_literal(err, GVIR_CONNECTION_ERROR,
+ 0,
+ "Unable to get capabilities");
+ return NULL;
+ }
+
+ caps = gvir_config_capabilities_new_from_xml(caps_xml, err);
+ free(caps_xml);
+
+ return caps;
+}
+
diff --git a/libvirt-gobject/libvirt-gobject-connection.h b/libvirt-gobject/libvirt-gobject-connection.h
index 3cc60a2..8c48f67 100644
--- a/libvirt-gobject/libvirt-gobject-connection.h
+++ b/libvirt-gobject/libvirt-gobject-connection.h
@@ -191,6 +191,9 @@ GVirStream *gvir_connection_get_stream(GVirConnection *conn,
GVirNodeInfo *gvir_connection_get_node_info(GVirConnection *conn,
GError **err);
+GVirConfigCapabilities *gvir_connection_get_capabilities(GVirConnection *conn,
+ GError **err);
+
G_END_DECLS
#endif /* __LIBVIRT_GOBJECT_CONNECTION_H__ */
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym
index f43836f..0c9fc37 100644
--- a/libvirt-gobject/libvirt-gobject.sym
+++ b/libvirt-gobject/libvirt-gobject.sym
@@ -31,6 +31,7 @@ LIBVIRT_GOBJECT_0.0.8 {
gvir_connection_create_storage_pool;
gvir_connection_start_domain;
gvir_connection_get_node_info;
+ gvir_connection_get_capabilities;
gvir_domain_device_get_type;
gvir_domain_device_get_domain;
--
1.7.7.6
12 years, 6 months
[libvirt] [PATCH] openvz: read vmguarpages/privvmpages to set memory tunables [v2]
by Guido Günther
---
This is a reworked version of the patch already sent, now adding
handling for "unlimited" (represented by LONG_MAX in openvz) as well as
a schema testcase. I also switched all value to unsigned long long to
avoid overflows.
Note that privvmpages is the amount of memory available to the
application. The total memory usage of the container might be higher due
to used kernel memory. This does probably warrant an extra tunable
later. O.k. to apply?
Cheers,
-- Guido
src/openvz/openvz_conf.c | 113 ++++++++++++
src/openvz/openvz_driver.c | 208 +++++++++++++++++++++++
tests/domainschemadata/domain-openvz-simple.xml | 27 +++
3 files changed, 348 insertions(+)
create mode 100644 tests/domainschemadata/domain-openvz-simple.xml
diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
index 5848ec4..a169ae6 100644
--- a/src/openvz/openvz_conf.c
+++ b/src/openvz/openvz_conf.c
@@ -129,6 +129,46 @@ int openvzExtractVersion(struct openvz_driver *driver)
}
+/* Parse config values of the form barrier:limit into barrier and limit */
+static int
+openvzParseBarrierLimit(const char* value,
+ unsigned long long *barrier,
+ unsigned long long *limit)
+{
+ char *token;
+ char *saveptr = NULL;
+ char *str = strdup(value);
+
+ if (str == NULL) {
+ virReportOOMError();
+ goto error;
+ }
+
+ token = strtok_r(str, ":", &saveptr);
+ if (token == NULL) {
+ goto error;
+ } else {
+ if (barrier != NULL) {
+ if (virStrToLong_ull(token, NULL, 10, barrier))
+ goto error;
+ }
+ }
+ token = strtok_r(NULL, ":", &saveptr);
+ if (token == NULL) {
+ goto error;
+ } else {
+ if (limit != NULL) {
+ if (virStrToLong_ull(token, NULL, 10, limit))
+ goto error;
+ }
+ }
+ return 0;
+error:
+ VIR_FREE(str);
+ return -1;
+}
+
+
static int openvzDefaultConsoleType(const char *ostype ATTRIBUTE_UNUSED)
{
return VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_OPENVZ;
@@ -423,6 +463,78 @@ error:
}
+static int
+openvzReadMemConf(virDomainDefPtr def, int veid)
+{
+ int ret;
+ char *temp = NULL;
+ unsigned long long barrier, limit;
+ const char *param;
+ unsigned long kb_per_pages;
+
+ kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
+ if (kb_per_pages == -1) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Can't determine page size"));
+ goto error;
+ }
+
+ /* Memory allocation guarantee */
+ param = "VMGUARPAGES";
+ ret = openvzReadVPSConfigParam(veid, param, &temp);
+ if (ret < 0) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not read '%s' from config for container %d"),
+ param, veid);
+ goto error;
+ } else if (ret > 0) {
+ ret = openvzParseBarrierLimit(temp, &barrier, NULL);
+ if (ret < 0) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse barrier of '%s' "
+ "from config for container %d"), param, veid);
+ goto error;
+ }
+ if (barrier == LONG_MAX)
+ def->mem.min_guarantee = 0ull;
+ else
+ def->mem.min_guarantee = barrier * kb_per_pages;
+ }
+
+ /* Memory hard and soft limits */
+ param = "PRIVVMPAGES";
+ ret = openvzReadVPSConfigParam(veid, param, &temp);
+ if (ret < 0) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not read '%s' from config for container %d"),
+ param, veid);
+ goto error;
+ } else if (ret > 0) {
+ ret = openvzParseBarrierLimit(temp, &barrier, &limit);
+ if (ret < 0) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not parse barrier and limit of '%s' "
+ "from config for container %d"), param, veid);
+ goto error;
+ }
+ if (barrier == LONG_MAX)
+ def->mem.soft_limit = 0ull;
+ else
+ def->mem.soft_limit = barrier * kb_per_pages;
+
+ if (limit == LONG_MAX)
+ def->mem.hard_limit = 0ull;
+ else
+ def->mem.hard_limit = limit * kb_per_pages;
+ }
+
+ ret = 0;
+error:
+ VIR_FREE(temp);
+ return ret;
+}
+
+
/* Free all memory associated with a openvz_driver structure */
void
openvzFreeDriver(struct openvz_driver *driver)
@@ -535,6 +647,7 @@ int openvzLoadDomains(struct openvz_driver *driver) {
openvzReadNetworkConf(dom->def, veid);
openvzReadFSConf(dom->def, veid);
+ openvzReadMemConf(dom->def, veid);
virUUIDFormat(dom->def->uuid, uuidstr);
if (virHashAddEntry(driver->domains.objs, uuidstr, dom) < 0)
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
index e8b6915..555161e 100644
--- a/src/openvz/openvz_driver.c
+++ b/src/openvz/openvz_driver.c
@@ -54,6 +54,7 @@
#include "nodeinfo.h"
#include "memory.h"
#include "virfile.h"
+#include "virtypedparam.h"
#include "logging.h"
#include "command.h"
#include "viruri.h"
@@ -65,6 +66,8 @@
#define CMDBUF_LEN 1488
#define CMDOP_LEN 288
+#define OPENVZ_NB_MEM_PARAM 3
+
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
static int openvzDomainGetMaxVcpus(virDomainPtr dom);
@@ -1631,6 +1634,209 @@ cleanup:
return -1;
}
+
+static int
+openvzDomainGetBarrierLimit(virDomainPtr domain,
+ const char *param,
+ unsigned long long *barrier,
+ unsigned long long *limit)
+{
+ int status, ret = -1;
+ char *output = NULL;
+ virCommandPtr cmd = virCommandNewArgList(VZLIST, "--no-header", NULL);
+
+ virCommandSetOutputBuffer(cmd, &output);
+ virCommandAddArgFormat(cmd, "-o%s.b,%s.l", param, param);
+ virCommandAddArg(cmd, domain->name);
+ if (virCommandRun(cmd, &status)) {
+ openvzError(VIR_ERR_OPERATION_FAILED,
+ _("Failed to get %s for %s: %d"), param, domain->name,
+ status);
+ goto cleanup;
+ }
+
+ if (sscanf(output, "%llu %llu", barrier, limit) != 2) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Can't parse "VZLIST" output, got %s"), output);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ VIR_FREE(output);
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+static int
+openvzDomainSetBarrierLimit(virDomainPtr domain,
+ const char *param,
+ unsigned long long barrier,
+ unsigned long long limit)
+{
+ int status, ret = -1;
+ virCommandPtr cmd = virCommandNewArgList(VZCTL, "--quiet", "set", NULL);
+
+ /* LONG_MAX indicates unlimited so reject larger values */
+ if (barrier > LONG_MAX || limit > LONG_MAX) {
+ openvzError(VIR_ERR_OPERATION_FAILED,
+ _("Failed to set %s for %s: value too large"), param,
+ domain->name);
+ goto cleanup;
+ }
+
+ virCommandAddArg(cmd, domain->name);
+ virCommandAddArgFormat(cmd, "--%s", param);
+ virCommandAddArgFormat(cmd, "%llu:%llu", barrier, limit);
+ virCommandAddArg(cmd, "--save");
+ if (virCommandRun(cmd, &status)) {
+ openvzError(VIR_ERR_OPERATION_FAILED,
+ _("Failed to set %s for %s: %d"), param, domain->name,
+ status);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
+
+
+static int
+openvzDomainGetMemoryParameters(virDomainPtr domain,
+ virTypedParameterPtr params,
+ int *nparams,
+ unsigned int flags)
+{
+ int i, result = -1;
+ const char *name;
+ long kb_per_pages;
+ unsigned long long barrier, limit, val;
+
+ virCheckFlags(0, -1);
+
+ kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
+ if (kb_per_pages == -1) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Can't determine page size"));
+ goto cleanup;
+ }
+
+ if (*nparams == 0) {
+ *nparams = OPENVZ_NB_MEM_PARAM;
+ return 0;
+ }
+
+ for (i = 0; i <= *nparams; i++) {
+ virMemoryParameterPtr param = ¶ms[i];
+
+ switch (i) {
+ case 0:
+ name = "privvmpages";
+ if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
+ goto cleanup;
+
+ val = (limit == LONG_MAX) ? 0ull : limit * kb_per_pages;
+ if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_HARD_LIMIT,
+ VIR_TYPED_PARAM_ULLONG, val) < 0)
+ goto cleanup;
+ break;
+
+ case 1:
+ name = "privvmpages";
+ if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
+ goto cleanup;
+
+ val = (barrier == LONG_MAX) ? 0ull : barrier * kb_per_pages;
+ if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_SOFT_LIMIT,
+ VIR_TYPED_PARAM_ULLONG, val) < 0)
+ goto cleanup;
+ break;
+
+ case 2:
+ name = "vmguarpages";
+ if (openvzDomainGetBarrierLimit(domain, name, &barrier, &limit) < 0)
+ goto cleanup;
+
+ val = (barrier == LONG_MAX) ? 0ull : barrier * kb_per_pages;
+ if (virTypedParameterAssign(param, VIR_DOMAIN_MEMORY_MIN_GUARANTEE,
+ VIR_TYPED_PARAM_ULLONG, val) < 0)
+ goto cleanup;
+ break;
+ }
+ }
+
+ if (*nparams > OPENVZ_NB_MEM_PARAM)
+ *nparams = OPENVZ_NB_MEM_PARAM;
+ result = 0;
+
+cleanup:
+ return result;
+}
+
+
+static int
+openvzDomainSetMemoryParameters(virDomainPtr domain,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ int i, result = -1;
+ long kb_per_pages;
+
+ kb_per_pages = sysconf(_SC_PAGESIZE) / 1024;
+ if (kb_per_pages == -1) {
+ openvzError(VIR_ERR_INTERNAL_ERROR,
+ _("Can't determine page size"));
+ goto cleanup;
+ }
+
+ virCheckFlags(0, -1);
+ if (virTypedParameterArrayValidate(params, nparams,
+ VIR_DOMAIN_MEMORY_HARD_LIMIT,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_MEMORY_SOFT_LIMIT,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_MEMORY_MIN_GUARANTEE,
+ VIR_TYPED_PARAM_ULLONG,
+ NULL) < 0)
+ return -1;
+
+ for (i = 0; i < nparams; i++) {
+ virTypedParameterPtr param = ¶ms[i];
+ unsigned long long barrier, limit;
+
+ if (STREQ(param->field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) {
+ if (openvzDomainGetBarrierLimit(domain, "privvmpages",
+ &barrier, &limit) < 0)
+ goto cleanup;
+ limit = params[i].value.ul / kb_per_pages;
+ if (openvzDomainSetBarrierLimit(domain, "privvmpages",
+ barrier, limit) < 0)
+ goto cleanup;
+ } else if (STREQ(param->field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) {
+ if (openvzDomainGetBarrierLimit(domain, "privvmpages",
+ &barrier, &limit) < 0)
+ goto cleanup;
+ barrier = params[i].value.ul / kb_per_pages;
+ if (openvzDomainSetBarrierLimit(domain, "privvmpages",
+ barrier, limit) < 0)
+ goto cleanup;
+ } else if (STREQ(param->field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) {
+ barrier = params[i].value.ul / kb_per_pages;
+ if (openvzDomainSetBarrierLimit(domain, "vmguarpages",
+ barrier, LONG_MAX) < 0)
+ goto cleanup;
+ }
+ }
+ result = 0;
+cleanup:
+ return result;
+}
+
+
static int
openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason)
{
@@ -1752,6 +1958,8 @@ static virDriver openvzDriver = {
.domainDestroy = openvzDomainShutdown, /* 0.3.1 */
.domainDestroyFlags = openvzDomainShutdownFlags, /* 0.9.4 */
.domainGetOSType = openvzGetOSType, /* 0.3.1 */
+ .domainGetMemoryParameters = openvzDomainGetMemoryParameters, /* 0.9.12 */
+ .domainSetMemoryParameters = openvzDomainSetMemoryParameters, /* 0.9.12 */
.domainGetInfo = openvzDomainGetInfo, /* 0.3.1 */
.domainGetState = openvzDomainGetState, /* 0.9.2 */
.domainSetVcpus = openvzDomainSetVcpus, /* 0.4.6 */
diff --git a/tests/domainschemadata/domain-openvz-simple.xml b/tests/domainschemadata/domain-openvz-simple.xml
new file mode 100644
index 0000000..aba64a4
--- /dev/null
+++ b/tests/domainschemadata/domain-openvz-simple.xml
@@ -0,0 +1,27 @@
+<domain type='openvz'>
+ <name>100</name>
+ <uuid>7109d234-f5a8-30a6-5dd2-39ca85ce3958</uuid>
+ <memory unit='KiB'>0</memory>
+ <currentMemory unit='KiB'>0</currentMemory>
+ <memtune>
+ <hard_limit unit='KiB'>278528</hard_limit>
+ <soft_limit unit='KiB'>262144</soft_limit>
+ <min_guarantee unit='KiB'>135168</min_guarantee>
+ </memtune>
+ <vcpu>1</vcpu>
+ <os>
+ <type>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type='template' accessmode='passthrough'>
+ <source name='debian'/>
+ <target dir='/'/>
+ </filesystem>
+ </devices>
+</domain>
+
--
1.7.10
12 years, 6 months
[libvirt] [PATCH] Allow stack traces to be included with log messages
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
Sometimes it is useful to see the callpath for log messages.
This change enhances the log filter syntax so that stck traces
can be show by setting '1:+NAME' instead of '1:NAME'.
This results in output like:
2012-05-09 14:18:45.136+0000: 13314: debug : virInitialize:414 : register drivers
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(virInitialize+0xd6)[0x7f89188ebe86]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x431921]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3a21e21735]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x40a279]
2012-05-09 14:18:45.136+0000: 13314: debug : virRegisterDriver:775 : driver=0x7f8918d02760 name=Test
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(virRegisterDriver+0x6b)[0x7f89188ec717]
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(+0x11b3ad)[0x7f891891e3ad]
/home/berrange/src/virt/libvirt/src/.libs/libvirt.so.0(virInitialize+0xf3)[0x7f89188ebea3]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x431921]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3a21e21735]
/home/berrange/src/virt/libvirt/tools/.libs/lt-virsh[0x40a279]
* docs/logging.html.in: Document new syntax
* configure.ac: Check for execinfo.h
* src/util/logging.c, src/util/logging.h: Add support for
stack traces
* tests/testutils.c: Adapt to API change
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
configure.ac | 2 +-
docs/logging.html.in | 6 +++--
src/util/logging.c | 67 +++++++++++++++++++++++++++++++++++++++++---------
src/util/logging.h | 9 ++++++-
tests/testutils.c | 1 +
5 files changed, 70 insertions(+), 15 deletions(-)
diff --git a/configure.ac b/configure.ac
index 30eff91..c1bf57b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -158,7 +158,7 @@ dnl Availability of various common headers (non-fatal if missing).
AC_CHECK_HEADERS([pwd.h paths.h regex.h sys/un.h \
sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h \
sys/un.h sys/syscall.h netinet/tcp.h ifaddrs.h libtasn1.h \
- net/if.h])
+ net/if.h execinfo.h])
AC_MSG_CHECKING([for struct ifreq in net/if.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
diff --git a/docs/logging.html.in b/docs/logging.html.in
index 22b5422..87e2292 100644
--- a/docs/logging.html.in
+++ b/docs/logging.html.in
@@ -114,8 +114,10 @@
</h3>
<p>The syntax for filters and outputs is the same for both types of
variables.</p>
- <p>The format for a filter is:</p>
- <pre>x:name</pre>
+ <p>The format for a filter is one of:</p>
+ <pre>
+ x:name (log message only)
+ x:+name (log message + stack trace)</pre>
<p>where <code>name</code> is a match string e.g. <code>remote</code> or
<code>qemu</code> and the x is the minimal level where matching messages
should be logged:</p>
diff --git a/src/util/logging.c b/src/util/logging.c
index 48a056d..062917d 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -34,6 +34,9 @@
#if HAVE_SYSLOG_H
# include <syslog.h>
#endif
+#ifdef HAVE_EXECINFO_H
+# include <execinfo.h>
+#endif
#include "ignore-value.h"
#include "virterror_internal.h"
@@ -64,6 +67,7 @@ static int virLogEnd = 0;
struct _virLogFilter {
const char *match;
int priority;
+ unsigned int flags;
};
typedef struct _virLogFilter virLogFilter;
typedef virLogFilter *virLogFilterPtr;
@@ -99,7 +103,9 @@ static int virLogResetFilters(void);
static int virLogResetOutputs(void);
static int virLogOutputToFd(const char *category, int priority,
const char *funcname, long long linenr,
- const char *timestamp, const char *str,
+ const char *timestamp,
+ unsigned int flags,
+ const char *str,
void *data);
/*
@@ -472,7 +478,7 @@ static int virLogResetFilters(void) {
* virLogDefineFilter:
* @match: the pattern to match
* @priority: the priority to give to messages matching the pattern
- * @flags: extra flag, currently unused
+ * @flags: extra flags, see virLogFilterFlags enum
*
* Defines a pattern used for log filtering, it allow to select or
* reject messages independently of the default priority.
@@ -487,7 +493,7 @@ int virLogDefineFilter(const char *match, int priority,
int i;
char *mdup = NULL;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_LOG_STACK_TRACE, -1);
if ((match == NULL) || (priority < VIR_LOG_DEBUG) ||
(priority > VIR_LOG_ERROR))
@@ -514,6 +520,7 @@ int virLogDefineFilter(const char *match, int priority,
}
virLogFilters[i].match = mdup;
virLogFilters[i].priority = priority;
+ virLogFilters[i].flags = flags;
virLogNbFilters++;
cleanup:
virLogUnlock();
@@ -530,7 +537,8 @@ cleanup:
*
* Returns 0 if not matched or the new priority if found.
*/
-static int virLogFiltersCheck(const char *input) {
+static int virLogFiltersCheck(const char *input,
+ unsigned int *flags) {
int ret = 0;
int i;
@@ -538,6 +546,7 @@ static int virLogFiltersCheck(const char *input) {
for (i = 0;i < virLogNbFilters;i++) {
if (strstr(input, virLogFilters[i].match)) {
ret = virLogFilters[i].priority;
+ *flags = virLogFilters[i].flags;
break;
}
}
@@ -691,6 +700,7 @@ void virLogMessage(const char *category, int priority, const char *funcname,
int saved_errno = errno;
int emit = 1;
va_list ap;
+ unsigned int filterflags = 0;
if (!virLogInitialized)
virLogStartup();
@@ -701,7 +711,7 @@ void virLogMessage(const char *category, int priority, const char *funcname,
/*
* check against list of specific logging patterns
*/
- fprio = virLogFiltersCheck(category);
+ fprio = virLogFiltersCheck(category, &filterflags);
if (fprio == 0) {
if (priority < virLogDefaultPriority)
emit = 0;
@@ -753,13 +763,14 @@ void virLogMessage(const char *category, int priority, const char *funcname,
if (virLogVersionString(&ver) >= 0)
virLogOutputs[i].f(category, VIR_LOG_INFO,
__func__, __LINE__,
- timestamp, ver,
+ timestamp, 0, ver,
virLogOutputs[i].data);
VIR_FREE(ver);
virLogOutputs[i].logVersion = false;
}
virLogOutputs[i].f(category, priority, funcname, linenr,
- timestamp, msg, virLogOutputs[i].data);
+ timestamp, filterflags,
+ msg, virLogOutputs[i].data);
}
}
if ((virLogNbOutputs == 0) && (flags != 1)) {
@@ -768,13 +779,14 @@ void virLogMessage(const char *category, int priority, const char *funcname,
if (virLogVersionString(&ver) >= 0)
virLogOutputToFd(category, VIR_LOG_INFO,
__func__, __LINE__,
- timestamp, ver,
+ timestamp, 0, ver,
(void *) STDERR_FILENO);
VIR_FREE(ver);
logVersionStderr = false;
}
virLogOutputToFd(category, priority, funcname, linenr,
- timestamp, msg, (void *) STDERR_FILENO);
+ timestamp, filterflags,
+ msg, (void *) STDERR_FILENO);
}
virLogUnlock();
@@ -783,11 +795,30 @@ cleanup:
errno = saved_errno;
}
+
+static void virLogStackTraceToFd(int fd)
+{
+#ifdef HAVE_EXECINFO_H
+ void *array[100];
+ int size;
+
+#define STRIP_DEPTH 3
+
+ size = backtrace(array, sizeof(array)/sizeof(array[0]));
+ backtrace_symbols_fd(array + STRIP_DEPTH, size - STRIP_DEPTH, fd);
+ ignore_value(safewrite(fd, "\n", 1));
+#else
+ const char *msg = "stack trace not available on this platform";
+ ignore_value(safewrite(fd, msg, strlen(msg)));
+#endif
+}
+
static int virLogOutputToFd(const char *category ATTRIBUTE_UNUSED,
int priority ATTRIBUTE_UNUSED,
const char *funcname ATTRIBUTE_UNUSED,
long long linenr ATTRIBUTE_UNUSED,
const char *timestamp,
+ unsigned int flags,
const char *str,
void *data)
{
@@ -804,6 +835,9 @@ static int virLogOutputToFd(const char *category ATTRIBUTE_UNUSED,
ret = safewrite(fd, msg, strlen(msg));
VIR_FREE(msg);
+ if (flags & VIR_LOG_STACK_TRACE)
+ virLogStackTraceToFd(fd);
+
return ret;
}
@@ -841,6 +875,7 @@ static int virLogOutputToSyslog(const char *category ATTRIBUTE_UNUSED,
const char *funcname ATTRIBUTE_UNUSED,
long long linenr ATTRIBUTE_UNUSED,
const char *timestamp ATTRIBUTE_UNUSED,
+ unsigned int flags ATTRIBUTE_UNUSED,
const char *str,
void *data ATTRIBUTE_UNUSED)
{
@@ -1024,12 +1059,17 @@ int virLogParseFilters(const char *filters) {
virSkipSpaces(&cur);
while (*cur != 0) {
+ unsigned int flags = 0;
prio= virParseNumber(&cur);
if ((prio < VIR_LOG_DEBUG) || (prio > VIR_LOG_ERROR))
goto cleanup;
if (*cur != ':')
goto cleanup;
cur++;
+ if (*cur == '+') {
+ flags |= VIR_LOG_STACK_TRACE;
+ cur++;
+ }
str = cur;
while ((*cur != 0) && (!IS_SPACE(cur)))
cur++;
@@ -1038,7 +1078,7 @@ int virLogParseFilters(const char *filters) {
name = strndup(str, cur - str);
if (name == NULL)
goto cleanup;
- if (virLogDefineFilter(name, prio, 0) >= 0)
+ if (virLogDefineFilter(name, prio, flags) >= 0)
count++;
VIR_FREE(name);
virSkipSpaces(&cur);
@@ -1072,7 +1112,12 @@ char *virLogGetFilters(void) {
virLogLock();
for (i = 0; i < virLogNbFilters; i++) {
- virBufferAsprintf(&filterbuf, "%d:%s ", virLogFilters[i].priority,
+ const char *sep = ":";
+ if (virLogFilters[i].flags & VIR_LOG_STACK_TRACE)
+ sep = ":+";
+ virBufferAsprintf(&filterbuf, "%d%s%s ",
+ virLogFilters[i].priority,
+ sep,
virLogFilters[i].match);
}
virLogUnlock();
diff --git a/src/util/logging.h b/src/util/logging.h
index 2343de0..a6fa63e 100644
--- a/src/util/logging.h
+++ b/src/util/logging.h
@@ -79,6 +79,7 @@ typedef enum {
* @funcname: the function emitting the message
* @linenr: line where the message was emitted
* @timestamp: zero terminated string with timestamp of the message
+ * @flags: flags associated with the message
* @str: the message to log, preformatted and zero terminated
* @data: extra output logging data
*
@@ -88,7 +89,9 @@ typedef enum {
*/
typedef int (*virLogOutputFunc) (const char *category, int priority,
const char *funcname, long long linenr,
- const char *timestamp, const char *str,
+ const char *timestamp,
+ unsigned int flags,
+ const char *str,
void *data);
/**
@@ -99,6 +102,10 @@ typedef int (*virLogOutputFunc) (const char *category, int priority,
*/
typedef void (*virLogCloseFunc) (void *data);
+typedef enum {
+ VIR_LOG_STACK_TRACE = (1 << 0),
+} virLogFlags;
+
extern int virLogGetNbFilters(void);
extern int virLogGetNbOutputs(void);
extern char *virLogGetFilters(void);
diff --git a/tests/testutils.c b/tests/testutils.c
index 4e8484f..57cf84c 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -469,6 +469,7 @@ virtTestLogOutput(const char *category ATTRIBUTE_UNUSED,
const char *funcname ATTRIBUTE_UNUSED,
long long lineno ATTRIBUTE_UNUSED,
const char *timestamp,
+ unsigned int flags ATTRIBUTE_UNUSED,
const char *str,
void *data)
{
--
1.7.10.1
12 years, 6 months
[libvirt] Re-2: Re-4: [Patch] Libvirt - Fix locking for readonly devices
by David Weber
> >> Thanks, your patch looks good but needs two further small additions
> >> to the libvirt_sanlock.aug and test_libvirt_sanlock.aug files to
> >> take account of the new config parameter.
> >
> > Oops, Updated patch attached (tested with augparse)
> >
> > David
> >
> >
> > ----------------------------------------
> >
> > commit 33678a8b2d294bebf327106d586d41c9b157174f
> > Author: David Weber <wb(a)munzinger.de>
> > Date: Mon May 14 09:43:27 2012 +0200
> >
> > Add ignore param for readonly and shared disk in sanlock
>
> ACK and pushed, after fixing up whitespace nits ('make syntax-check'
> would have caught the trailing whitespace, but not the other one), and
> adding you to AUTHORS (let me know if you prefer an alternate spelling).
Thanks for the push. Sorry for all the problems. I'll do it better next
time ;)
>
> Is it sanlock, or libvirt, or a combination of both that don't yet
> support shared resource locks? I modified this as follows (and hope
> that it was good enough, since I pushed):
>
> # Enable this flag to have sanlock ignore readonly and shared disks.
> # If disabled, then this rejects attempts to share resources until
> # sanlock gains support for shared locks.
> #
> #ignore_readonly_and_shared_disks = 1
Right, it's sanlock who doesn't support it. So your text is right.
David
To: eblake(a)redhat.com
Cc: berrange(a)redhat.com
libvir-list(a)redhat.com
sanlock-devel(a)lists.fedorahosted.org
12 years, 6 months