* [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2
@ 2012-08-21 17:05 Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 01/23] qtest: fix infinite loop when QEMU aborts abruptly Michael Roth
` (22 more replies)
0 siblings, 23 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
This is the current list of candidates for QEMU 1.1.2, which we're planning
to release on Friday. Please review and respond with any additional patches
you think should be included. These are also available at:
git://github.com/mdroth/qemu.git stable-1.1-staging
There's a few that Michael Tokarov had mentioned to me that are not
upstream yet that I'd also like to pull in:
"ahci: fix cdrom read corruption"
http://thread.gmane.org/gmane.comp.emulators.qemu/163543
"commit da57febfed "qdev: give all devices a canonical path" broke usb_ [...]"
http://thread.gmane.org/gmane.comp.emulators.qemu/164180/focus=164185
And one I just sent out:
"libcacard: Fix segfault when no backend specified"
Queued patches follow:
Anthony Liguori (2):
qtest: fix infinite loop when QEMU aborts abruptly
qdev: fix use-after-free in the error path of qdev_init_nofail
Avi Kivity (1):
virtio-blk: fix use-after-free while handling scsi commands
Christian Borntraeger (1):
s390: Fix error handling and condition code of service call
David Gibson (1):
ppc: Fix bug in handling of PAPR hypercall exits
Dunrong Huang (1):
slirp: Ensure smbd and shared directory exist when enable smb
Gerd Hoffmann (4):
ehci: fix reset
ehci: don't flush cache on doorbell rings.
uhci: fix uhci_async_cancel_all
usb: restore USBDevice->attached on vmload
Hans de Goede (2):
usb-redir: Correctly handle the usb_redir_babble usbredir status
usb-ehci: Fix an assert whenever isoc transfers are used
Jan Kiszka (6):
kvmvapic: Disable if there is insufficient memory
slirp: Enforce host-side user of smb share
slirp: Improve error reporting of inaccessible smb directories
apic: Resolve potential endless loop around apic_update_irq
apic: Reevaluate pending interrupts on LVT_LINT0 changes
apic: Defer interrupt updates to VCPU thread
Michael Roth (4):
qlist: add qlist_size()
json-parser: don't replicate tokens at each level of recursion
check-qjson: add test for large JSON objects
update VERSION for 1.1.2
Peter Maydell (1):
configure: Don't override user's --cpu on MacOS and Solaris
VERSION | 2 +-
configure | 60 +++++++-----
cpu-exec.c | 6 ++
hw/apic.c | 27 +++++-
hw/apic.h | 1 +
hw/apic_common.c | 4 +-
hw/apic_internal.h | 1 -
hw/qdev.c | 5 +-
hw/usb/bus.c | 13 +++
hw/usb/hcd-ehci.c | 45 +++++++--
hw/usb/hcd-uhci.c | 4 +-
hw/usb/redirect.c | 2 +
hw/virtio-blk.c | 1 +
json-parser.c | 230 ++++++++++++++++++++++++++++------------------
net/slirp.c | 26 +++++-
qlist.c | 13 +++
qlist.h | 1 +
target-i386/cpu.h | 4 +-
target-i386/kvm.c | 4 +
target-ppc/kvm.c | 2 +-
target-s390x/kvm.c | 5 +-
target-s390x/op_helper.c | 27 ++++--
tests/check-qjson.c | 53 +++++++++++
tests/libqtest.c | 5 +
24 files changed, 391 insertions(+), 150 deletions(-)
^ permalink raw reply [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 01/23] qtest: fix infinite loop when QEMU aborts abruptly
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 02/23] configure: Don't override user's --cpu on MacOS and Solaris Michael Roth
` (21 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Anthony Liguori <aliguori@us.ibm.com>
>From Markus:
Makes "make check" hang:
QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 gtester -k --verbose -m=quick tests/crash-test tests/rtc-test
TEST: tests/crash-test... (pid=972)
qemu-system-x86_64: Device needs media, but drive is empty
[Nothing happens, wait a while, then hit ^C]
make: *** [check-qtest-x86_64] Interrupt
This was due to the fact that we weren't checked for errors when
reading from the QMP socket. This patch adds appropriate error
checking.
Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 039380a8e18f618cdacf72486449c04dc1b70eef)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tests/libqtest.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 6d333ef..0664323 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -290,6 +290,11 @@ void qtest_qmp(QTestState *s, const char *fmt, ...)
continue;
}
+ if (len == -1 || len == 0) {
+ fprintf(stderr, "Broken pipe\n");
+ exit(1);
+ }
+
switch (c) {
case '{':
nesting++;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 02/23] configure: Don't override user's --cpu on MacOS and Solaris
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 01/23] qtest: fix infinite loop when QEMU aborts abruptly Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 03/23] ppc: Fix bug in handling of PAPR hypercall exits Michael Roth
` (20 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Peter Maydell <peter.maydell@linaro.org>
Both MacOS and Solaris have special case handling for the CPU
type, because the check_define probes will return i386 even if
the hardware is 64 bit and x86_64 would be preferable. Move
these checks earlier in the configure probing so that we can
do them only if the user didn't specify a CPU with --cpu. This
fixes a bug where the user's command line argument was being
ignored.
Reviewed-by: Andreas F=E4rber <afaerber@suse.de>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit bbea4050802a2e7e0296a21823c0925782c02b93)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
configure | 60 +++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 35 insertions(+), 25 deletions(-)
diff --git a/configure b/configure
index 72d16a4..df29c2f 100755
--- a/configure
+++ b/configure
@@ -275,6 +275,41 @@ EOF
compile_object
}
+if check_define __linux__ ; then
+ targetos="Linux"
+elif check_define _WIN32 ; then
+ targetos='MINGW32'
+elif check_define __OpenBSD__ ; then
+ targetos='OpenBSD'
+elif check_define __sun__ ; then
+ targetos='SunOS'
+elif check_define __HAIKU__ ; then
+ targetos='Haiku'
+else
+ targetos=`uname -s`
+fi
+
+# Some host OSes need non-standard checks for which CPU to use.
+# Note that these checks are broken for cross-compilation: if you're
+# cross-compiling to one of these OSes then you'll need to specify
+# the correct CPU with the --cpu option.
+case $targetos in
+Darwin)
+ # on Leopard most of the system is 32-bit, so we have to ask the kernel if we can
+ # run 64-bit userspace code.
+ # If the user didn't specify a CPU explicitly and the kernel says this is
+ # 64 bit hw, then assume x86_64. Otherwise fall through to the usual detection code.
+ if test -z "$cpu" && test "$(sysctl -n hw.optional.x86_64)" = "1"; then
+ cpu="x86_64"
+ fi
+ ;;
+SunOS)
+ # `uname -m` returns i86pc even on an x86_64 box, so default based on isainfo
+ if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
+ cpu="x86_64"
+ fi
+esac
+
if test ! -z "$cpu" ; then
# command line argument
:
@@ -349,19 +384,6 @@ if test -z "$ARCH"; then
fi
# OS specific
-if check_define __linux__ ; then
- targetos="Linux"
-elif check_define _WIN32 ; then
- targetos='MINGW32'
-elif check_define __OpenBSD__ ; then
- targetos='OpenBSD'
-elif check_define __sun__ ; then
- targetos='SunOS'
-elif check_define __HAIKU__ ; then
- targetos='Haiku'
-else
- targetos=`uname -s`
-fi
case $targetos in
CYGWIN*)
@@ -411,12 +433,6 @@ OpenBSD)
Darwin)
bsd="yes"
darwin="yes"
- # on Leopard most of the system is 32-bit, so we have to ask the kernel it if we can
- # run 64-bit userspace code
- if [ "$cpu" = "i386" ] ; then
- is_x86_64=`sysctl -n hw.optional.x86_64`
- [ "$is_x86_64" = "1" ] && cpu=x86_64
- fi
if [ "$cpu" = "x86_64" ] ; then
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
LDFLAGS="-arch x86_64 $LDFLAGS"
@@ -437,12 +453,6 @@ SunOS)
smbd="${SMBD-/usr/sfw/sbin/smbd}"
needs_libsunmath="no"
solarisrev=`uname -r | cut -f2 -d.`
- # have to select again, because `uname -m` returns i86pc
- # even on an x86_64 box.
- solariscpu=`isainfo -k`
- if test "${solariscpu}" = "amd64" ; then
- cpu="x86_64"
- fi
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
if test "$solarisrev" -le 9 ; then
if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 03/23] ppc: Fix bug in handling of PAPR hypercall exits
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 01/23] qtest: fix infinite loop when QEMU aborts abruptly Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 02/23] configure: Don't override user's --cpu on MacOS and Solaris Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 04/23] s390: Fix error handling and condition code of service call Michael Roth
` (19 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: David Gibson <david@gibson.dropbear.id.au>
Currently for powerpc, kvm_arch_handle_exit() always returns 1, meaning
that its caller - kvm_cpu_exec() - will always exit immediately afterwards
to the loop in qemu_kvm_cpu_thread_fn().
There's no need to do this. Once we've handled the hypercall there's no
reason we can't go straight around and KVM_RUN again, which is what ret = 0
will signal. The only exception might be for hypercalls which affect the
state of cpu_can_run(), however the only one that might do this is H_CEDE
and for kvm that is always handled in the kernel, not qemu.
Furtherm setting ret = 0 means that when exit_requested is set from a
hypercall, we will enter KVM_RUN once more with a signal which lets the
the kernel do its internal logic to complete the hypercall with out
actually executing any more guest code. This is important if our hypercall
also triggered a reset, which previously would re-initialize everything
without completing the hypercall. This caused the kernel to get confused
because it thought the guest was still in the middle of a hypercall when
it has actually been reset.
This patch therefore changes to ret = 0, which is both a bugfix and a small
optimization.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit 78e8fde26c032931ca2ae13bfc7c59e38afd17ee)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-ppc/kvm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index c09cc39..29997af 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -558,7 +558,7 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run)
dprintf("handle PAPR hypercall\n");
run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr,
run->papr_hcall.args);
- ret = 1;
+ ret = 0;
break;
#endif
default:
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 04/23] s390: Fix error handling and condition code of service call
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (2 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 03/23] ppc: Fix bug in handling of PAPR hypercall exits Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 05/23] kvmvapic: Disable if there is insufficient memory Michael Roth
` (18 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Christian Borntraeger <borntraeger@de.ibm.com>
Invalid sccb addresses will cause specification or addressing exception.
Lets add those checks. Furthermore, the good case (cc=0) was incorrect
for KVM, we did not set the CC at all. We now use return codes < 0
as program checks and return codes > 0 as condition code values.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
(cherry picked from commit 9abf567d95a4e840df868ca993219175fbef8c22)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
target-s390x/kvm.c | 5 +++--
target-s390x/op_helper.c | 27 ++++++++++++++++++---------
2 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 90aad61..e4e6f15 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -238,9 +238,10 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run,
code = env->regs[(ipbh0 & 0xf0) >> 4];
r = sclp_service_call(env, sccb, code);
- if (r) {
- setcc(env, 3);
+ if (r < 0) {
+ enter_pgmcheck(env, -r);
}
+ setcc(env, r);
return 0;
}
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 7b72473..91dd8dc 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -19,6 +19,8 @@
*/
#include "cpu.h"
+#include "memory.h"
+#include "cputlb.h"
#include "dyngen-exec.h"
#include "host-utils.h"
#include "helper.h"
@@ -2366,6 +2368,9 @@ static void ext_interrupt(CPUS390XState *env, int type, uint32_t param,
cpu_inject_ext(env, type, param, param64);
}
+/*
+ * ret < 0 indicates program check, ret = 0,1,2,3 -> cc
+ */
int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
{
int r = 0;
@@ -2375,10 +2380,12 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code);
#endif
+ /* basic checks */
+ if (!memory_region_is_ram(phys_page_find(sccb >> TARGET_PAGE_BITS)->mr)) {
+ return -PGM_ADDRESSING;
+ }
if (sccb & ~0x7ffffff8ul) {
- fprintf(stderr, "KVM: invalid sccb address 0x%x\n", sccb);
- r = -1;
- goto out;
+ return -PGM_SPECIFICATION;
}
switch(code) {
@@ -2405,22 +2412,24 @@ int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code)
#ifdef DEBUG_HELPER
printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code);
#endif
- r = -1;
+ r = 3;
break;
}
-out:
return r;
}
/* SCLP service call */
uint32_t HELPER(servc)(uint32_t r1, uint64_t r2)
{
- if (sclp_service_call(env, r1, r2)) {
- return 3;
- }
+ int r;
- return 0;
+ r = sclp_service_call(env, r1, r2);
+ if (r < 0) {
+ program_interrupt(env, -r, 4);
+ return 0;
+ }
+ return r;
}
/* DIAG */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 05/23] kvmvapic: Disable if there is insufficient memory
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (3 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 04/23] s390: Fix error handling and condition code of service call Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 06/23] qdev: fix use-after-free in the error path of qdev_init_nofail Michael Roth
` (17 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Jan Kiszka <jan.kiszka@siemens.com>
We need at least 1M of RAM to map the option ROM. Otherwise, we will
corrupt host memory or even crash:
$ qemu-system-x86_64 -nodefaults --enable-kvm -vnc :0 -m 640k
Segmentation fault (core dumped)
Reported-and-tested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
(cherry picked from commit a9605e0317c7a6d5e68f3a3b6708c8ef1096f4bc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/apic_common.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/hw/apic_common.c b/hw/apic_common.c
index 60b8259..e4612bb 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -289,7 +289,9 @@ static int apic_init_common(SysBusDevice *dev)
sysbus_init_mmio(dev, &s->io_memory);
- if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK) {
+ /* Note: We need at least 1M to map the VAPIC option ROM */
+ if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
+ ram_size >= 1024 * 1024) {
vapic = sysbus_create_simple("kvmvapic", -1, NULL);
}
s->vapic = vapic;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 06/23] qdev: fix use-after-free in the error path of qdev_init_nofail
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (4 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 05/23] kvmvapic: Disable if there is insufficient memory Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 07/23] virtio-blk: fix use-after-free while handling scsi commands Michael Roth
` (16 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Anthony Liguori <aliguori@us.ibm.com>
>From Markus:
Before:
$ qemu-system-x86_64 -display none -drive if=ide
qemu-system-x86_64: Device needs media, but drive is empty
qemu-system-x86_64: Initialization of device ide-hd failed
[Exit 1 ]
After:
$ qemu-system-x86_64 -display none -drive if=ide
qemu-system-x86_64: Device needs media, but drive is empty
Segmentation fault (core dumped)
[Exit 139 (SIGSEGV)]
This error always existed as qdev_init() frees the object. But QOM
goes a bit further and purposefully sets the class pointer to NULL to
help find use-after-free. It worked :-)
Cc: Andreas Faerber <afaerber@suse.de>
Reported-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7de3abe505e34398cef5bddf6c4d0bd9ee47007f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/qdev.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/hw/qdev.c b/hw/qdev.c
index af419b9..8e8ca3f 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -256,9 +256,10 @@ int qdev_simple_unplug_cb(DeviceState *dev)
way is somewhat unclean, and best avoided. */
void qdev_init_nofail(DeviceState *dev)
{
+ const char *typename = object_get_typename(OBJECT(dev));
+
if (qdev_init(dev) < 0) {
- error_report("Initialization of device %s failed",
- object_get_typename(OBJECT(dev)));
+ error_report("Initialization of device %s failed", typename);
exit(1);
}
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 07/23] virtio-blk: fix use-after-free while handling scsi commands
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (5 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 06/23] qdev: fix use-after-free in the error path of qdev_init_nofail Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 08/23] ehci: fix reset Michael Roth
` (15 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Avi Kivity <avi@redhat.com>
The scsi passthrough handler falls through after completing a
request into the failure path, resulting in a use after free.
Reproducible by running a guest with aio=native on a block device.
Reported-by: Stefan Priebe <s.priebe@profihost.ag>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 730a9c53b4e52681fcfe31cf38854cbf91e132c7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/virtio-blk.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index fe07746..f44d244 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -253,6 +253,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
virtio_blk_req_complete(req, status);
g_free(req);
+ return;
#else
abort();
#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 08/23] ehci: fix reset
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (6 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 07/23] virtio-blk: fix use-after-free while handling scsi commands Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 09/23] ehci: don't flush cache on doorbell rings Michael Roth
` (14 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Gerd Hoffmann <kraxel@redhat.com>
Check for the reset bit first when processing USBCMD register writes.
Also break out of the switch, there is no need to check the other bits.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 7046530c36fa3a3f87692bdb54556f5d891a9c03)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/usb/hcd-ehci.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index e759c99..5855c5d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1064,6 +1064,12 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
/* Do any register specific pre-write processing here. */
switch(addr) {
case USBCMD:
+ if (val & USBCMD_HCRESET) {
+ ehci_reset(s);
+ val = s->usbcmd;
+ break;
+ }
+
if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
SET_LAST_RUN_CLOCK(s);
@@ -1077,10 +1083,6 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
ehci_set_usbsts(s, USBSTS_HALT);
}
- if (val & USBCMD_HCRESET) {
- ehci_reset(s);
- val = s->usbcmd;
- }
/* not supporting dynamic frame list size at the moment */
if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 09/23] ehci: don't flush cache on doorbell rings.
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (7 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 08/23] ehci: fix reset Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 10/23] uhci: fix uhci_async_cancel_all Michael Roth
` (13 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Gerd Hoffmann <kraxel@redhat.com>
Commit 4be23939ab0d7019c7e59a37485b416fbbf0f073 makes ehci instantly
zap any unlinked queue heads when the guest rings the doorbell.
While hacking up uas support this turned out to be a problem. The linux
kernel can unlink and instantly relink the very same queue head, thereby
killing any async packets in flight. That alone isn't an issue yet, the
packet will canceled and resubmitted and everything is fine. We'll run
into trouble though in case the async packet is completed already, so we
can't cancel it any more. The transaction is simply lost then.
usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f0c2 qtds 29dbce40,29dbc4e0,00000009
usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: alloc
usb_packet_state_change bus 0, port 2, ep 1, packet 0x7f95fdec32e0, state undef -> setup
usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: process
usb_uas_command dev 2, tag 0x2, lun 0, lun64 00000000-00000000
scsi_req_parsed target 0 lun 0 tag 2 command 42 dir 2 length 16384
scsi_req_parsed_lba target 0 lun 0 tag 2 command 42 lba 5933312
scsi_req_alloc target 0 lun 0 tag 2
scsi_req_continue target 0 lun 0 tag 2
scsi_req_data target 0 lun 0 tag 2 len 16384
usb_uas_scsi_data dev 2, tag 0x2, bytes 16384
usb_uas_write_ready dev 2, tag 0x2
usb_packet_state_change bus 0, port 2, ep 1, packet 0x7f95fdec32e0, state setup -> complete
usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: free
usb_ehci_qh_ptrs q 0x7f95fdec3210 - QH @ 39c4f0c0: next 39c4f002 qtds 29dbce40,00000001,00000009
usb_ehci_qh_fields QH @ 39c4f0c0 - rl 4, mplen 512, eps 2, ep 2, dev 2
usb_ehci_queue_action q 0x7f95fe5152a0: free
usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state async -> complete
^^^ async packets completes.
usb_ehci_packet_action q 0x7f95fdec3210 p 0x7f95feba9130: wakeup
usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f002 qtds 29dbc4e0,29dbc8a0,00000009
usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
usb_ehci_queue_action q 0x7f95fdec3210: free
usb_ehci_packet_action q 0x7f95fdec3210 p 0x7f95feba9130: free
^^^ endpoint #2 queue head removed from schedule, doorbell makes ehci zap the queue,
the (completed) usb packet is freed too and gets lost.
usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f0c2 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f0c2 qtds 00000000,00000001,39c50000
usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
usb_ehci_queue_action q 0x7f9600dff570: alloc
usb_ehci_qh_ptrs q 0x7f9600dff570 - QH @ 39c4f0c0: next 39c4f122 qtds 29dbce40,00000001,00000009
usb_ehci_qh_fields QH @ 39c4f0c0 - rl 4, mplen 512, eps 2, ep 2, dev 2
usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: alloc
usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state undef -> setup
usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: process
usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state setup -> async
usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: async
^^^ linux kernel relinked the queue head, ehci creates a new usb packet,
but we should have delivered the completed one instead.
usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f002 qtds 29dbc4e0,29dbc8a0,00000009
usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
So instead of instantly zapping the queue we'll set a flag that the
queue needs revalidation in case we'll see it again in the schedule.
ehci then checks that the queue head fields addressing / describing the
endpoint and the qtd pointer match the cached content before reusing it.
Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0)
Conflicts:
hw/usb/hcd-ehci.c
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/usb/hcd-ehci.c | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 5855c5d..ce8b405 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -348,6 +348,7 @@ struct EHCIQueue {
QTAILQ_ENTRY(EHCIQueue) next;
uint32_t seen;
uint64_t ts;
+ int revalidate;
/* cached data from guest - needs to be flushed
* when guest removes an entry (doorbell, handshake sequence)
@@ -695,7 +696,18 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
return NULL;
}
-static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
+static void ehci_queues_tag_unused_async(EHCIState *ehci)
+{
+ EHCIQueue *q;
+
+ QTAILQ_FOREACH(q, &ehci->aqueues, next) {
+ if (!q->seen) {
+ q->revalidate = 1;
+ }
+ }
+}
+
+static void ehci_queues_rip_unused(EHCIState *ehci, int async)
{
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
EHCIQueue *q, *tmp;
@@ -706,7 +718,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
q->ts = ehci->last_run_ns;
continue;
}
- if (!flush && ehci->last_run_ns < q->ts + 250000000) {
+ if (ehci->last_run_ns < q->ts + 250000000) {
/* allow 0.25 sec idle */
continue;
}
@@ -1521,7 +1533,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
ehci_set_usbsts(ehci, USBSTS_REC);
}
- ehci_queues_rip_unused(ehci, async, 0);
+ ehci_queues_rip_unused(ehci, async);
/* Find the head of the list (4.9.1.1) */
for(i = 0; i < MAX_QH; i++) {
@@ -1605,6 +1617,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
{
uint32_t entry;
EHCIQueue *q;
+ EHCIqh qh;
entry = ehci_get_fetch_addr(ehci, async);
q = ehci_find_queue_by_qh(ehci, entry, async);
@@ -1622,7 +1635,16 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
}
get_dwords(ehci, NLPTR_GET(q->qhaddr),
- (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
+ (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
+ if (q->revalidate && (q->qh.epchar != qh.epchar ||
+ q->qh.epcap != qh.epcap ||
+ q->qh.current_qtd != qh.current_qtd)) {
+ ehci_free_queue(q, async);
+ q = ehci_alloc_queue(ehci, async);
+ q->seen++;
+ }
+ q->qh = qh;
+ q->revalidate = 0;
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
if (q->async == EHCI_ASYNC_INFLIGHT) {
@@ -2047,7 +2069,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
*/
if (ehci->usbcmd & USBCMD_IAAD) {
/* Remove all unseen qhs from the async qhs queue */
- ehci_queues_rip_unused(ehci, async, 1);
+ ehci_queues_tag_unused_async(ehci);
DPRINTF("ASYNC: doorbell request acknowledged\n");
ehci->usbcmd &= ~USBCMD_IAAD;
ehci_set_interrupt(ehci, USBSTS_IAA);
@@ -2102,7 +2124,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
ehci_set_fetch_addr(ehci, async,entry);
ehci_set_state(ehci, async, EST_FETCHENTRY);
ehci_advance_state(ehci, async);
- ehci_queues_rip_unused(ehci, async, 0);
+ ehci_queues_rip_unused(ehci, async);
break;
default:
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 10/23] uhci: fix uhci_async_cancel_all
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (8 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 09/23] ehci: don't flush cache on doorbell rings Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 11/23] usb: restore USBDevice->attached on vmload Michael Roth
` (12 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Gerd Hoffmann <kraxel@redhat.com>
We update the QTAILQ in the loop, thus we must use the SAFE version
to make sure we don't touch the queue struct after freeing it.
https://bugzilla.novell.com/show_bug.cgi?id=766310
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 77fa9aee38758a078870e25f0dcf642066b4d5cc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/usb/hcd-uhci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 9e211a0..3803f52 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -288,10 +288,10 @@ static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
static void uhci_async_cancel_all(UHCIState *s)
{
- UHCIQueue *queue;
+ UHCIQueue *queue, *nq;
UHCIAsync *curr, *n;
- QTAILQ_FOREACH(queue, &s->queues, next) {
+ QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) {
QTAILQ_FOREACH_SAFE(curr, &queue->asyncs, next, n) {
uhci_async_unlink(curr);
uhci_async_cancel(curr);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 11/23] usb: restore USBDevice->attached on vmload
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (9 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 10/23] uhci: fix uhci_async_cancel_all Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 12/23] usb-redir: Correctly handle the usb_redir_babble usbredir status Michael Roth
` (11 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 495d544798151206bafca65ec588c0388637eb40)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/usb/bus.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 2068640..77b2b99 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -27,10 +27,23 @@ static struct BusInfo usb_bus_info = {
static int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
+static int usb_device_post_load(void *opaque, int version_id)
+{
+ USBDevice *dev = opaque;
+
+ if (dev->state == USB_STATE_NOTATTACHED) {
+ dev->attached = 0;
+ } else {
+ dev->attached = 1;
+ }
+ return 0;
+}
+
const VMStateDescription vmstate_usb_device = {
.name = "USBDevice",
.version_id = 1,
.minimum_version_id = 1,
+ .post_load = usb_device_post_load,
.fields = (VMStateField []) {
VMSTATE_UINT8(addr, USBDevice),
VMSTATE_INT32(state, USBDevice),
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 12/23] usb-redir: Correctly handle the usb_redir_babble usbredir status
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (10 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 11/23] usb: restore USBDevice->attached on vmload Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 13/23] usb-ehci: Fix an assert whenever isoc transfers are used Michael Roth
` (10 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit adae502c0ae4572ef08f71cb5b5ed5a8e90299fe)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/usb/redirect.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 51c27b4..1fd903a 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1031,6 +1031,8 @@ static int usbredir_handle_status(USBRedirDevice *dev,
case usb_redir_inval:
WARNING("got invalid param error from usb-host?\n");
return USB_RET_NAK;
+ case usb_redir_babble:
+ return USB_RET_BABBLE;
case usb_redir_ioerror:
case usb_redir_timeout:
default:
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 13/23] usb-ehci: Fix an assert whenever isoc transfers are used
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (11 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 12/23] usb-redir: Correctly handle the usb_redir_babble usbredir status Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 14/23] qlist: add qlist_size() Michael Roth
` (9 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Hans de Goede <hdegoede@redhat.com>
hcd-ehci.c is missing an usb_packet_init() call for the ipacket UsbPacket
it uses for isoc transfers, triggering an assert (taking the entire vm down)
in usb_packet_setup as soon as any isoc transfers are done by a high speed
USB device.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 7341ea075c09258b98a1d0efc60efd402cbfc9b4)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/usb/hcd-ehci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index ce8b405..41c9d84 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2324,6 +2324,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
QTAILQ_INIT(&s->aqueues);
QTAILQ_INIT(&s->pqueues);
+ usb_packet_init(&s->ipacket);
qemu_register_reset(ehci_reset, s);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 14/23] qlist: add qlist_size()
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (12 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 13/23] usb-ehci: Fix an assert whenever isoc transfers are used Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 15/23] json-parser: don't replicate tokens at each level of recursion Michael Roth
` (8 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit a86a4c2f7b7f0b72816ea1c219d8140699b6665b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
qlist.c | 13 +++++++++++++
qlist.h | 1 +
2 files changed, 14 insertions(+)
diff --git a/qlist.c b/qlist.c
index 88498b1..b48ec5b 100644
--- a/qlist.c
+++ b/qlist.c
@@ -124,6 +124,19 @@ int qlist_empty(const QList *qlist)
return QTAILQ_EMPTY(&qlist->head);
}
+static void qlist_size_iter(QObject *obj, void *opaque)
+{
+ size_t *count = opaque;
+ (*count)++;
+}
+
+size_t qlist_size(const QList *qlist)
+{
+ size_t count = 0;
+ qlist_iter(qlist, qlist_size_iter, &count);
+ return count;
+}
+
/**
* qobject_to_qlist(): Convert a QObject into a QList
*/
diff --git a/qlist.h b/qlist.h
index d426bd4..ae776f9 100644
--- a/qlist.h
+++ b/qlist.h
@@ -49,6 +49,7 @@ void qlist_iter(const QList *qlist,
QObject *qlist_pop(QList *qlist);
QObject *qlist_peek(QList *qlist);
int qlist_empty(const QList *qlist);
+size_t qlist_size(const QList *qlist);
QList *qobject_to_qlist(const QObject *obj);
static inline const QListEntry *qlist_first(const QList *qlist)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 15/23] json-parser: don't replicate tokens at each level of recursion
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (13 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 14/23] qlist: add qlist_size() Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 16/23] check-qjson: add test for large JSON objects Michael Roth
` (7 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
Currently, when parsing a stream of tokens we make a copy of the token
list at the beginning of each level of recursion so that we do not
modify the original list in cases where we need to fall back to an
earlier state.
In the worst case, we will only read 1 or 2 tokens off the list before
recursing again, which means an upper bound of roughly N^2 token allocations.
For a "reasonably" sized QMP request (in this a QMP representation of
cirrus_vga's device state, generated via QIDL, being passed in via
qom-set), this caused my 16GB's of memory to be exhausted before any
noticeable progress was made by the parser.
This patch works around the issue by using single copy of the token list
in the form of an indexable array so that we can save/restore state by
manipulating indices.
A subsequent commit adds a "large_dict" test case which exhibits the
same behavior as above. With this patch applied the test case successfully
completes in under a second.
Tested with valgrind, make check, and QMP.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 65c0f1e9558c7c762cdb333406243fff1d687117)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
json-parser.c | 230 +++++++++++++++++++++++++++++++++++----------------------
1 file changed, 142 insertions(+), 88 deletions(-)
diff --git a/json-parser.c b/json-parser.c
index 849e215..457291b 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -27,6 +27,11 @@
typedef struct JSONParserContext
{
Error *err;
+ struct {
+ QObject **buf;
+ size_t pos;
+ size_t count;
+ } tokens;
} JSONParserContext;
#define BUG_ON(cond) assert(!(cond))
@@ -40,7 +45,7 @@ typedef struct JSONParserContext
* 4) deal with premature EOI
*/
-static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap);
+static QObject *parse_value(JSONParserContext *ctxt, va_list *ap);
/**
* Token manipulators
@@ -270,27 +275,111 @@ out:
return NULL;
}
+static QObject *parser_context_pop_token(JSONParserContext *ctxt)
+{
+ QObject *token;
+ g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+ token = ctxt->tokens.buf[ctxt->tokens.pos];
+ ctxt->tokens.pos++;
+ return token;
+}
+
+/* Note: parser_context_{peek|pop}_token do not increment the
+ * token object's refcount. In both cases the references will continue
+ * to be tracked and cleaned up in parser_context_free(), so do not
+ * attempt to free the token object.
+ */
+static QObject *parser_context_peek_token(JSONParserContext *ctxt)
+{
+ QObject *token;
+ g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+ token = ctxt->tokens.buf[ctxt->tokens.pos];
+ return token;
+}
+
+static JSONParserContext parser_context_save(JSONParserContext *ctxt)
+{
+ JSONParserContext saved_ctxt = {0};
+ saved_ctxt.tokens.pos = ctxt->tokens.pos;
+ saved_ctxt.tokens.count = ctxt->tokens.count;
+ saved_ctxt.tokens.buf = ctxt->tokens.buf;
+ return saved_ctxt;
+}
+
+static void parser_context_restore(JSONParserContext *ctxt,
+ JSONParserContext saved_ctxt)
+{
+ ctxt->tokens.pos = saved_ctxt.tokens.pos;
+ ctxt->tokens.count = saved_ctxt.tokens.count;
+ ctxt->tokens.buf = saved_ctxt.tokens.buf;
+}
+
+static void tokens_append_from_iter(QObject *obj, void *opaque)
+{
+ JSONParserContext *ctxt = opaque;
+ g_assert(ctxt->tokens.pos < ctxt->tokens.count);
+ ctxt->tokens.buf[ctxt->tokens.pos++] = obj;
+ qobject_incref(obj);
+}
+
+static JSONParserContext *parser_context_new(QList *tokens)
+{
+ JSONParserContext *ctxt;
+ size_t count;
+
+ if (!tokens) {
+ return NULL;
+ }
+
+ count = qlist_size(tokens);
+ if (count == 0) {
+ return NULL;
+ }
+
+ ctxt = g_malloc0(sizeof(JSONParserContext));
+ ctxt->tokens.pos = 0;
+ ctxt->tokens.count = count;
+ ctxt->tokens.buf = g_malloc(count * sizeof(QObject *));
+ qlist_iter(tokens, tokens_append_from_iter, ctxt);
+ ctxt->tokens.pos = 0;
+
+ return ctxt;
+}
+
+/* to support error propagation, ctxt->err must be freed separately */
+static void parser_context_free(JSONParserContext *ctxt)
+{
+ int i;
+ if (ctxt) {
+ for (i = 0; i < ctxt->tokens.count; i++) {
+ qobject_decref(ctxt->tokens.buf[i]);
+ }
+ g_free(ctxt->tokens.buf);
+ g_free(ctxt);
+ }
+}
+
/**
* Parsing rules
*/
-static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_list *ap)
+static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap)
{
QObject *key = NULL, *token = NULL, *value, *peek;
- QList *working = qlist_copy(*tokens);
+ JSONParserContext saved_ctxt = parser_context_save(ctxt);
- peek = qlist_peek(working);
+ peek = parser_context_peek_token(ctxt);
if (peek == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
- key = parse_value(ctxt, &working, ap);
+ key = parse_value(ctxt, ap);
if (!key || qobject_type(key) != QTYPE_QSTRING) {
parse_error(ctxt, peek, "key is not a string in object");
goto out;
}
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -301,7 +390,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l
goto out;
}
- value = parse_value(ctxt, &working, ap);
+ value = parse_value(ctxt, ap);
if (value == NULL) {
parse_error(ctxt, token, "Missing value in dict");
goto out;
@@ -309,28 +398,24 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l
qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value);
- qobject_decref(token);
qobject_decref(key);
- QDECREF(*tokens);
- *tokens = working;
return 0;
out:
- qobject_decref(token);
+ parser_context_restore(ctxt, saved_ctxt);
qobject_decref(key);
- QDECREF(working);
return -1;
}
-static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_object(JSONParserContext *ctxt, va_list *ap)
{
QDict *dict = NULL;
QObject *token, *peek;
- QList *working = qlist_copy(*tokens);
+ JSONParserContext saved_ctxt = parser_context_save(ctxt);
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -338,23 +423,22 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a
if (!token_is_operator(token, '{')) {
goto out;
}
- qobject_decref(token);
token = NULL;
dict = qdict_new();
- peek = qlist_peek(working);
+ peek = parser_context_peek_token(ctxt);
if (peek == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
if (!token_is_operator(peek, '}')) {
- if (parse_pair(ctxt, dict, &working, ap) == -1) {
+ if (parse_pair(ctxt, dict, ap) == -1) {
goto out;
}
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -365,59 +449,52 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a
parse_error(ctxt, token, "expected separator in dict");
goto out;
}
- qobject_decref(token);
token = NULL;
- if (parse_pair(ctxt, dict, &working, ap) == -1) {
+ if (parse_pair(ctxt, dict, ap) == -1) {
goto out;
}
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
}
- qobject_decref(token);
token = NULL;
} else {
- token = qlist_pop(working);
- qobject_decref(token);
+ token = parser_context_pop_token(ctxt);
token = NULL;
}
- QDECREF(*tokens);
- *tokens = working;
-
return QOBJECT(dict);
out:
- qobject_decref(token);
- QDECREF(working);
+ parser_context_restore(ctxt, saved_ctxt);
QDECREF(dict);
return NULL;
}
-static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_array(JSONParserContext *ctxt, va_list *ap)
{
QList *list = NULL;
QObject *token, *peek;
- QList *working = qlist_copy(*tokens);
+ JSONParserContext saved_ctxt = parser_context_save(ctxt);
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
if (!token_is_operator(token, '[')) {
+ token = NULL;
goto out;
}
- qobject_decref(token);
token = NULL;
list = qlist_new();
- peek = qlist_peek(working);
+ peek = parser_context_peek_token(ctxt);
if (peek == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -426,7 +503,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
if (!token_is_operator(peek, ']')) {
QObject *obj;
- obj = parse_value(ctxt, &working, ap);
+ obj = parse_value(ctxt, ap);
if (obj == NULL) {
parse_error(ctxt, token, "expecting value");
goto out;
@@ -434,7 +511,7 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
qlist_append_obj(list, obj);
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
@@ -446,10 +523,9 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
goto out;
}
- qobject_decref(token);
token = NULL;
- obj = parse_value(ctxt, &working, ap);
+ obj = parse_value(ctxt, ap);
if (obj == NULL) {
parse_error(ctxt, token, "expecting value");
goto out;
@@ -457,39 +533,33 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap
qlist_append_obj(list, obj);
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
parse_error(ctxt, NULL, "premature EOI");
goto out;
}
}
- qobject_decref(token);
token = NULL;
} else {
- token = qlist_pop(working);
- qobject_decref(token);
+ token = parser_context_pop_token(ctxt);
token = NULL;
}
- QDECREF(*tokens);
- *tokens = working;
-
return QOBJECT(list);
out:
- qobject_decref(token);
- QDECREF(working);
+ parser_context_restore(ctxt, saved_ctxt);
QDECREF(list);
return NULL;
}
-static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens)
+static QObject *parse_keyword(JSONParserContext *ctxt)
{
QObject *token, *ret;
- QList *working = qlist_copy(*tokens);
+ JSONParserContext saved_ctxt = parser_context_save(ctxt);
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -507,29 +577,24 @@ static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens)
goto out;
}
- qobject_decref(token);
- QDECREF(*tokens);
- *tokens = working;
-
return ret;
out:
- qobject_decref(token);
- QDECREF(working);
+ parser_context_restore(ctxt, saved_ctxt);
return NULL;
}
-static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
{
QObject *token = NULL, *obj;
- QList *working = qlist_copy(*tokens);
+ JSONParserContext saved_ctxt = parser_context_save(ctxt);
if (ap == NULL) {
goto out;
}
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -553,25 +618,20 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a
goto out;
}
- qobject_decref(token);
- QDECREF(*tokens);
- *tokens = working;
-
return obj;
out:
- qobject_decref(token);
- QDECREF(working);
+ parser_context_restore(ctxt, saved_ctxt);
return NULL;
}
-static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens)
+static QObject *parse_literal(JSONParserContext *ctxt)
{
QObject *token, *obj;
- QList *working = qlist_copy(*tokens);
+ JSONParserContext saved_ctxt = parser_context_save(ctxt);
- token = qlist_pop(working);
+ token = parser_context_pop_token(ctxt);
if (token == NULL) {
goto out;
}
@@ -591,35 +651,30 @@ static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens)
goto out;
}
- qobject_decref(token);
- QDECREF(*tokens);
- *tokens = working;
-
return obj;
out:
- qobject_decref(token);
- QDECREF(working);
+ parser_context_restore(ctxt, saved_ctxt);
return NULL;
}
-static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap)
+static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
{
QObject *obj;
- obj = parse_object(ctxt, tokens, ap);
+ obj = parse_object(ctxt, ap);
if (obj == NULL) {
- obj = parse_array(ctxt, tokens, ap);
+ obj = parse_array(ctxt, ap);
}
if (obj == NULL) {
- obj = parse_escape(ctxt, tokens, ap);
+ obj = parse_escape(ctxt, ap);
}
if (obj == NULL) {
- obj = parse_keyword(ctxt, tokens);
+ obj = parse_keyword(ctxt);
}
if (obj == NULL) {
- obj = parse_literal(ctxt, tokens);
+ obj = parse_literal(ctxt);
}
return obj;
@@ -632,19 +687,18 @@ QObject *json_parser_parse(QList *tokens, va_list *ap)
QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp)
{
- JSONParserContext ctxt = {};
- QList *working;
+ JSONParserContext *ctxt = parser_context_new(tokens);
QObject *result;
- if (!tokens) {
+ if (!ctxt) {
return NULL;
}
- working = qlist_copy(tokens);
- result = parse_value(&ctxt, &working, ap);
- QDECREF(working);
+ result = parse_value(ctxt, ap);
+
+ error_propagate(errp, ctxt->err);
- error_propagate(errp, ctxt.err);
+ parser_context_free(ctxt);
return result;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 16/23] check-qjson: add test for large JSON objects
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (14 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 15/23] json-parser: don't replicate tokens at each level of recursion Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 17/23] slirp: Enforce host-side user of smb share Michael Roth
` (6 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 7109edfeb69c1d3c2164175837784dfcd210fed0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
tests/check-qjson.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 526e25e..3b896f5 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -466,6 +466,58 @@ static void simple_dict(void)
}
}
+/*
+ * this generates json of the form:
+ * a(0,m) = [0, 1, ..., m-1]
+ * a(n,m) = {
+ * 'key0': a(0,m),
+ * 'key1': a(1,m),
+ * ...
+ * 'key(n-1)': a(n-1,m)
+ * }
+ */
+static void gen_test_json(GString *gstr, int nest_level_max,
+ int elem_count)
+{
+ int i;
+
+ g_assert(gstr);
+ if (nest_level_max == 0) {
+ g_string_append(gstr, "[");
+ for (i = 0; i < elem_count; i++) {
+ g_string_append_printf(gstr, "%d", i);
+ if (i < elem_count - 1) {
+ g_string_append_printf(gstr, ", ");
+ }
+ }
+ g_string_append(gstr, "]");
+ return;
+ }
+
+ g_string_append(gstr, "{");
+ for (i = 0; i < nest_level_max; i++) {
+ g_string_append_printf(gstr, "'key%d': ", i);
+ gen_test_json(gstr, i, elem_count);
+ if (i < nest_level_max - 1) {
+ g_string_append(gstr, ",");
+ }
+ }
+ g_string_append(gstr, "}");
+}
+
+static void large_dict(void)
+{
+ GString *gstr = g_string_new("");
+ QObject *obj;
+
+ gen_test_json(gstr, 10, 100);
+ obj = qobject_from_json(gstr->str);
+ g_assert(obj != NULL);
+
+ qobject_decref(obj);
+ g_string_free(gstr, true);
+}
+
static void simple_list(void)
{
int i;
@@ -706,6 +758,7 @@ int main(int argc, char **argv)
g_test_add_func("/literals/keyword", keyword_literal);
g_test_add_func("/dicts/simple_dict", simple_dict);
+ g_test_add_func("/dicts/large_dict", large_dict);
g_test_add_func("/lists/simple_list", simple_list);
g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 17/23] slirp: Enforce host-side user of smb share
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (15 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 16/23] check-qjson: add test for large JSON objects Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 18/23] slirp: Ensure smbd and shared directory exist when enable smb Michael Roth
` (5 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Jan Kiszka <jan.kiszka@siemens.com>
Windows 7 (and possibly other versions) cannot connect to the samba
share if the exported host directory is not world-readable. This can be
resolved by forcing the username used for access checks to the one
under which QEMU and smbd are running.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 1cb1c5d10bb9e180bd3f7be2c10b212ed86a97b4)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
net/slirp.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/net/slirp.c b/net/slirp.c
index 96f5032..c73610e 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -26,6 +26,7 @@
#include "config-host.h"
#ifndef _WIN32
+#include <pwd.h>
#include <sys/wait.h>
#endif
#include "net.h"
@@ -487,8 +488,15 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
static int instance;
char smb_conf[128];
char smb_cmdline[128];
+ struct passwd *passwd;
FILE *f;
+ passwd = getpwuid(geteuid());
+ if (!passwd) {
+ error_report("failed to retrieve user name");
+ return -1;
+ }
+
snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
(long)getpid(), instance++);
if (mkdir(s->smb_dir, 0700) < 0) {
@@ -517,14 +525,16 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
"[qemu]\n"
"path=%s\n"
"read only=no\n"
- "guest ok=yes\n",
+ "guest ok=yes\n"
+ "force user=%s\n",
s->smb_dir,
s->smb_dir,
s->smb_dir,
s->smb_dir,
s->smb_dir,
s->smb_dir,
- exported_dir
+ exported_dir,
+ passwd->pw_name
);
fclose(f);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 18/23] slirp: Ensure smbd and shared directory exist when enable smb
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (16 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 17/23] slirp: Enforce host-side user of smb share Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 19/23] slirp: Improve error reporting of inaccessible smb directories Michael Roth
` (4 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Dunrong Huang <riegamaths@gmail.com>
Users may pass the following parameters to qemu:
$ qemu-kvm -net nic -net user,smb= ...
$ qemu-kvm -net nic -net user,smb ...
$ qemu-kvm -net nic -net user,smb=bad_directory ...
In these cases, qemu started successfully while samba server
failed to start. Users will confuse since samba server
failed silently without any indication of what it did wrong.
To avoid it, we check whether the shared directory exist and
if users have permission to access this directory when QEMU's
"built-in" SMB server is enabled.
Signed-off-by: Dunrong Huang <riegamaths@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 927d811b282ffdf5386bd63f435c1507634ba49a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
net/slirp.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/net/slirp.c b/net/slirp.c
index c73610e..d3fcbf4 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -497,6 +497,18 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
return -1;
}
+ if (access(CONFIG_SMBD_COMMAND, F_OK)) {
+ error_report("could not find '%s', please install it",
+ CONFIG_SMBD_COMMAND);
+ return -1;
+ }
+
+ if (access(exported_dir, R_OK | X_OK)) {
+ error_report("no such directory '%s', or you do not have permission "
+ "to access it, please check it", exported_dir);
+ return -1;
+ }
+
snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
(long)getpid(), instance++);
if (mkdir(s->smb_dir, 0700) < 0) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 19/23] slirp: Improve error reporting of inaccessible smb directories
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (17 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 18/23] slirp: Ensure smbd and shared directory exist when enable smb Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 20/23] apic: Resolve potential endless loop around apic_update_irq Michael Roth
` (3 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Jan Kiszka <jan.kiszka@siemens.com>
Instead of guessing, print the error code returned by access.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
(cherry picked from commit 22a61f365df83d5d7884cceb1c462295977cb2db)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
net/slirp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/slirp.c b/net/slirp.c
index d3fcbf4..49f55bc 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -504,8 +504,8 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
}
if (access(exported_dir, R_OK | X_OK)) {
- error_report("no such directory '%s', or you do not have permission "
- "to access it, please check it", exported_dir);
+ error_report("error accessing shared directory '%s': %s",
+ exported_dir, strerror(errno));
return -1;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 20/23] apic: Resolve potential endless loop around apic_update_irq
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (18 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 19/23] slirp: Improve error reporting of inaccessible smb directories Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 21/23] apic: Reevaluate pending interrupts on LVT_LINT0 changes Michael Roth
` (2 subsequent siblings)
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Jan Kiszka <jan.kiszka@siemens.com>
Commit d96e173769 refactored the reinjection of pending PIC interrupts.
However, it missed the potential loop of apic_update_irq ->
apic_deliver_pic_intr -> apic_local_deliver -> apic_set_irq ->
apic_update_irq that /could/ occur if LINT0 is injected as APIC_DM_FIXED
and that vector is currently blocked via TPR.
Resolve this by reinjecting only where it matters: inside
apic_get_interrupt. This function may clear a vector while a
PIC-originated reason still exists.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit 3db3659bf60094657e1465cc809acb09551816ee)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/apic.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/hw/apic.c b/hw/apic.c
index 4eeaf88..ec8f9ba 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -371,9 +371,6 @@ static void apic_update_irq(APICCommonState *s)
}
if (apic_irq_pending(s) > 0) {
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
- } else if (apic_accept_pic_intr(&s->busdev.qdev) &&
- pic_get_output(isa_pic)) {
- apic_deliver_pic_intr(&s->busdev.qdev, 1);
}
}
@@ -568,7 +565,14 @@ int apic_get_interrupt(DeviceState *d)
reset_bit(s->irr, intno);
set_bit(s->isr, intno);
apic_sync_vapic(s, SYNC_TO_VAPIC);
+
+ /* re-inject if there is still a pending PIC interrupt */
+ if (apic_accept_pic_intr(&s->busdev.qdev) && pic_get_output(isa_pic)) {
+ apic_deliver_pic_intr(&s->busdev.qdev, 1);
+ }
+
apic_update_irq(s);
+
return intno;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 21/23] apic: Reevaluate pending interrupts on LVT_LINT0 changes
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (19 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 20/23] apic: Resolve potential endless loop around apic_update_irq Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 22/23] apic: Defer interrupt updates to VCPU thread Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 23/23] update VERSION for 1.1.2 Michael Roth
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Jan Kiszka <jan.kiszka@siemens.com>
When the guest modifies the LVT_LINT0 register, we need to check if some
pending PIC interrupt can now be delivered.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit a94820ddc36f8c452b37f9dcb323f55ffdbc75f9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
hw/apic.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/hw/apic.c b/hw/apic.c
index ec8f9ba..e96402d 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -540,6 +540,15 @@ static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode,
apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode);
}
+static bool apic_check_pic(APICCommonState *s)
+{
+ if (!apic_accept_pic_intr(&s->busdev.qdev) || !pic_get_output(isa_pic)) {
+ return false;
+ }
+ apic_deliver_pic_intr(&s->busdev.qdev, 1);
+ return true;
+}
+
int apic_get_interrupt(DeviceState *d)
{
APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
@@ -567,9 +576,7 @@ int apic_get_interrupt(DeviceState *d)
apic_sync_vapic(s, SYNC_TO_VAPIC);
/* re-inject if there is still a pending PIC interrupt */
- if (apic_accept_pic_intr(&s->busdev.qdev) && pic_get_output(isa_pic)) {
- apic_deliver_pic_intr(&s->busdev.qdev, 1);
- }
+ apic_check_pic(s);
apic_update_irq(s);
@@ -812,8 +819,11 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
int n = index - 0x32;
s->lvt[n] = val;
- if (n == APIC_LVT_TIMER)
+ if (n == APIC_LVT_TIMER) {
apic_timer_update(s, qemu_get_clock_ns(vm_clock));
+ } else if (n == APIC_LVT_LINT0 && apic_check_pic(s)) {
+ apic_update_irq(s);
+ }
}
break;
case 0x38:
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 22/23] apic: Defer interrupt updates to VCPU thread
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (20 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 21/23] apic: Reevaluate pending interrupts on LVT_LINT0 changes Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 23/23] update VERSION for 1.1.2 Michael Roth
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
From: Jan Kiszka <jan.kiszka@siemens.com>
KVM performs TPR raising asynchronously to QEMU, specifically outside
QEMU's global lock. When an interrupt is injected into the APIC and TPR
is checked to decide if this can be delivered, a stale TPR value may be
used, causing spurious interrupts in the end.
Fix this by deferring apic_update_irq to the context of the target VCPU.
We introduce a new interrupt flag for this, CPU_INTERRUPT_POLL. When it
is set, the VCPU calls apic_poll_irq before checking for further pending
interrupts. To avoid special-casing KVM, we also implement this logic
for TCG mode.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
(cherry picked from commit 5d62c43a17edaa7f6a88821c9086e6c8e0e5327d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
cpu-exec.c | 6 ++++++
hw/apic.c | 5 ++++-
hw/apic.h | 1 +
hw/apic_internal.h | 1 -
target-i386/cpu.h | 4 +++-
target-i386/kvm.c | 4 ++++
6 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index 0344cd5..6db32cd 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -285,6 +285,12 @@ int cpu_exec(CPUArchState *env)
}
#endif
#if defined(TARGET_I386)
+#if !defined(CONFIG_USER_ONLY)
+ if (interrupt_request & CPU_INTERRUPT_POLL) {
+ env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+ apic_poll_irq(env->apic_state);
+ }
+#endif
if (interrupt_request & CPU_INTERRUPT_INIT) {
svm_check_intercept(env, SVM_EXIT_INIT);
do_cpu_init(env);
diff --git a/hw/apic.c b/hw/apic.c
index e96402d..b2c6373 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -16,6 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>
*/
+#include "qemu-thread.h"
#include "apic_internal.h"
#include "apic.h"
#include "ioapic.h"
@@ -369,7 +370,9 @@ static void apic_update_irq(APICCommonState *s)
if (!(s->spurious_vec & APIC_SV_ENABLE)) {
return;
}
- if (apic_irq_pending(s) > 0) {
+ if (!qemu_cpu_is_self(s->cpu_env)) {
+ cpu_interrupt(s->cpu_env, CPU_INTERRUPT_POLL);
+ } else if (apic_irq_pending(s) > 0) {
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
}
}
diff --git a/hw/apic.h b/hw/apic.h
index 62179ce..a89542b 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -20,6 +20,7 @@ void apic_init_reset(DeviceState *s);
void apic_sipi(DeviceState *s);
void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
TPRAccess access);
+void apic_poll_irq(DeviceState *d);
/* pc.c */
int cpu_is_bsp(CPUX86State *env);
diff --git a/hw/apic_internal.h b/hw/apic_internal.h
index 60a6a8b..4d8ff49 100644
--- a/hw/apic_internal.h
+++ b/hw/apic_internal.h
@@ -141,7 +141,6 @@ void apic_report_irq_delivered(int delivered);
bool apic_next_timer(APICCommonState *s, int64_t current_time);
void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr);
-void apic_poll_irq(DeviceState *d);
void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
TPRAccess access);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 2460f63..8ff3f30 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -477,6 +477,7 @@
for syscall instruction */
/* i386-specific interrupt pending bits. */
+#define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
@@ -1029,7 +1030,8 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp)
static inline bool cpu_has_work(CPUX86State *env)
{
- return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ return ((env->interrupt_request & (CPU_INTERRUPT_HARD |
+ CPU_INTERRUPT_POLL)) &&
(env->eflags & IF_MASK)) ||
(env->interrupt_request & (CPU_INTERRUPT_NMI |
CPU_INTERRUPT_INIT |
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index e74a9e4..d8bbe4f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1725,6 +1725,10 @@ int kvm_arch_process_async_events(CPUX86State *env)
return 0;
}
+ if (env->interrupt_request & CPU_INTERRUPT_POLL) {
+ env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+ apic_poll_irq(env->apic_state);
+ }
if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
(env->eflags & IF_MASK)) ||
(env->interrupt_request & CPU_INTERRUPT_NMI)) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH 23/23] update VERSION for 1.1.2
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
` (21 preceding siblings ...)
2012-08-21 17:05 ` [Qemu-devel] [PATCH 22/23] apic: Defer interrupt updates to VCPU thread Michael Roth
@ 2012-08-21 17:05 ` Michael Roth
22 siblings, 0 replies; 24+ messages in thread
From: Michael Roth @ 2012-08-21 17:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
VERSION | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/VERSION b/VERSION
index 524cb55..45a1b3f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.1
+1.1.2
--
1.7.9.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
end of thread, other threads:[~2012-08-21 17:07 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-21 17:05 [Qemu-devel] [stable-1.1] Patch Round-up for stable 1.1.2 Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 01/23] qtest: fix infinite loop when QEMU aborts abruptly Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 02/23] configure: Don't override user's --cpu on MacOS and Solaris Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 03/23] ppc: Fix bug in handling of PAPR hypercall exits Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 04/23] s390: Fix error handling and condition code of service call Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 05/23] kvmvapic: Disable if there is insufficient memory Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 06/23] qdev: fix use-after-free in the error path of qdev_init_nofail Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 07/23] virtio-blk: fix use-after-free while handling scsi commands Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 08/23] ehci: fix reset Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 09/23] ehci: don't flush cache on doorbell rings Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 10/23] uhci: fix uhci_async_cancel_all Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 11/23] usb: restore USBDevice->attached on vmload Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 12/23] usb-redir: Correctly handle the usb_redir_babble usbredir status Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 13/23] usb-ehci: Fix an assert whenever isoc transfers are used Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 14/23] qlist: add qlist_size() Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 15/23] json-parser: don't replicate tokens at each level of recursion Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 16/23] check-qjson: add test for large JSON objects Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 17/23] slirp: Enforce host-side user of smb share Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 18/23] slirp: Ensure smbd and shared directory exist when enable smb Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 19/23] slirp: Improve error reporting of inaccessible smb directories Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 20/23] apic: Resolve potential endless loop around apic_update_irq Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 21/23] apic: Reevaluate pending interrupts on LVT_LINT0 changes Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 22/23] apic: Defer interrupt updates to VCPU thread Michael Roth
2012-08-21 17:05 ` [Qemu-devel] [PATCH 23/23] update VERSION for 1.1.2 Michael Roth
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).