[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Re: -drive werror=stop can cause state change handlers run
From: |
Markus Armbruster |
Subject: |
[Qemu-devel] Re: -drive werror=stop can cause state change handlers run out of order |
Date: |
Mon, 27 Jul 2009 20:44:27 +0200 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.3 (gnu/linux) |
I reproduced the problem as follows.
The appended patch does two things:
1. It lets me inject write errors by setting variable inject_write_error
in gdb. Crude, but works.
2. It shows what audio_vm_change_state_handler() does.
Apply it and start a guest with sound and werror=stop under gdb, say
$ gdb --args qemu -drive file=f10.qcow2,werror=stop -soundhw ac97 -monitor
unix:monitor,server,nowait
Let it boot to single user mode (just to speed things up). When
everything's nicely quiet, do
(gdb) set inject_write_error=1000
(gdb) c
Trigger a write. Running "sync" works for me. Guest stops, printing
injecting write error on ide0-hd0
audio_vm_change_state_handler voice disable
Connect to the monitor and resume the guest ("c"). Guest stops,
printing
injecting write error on ide0-hd0
audio_vm_change_state_handler voice disable
injecting write error on ide0-hd0
audio_vm_change_state_handler voice enable
You see that audio_vm_change_state_handler() are run in the wrong order,
and voice is thus left enabled rather than disabled.
diff --git a/audio/audio.c b/audio/audio.c
index 694a83e..64d079f 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1630,6 +1630,9 @@ static void audio_vm_change_state_handler (void *opaque,
int running,
HWVoiceIn *hwi = NULL;
int op = running ? VOICE_ENABLE : VOICE_DISABLE;
+ printf("audio_vm_change_state_handler voice %s\n",
+ running ? "enable" : "disable");
+
s->vm_running = running;
while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
hwo->pcm_ops->ctl_out (hwo, op);
diff --git a/hw/ide.c b/hw/ide.c
index 1e56786..98d0315 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -1060,6 +1061,8 @@ static void ide_sector_write_timer_cb(void *opaque)
ide_set_irq(s);
}
+int inject_write_error;
+
static void ide_sector_write(IDEState *s)
{
int64_t sector_num;
@@ -1075,6 +1078,12 @@ static void ide_sector_write(IDEState *s)
n = s->req_nb_sectors;
ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
+ if (inject_write_error) {
+ printf("injecting write error on %s\n", s->bs->device_name);
+ ret = -EIO;
+ inject_write_error--;
+ }
+
if (ret != 0) {
if (ide_handle_write_error(s, -ret, BM_STATUS_PIO_RETRY))
return;