[libvirt] [PATCH] Keep track of guest paused state after disk IO errors
by Daniel P. Berrange
With the QMP mode monitor, it is possible to get a notification
when the guest is paused indirectly (eg as result of a disk IO
error). This patch enables such reporting and when receiving an
error updates libvirt's view of the guest to indicate that it is
now paused. It also emits an event
VIR_DOMAIN_EVENT_SUSPENDED
with a detail of:
VIR_DOMAIN_EVENT_SUSPENDED_IOERROR
NB this patch does not make the error behaviour configurable. It
just copes with the pause transition, if QEMU is setup to do that
by default (current upstream now works this way for disks).
* include/libvirt/libvirt.h.in: Add VIR_DOMAIN_EVENT_SUSPENDED_IOERROR
* src/qemu/qemu_driver.c: Update VM state to paused when IO error
occurrs
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Wire up handlers for disk IO errors
---
include/libvirt/libvirt.h.in | 1 +
src/qemu/qemu_driver.c | 42 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 18 ++++++++++++++++++
src/qemu/qemu_monitor.h | 16 ++++++++++++++++
src/qemu/qemu_monitor_json.c | 34 ++++++++++++++++++++++++++++++++++
5 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 260505e..b7a6922 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1361,6 +1361,7 @@ typedef enum {
typedef enum {
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED = 0, /* Normal suspend due to admin pause */
VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED = 1, /* Suspended for offline migration */
+ VIR_DOMAIN_EVENT_SUSPENDED_IOERROR = 2, /* Suspended due to a disk I/O error */
} virDomainEventSuspendedDetailType;
/**
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8766ca2..ae19097 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -824,9 +824,51 @@ cleanup:
return ret;
}
+
+static int
+qemuHandleDiskIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ int action,
+ const char *diskalias ATTRIBUTE_UNUSED)
+{
+ struct qemud_driver *driver = qemu_driver;
+ virDomainEventPtr event = NULL;
+
+ VIR_DEBUG("Received IO error on %p '%s': action=%d disk=%s", vm, vm->def->name, action, diskalias);
+
+ if (action != QEMU_MONITOR_DISK_IO_ERROR_STOP)
+ return 0;
+
+ virDomainObjLock(vm);
+
+ if (action == QEMU_MONITOR_DISK_IO_ERROR_STOP &&
+ vm->state == VIR_DOMAIN_RUNNING) {
+ VIR_DEBUG("Transitioned guest %s to paused state", vm->def->name);
+
+ vm->state = VIR_DOMAIN_PAUSED;
+ event = virDomainEventNewFromObj(vm,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_IOERROR);
+
+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
+ VIR_WARN("Unable to save status on vm %s after IO error", vm->def->name);
+ }
+
+ virDomainObjUnlock(vm);
+
+ if (event) {
+ qemuDriverLock(driver);
+ qemuDomainEventQueue(driver, event);
+ qemuDriverUnlock(driver);
+ }
+ return 0;
+}
+
+
static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuHandleMonitorEOF,
.diskSecretLookup = findVolumeQcowPassphrase,
+ .diskIOError = qemuHandleDiskIOError,
};
static int
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b88532c..7205001 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -791,6 +791,24 @@ int qemuMonitorEmitStop(qemuMonitorPtr mon)
}
+int qemuMonitorEmitDiskIOError(qemuMonitorPtr mon,
+ int action,
+ const char *deviceAlias)
+{
+ int ret = -1;
+ VIR_DEBUG("mon=%p action=%d deviceAlias=%s", mon, action, deviceAlias);
+
+ qemuMonitorRef(mon);
+ qemuMonitorUnlock(mon);
+ if (mon->cb && mon->cb->diskIOError)
+ ret = mon->cb->diskIOError(mon, mon->vm, action, deviceAlias);
+ qemuMonitorLock(mon);
+ qemuMonitorUnref(mon);
+
+ return ret;
+}
+
+
int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
{
int ret;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 0ac3957..75a2853 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -60,6 +60,14 @@ struct _qemuMonitorMessage {
void *passwordOpaque;
};
+typedef enum {
+ QEMU_MONITOR_DISK_IO_ERROR_STOP,
+ QEMU_MONITOR_DISK_IO_ERROR_REPORT,
+ QEMU_MONITOR_DISK_IO_ERROR_IGNORE,
+
+ QEMU_MONITOR_DISK_IO_ERROR_LAST
+} qemuMonitorDiskIOErrorAction;
+
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
struct _qemuMonitorCallbacks {
@@ -86,6 +94,11 @@ struct _qemuMonitorCallbacks {
virDomainObjPtr vm);
int (*domainStop)(qemuMonitorPtr mon,
virDomainObjPtr vm);
+
+ int (*diskIOError)(qemuMonitorPtr mon,
+ virDomainObjPtr vm,
+ int actOBion,
+ const char *diskAlias);
};
@@ -122,6 +135,9 @@ int qemuMonitorEmitShutdown(qemuMonitorPtr mon);
int qemuMonitorEmitReset(qemuMonitorPtr mon);
int qemuMonitorEmitPowerdown(qemuMonitorPtr mon);
int qemuMonitorEmitStop(qemuMonitorPtr mon);
+int qemuMonitorEmitDiskIOError(qemuMonitorPtr mon,
+ int action,
+ const char *deviceAlias);
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 7b45594..8b3cda1 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -49,6 +49,7 @@ static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr da
static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleDiskIOError(qemuMonitorPtr mon, virJSONValuePtr data);
struct {
const char *type;
@@ -58,6 +59,7 @@ struct {
{ "RESET", qemuMonitorJSONHandleReset, },
{ "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
{ "STOP", qemuMonitorJSONHandleStop, },
+ { "BLOCK_IO_ERROR", qemuMonitorJSONHandleDiskIOError, },
};
@@ -496,6 +498,38 @@ static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data A
}
+VIR_ENUM_DECL(qemuMonitorDiskIOErrorAction)
+VIR_ENUM_IMPL(qemuMonitorDiskIOErrorAction, QEMU_MONITOR_DISK_IO_ERROR_LAST,
+ "stop", "report", "ignore");
+
+
+static void qemuMonitorJSONHandleDiskIOError(qemuMonitorPtr mon, virJSONValuePtr data)
+{
+ const char *device;
+ const char *action;
+ int actionID;
+
+ /* Throughout here we try our best to carry on upon errors,
+ since its imporatant to get as much info as possible out
+ to the application */
+
+ if ((action = virJSONValueObjectGetString(data, "action")) == NULL) {
+ VIR_WARN0("Missing action in disk io error event");
+ action = "ignore";
+ }
+
+ if ((device = virJSONValueObjectGetString(data, "device")) == NULL) {
+ VIR_WARN0("missing device in disk io error event");
+ }
+
+ if ((actionID = qemuMonitorDiskIOErrorActionTypeFromString(action)) < 0) {
+ VIR_WARN("unknown disk io error action '%s'", action);
+ actionID = QEMU_MONITOR_DISK_IO_ERROR_IGNORE;
+ }
+
+ qemuMonitorEmitDiskIOError(mon, actionID, device);
+}
+
int
qemuMonitorJSONSetCapabilities(qemuMonitorPtr mon)
{
--
1.6.2.5
14 years, 8 months
[libvirt] [PATCH] qemu: Fix FD leak in qemudStartVMDaemon
by Matthias Bolte
The logfile FD is dup2'ed in __virExec in the child. The FD needs to
be closed in the parent, otherwise it leaks.
---
src/qemu/qemu_driver.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c8f3a15..fbb1275 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2963,6 +2963,9 @@ static int qemudStartVMDaemon(virConnectPtr conn,
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
goto abort;
+ if (logfile != -1)
+ close(logfile);
+
return 0;
cleanup:
--
1.6.3.3
14 years, 8 months
[libvirt] [PATCH 14/14] Extension for iptables rules
by Stefan Berger
This patch adds support for L3/L4 filtering using iptables. This adds
support for 'tcp', 'udp', 'icmp', 'igmp', 'sctp' etc. filtering.
As mentioned in the introduction, a .c file provided by this patch
is #include'd into a .c file. This will need work, but should be alright
for review.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
14 years, 8 months
[libvirt] [PATCH] util: ensure virMutexInit is not recursive
by Eric Blake
POSIX states that creation of a mutex with default attributes
is unspecified whether the mutex is recursive or non-recursive.
We specifically want non-recursive (deadlock is desirable in
flushing out coding bugs that used our mutex incorrectly).
* src/util/threads-pthread.c (virMutexInit): Specifically request
non-recursive mutex, rather than relying on unspecified default.
---
src/util/threads-pthread.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c
index ad42483..2f0746b 100644
--- a/src/util/threads-pthread.c
+++ b/src/util/threads-pthread.c
@@ -1,7 +1,7 @@
/*
* threads-pthread.c: basic thread synchronization primitives
*
- * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009-2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -36,7 +36,10 @@ void virThreadOnExit(void)
int virMutexInit(virMutexPtr m)
{
int ret;
- if ((ret = pthread_mutex_init(&m->lock, NULL)) != 0) {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+ if ((ret = pthread_mutex_init(&m->lock, &attr)) != 0) {
errno = ret;
return -1;
}
--
1.6.6.1
14 years, 8 months
[libvirt] [PATCH] maint: make Red Hat copyright notices consistent
by Eric Blake
Spell out 'Red Hat, Inc.':
git grep -i 'Copyright.*Red Hat' | grep -v Inc
Include (C) consistently:
git grep -i 'Copyright [^(].*Red Hat'
* src/lxc/lxc_container.c: Update copyright formatting.
* src/node_device/node_device_udev.c: Likewise.
* src/node_device/node_device_udev.h: Likewise.
* src/xen/xend_internal.h: Likewise.
* src/xen/xm_internal.c: Likewise.
* src/xen/xm_internal.h: Likewise.
* tests/xmconfigtest.c: Likewise.
* tests/object-locking.ml: Likewise.
---
src/lxc/lxc_container.c | 4 ++--
src/node_device/node_device_udev.c | 2 +-
src/node_device/node_device_udev.h | 2 +-
src/xen/xend_internal.h | 2 +-
src/xen/xm_internal.c | 2 +-
src/xen/xm_internal.h | 2 +-
tests/object-locking.ml | 2 +-
tests/xmconfigtest.c | 2 +-
8 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 68b4656..706c796 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1,6 +1,6 @@
/*
- * Copyright IBM Corp. 2008
- * Copyright Red Hat 2008-2009
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2008 IBM Corp.
*
* lxc_container.c: file description
*
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 11e27e0..e3114fa 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1,7 +1,7 @@
/*
* node_device_udev.c: node device enumeration - libudev implementation
*
- * Copyright (C) 2009-2010 Red Hat
+ * Copyright (C) 2009-2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/src/node_device/node_device_udev.h b/src/node_device/node_device_udev.h
index 8367494..cdaa142 100644
--- a/src/node_device/node_device_udev.h
+++ b/src/node_device/node_device_udev.h
@@ -1,7 +1,7 @@
/*
* node_device_udev.h: node device enumeration - libudev implementation
*
- * Copyright (C) 2009 Red Hat
+ * Copyright (C) 2009-2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
index 483253f..028a293 100644
--- a/src/xen/xend_internal.h
+++ b/src/xen/xend_internal.h
@@ -1,12 +1,12 @@
/*
* xend_internal.h
*
+ * Copyright (C) 2006-2008, 2010 Red Hat, Inc.
* Copyright (C) 2005,2006
*
* Anthony Liguori <aliguori(a)us.ibm.com>
* Daniel Veillard <veillard(a)redhat.com>
*
- * Copyright 2006-2008 Red Hat
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file COPYING in the main directory of this archive
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 3d4624d..74bf0b6 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -1,7 +1,7 @@
/*
* xm_internal.h: helper routines for dealing with inactive domains
*
- * Copyright (C) 2006-2007, 2009, 2010 Red Hat
+ * Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h
index 37132ef..3ad3456 100644
--- a/src/xen/xm_internal.h
+++ b/src/xen/xm_internal.h
@@ -1,7 +1,7 @@
/*
* xm_internal.h: helper routines for dealing with inactive domains
*
- * Copyright (C) 2006-2007 Red Hat
+ * Copyright (C) 2006-2007, 2010 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
diff --git a/tests/object-locking.ml b/tests/object-locking.ml
index a4cd77d..1fddd51 100644
--- a/tests/object-locking.ml
+++ b/tests/object-locking.ml
@@ -1,7 +1,7 @@
(*
* Analyse libvirt driver API methods for mutex locking mistakes
*
- * Copyright 2008-2009 Red Hat, Inc
+ * Copyright (C) 2008-2010 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c
index acb6d18..a199c72 100644
--- a/tests/xmconfigtest.c
+++ b/tests/xmconfigtest.c
@@ -1,7 +1,7 @@
/*
* xmconfigtest.c: Test backend for xm_internal config file handling
*
- * Copyright (C) 2007 Red Hat
+ * Copyright (C) 2007, 2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
--
1.6.6.1
14 years, 8 months
Re: [libvirt] virtio serial config
by Matthew Booth
On 18/03/10 14:31, Matthew Whitehead wrote:
> Matthew,
> Dan B referred me to you. I want to create 4 (or more) virtual serial devices between two KVM virtual hosts. The output of one serial device would be the input to the other. Virt-manager doesn't provide this, so I'm prepared to hack the config files manually. Unfortunately, I can't find documentation on the syntax.
>
> Can you assist?
I'm normally the one complaining about lack of documentation :) That's
quite an oversight.
The basic syntax for a virtio-serial channel is:
<channel type='pty'>
<target type='virtio' name='org.linux-kvm.port.1'/>
</channel>
You'll want 4 <channel/> entries per guest. Give them all different names.
The interesting bit is going to be plugging the character devices
together on the host. I'm pretty sure you'll have to use pipes. Note
that afaik the libvirt documentation on this is wrong and misleading.
Don't read it, just test instead :)
IIRC, the way pipes actually work is that it expects to be able to use 2
pipes based on the path you specify, called foo.in and foo.out. I seem
to recall you need to create these manually too. The following advice is
completely untested. It may also be responsible for global warming and
the rise of reality TV.
Host:
# mkfifo /tmp/guesta-virtioserial{1,2}.{in,out}
# ln /tmp/guesta-virtioserial1.in /tmp/guestb-virtioserial1.out
# ln /tmp/guesta-virtioserial1.out /tmp/guestb-virtioserial1.in
# ln /tmp/guesta-virtioserial2.in /tmp/guestb-virtioserial2.out
# ln /tmp/guesta-virtioserial2.out /tmp/guestb-virtioserial2.in
Guest A:
<channel type='pipe'>
<source path="/tmp/guesta-virtioserial1"/>
<target type='virtio' name='org.linux-kvm.port.1'/>
</channel>
<channel type='pipe'>
<source path="/tmp/guesta-virtioserial2"/>
<target type='virtio' name='org.linux-kvm.port.2'/>
</channel>
Guest B:
<channel type='pipe'>
<source path="/tmp/guestb-virtioserial1"/>
<target type='virtio' name='org.linux-kvm.port.1'/>
</channel>
<channel type='pipe'>
<source path="/tmp/guestb-virtioserial2"/>
<target type='virtio' name='org.linux-kvm.port.2'/>
</channel>
At this point, both virtio-serial devices in each guest should be
full-duplex.
Matt
--
Matthew Booth, RHCA, RHCSS
Red Hat Engineering, Virtualisation Team
M: +44 (0)7977 267231
GPG ID: D33C3490
GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490
14 years, 8 months
[libvirt] [APPENDIX] Sample filters
by Stefan Berger
Attached are some sample filter templates. Some of these should probably
become available through libvirt repository later on as 'standard
filters'.
One may copy the XML files into /etc/libvirt/nwfilter or use 'virsh
nwfilter-define <filename>' to make them known to libvirt. Using 'virsh
nwfilter-list' one can then list the filters.
The simpleloop.xml filter will not be accepted since it would directly
introduce a loop. More complex loops are also detected.
Regards,
Stefan, Gerhard
14 years, 8 months