Package init
Signed-off-by: yezengruan <yezengruan@huawei.com>
This commit is contained in:
parent
cff59dc576
commit
787ea25064
@ -1,38 +0,0 @@
|
|||||||
From 841b8d099c462cd4282c4ced8c2a6512899fd8d9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiajun Chen <chenjiajun8@huawei.com>
|
|
||||||
Date: Mon, 20 Jan 2020 15:11:39 +0100
|
|
||||||
Subject: [PATCH] 9pfs: local: Fix possible memory leak in local_link()
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
There is a possible memory leak while local_link return -1 without free
|
|
||||||
odirpath and oname.
|
|
||||||
|
|
||||||
Reported-by: Euler Robot <euler.robot@huawei.com>
|
|
||||||
Signed-off-by: Jaijun Chen <chenjiajun8@huawei.com>
|
|
||||||
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
|
|
||||||
Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Signed-off-by: Greg Kurz <groug@kaod.org>
|
|
||||||
(cherry picked from commit 841b8d099c462cd4282c4ced8c2a6512899fd8d9)
|
|
||||||
---
|
|
||||||
hw/9pfs/9p-local.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
|
|
||||||
index ca64139..d0592c3 100644
|
|
||||||
--- a/hw/9pfs/9p-local.c
|
|
||||||
+++ b/hw/9pfs/9p-local.c
|
|
||||||
@@ -947,7 +947,7 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath,
|
|
||||||
if (ctx->export_flags & V9FS_SM_MAPPED_FILE &&
|
|
||||||
local_is_mapped_file_metadata(ctx, name)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
- return -1;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
odirfd = local_opendir_nofollow(ctx, odirpath);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
From e3a7ec839fa4f823666d726989c375dcf73348a4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ying Fang <fangying1@huawei.com>
|
|
||||||
Date: Wed, 15 Apr 2020 16:14:50 +0800
|
|
||||||
Subject: [PATCH] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus >
|
|
||||||
256
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Host kernel within [4.18, 5.3] report an erroneous KVM_MAX_VCPUS=512
|
|
||||||
for ARM. The actual capability to instantiate more than 256 vcpus
|
|
||||||
was fixed in 5.4 with the upgrade of the KVM_IRQ_LINE ABI to support
|
|
||||||
vcpu id encoded on 12 bits instead of 8 and a redistributor consuming
|
|
||||||
a single KVM IO device instead of 2.
|
|
||||||
|
|
||||||
So let's check this capability when attempting to use more than 256
|
|
||||||
vcpus within any ARM kvm accelerated machine.
|
|
||||||
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
|
||||||
Reviewed-by: Andrew Jones <drjones@redhat.com>
|
|
||||||
Acked-by: Marc Zyngier <maz@kernel.org>
|
|
||||||
Message-id: 20191003154640.22451-4-eric.auger@redhat.com
|
|
||||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
|
||||||
(cherry-picked from commit fff9f5558d0e0813d4f80bfe1602acf225eca4fd)
|
|
||||||
[yu: Use the legacy smp_cpus instead of ms->smp.cpus, as we don't have
|
|
||||||
¦struct CpuTopology in MachineState at that time. See commit
|
|
||||||
¦edeeec911702 for details.]
|
|
||||||
Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
|
|
||||||
---
|
|
||||||
target/arm/kvm.c | 11 ++++++++++-
|
|
||||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
|
|
||||||
index 50e86f8b..cc7a46df 100644
|
|
||||||
--- a/target/arm/kvm.c
|
|
||||||
+++ b/target/arm/kvm.c
|
|
||||||
@@ -173,6 +173,8 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
|
|
||||||
|
|
||||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
|
||||||
{
|
|
||||||
+ int ret = 0;
|
|
||||||
+ unsigned int smp_cpus = ms->smp.cpus;
|
|
||||||
/* For ARM interrupt delivery is always asynchronous,
|
|
||||||
* whether we are using an in-kernel VGIC or not.
|
|
||||||
*/
|
|
||||||
@@ -186,7 +188,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
|
||||||
|
|
||||||
cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
|
|
||||||
|
|
||||||
- return 0;
|
|
||||||
+ if (smp_cpus > 256 &&
|
|
||||||
+ !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) {
|
|
||||||
+ error_report("Using more than 256 vcpus requires a host kernel "
|
|
||||||
+ "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2");
|
|
||||||
+ ret = -EINVAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long kvm_arch_vcpu_id(CPUState *cpu)
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
From 4646a24045cf53f2cc5e0ef1974da88ef50ef676 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ying Fang <fangying1@huawei.com>
|
|
||||||
Date: Wed, 27 May 2020 11:54:31 +0800
|
|
||||||
Subject: [PATCH] ARM64: record vtimer tick when cpu is stopped
|
|
||||||
|
|
||||||
The vtimer kick still increases even if the vcpu is stopped when VM has
|
|
||||||
save/restore or suspend/resume operation. This will cause guest watchdog
|
|
||||||
soft-lockup if the VM has lots of memory in use.
|
|
||||||
|
|
||||||
Signed-off-by: Hao Hong <honghao5@huawei.com>
|
|
||||||
Signed-off-by: Haibin Wang <wanghaibin.wang@huawei.com>
|
|
||||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
|
||||||
---
|
|
||||||
cpus.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
target/arm/cpu.h | 2 ++
|
|
||||||
target/arm/machine.c | 1 +
|
|
||||||
3 files changed, 61 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/cpus.c b/cpus.c
|
|
||||||
index 927a00aa..b9aa51f8 100644
|
|
||||||
--- a/cpus.c
|
|
||||||
+++ b/cpus.c
|
|
||||||
@@ -1066,6 +1066,28 @@ void cpu_synchronize_all_pre_loadvm(void)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef __aarch64__
|
|
||||||
+static void get_vcpu_timer_tick(CPUState *cs)
|
|
||||||
+{
|
|
||||||
+ CPUARMState *env = &ARM_CPU(cs)->env;
|
|
||||||
+ int err;
|
|
||||||
+ struct kvm_one_reg reg;
|
|
||||||
+ uint64_t timer_tick;
|
|
||||||
+
|
|
||||||
+ reg.id = KVM_REG_ARM_TIMER_CNT;
|
|
||||||
+ reg.addr = (uintptr_t) &timer_tick;
|
|
||||||
+
|
|
||||||
+ err = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ error_report("get vcpu tick failed, ret = %d", err);
|
|
||||||
+ env->vtimer = 0;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ env->vtimer = timer_tick;
|
|
||||||
+ return;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
static int do_vm_stop(RunState state, bool send_stop)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
@@ -1073,6 +1095,11 @@ static int do_vm_stop(RunState state, bool send_stop)
|
|
||||||
if (runstate_is_running()) {
|
|
||||||
cpu_disable_ticks();
|
|
||||||
pause_all_vcpus();
|
|
||||||
+#ifdef __aarch64__
|
|
||||||
+ if (first_cpu) {
|
|
||||||
+ get_vcpu_timer_tick(first_cpu);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
runstate_set(state);
|
|
||||||
vm_state_notify(0, state);
|
|
||||||
if (send_stop) {
|
|
||||||
@@ -1918,11 +1945,42 @@ void cpu_resume(CPUState *cpu)
|
|
||||||
qemu_cpu_kick(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef __aarch64__
|
|
||||||
+static void set_vcpu_timer_tick(CPUState *cs)
|
|
||||||
+{
|
|
||||||
+ CPUARMState *env = &ARM_CPU(cs)->env;
|
|
||||||
+
|
|
||||||
+ if (env->vtimer == 0) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ int err;
|
|
||||||
+ struct kvm_one_reg reg;
|
|
||||||
+ uint64_t timer_tick = env->vtimer;
|
|
||||||
+ env->vtimer = 0;
|
|
||||||
+
|
|
||||||
+ reg.id = KVM_REG_ARM_TIMER_CNT;
|
|
||||||
+ reg.addr = (uintptr_t) &timer_tick;
|
|
||||||
+
|
|
||||||
+ err = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ error_report("Set vcpu tick failed, ret = %d", err);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ return;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
void resume_all_vcpus(void)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
|
|
||||||
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
|
|
||||||
+#ifdef __aarch64__
|
|
||||||
+ if (first_cpu) {
|
|
||||||
+ set_vcpu_timer_tick(first_cpu);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
cpu_resume(cpu);
|
|
||||||
}
|
|
||||||
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
|
|
||||||
index 86eb79cd..aec6a214 100644
|
|
||||||
--- a/target/arm/cpu.h
|
|
||||||
+++ b/target/arm/cpu.h
|
|
||||||
@@ -262,6 +262,8 @@ typedef struct CPUARMState {
|
|
||||||
uint64_t sp_el[4]; /* AArch64 banked stack pointers */
|
|
||||||
|
|
||||||
|
|
||||||
+ uint64_t vtimer; /* Timer tick when vcpu stop */
|
|
||||||
+
|
|
||||||
/* System control coprocessor (cp15) */
|
|
||||||
struct {
|
|
||||||
uint32_t c0_cpuid;
|
|
||||||
diff --git a/target/arm/machine.c b/target/arm/machine.c
|
|
||||||
index ee3c59a6..ec28b839 100644
|
|
||||||
--- a/target/arm/machine.c
|
|
||||||
+++ b/target/arm/machine.c
|
|
||||||
@@ -814,6 +814,7 @@ const VMStateDescription vmstate_arm_cpu = {
|
|
||||||
VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
|
|
||||||
VMSTATE_UINT32(env.exception.fsr, ARMCPU),
|
|
||||||
VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
|
|
||||||
+ VMSTATE_UINT64(env.vtimer, ARMCPU),
|
|
||||||
VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
|
|
||||||
VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
From 8cb4d202d4e5713e9b2b5f0ec817234941623f10 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
|
||||||
Date: Fri, 4 Jun 2021 15:58:25 +0400
|
|
||||||
Subject: [PATCH 1/6] Add mtod_check()
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Recent security issues demonstrate the lack of safety care when casting
|
|
||||||
a mbuf to a particular structure type. At least, it should check that
|
|
||||||
the buffer is large enough. The following patches will make use of this
|
|
||||||
function.
|
|
||||||
|
|
||||||
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
|
||||||
Signed-off-by: imxcc <xingchaochao@huawei.com>
|
|
||||||
---
|
|
||||||
slirp/src/mbuf.c | 11 +++++++++++
|
|
||||||
slirp/src/mbuf.h | 1 +
|
|
||||||
2 files changed, 12 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/slirp/src/mbuf.c b/slirp/src/mbuf.c
|
|
||||||
index 4fd62282..6d0653ed 100644
|
|
||||||
--- a/slirp/src/mbuf.c
|
|
||||||
+++ b/slirp/src/mbuf.c
|
|
||||||
@@ -222,3 +222,14 @@ struct mbuf *dtom(Slirp *slirp, void *dat)
|
|
||||||
|
|
||||||
return (struct mbuf *)0;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+void *mtod_check(struct mbuf *m, size_t len)
|
|
||||||
+{
|
|
||||||
+ if (m->m_len >= len) {
|
|
||||||
+ return m->m_data;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ DEBUG_ERROR("mtod failed");
|
|
||||||
+
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
diff --git a/slirp/src/mbuf.h b/slirp/src/mbuf.h
|
|
||||||
index 546e7852..2015e323 100644
|
|
||||||
--- a/slirp/src/mbuf.h
|
|
||||||
+++ b/slirp/src/mbuf.h
|
|
||||||
@@ -118,6 +118,7 @@ void m_inc(struct mbuf *, int);
|
|
||||||
void m_adj(struct mbuf *, int);
|
|
||||||
int m_copy(struct mbuf *, struct mbuf *, int, int);
|
|
||||||
struct mbuf *dtom(Slirp *, void *);
|
|
||||||
+void *mtod_check(struct mbuf *, size_t len);
|
|
||||||
|
|
||||||
static inline void ifs_init(struct mbuf *ifm)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
From 38734e26ce3840d459da13607a9d46de24a15388 Mon Sep 17 00:00:00 2001
|
|
||||||
From: kevinZhu <zhukeqian94@163.com>
|
|
||||||
Date: Thu, 29 Oct 2020 19:24:48 +0800
|
|
||||||
Subject: [PATCH] Bugfix: hw/acpi: Use max_cpus instead of cpus when build PPTT
|
|
||||||
table
|
|
||||||
|
|
||||||
The field "cpus" is the initial number of CPU for guest, and the field "max_cpus"
|
|
||||||
is the max number of CPU after CPU hotplug. When building PPTT for guest, we
|
|
||||||
should take all CPUs into account, otherwise the "smp_sockets" is wrong.
|
|
||||||
|
|
||||||
Fixes: 7cfcd8c8a2fe ("build smt processor structure to support smt topology")
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
---
|
|
||||||
hw/acpi/aml-build.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
|
||||||
index 8a3b51c835..f01669df57 100644
|
|
||||||
--- a/hw/acpi/aml-build.c
|
|
||||||
+++ b/hw/acpi/aml-build.c
|
|
||||||
@@ -167,7 +167,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus)
|
|
||||||
struct offset_status offset;
|
|
||||||
const MachineState *ms = MACHINE(qdev_get_machine());
|
|
||||||
unsigned int smp_cores = ms->smp.cores;
|
|
||||||
- unsigned int smp_sockets = ms->smp.cpus / (smp_cores * ms->smp.threads);
|
|
||||||
+ unsigned int smp_sockets = ms->smp.max_cpus / (smp_cores * ms->smp.threads);
|
|
||||||
|
|
||||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
From 124032e79e354f5e7cc28958f2ca6b9f898da719 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Fan Yang <Fan_Yang@sjtu.edu.cn>
|
|
||||||
Date: Tue, 24 Sep 2019 22:08:29 +0800
|
|
||||||
Subject: [PATCH] COLO-compare: Fix incorrect `if` logic
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
'colo_mark_tcp_pkt' should return 'true' when packets are the same, and
|
|
||||||
'false' otherwise. However, it returns 'true' when
|
|
||||||
'colo_compare_packet_payload' returns non-zero while
|
|
||||||
'colo_compare_packet_payload' is just a 'memcmp'. The result is that
|
|
||||||
COLO-compare reports inconsistent TCP packets when they are actually
|
|
||||||
the same.
|
|
||||||
|
|
||||||
Fixes: f449c9e549c ("colo: compare the packet based on the tcp sequence number")
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Signed-off-by: Fan Yang <Fan_Yang@sjtu.edu.cn>
|
|
||||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
|
||||||
(cherry picked from commit 1e907a32b77e5d418538453df5945242e43224fa)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
net/colo-compare.c | 6 +++---
|
|
||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/net/colo-compare.c b/net/colo-compare.c
|
|
||||||
index bf10526..9827c0e 100644
|
|
||||||
--- a/net/colo-compare.c
|
|
||||||
+++ b/net/colo-compare.c
|
|
||||||
@@ -287,7 +287,7 @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
|
|
||||||
*mark = 0;
|
|
||||||
|
|
||||||
if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) {
|
|
||||||
- if (colo_compare_packet_payload(ppkt, spkt,
|
|
||||||
+ if (!colo_compare_packet_payload(ppkt, spkt,
|
|
||||||
ppkt->header_size, spkt->header_size,
|
|
||||||
ppkt->payload_size)) {
|
|
||||||
*mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY;
|
|
||||||
@@ -297,7 +297,7 @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
|
|
||||||
|
|
||||||
/* one part of secondary packet payload still need to be compared */
|
|
||||||
if (!after(ppkt->seq_end, spkt->seq_end)) {
|
|
||||||
- if (colo_compare_packet_payload(ppkt, spkt,
|
|
||||||
+ if (!colo_compare_packet_payload(ppkt, spkt,
|
|
||||||
ppkt->header_size + ppkt->offset,
|
|
||||||
spkt->header_size + spkt->offset,
|
|
||||||
ppkt->payload_size - ppkt->offset)) {
|
|
||||||
@@ -316,7 +316,7 @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt,
|
|
||||||
/* primary packet is longer than secondary packet, compare
|
|
||||||
* the same part and mark the primary packet offset
|
|
||||||
*/
|
|
||||||
- if (colo_compare_packet_payload(ppkt, spkt,
|
|
||||||
+ if (!colo_compare_packet_payload(ppkt, spkt,
|
|
||||||
ppkt->header_size + ppkt->offset,
|
|
||||||
spkt->header_size + spkt->offset,
|
|
||||||
spkt->payload_size - spkt->offset)) {
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
From e8b555c08061ad78920611a5e98ee14fcd967692 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ralf Haferkamp <rhafer@suse.com>
|
|
||||||
Date: Fri, 11 Sep 2020 10:55:49 +0800
|
|
||||||
Subject: [PATCH] Drop bogus IPv6 messages
|
|
||||||
|
|
||||||
Drop IPv6 message shorter than what's mentioned in the playload
|
|
||||||
length header (+the size of IPv6 header). They're invalid and could
|
|
||||||
lead to data leakage in icmp6_send_echoreply().
|
|
||||||
|
|
||||||
diff --git a/slirp/src/ip6_input.c b/slirp/src/ip6_input.c
|
|
||||||
index d9d2b7e..c2dce52 100644
|
|
||||||
--- a/slirp/src/ip6_input.c
|
|
||||||
+++ b/slirp/src/ip6_input.c
|
|
||||||
@@ -49,6 +49,13 @@ void ip6_input(struct mbuf *m)
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ // Check if the message size is big enough to hold what's
|
|
||||||
+ // set in the payload length header. If not this is an invalid
|
|
||||||
+ // packet
|
|
||||||
+ if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) {
|
|
||||||
+ goto bad;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* check ip_ttl for a correct ICMP reply */
|
|
||||||
if (ip6->ip_hl == 0) {
|
|
||||||
icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
From 126fc13ebe9c5e58a5b1daeb4e102e6fa5845779 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kirti Wankhede <kwankhede@nvidia.com>
|
|
||||||
Date: Fri, 6 Nov 2020 23:32:24 +0530
|
|
||||||
Subject: [PATCH] Fix use after free in vfio_migration_probe
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Fixes Coverity issue:
|
|
||||||
CID 1436126: Memory - illegal accesses (USE_AFTER_FREE)
|
|
||||||
|
|
||||||
Fixes: a9e271ec9b36 ("vfio: Add migration region initialization and finalize function")
|
|
||||||
Signed-off-by: Kirti Wankhede <kwankhede@nvidia.com>
|
|
||||||
Reviewed-by: David Edmondson <dme@dme.org>
|
|
||||||
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
|
|
||||||
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
|
|
||||||
---
|
|
||||||
hw/vfio/migration.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
|
|
||||||
index 1a97784486..8546075706 100644
|
|
||||||
--- a/hw/vfio/migration.c
|
|
||||||
+++ b/hw/vfio/migration.c
|
|
||||||
@@ -903,8 +903,8 @@ int vfio_migration_probe(VFIODevice *vbasedev, Error **errp)
|
|
||||||
goto add_blocker;
|
|
||||||
}
|
|
||||||
|
|
||||||
- g_free(info);
|
|
||||||
trace_vfio_migration_probe(vbasedev->name, info->index);
|
|
||||||
+ g_free(info);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
add_blocker:
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
From 41077af2c4283c15c0a822017ea51612d15b68f8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Andrew Melnychenko <andrew@daynix.com>
|
|
||||||
Date: Wed, 4 Mar 2020 16:20:58 +0200
|
|
||||||
Subject: [PATCH 1/5] Fixed integer overflow in e1000e
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1737400
|
|
||||||
Fixed setting max_queue_num if there are no peers in
|
|
||||||
NICConf. qemu_new_nic() creates NICState with 1 NetClientState(index
|
|
||||||
0) without peers, set max_queue_num to 0 - It prevents undefined
|
|
||||||
behavior and possible crashes, especially during pcie hotplug.
|
|
||||||
|
|
||||||
Fixes: 6f3fbe4ed06 ("net: Introduce e1000e device emulation")
|
|
||||||
Signed-off-by: Andrew Melnychenko <andrew@daynix.com>
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Reviewed-by: Dmitry Fleytman <dmitry.fleytman@gmail.com>
|
|
||||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
|
||||||
Signed-off-by: Zhenyu Ye <yezhenyu2@huawei.com>
|
|
||||||
---
|
|
||||||
hw/net/e1000e.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
|
|
||||||
index 581f7d03..1e827c4f 100644
|
|
||||||
--- a/hw/net/e1000e.c
|
|
||||||
+++ b/hw/net/e1000e.c
|
|
||||||
@@ -325,7 +325,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr)
|
|
||||||
s->nic = qemu_new_nic(&net_e1000e_info, &s->conf,
|
|
||||||
object_get_typename(OBJECT(s)), dev->id, s);
|
|
||||||
|
|
||||||
- s->core.max_queue_num = s->conf.peers.queues - 1;
|
|
||||||
+ s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0;
|
|
||||||
|
|
||||||
trace_e1000e_mac_set_permanent(MAC_ARG(macaddr));
|
|
||||||
memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac));
|
|
||||||
--
|
|
||||||
2.22.0.windows.1
|
|
||||||
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
From 73a5bf472921068e6db10e7e325b7ac46f111834 Mon Sep 17 00:00:00 2001
|
|
||||||
From: John Snow <jsnow@redhat.com>
|
|
||||||
Date: Mon, 29 Jul 2019 18:36:05 -0400
|
|
||||||
Subject: [PATCH] Revert "ide/ahci: Check for -ECANCELED in aio callbacks"
|
|
||||||
|
|
||||||
This reverts commit 0d910cfeaf2076b116b4517166d5deb0fea76394.
|
|
||||||
|
|
||||||
It's not correct to just ignore an error code in a callback; we need to
|
|
||||||
handle that error and possible report failure to the guest so that they
|
|
||||||
don't wait indefinitely for an operation that will now never finish.
|
|
||||||
|
|
||||||
This ought to help cases reported by Nutanix where iSCSI returns a
|
|
||||||
legitimate -ECANCELED for certain operations which should be propagated
|
|
||||||
normally.
|
|
||||||
|
|
||||||
Reported-by: Shaju Abraham <shaju.abraham@nutanix.com>
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
Message-id: 20190729223605.7163-1-jsnow@redhat.com
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
(cherry picked from commit 8ec41c4265714255d5a138f8b538faf3583dcff6)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
hw/ide/ahci.c | 3 ---
|
|
||||||
hw/ide/core.c | 14 --------------
|
|
||||||
2 files changed, 17 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
|
|
||||||
index 00ba422a48..6aaf66534a 100644
|
|
||||||
--- a/hw/ide/ahci.c
|
|
||||||
+++ b/hw/ide/ahci.c
|
|
||||||
@@ -1023,9 +1023,6 @@ static void ncq_cb(void *opaque, int ret)
|
|
||||||
IDEState *ide_state = &ncq_tfs->drive->port.ifs[0];
|
|
||||||
|
|
||||||
ncq_tfs->aiocb = NULL;
|
|
||||||
- if (ret == -ECANCELED) {
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
bool is_read = ncq_tfs->cmd == READ_FPDMA_QUEUED;
|
|
||||||
diff --git a/hw/ide/core.c b/hw/ide/core.c
|
|
||||||
index 6afadf894f..8e1624f7ce 100644
|
|
||||||
--- a/hw/ide/core.c
|
|
||||||
+++ b/hw/ide/core.c
|
|
||||||
@@ -722,9 +722,6 @@ static void ide_sector_read_cb(void *opaque, int ret)
|
|
||||||
s->pio_aiocb = NULL;
|
|
||||||
s->status &= ~BUSY_STAT;
|
|
||||||
|
|
||||||
- if (ret == -ECANCELED) {
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
if (ret != 0) {
|
|
||||||
if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO |
|
|
||||||
IDE_RETRY_READ)) {
|
|
||||||
@@ -840,10 +837,6 @@ static void ide_dma_cb(void *opaque, int ret)
|
|
||||||
uint64_t offset;
|
|
||||||
bool stay_active = false;
|
|
||||||
|
|
||||||
- if (ret == -ECANCELED) {
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
if (ret == -EINVAL) {
|
|
||||||
ide_dma_error(s);
|
|
||||||
return;
|
|
||||||
@@ -975,10 +968,6 @@ static void ide_sector_write_cb(void *opaque, int ret)
|
|
||||||
IDEState *s = opaque;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
- if (ret == -ECANCELED) {
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
s->pio_aiocb = NULL;
|
|
||||||
s->status &= ~BUSY_STAT;
|
|
||||||
|
|
||||||
@@ -1058,9 +1047,6 @@ static void ide_flush_cb(void *opaque, int ret)
|
|
||||||
|
|
||||||
s->pio_aiocb = NULL;
|
|
||||||
|
|
||||||
- if (ret == -ECANCELED) {
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
if (ret < 0) {
|
|
||||||
/* XXX: What sector number to set here? */
|
|
||||||
if (ide_handle_rw_error(s, -ret, IDE_RETRY_FLUSH)) {
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
From ced290d644a00e18e70046194d042bcaa2703b65 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ying Fang <fangying1@huawei.com>
|
|
||||||
Date: Wed, 27 May 2020 11:16:53 +0800
|
|
||||||
Subject: [PATCH] Revert: "vtimer: compat cross version migration from v4.0.1"
|
|
||||||
|
|
||||||
This reverts commit patch:
|
|
||||||
vtimer-compat-cross-version-migration-from-v4.0.1.patch
|
|
||||||
|
|
||||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
|
||||||
|
|
||||||
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
|
|
||||||
index 2609113d..86eb79cd 100644
|
|
||||||
--- a/target/arm/cpu.h
|
|
||||||
+++ b/target/arm/cpu.h
|
|
||||||
@@ -261,7 +261,6 @@ typedef struct CPUARMState {
|
|
||||||
uint64_t elr_el[4]; /* AArch64 exception link regs */
|
|
||||||
uint64_t sp_el[4]; /* AArch64 banked stack pointers */
|
|
||||||
|
|
||||||
- uint64_t vtimer; /* Timer tick when vcpu is stopped */
|
|
||||||
|
|
||||||
/* System control coprocessor (cp15) */
|
|
||||||
struct {
|
|
||||||
diff --git a/target/arm/machine.c b/target/arm/machine.c
|
|
||||||
index ec28b839..ee3c59a6 100644
|
|
||||||
--- a/target/arm/machine.c
|
|
||||||
+++ b/target/arm/machine.c
|
|
||||||
@@ -814,7 +814,6 @@ const VMStateDescription vmstate_arm_cpu = {
|
|
||||||
VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
|
|
||||||
VMSTATE_UINT32(env.exception.fsr, ARMCPU),
|
|
||||||
VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
|
|
||||||
- VMSTATE_UINT64(env.vtimer, ARMCPU),
|
|
||||||
VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
|
|
||||||
VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
From 843f593280b93e03bb7b0d0001da7488d61f13f6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Mon, 6 Apr 2020 08:55:17 +0800
|
|
||||||
Subject: [PATCH] Typo: Correct the name of CPU hotplug memory region
|
|
||||||
|
|
||||||
Replace "acpi-mem-hotplug" with "acpi-cpu-hotplug"
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
---
|
|
||||||
hw/acpi/cpu.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
|
||||||
index 7a90c8f82d..0c0bfe479a 100644
|
|
||||||
--- a/hw/acpi/cpu.c
|
|
||||||
+++ b/hw/acpi/cpu.c
|
|
||||||
@@ -203,7 +203,7 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
|
|
||||||
state->devs[i].arch_id = id_list->cpus[i].arch_id;
|
|
||||||
}
|
|
||||||
memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state,
|
|
||||||
- "acpi-mem-hotplug", ACPI_CPU_HOTPLUG_REG_LEN);
|
|
||||||
+ "acpi-cpu-hotplug", ACPI_CPU_HOTPLUG_REG_LEN);
|
|
||||||
memory_region_add_subregion(as, base_addr, &state->ctrl_reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
From 135119d2e82e99adc67346572c761fbe54d73e4a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 13:04:40 +0800
|
|
||||||
Subject: [PATCH] accel/kvm: Add pre-park vCPU support
|
|
||||||
|
|
||||||
For that KVM do not support dynamic adjustment of vCPU count,
|
|
||||||
we must pre-park all possible vCPU at start.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
accel/kvm/kvm-all.c | 23 +++++++++++++++++++++++
|
|
||||||
include/sysemu/kvm.h | 1 +
|
|
||||||
2 files changed, 24 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
|
||||||
index f450f25295..84edbe8bb1 100644
|
|
||||||
--- a/accel/kvm/kvm-all.c
|
|
||||||
+++ b/accel/kvm/kvm-all.c
|
|
||||||
@@ -339,6 +339,29 @@ err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+int kvm_create_parked_vcpu(unsigned long vcpu_id)
|
|
||||||
+{
|
|
||||||
+ KVMState *s = kvm_state;
|
|
||||||
+ struct KVMParkedVcpu *vcpu = NULL;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ DPRINTF("kvm_create_parked_vcpu\n");
|
|
||||||
+
|
|
||||||
+ ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ DPRINTF("kvm_create_vcpu failed\n");
|
|
||||||
+ goto err;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ vcpu = g_malloc0(sizeof(*vcpu));
|
|
||||||
+ vcpu->vcpu_id = vcpu_id;
|
|
||||||
+ vcpu->kvm_fd = ret;
|
|
||||||
+ QLIST_INSERT_HEAD(&s->kvm_parked_vcpus, vcpu, node);
|
|
||||||
+
|
|
||||||
+err:
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
|
|
||||||
{
|
|
||||||
struct KVMParkedVcpu *cpu;
|
|
||||||
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
|
||||||
index acd90aebb6..565adb4e2c 100644
|
|
||||||
--- a/include/sysemu/kvm.h
|
|
||||||
+++ b/include/sysemu/kvm.h
|
|
||||||
@@ -216,6 +216,7 @@ int kvm_has_many_ioeventfds(void);
|
|
||||||
int kvm_has_gsi_routing(void);
|
|
||||||
int kvm_has_intx_set_mask(void);
|
|
||||||
|
|
||||||
+int kvm_create_parked_vcpu(unsigned long vcpu_id);
|
|
||||||
int kvm_init_vcpu(CPUState *cpu);
|
|
||||||
int kvm_cpu_exec(CPUState *cpu);
|
|
||||||
int kvm_destroy_vcpu(CPUState *cpu);
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
From b50b9a0e2e5e8262c830df5994f3abbe0a37655a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Thu, 17 Dec 2020 09:49:40 +0800
|
|
||||||
Subject: [PATCH] accel: kvm: Fix memory waste under mismatch page size
|
|
||||||
|
|
||||||
When handle dirty log, we face qemu_real_host_page_size and
|
|
||||||
TARGET_PAGE_SIZE. The first one is the granule of KVM dirty
|
|
||||||
bitmap, and the second one is the granule of QEMU dirty bitmap.
|
|
||||||
|
|
||||||
As qemu_real_host_page_size >= TARGET_PAGE_SIZE (kvm_init()
|
|
||||||
enforced it), misuse TARGET_PAGE_SIZE to init kvmslot dirty_bmap
|
|
||||||
may waste memory. For example, when qemu_real_host_page_size is
|
|
||||||
64K and TARGET_PAGE_SIZE is 4K, it wastes 93.75% (15/16) memory.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Reviewed-by: Andrew Jones <drjones@redhat.com>
|
|
||||||
Reviewed-by: Peter Xu <peterx@redhat.com>
|
|
||||||
Message-Id: <20201217014941.22872-2-zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
|
|
||||||
---
|
|
||||||
accel/kvm/kvm-all.c | 6 +++++-
|
|
||||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
|
||||||
index 5a6b89cc2a..4daff563a0 100644
|
|
||||||
--- a/accel/kvm/kvm-all.c
|
|
||||||
+++ b/accel/kvm/kvm-all.c
|
|
||||||
@@ -551,8 +551,12 @@ static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
|
|
||||||
* too, in most cases).
|
|
||||||
* So for now, let's align to 64 instead of HOST_LONG_BITS here, in
|
|
||||||
* a hope that sizeof(long) won't become >8 any time soon.
|
|
||||||
+ *
|
|
||||||
+ * Note: the granule of kvm dirty log is qemu_real_host_page_size.
|
|
||||||
+ * And mem->memory_size is aligned to it (otherwise this mem can't
|
|
||||||
+ * be registered to KVM).
|
|
||||||
*/
|
|
||||||
- hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS),
|
|
||||||
+ hwaddr bitmap_size = ALIGN(mem->memory_size / qemu_real_host_page_size,
|
|
||||||
/*HOST_LONG_BITS*/ 64) / 8;
|
|
||||||
mem->dirty_bmap = g_malloc0(bitmap_size);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
From 107c267ebe5b8c461268a4ff8384ad2f2b9e8ce0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Wed, 22 Apr 2020 16:11:13 +0800
|
|
||||||
Subject: [PATCH] acpi/cpu: Prepare build_cpus_aml for arm virt
|
|
||||||
|
|
||||||
We will reuse build_cpus_aml to build DSDT cpus aml in arm/virt
|
|
||||||
ACPI to realize cpu hotplug. Three points are added.
|
|
||||||
|
|
||||||
1. Make ACPI IO address space configurable, because ARM64 platforms
|
|
||||||
don't use port IO for ACPI IO space.
|
|
||||||
2. Add GICC struct building support in _MAT of cpu aml.
|
|
||||||
3. Let the hotplug method parameter can be NULL, because ACPI GED
|
|
||||||
will realize it.
|
|
||||||
|
|
||||||
Besides, CPU CPPC building is injected.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/acpi/cpu.c | 32 +++++++++++++++++++++++++-------
|
|
||||||
hw/i386/acpi-build.c | 2 +-
|
|
||||||
include/hw/acpi/cpu.h | 3 ++-
|
|
||||||
3 files changed, 28 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
|
||||||
index 0c0bfe479a..72ad1fcff2 100644
|
|
||||||
--- a/hw/acpi/cpu.c
|
|
||||||
+++ b/hw/acpi/cpu.c
|
|
||||||
@@ -314,7 +314,8 @@ const VMStateDescription vmstate_cpu_hotplug = {
|
|
||||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
|
||||||
hwaddr io_base,
|
|
||||||
const char *res_root,
|
|
||||||
- const char *event_handler_method)
|
|
||||||
+ const char *event_handler_method,
|
|
||||||
+ AmlRegionSpace rs)
|
|
||||||
{
|
|
||||||
Aml *ifctx;
|
|
||||||
Aml *field;
|
|
||||||
@@ -342,13 +343,18 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
|
||||||
aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
|
|
||||||
|
|
||||||
crs = aml_resource_template();
|
|
||||||
- aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
|
|
||||||
- ACPI_CPU_HOTPLUG_REG_LEN));
|
|
||||||
+ if (rs == AML_SYSTEM_IO) {
|
|
||||||
+ aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
|
|
||||||
+ ACPI_CPU_HOTPLUG_REG_LEN));
|
|
||||||
+ } else {
|
|
||||||
+ aml_append(crs, aml_memory32_fixed(io_base,
|
|
||||||
+ ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE));
|
|
||||||
+ }
|
|
||||||
aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
|
|
||||||
|
|
||||||
/* declare CPU hotplug MMIO region with related access fields */
|
|
||||||
aml_append(cpu_ctrl_dev,
|
|
||||||
- aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base),
|
|
||||||
+ aml_operation_region("PRST", rs, aml_int(io_base),
|
|
||||||
ACPI_CPU_HOTPLUG_REG_LEN));
|
|
||||||
|
|
||||||
field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
|
|
||||||
@@ -517,6 +523,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
|
||||||
aml_append(dev, aml_name_decl("_UID", uid));
|
|
||||||
}
|
|
||||||
|
|
||||||
+ assert(adevc);
|
|
||||||
+ if (adevc->cpu_cppc) {
|
|
||||||
+ adevc->cpu_cppc(adev, i, arch_ids->len, dev);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
method = aml_method("_STA", 0, AML_SERIALIZED);
|
|
||||||
aml_append(method, aml_return(aml_call1(CPU_STS_METHOD, uid)));
|
|
||||||
aml_append(dev, method);
|
|
||||||
@@ -535,6 +546,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
|
||||||
apic->flags = cpu_to_le32(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
+ case ACPI_APIC_GENERIC_CPU_INTERFACE: {
|
|
||||||
+ AcpiMadtGenericCpuInterface *gicc = (void *)madt_buf->data;
|
|
||||||
+ gicc->flags = cpu_to_le32(1);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
@@ -570,9 +586,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
|
||||||
aml_append(sb_scope, cpus_dev);
|
|
||||||
aml_append(table, sb_scope);
|
|
||||||
|
|
||||||
- method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
|
|
||||||
- aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
|
|
||||||
- aml_append(table, method);
|
|
||||||
+ if (event_handler_method) {
|
|
||||||
+ method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
|
|
||||||
+ aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
|
|
||||||
+ aml_append(table, method);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
g_free(cphp_res_path);
|
|
||||||
}
|
|
||||||
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
|
|
||||||
index 749218561a..c97731ecb3 100644
|
|
||||||
--- a/hw/i386/acpi-build.c
|
|
||||||
+++ b/hw/i386/acpi-build.c
|
|
||||||
@@ -1869,7 +1869,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
|
||||||
.acpi_1_compatible = true, .has_legacy_cphp = true
|
|
||||||
};
|
|
||||||
build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base,
|
|
||||||
- "\\_SB.PCI0", "\\_GPE._E02");
|
|
||||||
+ "\\_SB.PCI0", "\\_GPE._E02", AML_SYSTEM_IO);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcms->memhp_io_base && nr_mem) {
|
|
||||||
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
|
|
||||||
index 62f0278ba2..a30ec84a4f 100644
|
|
||||||
--- a/include/hw/acpi/cpu.h
|
|
||||||
+++ b/include/hw/acpi/cpu.h
|
|
||||||
@@ -55,7 +55,8 @@ typedef struct CPUHotplugFeatures {
|
|
||||||
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
|
||||||
hwaddr io_base,
|
|
||||||
const char *res_root,
|
|
||||||
- const char *event_handler_method);
|
|
||||||
+ const char *event_handler_method,
|
|
||||||
+ AmlRegionSpace rs);
|
|
||||||
|
|
||||||
void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list);
|
|
||||||
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
From 3cd6df0b9e7d7b544673ce9a63b405e236d8265b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 10:05:54 +0800
|
|
||||||
Subject: [PATCH] acpi/ged: Add virt_madt_cpu_entry to madt_cpu hook
|
|
||||||
|
|
||||||
In build_cpus_aml, we will invoke this hook to build _MAT
|
|
||||||
aml mehtod for cpus.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/acpi/generic_event_device.c | 1 +
|
|
||||||
include/hw/acpi/generic_event_device.h | 1 +
|
|
||||||
2 files changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
|
||||||
index 9cee90cc70..b834ae3ff6 100644
|
|
||||||
--- a/hw/acpi/generic_event_device.c
|
|
||||||
+++ b/hw/acpi/generic_event_device.c
|
|
||||||
@@ -288,6 +288,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data)
|
|
||||||
hc->plug = acpi_ged_device_plug_cb;
|
|
||||||
|
|
||||||
adevc->send_event = acpi_ged_send_event;
|
|
||||||
+ adevc->madt_cpu = virt_madt_cpu_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const TypeInfo acpi_ged_info = {
|
|
||||||
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
|
|
||||||
index d157eac088..f99efad7a3 100644
|
|
||||||
--- a/include/hw/acpi/generic_event_device.h
|
|
||||||
+++ b/include/hw/acpi/generic_event_device.h
|
|
||||||
@@ -61,6 +61,7 @@
|
|
||||||
|
|
||||||
#include "hw/sysbus.h"
|
|
||||||
#include "hw/acpi/memory_hotplug.h"
|
|
||||||
+#include "hw/arm/virt.h"
|
|
||||||
|
|
||||||
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
|
|
||||||
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,204 +0,0 @@
|
|||||||
From 05d22b55133db1a2526cfe305102e075e883b5e2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 3 Apr 2020 15:41:01 +0800
|
|
||||||
Subject: [PATCH] acpi/ged: Extend ACPI GED to support CPU hotplug
|
|
||||||
|
|
||||||
This adds a new GED event called ACPI_GED_CPU_HOTPLUG_EVT.
|
|
||||||
The basic workflow is that: GED sends this event to guest,
|
|
||||||
then ACPI driver in guest will call _EVT method of GED aml,
|
|
||||||
then _EVT will call CSCN method in cpus aml to get status of
|
|
||||||
all cpus.
|
|
||||||
|
|
||||||
The status of cpus is maintained by CPUHotplugState in GED and
|
|
||||||
is made accessable to guest through memory region.
|
|
||||||
|
|
||||||
This also adds migration support to CPUHotplugState.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
docs/specs/acpi_hw_reduced_hotplug.rst | 3 ++-
|
|
||||||
hw/acpi/cpu.c | 1 -
|
|
||||||
hw/acpi/generic_event_device.c | 35 ++++++++++++++++++++++++++
|
|
||||||
hw/arm/Kconfig | 1 +
|
|
||||||
include/hw/acpi/cpu.h | 2 ++
|
|
||||||
include/hw/acpi/generic_event_device.h | 4 +++
|
|
||||||
6 files changed, 44 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst
|
|
||||||
index 911a98255b..deb481555d 100644
|
|
||||||
--- a/docs/specs/acpi_hw_reduced_hotplug.rst
|
|
||||||
+++ b/docs/specs/acpi_hw_reduced_hotplug.rst
|
|
||||||
@@ -63,7 +63,8 @@ GED IO interface (4 byte access)
|
|
||||||
bits:
|
|
||||||
0: Memory hotplug event
|
|
||||||
1: System power down event
|
|
||||||
- 2-31: Reserved
|
|
||||||
+ 2: CPU hotplug event
|
|
||||||
+ 3-31: Reserved
|
|
||||||
|
|
||||||
**write_access:**
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
|
||||||
index 72ad1fcff2..cb6bb67f3c 100644
|
|
||||||
--- a/hw/acpi/cpu.c
|
|
||||||
+++ b/hw/acpi/cpu.c
|
|
||||||
@@ -6,7 +6,6 @@
|
|
||||||
#include "trace.h"
|
|
||||||
#include "sysemu/numa.h"
|
|
||||||
|
|
||||||
-#define ACPI_CPU_HOTPLUG_REG_LEN 12
|
|
||||||
#define ACPI_CPU_SELECTOR_OFFSET_WR 0
|
|
||||||
#define ACPI_CPU_FLAGS_OFFSET_RW 4
|
|
||||||
#define ACPI_CPU_CMD_OFFSET_WR 5
|
|
||||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
|
||||||
index 82139b4314..478a4ee87c 100644
|
|
||||||
--- a/hw/acpi/generic_event_device.c
|
|
||||||
+++ b/hw/acpi/generic_event_device.c
|
|
||||||
@@ -23,6 +23,7 @@
|
|
||||||
static const uint32_t ged_supported_events[] = {
|
|
||||||
ACPI_GED_MEM_HOTPLUG_EVT,
|
|
||||||
ACPI_GED_PWR_DOWN_EVT,
|
|
||||||
+ ACPI_GED_CPU_HOTPLUG_EVT,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -110,6 +111,9 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
|
|
||||||
aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
|
|
||||||
aml_int(0x80)));
|
|
||||||
break;
|
|
||||||
+ case ACPI_GED_CPU_HOTPLUG_EVT:
|
|
||||||
+ aml_append(if_ctx, aml_call0("\\_SB.CPUS.CSCN"));
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
/*
|
|
||||||
* Please make sure all the events in ged_supported_events[]
|
|
||||||
@@ -176,6 +180,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
|
|
||||||
|
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
|
||||||
acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
|
||||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
|
||||||
+ acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
|
|
||||||
} else {
|
|
||||||
error_setg(errp, "virt: device plug request for unsupported device"
|
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
|
||||||
@@ -192,6 +198,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
|
||||||
sel = ACPI_GED_MEM_HOTPLUG_EVT;
|
|
||||||
} else if (ev & ACPI_POWER_DOWN_STATUS) {
|
|
||||||
sel = ACPI_GED_PWR_DOWN_EVT;
|
|
||||||
+ } else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
|
|
||||||
+ sel = ACPI_GED_CPU_HOTPLUG_EVT;
|
|
||||||
} else {
|
|
||||||
/* Unknown event. Return without generating interrupt. */
|
|
||||||
warn_report("GED: Unsupported event %d. No irq injected", ev);
|
|
||||||
@@ -224,6 +232,16 @@ static const VMStateDescription vmstate_memhp_state = {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
+static const VMStateDescription vmstate_cpuhp_state = {
|
|
||||||
+ .name = "acpi-ged/cpuhp",
|
|
||||||
+ .version_id = 1,
|
|
||||||
+ .minimum_version_id = 1,
|
|
||||||
+ .fields = (VMStateField[]) {
|
|
||||||
+ VMSTATE_CPU_HOTPLUG(cpuhp_state, AcpiGedState),
|
|
||||||
+ VMSTATE_END_OF_LIST()
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
static const VMStateDescription vmstate_ged_state = {
|
|
||||||
.name = "acpi-ged-state",
|
|
||||||
.version_id = 1,
|
|
||||||
@@ -244,6 +262,7 @@ static const VMStateDescription vmstate_acpi_ged = {
|
|
||||||
},
|
|
||||||
.subsections = (const VMStateDescription * []) {
|
|
||||||
&vmstate_memhp_state,
|
|
||||||
+ &vmstate_cpuhp_state,
|
|
||||||
NULL
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -254,6 +273,7 @@ static void acpi_ged_initfn(Object *obj)
|
|
||||||
AcpiGedState *s = ACPI_GED(dev);
|
|
||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
|
||||||
GEDState *ged_st = &s->ged_state;
|
|
||||||
+ MachineClass *mc;
|
|
||||||
|
|
||||||
memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st,
|
|
||||||
TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN);
|
|
||||||
@@ -273,6 +293,21 @@ static void acpi_ged_initfn(Object *obj)
|
|
||||||
sysbus_init_mmio(sbd, &s->container_memhp);
|
|
||||||
acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev),
|
|
||||||
&s->memhp_state, 0);
|
|
||||||
+
|
|
||||||
+ mc = MACHINE_GET_CLASS(qdev_get_machine());
|
|
||||||
+ if (!mc->possible_cpu_arch_ids) {
|
|
||||||
+ /*
|
|
||||||
+ * MachineClass should support possible_cpu_arch_ids in
|
|
||||||
+ * cpu_hotplug_hw_init below.
|
|
||||||
+ */
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container",
|
|
||||||
+ ACPI_CPU_HOTPLUG_REG_LEN);
|
|
||||||
+ sysbus_init_mmio(sbd, &s->container_cpuhp);
|
|
||||||
+ cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev),
|
|
||||||
+ &s->cpuhp_state, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void acpi_ged_class_init(ObjectClass *class, void *data)
|
|
||||||
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
|
|
||||||
index ad7f7c089b..15e18b0a48 100644
|
|
||||||
--- a/hw/arm/Kconfig
|
|
||||||
+++ b/hw/arm/Kconfig
|
|
||||||
@@ -24,6 +24,7 @@ config ARM_VIRT
|
|
||||||
select DIMM
|
|
||||||
select ACPI_MEMORY_HOTPLUG
|
|
||||||
select ACPI_HW_REDUCED
|
|
||||||
+ select ACPI_CPU_HOTPLUG
|
|
||||||
|
|
||||||
config CHEETAH
|
|
||||||
bool
|
|
||||||
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
|
|
||||||
index a30ec84a4f..e726414459 100644
|
|
||||||
--- a/include/hw/acpi/cpu.h
|
|
||||||
+++ b/include/hw/acpi/cpu.h
|
|
||||||
@@ -17,6 +17,8 @@
|
|
||||||
#include "hw/acpi/aml-build.h"
|
|
||||||
#include "hw/hotplug.h"
|
|
||||||
|
|
||||||
+#define ACPI_CPU_HOTPLUG_REG_LEN 12
|
|
||||||
+
|
|
||||||
typedef struct AcpiCpuStatus {
|
|
||||||
struct CPUState *cpu;
|
|
||||||
uint64_t arch_id;
|
|
||||||
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
|
|
||||||
index f99efad7a3..e702ff1e18 100644
|
|
||||||
--- a/include/hw/acpi/generic_event_device.h
|
|
||||||
+++ b/include/hw/acpi/generic_event_device.h
|
|
||||||
@@ -62,6 +62,7 @@
|
|
||||||
#include "hw/sysbus.h"
|
|
||||||
#include "hw/acpi/memory_hotplug.h"
|
|
||||||
#include "hw/arm/virt.h"
|
|
||||||
+#include "hw/acpi/cpu.h"
|
|
||||||
|
|
||||||
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
|
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@
|
|
||||||
*/
|
|
||||||
#define ACPI_GED_MEM_HOTPLUG_EVT 0x1
|
|
||||||
#define ACPI_GED_PWR_DOWN_EVT 0x2
|
|
||||||
+#define ACPI_GED_CPU_HOTPLUG_EVT 0x4
|
|
||||||
|
|
||||||
typedef struct GEDState {
|
|
||||||
MemoryRegion io;
|
|
||||||
@@ -93,6 +95,8 @@ typedef struct AcpiGedState {
|
|
||||||
SysBusDevice parent_obj;
|
|
||||||
MemHotplugState memhp_state;
|
|
||||||
MemoryRegion container_memhp;
|
|
||||||
+ CPUHotplugState cpuhp_state;
|
|
||||||
+ MemoryRegion container_cpuhp;
|
|
||||||
GEDState ged_state;
|
|
||||||
uint32_t ged_event_bitmap;
|
|
||||||
qemu_irq irq;
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
From 0288d98f0ef4d17a73cf2bad1b928cd7c044e318 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 13:40:44 +0800
|
|
||||||
Subject: [PATCH] acpi/madt: Add pre-sizing capability to MADT GICC struct
|
|
||||||
|
|
||||||
The count of possible CPUs is exposed to guest through the count
|
|
||||||
of MADT GICC struct, so we should pre-sizing MADT GICC too.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt-acpi-build.c | 26 +++++++++++++++++++++-----
|
|
||||||
include/hw/acpi/acpi-defs.h | 1 +
|
|
||||||
2 files changed, 22 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
|
||||||
index dbe9acb148..efac788ba1 100644
|
|
||||||
--- a/hw/arm/virt-acpi-build.c
|
|
||||||
+++ b/hw/arm/virt-acpi-build.c
|
|
||||||
@@ -678,6 +678,13 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
|
||||||
const MemMapEntry *memmap = vms->memmap;
|
|
||||||
AcpiMadtGenericCpuInterface *gicc = acpi_data_push(entry, sizeof(*gicc));
|
|
||||||
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(uid));
|
|
||||||
+ static bool pmu;
|
|
||||||
+
|
|
||||||
+ if (uid == 0) {
|
|
||||||
+ pmu = arm_feature(&armcpu->env, ARM_FEATURE_PMU);
|
|
||||||
+ }
|
|
||||||
+ /* FEATURE_PMU should be all enabled or disabled for CPUs */
|
|
||||||
+ assert(!armcpu || arm_feature(&armcpu->env, ARM_FEATURE_PMU) == pmu);
|
|
||||||
|
|
||||||
gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
|
|
||||||
gicc->length = sizeof(*gicc);
|
|
||||||
@@ -687,11 +694,15 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
|
||||||
gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
|
|
||||||
}
|
|
||||||
gicc->cpu_interface_number = cpu_to_le32(uid);
|
|
||||||
- gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
|
|
||||||
+ gicc->arm_mpidr = possible_cpus->cpus[uid].arch_id;
|
|
||||||
gicc->uid = cpu_to_le32(uid);
|
|
||||||
- gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
|
|
||||||
+ if (armcpu) {
|
|
||||||
+ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
|
|
||||||
+ } else {
|
|
||||||
+ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_DISABLED);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
|
|
||||||
+ if (pmu) {
|
|
||||||
gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
|
|
||||||
}
|
|
||||||
if (vms->virt) {
|
|
||||||
@@ -704,12 +715,17 @@ static void
|
|
||||||
build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
{
|
|
||||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
|
||||||
+ MachineClass *mc = MACHINE_GET_CLASS(vms);
|
|
||||||
+ MachineState *ms = MACHINE(vms);
|
|
||||||
+ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
|
|
||||||
int madt_start = table_data->len;
|
|
||||||
const MemMapEntry *memmap = vms->memmap;
|
|
||||||
const int *irqmap = vms->irqmap;
|
|
||||||
AcpiMultipleApicTable *madt;
|
|
||||||
AcpiMadtGenericDistributor *gicd;
|
|
||||||
AcpiMadtGenericMsiFrame *gic_msi;
|
|
||||||
+ /* The MADT GICC numbers */
|
|
||||||
+ int num_cpu = vms->smp_cpus;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
madt = acpi_data_push(table_data, sizeof *madt);
|
|
||||||
@@ -720,8 +736,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
|
|
||||||
gicd->version = vms->gic_version;
|
|
||||||
|
|
||||||
- for (i = 0; i < vms->smp_cpus; i++) {
|
|
||||||
- virt_madt_cpu_entry(NULL, i, NULL, table_data);
|
|
||||||
+ for (i = 0; i < num_cpu; i++) {
|
|
||||||
+ virt_madt_cpu_entry(NULL, i, possible_cpus, table_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vms->gic_version == 3) {
|
|
||||||
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
|
|
||||||
index 39ae91d3b8..6bfa7f9152 100644
|
|
||||||
--- a/include/hw/acpi/acpi-defs.h
|
|
||||||
+++ b/include/hw/acpi/acpi-defs.h
|
|
||||||
@@ -306,6 +306,7 @@ typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface;
|
|
||||||
|
|
||||||
/* GICC CPU Interface Flags */
|
|
||||||
#define ACPI_MADT_GICC_ENABLED 1
|
|
||||||
+#define ACPI_MADT_GICC_DISABLED 0
|
|
||||||
|
|
||||||
struct AcpiMadtGenericDistributor {
|
|
||||||
ACPI_SUB_HEADER_DEF
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
From a3097eed8b642dc6fe891112340821e869b90cc2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Mon, 13 Jan 2020 19:02:20 +0800
|
|
||||||
Subject: [PATCH] acpi/madt: Factor out the building of MADT GICC struct
|
|
||||||
|
|
||||||
To realize CPU hotplug, the cpus aml within ACPI DSDT should contain
|
|
||||||
_MAT mathod, which is equal to the GICC struct in ACPI MADT. Factor
|
|
||||||
out the GICC building code from ACPI MADT and reuse it in build_cpus_aml.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt-acpi-build.c | 51 +++++++++++++++++++++++-----------------
|
|
||||||
include/hw/arm/virt.h | 3 +++
|
|
||||||
2 files changed, 32 insertions(+), 22 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
|
||||||
index f48733d9f2..4b6aace433 100644
|
|
||||||
--- a/hw/arm/virt-acpi-build.c
|
|
||||||
+++ b/hw/arm/virt-acpi-build.c
|
|
||||||
@@ -664,6 +664,34 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
table_data->len - gtdt_start, 2, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
|
||||||
+ const CPUArchIdList *possible_cpus, GArray *entry)
|
|
||||||
+{
|
|
||||||
+ VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
|
|
||||||
+ const MemMapEntry *memmap = vms->memmap;
|
|
||||||
+ AcpiMadtGenericCpuInterface *gicc = acpi_data_push(entry, sizeof(*gicc));
|
|
||||||
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(uid));
|
|
||||||
+
|
|
||||||
+ gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
|
|
||||||
+ gicc->length = sizeof(*gicc);
|
|
||||||
+ if (vms->gic_version == 2) {
|
|
||||||
+ gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
|
|
||||||
+ gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
|
|
||||||
+ gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
|
|
||||||
+ }
|
|
||||||
+ gicc->cpu_interface_number = cpu_to_le32(uid);
|
|
||||||
+ gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
|
|
||||||
+ gicc->uid = cpu_to_le32(uid);
|
|
||||||
+ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
|
|
||||||
+
|
|
||||||
+ if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
|
|
||||||
+ gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
|
|
||||||
+ }
|
|
||||||
+ if (vms->virt) {
|
|
||||||
+ gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ));
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* MADT */
|
|
||||||
static void
|
|
||||||
build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
@@ -686,28 +714,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
gicd->version = vms->gic_version;
|
|
||||||
|
|
||||||
for (i = 0; i < vms->smp_cpus; i++) {
|
|
||||||
- AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
|
|
||||||
- sizeof(*gicc));
|
|
||||||
- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
|
|
||||||
-
|
|
||||||
- gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
|
|
||||||
- gicc->length = sizeof(*gicc);
|
|
||||||
- if (vms->gic_version == 2) {
|
|
||||||
- gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
|
|
||||||
- gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
|
|
||||||
- gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
|
|
||||||
- }
|
|
||||||
- gicc->cpu_interface_number = cpu_to_le32(i);
|
|
||||||
- gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
|
|
||||||
- gicc->uid = cpu_to_le32(i);
|
|
||||||
- gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
|
|
||||||
-
|
|
||||||
- if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
|
|
||||||
- gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
|
|
||||||
- }
|
|
||||||
- if (vms->virt) {
|
|
||||||
- gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ));
|
|
||||||
- }
|
|
||||||
+ virt_madt_cpu_entry(NULL, i, NULL, table_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vms->gic_version == 3) {
|
|
||||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
|
||||||
index 3dfefca93b..6b1f10b231 100644
|
|
||||||
--- a/include/hw/arm/virt.h
|
|
||||||
+++ b/include/hw/arm/virt.h
|
|
||||||
@@ -37,6 +37,7 @@
|
|
||||||
#include "hw/block/flash.h"
|
|
||||||
#include "sysemu/kvm.h"
|
|
||||||
#include "hw/intc/arm_gicv3_common.h"
|
|
||||||
+#include "hw/acpi/acpi_dev_interface.h"
|
|
||||||
|
|
||||||
#define NUM_GICV2M_SPIS 64
|
|
||||||
#define NUM_VIRTIO_TRANSPORTS 32
|
|
||||||
@@ -154,6 +155,8 @@ typedef struct {
|
|
||||||
OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE)
|
|
||||||
|
|
||||||
void virt_acpi_setup(VirtMachineState *vms);
|
|
||||||
+void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
|
||||||
+ const CPUArchIdList *cpu_list, GArray *entry);
|
|
||||||
|
|
||||||
/* Return the number of used redistributor regions */
|
|
||||||
static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
From ea7a395de920cfecd9bf99f0cf55914d47718edf Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiadong Zeng <zengjiadong@phytium.com.cn>
|
|
||||||
Date: Thu, 11 Nov 2021 14:25:38 +0800
|
|
||||||
Subject: [PATCH] add Phytium's CPU models: FT-2000+ and Tengyun-S2500.
|
|
||||||
|
|
||||||
Signed-off-by: Jiadong Zeng <zengjiadong@phytium.com.cn>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 2 ++
|
|
||||||
target/arm/cpu64.c | 28 ++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 30 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 7506d0ff32..0e46260116 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -195,6 +195,8 @@ static const char *valid_cpus[] = {
|
|
||||||
ARM_CPU_TYPE_NAME("cortex-a57"),
|
|
||||||
ARM_CPU_TYPE_NAME("cortex-a72"),
|
|
||||||
ARM_CPU_TYPE_NAME("Kunpeng-920"),
|
|
||||||
+ ARM_CPU_TYPE_NAME("FT-2000+"),
|
|
||||||
+ ARM_CPU_TYPE_NAME("Tengyun-S2500"),
|
|
||||||
ARM_CPU_TYPE_NAME("host"),
|
|
||||||
ARM_CPU_TYPE_NAME("max"),
|
|
||||||
};
|
|
||||||
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
|
|
||||||
index a1649f8844..4cf5b89db0 100644
|
|
||||||
--- a/target/arm/cpu64.c
|
|
||||||
+++ b/target/arm/cpu64.c
|
|
||||||
@@ -327,6 +327,32 @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
|
|
||||||
error_propagate(errp, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void aarch64_max_ft2000plus_initfn(Object *obj)
|
|
||||||
+{
|
|
||||||
+ ARMCPU *cpu = ARM_CPU(obj);
|
|
||||||
+
|
|
||||||
+ if (kvm_enabled()) {
|
|
||||||
+ kvm_arm_set_cpu_features_from_host(cpu);
|
|
||||||
+ kvm_arm_add_vcpu_properties(obj);
|
|
||||||
+ } else {
|
|
||||||
+ aarch64_a72_initfn(obj);
|
|
||||||
+ cpu->midr = 0x70186622;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void aarch64_max_tengyun_s2500_initfn(Object *obj)
|
|
||||||
+{
|
|
||||||
+ ARMCPU *cpu = ARM_CPU(obj);
|
|
||||||
+
|
|
||||||
+ if (kvm_enabled()) {
|
|
||||||
+ kvm_arm_set_cpu_features_from_host(cpu);
|
|
||||||
+ kvm_arm_add_vcpu_properties(obj);
|
|
||||||
+ } else {
|
|
||||||
+ aarch64_a72_initfn(obj);
|
|
||||||
+ cpu->midr = 0x70186632;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
|
|
||||||
* otherwise, a CPU with as many features enabled as our emulation supports.
|
|
||||||
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
|
|
||||||
@@ -442,6 +468,8 @@ static const ARMCPUInfo aarch64_cpus[] = {
|
|
||||||
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
|
|
||||||
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
|
|
||||||
{ .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn },
|
|
||||||
+ { .name = "FT-2000+", .initfn = aarch64_max_ft2000plus_initfn },
|
|
||||||
+ { .name = "Tengyun-S2500", .initfn = aarch64_max_tengyun_s2500_initfn },
|
|
||||||
{ .name = "max", .initfn = aarch64_max_initfn },
|
|
||||||
{ .name = NULL }
|
|
||||||
};
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
From 929d29ec7bf9dd6ec3802bea2148a041ff30d59b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
Date: Tue, 14 Apr 2020 21:17:09 +0800
|
|
||||||
Subject: [PATCH] aio-wait: delegate polling of main AioContext if BQL not held
|
|
||||||
|
|
||||||
Any thread that is not a iothread returns NULL for qemu_get_current_aio_context().
|
|
||||||
As a result, it would also return true for
|
|
||||||
in_aio_context_home_thread(qemu_get_aio_context()), causing
|
|
||||||
AIO_WAIT_WHILE to invoke aio_poll() directly. This is incorrect
|
|
||||||
if the BQL is not held, because aio_poll() does not expect to
|
|
||||||
run concurrently from multiple threads, and it can actually
|
|
||||||
happen when savevm writes to the vmstate file from the
|
|
||||||
migration thread.
|
|
||||||
|
|
||||||
Therefore, restrict in_aio_context_home_thread to return true
|
|
||||||
for the main AioContext only if the BQL is held.
|
|
||||||
|
|
||||||
The function is moved to aio-wait.h because it is mostly used
|
|
||||||
there and to avoid a circular reference between main-loop.h
|
|
||||||
and block/aio.h.
|
|
||||||
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
Message-Id: <20200407140746.8041-5-pbonzini@redhat.com>
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
include/block/aio-wait.h | 22 ++++++++++++++++++++++
|
|
||||||
include/block/aio.h | 29 ++++++++++-------------------
|
|
||||||
2 files changed, 32 insertions(+), 19 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
|
|
||||||
index afeeb18f..716d2639 100644
|
|
||||||
--- a/include/block/aio-wait.h
|
|
||||||
+++ b/include/block/aio-wait.h
|
|
||||||
@@ -26,6 +26,7 @@
|
|
||||||
#define QEMU_AIO_WAIT_H
|
|
||||||
|
|
||||||
#include "block/aio.h"
|
|
||||||
+#include "qemu/main-loop.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AioWait:
|
|
||||||
@@ -124,4 +125,25 @@ void aio_wait_kick(void);
|
|
||||||
*/
|
|
||||||
void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * in_aio_context_home_thread:
|
|
||||||
+ * @ctx: the aio context
|
|
||||||
+ *
|
|
||||||
+ * Return whether we are running in the thread that normally runs @ctx. Note
|
|
||||||
+ * that acquiring/releasing ctx does not affect the outcome, each AioContext
|
|
||||||
+ * still only has one home thread that is responsible for running it.
|
|
||||||
+ */
|
|
||||||
+static inline bool in_aio_context_home_thread(AioContext *ctx)
|
|
||||||
+{
|
|
||||||
+ if (ctx == qemu_get_current_aio_context()) {
|
|
||||||
+ return true;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (ctx == qemu_get_aio_context()) {
|
|
||||||
+ return qemu_mutex_iothread_locked();
|
|
||||||
+ } else {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
#endif /* QEMU_AIO_WAIT_H */
|
|
||||||
diff --git a/include/block/aio.h b/include/block/aio.h
|
|
||||||
index 6b0d52f7..9d28e247 100644
|
|
||||||
--- a/include/block/aio.h
|
|
||||||
+++ b/include/block/aio.h
|
|
||||||
@@ -60,12 +60,16 @@ struct AioContext {
|
|
||||||
QLIST_HEAD(, AioHandler) aio_handlers;
|
|
||||||
|
|
||||||
/* Used to avoid unnecessary event_notifier_set calls in aio_notify;
|
|
||||||
- * accessed with atomic primitives. If this field is 0, everything
|
|
||||||
- * (file descriptors, bottom halves, timers) will be re-evaluated
|
|
||||||
- * before the next blocking poll(), thus the event_notifier_set call
|
|
||||||
- * can be skipped. If it is non-zero, you may need to wake up a
|
|
||||||
- * concurrent aio_poll or the glib main event loop, making
|
|
||||||
- * event_notifier_set necessary.
|
|
||||||
+ * only written from the AioContext home thread, or under the BQL in
|
|
||||||
+ * the case of the main AioContext. However, it is read from any
|
|
||||||
+ * thread so it is still accessed with atomic primitives.
|
|
||||||
+ *
|
|
||||||
+ * If this field is 0, everything (file descriptors, bottom halves,
|
|
||||||
+ * timers) will be re-evaluated before the next blocking poll() or
|
|
||||||
+ * io_uring wait; therefore, the event_notifier_set call can be
|
|
||||||
+ * skipped. If it is non-zero, you may need to wake up a concurrent
|
|
||||||
+ * aio_poll or the glib main event loop, making event_notifier_set
|
|
||||||
+ * necessary.
|
|
||||||
*
|
|
||||||
* Bit 0 is reserved for GSource usage of the AioContext, and is 1
|
|
||||||
* between a call to aio_ctx_prepare and the next call to aio_ctx_check.
|
|
||||||
@@ -580,19 +584,6 @@ void aio_co_enter(AioContext *ctx, struct Coroutine *co);
|
|
||||||
*/
|
|
||||||
AioContext *qemu_get_current_aio_context(void);
|
|
||||||
|
|
||||||
-/**
|
|
||||||
- * in_aio_context_home_thread:
|
|
||||||
- * @ctx: the aio context
|
|
||||||
- *
|
|
||||||
- * Return whether we are running in the thread that normally runs @ctx. Note
|
|
||||||
- * that acquiring/releasing ctx does not affect the outcome, each AioContext
|
|
||||||
- * still only has one home thread that is responsible for running it.
|
|
||||||
- */
|
|
||||||
-static inline bool in_aio_context_home_thread(AioContext *ctx)
|
|
||||||
-{
|
|
||||||
- return ctx == qemu_get_current_aio_context();
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
/**
|
|
||||||
* aio_context_setup:
|
|
||||||
* @ctx: the aio context
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
From 3bdd21c4b7d80cacc6b5f1b26ab52ef3a0aceb06 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Peter Xu <peterx@redhat.com>
|
|
||||||
Date: Wed, 16 Oct 2019 10:29:32 +0800
|
|
||||||
Subject: [PATCH 7/8] apic: Use 32bit APIC ID for migration instance ID
|
|
||||||
|
|
||||||
Migration is silently broken now with x2apic config like this:
|
|
||||||
|
|
||||||
-smp 200,maxcpus=288,sockets=2,cores=72,threads=2 \
|
|
||||||
-device intel-iommu,intremap=on,eim=on
|
|
||||||
|
|
||||||
After migration, the guest kernel could hang at anything, due to
|
|
||||||
x2apic bit not migrated correctly in IA32_APIC_BASE on some vcpus, so
|
|
||||||
any operations related to x2apic could be broken then (e.g., RDMSR on
|
|
||||||
x2apic MSRs could fail because KVM would think that the vcpu hasn't
|
|
||||||
enabled x2apic at all).
|
|
||||||
|
|
||||||
The issue is that the x2apic bit was never applied correctly for vcpus
|
|
||||||
whose ID > 255 when migrate completes, and that's because when we
|
|
||||||
migrate APIC we use the APICCommonState.id as instance ID of the
|
|
||||||
migration stream, while that's too short for x2apic.
|
|
||||||
|
|
||||||
Let's use the newly introduced initial_apic_id for that.
|
|
||||||
|
|
||||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
|
||||||
Reviewed-by: Juan Quintela <quintela@redhat.com>
|
|
||||||
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
|
|
||||||
Signed-off-by: Juan Quintela <quintela@redhat.com>
|
|
||||||
---
|
|
||||||
hw/intc/apic_common.c | 5 ++++-
|
|
||||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
|
|
||||||
index 07adba0..2c0cb1e 100644
|
|
||||||
--- a/hw/intc/apic_common.c
|
|
||||||
+++ b/hw/intc/apic_common.c
|
|
||||||
@@ -313,7 +313,10 @@ static void apic_common_realize(DeviceState *dev, Error **errp)
|
|
||||||
APICCommonState *s = APIC_COMMON(dev);
|
|
||||||
APICCommonClass *info;
|
|
||||||
static DeviceState *vapic;
|
|
||||||
- uint32_t instance_id = s->id;
|
|
||||||
+ uint32_t instance_id = s->initial_apic_id;
|
|
||||||
+
|
|
||||||
+ /* Normally initial APIC ID should be no more than hundreds */
|
|
||||||
+ assert(instance_id != VMSTATE_INSTANCE_ID_ANY);
|
|
||||||
|
|
||||||
info = APIC_COMMON_GET_CLASS(s);
|
|
||||||
info->realize(dev, errp);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
From 6d795b30ff09bc1f799daa454f776d682cc77197 Mon Sep 17 00:00:00 2001
|
|
||||||
From: zhanghao1 <zhanghao1@kylinos.cn>
|
|
||||||
Date: Tue, 11 May 2021 20:17:16 +0800
|
|
||||||
Subject: [PATCH] arm/cpu: Fixed function undefined error at compile time under
|
|
||||||
arm
|
|
||||||
|
|
||||||
Add the compilation option CONFIG_KVM while using
|
|
||||||
"kvm_arm_cpu_feature_supported" and "kvm_arm_get_one_reg".
|
|
||||||
In arm, the default value of CONFIG_KVM is no.
|
|
||||||
|
|
||||||
While the target is arm, the compilation fails because
|
|
||||||
the function "kvm_arm_cpu_feature_supporte" is declared
|
|
||||||
or the function "kvm_arm_get_one_reg" is not defined.
|
|
||||||
|
|
||||||
Signed-off-by: zhanghao1 <zhanghao1@kylinos.cn>
|
|
||||||
---
|
|
||||||
target/arm/helper.c | 4 ++++
|
|
||||||
target/arm/kvm_arm.h | 4 ++++
|
|
||||||
2 files changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/target/arm/helper.c b/target/arm/helper.c
|
|
||||||
index bddd355fa0..9d2b2659f6 100644
|
|
||||||
--- a/target/arm/helper.c
|
|
||||||
+++ b/target/arm/helper.c
|
|
||||||
@@ -284,6 +284,7 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
|
|
||||||
|
|
||||||
newval = read_raw_cp_reg(&cpu->env, ri);
|
|
||||||
if (kvm_sync) {
|
|
||||||
+#ifdef CONFIG_KVM
|
|
||||||
if (is_id_reg(ri)) {
|
|
||||||
/* Only sync if we can sync to KVM successfully. */
|
|
||||||
uint64_t oldval;
|
|
||||||
@@ -306,6 +307,7 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
|
|
||||||
|
|
||||||
kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval);
|
|
||||||
} else {
|
|
||||||
+#endif
|
|
||||||
/*
|
|
||||||
* Only sync if the previous list->cpustate sync succeeded.
|
|
||||||
* Rather than tracking the success/failure state for every
|
|
||||||
@@ -324,7 +326,9 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
|
|
||||||
}
|
|
||||||
|
|
||||||
write_raw_cp_reg(&cpu->env, ri, newval);
|
|
||||||
+#ifdef CONFIG_KVM
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
cpu->cpreg_values[i] = newval;
|
|
||||||
}
|
|
||||||
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
|
|
||||||
index 49e80878f4..a223967d4d 100644
|
|
||||||
--- a/target/arm/kvm_arm.h
|
|
||||||
+++ b/target/arm/kvm_arm.h
|
|
||||||
@@ -312,6 +312,10 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
|
|
||||||
|
|
||||||
static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
|
|
||||||
|
|
||||||
+static inline bool kvm_arm_cpu_feature_supported(void) {
|
|
||||||
+ return false;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
|
|
||||||
{
|
|
||||||
return -ENOENT;
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
From d8e0b51447d8c64788cd7f9b0fa75c4ccb06f8eb Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 10:17:27 +0800
|
|
||||||
Subject: [PATCH] arm/cpu: assign arm_get_arch_id handler to get_arch_id hook
|
|
||||||
|
|
||||||
This hook will be called in get_cpu_status, which is called
|
|
||||||
during cpu hotplug.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
target/arm/cpu.c | 8 ++++++++
|
|
||||||
1 file changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
|
|
||||||
index 39bbe7e2d7..1ccb30e5eb 100644
|
|
||||||
--- a/target/arm/cpu.c
|
|
||||||
+++ b/target/arm/cpu.c
|
|
||||||
@@ -2575,6 +2575,13 @@ static gchar *arm_gdb_arch_name(CPUState *cs)
|
|
||||||
return g_strdup("arm");
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int64_t arm_cpu_get_arch_id(CPUState *cs)
|
|
||||||
+{
|
|
||||||
+ ARMCPU *cpu = ARM_CPU(cs);
|
|
||||||
+
|
|
||||||
+ return cpu->mp_affinity;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void arm_cpu_class_init(ObjectClass *oc, void *data)
|
|
||||||
{
|
|
||||||
ARMCPUClass *acc = ARM_CPU_CLASS(oc);
|
|
||||||
@@ -2596,6 +2603,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
|
|
||||||
cc->synchronize_from_tb = arm_cpu_synchronize_from_tb;
|
|
||||||
cc->gdb_read_register = arm_cpu_gdb_read_register;
|
|
||||||
cc->gdb_write_register = arm_cpu_gdb_write_register;
|
|
||||||
+ cc->get_arch_id = arm_cpu_get_arch_id;
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
cc->do_interrupt = arm_cpu_do_interrupt;
|
|
||||||
cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
From b4bab3bf6a75d97d2f1098c4dc52d35ced003c70 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
Date: Mon, 13 Jan 2020 17:01:11 +0800
|
|
||||||
Subject: [PATCH] arm/translate-a64: fix uninitialized variable warning
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
target/arm/translate-a64.c: In function 'disas_crypto_three_reg_sha512':
|
|
||||||
target/arm/translate-a64.c:13625:9: error: 'genfn' may be used uninitialized in this function [-Werror=maybe-uninitialized]
|
|
||||||
genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
|
|
||||||
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
qemu/target/arm/translate-a64.c:13609:8: error: 'feature' may be used uninitialized in this function [-Werror=maybe-uninitialized]
|
|
||||||
if (!feature) {
|
|
||||||
|
|
||||||
Reported-by: Euler Robot <euler.robot@huawei.com>
|
|
||||||
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
---
|
|
||||||
target/arm/translate-a64.c | 2 ++
|
|
||||||
1 file changed, 2 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
|
|
||||||
index dcdeb801..5f423d5d 100644
|
|
||||||
--- a/target/arm/translate-a64.c
|
|
||||||
+++ b/target/arm/translate-a64.c
|
|
||||||
@@ -13767,6 +13767,8 @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
|
|
||||||
feature = dc_isar_feature(aa64_sha3, s);
|
|
||||||
genfn = NULL;
|
|
||||||
break;
|
|
||||||
+ default:
|
|
||||||
+ g_assert_not_reached();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (opcode) {
|
|
||||||
--
|
|
||||||
2.18.1
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
From 6d287b3f1d961cc4adda1c6a452f41db84466f5a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 3 Apr 2020 16:16:18 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Add CPU hotplug framework
|
|
||||||
|
|
||||||
Establish the CPU hotplug framework for arm/virt, we will add
|
|
||||||
necessary code legs to this framework gradually to realize CPU
|
|
||||||
hotplug finally.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 19 ++++++++++++++++++-
|
|
||||||
1 file changed, 18 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index d09a5773df..0bd37af26c 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -2077,11 +2077,25 @@ out:
|
|
||||||
error_propagate(errp, local_err);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|
||||||
+ DeviceState *dev, Error **errp)
|
|
||||||
+{
|
|
||||||
+ /* Currently nothing to do */
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void virt_cpu_plug(HotplugHandler *hotplug_dev,
|
|
||||||
+ DeviceState *dev, Error **errp)
|
|
||||||
+{
|
|
||||||
+ /* Currently nothing to do */
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
|
||||||
DeviceState *dev, Error **errp)
|
|
||||||
{
|
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
|
||||||
virt_memory_pre_plug(hotplug_dev, dev, errp);
|
|
||||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
|
||||||
+ virt_cpu_pre_plug(hotplug_dev, dev, errp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2098,6 +2112,8 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
|
|
||||||
}
|
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
|
||||||
virt_memory_plug(hotplug_dev, dev, errp);
|
|
||||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
|
||||||
+ virt_cpu_plug(hotplug_dev, dev, errp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2112,7 +2128,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
|
|
||||||
DeviceState *dev)
|
|
||||||
{
|
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE) ||
|
|
||||||
- (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) {
|
|
||||||
+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
|
|
||||||
+ object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
|
||||||
return HOTPLUG_HANDLER(machine);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,219 +0,0 @@
|
|||||||
From cde57fcae2ed16a10e1ef7f2da0ec368883988ba Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Mon, 6 Apr 2020 10:54:35 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Add CPU topology support
|
|
||||||
|
|
||||||
The CPU topology specified by user (through -smp options) is used in
|
|
||||||
ACPI PPTT. Now we will use this information to locate which CPU to
|
|
||||||
plug or unplug.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 68 +++++++++++++++++++++++++++++++++++++--
|
|
||||||
include/hw/arm/topology.h | 61 +++++++++++++++++++++++++++++++++++
|
|
||||||
target/arm/cpu.c | 3 ++
|
|
||||||
target/arm/cpu.h | 3 ++
|
|
||||||
4 files changed, 133 insertions(+), 2 deletions(-)
|
|
||||||
create mode 100644 include/hw/arm/topology.h
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 0bd37af26c..64532b61b2 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -36,6 +36,7 @@
|
|
||||||
#include "hw/sysbus.h"
|
|
||||||
#include "hw/arm/boot.h"
|
|
||||||
#include "hw/arm/primecell.h"
|
|
||||||
+#include "hw/arm/topology.h"
|
|
||||||
#include "hw/arm/virt.h"
|
|
||||||
#include "hw/block/flash.h"
|
|
||||||
#include "hw/vfio/vfio-calxeda-xgmac.h"
|
|
||||||
@@ -2020,6 +2021,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
|
||||||
int n;
|
|
||||||
unsigned int max_cpus = ms->smp.max_cpus;
|
|
||||||
VirtMachineState *vms = VIRT_MACHINE(ms);
|
|
||||||
+ ARMCPUTopoInfo topo;
|
|
||||||
|
|
||||||
if (ms->possible_cpus) {
|
|
||||||
assert(ms->possible_cpus->len == max_cpus);
|
|
||||||
@@ -2031,10 +2033,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
|
||||||
ms->possible_cpus->len = max_cpus;
|
|
||||||
for (n = 0; n < ms->possible_cpus->len; n++) {
|
|
||||||
ms->possible_cpus->cpus[n].type = ms->cpu_type;
|
|
||||||
+ ms->possible_cpus->cpus[n].vcpus_count = 1;
|
|
||||||
ms->possible_cpus->cpus[n].arch_id =
|
|
||||||
virt_cpu_mp_affinity(vms, n);
|
|
||||||
+
|
|
||||||
+ topo_ids_from_idx(n, ms->smp.cores, ms->smp.threads, &topo);
|
|
||||||
+ ms->possible_cpus->cpus[n].props.has_socket_id = true;
|
|
||||||
+ ms->possible_cpus->cpus[n].props.socket_id = topo.pkg_id;
|
|
||||||
+ ms->possible_cpus->cpus[n].props.has_core_id = true;
|
|
||||||
+ ms->possible_cpus->cpus[n].props.core_id = topo.core_id;
|
|
||||||
ms->possible_cpus->cpus[n].props.has_thread_id = true;
|
|
||||||
- ms->possible_cpus->cpus[n].props.thread_id = n;
|
|
||||||
+ ms->possible_cpus->cpus[n].props.thread_id = topo.smt_id;
|
|
||||||
}
|
|
||||||
return ms->possible_cpus;
|
|
||||||
}
|
|
||||||
@@ -2080,7 +2089,62 @@ out:
|
|
||||||
static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|
||||||
DeviceState *dev, Error **errp)
|
|
||||||
{
|
|
||||||
- /* Currently nothing to do */
|
|
||||||
+ CPUState *cs = CPU(dev);
|
|
||||||
+ ARMCPUTopoInfo topo;
|
|
||||||
+ ARMCPU *cpu = ARM_CPU(dev);
|
|
||||||
+ MachineState *ms = MACHINE(hotplug_dev);
|
|
||||||
+ int smp_cores = ms->smp.cores;
|
|
||||||
+ int smp_threads = ms->smp.threads;
|
|
||||||
+
|
|
||||||
+ /* if cpu idx is not set, set it based on socket/core/thread properties */
|
|
||||||
+ if (cs->cpu_index == UNASSIGNED_CPU_INDEX) {
|
|
||||||
+ int max_socket = ms->smp.max_cpus / smp_threads / smp_cores;
|
|
||||||
+ if (cpu->socket_id < 0 || cpu->socket_id >= max_socket) {
|
|
||||||
+ error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u",
|
|
||||||
+ cpu->socket_id, max_socket - 1);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ if (cpu->core_id < 0 || cpu->core_id >= smp_cores) {
|
|
||||||
+ error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u",
|
|
||||||
+ cpu->core_id, smp_cores - 1);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ if (cpu->thread_id < 0 || cpu->thread_id >= smp_threads) {
|
|
||||||
+ error_setg(errp, "Invalid CPU thread-id: %u must be in range 0:%u",
|
|
||||||
+ cpu->thread_id, smp_threads - 1);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ topo.pkg_id = cpu->socket_id;
|
|
||||||
+ topo.core_id = cpu->core_id;
|
|
||||||
+ topo.smt_id = cpu->thread_id;
|
|
||||||
+ cs->cpu_index = idx_from_topo_ids(smp_cores, smp_threads, &topo);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* if 'address' properties socket-id/core-id/thread-id are not set, set them
|
|
||||||
+ * so that machine_query_hotpluggable_cpus would show correct values
|
|
||||||
+ */
|
|
||||||
+ topo_ids_from_idx(cs->cpu_index, smp_cores, smp_threads, &topo);
|
|
||||||
+ if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) {
|
|
||||||
+ error_setg(errp, "property socket-id: %u doesn't match set idx:"
|
|
||||||
+ " 0x%x (socket-id: %u)", cpu->socket_id, cs->cpu_index, topo.pkg_id);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ cpu->socket_id = topo.pkg_id;
|
|
||||||
+
|
|
||||||
+ if (cpu->core_id != -1 && cpu->core_id != topo.core_id) {
|
|
||||||
+ error_setg(errp, "property core-id: %u doesn't match set idx:"
|
|
||||||
+ " 0x%x (core-id: %u)", cpu->core_id, cs->cpu_index, topo.core_id);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ cpu->core_id = topo.core_id;
|
|
||||||
+
|
|
||||||
+ if (cpu->thread_id != -1 && cpu->thread_id != topo.smt_id) {
|
|
||||||
+ error_setg(errp, "property thread-id: %u doesn't match set idx:"
|
|
||||||
+ " 0x%x (thread-id: %u)", cpu->thread_id, cs->cpu_index, topo.smt_id);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ cpu->thread_id = topo.smt_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virt_cpu_plug(HotplugHandler *hotplug_dev,
|
|
||||||
diff --git a/include/hw/arm/topology.h b/include/hw/arm/topology.h
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..a3e5f436c5
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/hw/arm/topology.h
|
|
||||||
@@ -0,0 +1,61 @@
|
|
||||||
+/*
|
|
||||||
+ * ARM CPU topology data structures and functions
|
|
||||||
+ *
|
|
||||||
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO.,LTD.
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or modify
|
|
||||||
+ * it under the terms of the GNU General Public License as published by
|
|
||||||
+ * the Free Software Foundation; either version 2 of the License, or
|
|
||||||
+ * (at your option) any later version.
|
|
||||||
+ *
|
|
||||||
+ * This program is distributed in the hope that it will be useful,
|
|
||||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
+ * GNU General Public License for more details.
|
|
||||||
+ *
|
|
||||||
+ * You should have received a copy of the GNU General Public License along
|
|
||||||
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef HW_ARM_TOPOLOGY_H
|
|
||||||
+#define HW_ARM_TOPOLOGY_H
|
|
||||||
+
|
|
||||||
+typedef struct ARMCPUTopoInfo {
|
|
||||||
+ unsigned pkg_id;
|
|
||||||
+ unsigned core_id;
|
|
||||||
+ unsigned smt_id;
|
|
||||||
+} ARMCPUTopoInfo;
|
|
||||||
+
|
|
||||||
+/* Calculate (contiguous) CPU index based on topology */
|
|
||||||
+static inline unsigned idx_from_topo_ids(unsigned nr_cores,
|
|
||||||
+ unsigned nr_threads,
|
|
||||||
+ const ARMCPUTopoInfo *topo)
|
|
||||||
+{
|
|
||||||
+ assert(nr_cores > 0);
|
|
||||||
+ assert(nr_threads > 0);
|
|
||||||
+ assert(topo != NULL);
|
|
||||||
+
|
|
||||||
+ return topo->pkg_id * nr_cores * nr_threads +
|
|
||||||
+ topo->core_id * nr_threads +
|
|
||||||
+ topo->smt_id;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* Calculate thread/core/package topology
|
|
||||||
+ * based on (contiguous) CPU index
|
|
||||||
+ */
|
|
||||||
+static inline void topo_ids_from_idx(unsigned cpu_index,
|
|
||||||
+ unsigned nr_cores,
|
|
||||||
+ unsigned nr_threads,
|
|
||||||
+ ARMCPUTopoInfo *topo)
|
|
||||||
+{
|
|
||||||
+ assert(nr_cores > 0);
|
|
||||||
+ assert(nr_threads > 0);
|
|
||||||
+ assert(topo != NULL);
|
|
||||||
+
|
|
||||||
+ topo->smt_id = cpu_index % nr_threads;
|
|
||||||
+ topo->core_id = cpu_index / nr_threads % nr_cores;
|
|
||||||
+ topo->pkg_id = cpu_index / nr_threads / nr_cores;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif /* HW_ARM_TOPOLOGY_H */
|
|
||||||
+
|
|
||||||
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
|
|
||||||
index 1ccb30e5eb..91f1e36cd8 100644
|
|
||||||
--- a/target/arm/cpu.c
|
|
||||||
+++ b/target/arm/cpu.c
|
|
||||||
@@ -2560,6 +2560,9 @@ static Property arm_cpu_properties[] = {
|
|
||||||
DEFINE_PROP_UINT64("mp-affinity", ARMCPU,
|
|
||||||
mp_affinity, ARM64_AFFINITY_INVALID),
|
|
||||||
DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
|
|
||||||
+ DEFINE_PROP_INT32("socket-id", ARMCPU, socket_id, -1),
|
|
||||||
+ DEFINE_PROP_INT32("core-id", ARMCPU, core_id, -1),
|
|
||||||
+ DEFINE_PROP_INT32("thread-id", ARMCPU, thread_id, -1),
|
|
||||||
DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1),
|
|
||||||
DEFINE_PROP_END_OF_LIST()
|
|
||||||
};
|
|
||||||
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
|
|
||||||
index e19531a77b..219c222b89 100644
|
|
||||||
--- a/target/arm/cpu.h
|
|
||||||
+++ b/target/arm/cpu.h
|
|
||||||
@@ -916,6 +916,9 @@ struct ARMCPU {
|
|
||||||
QLIST_HEAD(, ARMELChangeHook) el_change_hooks;
|
|
||||||
|
|
||||||
int32_t node_id; /* NUMA node this CPU belongs to */
|
|
||||||
+ int32_t socket_id;
|
|
||||||
+ int32_t core_id;
|
|
||||||
+ int32_t thread_id;
|
|
||||||
|
|
||||||
/* Used to synchronize KVM and QEMU in-kernel device levels */
|
|
||||||
uint8_t device_irq_level;
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
From 31873c4c0454fb17654f57adece2bc396415f8bf Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 13:50:40 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Add cpu_hotplug_enabled field
|
|
||||||
|
|
||||||
Some conditions must be satisfied to support CPU hotplug, including
|
|
||||||
ACPI, GED, 64bit CPU, GICv3.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 7 +++++++
|
|
||||||
include/hw/arm/virt.h | 1 +
|
|
||||||
2 files changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index dda22194b5..304a4c2d31 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -1645,6 +1645,7 @@ static void machvirt_init(MachineState *machine)
|
|
||||||
{
|
|
||||||
VirtMachineState *vms = VIRT_MACHINE(machine);
|
|
||||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
|
|
||||||
+ MachineState *ms = MACHINE(machine);
|
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
|
||||||
const CPUArchIdList *possible_cpus;
|
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
|
||||||
@@ -1655,6 +1656,7 @@ static void machvirt_init(MachineState *machine)
|
|
||||||
bool has_ged = !vmc->no_ged;
|
|
||||||
unsigned int smp_cpus = machine->smp.cpus;
|
|
||||||
unsigned int max_cpus = machine->smp.max_cpus;
|
|
||||||
+ ObjectClass *cpu_class;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In accelerated mode, the memory map is computed earlier in kvm_type()
|
|
||||||
@@ -1760,6 +1762,11 @@ static void machvirt_init(MachineState *machine)
|
|
||||||
|
|
||||||
create_fdt(vms);
|
|
||||||
|
|
||||||
+ cpu_class = object_class_by_name(ms->cpu_type);
|
|
||||||
+ vms->cpu_hotplug_enabled = has_ged && firmware_loaded &&
|
|
||||||
+ acpi_enabled && vms->gic_version == 3 &&
|
|
||||||
+ !!object_class_dynamic_cast(cpu_class, TYPE_AARCH64_CPU);
|
|
||||||
+
|
|
||||||
possible_cpus = mc->possible_cpu_arch_ids(machine);
|
|
||||||
for (n = 0; n < possible_cpus->len; n++) {
|
|
||||||
Object *cpuobj;
|
|
||||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
|
||||||
index beef4c8002..b4c53d920e 100644
|
|
||||||
--- a/include/hw/arm/virt.h
|
|
||||||
+++ b/include/hw/arm/virt.h
|
|
||||||
@@ -126,6 +126,7 @@ typedef struct {
|
|
||||||
bool highmem_ecam;
|
|
||||||
bool its;
|
|
||||||
bool virt;
|
|
||||||
+ bool cpu_hotplug_enabled;
|
|
||||||
int32_t gic_version;
|
|
||||||
VirtIOMMUType iommu;
|
|
||||||
struct arm_boot_info bootinfo;
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
From 7cfb37c50209208f853c6fbd0df6673a95e03ef9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 14:16:40 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Add some sanity checks in cpu_pre_plug hook
|
|
||||||
|
|
||||||
For that user will try to hotplug a CPU when preconditions
|
|
||||||
are not satisfied, check these CPU hotplug preconditions in
|
|
||||||
pre_plug hook.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 27 +++++++++++++++++++++++++++
|
|
||||||
1 file changed, 27 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 983084c459..c6a99e683a 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -2086,10 +2086,30 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|
||||||
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
|
||||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev);
|
|
||||||
const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
|
|
||||||
+ const CPUArchId *cpu_slot = NULL;
|
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
|
||||||
int smp_cores = ms->smp.cores;
|
|
||||||
int smp_threads = ms->smp.threads;
|
|
||||||
|
|
||||||
+ /* Some hotplug capability checks */
|
|
||||||
+
|
|
||||||
+ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
|
|
||||||
+ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
|
|
||||||
+ ms->cpu_type);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (dev->hotplugged && !vms->acpi_dev) {
|
|
||||||
+ error_setg(errp, "CPU hotplug is disabled: missing acpi device.");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (dev->hotplugged && !vms->cpu_hotplug_enabled) {
|
|
||||||
+ error_setg(errp, "CPU hotplug is disabled: "
|
|
||||||
+ "should use AArch64 CPU and GICv3.");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* if cpu idx is not set, set it based on socket/core/thread properties */
|
|
||||||
if (cs->cpu_index == UNASSIGNED_CPU_INDEX) {
|
|
||||||
int max_socket = ms->smp.max_cpus / smp_threads / smp_cores;
|
|
||||||
@@ -2145,6 +2165,13 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|
||||||
object_property_set_int(cpuobj, possible_cpus->cpus[cs->cpu_index].arch_id,
|
|
||||||
"mp-affinity", NULL);
|
|
||||||
|
|
||||||
+ cpu_slot = &possible_cpus->cpus[cs->cpu_index];
|
|
||||||
+ if (cpu_slot->cpu) {
|
|
||||||
+ error_setg(errp, "CPU[%d] with mp_affinity %" PRIu64 " exists",
|
|
||||||
+ cs->cpu_index, cpu->mp_affinity);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
|
|
||||||
&error_fatal);
|
|
||||||
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
From d38d1d4e859450535ddc6bf0c7a59f6217b1403c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Sun, 5 Apr 2020 16:03:15 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Attach ACPI CPU hotplug support to virt
|
|
||||||
|
|
||||||
Attach cpus aml building and GED support for CPU hotplug to
|
|
||||||
arm/virt, but currently we make it diabled by not add CPU
|
|
||||||
hotplug event to GED.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt-acpi-build.c | 15 ++++++++++++++-
|
|
||||||
hw/arm/virt.c | 6 ++++++
|
|
||||||
include/hw/arm/virt.h | 1 +
|
|
||||||
3 files changed, 21 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
|
||||||
index 8b68a15d76..dbe9acb148 100644
|
|
||||||
--- a/hw/arm/virt-acpi-build.c
|
|
||||||
+++ b/hw/arm/virt-acpi-build.c
|
|
||||||
@@ -806,6 +806,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
MachineState *ms = MACHINE(vms);
|
|
||||||
const MemMapEntry *memmap = vms->memmap;
|
|
||||||
const int *irqmap = vms->irqmap;
|
|
||||||
+ bool cpu_aml_built = false;
|
|
||||||
|
|
||||||
dsdt = init_aml_allocator();
|
|
||||||
/* Reserve space for header */
|
|
||||||
@@ -817,7 +818,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
* the RTC ACPI device at all when using UEFI.
|
|
||||||
*/
|
|
||||||
scope = aml_scope("\\_SB");
|
|
||||||
- acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms);
|
|
||||||
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
|
|
||||||
(irqmap[VIRT_UART] + ARM_SPI_BASE));
|
|
||||||
acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
|
|
||||||
@@ -845,6 +845,19 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
AML_SYSTEM_MEMORY,
|
|
||||||
memmap[VIRT_PCDIMM_ACPI].base);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if (event & ACPI_GED_CPU_HOTPLUG_EVT) {
|
|
||||||
+ CPUHotplugFeatures opts = {
|
|
||||||
+ .acpi_1_compatible = false, .has_legacy_cphp = false
|
|
||||||
+ };
|
|
||||||
+ build_cpus_aml(dsdt, ms, opts, memmap[VIRT_CPU_ACPI].base,
|
|
||||||
+ "\\_SB", NULL, AML_SYSTEM_MEMORY);
|
|
||||||
+ cpu_aml_built = true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!cpu_aml_built) {
|
|
||||||
+ acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms);
|
|
||||||
}
|
|
||||||
|
|
||||||
acpi_dsdt_add_power_button(scope);
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 8638aeedb7..d09a5773df 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -140,6 +140,7 @@ static const MemMapEntry base_memmap[] = {
|
|
||||||
[VIRT_SMMU] = { 0x09050000, 0x00020000 },
|
|
||||||
[VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN },
|
|
||||||
[VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN },
|
|
||||||
+ [VIRT_CPU_ACPI] = { 0x09090000, ACPI_CPU_HOTPLUG_REG_LEN },
|
|
||||||
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
|
|
||||||
[VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 },
|
|
||||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
|
||||||
@@ -645,11 +646,16 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
|
||||||
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* event |= ACPI_GED_CPU_HOTPLUG_EVT;
|
|
||||||
+ * Currently CPU hotplug is not enabled.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
dev = qdev_create(NULL, TYPE_ACPI_GED);
|
|
||||||
qdev_prop_set_uint32(dev, "ged-event", event);
|
|
||||||
|
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base);
|
|
||||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base);
|
|
||||||
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, vms->memmap[VIRT_CPU_ACPI].base);
|
|
||||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));
|
|
||||||
|
|
||||||
qdev_init_nofail(dev);
|
|
||||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
|
||||||
index cbdea7ff32..6880ebe07c 100644
|
|
||||||
--- a/include/hw/arm/virt.h
|
|
||||||
+++ b/include/hw/arm/virt.h
|
|
||||||
@@ -81,6 +81,7 @@ enum {
|
|
||||||
VIRT_SECURE_MEM,
|
|
||||||
VIRT_PCDIMM_ACPI,
|
|
||||||
VIRT_ACPI_GED,
|
|
||||||
+ VIRT_CPU_ACPI,
|
|
||||||
VIRT_LOWMEMMAP_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
From bf47ef282bfe8b0a98e1f87d8708051ffa7192a1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 13:55:11 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Pre-sizing MADT-GICC PPTT GICv3 and Pre-park KVM
|
|
||||||
vCPU
|
|
||||||
|
|
||||||
Establish all pre-sizing facilities based on cpu_hotplug_enabled
|
|
||||||
field.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt-acpi-build.c | 12 +++++++++++-
|
|
||||||
hw/arm/virt.c | 14 ++++++++++++--
|
|
||||||
target/arm/kvm.c | 6 +++---
|
|
||||||
3 files changed, 26 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
|
||||||
index efac788ba1..2cfac7b84f 100644
|
|
||||||
--- a/hw/arm/virt-acpi-build.c
|
|
||||||
+++ b/hw/arm/virt-acpi-build.c
|
|
||||||
@@ -736,6 +736,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
|
|
||||||
gicd->version = vms->gic_version;
|
|
||||||
|
|
||||||
+ if (vms->cpu_hotplug_enabled) {
|
|
||||||
+ num_cpu = ms->smp.max_cpus;
|
|
||||||
+ }
|
|
||||||
for (i = 0; i < num_cpu; i++) {
|
|
||||||
virt_madt_cpu_entry(NULL, i, possible_cpus, table_data);
|
|
||||||
}
|
|
||||||
@@ -902,9 +905,11 @@ static
|
|
||||||
void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
|
||||||
{
|
|
||||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
|
||||||
+ MachineState *ms = MACHINE(vms);
|
|
||||||
GArray *table_offsets;
|
|
||||||
unsigned dsdt, xsdt;
|
|
||||||
GArray *tables_blob = tables->table_data;
|
|
||||||
+ int num_cpus;
|
|
||||||
|
|
||||||
table_offsets = g_array_new(false, true /* clear */,
|
|
||||||
sizeof(uint32_t));
|
|
||||||
@@ -923,7 +928,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
|
||||||
|
|
||||||
acpi_add_table(table_offsets, tables_blob);
|
|
||||||
|
|
||||||
- build_pptt(tables_blob, tables->linker, vms->smp_cpus);
|
|
||||||
+ if (vms->cpu_hotplug_enabled) {
|
|
||||||
+ num_cpus = ms->smp.max_cpus;
|
|
||||||
+ } else {
|
|
||||||
+ num_cpus = ms->smp.cpus;
|
|
||||||
+ }
|
|
||||||
+ build_pptt(tables_blob, tables->linker, num_cpus);
|
|
||||||
|
|
||||||
acpi_add_table(table_offsets, tables_blob);
|
|
||||||
build_madt(tables_blob, tables->linker, vms);
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 304a4c2d31..983084c459 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -767,6 +767,9 @@ static void create_gic(VirtMachineState *vms)
|
|
||||||
unsigned int smp_cpus = ms->smp.cpus;
|
|
||||||
uint32_t nb_redist_regions = 0;
|
|
||||||
|
|
||||||
+ if (vms->cpu_hotplug_enabled) {
|
|
||||||
+ num_cpus = ms->smp.max_cpus;
|
|
||||||
+ }
|
|
||||||
assert(num_cpus >= smp_cpus);
|
|
||||||
|
|
||||||
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
|
|
||||||
@@ -1772,8 +1775,15 @@ static void machvirt_init(MachineState *machine)
|
|
||||||
Object *cpuobj;
|
|
||||||
CPUState *cs;
|
|
||||||
|
|
||||||
+ if (kvm_enabled() && vms->cpu_hotplug_enabled) {
|
|
||||||
+ if (kvm_create_parked_vcpu(n) < 0) {
|
|
||||||
+ error_report("mach-virt: Create KVM parked vCPU failed");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (n >= smp_cpus) {
|
|
||||||
- break;
|
|
||||||
+ continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpuobj = object_new(possible_cpus->cpus[n].type);
|
|
||||||
@@ -1857,7 +1867,7 @@ static void machvirt_init(MachineState *machine)
|
|
||||||
vms->bootinfo.kernel_filename = machine->kernel_filename;
|
|
||||||
vms->bootinfo.kernel_cmdline = machine->kernel_cmdline;
|
|
||||||
vms->bootinfo.initrd_filename = machine->initrd_filename;
|
|
||||||
- vms->bootinfo.nb_cpus = smp_cpus;
|
|
||||||
+ vms->bootinfo.nb_cpus = vms->cpu_hotplug_enabled ? max_cpus : smp_cpus;
|
|
||||||
vms->bootinfo.board_id = -1;
|
|
||||||
vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base;
|
|
||||||
vms->bootinfo.get_dtb = machvirt_dtb;
|
|
||||||
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
|
|
||||||
index 327b3bc338..4f131f687d 100644
|
|
||||||
--- a/target/arm/kvm.c
|
|
||||||
+++ b/target/arm/kvm.c
|
|
||||||
@@ -202,7 +202,7 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
|
|
||||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
- unsigned int smp_cpus = ms->smp.cpus;
|
|
||||||
+ unsigned int max_cpus = ms->smp.max_cpus;
|
|
||||||
/* For ARM interrupt delivery is always asynchronous,
|
|
||||||
* whether we are using an in-kernel VGIC or not.
|
|
||||||
*/
|
|
||||||
@@ -216,9 +216,9 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
|
||||||
|
|
||||||
cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
|
|
||||||
|
|
||||||
- if (smp_cpus > 256 &&
|
|
||||||
+ if (max_cpus > 256 &&
|
|
||||||
!kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) {
|
|
||||||
- error_report("Using more than 256 vcpus requires a host kernel "
|
|
||||||
+ error_report("Using more than max 256 vcpus requires a host kernel "
|
|
||||||
"with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2");
|
|
||||||
ret = -EINVAL;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,159 +0,0 @@
|
|||||||
From 11f9628ceff019259ff12ce469deafbf50eb3075 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 14:20:59 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Start up CPU hot-plug
|
|
||||||
|
|
||||||
All the CPU hotplug facilities are ready. Assemble them
|
|
||||||
to start up CPU hot-plug capability for arm/virt.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 61 ++++++++++++++++++++++++++++++++++++++++---
|
|
||||||
include/hw/arm/virt.h | 1 +
|
|
||||||
qom/cpu.c | 5 ++++
|
|
||||||
target/arm/cpu.c | 2 ++
|
|
||||||
4 files changed, 65 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index c6a99e683a..112a6ae7cb 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -48,6 +48,8 @@
|
|
||||||
#include "sysemu/cpus.h"
|
|
||||||
#include "sysemu/sysemu.h"
|
|
||||||
#include "sysemu/kvm.h"
|
|
||||||
+#include "sysemu/cpus.h"
|
|
||||||
+#include "sysemu/hw_accel.h"
|
|
||||||
#include "hw/loader.h"
|
|
||||||
#include "exec/address-spaces.h"
|
|
||||||
#include "qemu/bitops.h"
|
|
||||||
@@ -649,9 +651,9 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
|
||||||
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* event |= ACPI_GED_CPU_HOTPLUG_EVT;
|
|
||||||
- * Currently CPU hotplug is not enabled.
|
|
||||||
- */
|
|
||||||
+ if (vms->cpu_hotplug_enabled) {
|
|
||||||
+ event |= ACPI_GED_CPU_HOTPLUG_EVT;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
dev = qdev_create(NULL, TYPE_ACPI_GED);
|
|
||||||
qdev_prop_set_uint32(dev, "ged-event", event);
|
|
||||||
@@ -2214,12 +2216,62 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|
||||||
object_property_set_link(cpuobj, OBJECT(secure_sysmem),
|
|
||||||
"secure-memory", &error_abort);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /* If we use KVM accel, we should pause all vcpus to
|
|
||||||
+ * allow hot access of vcpu registers.
|
|
||||||
+ */
|
|
||||||
+ if (dev->hotplugged && kvm_enabled()) {
|
|
||||||
+ pause_all_vcpus();
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virt_cpu_plug(HotplugHandler *hotplug_dev,
|
|
||||||
DeviceState *dev, Error **errp)
|
|
||||||
{
|
|
||||||
- /* Currently nothing to do */
|
|
||||||
+ CPUArchId *cpu_slot;
|
|
||||||
+ CPUState *cs = CPU(dev);
|
|
||||||
+ int ncpu = cs->cpu_index;
|
|
||||||
+ MachineState *ms = MACHINE(hotplug_dev);
|
|
||||||
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
|
|
||||||
+ GICv3State *gicv3;
|
|
||||||
+ ARMGICv3CommonClass *agcc;
|
|
||||||
+ Error *local_err = NULL;
|
|
||||||
+
|
|
||||||
+ if (dev->hotplugged) {
|
|
||||||
+ /* Realize GIC related parts of CPU */
|
|
||||||
+ assert(vms->gic_version == 3);
|
|
||||||
+ gicv3 = ARM_GICV3_COMMON(vms->gic);
|
|
||||||
+ agcc = ARM_GICV3_COMMON_GET_CLASS(gicv3);
|
|
||||||
+ agcc->cpu_hotplug_realize(gicv3, ncpu);
|
|
||||||
+ connect_gic_cpu_irqs(vms, ncpu);
|
|
||||||
+
|
|
||||||
+ /* Register CPU reset and trigger it manually */
|
|
||||||
+ cpu_synchronize_state(cs);
|
|
||||||
+ cpu_hotplug_register_reset(ncpu);
|
|
||||||
+ cpu_hotplug_reset_manually(ncpu);
|
|
||||||
+ cpu_synchronize_post_reset(cs);
|
|
||||||
+
|
|
||||||
+ if (kvm_enabled()) {
|
|
||||||
+ resume_all_vcpus();
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (vms->acpi_dev) {
|
|
||||||
+ hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
|
|
||||||
+ if (local_err) {
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ vms->boot_cpus++;
|
|
||||||
+ if (vms->fw_cfg) {
|
|
||||||
+ fw_cfg_modify_i16(vms->fw_cfg, FW_CFG_NB_CPUS, vms->boot_cpus);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ cpu_slot = &ms->possible_cpus->cpus[ncpu];
|
|
||||||
+ cpu_slot->cpu = OBJECT(dev);
|
|
||||||
+out:
|
|
||||||
+ error_propagate(errp, local_err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
|
||||||
@@ -2324,6 +2376,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
|
||||||
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
|
|
||||||
mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
|
|
||||||
mc->kvm_type = virt_kvm_type;
|
|
||||||
+ mc->has_hotpluggable_cpus = true;
|
|
||||||
assert(!mc->get_hotplug_handler);
|
|
||||||
mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
|
|
||||||
hc->pre_plug = virt_machine_device_pre_plug_cb;
|
|
||||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
|
||||||
index b4c53d920e..a9429bed25 100644
|
|
||||||
--- a/include/hw/arm/virt.h
|
|
||||||
+++ b/include/hw/arm/virt.h
|
|
||||||
@@ -140,6 +140,7 @@ typedef struct {
|
|
||||||
uint32_t msi_phandle;
|
|
||||||
uint32_t iommu_phandle;
|
|
||||||
int psci_conduit;
|
|
||||||
+ uint32_t boot_cpus;
|
|
||||||
hwaddr highest_gpa;
|
|
||||||
DeviceState *gic;
|
|
||||||
DeviceState *acpi_dev;
|
|
||||||
diff --git a/qom/cpu.c b/qom/cpu.c
|
|
||||||
index f376f782d8..58cd9d5bbc 100644
|
|
||||||
--- a/qom/cpu.c
|
|
||||||
+++ b/qom/cpu.c
|
|
||||||
@@ -342,7 +342,12 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
|
|
||||||
|
|
||||||
if (dev->hotplugged) {
|
|
||||||
cpu_synchronize_post_init(cpu);
|
|
||||||
+
|
|
||||||
+#ifdef __aarch64__
|
|
||||||
+ if (!kvm_enabled())
|
|
||||||
+#endif
|
|
||||||
cpu_resume(cpu);
|
|
||||||
+
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTE: latest generic point where the cpu is fully realized */
|
|
||||||
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
|
|
||||||
index 91f1e36cd8..811e5c6365 100644
|
|
||||||
--- a/target/arm/cpu.c
|
|
||||||
+++ b/target/arm/cpu.c
|
|
||||||
@@ -2598,6 +2598,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
|
|
||||||
acc->parent_reset = cc->reset;
|
|
||||||
cc->reset = arm_cpu_reset;
|
|
||||||
|
|
||||||
+ dc->user_creatable = true;
|
|
||||||
+
|
|
||||||
cc->class_by_name = arm_cpu_class_by_name;
|
|
||||||
cc->has_work = arm_cpu_has_work;
|
|
||||||
cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,92 +0,0 @@
|
|||||||
From e3a1af72fca5bbcc840fba44d512bbe69ec55ca9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Tue, 12 May 2020 15:05:06 +0800
|
|
||||||
Subject: [PATCH] arm/virt: Support CPU cold plug
|
|
||||||
|
|
||||||
This adds CPU cold plug support to arm virt machine board.
|
|
||||||
CPU cold plug means adding CPU by using "-device xx-arm-cpu"
|
|
||||||
when we bring up Qemu.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 36 +++++++++++++++++++-----------------
|
|
||||||
1 file changed, 19 insertions(+), 17 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 112a6ae7cb..4c7279392f 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -2093,25 +2093,12 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|
||||||
int smp_cores = ms->smp.cores;
|
|
||||||
int smp_threads = ms->smp.threads;
|
|
||||||
|
|
||||||
- /* Some hotplug capability checks */
|
|
||||||
-
|
|
||||||
if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
|
|
||||||
error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
|
|
||||||
ms->cpu_type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (dev->hotplugged && !vms->acpi_dev) {
|
|
||||||
- error_setg(errp, "CPU hotplug is disabled: missing acpi device.");
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (dev->hotplugged && !vms->cpu_hotplug_enabled) {
|
|
||||||
- error_setg(errp, "CPU hotplug is disabled: "
|
|
||||||
- "should use AArch64 CPU and GICv3.");
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
/* if cpu idx is not set, set it based on socket/core/thread properties */
|
|
||||||
if (cs->cpu_index == UNASSIGNED_CPU_INDEX) {
|
|
||||||
int max_socket = ms->smp.max_cpus / smp_threads / smp_cores;
|
|
||||||
@@ -2137,6 +2124,20 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|
||||||
cs->cpu_index = idx_from_topo_ids(smp_cores, smp_threads, &topo);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Some hotplug capability checks */
|
|
||||||
+ if (cs->cpu_index >= ms->smp.cpus) {
|
|
||||||
+ if (!vms->acpi_dev) {
|
|
||||||
+ error_setg(errp, "CPU cold/hot plug is disabled: "
|
|
||||||
+ "missing acpi device.");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ if (!vms->cpu_hotplug_enabled) {
|
|
||||||
+ error_setg(errp, "CPU cold/hot plug is disabled: "
|
|
||||||
+ "should use AArch64 CPU and GICv3.");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* if 'address' properties socket-id/core-id/thread-id are not set, set them
|
|
||||||
* so that machine_query_hotpluggable_cpus would show correct values
|
|
||||||
*/
|
|
||||||
@@ -2237,7 +2238,8 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
|
|
||||||
ARMGICv3CommonClass *agcc;
|
|
||||||
Error *local_err = NULL;
|
|
||||||
|
|
||||||
- if (dev->hotplugged) {
|
|
||||||
+ /* For CPU that is cold/hot plugged */
|
|
||||||
+ if (ncpu >= ms->smp.cpus) {
|
|
||||||
/* Realize GIC related parts of CPU */
|
|
||||||
assert(vms->gic_version == 3);
|
|
||||||
gicv3 = ARM_GICV3_COMMON(vms->gic);
|
|
||||||
@@ -2250,10 +2252,10 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
|
|
||||||
cpu_hotplug_register_reset(ncpu);
|
|
||||||
cpu_hotplug_reset_manually(ncpu);
|
|
||||||
cpu_synchronize_post_reset(cs);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (kvm_enabled()) {
|
|
||||||
- resume_all_vcpus();
|
|
||||||
- }
|
|
||||||
+ if (dev->hotplugged && kvm_enabled()) {
|
|
||||||
+ resume_all_vcpus();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vms->acpi_dev) {
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
From 91fed8840b004ec7bc91969afa10f03e13f311c4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Wed, 22 Apr 2020 19:52:58 +0800
|
|
||||||
Subject: [PATCH] arm/virt/acpi: Extend cpufreq to support max_cpus
|
|
||||||
|
|
||||||
We will support CPU hotplug soon, so extend memory region size to
|
|
||||||
allow hotplugged CPU access cpufreq space.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
---
|
|
||||||
hw/acpi/cpufreq.c | 15 ++++++---------
|
|
||||||
1 file changed, 6 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c
|
|
||||||
index d02a25a6de..38dcab5683 100644
|
|
||||||
--- a/hw/acpi/cpufreq.c
|
|
||||||
+++ b/hw/acpi/cpufreq.c
|
|
||||||
@@ -84,6 +84,7 @@ typedef struct CpuhzState {
|
|
||||||
uint32_t PerformanceLimited;
|
|
||||||
uint32_t LowestFreq;
|
|
||||||
uint32_t NominalFreq;
|
|
||||||
+ uint32_t num_cpu;
|
|
||||||
uint32_t reg_size;
|
|
||||||
} CpuhzState;
|
|
||||||
|
|
||||||
@@ -95,10 +96,7 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset,
|
|
||||||
uint64_t r;
|
|
||||||
uint64_t n;
|
|
||||||
|
|
||||||
- MachineState *ms = MACHINE(qdev_get_machine());
|
|
||||||
- unsigned int smp_cpus = ms->smp.cpus;
|
|
||||||
-
|
|
||||||
- if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
|
|
||||||
+ if (offset >= s->num_cpu * CPPC_REG_PER_CPU_STRIDE) {
|
|
||||||
warn_report("cpufreq_read: offset 0x%lx out of range", offset);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -166,11 +164,10 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset,
|
|
||||||
static void cpufreq_write(void *opaque, hwaddr offset,
|
|
||||||
uint64_t value, unsigned size)
|
|
||||||
{
|
|
||||||
+ CpuhzState *s = CPUFREQ(opaque);
|
|
||||||
uint64_t n;
|
|
||||||
- MachineState *ms = MACHINE(qdev_get_machine());
|
|
||||||
- unsigned int smp_cpus = ms->smp.cpus;
|
|
||||||
|
|
||||||
- if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
|
|
||||||
+ if (offset >= s->num_cpu * CPPC_REG_PER_CPU_STRIDE) {
|
|
||||||
error_printf("cpufreq_write: offset 0x%lx out of range", offset);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -251,9 +248,9 @@ static void cpufreq_init(Object *obj)
|
|
||||||
CpuhzState *s = CPUFREQ(obj);
|
|
||||||
|
|
||||||
MachineState *ms = MACHINE(qdev_get_machine());
|
|
||||||
- unsigned int smp_cpus = ms->smp.cpus;
|
|
||||||
+ s->num_cpu = ms->smp.max_cpus;
|
|
||||||
|
|
||||||
- s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE;
|
|
||||||
+ s->reg_size = s->num_cpu * CPPC_REG_PER_CPU_STRIDE;
|
|
||||||
if (s->reg_size > MAX_SUPPORT_SPACE) {
|
|
||||||
error_report("Required space 0x%x excesses the max support 0x%x",
|
|
||||||
s->reg_size, MAX_SUPPORT_SPACE);
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
From 2fdece10dac6161cb6c1f0f05247391aa3269eed Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Wed, 22 Apr 2020 15:58:27 +0800
|
|
||||||
Subject: [PATCH] arm/virt/acpi: Factor out CPPC building from DSDT CPU aml
|
|
||||||
|
|
||||||
When CPU hotplug is enabled, we will use build_cpus_aml instead of
|
|
||||||
acpi_dsdt_add_cpus, so factor out CPPC building and we can reuse it
|
|
||||||
in build_cpus_aml.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
---
|
|
||||||
hw/acpi/generic_event_device.c | 1 +
|
|
||||||
hw/arm/virt-acpi-build.c | 33 +++++++++++++++++-----------
|
|
||||||
include/hw/acpi/acpi_dev_interface.h | 2 ++
|
|
||||||
include/hw/arm/virt.h | 2 ++
|
|
||||||
4 files changed, 25 insertions(+), 13 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
|
||||||
index b834ae3ff6..82139b4314 100644
|
|
||||||
--- a/hw/acpi/generic_event_device.c
|
|
||||||
+++ b/hw/acpi/generic_event_device.c
|
|
||||||
@@ -289,6 +289,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data)
|
|
||||||
|
|
||||||
adevc->send_event = acpi_ged_send_event;
|
|
||||||
adevc->madt_cpu = virt_madt_cpu_entry;
|
|
||||||
+ adevc->cpu_cppc = virt_acpi_dsdt_cpu_cppc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const TypeInfo acpi_ged_info = {
|
|
||||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
|
||||||
index 4b6aace433..8b68a15d76 100644
|
|
||||||
--- a/hw/arm/virt-acpi-build.c
|
|
||||||
+++ b/hw/arm/virt-acpi-build.c
|
|
||||||
@@ -111,8 +111,24 @@ static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset)
|
|
||||||
aml_append(dev, aml_name_decl("_CPC", cpc));
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus,
|
|
||||||
- const MemMapEntry *cppc_memmap)
|
|
||||||
+void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int ncpu, int num_cpu, Aml *dev)
|
|
||||||
+{
|
|
||||||
+ VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine());
|
|
||||||
+ const MemMapEntry *cppc_memmap = &vms->memmap[VIRT_CPUFREQ];
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Append _CPC and _PSD to support CPU frequence show
|
|
||||||
+ * Check CPPC available by DESIRED_PERF register
|
|
||||||
+ */
|
|
||||||
+ if (cppc_regs_offset[DESIRED_PERF] != -1) {
|
|
||||||
+ acpi_dsdt_add_cppc(dev,
|
|
||||||
+ cppc_memmap->base + ncpu * CPPC_REG_PER_CPU_STRIDE,
|
|
||||||
+ cppc_regs_offset);
|
|
||||||
+ acpi_dsdt_add_psd(dev, num_cpu);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, VirtMachineState *vms)
|
|
||||||
{
|
|
||||||
uint16_t i;
|
|
||||||
|
|
||||||
@@ -121,16 +137,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus,
|
|
||||||
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
|
|
||||||
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
|
|
||||||
|
|
||||||
- /*
|
|
||||||
- * Append _CPC and _PSD to support CPU frequence show
|
|
||||||
- * Check CPPC available by DESIRED_PERF register
|
|
||||||
- */
|
|
||||||
- if (cppc_regs_offset[DESIRED_PERF] != -1) {
|
|
||||||
- acpi_dsdt_add_cppc(dev,
|
|
||||||
- cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE,
|
|
||||||
- cppc_regs_offset);
|
|
||||||
- acpi_dsdt_add_psd(dev, smp_cpus);
|
|
||||||
- }
|
|
||||||
+ virt_acpi_dsdt_cpu_cppc(NULL, i, smp_cpus, dev);
|
|
||||||
|
|
||||||
aml_append(scope, dev);
|
|
||||||
}
|
|
||||||
@@ -810,7 +817,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|
||||||
* the RTC ACPI device at all when using UEFI.
|
|
||||||
*/
|
|
||||||
scope = aml_scope("\\_SB");
|
|
||||||
- acpi_dsdt_add_cpus(scope, vms->smp_cpus, &memmap[VIRT_CPUFREQ]);
|
|
||||||
+ acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms);
|
|
||||||
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
|
|
||||||
(irqmap[VIRT_UART] + ARM_SPI_BASE));
|
|
||||||
acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
|
|
||||||
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
|
|
||||||
index adcb3a816c..2952914569 100644
|
|
||||||
--- a/include/hw/acpi/acpi_dev_interface.h
|
|
||||||
+++ b/include/hw/acpi/acpi_dev_interface.h
|
|
||||||
@@ -3,6 +3,7 @@
|
|
||||||
|
|
||||||
#include "qom/object.h"
|
|
||||||
#include "hw/boards.h"
|
|
||||||
+#include "hw/acpi/aml-build.h"
|
|
||||||
|
|
||||||
/* These values are part of guest ABI, and can not be changed */
|
|
||||||
typedef enum {
|
|
||||||
@@ -55,5 +56,6 @@ typedef struct AcpiDeviceIfClass {
|
|
||||||
void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev);
|
|
||||||
void (*madt_cpu)(AcpiDeviceIf *adev, int uid,
|
|
||||||
const CPUArchIdList *apic_ids, GArray *entry);
|
|
||||||
+ void (*cpu_cppc)(AcpiDeviceIf *adev, int uid, int num_cpu, Aml *dev);
|
|
||||||
} AcpiDeviceIfClass;
|
|
||||||
#endif
|
|
||||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
|
||||||
index 6b1f10b231..cbdea7ff32 100644
|
|
||||||
--- a/include/hw/arm/virt.h
|
|
||||||
+++ b/include/hw/arm/virt.h
|
|
||||||
@@ -157,6 +157,8 @@ typedef struct {
|
|
||||||
void virt_acpi_setup(VirtMachineState *vms);
|
|
||||||
void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
|
||||||
const CPUArchIdList *cpu_list, GArray *entry);
|
|
||||||
+void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int uid,
|
|
||||||
+ int num_cpu, Aml *dev);
|
|
||||||
|
|
||||||
/* Return the number of used redistributor regions */
|
|
||||||
static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,123 +0,0 @@
|
|||||||
From 92124743f4560c490780a229f53ea5881f706383 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Sun, 5 Apr 2020 15:29:16 +0800
|
|
||||||
Subject: [PATCH] arm/virt/gic: Construct irqs connection from create_gic
|
|
||||||
|
|
||||||
Make the irqs can be connected to for individual CPU.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 90 ++++++++++++++++++++++++++++-----------------------
|
|
||||||
1 file changed, 49 insertions(+), 41 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 83f4887e57..55d403bad6 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -706,6 +706,54 @@ static void create_v2m(VirtMachineState *vms)
|
|
||||||
fdt_add_v2m_gic_node(vms);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void connect_gic_cpu_irqs(VirtMachineState *vms, int i)
|
|
||||||
+{
|
|
||||||
+ DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
|
|
||||||
+ SysBusDevice *gicbusdev = SYS_BUS_DEVICE(vms->gic);
|
|
||||||
+ int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
|
|
||||||
+ int num_cpus = object_property_get_uint(OBJECT(vms->gic), "num-cpu", NULL);
|
|
||||||
+ int gic_type = vms->gic_version;
|
|
||||||
+ int irq;
|
|
||||||
+ /* Mapping from the output timer irq lines from the CPU to the
|
|
||||||
+ * GIC PPI inputs we use for the virt board.
|
|
||||||
+ */
|
|
||||||
+ const int timer_irq[] = {
|
|
||||||
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
|
|
||||||
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
|
|
||||||
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
|
|
||||||
+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
|
||||||
+ qdev_connect_gpio_out(cpudev, irq,
|
|
||||||
+ qdev_get_gpio_in(vms->gic,
|
|
||||||
+ ppibase + timer_irq[irq]));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (gic_type == 3) {
|
|
||||||
+ qemu_irq irq = qdev_get_gpio_in(vms->gic,
|
|
||||||
+ ppibase + ARCH_GIC_MAINT_IRQ);
|
|
||||||
+ qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
|
|
||||||
+ 0, irq);
|
|
||||||
+ } else if (vms->virt) {
|
|
||||||
+ qemu_irq irq = qdev_get_gpio_in(vms->gic,
|
|
||||||
+ ppibase + ARCH_GIC_MAINT_IRQ);
|
|
||||||
+ sysbus_connect_irq(gicbusdev, i + 4 * num_cpus, irq);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
|
|
||||||
+ qdev_get_gpio_in(vms->gic, ppibase
|
|
||||||
+ + VIRTUAL_PMU_IRQ));
|
|
||||||
+
|
|
||||||
+ sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
|
||||||
+ sysbus_connect_irq(gicbusdev, i + num_cpus,
|
|
||||||
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
|
|
||||||
+ sysbus_connect_irq(gicbusdev, i + 2 * num_cpus,
|
|
||||||
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
|
|
||||||
+ sysbus_connect_irq(gicbusdev, i + 3 * num_cpus,
|
|
||||||
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void create_gic(VirtMachineState *vms)
|
|
||||||
{
|
|
||||||
MachineState *ms = MACHINE(vms);
|
|
||||||
@@ -775,47 +823,7 @@ static void create_gic(VirtMachineState *vms)
|
|
||||||
* and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < smp_cpus; i++) {
|
|
||||||
- DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
|
|
||||||
- int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
|
|
||||||
- int irq;
|
|
||||||
- /* Mapping from the output timer irq lines from the CPU to the
|
|
||||||
- * GIC PPI inputs we use for the virt board.
|
|
||||||
- */
|
|
||||||
- const int timer_irq[] = {
|
|
||||||
- [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
|
|
||||||
- [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
|
|
||||||
- [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
|
|
||||||
- [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
|
|
||||||
- };
|
|
||||||
-
|
|
||||||
- for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
|
||||||
- qdev_connect_gpio_out(cpudev, irq,
|
|
||||||
- qdev_get_gpio_in(vms->gic,
|
|
||||||
- ppibase + timer_irq[irq]));
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (type == 3) {
|
|
||||||
- qemu_irq irq = qdev_get_gpio_in(vms->gic,
|
|
||||||
- ppibase + ARCH_GIC_MAINT_IRQ);
|
|
||||||
- qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt",
|
|
||||||
- 0, irq);
|
|
||||||
- } else if (vms->virt) {
|
|
||||||
- qemu_irq irq = qdev_get_gpio_in(vms->gic,
|
|
||||||
- ppibase + ARCH_GIC_MAINT_IRQ);
|
|
||||||
- sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
|
|
||||||
- qdev_get_gpio_in(vms->gic, ppibase
|
|
||||||
- + VIRTUAL_PMU_IRQ));
|
|
||||||
-
|
|
||||||
- sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
|
||||||
- sysbus_connect_irq(gicbusdev, i + smp_cpus,
|
|
||||||
- qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
|
|
||||||
- sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus,
|
|
||||||
- qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
|
|
||||||
- sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
|
|
||||||
- qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
|
|
||||||
+ connect_gic_cpu_irqs(vms, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
fdt_add_gic_node(vms);
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,171 +0,0 @@
|
|||||||
From 787af8ed2bc86dc8688727d62a251965d9c42e00 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ying Fang <fangying1@huawei.com>
|
|
||||||
Date: Fri, 10 Apr 2020 16:19:50 +0000
|
|
||||||
Subject: [PATCH 2/2] async: use explicit memory barriers
|
|
||||||
|
|
||||||
When using C11 atomics, non-seqcst reads and writes do not participate
|
|
||||||
in the total order of seqcst operations. In util/async.c and util/aio-posix.c,
|
|
||||||
in particular, the pattern that we use
|
|
||||||
|
|
||||||
write ctx->notify_me write bh->scheduled
|
|
||||||
read bh->scheduled read ctx->notify_me
|
|
||||||
if !bh->scheduled, sleep if ctx->notify_me, notify
|
|
||||||
|
|
||||||
needs to use seqcst operations for both the write and the read. In
|
|
||||||
general this is something that we do not want, because there can be
|
|
||||||
many sources that are polled in addition to bottom halves. The
|
|
||||||
alternative is to place a seqcst memory barrier between the write
|
|
||||||
and the read. This also comes with a disadvantage, in that the
|
|
||||||
memory barrier is implicit on strongly-ordered architectures and
|
|
||||||
it wastes a few dozen clock cycles.
|
|
||||||
|
|
||||||
Fortunately, ctx->notify_me is never written concurrently by two
|
|
||||||
threads, so we can assert that and relax the writes to ctx->notify_me.
|
|
||||||
The resulting solution works and performs well on both aarch64 and x86.
|
|
||||||
|
|
||||||
Note that the atomic_set/atomic_read combination is not an atomic
|
|
||||||
read-modify-write, and therefore it is even weaker than C11 ATOMIC_RELAXED;
|
|
||||||
on x86, ATOMIC_RELAXED compiles to a locked operation.
|
|
||||||
|
|
||||||
upstream_url: https://patchwork.kernel.org/patch/11482103/
|
|
||||||
|
|
||||||
Analyzed-by: Ying Fang <fangying1@huawei.com>
|
|
||||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
Tested-by: Ying Fang <fangying1@huawei.com>
|
|
||||||
Message-Id: <20200407140746.8041-6-pbonzini@redhat.com>
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
---
|
|
||||||
util/aio-posix.c | 16 ++++++++++++++--
|
|
||||||
util/aio-win32.c | 17 ++++++++++++++---
|
|
||||||
util/async.c | 16 ++++++++++++----
|
|
||||||
3 files changed, 40 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/util/aio-posix.c b/util/aio-posix.c
|
|
||||||
index 6fbfa792..ca58b9a4 100644
|
|
||||||
--- a/util/aio-posix.c
|
|
||||||
+++ b/util/aio-posix.c
|
|
||||||
@@ -613,6 +613,11 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|
||||||
int64_t timeout;
|
|
||||||
int64_t start = 0;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * There cannot be two concurrent aio_poll calls for the same AioContext (or
|
|
||||||
+ * an aio_poll concurrent with a GSource prepare/check/dispatch callback).
|
|
||||||
+ * We rely on this below to avoid slow locked accesses to ctx->notify_me.
|
|
||||||
+ */
|
|
||||||
assert(in_aio_context_home_thread(ctx));
|
|
||||||
|
|
||||||
/* aio_notify can avoid the expensive event_notifier_set if
|
|
||||||
@@ -623,7 +628,13 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|
||||||
* so disable the optimization now.
|
|
||||||
*/
|
|
||||||
if (blocking) {
|
|
||||||
- atomic_add(&ctx->notify_me, 2);
|
|
||||||
+ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2);
|
|
||||||
+ /*
|
|
||||||
+ * Write ctx->notify_me before computing the timeout
|
|
||||||
+ * (reading bottom half flags, etc.). Pairs with
|
|
||||||
+ * smp_mb in aio_notify().
|
|
||||||
+ */
|
|
||||||
+ smp_mb();
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_lockcnt_inc(&ctx->list_lock);
|
|
||||||
@@ -668,7 +679,8 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blocking) {
|
|
||||||
- atomic_sub(&ctx->notify_me, 2);
|
|
||||||
+ /* Finish the poll before clearing the flag. */
|
|
||||||
+ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2);
|
|
||||||
aio_notify_accept(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/util/aio-win32.c b/util/aio-win32.c
|
|
||||||
index a23b9c36..729d533f 100644
|
|
||||||
--- a/util/aio-win32.c
|
|
||||||
+++ b/util/aio-win32.c
|
|
||||||
@@ -321,6 +321,12 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|
||||||
int count;
|
|
||||||
int timeout;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * There cannot be two concurrent aio_poll calls for the same AioContext (or
|
|
||||||
+ * an aio_poll concurrent with a GSource prepare/check/dispatch callback).
|
|
||||||
+ * We rely on this below to avoid slow locked accesses to ctx->notify_me.
|
|
||||||
+ */
|
|
||||||
+ assert(in_aio_context_home_thread(ctx));
|
|
||||||
progress = false;
|
|
||||||
|
|
||||||
/* aio_notify can avoid the expensive event_notifier_set if
|
|
||||||
@@ -331,7 +337,13 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|
||||||
* so disable the optimization now.
|
|
||||||
*/
|
|
||||||
if (blocking) {
|
|
||||||
- atomic_add(&ctx->notify_me, 2);
|
|
||||||
+ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2);
|
|
||||||
+ /*
|
|
||||||
+ * Write ctx->notify_me before computing the timeout
|
|
||||||
+ * (reading bottom half flags, etc.). Pairs with
|
|
||||||
+ * smp_mb in aio_notify().
|
|
||||||
+ */
|
|
||||||
+ smp_mb();
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_lockcnt_inc(&ctx->list_lock);
|
|
||||||
@@ -364,8 +376,7 @@ bool aio_poll(AioContext *ctx, bool blocking)
|
|
||||||
ret = WaitForMultipleObjects(count, events, FALSE, timeout);
|
|
||||||
if (blocking) {
|
|
||||||
assert(first);
|
|
||||||
- assert(in_aio_context_home_thread(ctx));
|
|
||||||
- atomic_sub(&ctx->notify_me, 2);
|
|
||||||
+ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2);
|
|
||||||
aio_notify_accept(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/util/async.c b/util/async.c
|
|
||||||
index afc17fb3..12b33204 100644
|
|
||||||
--- a/util/async.c
|
|
||||||
+++ b/util/async.c
|
|
||||||
@@ -221,7 +221,14 @@ aio_ctx_prepare(GSource *source, gint *timeout)
|
|
||||||
{
|
|
||||||
AioContext *ctx = (AioContext *) source;
|
|
||||||
|
|
||||||
- atomic_or(&ctx->notify_me, 1);
|
|
||||||
+ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) | 1);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Write ctx->notify_me before computing the timeout
|
|
||||||
+ * (reading bottom half flags, etc.). Pairs with
|
|
||||||
+ * smp_mb in aio_notify().
|
|
||||||
+ */
|
|
||||||
+ smp_mb();
|
|
||||||
|
|
||||||
/* We assume there is no timeout already supplied */
|
|
||||||
*timeout = qemu_timeout_ns_to_ms(aio_compute_timeout(ctx));
|
|
||||||
@@ -239,7 +246,8 @@ aio_ctx_check(GSource *source)
|
|
||||||
AioContext *ctx = (AioContext *) source;
|
|
||||||
QEMUBH *bh;
|
|
||||||
|
|
||||||
- atomic_and(&ctx->notify_me, ~1);
|
|
||||||
+ /* Finish computing the timeout before clearing the flag. */
|
|
||||||
+ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) & ~1);
|
|
||||||
aio_notify_accept(ctx);
|
|
||||||
|
|
||||||
for (bh = ctx->first_bh; bh; bh = bh->next) {
|
|
||||||
@@ -344,10 +352,10 @@ LinuxAioState *aio_get_linux_aio(AioContext *ctx)
|
|
||||||
void aio_notify(AioContext *ctx)
|
|
||||||
{
|
|
||||||
/* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs
|
|
||||||
- * with atomic_or in aio_ctx_prepare or atomic_add in aio_poll.
|
|
||||||
+ * with smp_mb in aio_ctx_prepare or aio_poll.
|
|
||||||
*/
|
|
||||||
smp_mb();
|
|
||||||
- if (ctx->notify_me) {
|
|
||||||
+ if (atomic_read(&ctx->notify_me)) {
|
|
||||||
event_notifier_set(&ctx->notifier);
|
|
||||||
atomic_mb_set(&ctx->notified, true);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.25.2
|
|
||||||
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
From 9557ba506470517668ffecb4d5ef4804eca4fd88 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
|
||||||
Date: Wed, 18 Nov 2020 10:22:32 +0800
|
|
||||||
Subject: [PATCH] ati: check x y display parameter values
|
|
||||||
|
|
||||||
fix CVE-2020-24352
|
|
||||||
|
|
||||||
The source and destination x,y display parameters in ati_2d_blt()
|
|
||||||
may run off the vga limits if either of s->regs.[src|dst]_[xy] is
|
|
||||||
zero. Check the parameter values to avoid potential crash.
|
|
||||||
|
|
||||||
Reported-by: Gaoning Pan <pgn@zju.edu.cn>
|
|
||||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
|
||||||
Message-id: 20201021103818.1704030-1-ppandit@redhat.com
|
|
||||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
||||||
|
|
||||||
cherry-pick from commit ca1f9cbfdce4d63b10d57de80fef89a89d92a540
|
|
||||||
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
|
|
||||||
---
|
|
||||||
hw/display/ati_2d.c | 10 ++++++----
|
|
||||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
|
|
||||||
index 23a8ae0cd8..4dc10ea795 100644
|
|
||||||
--- a/hw/display/ati_2d.c
|
|
||||||
+++ b/hw/display/ati_2d.c
|
|
||||||
@@ -75,8 +75,9 @@ void ati_2d_blt(ATIVGAState *s)
|
|
||||||
dst_stride *= bpp;
|
|
||||||
}
|
|
||||||
uint8_t *end = s->vga.vram_ptr + s->vga.vram_size;
|
|
||||||
- if (dst_bits >= end || dst_bits + dst_x + (dst_y + s->regs.dst_height) *
|
|
||||||
- dst_stride >= end) {
|
|
||||||
+ if (dst_x > 0x3fff || dst_y > 0x3fff || dst_bits >= end
|
|
||||||
+ || dst_bits + dst_x
|
|
||||||
+ + (dst_y + s->regs.dst_height) * dst_stride >= end) {
|
|
||||||
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -107,8 +108,9 @@ void ati_2d_blt(ATIVGAState *s)
|
|
||||||
src_bits += s->regs.crtc_offset & 0x07ffffff;
|
|
||||||
src_stride *= bpp;
|
|
||||||
}
|
|
||||||
- if (src_bits >= end || src_bits + src_x +
|
|
||||||
- (src_y + s->regs.dst_height) * src_stride >= end) {
|
|
||||||
+ if (src_x > 0x3fff || src_y > 0x3fff || src_bits >= end
|
|
||||||
+ || src_bits + src_x
|
|
||||||
+ + (src_y + s->regs.dst_height) * src_stride >= end) {
|
|
||||||
qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,198 +0,0 @@
|
|||||||
From 1ebe0e71d04bfdc76777a3a672e873f006d207e2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
|
||||||
Date: Fri, 5 Feb 2021 10:38:24 +0800
|
|
||||||
Subject: [PATCH] ati: use vga_read_byte in ati_cursor_define
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
fix CVE-2019-20808
|
|
||||||
|
|
||||||
This makes sure reads are confined to vga video memory.
|
|
||||||
|
|
||||||
v3: use uint32_t, fix cut+paste bug.
|
|
||||||
v2: fix ati_cursor_draw_line too.
|
|
||||||
|
|
||||||
Reported-by: xu hang <flier_m@outlook.com>
|
|
||||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
||||||
Reviewed-by: BALATON Zoltan <balaton@eik.bme.hu>
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Message-id: 20190917111441.27405-3-kraxel@redhat.com
|
|
||||||
|
|
||||||
cherry-pick from aab0e2a661b2b6bf7915c0aefe807fb60d6d9d13
|
|
||||||
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
|
|
||||||
---
|
|
||||||
hw/display/ati.c | 21 ++++++++---------
|
|
||||||
hw/display/vga-access.h | 49 ++++++++++++++++++++++++++++++++++++++++
|
|
||||||
hw/display/vga-helpers.h | 27 +---------------------
|
|
||||||
3 files changed, 60 insertions(+), 37 deletions(-)
|
|
||||||
create mode 100644 hw/display/vga-access.h
|
|
||||||
|
|
||||||
diff --git a/hw/display/ati.c b/hw/display/ati.c
|
|
||||||
index 5943040416..b17569874e 100644
|
|
||||||
--- a/hw/display/ati.c
|
|
||||||
+++ b/hw/display/ati.c
|
|
||||||
@@ -19,6 +19,7 @@
|
|
||||||
#include "qemu/osdep.h"
|
|
||||||
#include "ati_int.h"
|
|
||||||
#include "ati_regs.h"
|
|
||||||
+#include "vga-access.h"
|
|
||||||
#include "vga_regs.h"
|
|
||||||
#include "qemu/log.h"
|
|
||||||
#include "qemu/module.h"
|
|
||||||
@@ -125,20 +126,19 @@ static void ati_vga_switch_mode(ATIVGAState *s)
|
|
||||||
static void ati_cursor_define(ATIVGAState *s)
|
|
||||||
{
|
|
||||||
uint8_t data[1024];
|
|
||||||
- uint8_t *src;
|
|
||||||
+ uint32_t srcoff;
|
|
||||||
int i, j, idx = 0;
|
|
||||||
|
|
||||||
if ((s->regs.cur_offset & BIT(31)) || s->cursor_guest_mode) {
|
|
||||||
return; /* Do not update cursor if locked or rendered by guest */
|
|
||||||
}
|
|
||||||
/* FIXME handle cur_hv_offs correctly */
|
|
||||||
- src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
|
|
||||||
- s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
|
|
||||||
- (s->regs.cur_hv_offs & 0xffff) * 16;
|
|
||||||
+ srcoff = s->regs.cur_offset -
|
|
||||||
+ (s->regs.cur_hv_offs >> 16) - (s->regs.cur_hv_offs & 0xffff) * 16;
|
|
||||||
for (i = 0; i < 64; i++) {
|
|
||||||
for (j = 0; j < 8; j++, idx++) {
|
|
||||||
- data[idx] = src[i * 16 + j];
|
|
||||||
- data[512 + idx] = src[i * 16 + j + 8];
|
|
||||||
+ data[idx] = vga_read_byte(&s->vga, srcoff + i * 16 + j);
|
|
||||||
+ data[512 + idx] = vga_read_byte(&s->vga, srcoff + i * 16 + j + 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!s->cursor) {
|
|
||||||
@@ -180,7 +180,7 @@ static void ati_cursor_invalidate(VGACommonState *vga)
|
|
||||||
static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
|
|
||||||
{
|
|
||||||
ATIVGAState *s = container_of(vga, ATIVGAState, vga);
|
|
||||||
- uint8_t *src;
|
|
||||||
+ uint32_t srcoff;
|
|
||||||
uint32_t *dp = (uint32_t *)d;
|
|
||||||
int i, j, h;
|
|
||||||
|
|
||||||
@@ -190,14 +190,13 @@ static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* FIXME handle cur_hv_offs correctly */
|
|
||||||
- src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
|
|
||||||
- s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
|
|
||||||
+ srcoff = s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
|
|
||||||
dp = &dp[vga->hw_cursor_x];
|
|
||||||
h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
uint32_t color;
|
|
||||||
- uint8_t abits = src[i];
|
|
||||||
- uint8_t xbits = src[i + 8];
|
|
||||||
+ uint8_t abits = vga_read_byte(vga, srcoff + i);
|
|
||||||
+ uint8_t xbits = vga_read_byte(vga, srcoff + i + 8);
|
|
||||||
for (j = 0; j < 8; j++, abits <<= 1, xbits <<= 1) {
|
|
||||||
if (abits & BIT(7)) {
|
|
||||||
if (xbits & BIT(7)) {
|
|
||||||
diff --git a/hw/display/vga-access.h b/hw/display/vga-access.h
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..c0fbd9958b
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/hw/display/vga-access.h
|
|
||||||
@@ -0,0 +1,49 @@
|
|
||||||
+/*
|
|
||||||
+ * QEMU VGA Emulator templates
|
|
||||||
+ *
|
|
||||||
+ * Copyright (c) 2003 Fabrice Bellard
|
|
||||||
+ *
|
|
||||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
+ * of this software and associated documentation files (the "Software"), to deal
|
|
||||||
+ * in the Software without restriction, including without limitation the rights
|
|
||||||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
+ * copies of the Software, and to permit persons to whom the Software is
|
|
||||||
+ * furnished to do so, subject to the following conditions:
|
|
||||||
+ *
|
|
||||||
+ * The above copyright notice and this permission notice shall be included in
|
|
||||||
+ * all copies or substantial portions of the Software.
|
|
||||||
+ *
|
|
||||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
+ * THE SOFTWARE.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr)
|
|
||||||
+{
|
|
||||||
+ return vga->vram_ptr[addr & vga->vbe_size_mask];
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr)
|
|
||||||
+{
|
|
||||||
+ uint32_t offset = addr & vga->vbe_size_mask & ~1;
|
|
||||||
+ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
|
|
||||||
+ return lduw_le_p(ptr);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr)
|
|
||||||
+{
|
|
||||||
+ uint32_t offset = addr & vga->vbe_size_mask & ~1;
|
|
||||||
+ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
|
|
||||||
+ return lduw_be_p(ptr);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr)
|
|
||||||
+{
|
|
||||||
+ uint32_t offset = addr & vga->vbe_size_mask & ~3;
|
|
||||||
+ uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset);
|
|
||||||
+ return ldl_le_p(ptr);
|
|
||||||
+}
|
|
||||||
diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h
|
|
||||||
index 5a752b3f9e..5b6c02faa6 100644
|
|
||||||
--- a/hw/display/vga-helpers.h
|
|
||||||
+++ b/hw/display/vga-helpers.h
|
|
||||||
@@ -21,6 +21,7 @@
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
+#include "vga-access.h"
|
|
||||||
|
|
||||||
static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data,
|
|
||||||
uint32_t xorcol, uint32_t bgcol)
|
|
||||||
@@ -95,32 +96,6 @@ static void vga_draw_glyph9(uint8_t *d, int linesize,
|
|
||||||
} while (--h);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr)
|
|
||||||
-{
|
|
||||||
- return vga->vram_ptr[addr & vga->vbe_size_mask];
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr)
|
|
||||||
-{
|
|
||||||
- uint32_t offset = addr & vga->vbe_size_mask & ~1;
|
|
||||||
- uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
|
|
||||||
- return lduw_le_p(ptr);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr)
|
|
||||||
-{
|
|
||||||
- uint32_t offset = addr & vga->vbe_size_mask & ~1;
|
|
||||||
- uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset);
|
|
||||||
- return lduw_be_p(ptr);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr)
|
|
||||||
-{
|
|
||||||
- uint32_t offset = addr & vga->vbe_size_mask & ~3;
|
|
||||||
- uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset);
|
|
||||||
- return ldl_le_p(ptr);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* 4 color mode
|
|
||||||
*/
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
From ac2071c3791b67fc7af78b8ceb320c01ca1b5df7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: BALATON Zoltan <balaton@eik.bme.hu>
|
|
||||||
Date: Mon, 6 Apr 2020 22:34:26 +0200
|
|
||||||
Subject: [PATCH] ati-vga: Fix checks in ati_2d_blt() to avoid crash
|
|
||||||
|
|
||||||
In some corner cases (that never happen during normal operation but a
|
|
||||||
malicious guest could program wrong values) pixman functions were
|
|
||||||
called with parameters that result in a crash. Fix this and add more
|
|
||||||
checks to disallow such cases.
|
|
||||||
|
|
||||||
Reported-by: Ziming Zhang <ezrakiez@gmail.com>
|
|
||||||
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
|
|
||||||
Message-id: 20200406204029.19559747D5D@zero.eik.bme.hu
|
|
||||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
||||||
|
|
||||||
diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
|
|
||||||
index 42e82311eb..23a8ae0cd8 100644
|
|
||||||
--- a/hw/display/ati_2d.c
|
|
||||||
+++ b/hw/display/ati_2d.c
|
|
||||||
@@ -53,12 +53,20 @@ void ati_2d_blt(ATIVGAState *s)
|
|
||||||
s->vga.vbe_start_addr, surface_data(ds), surface_stride(ds),
|
|
||||||
surface_bits_per_pixel(ds),
|
|
||||||
(s->regs.dp_mix & GMC_ROP3_MASK) >> 16);
|
|
||||||
- int dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
|
|
||||||
- s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width);
|
|
||||||
- int dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
|
|
||||||
- s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height);
|
|
||||||
+ unsigned dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
|
|
||||||
+ s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width);
|
|
||||||
+ unsigned dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
|
|
||||||
+ s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height);
|
|
||||||
int bpp = ati_bpp_from_datatype(s);
|
|
||||||
+ if (!bpp) {
|
|
||||||
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
int dst_stride = DEFAULT_CNTL ? s->regs.dst_pitch : s->regs.default_pitch;
|
|
||||||
+ if (!dst_stride) {
|
|
||||||
+ qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
uint8_t *dst_bits = s->vga.vram_ptr + (DEFAULT_CNTL ?
|
|
||||||
s->regs.dst_offset : s->regs.default_offset);
|
|
||||||
|
|
||||||
@@ -82,12 +90,16 @@ void ati_2d_blt(ATIVGAState *s)
|
|
||||||
switch (s->regs.dp_mix & GMC_ROP3_MASK) {
|
|
||||||
case ROP3_SRCCOPY:
|
|
||||||
{
|
|
||||||
- int src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
|
|
||||||
- s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width);
|
|
||||||
- int src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
|
|
||||||
- s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height);
|
|
||||||
+ unsigned src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
|
|
||||||
+ s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width);
|
|
||||||
+ unsigned src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
|
|
||||||
+ s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height);
|
|
||||||
int src_stride = DEFAULT_CNTL ?
|
|
||||||
s->regs.src_pitch : s->regs.default_pitch;
|
|
||||||
+ if (!src_stride) {
|
|
||||||
+ qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
uint8_t *src_bits = s->vga.vram_ptr + (DEFAULT_CNTL ?
|
|
||||||
s->regs.src_offset : s->regs.default_offset);
|
|
||||||
|
|
||||||
@@ -137,8 +149,10 @@ void ati_2d_blt(ATIVGAState *s)
|
|
||||||
dst_y * surface_stride(ds),
|
|
||||||
s->regs.dst_height * surface_stride(ds));
|
|
||||||
}
|
|
||||||
- s->regs.dst_x += s->regs.dst_width;
|
|
||||||
- s->regs.dst_y += s->regs.dst_height;
|
|
||||||
+ s->regs.dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ?
|
|
||||||
+ dst_x + s->regs.dst_width : dst_x);
|
|
||||||
+ s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
|
|
||||||
+ dst_y + s->regs.dst_height : dst_y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ROP3_PATCOPY:
|
|
||||||
@@ -179,7 +193,8 @@ void ati_2d_blt(ATIVGAState *s)
|
|
||||||
dst_y * surface_stride(ds),
|
|
||||||
s->regs.dst_height * surface_stride(ds));
|
|
||||||
}
|
|
||||||
- s->regs.dst_y += s->regs.dst_height;
|
|
||||||
+ s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ?
|
|
||||||
+ dst_y + s->regs.dst_height : dst_y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
From 89554d2f71d4c79c5d8e804d90d74f3985d7ded5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
|
||||||
Date: Thu, 4 Jun 2020 14:38:30 +0530
|
|
||||||
Subject: [PATCH 3/9] ati-vga: check mm_index before recursive call
|
|
||||||
(CVE-2020-13800)
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
While accessing VGA registers via ati_mm_read/write routines,
|
|
||||||
a guest may set 's->regs.mm_index' such that it leads to infinite
|
|
||||||
recursion. Check mm_index value to avoid such recursion. Log an
|
|
||||||
error message for wrong values.
|
|
||||||
|
|
||||||
Reported-by: Ren Ding <rding@gatech.edu>
|
|
||||||
Reported-by: Hanqing Zhao <hanqing@gatech.edu>
|
|
||||||
Reported-by: Yi Ren <c4tren@gmail.com>
|
|
||||||
Message-id: 20200604090830.33885-1-ppandit@redhat.com
|
|
||||||
Suggested-by: BALATON Zoltan <balaton@eik.bme.hu>
|
|
||||||
Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
|
||||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
||||||
---
|
|
||||||
hw/display/ati.c | 10 ++++++++--
|
|
||||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/display/ati.c b/hw/display/ati.c
|
|
||||||
index a747c4cc98..5943040416 100644
|
|
||||||
--- a/hw/display/ati.c
|
|
||||||
+++ b/hw/display/ati.c
|
|
||||||
@@ -261,8 +261,11 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
|
|
||||||
if (idx <= s->vga.vram_size - size) {
|
|
||||||
val = ldn_le_p(s->vga.vram_ptr + idx, size);
|
|
||||||
}
|
|
||||||
- } else {
|
|
||||||
+ } else if (s->regs.mm_index > MM_DATA + 3) {
|
|
||||||
val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size);
|
|
||||||
+ } else {
|
|
||||||
+ qemu_log_mask(LOG_GUEST_ERROR,
|
|
||||||
+ "ati_mm_read: mm_index too small: %u\n", s->regs.mm_index);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BIOS_0_SCRATCH ... BUS_CNTL - 1:
|
|
||||||
@@ -472,8 +475,11 @@ static void ati_mm_write(void *opaque, hwaddr addr,
|
|
||||||
if (idx <= s->vga.vram_size - size) {
|
|
||||||
stn_le_p(s->vga.vram_ptr + idx, size, data);
|
|
||||||
}
|
|
||||||
- } else {
|
|
||||||
+ } else if (s->regs.mm_index > MM_DATA + 3) {
|
|
||||||
ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size);
|
|
||||||
+ } else {
|
|
||||||
+ qemu_log_mask(LOG_GUEST_ERROR,
|
|
||||||
+ "ati_mm_write: mm_index too small: %u\n", s->regs.mm_index);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BIOS_0_SCRATCH ... BUS_CNTL - 1:
|
|
||||||
--
|
|
||||||
2.25.1
|
|
||||||
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
From d0c4e8cc25dc3bfed1659c35fb59b2f0418ba1d5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Volker=20R=C3=BCmelin?= <vr_qemu@t-online.de>
|
|
||||||
Date: Thu, 19 Dec 2019 21:34:05 +0100
|
|
||||||
Subject: [PATCH 2/8] audio: fix integer overflow
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Tell the compiler to do a 32bit * 32bit -> 64bit multiplication
|
|
||||||
because period_ticks is a 64bit variable. The overflow occurs
|
|
||||||
for audio timer periods larger than 4294967us.
|
|
||||||
|
|
||||||
Fixes: be1092afa0 "audio: fix audio timer rate conversion bug"
|
|
||||||
|
|
||||||
Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
|
|
||||||
Message-id: 8893a235-66a8-8fbe-7d95-862e29da90b1@t-online.de
|
|
||||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
||||||
---
|
|
||||||
audio/audio.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/audio/audio.c b/audio/audio.c
|
|
||||||
index 05adf7f..efcb5d4 100644
|
|
||||||
--- a/audio/audio.c
|
|
||||||
+++ b/audio/audio.c
|
|
||||||
@@ -1473,7 +1473,7 @@ static int audio_init(Audiodev *dev)
|
|
||||||
if (dev->timer_period <= 0) {
|
|
||||||
s->period_ticks = 1;
|
|
||||||
} else {
|
|
||||||
- s->period_ticks = dev->timer_period * SCALE_US;
|
|
||||||
+ s->period_ticks = dev->timer_period * (int64_t)SCALE_US;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
From 0b66aef5389d622434128fc7db9abd2cd4724b51 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Date: Wed, 3 Jun 2020 16:03:19 +0100
|
|
||||||
Subject: [PATCH] backup: Improve error for bdrv_getlength() failure
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Message-id: <20200603160325.67506-6-kwolf@redhat.com>
|
|
||||||
Patchwork-id: 97103
|
|
||||||
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 05/11] backup: Improve error for bdrv_getlength() failure
|
|
||||||
Bugzilla: 1778593
|
|
||||||
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
||||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
||||||
|
|
||||||
bdrv_get_device_name() will be an empty string with modern management
|
|
||||||
tools that don't use -drive. Use bdrv_get_device_or_node_name() instead
|
|
||||||
so that the node name is used if the BlockBackend is anonymous.
|
|
||||||
|
|
||||||
While at it, start with upper case to make the message consistent with
|
|
||||||
the rest of the function.
|
|
||||||
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Reviewed-by: Alberto Garcia <berto@igalia.com>
|
|
||||||
Message-Id: <20200430142755.315494-3-kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
(cherry picked from commit 58226634c4b02af7b10862f7fbd3610a344bfb7f)
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index 8761f1f9a7..88354dcb32 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -613,8 +613,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
|
|
||||||
len = bdrv_getlength(bs);
|
|
||||||
if (len < 0) {
|
|
||||||
- error_setg_errno(errp, -len, "unable to get length for '%s'",
|
|
||||||
- bdrv_get_device_name(bs));
|
|
||||||
+ error_setg_errno(errp, -len, "Unable to get length for '%s'",
|
|
||||||
+ bdrv_get_device_or_node_name(bs));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
From 2892a4b1f7dfc75e06d0ce770d44a062b6334eb0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ying Fang <fangying1@huawei.com>
|
|
||||||
Date: Wed, 15 Apr 2020 17:03:54 +0800
|
|
||||||
Subject: [PATCH] bios-tables-test: prepare to change ARM virt ACPI DSDT
|
|
||||||
|
|
||||||
We will change ARM virt ACPI DSDT table in order to add the cpufreq device,
|
|
||||||
which use ACPI CPPC to show CPU frequency info to guest.
|
|
||||||
|
|
||||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
|
||||||
---
|
|
||||||
tests/bios-tables-test-allowed-diff.h | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h
|
|
||||||
index dfb8523c..32a401ae 100644
|
|
||||||
--- a/tests/bios-tables-test-allowed-diff.h
|
|
||||||
+++ b/tests/bios-tables-test-allowed-diff.h
|
|
||||||
@@ -1 +1,4 @@
|
|
||||||
/* List of comma-separated changed AML files to ignore */
|
|
||||||
+"tests/data/acpi/virt/DSDT",
|
|
||||||
+"tests/data/acpi/virt/DSDT.memhp",
|
|
||||||
+"tests/data/acpi/virt/DSDT.numamem",
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
From d9b88f7e0d56feb4d7daa2506e2756fc48e975a1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Max Reitz <mreitz@redhat.com>
|
|
||||||
Date: Fri, 1 Nov 2019 16:25:09 +0100
|
|
||||||
Subject: [PATCH] block: Add bdrv_co_get_self_request()
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20191101152510.11719-3-mreitz@redhat.com
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit c28107e9e55b11cd35cf3dc2505e3e69d10dcf13)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/io.c | 18 ++++++++++++++++++
|
|
||||||
include/block/block_int.h | 1 +
|
|
||||||
2 files changed, 19 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/block/io.c b/block/io.c
|
|
||||||
index d4ceaaa2ce..65b5102714 100644
|
|
||||||
--- a/block/io.c
|
|
||||||
+++ b/block/io.c
|
|
||||||
@@ -721,6 +721,24 @@ static bool is_request_serialising_and_aligned(BdrvTrackedRequest *req)
|
|
||||||
(req->bytes == req->overlap_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * Return the tracked request on @bs for the current coroutine, or
|
|
||||||
+ * NULL if there is none.
|
|
||||||
+ */
|
|
||||||
+BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
|
|
||||||
+{
|
|
||||||
+ BdrvTrackedRequest *req;
|
|
||||||
+ Coroutine *self = qemu_coroutine_self();
|
|
||||||
+
|
|
||||||
+ QLIST_FOREACH(req, &bs->tracked_requests, list) {
|
|
||||||
+ if (req->co == self) {
|
|
||||||
+ return req;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* Round a region to cluster boundaries
|
|
||||||
*/
|
|
||||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
|
||||||
index 4465b02242..05ee6b4866 100644
|
|
||||||
--- a/include/block/block_int.h
|
|
||||||
+++ b/include/block/block_int.h
|
|
||||||
@@ -964,6 +964,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent);
|
|
||||||
|
|
||||||
bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self);
|
|
||||||
void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align);
|
|
||||||
+BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs);
|
|
||||||
|
|
||||||
int get_tmp_filename(char *filename, int size);
|
|
||||||
BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,226 +0,0 @@
|
|||||||
From 3464a135565d718d0fedadd67081a0f76d81a9c6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Date: Thu, 21 Jan 2021 15:46:50 +0800
|
|
||||||
Subject: [PATCH] block: Add error retry param setting
|
|
||||||
|
|
||||||
Add "retry_interval" and "retry_timeout" parameter for drive and device
|
|
||||||
option. These parameter are valid only when werror/rerror=retry.
|
|
||||||
|
|
||||||
eg. --drive file=image,rerror=retry,retry_interval=1000,retry_timeout=5000
|
|
||||||
|
|
||||||
Signed-off-by: Jiahui Cen <cenjiahui(a)huawei.com>
|
|
||||||
Signed-off-by: Ying Fang <fangying1(a)huawei.com>
|
|
||||||
---
|
|
||||||
block/block-backend.c | 13 +++++++--
|
|
||||||
blockdev.c | 50 ++++++++++++++++++++++++++++++++++
|
|
||||||
hw/block/block.c | 10 +++++++
|
|
||||||
include/hw/block/block.h | 7 ++++-
|
|
||||||
include/sysemu/block-backend.h | 5 ++++
|
|
||||||
5 files changed, 81 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index 0fe99ffe52..2d812e2254 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -31,9 +31,6 @@
|
|
||||||
|
|
||||||
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
|
|
||||||
|
|
||||||
-/* block backend default retry interval */
|
|
||||||
-#define BLOCK_BACKEND_DEFAULT_RETRY_INTERVAL 1000
|
|
||||||
-
|
|
||||||
typedef struct BlockBackendAioNotifier {
|
|
||||||
void (*attached_aio_context)(AioContext *new_context, void *opaque);
|
|
||||||
void (*detach_aio_context)(void *opaque);
|
|
||||||
@@ -1633,6 +1630,16 @@ void blk_drain_all(void)
|
|
||||||
bdrv_drain_all_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
+void blk_set_on_error_retry_interval(BlockBackend *blk, int64_t interval)
|
|
||||||
+{
|
|
||||||
+ blk->retry_interval = interval;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void blk_set_on_error_retry_timeout(BlockBackend *blk, int64_t timeout)
|
|
||||||
+{
|
|
||||||
+ blk->retry_timeout = timeout;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static bool blk_error_retry_timeout(BlockBackend *blk)
|
|
||||||
{
|
|
||||||
/* No timeout set, infinite retries. */
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 0f49fd290e..99c92b96d2 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -470,6 +470,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
|
||||||
const char *buf;
|
|
||||||
int bdrv_flags = 0;
|
|
||||||
int on_read_error, on_write_error;
|
|
||||||
+ int64_t retry_interval, retry_timeout;
|
|
||||||
bool account_invalid, account_failed;
|
|
||||||
bool writethrough, read_only;
|
|
||||||
BlockBackend *blk;
|
|
||||||
@@ -565,6 +566,10 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ retry_interval = qemu_opt_get_number(opts, "retry_interval",
|
|
||||||
+ BLOCK_BACKEND_DEFAULT_RETRY_INTERVAL);
|
|
||||||
+ retry_timeout = qemu_opt_get_number(opts, "retry_timeout", 0);
|
|
||||||
+
|
|
||||||
if (snapshot) {
|
|
||||||
bdrv_flags |= BDRV_O_SNAPSHOT;
|
|
||||||
}
|
|
||||||
@@ -629,6 +634,11 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
|
||||||
|
|
||||||
blk_set_enable_write_cache(blk, !writethrough);
|
|
||||||
blk_set_on_error(blk, on_read_error, on_write_error);
|
|
||||||
+ if (on_read_error == BLOCKDEV_ON_ERROR_RETRY ||
|
|
||||||
+ on_write_error == BLOCKDEV_ON_ERROR_RETRY) {
|
|
||||||
+ blk_set_on_error_retry_interval(blk, retry_interval);
|
|
||||||
+ blk_set_on_error_retry_timeout(blk, retry_timeout);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (!monitor_add_blk(blk, id, errp)) {
|
|
||||||
blk_unref(blk);
|
|
||||||
@@ -754,6 +764,14 @@ QemuOptsList qemu_legacy_drive_opts = {
|
|
||||||
.name = "werror",
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "write error action",
|
|
||||||
+ },{
|
|
||||||
+ .name = "retry_interval",
|
|
||||||
+ .type = QEMU_OPT_NUMBER,
|
|
||||||
+ .help = "interval for retry action in millisecond",
|
|
||||||
+ },{
|
|
||||||
+ .name = "retry_timeout",
|
|
||||||
+ .type = QEMU_OPT_NUMBER,
|
|
||||||
+ .help = "timeout for retry action in millisecond",
|
|
||||||
},{
|
|
||||||
.name = "copy-on-read",
|
|
||||||
.type = QEMU_OPT_BOOL,
|
|
||||||
@@ -776,6 +794,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type,
|
|
||||||
BlockInterfaceType type;
|
|
||||||
int max_devs, bus_id, unit_id, index;
|
|
||||||
const char *werror, *rerror;
|
|
||||||
+ int64_t retry_interval, retry_timeout;
|
|
||||||
bool read_only = false;
|
|
||||||
bool copy_on_read;
|
|
||||||
const char *filename;
|
|
||||||
@@ -992,6 +1011,29 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type,
|
|
||||||
qdict_put_str(bs_opts, "rerror", rerror);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (qemu_opt_find(legacy_opts, "retry_interval")) {
|
|
||||||
+ if ((werror == NULL || strcmp(werror, "retry")) &&
|
|
||||||
+ (rerror == NULL || strcmp(rerror, "retry"))) {
|
|
||||||
+ error_setg(errp, "retry_interval is only supported "
|
|
||||||
+ "by werror/rerror=retry");
|
|
||||||
+ goto fail;
|
|
||||||
+ }
|
|
||||||
+ retry_interval = qemu_opt_get_number(legacy_opts, "retry_interval",
|
|
||||||
+ BLOCK_BACKEND_DEFAULT_RETRY_INTERVAL);
|
|
||||||
+ qdict_put_int(bs_opts, "retry_interval", retry_interval);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (qemu_opt_find(legacy_opts, "retry_timeout")) {
|
|
||||||
+ if ((werror == NULL || strcmp(werror, "retry")) &&
|
|
||||||
+ (rerror == NULL || strcmp(rerror, "retry"))) {
|
|
||||||
+ error_setg(errp, "retry_timeout is only supported "
|
|
||||||
+ "by werror/rerror=retry");
|
|
||||||
+ goto fail;
|
|
||||||
+ }
|
|
||||||
+ retry_timeout = qemu_opt_get_number(legacy_opts, "retry_timeout", 0);
|
|
||||||
+ qdict_put_int(bs_opts, "retry_timeout", retry_timeout);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Actual block device init: Functionality shared with blockdev-add */
|
|
||||||
blk = blockdev_init(filename, bs_opts, &local_err);
|
|
||||||
bs_opts = NULL;
|
|
||||||
@@ -4593,6 +4635,14 @@ QemuOptsList qemu_common_drive_opts = {
|
|
||||||
.name = "werror",
|
|
||||||
.type = QEMU_OPT_STRING,
|
|
||||||
.help = "write error action",
|
|
||||||
+ },{
|
|
||||||
+ .name = "retry_interval",
|
|
||||||
+ .type = QEMU_OPT_NUMBER,
|
|
||||||
+ .help = "interval for retry action in millisecond",
|
|
||||||
+ },{
|
|
||||||
+ .name = "retry_timeout",
|
|
||||||
+ .type = QEMU_OPT_NUMBER,
|
|
||||||
+ .help = "timeout for retry action in millisecond",
|
|
||||||
},{
|
|
||||||
.name = BDRV_OPT_READ_ONLY,
|
|
||||||
.type = QEMU_OPT_BOOL,
|
|
||||||
diff --git a/hw/block/block.c b/hw/block/block.c
|
|
||||||
index bf56c7612b..56141940ca 100644
|
|
||||||
--- a/hw/block/block.c
|
|
||||||
+++ b/hw/block/block.c
|
|
||||||
@@ -134,6 +134,16 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
|
|
||||||
blk_set_enable_write_cache(blk, wce);
|
|
||||||
blk_set_on_error(blk, rerror, werror);
|
|
||||||
|
|
||||||
+ if (rerror == BLOCKDEV_ON_ERROR_RETRY ||
|
|
||||||
+ werror == BLOCKDEV_ON_ERROR_RETRY) {
|
|
||||||
+ if (conf->retry_interval >= 0) {
|
|
||||||
+ blk_set_on_error_retry_interval(blk, conf->retry_interval);
|
|
||||||
+ }
|
|
||||||
+ if (conf->retry_timeout >= 0) {
|
|
||||||
+ blk_set_on_error_retry_timeout(blk, conf->retry_timeout);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
|
|
||||||
index 607539057a..d12603aabd 100644
|
|
||||||
--- a/include/hw/block/block.h
|
|
||||||
+++ b/include/hw/block/block.h
|
|
||||||
@@ -30,6 +30,8 @@ typedef struct BlockConf {
|
|
||||||
bool share_rw;
|
|
||||||
BlockdevOnError rerror;
|
|
||||||
BlockdevOnError werror;
|
|
||||||
+ int64_t retry_interval;
|
|
||||||
+ int64_t retry_timeout;
|
|
||||||
} BlockConf;
|
|
||||||
|
|
||||||
static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
|
||||||
@@ -71,7 +73,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
|
||||||
DEFINE_PROP_BLOCKDEV_ON_ERROR("rerror", _state, _conf.rerror, \
|
|
||||||
BLOCKDEV_ON_ERROR_AUTO), \
|
|
||||||
DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \
|
|
||||||
- BLOCKDEV_ON_ERROR_AUTO)
|
|
||||||
+ BLOCKDEV_ON_ERROR_AUTO), \
|
|
||||||
+ DEFINE_PROP_INT64("retry_interval", _state, _conf.retry_interval, \
|
|
||||||
+ -1), \
|
|
||||||
+ DEFINE_PROP_INT64("retry_timeout", _state, _conf.retry_timeout, -1)
|
|
||||||
|
|
||||||
/* Backend access helpers */
|
|
||||||
|
|
||||||
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
|
|
||||||
index 58dde446ca..dc10e507ae 100644
|
|
||||||
--- a/include/sysemu/block-backend.h
|
|
||||||
+++ b/include/sysemu/block-backend.h
|
|
||||||
@@ -25,6 +25,9 @@
|
|
||||||
*/
|
|
||||||
#include "block/block.h"
|
|
||||||
|
|
||||||
+/* block backend default retry interval */
|
|
||||||
+#define BLOCK_BACKEND_DEFAULT_RETRY_INTERVAL 1000
|
|
||||||
+
|
|
||||||
/* Callbacks for block device models */
|
|
||||||
typedef struct BlockDevOps {
|
|
||||||
/*
|
|
||||||
@@ -184,6 +187,8 @@ void blk_inc_in_flight(BlockBackend *blk);
|
|
||||||
void blk_dec_in_flight(BlockBackend *blk);
|
|
||||||
void blk_drain(BlockBackend *blk);
|
|
||||||
void blk_drain_all(void);
|
|
||||||
+void blk_set_on_error_retry_interval(BlockBackend *blk, int64_t interval);
|
|
||||||
+void blk_set_on_error_retry_timeout(BlockBackend *blk, int64_t timeout);
|
|
||||||
void blk_error_retry_reset_timeout(BlockBackend *blk);
|
|
||||||
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
|
|
||||||
BlockdevOnError on_write_error);
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
From 6642b2c6fcad2e1099c61b56f4fe78f3180d005e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Date: Thu, 18 Mar 2021 19:45:11 +0800
|
|
||||||
Subject: [PATCH] block: Add sanity check when setting retry parameters
|
|
||||||
|
|
||||||
Add sanity check when setting retry parameters to avoid invalid retry
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
Signed-off-by: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
---
|
|
||||||
hw/core/qdev-properties.c | 45 ++++++++++++++++++++++++++++++++++++
|
|
||||||
include/hw/block/block.h | 7 +++---
|
|
||||||
include/hw/qdev-properties.h | 8 +++++++
|
|
||||||
3 files changed, 57 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
|
|
||||||
index 709f9e0f9d..2601091f8f 100644
|
|
||||||
--- a/hw/core/qdev-properties.c
|
|
||||||
+++ b/hw/core/qdev-properties.c
|
|
||||||
@@ -628,6 +628,51 @@ const PropertyInfo qdev_prop_blockdev_on_error = {
|
|
||||||
.set_default_value = set_default_value_enum,
|
|
||||||
};
|
|
||||||
|
|
||||||
+static void set_retry_time(Object *obj, Visitor *v, const char *name,
|
|
||||||
+ void *opaque, Error **errp)
|
|
||||||
+{
|
|
||||||
+ DeviceState *dev = DEVICE(obj);
|
|
||||||
+ Property *prop = opaque;
|
|
||||||
+ int64_t value, *ptr = qdev_get_prop_ptr(dev, prop);
|
|
||||||
+ Error *local_err = NULL;
|
|
||||||
+
|
|
||||||
+ if (dev->realized) {
|
|
||||||
+ qdev_prop_set_after_realize(dev, name, errp);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ visit_type_int64(v, name, &value, &local_err);
|
|
||||||
+ if (local_err) {
|
|
||||||
+ error_propagate(errp, local_err);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* value should not be negative */
|
|
||||||
+ if (value < 0) {
|
|
||||||
+ error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
|
|
||||||
+ dev->id ? : "", name, (int64_t)value, 0L, LONG_MAX);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *ptr = value;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+const PropertyInfo qdev_prop_blockdev_retry_interval = {
|
|
||||||
+ .name = "BlockdevRetryInterval",
|
|
||||||
+ .description = "Interval for retry error handling policy",
|
|
||||||
+ .get = get_int64,
|
|
||||||
+ .set = set_retry_time,
|
|
||||||
+ .set_default_value = set_default_value_int,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+const PropertyInfo qdev_prop_blockdev_retry_timeout = {
|
|
||||||
+ .name = "BlockdevRetryTimeout",
|
|
||||||
+ .description = "Timeout for retry error handling policy",
|
|
||||||
+ .get = get_int64,
|
|
||||||
+ .set = set_retry_time,
|
|
||||||
+ .set_default_value = set_default_value_int,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* --- BIOS CHS translation */
|
|
||||||
|
|
||||||
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
|
|
||||||
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
|
|
||||||
index d12603aabd..c5276fec0d 100644
|
|
||||||
--- a/include/hw/block/block.h
|
|
||||||
+++ b/include/hw/block/block.h
|
|
||||||
@@ -74,9 +74,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
|
|
||||||
BLOCKDEV_ON_ERROR_AUTO), \
|
|
||||||
DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \
|
|
||||||
BLOCKDEV_ON_ERROR_AUTO), \
|
|
||||||
- DEFINE_PROP_INT64("retry_interval", _state, _conf.retry_interval, \
|
|
||||||
- -1), \
|
|
||||||
- DEFINE_PROP_INT64("retry_timeout", _state, _conf.retry_timeout, -1)
|
|
||||||
+ DEFINE_PROP_BLOCKDEV_RETRY_INTERVAL("retry_interval", _state, \
|
|
||||||
+ _conf.retry_interval, 1000), \
|
|
||||||
+ DEFINE_PROP_BLOCKDEV_RETRY_TIMEOUT("retry_timeout", _state, \
|
|
||||||
+ _conf.retry_timeout, 0)
|
|
||||||
|
|
||||||
/* Backend access helpers */
|
|
||||||
|
|
||||||
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
|
|
||||||
index a22a532eb8..d7742be3bc 100644
|
|
||||||
--- a/include/hw/qdev-properties.h
|
|
||||||
+++ b/include/hw/qdev-properties.h
|
|
||||||
@@ -26,6 +26,8 @@ extern const PropertyInfo qdev_prop_on_off_auto;
|
|
||||||
extern const PropertyInfo qdev_prop_compress_method;
|
|
||||||
extern const PropertyInfo qdev_prop_losttickpolicy;
|
|
||||||
extern const PropertyInfo qdev_prop_blockdev_on_error;
|
|
||||||
+extern const PropertyInfo qdev_prop_blockdev_retry_interval;
|
|
||||||
+extern const PropertyInfo qdev_prop_blockdev_retry_timeout;
|
|
||||||
extern const PropertyInfo qdev_prop_bios_chs_trans;
|
|
||||||
extern const PropertyInfo qdev_prop_fdc_drive_type;
|
|
||||||
extern const PropertyInfo qdev_prop_drive;
|
|
||||||
@@ -215,6 +217,12 @@ extern const PropertyInfo qdev_prop_pcie_link_width;
|
|
||||||
#define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \
|
|
||||||
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
|
|
||||||
BlockdevOnError)
|
|
||||||
+#define DEFINE_PROP_BLOCKDEV_RETRY_INTERVAL(_n, _s, _f, _d) \
|
|
||||||
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_retry_interval, \
|
|
||||||
+ int64_t)
|
|
||||||
+#define DEFINE_PROP_BLOCKDEV_RETRY_TIMEOUT(_n, _s, _f, _d) \
|
|
||||||
+ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_retry_timeout, \
|
|
||||||
+ int64_t)
|
|
||||||
#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
|
|
||||||
DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
|
|
||||||
#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
From 6a39af8880c18fb3bcbfb715aef909c64286524e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Eric Blake <eblake@redhat.com>
|
|
||||||
Date: Fri, 20 Mar 2020 13:36:20 -0500
|
|
||||||
Subject: [PATCH 04/14] block: Avoid memleak on qcow2 image info failure
|
|
||||||
|
|
||||||
If we fail to get bitmap info, we must not leak the encryption info.
|
|
||||||
|
|
||||||
Fixes: b8968c875f403
|
|
||||||
Fixes: Coverity CID 1421894
|
|
||||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Message-Id: <20200320183620.1112123-1-eblake@redhat.com>
|
|
||||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
|
|
||||||
Tested-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
|
||||||
---
|
|
||||||
block/qcow2.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
|
||||||
index 27c54b9905aa..0f4b0940d457 100644
|
|
||||||
--- a/block/qcow2.c
|
|
||||||
+++ b/block/qcow2.c
|
|
||||||
@@ -4588,6 +4588,7 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
|
|
||||||
if (local_err) {
|
|
||||||
error_propagate(errp, local_err);
|
|
||||||
qapi_free_ImageInfoSpecific(spec_info);
|
|
||||||
+ qapi_free_QCryptoBlockInfo(encrypt_info);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
From e94c1625c0f8155740b1bb7b2c749df759e04526 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Eric Blake <eblake@redhat.com>
|
|
||||||
Date: Wed, 10 Jun 2020 18:32:02 -0400
|
|
||||||
Subject: [PATCH] block: Call attention to truncation of long NBD exports
|
|
||||||
|
|
||||||
RH-Author: Eric Blake <eblake@redhat.com>
|
|
||||||
Message-id: <20200610183202.3780750-3-eblake@redhat.com>
|
|
||||||
Patchwork-id: 97495
|
|
||||||
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block: Call attention to truncation of long NBD exports
|
|
||||||
Bugzilla: 1845384
|
|
||||||
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
|
|
||||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
|
|
||||||
Commit 93676c88 relaxed our NBD client code to request export names up
|
|
||||||
to the NBD protocol maximum of 4096 bytes without NUL terminator, even
|
|
||||||
though the block layer can't store anything longer than 4096 bytes
|
|
||||||
including NUL terminator for display to the user. Since this means
|
|
||||||
there are some export names where we have to truncate things, we can
|
|
||||||
at least try to make the truncation a bit more obvious for the user.
|
|
||||||
Note that in spite of the truncated display name, we can still
|
|
||||||
communicate with an NBD server using such a long export name; this was
|
|
||||||
deemed nicer than refusing to even connect to such a server (since the
|
|
||||||
server may not be under our control, and since determining our actual
|
|
||||||
length limits gets tricky when nbd://host:port/export and
|
|
||||||
nbd+unix:///export?socket=/path are themselves variable-length
|
|
||||||
expansions beyond the export name but count towards the block layer
|
|
||||||
name length).
|
|
||||||
|
|
||||||
Reported-by: Xueqiang Wei <xuwei@redhat.com>
|
|
||||||
Fixes: https://bugzilla.redhat.com/1843684
|
|
||||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-Id: <20200610163741.3745251-3-eblake@redhat.com>
|
|
||||||
(cherry picked from commit 5c86bdf1208916ece0b87e1151c9b48ee54faa3e)
|
|
||||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Signed-off-by: Eduardo Lima (Etrunko) <etrunko@redhat.com>
|
|
||||||
---
|
|
||||||
block.c | 7 +++++--
|
|
||||||
block/nbd.c | 21 +++++++++++++--------
|
|
||||||
2 files changed, 18 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block.c b/block.c
|
|
||||||
index 38880eabf8..ba36b53a00 100644
|
|
||||||
--- a/block.c
|
|
||||||
+++ b/block.c
|
|
||||||
@@ -6444,8 +6444,11 @@ void bdrv_refresh_filename(BlockDriverState *bs)
|
|
||||||
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
|
|
||||||
} else {
|
|
||||||
QString *json = qobject_to_json(QOBJECT(bs->full_open_options));
|
|
||||||
- snprintf(bs->filename, sizeof(bs->filename), "json:%s",
|
|
||||||
- qstring_get_str(json));
|
|
||||||
+ if (snprintf(bs->filename, sizeof(bs->filename), "json:%s",
|
|
||||||
+ qstring_get_str(json)) >= sizeof(bs->filename)) {
|
|
||||||
+ /* Give user a hint if we truncated things. */
|
|
||||||
+ strcpy(bs->filename + sizeof(bs->filename) - 4, "...");
|
|
||||||
+ }
|
|
||||||
qobject_unref(json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/block/nbd.c b/block/nbd.c
|
|
||||||
index 3977b1efc7..63cdd051ab 100644
|
|
||||||
--- a/block/nbd.c
|
|
||||||
+++ b/block/nbd.c
|
|
||||||
@@ -1714,6 +1714,7 @@ static void nbd_refresh_filename(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
BDRVNBDState *s = bs->opaque;
|
|
||||||
const char *host = NULL, *port = NULL, *path = NULL;
|
|
||||||
+ size_t len = 0;
|
|
||||||
|
|
||||||
if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) {
|
|
||||||
const InetSocketAddress *inet = &s->saddr->u.inet;
|
|
||||||
@@ -1726,17 +1727,21 @@ static void nbd_refresh_filename(BlockDriverState *bs)
|
|
||||||
} /* else can't represent as pseudo-filename */
|
|
||||||
|
|
||||||
if (path && s->export) {
|
|
||||||
- snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
- "nbd+unix:///%s?socket=%s", s->export, path);
|
|
||||||
+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
+ "nbd+unix:///%s?socket=%s", s->export, path);
|
|
||||||
} else if (path && !s->export) {
|
|
||||||
- snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
- "nbd+unix://?socket=%s", path);
|
|
||||||
+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
+ "nbd+unix://?socket=%s", path);
|
|
||||||
} else if (host && s->export) {
|
|
||||||
- snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
- "nbd://%s:%s/%s", host, port, s->export);
|
|
||||||
+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
+ "nbd://%s:%s/%s", host, port, s->export);
|
|
||||||
} else if (host && !s->export) {
|
|
||||||
- snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
- "nbd://%s:%s", host, port);
|
|
||||||
+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
|
||||||
+ "nbd://%s:%s", host, port);
|
|
||||||
+ }
|
|
||||||
+ if (len > sizeof(bs->exact_filename)) {
|
|
||||||
+ /* Name is too long to represent exactly, so leave it empty. */
|
|
||||||
+ bs->exact_filename[0] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
From ec96b9f64c239736003413d70dc3999ad0b8271c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Date: Tue, 10 Mar 2020 12:38:29 +0100
|
|
||||||
Subject: [PATCH] block: Fix cross-AioContext blockdev-snapshot
|
|
||||||
|
|
||||||
external_snapshot_prepare() tries to move the overlay to the AioContext
|
|
||||||
of the backing file (the snapshotted node). However, it's possible that
|
|
||||||
this doesn't work, but the backing file can instead be moved to the
|
|
||||||
overlay's AioContext (e.g. opening the backing chain for a mirror
|
|
||||||
target).
|
|
||||||
|
|
||||||
bdrv_append() already indirectly uses bdrv_attach_node(), which takes
|
|
||||||
care to move nodes to make sure they use the same AioContext and which
|
|
||||||
tries both directions.
|
|
||||||
|
|
||||||
So the problem has a simple fix: Just delete the unnecessary extra
|
|
||||||
bdrv_try_set_aio_context() call in external_snapshot_prepare() and
|
|
||||||
instead assert in bdrv_append() that both nodes were indeed moved to the
|
|
||||||
same AioContext.
|
|
||||||
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Message-Id: <20200310113831.27293-6-kwolf@redhat.com>
|
|
||||||
Tested-by: Peter Krempa <pkrempa@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
block.c | 1 +
|
|
||||||
blockdev.c | 16 ----------------
|
|
||||||
2 files changed, 1 insertion(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block.c b/block.c
|
|
||||||
index ba36b53a00..824025f781 100644
|
|
||||||
--- a/block.c
|
|
||||||
+++ b/block.c
|
|
||||||
@@ -4165,6 +4165,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
|
|
||||||
bdrv_ref(from);
|
|
||||||
|
|
||||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
|
||||||
+ assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to));
|
|
||||||
bdrv_drained_begin(from);
|
|
||||||
|
|
||||||
/* Put all parents into @list and calculate their cumulative permissions */
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 79112be2e6..d1a3b6a630 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -1578,8 +1578,6 @@ static void external_snapshot_prepare(BlkActionState *common,
|
|
||||||
DO_UPCAST(ExternalSnapshotState, common, common);
|
|
||||||
TransactionAction *action = common->action;
|
|
||||||
AioContext *aio_context;
|
|
||||||
- AioContext *old_context;
|
|
||||||
- int ret;
|
|
||||||
|
|
||||||
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
|
|
||||||
* purpose but a different set of parameters */
|
|
||||||
@@ -1719,20 +1717,6 @@ static void external_snapshot_prepare(BlkActionState *common,
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
|
||||||
- old_context = bdrv_get_aio_context(state->new_bs);
|
|
||||||
- aio_context_release(aio_context);
|
|
||||||
- aio_context_acquire(old_context);
|
|
||||||
-
|
|
||||||
- ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
|
|
||||||
-
|
|
||||||
- aio_context_release(old_context);
|
|
||||||
- aio_context_acquire(aio_context);
|
|
||||||
-
|
|
||||||
- if (ret < 0) {
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
/* This removes our old bs and adds the new bs. This is an operation that
|
|
||||||
* can fail, so we need to do it in .prepare; undoing it for abort is
|
|
||||||
* always possible. */
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
From 590cff8230749794ba09b38f3ea4eb6b0f2f73b5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Max Reitz <mreitz@redhat.com>
|
|
||||||
Date: Fri, 1 Nov 2019 16:25:08 +0100
|
|
||||||
Subject: [PATCH] block: Make wait/mark serialising requests public
|
|
||||||
|
|
||||||
Make both bdrv_mark_request_serialising() and
|
|
||||||
bdrv_wait_serialising_requests() public so they can be used from block
|
|
||||||
drivers.
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20191101152510.11719-2-mreitz@redhat.com
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit 304d9d7f034ff7f5e1e66a65b7f720f63a72c57e)
|
|
||||||
Conflicts:
|
|
||||||
block/io.c
|
|
||||||
*drop context dependency on 1acc3466a2
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/io.c | 24 ++++++++++++------------
|
|
||||||
include/block/block_int.h | 3 +++
|
|
||||||
2 files changed, 15 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/io.c b/block/io.c
|
|
||||||
index 07d2d825c3..d4ceaaa2ce 100644
|
|
||||||
--- a/block/io.c
|
|
||||||
+++ b/block/io.c
|
|
||||||
@@ -694,7 +694,7 @@ static void tracked_request_begin(BdrvTrackedRequest *req,
|
|
||||||
qemu_co_mutex_unlock(&bs->reqs_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
|
|
||||||
+void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
|
|
||||||
{
|
|
||||||
int64_t overlap_offset = req->offset & ~(align - 1);
|
|
||||||
uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align)
|
|
||||||
@@ -784,7 +784,7 @@ void bdrv_dec_in_flight(BlockDriverState *bs)
|
|
||||||
bdrv_wakeup(bs);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
|
|
||||||
+bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self)
|
|
||||||
{
|
|
||||||
BlockDriverState *bs = self->bs;
|
|
||||||
BdrvTrackedRequest *req;
|
|
||||||
@@ -1340,14 +1340,14 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
|
|
||||||
* with each other for the same cluster. For example, in copy-on-read
|
|
||||||
* it ensures that the CoR read and write operations are atomic and
|
|
||||||
* guest writes cannot interleave between them. */
|
|
||||||
- mark_request_serialising(req, bdrv_get_cluster_size(bs));
|
|
||||||
+ bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BDRV_REQ_SERIALISING is only for write operation */
|
|
||||||
assert(!(flags & BDRV_REQ_SERIALISING));
|
|
||||||
|
|
||||||
if (!(flags & BDRV_REQ_NO_SERIALISING)) {
|
|
||||||
- wait_serialising_requests(req);
|
|
||||||
+ bdrv_wait_serialising_requests(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & BDRV_REQ_COPY_ON_READ) {
|
|
||||||
@@ -1736,10 +1736,10 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
|
|
||||||
assert(!(flags & ~BDRV_REQ_MASK));
|
|
||||||
|
|
||||||
if (flags & BDRV_REQ_SERIALISING) {
|
|
||||||
- mark_request_serialising(req, bdrv_get_cluster_size(bs));
|
|
||||||
+ bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs));
|
|
||||||
}
|
|
||||||
|
|
||||||
- waited = wait_serialising_requests(req);
|
|
||||||
+ waited = bdrv_wait_serialising_requests(req);
|
|
||||||
|
|
||||||
assert(!waited || !req->serialising ||
|
|
||||||
is_request_serialising_and_aligned(req));
|
|
||||||
@@ -1905,8 +1905,8 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
|
||||||
|
|
||||||
padding = bdrv_init_padding(bs, offset, bytes, &pad);
|
|
||||||
if (padding) {
|
|
||||||
- mark_request_serialising(req, align);
|
|
||||||
- wait_serialising_requests(req);
|
|
||||||
+ bdrv_mark_request_serialising(req, align);
|
|
||||||
+ bdrv_wait_serialising_requests(req);
|
|
||||||
|
|
||||||
bdrv_padding_rmw_read(child, req, &pad, true);
|
|
||||||
|
|
||||||
@@ -1993,8 +1993,8 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
|
|
||||||
- mark_request_serialising(&req, align);
|
|
||||||
- wait_serialising_requests(&req);
|
|
||||||
+ bdrv_mark_request_serialising(&req, align);
|
|
||||||
+ bdrv_wait_serialising_requests(&req);
|
|
||||||
bdrv_padding_rmw_read(child, &req, &pad, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -3078,7 +3078,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(
|
|
||||||
/* BDRV_REQ_SERIALISING is only for write operation */
|
|
||||||
assert(!(read_flags & BDRV_REQ_SERIALISING));
|
|
||||||
if (!(read_flags & BDRV_REQ_NO_SERIALISING)) {
|
|
||||||
- wait_serialising_requests(&req);
|
|
||||||
+ bdrv_wait_serialising_requests(&req);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
|
|
||||||
@@ -3205,7 +3205,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset,
|
|
||||||
* new area, we need to make sure that no write requests are made to it
|
|
||||||
* concurrently or they might be overwritten by preallocation. */
|
|
||||||
if (new_bytes) {
|
|
||||||
- mark_request_serialising(&req, 1);
|
|
||||||
+ bdrv_mark_request_serialising(&req, 1);
|
|
||||||
}
|
|
||||||
if (bs->read_only) {
|
|
||||||
error_setg(errp, "Image is read-only");
|
|
||||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
|
||||||
index 3aa1e832a8..4465b02242 100644
|
|
||||||
--- a/include/block/block_int.h
|
|
||||||
+++ b/include/block/block_int.h
|
|
||||||
@@ -962,6 +962,9 @@ extern unsigned int bdrv_drain_all_count;
|
|
||||||
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent);
|
|
||||||
void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent);
|
|
||||||
|
|
||||||
+bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self);
|
|
||||||
+void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align);
|
|
||||||
+
|
|
||||||
int get_tmp_filename(char *filename, int size);
|
|
||||||
BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
|
|
||||||
const char *filename);
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
From b353d059bddf4b211c2560e7c123f874ed5c8cf6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: AlexChen <alex.chen@huawei.com>
|
|
||||||
Date: Wed, 21 Oct 2020 17:12:52 +0800
|
|
||||||
Subject: [PATCH] block: Remove unused include
|
|
||||||
|
|
||||||
The "qemu-common.h" include is not used, remove it.
|
|
||||||
|
|
||||||
Reported-by: Euler Robot <euler.robot@huawei.com>
|
|
||||||
Signed-off-by: AlexChen <alex.chen@huawei.com>
|
|
||||||
Message-Id: <5F8FFB94.3030209@huawei.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry-picked from commit 3d86af858e)
|
|
||||||
---
|
|
||||||
block/dmg-lzfse.c | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/block/dmg-lzfse.c b/block/dmg-lzfse.c
|
|
||||||
index 19d25bc646..6798cf4fbf 100644
|
|
||||||
--- a/block/dmg-lzfse.c
|
|
||||||
+++ b/block/dmg-lzfse.c
|
|
||||||
@@ -22,7 +22,6 @@
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#include "qemu/osdep.h"
|
|
||||||
-#include "qemu-common.h"
|
|
||||||
#include "dmg.h"
|
|
||||||
#include <lzfse.h>
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
From f74edc7c8c85874691daf8801c159874ef45aae0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Date: Thu, 21 Jan 2021 15:46:47 +0800
|
|
||||||
Subject: [PATCH] block-backend: Add device specific retry callback
|
|
||||||
|
|
||||||
Add retry_request_cb in BlockDevOps to do device specific retry action.
|
|
||||||
Backend's timer would be registered only when the backend is set 'retry'
|
|
||||||
on errors and the device supports retry action.
|
|
||||||
|
|
||||||
Signed-off-by: Jiahui Cen <cenjiahui(a)huawei.com>
|
|
||||||
Signed-off-by: Ying Fang <fangying1(a)huawei.com>
|
|
||||||
---
|
|
||||||
block/block-backend.c | 8 ++++++++
|
|
||||||
include/sysemu/block-backend.h | 4 ++++
|
|
||||||
2 files changed, 12 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index a9a43b1440..b8f535a5fd 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -958,6 +958,14 @@ void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
|
|
||||||
blk->dev_ops = ops;
|
|
||||||
blk->dev_opaque = opaque;
|
|
||||||
|
|
||||||
+ if ((blk->on_read_error == BLOCKDEV_ON_ERROR_RETRY ||
|
|
||||||
+ blk->on_write_error == BLOCKDEV_ON_ERROR_RETRY) &&
|
|
||||||
+ ops->retry_request_cb) {
|
|
||||||
+ blk->retry_timer = aio_timer_new(blk->ctx, QEMU_CLOCK_REALTIME,
|
|
||||||
+ SCALE_MS, ops->retry_request_cb,
|
|
||||||
+ opaque);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Are we currently quiesced? Should we enforce this right now? */
|
|
||||||
if (blk->quiesce_counter && ops->drained_begin) {
|
|
||||||
ops->drained_begin(opaque);
|
|
||||||
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
|
|
||||||
index 733c4957eb..b58dc6bde8 100644
|
|
||||||
--- a/include/sysemu/block-backend.h
|
|
||||||
+++ b/include/sysemu/block-backend.h
|
|
||||||
@@ -66,6 +66,10 @@ typedef struct BlockDevOps {
|
|
||||||
* Runs when the backend's last drain request ends.
|
|
||||||
*/
|
|
||||||
void (*drained_end)(void *opaque);
|
|
||||||
+ /*
|
|
||||||
+ * Runs when retrying failed requests.
|
|
||||||
+ */
|
|
||||||
+ void (*retry_request_cb)(void *opaque);
|
|
||||||
} BlockDevOps;
|
|
||||||
|
|
||||||
/* This struct is embedded in (the private) BlockBackend struct and contains
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
From c58269c64af18bc2a22bbef8b92e489214272429 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Date: Thu, 21 Jan 2021 15:46:49 +0800
|
|
||||||
Subject: [PATCH] block-backend: Add timeout support for retry
|
|
||||||
|
|
||||||
Retry should only be triggered when timeout is not reached, so let's check
|
|
||||||
timeout before retry. Device should also reset retry_start_time after
|
|
||||||
successful retry.
|
|
||||||
|
|
||||||
Signed-off-by: Jiahui Cen <cenjiahui(a)huawei.com>
|
|
||||||
Signed-off-by: Ying Fang <fangying1(a)huawei.com>
|
|
||||||
---
|
|
||||||
block/block-backend.c | 25 ++++++++++++++++++++++++-
|
|
||||||
include/sysemu/block-backend.h | 1 +
|
|
||||||
2 files changed, 25 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index 11f8ff4301..0fe99ffe52 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -1633,6 +1633,29 @@ void blk_drain_all(void)
|
|
||||||
bdrv_drain_all_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
+static bool blk_error_retry_timeout(BlockBackend *blk)
|
|
||||||
+{
|
|
||||||
+ /* No timeout set, infinite retries. */
|
|
||||||
+ if (!blk->retry_timeout) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* The first time an error occurs. */
|
|
||||||
+ if (!blk->retry_start_time) {
|
|
||||||
+ blk->retry_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return qemu_clock_get_ms(QEMU_CLOCK_REALTIME) > (blk->retry_start_time +
|
|
||||||
+ blk->retry_timeout);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void blk_error_retry_reset_timeout(BlockBackend *blk)
|
|
||||||
+{
|
|
||||||
+ if (blk->retry_timer && blk->retry_start_time)
|
|
||||||
+ blk->retry_start_time = 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
|
|
||||||
BlockdevOnError on_write_error)
|
|
||||||
{
|
|
||||||
@@ -1661,7 +1684,7 @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
|
|
||||||
case BLOCKDEV_ON_ERROR_IGNORE:
|
|
||||||
return BLOCK_ERROR_ACTION_IGNORE;
|
|
||||||
case BLOCKDEV_ON_ERROR_RETRY:
|
|
||||||
- return (blk->retry_timer) ?
|
|
||||||
+ return (blk->retry_timer && !blk_error_retry_timeout(blk)) ?
|
|
||||||
BLOCK_ERROR_ACTION_RETRY : BLOCK_ERROR_ACTION_REPORT;
|
|
||||||
case BLOCKDEV_ON_ERROR_AUTO:
|
|
||||||
default:
|
|
||||||
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
|
|
||||||
index b58dc6bde8..58dde446ca 100644
|
|
||||||
--- a/include/sysemu/block-backend.h
|
|
||||||
+++ b/include/sysemu/block-backend.h
|
|
||||||
@@ -184,6 +184,7 @@ void blk_inc_in_flight(BlockBackend *blk);
|
|
||||||
void blk_dec_in_flight(BlockBackend *blk);
|
|
||||||
void blk_drain(BlockBackend *blk);
|
|
||||||
void blk_drain_all(void);
|
|
||||||
+void blk_error_retry_reset_timeout(BlockBackend *blk);
|
|
||||||
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
|
|
||||||
BlockdevOnError on_write_error);
|
|
||||||
BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read);
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
From 8df36cddd1e5e2b3c3598c83a70e8cbb81c26cec Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Date: Thu, 21 Jan 2021 15:46:48 +0800
|
|
||||||
Subject: [PATCH] block-backend: Enable retry action on errors
|
|
||||||
|
|
||||||
Enable retry action when backend's retry timer is available. It would
|
|
||||||
trigger the timer to do device specific retry action.
|
|
||||||
|
|
||||||
Signed-off-by: Jiahui Cen <cenjiahui(a)huawei.com>
|
|
||||||
Signed-off-by: Ying Fang <fangying1(a)huawei.com>
|
|
||||||
---
|
|
||||||
block/block-backend.c | 7 +++++++
|
|
||||||
1 file changed, 7 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index b8f535a5fd..11f8ff4301 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -1660,6 +1660,9 @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
|
|
||||||
return BLOCK_ERROR_ACTION_REPORT;
|
|
||||||
case BLOCKDEV_ON_ERROR_IGNORE:
|
|
||||||
return BLOCK_ERROR_ACTION_IGNORE;
|
|
||||||
+ case BLOCKDEV_ON_ERROR_RETRY:
|
|
||||||
+ return (blk->retry_timer) ?
|
|
||||||
+ BLOCK_ERROR_ACTION_RETRY : BLOCK_ERROR_ACTION_REPORT;
|
|
||||||
case BLOCKDEV_ON_ERROR_AUTO:
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
@@ -1707,6 +1710,10 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
|
|
||||||
qemu_system_vmstop_request_prepare();
|
|
||||||
send_qmp_error_event(blk, action, is_read, error);
|
|
||||||
qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
|
|
||||||
+ } else if (action == BLOCK_ERROR_ACTION_RETRY) {
|
|
||||||
+ timer_mod(blk->retry_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
|
|
||||||
+ blk->retry_interval);
|
|
||||||
+ send_qmp_error_event(blk, action, is_read, error);
|
|
||||||
} else {
|
|
||||||
send_qmp_error_event(blk, action, is_read, error);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
From 805c2e121e1ad612f63bafec458284554e76d034 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Date: Thu, 21 Jan 2021 15:46:46 +0800
|
|
||||||
Subject: [PATCH] block-backend: Introduce retry timer
|
|
||||||
|
|
||||||
Add a timer to regularly trigger retry on errors.
|
|
||||||
|
|
||||||
Signed-off-by: Jiahui Cen <cenjiahui(a)huawei.com>
|
|
||||||
Signed-off-by: Ying Fang <fangying1(a)huawei.com>
|
|
||||||
---
|
|
||||||
block/block-backend.c | 21 +++++++++++++++++++++
|
|
||||||
1 file changed, 21 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index 0056b526b8..a9a43b1440 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -31,6 +31,9 @@
|
|
||||||
|
|
||||||
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
|
|
||||||
|
|
||||||
+/* block backend default retry interval */
|
|
||||||
+#define BLOCK_BACKEND_DEFAULT_RETRY_INTERVAL 1000
|
|
||||||
+
|
|
||||||
typedef struct BlockBackendAioNotifier {
|
|
||||||
void (*attached_aio_context)(AioContext *new_context, void *opaque);
|
|
||||||
void (*detach_aio_context)(void *opaque);
|
|
||||||
@@ -88,6 +91,15 @@ struct BlockBackend {
|
|
||||||
* Accessed with atomic ops.
|
|
||||||
*/
|
|
||||||
unsigned int in_flight;
|
|
||||||
+
|
|
||||||
+ /* Timer for retry on errors. */
|
|
||||||
+ QEMUTimer *retry_timer;
|
|
||||||
+ /* Interval in ms to trigger next retry. */
|
|
||||||
+ int64_t retry_interval;
|
|
||||||
+ /* Start time of the first error. Used to check timeout. */
|
|
||||||
+ int64_t retry_start_time;
|
|
||||||
+ /* Retry timeout. 0 represents infinite retry. */
|
|
||||||
+ int64_t retry_timeout;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct BlockBackendAIOCB {
|
|
||||||
@@ -337,6 +349,11 @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
|
|
||||||
blk->on_read_error = BLOCKDEV_ON_ERROR_REPORT;
|
|
||||||
blk->on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
|
|
||||||
|
|
||||||
+ blk->retry_timer = NULL;
|
|
||||||
+ blk->retry_interval = BLOCK_BACKEND_DEFAULT_RETRY_INTERVAL;
|
|
||||||
+ blk->retry_start_time = 0;
|
|
||||||
+ blk->retry_timeout = 0;
|
|
||||||
+
|
|
||||||
block_acct_init(&blk->stats);
|
|
||||||
|
|
||||||
notifier_list_init(&blk->remove_bs_notifiers);
|
|
||||||
@@ -423,6 +440,10 @@ static void blk_delete(BlockBackend *blk)
|
|
||||||
QTAILQ_REMOVE(&block_backends, blk, link);
|
|
||||||
drive_info_del(blk->legacy_dinfo);
|
|
||||||
block_acct_cleanup(&blk->stats);
|
|
||||||
+ if (blk->retry_timer) {
|
|
||||||
+ timer_del(blk->retry_timer);
|
|
||||||
+ timer_free(blk->retry_timer);
|
|
||||||
+ }
|
|
||||||
g_free(blk);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
From da64af4b1e92c345296d937e66136f86027d1ca2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Date: Thu, 25 Feb 2021 18:03:57 +0800
|
|
||||||
Subject: [PATCH] block-backend: Stop retrying when draining
|
|
||||||
|
|
||||||
Retrying failed requests when draining would make the draining hung. So it
|
|
||||||
is better not to trigger the retry timer when draining. And after the
|
|
||||||
virtual devices go back to work, they would retry those queued requests.
|
|
||||||
|
|
||||||
Signed-off-by: Jiahui Cen <cenjiahui@huawei.com>
|
|
||||||
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
|
||||||
---
|
|
||||||
block/block-backend.c | 8 +++++---
|
|
||||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index 2d812e2254..f6c918f1d9 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -1741,9 +1741,11 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
|
|
||||||
send_qmp_error_event(blk, action, is_read, error);
|
|
||||||
qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
|
|
||||||
} else if (action == BLOCK_ERROR_ACTION_RETRY) {
|
|
||||||
- timer_mod(blk->retry_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
|
|
||||||
- blk->retry_interval);
|
|
||||||
- send_qmp_error_event(blk, action, is_read, error);
|
|
||||||
+ if (!blk->quiesce_counter) {
|
|
||||||
+ timer_mod(blk->retry_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
|
|
||||||
+ blk->retry_interval);
|
|
||||||
+ send_qmp_error_event(blk, action, is_read, error);
|
|
||||||
+ }
|
|
||||||
} else {
|
|
||||||
send_qmp_error_event(blk, action, is_read, error);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,252 +0,0 @@
|
|||||||
From e0a0150e671e8129f11aa3df907e444e91711f53 Mon Sep 17 00:00:00 2001
|
|
||||||
From: John Snow <jsnow@redhat.com>
|
|
||||||
Date: Mon, 29 Jul 2019 16:35:52 -0400
|
|
||||||
Subject: [PATCH] block/backup: Add mirror sync mode 'bitmap'
|
|
||||||
|
|
||||||
We don't need or want a new sync mode for simple differences in
|
|
||||||
semantics. Create a new mode simply named "BITMAP" that is designed to
|
|
||||||
make use of the new Bitmap Sync Mode field.
|
|
||||||
|
|
||||||
Because the only bitmap sync mode is 'on-success', this adds no new
|
|
||||||
functionality to the backup job (yet). The old incremental backup mode
|
|
||||||
is maintained as a syntactic sugar for sync=bitmap, mode=on-success.
|
|
||||||
|
|
||||||
Add all of the plumbing necessary to support this new instruction.
|
|
||||||
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20190709232550.10724-6-jsnow@redhat.com
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 20 ++++++++++++--------
|
|
||||||
block/mirror.c | 6 ++++--
|
|
||||||
block/replication.c | 2 +-
|
|
||||||
blockdev.c | 25 +++++++++++++++++++++++--
|
|
||||||
include/block/block_int.h | 4 +++-
|
|
||||||
qapi/block-core.json | 21 +++++++++++++++------
|
|
||||||
6 files changed, 58 insertions(+), 20 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index 88354dcb32..e37eda80cd 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -38,9 +38,9 @@ typedef struct CowRequest {
|
|
||||||
typedef struct BackupBlockJob {
|
|
||||||
BlockJob common;
|
|
||||||
BlockBackend *target;
|
|
||||||
- /* bitmap for sync=incremental */
|
|
||||||
BdrvDirtyBitmap *sync_bitmap;
|
|
||||||
MirrorSyncMode sync_mode;
|
|
||||||
+ BitmapSyncMode bitmap_mode;
|
|
||||||
BlockdevOnError on_source_error;
|
|
||||||
BlockdevOnError on_target_error;
|
|
||||||
CoRwlock flush_rwlock;
|
|
||||||
@@ -461,7 +461,7 @@ static int coroutine_fn backup_run(Job *job, Error **errp)
|
|
||||||
|
|
||||||
job_progress_set_remaining(job, s->len);
|
|
||||||
|
|
||||||
- if (s->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
|
|
||||||
+ if (s->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
|
||||||
backup_incremental_init_copy_bitmap(s);
|
|
||||||
} else {
|
|
||||||
hbitmap_set(s->copy_bitmap, 0, s->len);
|
|
||||||
@@ -545,6 +545,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target,
|
|
||||||
BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
BlockDriverState *target, int64_t speed,
|
|
||||||
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
|
|
||||||
+ BitmapSyncMode bitmap_mode,
|
|
||||||
bool compress,
|
|
||||||
BlockdevOnError on_source_error,
|
|
||||||
BlockdevOnError on_target_error,
|
|
||||||
@@ -592,10 +593,13 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
|
|
||||||
+ /* QMP interface should have handled translating this to bitmap mode */
|
|
||||||
+ assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
|
|
||||||
+
|
|
||||||
+ if (sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
|
||||||
if (!sync_bitmap) {
|
|
||||||
error_setg(errp, "must provide a valid bitmap name for "
|
|
||||||
- "\"incremental\" sync mode");
|
|
||||||
+ "'%s' sync mode", MirrorSyncMode_str(sync_mode));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -605,8 +609,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
}
|
|
||||||
} else if (sync_bitmap) {
|
|
||||||
error_setg(errp,
|
|
||||||
- "a sync_bitmap was provided to backup_run, "
|
|
||||||
- "but received an incompatible sync_mode (%s)",
|
|
||||||
+ "a bitmap was given to backup_job_create, "
|
|
||||||
+ "but it received an incompatible sync_mode (%s)",
|
|
||||||
MirrorSyncMode_str(sync_mode));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
@@ -648,8 +652,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
job->on_source_error = on_source_error;
|
|
||||||
job->on_target_error = on_target_error;
|
|
||||||
job->sync_mode = sync_mode;
|
|
||||||
- job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
|
|
||||||
- sync_bitmap : NULL;
|
|
||||||
+ job->sync_bitmap = sync_bitmap;
|
|
||||||
+ job->bitmap_mode = bitmap_mode;
|
|
||||||
job->compress = compress;
|
|
||||||
|
|
||||||
/* Detect image-fleecing (and similar) schemes */
|
|
||||||
diff --git a/block/mirror.c b/block/mirror.c
|
|
||||||
index abcf60a961..ccae49a28e 100644
|
|
||||||
--- a/block/mirror.c
|
|
||||||
+++ b/block/mirror.c
|
|
||||||
@@ -1770,8 +1770,10 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
|
||||||
bool is_none_mode;
|
|
||||||
BlockDriverState *base;
|
|
||||||
|
|
||||||
- if (mode == MIRROR_SYNC_MODE_INCREMENTAL) {
|
|
||||||
- error_setg(errp, "Sync mode 'incremental' not supported");
|
|
||||||
+ if ((mode == MIRROR_SYNC_MODE_INCREMENTAL) ||
|
|
||||||
+ (mode == MIRROR_SYNC_MODE_BITMAP)) {
|
|
||||||
+ error_setg(errp, "Sync mode '%s' not supported",
|
|
||||||
+ MirrorSyncMode_str(mode));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
|
|
||||||
diff --git a/block/replication.c b/block/replication.c
|
|
||||||
index 23b2993d74..936b2f8b5a 100644
|
|
||||||
--- a/block/replication.c
|
|
||||||
+++ b/block/replication.c
|
|
||||||
@@ -543,7 +543,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
|
||||||
|
|
||||||
s->backup_job = backup_job_create(
|
|
||||||
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
|
|
||||||
- 0, MIRROR_SYNC_MODE_NONE, NULL, false,
|
|
||||||
+ 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false,
|
|
||||||
BLOCKDEV_ON_ERROR_REPORT,
|
|
||||||
BLOCKDEV_ON_ERROR_REPORT, JOB_INTERNAL,
|
|
||||||
backup_job_completed, bs, NULL, &local_err);
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index aa15ed1f00..34c8b651e1 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -3508,12 +3508,31 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL) {
|
|
||||||
+ if (backup->has_bitmap_mode &&
|
|
||||||
+ backup->bitmap_mode != BITMAP_SYNC_MODE_ON_SUCCESS) {
|
|
||||||
+ error_setg(errp, "Bitmap sync mode must be '%s' "
|
|
||||||
+ "when using sync mode '%s'",
|
|
||||||
+ BitmapSyncMode_str(BITMAP_SYNC_MODE_ON_SUCCESS),
|
|
||||||
+ MirrorSyncMode_str(backup->sync));
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ backup->has_bitmap_mode = true;
|
|
||||||
+ backup->sync = MIRROR_SYNC_MODE_BITMAP;
|
|
||||||
+ backup->bitmap_mode = BITMAP_SYNC_MODE_ON_SUCCESS;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (backup->has_bitmap) {
|
|
||||||
bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
|
|
||||||
if (!bmap) {
|
|
||||||
error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
+ if (!backup->has_bitmap_mode) {
|
|
||||||
+ error_setg(errp, "Bitmap sync mode must be given "
|
|
||||||
+ "when providing a bitmap");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
@@ -3527,8 +3546,10 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
}
|
|
||||||
|
|
||||||
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
|
||||||
- backup->sync, bmap, backup->compress,
|
|
||||||
- backup->on_source_error, backup->on_target_error,
|
|
||||||
+ backup->sync, bmap, backup->bitmap_mode,
|
|
||||||
+ backup->compress,
|
|
||||||
+ backup->on_source_error,
|
|
||||||
+ backup->on_target_error,
|
|
||||||
job_flags, NULL, NULL, txn, errp);
|
|
||||||
return job;
|
|
||||||
}
|
|
||||||
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
|
||||||
index 05ee6b4866..76117a761a 100644
|
|
||||||
--- a/include/block/block_int.h
|
|
||||||
+++ b/include/block/block_int.h
|
|
||||||
@@ -1152,7 +1152,8 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
|
|
||||||
* @target: Block device to write to.
|
|
||||||
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
|
|
||||||
* @sync_mode: What parts of the disk image should be copied to the destination.
|
|
||||||
- * @sync_bitmap: The dirty bitmap if sync_mode is MIRROR_SYNC_MODE_INCREMENTAL.
|
|
||||||
+ * @sync_bitmap: The dirty bitmap if sync_mode is 'bitmap' or 'incremental'
|
|
||||||
+ * @bitmap_mode: The bitmap synchronization policy to use.
|
|
||||||
* @on_source_error: The action to take upon error reading from the source.
|
|
||||||
* @on_target_error: The action to take upon error writing to the target.
|
|
||||||
* @creation_flags: Flags that control the behavior of the Job lifetime.
|
|
||||||
@@ -1168,6 +1169,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
BlockDriverState *target, int64_t speed,
|
|
||||||
MirrorSyncMode sync_mode,
|
|
||||||
BdrvDirtyBitmap *sync_bitmap,
|
|
||||||
+ BitmapSyncMode bitmap_mode,
|
|
||||||
bool compress,
|
|
||||||
BlockdevOnError on_source_error,
|
|
||||||
BlockdevOnError on_target_error,
|
|
||||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
|
||||||
index b8d12a4951..97baff3a8c 100644
|
|
||||||
--- a/qapi/block-core.json
|
|
||||||
+++ b/qapi/block-core.json
|
|
||||||
@@ -1127,12 +1127,15 @@
|
|
||||||
#
|
|
||||||
# @none: only copy data written from now on
|
|
||||||
#
|
|
||||||
-# @incremental: only copy data described by the dirty bitmap. Since: 2.4
|
|
||||||
+# @incremental: only copy data described by the dirty bitmap. (since: 2.4)
|
|
||||||
+#
|
|
||||||
+# @bitmap: only copy data described by the dirty bitmap. (since: 4.2)
|
|
||||||
+# Behavior on completion is determined by the BitmapSyncMode.
|
|
||||||
#
|
|
||||||
# Since: 1.3
|
|
||||||
##
|
|
||||||
{ 'enum': 'MirrorSyncMode',
|
|
||||||
- 'data': ['top', 'full', 'none', 'incremental'] }
|
|
||||||
+ 'data': ['top', 'full', 'none', 'incremental', 'bitmap'] }
|
|
||||||
|
|
||||||
##
|
|
||||||
# @BitmapSyncMode:
|
|
||||||
@@ -1343,9 +1346,14 @@
|
|
||||||
# @speed: the maximum speed, in bytes per second. The default is 0,
|
|
||||||
# for unlimited.
|
|
||||||
#
|
|
||||||
-# @bitmap: the name of dirty bitmap if sync is "incremental".
|
|
||||||
-# Must be present if sync is "incremental", must NOT be present
|
|
||||||
-# otherwise. (Since 2.4 (drive-backup), 3.1 (blockdev-backup))
|
|
||||||
+# @bitmap: the name of a dirty bitmap if sync is "bitmap" or "incremental".
|
|
||||||
+# Must be present if sync is "bitmap" or "incremental".
|
|
||||||
+# Must not be present otherwise.
|
|
||||||
+# (Since 2.4 (drive-backup), 3.1 (blockdev-backup))
|
|
||||||
+#
|
|
||||||
+# @bitmap-mode: Specifies the type of data the bitmap should contain after
|
|
||||||
+# the operation concludes. Must be present if sync is "bitmap".
|
|
||||||
+# Must NOT be present otherwise. (Since 4.2)
|
|
||||||
#
|
|
||||||
# @compress: true to compress data, if the target format supports it.
|
|
||||||
# (default: false) (since 2.8)
|
|
||||||
@@ -1380,7 +1388,8 @@
|
|
||||||
{ 'struct': 'BackupCommon',
|
|
||||||
'data': { '*job-id': 'str', 'device': 'str',
|
|
||||||
'sync': 'MirrorSyncMode', '*speed': 'int',
|
|
||||||
- '*bitmap': 'str', '*compress': 'bool',
|
|
||||||
+ '*bitmap': 'str', '*bitmap-mode': 'BitmapSyncMode',
|
|
||||||
+ '*compress': 'bool',
|
|
||||||
'*on-source-error': 'BlockdevOnError',
|
|
||||||
'*on-target-error': 'BlockdevOnError',
|
|
||||||
'*auto-finalize': 'bool', '*auto-dismiss': 'bool' } }
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
From 98ed0f915cf3335768ed84ee5dfa54f4e99aaf00 Mon Sep 17 00:00:00 2001
|
|
||||||
From: John Snow <jsnow@redhat.com>
|
|
||||||
Date: Mon, 29 Jul 2019 16:35:53 -0400
|
|
||||||
Subject: [PATCH] block/backup: add 'never' policy to bitmap sync mode
|
|
||||||
|
|
||||||
This adds a "never" policy for bitmap synchronization. Regardless of if
|
|
||||||
the job succeeds or fails, we never update the bitmap. This can be used
|
|
||||||
to perform differential backups, or simply to avoid the job modifying a
|
|
||||||
bitmap.
|
|
||||||
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20190709232550.10724-7-jsnow@redhat.com
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 7 +++++--
|
|
||||||
qapi/block-core.json | 5 ++++-
|
|
||||||
2 files changed, 9 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index e37eda80cd..84a56337ac 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -274,8 +274,11 @@ static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
|
|
||||||
BdrvDirtyBitmap *bm;
|
|
||||||
BlockDriverState *bs = blk_bs(job->common.blk);
|
|
||||||
|
|
||||||
- if (ret < 0) {
|
|
||||||
- /* Merge the successor back into the parent, delete nothing. */
|
|
||||||
+ if (ret < 0 || job->bitmap_mode == BITMAP_SYNC_MODE_NEVER) {
|
|
||||||
+ /*
|
|
||||||
+ * Failure, or we don't want to synchronize the bitmap.
|
|
||||||
+ * Merge the successor back into the parent, delete nothing.
|
|
||||||
+ */
|
|
||||||
bm = bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL);
|
|
||||||
assert(bm);
|
|
||||||
} else {
|
|
||||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
|
||||||
index 97baff3a8c..48a0bfab63 100644
|
|
||||||
--- a/qapi/block-core.json
|
|
||||||
+++ b/qapi/block-core.json
|
|
||||||
@@ -1146,10 +1146,13 @@
|
|
||||||
# @on-success: The bitmap is only synced when the operation is successful.
|
|
||||||
# This is the behavior always used for 'INCREMENTAL' backups.
|
|
||||||
#
|
|
||||||
+# @never: The bitmap is never synchronized with the operation, and is
|
|
||||||
+# treated solely as a read-only manifest of blocks to copy.
|
|
||||||
+#
|
|
||||||
# Since: 4.2
|
|
||||||
##
|
|
||||||
{ 'enum': 'BitmapSyncMode',
|
|
||||||
- 'data': ['on-success'] }
|
|
||||||
+ 'data': ['on-success', 'never'] }
|
|
||||||
|
|
||||||
##
|
|
||||||
# @MirrorCopyMode:
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
From 3cf14b9a7daf0a40eb2af7a86e67cb05f6d2bea6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Tue, 30 Jul 2019 19:32:49 +0300
|
|
||||||
Subject: [PATCH] block/backup: deal with zero detection
|
|
||||||
|
|
||||||
We have detect_zeroes option, so at least for blockdev-backup user
|
|
||||||
should define it if zero-detection is needed. For drive-backup leave
|
|
||||||
detection enabled by default but do it through existing option instead
|
|
||||||
of open-coding.
|
|
||||||
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20190730163251.755248-2-vsementsov@virtuozzo.com
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 15 ++++++---------
|
|
||||||
blockdev.c | 8 ++++----
|
|
||||||
2 files changed, 10 insertions(+), 13 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index cc19643b47..6023573299 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -110,7 +110,10 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
|
|
||||||
BlockBackend *blk = job->common.blk;
|
|
||||||
int nbytes;
|
|
||||||
int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0;
|
|
||||||
- int write_flags = job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0;
|
|
||||||
+ int write_flags =
|
|
||||||
+ (job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0) |
|
|
||||||
+ (job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
|
|
||||||
+
|
|
||||||
|
|
||||||
assert(QEMU_IS_ALIGNED(start, job->cluster_size));
|
|
||||||
hbitmap_reset(job->copy_bitmap, start, job->cluster_size);
|
|
||||||
@@ -128,14 +131,8 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job,
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (buffer_is_zero(*bounce_buffer, nbytes)) {
|
|
||||||
- ret = blk_co_pwrite_zeroes(job->target, start,
|
|
||||||
- nbytes, write_flags | BDRV_REQ_MAY_UNMAP);
|
|
||||||
- } else {
|
|
||||||
- ret = blk_co_pwrite(job->target, start,
|
|
||||||
- nbytes, *bounce_buffer, write_flags |
|
|
||||||
- (job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0));
|
|
||||||
- }
|
|
||||||
+ ret = blk_co_pwrite(job->target, start, nbytes, *bounce_buffer,
|
|
||||||
+ write_flags);
|
|
||||||
if (ret < 0) {
|
|
||||||
trace_backup_do_cow_write_fail(job, start, ret);
|
|
||||||
if (error_is_read) {
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 0a71a15fa2..94e5aee30b 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -3572,7 +3572,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
|
||||||
BlockDriverState *source = NULL;
|
|
||||||
BlockJob *job = NULL;
|
|
||||||
AioContext *aio_context;
|
|
||||||
- QDict *options = NULL;
|
|
||||||
+ QDict *options;
|
|
||||||
Error *local_err = NULL;
|
|
||||||
int flags;
|
|
||||||
int64_t size;
|
|
||||||
@@ -3645,10 +3645,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ options = qdict_new();
|
|
||||||
+ qdict_put_str(options, "discard", "unmap");
|
|
||||||
+ qdict_put_str(options, "detect-zeroes", "unmap");
|
|
||||||
if (backup->format) {
|
|
||||||
- if (!options) {
|
|
||||||
- options = qdict_new();
|
|
||||||
- }
|
|
||||||
qdict_put_str(options, "driver", backup->format);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
From adb934c8d2cfd8b920e69712f07a8fb9399fdc2d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Fri, 20 Sep 2019 17:20:43 +0300
|
|
||||||
Subject: [PATCH] block/backup: fix backup_cow_with_offload for last cluster
|
|
||||||
|
|
||||||
We shouldn't try to copy bytes beyond EOF. Fix it.
|
|
||||||
|
|
||||||
Fixes: 9ded4a0114968e
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
||||||
Message-id: 20190920142056.12778-3-vsementsov@virtuozzo.com
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit 1048ddf0a32dcdaa952e581bd503d49adad527cc)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index 8119d3c..55736ea 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -169,7 +169,7 @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job,
|
|
||||||
|
|
||||||
assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size));
|
|
||||||
assert(QEMU_IS_ALIGNED(start, job->cluster_size));
|
|
||||||
- nbytes = MIN(job->copy_range_size, end - start);
|
|
||||||
+ nbytes = MIN(job->copy_range_size, MIN(end, job->len) - start);
|
|
||||||
nr_clusters = DIV_ROUND_UP(nbytes, job->cluster_size);
|
|
||||||
hbitmap_reset(job->copy_bitmap, start, job->cluster_size * nr_clusters);
|
|
||||||
ret = blk_co_copy_range(blk, start, job->target, start, nbytes,
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
From bad8a640a29f16b4d333673577b06880894766e1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Fri, 20 Sep 2019 17:20:42 +0300
|
|
||||||
Subject: [PATCH] block/backup: fix max_transfer handling for copy_range
|
|
||||||
|
|
||||||
Of course, QEMU_ALIGN_UP is a typo, it should be QEMU_ALIGN_DOWN, as we
|
|
||||||
are trying to find aligned size which satisfy both source and target.
|
|
||||||
Also, don't ignore too small max_transfer. In this case seems safer to
|
|
||||||
disable copy_range.
|
|
||||||
|
|
||||||
Fixes: 9ded4a0114968e
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-id: 20190920142056.12778-2-vsementsov@virtuozzo.com
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit 981fb5810aa3f68797ee6e261db338bd78857614)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 15 +++++++++++----
|
|
||||||
1 file changed, 11 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index 381659d..8119d3c 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -666,12 +666,19 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
job->cluster_size = cluster_size;
|
|
||||||
job->copy_bitmap = copy_bitmap;
|
|
||||||
copy_bitmap = NULL;
|
|
||||||
- job->use_copy_range = !compress; /* compression isn't supported for it */
|
|
||||||
job->copy_range_size = MIN_NON_ZERO(blk_get_max_transfer(job->common.blk),
|
|
||||||
blk_get_max_transfer(job->target));
|
|
||||||
- job->copy_range_size = MAX(job->cluster_size,
|
|
||||||
- QEMU_ALIGN_UP(job->copy_range_size,
|
|
||||||
- job->cluster_size));
|
|
||||||
+ job->copy_range_size = QEMU_ALIGN_DOWN(job->copy_range_size,
|
|
||||||
+ job->cluster_size);
|
|
||||||
+ /*
|
|
||||||
+ * Set use_copy_range, consider the following:
|
|
||||||
+ * 1. Compression is not supported for copy_range.
|
|
||||||
+ * 2. copy_range does not respect max_transfer (it's a TODO), so we factor
|
|
||||||
+ * that in here. If max_transfer is smaller than the job->cluster_size,
|
|
||||||
+ * we do not use copy_range (in that case it's zero after aligning down
|
|
||||||
+ * above).
|
|
||||||
+ */
|
|
||||||
+ job->use_copy_range = !compress && job->copy_range_size > 0;
|
|
||||||
|
|
||||||
/* Required permissions are already taken with target's blk_new() */
|
|
||||||
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
From 9cc9e9657aad126502183fa4ceb9b962b55471cb Mon Sep 17 00:00:00 2001
|
|
||||||
From: John Snow <jsnow@redhat.com>
|
|
||||||
Date: Mon, 29 Jul 2019 16:35:55 -0400
|
|
||||||
Subject: [PATCH] block/backup: hoist bitmap check into QMP interface
|
|
||||||
|
|
||||||
This is nicer to do in the unified QMP interface that we have now,
|
|
||||||
because it lets us use the right terminology back at the user.
|
|
||||||
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20190716000117.25219-5-jsnow@redhat.com
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 13 ++++---------
|
|
||||||
blockdev.c | 10 ++++++++++
|
|
||||||
2 files changed, 14 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index 59ac2c0396..cc19643b47 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -565,6 +565,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
assert(bs);
|
|
||||||
assert(target);
|
|
||||||
|
|
||||||
+ /* QMP interface protects us from these cases */
|
|
||||||
+ assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
|
|
||||||
+ assert(sync_bitmap || sync_mode != MIRROR_SYNC_MODE_BITMAP);
|
|
||||||
+
|
|
||||||
if (bs == target) {
|
|
||||||
error_setg(errp, "Source and target cannot be the same");
|
|
||||||
return NULL;
|
|
||||||
@@ -596,16 +600,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* QMP interface should have handled translating this to bitmap mode */
|
|
||||||
- assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
|
|
||||||
-
|
|
||||||
if (sync_mode == MIRROR_SYNC_MODE_BITMAP) {
|
|
||||||
- if (!sync_bitmap) {
|
|
||||||
- error_setg(errp, "must provide a valid bitmap name for "
|
|
||||||
- "'%s' sync mode", MirrorSyncMode_str(sync_mode));
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
/* If we need to write to this bitmap, check that we can: */
|
|
||||||
if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
|
|
||||||
bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) {
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index efb69d343a..0a71a15fa2 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -3508,6 +3508,16 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
|
|
||||||
+ (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) {
|
|
||||||
+ /* done before desugaring 'incremental' to print the right message */
|
|
||||||
+ if (!backup->has_bitmap) {
|
|
||||||
+ error_setg(errp, "must provide a valid bitmap name for "
|
|
||||||
+ "'%s' sync mode", MirrorSyncMode_str(backup->sync));
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL) {
|
|
||||||
if (backup->has_bitmap_mode &&
|
|
||||||
backup->bitmap_mode != BITMAP_SYNC_MODE_ON_SUCCESS) {
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
From 801e9452bc80a38ee26fe12ba42356851acd6a9e Mon Sep 17 00:00:00 2001
|
|
||||||
From: John Snow <jsnow@redhat.com>
|
|
||||||
Date: Mon, 29 Jul 2019 16:35:54 -0400
|
|
||||||
Subject: [PATCH] block/backup: loosen restriction on readonly bitmaps
|
|
||||||
|
|
||||||
With the "never" sync policy, we actually can utilize readonly bitmaps
|
|
||||||
now. Loosen the check at the QMP level, and tighten it based on
|
|
||||||
provided arguments down at the job creation level instead.
|
|
||||||
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20190709232550.10724-19-jsnow@redhat.com
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
---
|
|
||||||
block/backup.c | 6 ++++++
|
|
||||||
blockdev.c | 2 +-
|
|
||||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/block/backup.c b/block/backup.c
|
|
||||||
index 84a56337ac..59ac2c0396 100644
|
|
||||||
--- a/block/backup.c
|
|
||||||
+++ b/block/backup.c
|
|
||||||
@@ -606,6 +606,12 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* If we need to write to this bitmap, check that we can: */
|
|
||||||
+ if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
|
|
||||||
+ bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) {
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Create a new bitmap, and freeze/disable this one. */
|
|
||||||
if (bdrv_dirty_bitmap_create_successor(bs, sync_bitmap, errp) < 0) {
|
|
||||||
return NULL;
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 34c8b651e1..efb69d343a 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -3533,7 +3533,7 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
"when providing a bitmap");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
|
||||||
+ if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_ALLOW_RO, errp)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
From 3754525eb383f91869634766ccd041cfe40bbf17 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Mon, 16 Mar 2020 09:06:30 +0300
|
|
||||||
Subject: [PATCH 05/14] block: bdrv_set_backing_bs: fix use-after-free
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
There is a use-after-free possible: bdrv_unref_child() leaves
|
|
||||||
bs->backing freed but not NULL. bdrv_attach_child may produce nested
|
|
||||||
polling loop due to drain, than access of freed pointer is possible.
|
|
||||||
|
|
||||||
I've produced the following crash on 30 iotest with modified code. It
|
|
||||||
does not reproduce on master, but still seems possible:
|
|
||||||
|
|
||||||
#0 __strcmp_avx2 () at /lib64/libc.so.6
|
|
||||||
#1 bdrv_backing_overridden (bs=0x55c9d3cc2060) at block.c:6350
|
|
||||||
#2 bdrv_refresh_filename (bs=0x55c9d3cc2060) at block.c:6404
|
|
||||||
#3 bdrv_backing_attach (c=0x55c9d48e5520) at block.c:1063
|
|
||||||
#4 bdrv_replace_child_noperm
|
|
||||||
(child=child@entry=0x55c9d48e5520,
|
|
||||||
new_bs=new_bs@entry=0x55c9d3cc2060) at block.c:2290
|
|
||||||
#5 bdrv_replace_child
|
|
||||||
(child=child@entry=0x55c9d48e5520,
|
|
||||||
new_bs=new_bs@entry=0x55c9d3cc2060) at block.c:2320
|
|
||||||
#6 bdrv_root_attach_child
|
|
||||||
(child_bs=child_bs@entry=0x55c9d3cc2060,
|
|
||||||
child_name=child_name@entry=0x55c9d241d478 "backing",
|
|
||||||
child_role=child_role@entry=0x55c9d26ecee0 <child_backing>,
|
|
||||||
ctx=<optimized out>, perm=<optimized out>, shared_perm=21,
|
|
||||||
opaque=0x55c9d3c5a3d0, errp=0x7ffd117108e0) at block.c:2424
|
|
||||||
#7 bdrv_attach_child
|
|
||||||
(parent_bs=parent_bs@entry=0x55c9d3c5a3d0,
|
|
||||||
child_bs=child_bs@entry=0x55c9d3cc2060,
|
|
||||||
child_name=child_name@entry=0x55c9d241d478 "backing",
|
|
||||||
child_role=child_role@entry=0x55c9d26ecee0 <child_backing>,
|
|
||||||
errp=errp@entry=0x7ffd117108e0) at block.c:5876
|
|
||||||
#8 in bdrv_set_backing_hd
|
|
||||||
(bs=bs@entry=0x55c9d3c5a3d0,
|
|
||||||
backing_hd=backing_hd@entry=0x55c9d3cc2060,
|
|
||||||
errp=errp@entry=0x7ffd117108e0)
|
|
||||||
at block.c:2576
|
|
||||||
#9 stream_prepare (job=0x55c9d49d84a0) at block/stream.c:150
|
|
||||||
#10 job_prepare (job=0x55c9d49d84a0) at job.c:761
|
|
||||||
#11 job_txn_apply (txn=<optimized out>, fn=<optimized out>) at
|
|
||||||
job.c:145
|
|
||||||
#12 job_do_finalize (job=0x55c9d49d84a0) at job.c:778
|
|
||||||
#13 job_completed_txn_success (job=0x55c9d49d84a0) at job.c:832
|
|
||||||
#14 job_completed (job=0x55c9d49d84a0) at job.c:845
|
|
||||||
#15 job_completed (job=0x55c9d49d84a0) at job.c:836
|
|
||||||
#16 job_exit (opaque=0x55c9d49d84a0) at job.c:864
|
|
||||||
#17 aio_bh_call (bh=0x55c9d471a160) at util/async.c:117
|
|
||||||
#18 aio_bh_poll (ctx=ctx@entry=0x55c9d3c46720) at util/async.c:117
|
|
||||||
#19 aio_poll (ctx=ctx@entry=0x55c9d3c46720,
|
|
||||||
blocking=blocking@entry=true)
|
|
||||||
at util/aio-posix.c:728
|
|
||||||
#20 bdrv_parent_drained_begin_single (poll=true, c=0x55c9d3d558f0)
|
|
||||||
at block/io.c:121
|
|
||||||
#21 bdrv_parent_drained_begin_single (c=c@entry=0x55c9d3d558f0,
|
|
||||||
poll=poll@entry=true)
|
|
||||||
at block/io.c:114
|
|
||||||
#22 bdrv_replace_child_noperm
|
|
||||||
(child=child@entry=0x55c9d3d558f0,
|
|
||||||
new_bs=new_bs@entry=0x55c9d3d27300) at block.c:2258
|
|
||||||
#23 bdrv_replace_child
|
|
||||||
(child=child@entry=0x55c9d3d558f0,
|
|
||||||
new_bs=new_bs@entry=0x55c9d3d27300) at block.c:2320
|
|
||||||
#24 bdrv_root_attach_child
|
|
||||||
(child_bs=child_bs@entry=0x55c9d3d27300,
|
|
||||||
child_name=child_name@entry=0x55c9d241d478 "backing",
|
|
||||||
child_role=child_role@entry=0x55c9d26ecee0 <child_backing>,
|
|
||||||
ctx=<optimized out>, perm=<optimized out>, shared_perm=21,
|
|
||||||
opaque=0x55c9d3cc2060, errp=0x7ffd11710c60) at block.c:2424
|
|
||||||
#25 bdrv_attach_child
|
|
||||||
(parent_bs=parent_bs@entry=0x55c9d3cc2060,
|
|
||||||
child_bs=child_bs@entry=0x55c9d3d27300,
|
|
||||||
child_name=child_name@entry=0x55c9d241d478 "backing",
|
|
||||||
child_role=child_role@entry=0x55c9d26ecee0 <child_backing>,
|
|
||||||
errp=errp@entry=0x7ffd11710c60) at block.c:5876
|
|
||||||
#26 bdrv_set_backing_hd
|
|
||||||
(bs=bs@entry=0x55c9d3cc2060,
|
|
||||||
backing_hd=backing_hd@entry=0x55c9d3d27300,
|
|
||||||
errp=errp@entry=0x7ffd11710c60)
|
|
||||||
at block.c:2576
|
|
||||||
#27 stream_prepare (job=0x55c9d495ead0) at block/stream.c:150
|
|
||||||
...
|
|
||||||
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-Id: <20200316060631.30052-2-vsementsov@virtuozzo.com>
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
|
||||||
---
|
|
||||||
block.c | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/block.c b/block.c
|
|
||||||
index 29e504b86aff..e834102c87f7 100644
|
|
||||||
--- a/block.c
|
|
||||||
+++ b/block.c
|
|
||||||
@@ -2549,10 +2549,10 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
|
||||||
|
|
||||||
if (bs->backing) {
|
|
||||||
bdrv_unref_child(bs, bs->backing);
|
|
||||||
+ bs->backing = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!backing_hd) {
|
|
||||||
- bs->backing = NULL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
From 088f1e8fd9e790bc5766bd43af134230abcff6dd Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
|
|
||||||
Date: Thu, 12 Sep 2019 00:08:49 +0200
|
|
||||||
Subject: [PATCH] block/create: Do not abort if a block driver is not available
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
The 'blockdev-create' QMP command was introduced as experimental
|
|
||||||
feature in commit b0292b851b8, using the assert() debug call.
|
|
||||||
It got promoted to 'stable' command in 3fb588a0f2c, but the
|
|
||||||
assert call was not removed.
|
|
||||||
|
|
||||||
Some block drivers are optional, and bdrv_find_format() might
|
|
||||||
return a NULL value, triggering the assertion.
|
|
||||||
|
|
||||||
Stable code is not expected to abort, so return an error instead.
|
|
||||||
|
|
||||||
This is easily reproducible when libnfs is not installed:
|
|
||||||
|
|
||||||
./configure
|
|
||||||
[...]
|
|
||||||
module support no
|
|
||||||
Block whitelist (rw)
|
|
||||||
Block whitelist (ro)
|
|
||||||
libiscsi support yes
|
|
||||||
libnfs support no
|
|
||||||
[...]
|
|
||||||
|
|
||||||
Start QEMU:
|
|
||||||
|
|
||||||
$ qemu-system-x86_64 -S -qmp unix:/tmp/qemu.qmp,server,nowait
|
|
||||||
|
|
||||||
Send the 'blockdev-create' with the 'nfs' driver:
|
|
||||||
|
|
||||||
$ ( cat << 'EOF'
|
|
||||||
{'execute': 'qmp_capabilities'}
|
|
||||||
{'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'}
|
|
||||||
EOF
|
|
||||||
) | socat STDIO UNIX:/tmp/qemu.qmp
|
|
||||||
{"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 4}, "package": "v4.1.0-733-g89ea03a7dc"}, "capabilities": ["oob"]}}
|
|
||||||
{"return": {}}
|
|
||||||
|
|
||||||
QEMU crashes:
|
|
||||||
|
|
||||||
$ gdb qemu-system-x86_64 core
|
|
||||||
Program received signal SIGSEGV, Segmentation fault.
|
|
||||||
(gdb) bt
|
|
||||||
#0 0x00007ffff510957f in raise () at /lib64/libc.so.6
|
|
||||||
#1 0x00007ffff50f3895 in abort () at /lib64/libc.so.6
|
|
||||||
#2 0x00007ffff50f3769 in _nl_load_domain.cold.0 () at /lib64/libc.so.6
|
|
||||||
#3 0x00007ffff5101a26 in .annobin_assert.c_end () at /lib64/libc.so.6
|
|
||||||
#4 0x0000555555d7e1f1 in qmp_blockdev_create (job_id=0x555556baee40 "x", options=0x555557666610, errp=0x7fffffffc770) at block/create.c:69
|
|
||||||
#5 0x0000555555c96b52 in qmp_marshal_blockdev_create (args=0x7fffdc003830, ret=0x7fffffffc7f8, errp=0x7fffffffc7f0) at qapi/qapi-commands-block-core.c:1314
|
|
||||||
#6 0x0000555555deb0a0 in do_qmp_dispatch (cmds=0x55555645de70 <qmp_commands>, request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131
|
|
||||||
#7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 <qmp_commands>, request=0x7fffdc005c70, allow_oob=false) at qapi/qmp-dispatch.c:174
|
|
||||||
|
|
||||||
With this patch applied, QEMU returns a QMP error:
|
|
||||||
|
|
||||||
{'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'}
|
|
||||||
{"id": "x", "error": {"class": "GenericError", "desc": "Block driver 'nfs' not found or not supported"}}
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Reported-by: Xu Tian <xutian@redhat.com>
|
|
||||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
(cherry picked from commit d90d5cae2b10efc0e8d0b3cc91ff16201853d3ba)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/create.c | 6 +++++-
|
|
||||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/block/create.c b/block/create.c
|
|
||||||
index 95341219ef..de5e97bb18 100644
|
|
||||||
--- a/block/create.c
|
|
||||||
+++ b/block/create.c
|
|
||||||
@@ -63,9 +63,13 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
|
|
||||||
const char *fmt = BlockdevDriver_str(options->driver);
|
|
||||||
BlockDriver *drv = bdrv_find_format(fmt);
|
|
||||||
|
|
||||||
+ if (!drv) {
|
|
||||||
+ error_setg(errp, "Block driver '%s' not found or not supported", fmt);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* If the driver is in the schema, we know that it exists. But it may not
|
|
||||||
* be whitelisted. */
|
|
||||||
- assert(drv);
|
|
||||||
if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
|
|
||||||
error_setg(errp, "Driver is not whitelisted");
|
|
||||||
return;
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
From ae2c6d13c4ac625a2c6b217a7f6a17506a2b26e5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Richard Jones <rjones@redhat.com>
|
|
||||||
Date: Thu, 28 May 2020 14:27:37 +0100
|
|
||||||
Subject: [PATCH] block/curl: HTTP header field names are case insensitive
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Richard Jones <rjones@redhat.com>
|
|
||||||
Message-id: <20200528142737.17318-3-rjones@redhat.com>
|
|
||||||
Patchwork-id: 96895
|
|
||||||
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block/curl: HTTP header field names are case insensitive
|
|
||||||
Bugzilla: 1841038
|
|
||||||
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
||||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
|
|
||||||
From: David Edmondson <david.edmondson@oracle.com>
|
|
||||||
|
|
||||||
RFC 7230 section 3.2 indicates that HTTP header field names are case
|
|
||||||
insensitive.
|
|
||||||
|
|
||||||
Signed-off-by: David Edmondson <david.edmondson@oracle.com>
|
|
||||||
Message-Id: <20200224101310.101169-3-david.edmondson@oracle.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit 69032253c33ae1774233c63cedf36d32242a85fc)
|
|
||||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
||||||
---
|
|
||||||
block/curl.c | 5 +++--
|
|
||||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/curl.c b/block/curl.c
|
|
||||||
index bfabe7eabd..a298fcc591 100644
|
|
||||||
--- a/block/curl.c
|
|
||||||
+++ b/block/curl.c
|
|
||||||
@@ -214,11 +214,12 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
|
||||||
size_t realsize = size * nmemb;
|
|
||||||
const char *header = (char *)ptr;
|
|
||||||
const char *end = header + realsize;
|
|
||||||
- const char *accept_ranges = "Accept-Ranges:";
|
|
||||||
+ const char *accept_ranges = "accept-ranges:";
|
|
||||||
const char *bytes = "bytes";
|
|
||||||
|
|
||||||
if (realsize >= strlen(accept_ranges)
|
|
||||||
- && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) {
|
|
||||||
+ && g_ascii_strncasecmp(header, accept_ranges,
|
|
||||||
+ strlen(accept_ranges)) == 0) {
|
|
||||||
|
|
||||||
char *p = strchr(header, ':') + 1;
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
From c8fd37c06fd24d1242629dda329dd16bea20f319 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Richard Jones <rjones@redhat.com>
|
|
||||||
Date: Thu, 28 May 2020 14:27:36 +0100
|
|
||||||
Subject: [PATCH] block/curl: HTTP header fields allow whitespace around values
|
|
||||||
|
|
||||||
RH-Author: Richard Jones <rjones@redhat.com>
|
|
||||||
Message-id: <20200528142737.17318-2-rjones@redhat.com>
|
|
||||||
Patchwork-id: 96894
|
|
||||||
O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] block/curl: HTTP header fields allow whitespace around values
|
|
||||||
Bugzilla: 1841038
|
|
||||||
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
||||||
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
|
|
||||||
|
|
||||||
From: David Edmondson <david.edmondson@oracle.com>
|
|
||||||
|
|
||||||
RFC 7230 section 3.2 indicates that whitespace is permitted between
|
|
||||||
the field name and field value and after the field value.
|
|
||||||
|
|
||||||
Signed-off-by: David Edmondson <david.edmondson@oracle.com>
|
|
||||||
Message-Id: <20200224101310.101169-2-david.edmondson@oracle.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit 7788a319399f17476ff1dd43164c869e320820a2)
|
|
||||||
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
|
|
||||||
---
|
|
||||||
block/curl.c | 31 +++++++++++++++++++++++++++----
|
|
||||||
1 file changed, 27 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/curl.c b/block/curl.c
|
|
||||||
index d4c8e94f3e..bfabe7eabd 100644
|
|
||||||
--- a/block/curl.c
|
|
||||||
+++ b/block/curl.c
|
|
||||||
@@ -212,11 +212,34 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
|
|
||||||
{
|
|
||||||
BDRVCURLState *s = opaque;
|
|
||||||
size_t realsize = size * nmemb;
|
|
||||||
- const char *accept_line = "Accept-Ranges: bytes";
|
|
||||||
+ const char *header = (char *)ptr;
|
|
||||||
+ const char *end = header + realsize;
|
|
||||||
+ const char *accept_ranges = "Accept-Ranges:";
|
|
||||||
+ const char *bytes = "bytes";
|
|
||||||
|
|
||||||
- if (realsize >= strlen(accept_line)
|
|
||||||
- && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
|
|
||||||
- s->accept_range = true;
|
|
||||||
+ if (realsize >= strlen(accept_ranges)
|
|
||||||
+ && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) {
|
|
||||||
+
|
|
||||||
+ char *p = strchr(header, ':') + 1;
|
|
||||||
+
|
|
||||||
+ /* Skip whitespace between the header name and value. */
|
|
||||||
+ while (p < end && *p && g_ascii_isspace(*p)) {
|
|
||||||
+ p++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (end - p >= strlen(bytes)
|
|
||||||
+ && strncmp(p, bytes, strlen(bytes)) == 0) {
|
|
||||||
+
|
|
||||||
+ /* Check that there is nothing but whitespace after the value. */
|
|
||||||
+ p += strlen(bytes);
|
|
||||||
+ while (p < end && *p && g_ascii_isspace(*p)) {
|
|
||||||
+ p++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (p == end || !*p) {
|
|
||||||
+ s->accept_range = true;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
return realsize;
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
From 7db05c8a732fbdc986a40aadf0de6dd23057d044 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Max Reitz <mreitz@redhat.com>
|
|
||||||
Date: Fri, 1 Nov 2019 16:25:10 +0100
|
|
||||||
Subject: [PATCH] block/file-posix: Let post-EOF fallocate serialize
|
|
||||||
|
|
||||||
The XFS kernel driver has a bug that may cause data corruption for qcow2
|
|
||||||
images as of qemu commit c8bb23cbdbe32f. We can work around it by
|
|
||||||
treating post-EOF fallocates as serializing up until infinity (INT64_MAX
|
|
||||||
in practice).
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20191101152510.11719-4-mreitz@redhat.com
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit 292d06b925b2787ee6f2430996b95651cae42fce)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/file-posix.c | 36 ++++++++++++++++++++++++++++++++++++
|
|
||||||
1 file changed, 36 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/block/file-posix.c b/block/file-posix.c
|
|
||||||
index 992eb4a798..c5df61b477 100644
|
|
||||||
--- a/block/file-posix.c
|
|
||||||
+++ b/block/file-posix.c
|
|
||||||
@@ -2623,6 +2623,42 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes,
|
|
||||||
RawPosixAIOData acb;
|
|
||||||
ThreadPoolFunc *handler;
|
|
||||||
|
|
||||||
+#ifdef CONFIG_FALLOCATE
|
|
||||||
+ if (offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) {
|
|
||||||
+ BdrvTrackedRequest *req;
|
|
||||||
+ uint64_t end;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * This is a workaround for a bug in the Linux XFS driver,
|
|
||||||
+ * where writes submitted through the AIO interface will be
|
|
||||||
+ * discarded if they happen beyond a concurrently running
|
|
||||||
+ * fallocate() that increases the file length (i.e., both the
|
|
||||||
+ * write and the fallocate() happen beyond the EOF).
|
|
||||||
+ *
|
|
||||||
+ * To work around it, we extend the tracked request for this
|
|
||||||
+ * zero write until INT64_MAX (effectively infinity), and mark
|
|
||||||
+ * it as serializing.
|
|
||||||
+ *
|
|
||||||
+ * We have to enable this workaround for all filesystems and
|
|
||||||
+ * AIO modes (not just XFS with aio=native), because for
|
|
||||||
+ * remote filesystems we do not know the host configuration.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+ req = bdrv_co_get_self_request(bs);
|
|
||||||
+ assert(req);
|
|
||||||
+ assert(req->type == BDRV_TRACKED_WRITE);
|
|
||||||
+ assert(req->offset <= offset);
|
|
||||||
+ assert(req->offset + req->bytes >= offset + bytes);
|
|
||||||
+
|
|
||||||
+ end = INT64_MAX & -(uint64_t)bs->bl.request_alignment;
|
|
||||||
+ req->bytes = end - req->offset;
|
|
||||||
+ req->overlap_bytes = req->bytes;
|
|
||||||
+
|
|
||||||
+ bdrv_mark_request_serialising(req, bs->bl.request_alignment);
|
|
||||||
+ bdrv_wait_serialising_requests(req);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
acb = (RawPosixAIOData) {
|
|
||||||
.bs = bs,
|
|
||||||
.aio_fildes = s->fd,
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,165 +0,0 @@
|
|||||||
From 6f1a94035b02d3676a897ea5fa4cda4c62128228 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Max Reitz <mreitz@redhat.com>
|
|
||||||
Date: Fri, 23 Aug 2019 15:03:40 +0200
|
|
||||||
Subject: [PATCH] block/file-posix: Reduce xfsctl() use
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
This patch removes xfs_write_zeroes() and xfs_discard(). Both functions
|
|
||||||
have been added just before the same feature was present through
|
|
||||||
fallocate():
|
|
||||||
|
|
||||||
- fallocate() has supported PUNCH_HOLE for XFS since Linux 2.6.38 (March
|
|
||||||
2011); xfs_discard() was added in December 2010.
|
|
||||||
|
|
||||||
- fallocate() has supported ZERO_RANGE for XFS since Linux 3.15 (June
|
|
||||||
2014); xfs_write_zeroes() was added in November 2013.
|
|
||||||
|
|
||||||
Nowadays, all systems that qemu runs on should support both fallocate()
|
|
||||||
features (RHEL 7's kernel does).
|
|
||||||
|
|
||||||
xfsctl() is still useful for getting the request alignment for O_DIRECT,
|
|
||||||
so this patch does not remove our dependency on it completely.
|
|
||||||
|
|
||||||
Note that xfs_write_zeroes() had a bug: It calls ftruncate() when the
|
|
||||||
file is shorter than the specified range (because ZERO_RANGE does not
|
|
||||||
increase the file length). ftruncate() may yield and then discard data
|
|
||||||
that parallel write requests have written past the EOF in the meantime.
|
|
||||||
Dropping the function altogether fixes the bug.
|
|
||||||
|
|
||||||
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
||||||
Fixes: 50ba5b2d994853b38fed10e0841b119da0f8b8e5
|
|
||||||
Reported-by: Lukáš Doktor <ldoktor@redhat.com>
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
||||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
||||||
Tested-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
||||||
Tested-by: John Snow <jsnow@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
(cherry picked from commit b2c6f23f4a9f6d8f1b648705cd46d3713b78d6a2)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/file-posix.c | 77 +---------------------------------------------
|
|
||||||
1 file changed, 1 insertion(+), 76 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/file-posix.c b/block/file-posix.c
|
|
||||||
index 4479cc7ab4..992eb4a798 100644
|
|
||||||
--- a/block/file-posix.c
|
|
||||||
+++ b/block/file-posix.c
|
|
||||||
@@ -1445,59 +1445,6 @@ out:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-#ifdef CONFIG_XFS
|
|
||||||
-static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes)
|
|
||||||
-{
|
|
||||||
- int64_t len;
|
|
||||||
- struct xfs_flock64 fl;
|
|
||||||
- int err;
|
|
||||||
-
|
|
||||||
- len = lseek(s->fd, 0, SEEK_END);
|
|
||||||
- if (len < 0) {
|
|
||||||
- return -errno;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (offset + bytes > len) {
|
|
||||||
- /* XFS_IOC_ZERO_RANGE does not increase the file length */
|
|
||||||
- if (ftruncate(s->fd, offset + bytes) < 0) {
|
|
||||||
- return -errno;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- memset(&fl, 0, sizeof(fl));
|
|
||||||
- fl.l_whence = SEEK_SET;
|
|
||||||
- fl.l_start = offset;
|
|
||||||
- fl.l_len = bytes;
|
|
||||||
-
|
|
||||||
- if (xfsctl(NULL, s->fd, XFS_IOC_ZERO_RANGE, &fl) < 0) {
|
|
||||||
- err = errno;
|
|
||||||
- trace_file_xfs_write_zeroes(strerror(errno));
|
|
||||||
- return -err;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return 0;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes)
|
|
||||||
-{
|
|
||||||
- struct xfs_flock64 fl;
|
|
||||||
- int err;
|
|
||||||
-
|
|
||||||
- memset(&fl, 0, sizeof(fl));
|
|
||||||
- fl.l_whence = SEEK_SET;
|
|
||||||
- fl.l_start = offset;
|
|
||||||
- fl.l_len = bytes;
|
|
||||||
-
|
|
||||||
- if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
|
|
||||||
- err = errno;
|
|
||||||
- trace_file_xfs_discard(strerror(errno));
|
|
||||||
- return -err;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return 0;
|
|
||||||
-}
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
static int translate_err(int err)
|
|
||||||
{
|
|
||||||
if (err == -ENODEV || err == -ENOSYS || err == -EOPNOTSUPP ||
|
|
||||||
@@ -1553,10 +1500,8 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb)
|
|
||||||
static int handle_aiocb_write_zeroes(void *opaque)
|
|
||||||
{
|
|
||||||
RawPosixAIOData *aiocb = opaque;
|
|
||||||
-#if defined(CONFIG_FALLOCATE) || defined(CONFIG_XFS)
|
|
||||||
- BDRVRawState *s = aiocb->bs->opaque;
|
|
||||||
-#endif
|
|
||||||
#ifdef CONFIG_FALLOCATE
|
|
||||||
+ BDRVRawState *s = aiocb->bs->opaque;
|
|
||||||
int64_t len;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1564,12 +1509,6 @@ static int handle_aiocb_write_zeroes(void *opaque)
|
|
||||||
return handle_aiocb_write_zeroes_block(aiocb);
|
|
||||||
}
|
|
||||||
|
|
||||||
-#ifdef CONFIG_XFS
|
|
||||||
- if (s->is_xfs) {
|
|
||||||
- return xfs_write_zeroes(s, aiocb->aio_offset, aiocb->aio_nbytes);
|
|
||||||
- }
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
#ifdef CONFIG_FALLOCATE_ZERO_RANGE
|
|
||||||
if (s->has_write_zeroes) {
|
|
||||||
int ret = do_fallocate(s->fd, FALLOC_FL_ZERO_RANGE,
|
|
||||||
@@ -1632,14 +1571,6 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-#ifdef CONFIG_XFS
|
|
||||||
- if (s->is_xfs) {
|
|
||||||
- /* xfs_discard() guarantees that the discarded area reads as all-zero
|
|
||||||
- * afterwards, so we can use it here. */
|
|
||||||
- return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes);
|
|
||||||
- }
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
/* If we couldn't manage to unmap while guaranteed that the area reads as
|
|
||||||
* all-zero afterwards, just write zeroes without unmapping */
|
|
||||||
ret = handle_aiocb_write_zeroes(aiocb);
|
|
||||||
@@ -1716,12 +1647,6 @@ static int handle_aiocb_discard(void *opaque)
|
|
||||||
ret = -errno;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
-#ifdef CONFIG_XFS
|
|
||||||
- if (s->is_xfs) {
|
|
||||||
- return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes);
|
|
||||||
- }
|
|
||||||
-#endif
|
|
||||||
-
|
|
||||||
#ifdef CONFIG_FALLOCATE_PUNCH_HOLE
|
|
||||||
ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
|
||||||
aiocb->aio_offset, aiocb->aio_nbytes);
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
From 5060ef71fa4621061101a30fa9e0d1690696c5c1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Tue, 24 Mar 2020 18:59:21 +0300
|
|
||||||
Subject: [PATCH 10/14] block: fix bdrv_root_attach_child forget to unref
|
|
||||||
child_bs
|
|
||||||
|
|
||||||
bdrv_root_attach_child promises to drop child_bs reference on failure.
|
|
||||||
It does it on first handled failure path, but not on the second. Fix
|
|
||||||
that.
|
|
||||||
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-Id: <20200324155921.23822-1-vsementsov@virtuozzo.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
|
||||||
---
|
|
||||||
block.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/block.c b/block.c
|
|
||||||
index e834102c87f7..38880eabf801 100644
|
|
||||||
--- a/block.c
|
|
||||||
+++ b/block.c
|
|
||||||
@@ -2399,6 +2399,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
|
|
||||||
error_propagate(errp, local_err);
|
|
||||||
g_free(child);
|
|
||||||
bdrv_abort_perm_update(child_bs);
|
|
||||||
+ bdrv_unref(child_bs);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
From d09b8364d9f89c9d5f36dc983c4d4a36bb7388b9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
Date: Thu, 16 Jan 2020 17:29:29 +0800
|
|
||||||
Subject: [PATCH] block: fix memleaks in bdrv_refresh_filename
|
|
||||||
|
|
||||||
If we call the qmp 'query-block' while qemu is working on 'block-commit',
|
|
||||||
it will cause memleaks. The memory leak stack is as follow:
|
|
||||||
|
|
||||||
Indirect leak of 12360 byte(s) in 3 object(s) allocated from:
|
|
||||||
#0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970)
|
|
||||||
#1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d)
|
|
||||||
#2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu/qobject/qdict.c
|
|
||||||
#3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu/block.c
|
|
||||||
#4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c
|
|
||||||
#5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c
|
|
||||||
#6 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c
|
|
||||||
#7 0x55ea958818ea in bdrv_block_device_info /mnt/sdb/qemu/block/qapi.c
|
|
||||||
#8 0x55ea958879de in bdrv_query_info /mnt/sdb/qemu/block/qapi.c
|
|
||||||
#9 0x55ea9588b58f in qmp_query_block /mnt/sdb/qemu/block/qapi.c
|
|
||||||
#10 0x55ea95567392 in qmp_marshal_query_block qapi/qapi-commands-block-core.c
|
|
||||||
|
|
||||||
Indirect leak of 4120 byte(s) in 1 object(s) allocated from:
|
|
||||||
#0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970)
|
|
||||||
#1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d)
|
|
||||||
#2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu/qobject/qdict.c
|
|
||||||
#3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu/block.c
|
|
||||||
#4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c
|
|
||||||
#5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c
|
|
||||||
#6 0x55ea9569f301 in bdrv_backing_attach /mnt/sdb/qemu/block.c
|
|
||||||
#7 0x55ea956a99dd in bdrv_replace_child_noperm /mnt/sdb/qemu/block.c
|
|
||||||
#8 0x55ea956b9b53 in bdrv_replace_node /mnt/sdb/qemu/block.c
|
|
||||||
#9 0x55ea956b9e49 in bdrv_append /mnt/sdb/qemu/block.c
|
|
||||||
#10 0x55ea958c3472 in commit_start /mnt/sdb/qemu/block/commit.c
|
|
||||||
#11 0x55ea94b68ab0 in qmp_block_commit /mnt/sdb/qemu/blockdev.c
|
|
||||||
|
|
||||||
Reported-by: Euler Robot <euler.robot@huawei.com>
|
|
||||||
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
---
|
|
||||||
block.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/block.c b/block.c
|
|
||||||
index 9ae5c0e..52bad05 100644
|
|
||||||
--- a/block.c
|
|
||||||
+++ b/block.c
|
|
||||||
@@ -6048,6 +6048,7 @@ void bdrv_refresh_filename(BlockDriverState *bs)
|
|
||||||
child->bs->exact_filename);
|
|
||||||
pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename);
|
|
||||||
|
|
||||||
+ qobject_unref(bs->full_open_options);
|
|
||||||
bs->full_open_options = qobject_ref(child->bs->full_open_options);
|
|
||||||
|
|
||||||
return;
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,481 +0,0 @@
|
|||||||
From 2e2ad02f2cecf419eaad0df982ceb5b41170cc7e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Tue, 4 Jun 2019 19:15:05 +0300
|
|
||||||
Subject: [PATCH] block/io: refactor padding
|
|
||||||
|
|
||||||
We have similar padding code in bdrv_co_pwritev,
|
|
||||||
bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify
|
|
||||||
it.
|
|
||||||
|
|
||||||
[Squashed in Vladimir's qemu-iotests 077 fix
|
|
||||||
--Stefan]
|
|
||||||
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Message-id: 20190604161514.262241-4-vsementsov@virtuozzo.com
|
|
||||||
Message-Id: <20190604161514.262241-4-vsementsov@virtuozzo.com>
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
(cherry picked from commit 7a3f542fbdfd799be4fa6f8b96dc8c1e6933fce4)
|
|
||||||
*prereq for 292d06b9
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/io.c | 365 +++++++++++++++++++++++++++++------------------------
|
|
||||||
1 file changed, 200 insertions(+), 165 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/io.c b/block/io.c
|
|
||||||
index dccf687acc..07d2d825c3 100644
|
|
||||||
--- a/block/io.c
|
|
||||||
+++ b/block/io.c
|
|
||||||
@@ -1408,28 +1408,177 @@ out:
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * Handle a read request in coroutine context
|
|
||||||
+ * Request padding
|
|
||||||
+ *
|
|
||||||
+ * |<---- align ----->| |<----- align ---->|
|
|
||||||
+ * |<- head ->|<------------- bytes ------------->|<-- tail -->|
|
|
||||||
+ * | | | | | |
|
|
||||||
+ * -*----------$-------*-------- ... --------*-----$------------*---
|
|
||||||
+ * | | | | | |
|
|
||||||
+ * | offset | | end |
|
|
||||||
+ * ALIGN_DOWN(offset) ALIGN_UP(offset) ALIGN_DOWN(end) ALIGN_UP(end)
|
|
||||||
+ * [buf ... ) [tail_buf )
|
|
||||||
+ *
|
|
||||||
+ * @buf is an aligned allocation needed to store @head and @tail paddings. @head
|
|
||||||
+ * is placed at the beginning of @buf and @tail at the @end.
|
|
||||||
+ *
|
|
||||||
+ * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk
|
|
||||||
+ * around tail, if tail exists.
|
|
||||||
+ *
|
|
||||||
+ * @merge_reads is true for small requests,
|
|
||||||
+ * if @buf_len == @head + bytes + @tail. In this case it is possible that both
|
|
||||||
+ * head and tail exist but @buf_len == align and @tail_buf == @buf.
|
|
||||||
+ */
|
|
||||||
+typedef struct BdrvRequestPadding {
|
|
||||||
+ uint8_t *buf;
|
|
||||||
+ size_t buf_len;
|
|
||||||
+ uint8_t *tail_buf;
|
|
||||||
+ size_t head;
|
|
||||||
+ size_t tail;
|
|
||||||
+ bool merge_reads;
|
|
||||||
+ QEMUIOVector local_qiov;
|
|
||||||
+} BdrvRequestPadding;
|
|
||||||
+
|
|
||||||
+static bool bdrv_init_padding(BlockDriverState *bs,
|
|
||||||
+ int64_t offset, int64_t bytes,
|
|
||||||
+ BdrvRequestPadding *pad)
|
|
||||||
+{
|
|
||||||
+ uint64_t align = bs->bl.request_alignment;
|
|
||||||
+ size_t sum;
|
|
||||||
+
|
|
||||||
+ memset(pad, 0, sizeof(*pad));
|
|
||||||
+
|
|
||||||
+ pad->head = offset & (align - 1);
|
|
||||||
+ pad->tail = ((offset + bytes) & (align - 1));
|
|
||||||
+ if (pad->tail) {
|
|
||||||
+ pad->tail = align - pad->tail;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((!pad->head && !pad->tail) || !bytes) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ sum = pad->head + bytes + pad->tail;
|
|
||||||
+ pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : align;
|
|
||||||
+ pad->buf = qemu_blockalign(bs, pad->buf_len);
|
|
||||||
+ pad->merge_reads = sum == pad->buf_len;
|
|
||||||
+ if (pad->tail) {
|
|
||||||
+ pad->tail_buf = pad->buf + pad->buf_len - align;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int bdrv_padding_rmw_read(BdrvChild *child,
|
|
||||||
+ BdrvTrackedRequest *req,
|
|
||||||
+ BdrvRequestPadding *pad,
|
|
||||||
+ bool zero_middle)
|
|
||||||
+{
|
|
||||||
+ QEMUIOVector local_qiov;
|
|
||||||
+ BlockDriverState *bs = child->bs;
|
|
||||||
+ uint64_t align = bs->bl.request_alignment;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ assert(req->serialising && pad->buf);
|
|
||||||
+
|
|
||||||
+ if (pad->head || pad->merge_reads) {
|
|
||||||
+ uint64_t bytes = pad->merge_reads ? pad->buf_len : align;
|
|
||||||
+
|
|
||||||
+ qemu_iovec_init_buf(&local_qiov, pad->buf, bytes);
|
|
||||||
+
|
|
||||||
+ if (pad->head) {
|
|
||||||
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
|
|
||||||
+ }
|
|
||||||
+ if (pad->merge_reads && pad->tail) {
|
|
||||||
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
|
|
||||||
+ }
|
|
||||||
+ ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes,
|
|
||||||
+ align, &local_qiov, 0);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ if (pad->head) {
|
|
||||||
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
|
|
||||||
+ }
|
|
||||||
+ if (pad->merge_reads && pad->tail) {
|
|
||||||
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (pad->merge_reads) {
|
|
||||||
+ goto zero_mem;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (pad->tail) {
|
|
||||||
+ qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align);
|
|
||||||
+
|
|
||||||
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
|
|
||||||
+ ret = bdrv_aligned_preadv(
|
|
||||||
+ child, req,
|
|
||||||
+ req->overlap_offset + req->overlap_bytes - align,
|
|
||||||
+ align, align, &local_qiov, 0);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+zero_mem:
|
|
||||||
+ if (zero_middle) {
|
|
||||||
+ memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - pad->tail);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void bdrv_padding_destroy(BdrvRequestPadding *pad)
|
|
||||||
+{
|
|
||||||
+ if (pad->buf) {
|
|
||||||
+ qemu_vfree(pad->buf);
|
|
||||||
+ qemu_iovec_destroy(&pad->local_qiov);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * bdrv_pad_request
|
|
||||||
+ *
|
|
||||||
+ * Exchange request parameters with padded request if needed. Don't include RMW
|
|
||||||
+ * read of padding, bdrv_padding_rmw_read() should be called separately if
|
|
||||||
+ * needed.
|
|
||||||
+ *
|
|
||||||
+ * All parameters except @bs are in-out: they represent original request at
|
|
||||||
+ * function call and padded (if padding needed) at function finish.
|
|
||||||
+ *
|
|
||||||
+ * Function always succeeds.
|
|
||||||
*/
|
|
||||||
+static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov,
|
|
||||||
+ int64_t *offset, unsigned int *bytes,
|
|
||||||
+ BdrvRequestPadding *pad)
|
|
||||||
+{
|
|
||||||
+ if (!bdrv_init_padding(bs, *offset, *bytes, pad)) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head,
|
|
||||||
+ *qiov, 0, *bytes,
|
|
||||||
+ pad->buf + pad->buf_len - pad->tail, pad->tail);
|
|
||||||
+ *bytes += pad->head + pad->tail;
|
|
||||||
+ *offset -= pad->head;
|
|
||||||
+ *qiov = &pad->local_qiov;
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
|
||||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
|
||||||
BdrvRequestFlags flags)
|
|
||||||
{
|
|
||||||
BlockDriverState *bs = child->bs;
|
|
||||||
- BlockDriver *drv = bs->drv;
|
|
||||||
BdrvTrackedRequest req;
|
|
||||||
-
|
|
||||||
- uint64_t align = bs->bl.request_alignment;
|
|
||||||
- uint8_t *head_buf = NULL;
|
|
||||||
- uint8_t *tail_buf = NULL;
|
|
||||||
- QEMUIOVector local_qiov;
|
|
||||||
- bool use_local_qiov = false;
|
|
||||||
+ BdrvRequestPadding pad;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
- trace_bdrv_co_preadv(child->bs, offset, bytes, flags);
|
|
||||||
-
|
|
||||||
- if (!drv) {
|
|
||||||
- return -ENOMEDIUM;
|
|
||||||
- }
|
|
||||||
+ trace_bdrv_co_preadv(bs, offset, bytes, flags);
|
|
||||||
|
|
||||||
ret = bdrv_check_byte_request(bs, offset, bytes);
|
|
||||||
if (ret < 0) {
|
|
||||||
@@ -1443,43 +1592,16 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child,
|
|
||||||
flags |= BDRV_REQ_COPY_ON_READ;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Align read if necessary by padding qiov */
|
|
||||||
- if (offset & (align - 1)) {
|
|
||||||
- head_buf = qemu_blockalign(bs, align);
|
|
||||||
- qemu_iovec_init(&local_qiov, qiov->niov + 2);
|
|
||||||
- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1));
|
|
||||||
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
|
|
||||||
- use_local_qiov = true;
|
|
||||||
-
|
|
||||||
- bytes += offset & (align - 1);
|
|
||||||
- offset = offset & ~(align - 1);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if ((offset + bytes) & (align - 1)) {
|
|
||||||
- if (!use_local_qiov) {
|
|
||||||
- qemu_iovec_init(&local_qiov, qiov->niov + 1);
|
|
||||||
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
|
|
||||||
- use_local_qiov = true;
|
|
||||||
- }
|
|
||||||
- tail_buf = qemu_blockalign(bs, align);
|
|
||||||
- qemu_iovec_add(&local_qiov, tail_buf,
|
|
||||||
- align - ((offset + bytes) & (align - 1)));
|
|
||||||
-
|
|
||||||
- bytes = ROUND_UP(bytes, align);
|
|
||||||
- }
|
|
||||||
+ bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad);
|
|
||||||
|
|
||||||
tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ);
|
|
||||||
- ret = bdrv_aligned_preadv(child, &req, offset, bytes, align,
|
|
||||||
- use_local_qiov ? &local_qiov : qiov,
|
|
||||||
- flags);
|
|
||||||
+ ret = bdrv_aligned_preadv(child, &req, offset, bytes,
|
|
||||||
+ bs->bl.request_alignment,
|
|
||||||
+ qiov, flags);
|
|
||||||
tracked_request_end(&req);
|
|
||||||
bdrv_dec_in_flight(bs);
|
|
||||||
|
|
||||||
- if (use_local_qiov) {
|
|
||||||
- qemu_iovec_destroy(&local_qiov);
|
|
||||||
- qemu_vfree(head_buf);
|
|
||||||
- qemu_vfree(tail_buf);
|
|
||||||
- }
|
|
||||||
+ bdrv_padding_destroy(&pad);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@@ -1775,44 +1897,34 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
|
||||||
BdrvTrackedRequest *req)
|
|
||||||
{
|
|
||||||
BlockDriverState *bs = child->bs;
|
|
||||||
- uint8_t *buf = NULL;
|
|
||||||
QEMUIOVector local_qiov;
|
|
||||||
uint64_t align = bs->bl.request_alignment;
|
|
||||||
- unsigned int head_padding_bytes, tail_padding_bytes;
|
|
||||||
int ret = 0;
|
|
||||||
+ bool padding;
|
|
||||||
+ BdrvRequestPadding pad;
|
|
||||||
|
|
||||||
- head_padding_bytes = offset & (align - 1);
|
|
||||||
- tail_padding_bytes = (align - (offset + bytes)) & (align - 1);
|
|
||||||
-
|
|
||||||
-
|
|
||||||
- assert(flags & BDRV_REQ_ZERO_WRITE);
|
|
||||||
- if (head_padding_bytes || tail_padding_bytes) {
|
|
||||||
- buf = qemu_blockalign(bs, align);
|
|
||||||
- qemu_iovec_init_buf(&local_qiov, buf, align);
|
|
||||||
- }
|
|
||||||
- if (head_padding_bytes) {
|
|
||||||
- uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes);
|
|
||||||
-
|
|
||||||
- /* RMW the unaligned part before head. */
|
|
||||||
+ padding = bdrv_init_padding(bs, offset, bytes, &pad);
|
|
||||||
+ if (padding) {
|
|
||||||
mark_request_serialising(req, align);
|
|
||||||
wait_serialising_requests(req);
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
|
|
||||||
- ret = bdrv_aligned_preadv(child, req, offset & ~(align - 1), align,
|
|
||||||
- align, &local_qiov, 0);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- goto fail;
|
|
||||||
- }
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
|
|
||||||
|
|
||||||
- memset(buf + head_padding_bytes, 0, zero_bytes);
|
|
||||||
- ret = bdrv_aligned_pwritev(child, req, offset & ~(align - 1), align,
|
|
||||||
- align, &local_qiov,
|
|
||||||
- flags & ~BDRV_REQ_ZERO_WRITE);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- goto fail;
|
|
||||||
+ bdrv_padding_rmw_read(child, req, &pad, true);
|
|
||||||
+
|
|
||||||
+ if (pad.head || pad.merge_reads) {
|
|
||||||
+ int64_t aligned_offset = offset & ~(align - 1);
|
|
||||||
+ int64_t write_bytes = pad.merge_reads ? pad.buf_len : align;
|
|
||||||
+
|
|
||||||
+ qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes);
|
|
||||||
+ ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes,
|
|
||||||
+ align, &local_qiov,
|
|
||||||
+ flags & ~BDRV_REQ_ZERO_WRITE);
|
|
||||||
+ if (ret < 0 || pad.merge_reads) {
|
|
||||||
+ /* Error or all work is done */
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ offset += write_bytes - pad.head;
|
|
||||||
+ bytes -= write_bytes - pad.head;
|
|
||||||
}
|
|
||||||
- offset += zero_bytes;
|
|
||||||
- bytes -= zero_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!bytes || (offset & (align - 1)) == 0);
|
|
||||||
@@ -1822,7 +1934,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
|
||||||
ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
|
|
||||||
NULL, flags);
|
|
||||||
if (ret < 0) {
|
|
||||||
- goto fail;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
bytes -= aligned_bytes;
|
|
||||||
offset += aligned_bytes;
|
|
||||||
@@ -1830,26 +1942,17 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
|
|
||||||
|
|
||||||
assert(!bytes || (offset & (align - 1)) == 0);
|
|
||||||
if (bytes) {
|
|
||||||
- assert(align == tail_padding_bytes + bytes);
|
|
||||||
- /* RMW the unaligned part after tail. */
|
|
||||||
- mark_request_serialising(req, align);
|
|
||||||
- wait_serialising_requests(req);
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
|
|
||||||
- ret = bdrv_aligned_preadv(child, req, offset, align,
|
|
||||||
- align, &local_qiov, 0);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- goto fail;
|
|
||||||
- }
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
|
|
||||||
+ assert(align == pad.tail + bytes);
|
|
||||||
|
|
||||||
- memset(buf, 0, bytes);
|
|
||||||
+ qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align);
|
|
||||||
ret = bdrv_aligned_pwritev(child, req, offset, align, align,
|
|
||||||
&local_qiov, flags & ~BDRV_REQ_ZERO_WRITE);
|
|
||||||
}
|
|
||||||
-fail:
|
|
||||||
- qemu_vfree(buf);
|
|
||||||
- return ret;
|
|
||||||
|
|
||||||
+out:
|
|
||||||
+ bdrv_padding_destroy(&pad);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -1862,10 +1965,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
|
||||||
BlockDriverState *bs = child->bs;
|
|
||||||
BdrvTrackedRequest req;
|
|
||||||
uint64_t align = bs->bl.request_alignment;
|
|
||||||
- uint8_t *head_buf = NULL;
|
|
||||||
- uint8_t *tail_buf = NULL;
|
|
||||||
- QEMUIOVector local_qiov;
|
|
||||||
- bool use_local_qiov = false;
|
|
||||||
+ BdrvRequestPadding pad;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
trace_bdrv_co_pwritev(child->bs, offset, bytes, flags);
|
|
||||||
@@ -1892,86 +1992,21 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (offset & (align - 1)) {
|
|
||||||
- QEMUIOVector head_qiov;
|
|
||||||
-
|
|
||||||
+ if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) {
|
|
||||||
mark_request_serialising(&req, align);
|
|
||||||
wait_serialising_requests(&req);
|
|
||||||
-
|
|
||||||
- head_buf = qemu_blockalign(bs, align);
|
|
||||||
- qemu_iovec_init_buf(&head_qiov, head_buf, align);
|
|
||||||
-
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD);
|
|
||||||
- ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align,
|
|
||||||
- align, &head_qiov, 0);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- goto fail;
|
|
||||||
- }
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD);
|
|
||||||
-
|
|
||||||
- qemu_iovec_init(&local_qiov, qiov->niov + 2);
|
|
||||||
- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1));
|
|
||||||
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
|
|
||||||
- use_local_qiov = true;
|
|
||||||
-
|
|
||||||
- bytes += offset & (align - 1);
|
|
||||||
- offset = offset & ~(align - 1);
|
|
||||||
-
|
|
||||||
- /* We have read the tail already if the request is smaller
|
|
||||||
- * than one aligned block.
|
|
||||||
- */
|
|
||||||
- if (bytes < align) {
|
|
||||||
- qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes);
|
|
||||||
- bytes = align;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if ((offset + bytes) & (align - 1)) {
|
|
||||||
- QEMUIOVector tail_qiov;
|
|
||||||
- size_t tail_bytes;
|
|
||||||
- bool waited;
|
|
||||||
-
|
|
||||||
- mark_request_serialising(&req, align);
|
|
||||||
- waited = wait_serialising_requests(&req);
|
|
||||||
- assert(!waited || !use_local_qiov);
|
|
||||||
-
|
|
||||||
- tail_buf = qemu_blockalign(bs, align);
|
|
||||||
- qemu_iovec_init_buf(&tail_qiov, tail_buf, align);
|
|
||||||
-
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL);
|
|
||||||
- ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 1),
|
|
||||||
- align, align, &tail_qiov, 0);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- goto fail;
|
|
||||||
- }
|
|
||||||
- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL);
|
|
||||||
-
|
|
||||||
- if (!use_local_qiov) {
|
|
||||||
- qemu_iovec_init(&local_qiov, qiov->niov + 1);
|
|
||||||
- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size);
|
|
||||||
- use_local_qiov = true;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- tail_bytes = (offset + bytes) & (align - 1);
|
|
||||||
- qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tail_bytes);
|
|
||||||
-
|
|
||||||
- bytes = ROUND_UP(bytes, align);
|
|
||||||
+ bdrv_padding_rmw_read(child, &req, &pad, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align,
|
|
||||||
- use_local_qiov ? &local_qiov : qiov,
|
|
||||||
- flags);
|
|
||||||
+ qiov, flags);
|
|
||||||
|
|
||||||
-fail:
|
|
||||||
+ bdrv_padding_destroy(&pad);
|
|
||||||
|
|
||||||
- if (use_local_qiov) {
|
|
||||||
- qemu_iovec_destroy(&local_qiov);
|
|
||||||
- }
|
|
||||||
- qemu_vfree(head_buf);
|
|
||||||
- qemu_vfree(tail_buf);
|
|
||||||
out:
|
|
||||||
tracked_request_end(&req);
|
|
||||||
bdrv_dec_in_flight(bs);
|
|
||||||
+
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
From 547b06bb04287eb97ffb02e213aa8466c15cce65 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Chen Qun <kuhn.chenqun@huawei.com>
|
|
||||||
Date: Mon, 16 Mar 2020 14:35:34 +0800
|
|
||||||
Subject: [PATCH] block/iscsi: use MIN() between mx_sb_len and sb_len_wr
|
|
||||||
|
|
||||||
Use MIN() macro between mx_sb_len and sb_len_wr the len for sbp copy data.
|
|
||||||
|
|
||||||
Reported-by: Euler Robot <euler.robot@huawei.com>
|
|
||||||
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
|
|
||||||
---
|
|
||||||
block/iscsi.c | 3 +--
|
|
||||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/iscsi.c b/block/iscsi.c
|
|
||||||
index 3f86aaf..5c3c598 100644
|
|
||||||
--- a/block/iscsi.c
|
|
||||||
+++ b/block/iscsi.c
|
|
||||||
@@ -989,8 +989,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
|
|
||||||
acb->ioh->driver_status |= SG_ERR_DRIVER_SENSE;
|
|
||||||
|
|
||||||
acb->ioh->sb_len_wr = acb->task->datain.size - 2;
|
|
||||||
- ss = (acb->ioh->mx_sb_len >= acb->ioh->sb_len_wr) ?
|
|
||||||
- acb->ioh->mx_sb_len : acb->ioh->sb_len_wr;
|
|
||||||
+ ss = MIN(acb->ioh->mx_sb_len, acb->ioh->sb_len_wr);
|
|
||||||
memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
From 682d23829adf0a872d5a3ca6eb4b31c424f558fc Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Tue, 24 Mar 2020 18:36:26 +0300
|
|
||||||
Subject: [PATCH 09/14] block/mirror: fix use after free of local_err
|
|
||||||
|
|
||||||
local_err is used again in mirror_exit_common() after
|
|
||||||
bdrv_set_backing_hd(), so we must zero it. Otherwise try to set
|
|
||||||
non-NULL local_err will crash.
|
|
||||||
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-Id: <20200324153630.11882-3-vsementsov@virtuozzo.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Reviewed-by: John Snow <jsnow@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
|
||||||
---
|
|
||||||
block/mirror.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/block/mirror.c b/block/mirror.c
|
|
||||||
index 681b305de650..ef6c958ff9b3 100644
|
|
||||||
--- a/block/mirror.c
|
|
||||||
+++ b/block/mirror.c
|
|
||||||
@@ -674,6 +674,7 @@ static int mirror_exit_common(Job *job)
|
|
||||||
bdrv_set_backing_hd(target_bs, backing, &local_err);
|
|
||||||
if (local_err) {
|
|
||||||
error_report_err(local_err);
|
|
||||||
+ local_err = NULL;
|
|
||||||
ret = -EPERM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
From 1196a2079a558cbb673e06142fa67a401c5e6c30 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
Date: Thu, 5 Dec 2019 11:45:27 +0800
|
|
||||||
Subject: [PATCH 6/9] block/nbd: extract the common cleanup code
|
|
||||||
|
|
||||||
The BDRVNBDState cleanup code is common in two places, add
|
|
||||||
nbd_clear_bdrvstate() function to do these cleanups.
|
|
||||||
|
|
||||||
Suggested-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
||||||
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-Id: <1575517528-44312-2-git-send-email-pannengyuan@huawei.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
[eblake: fix compilation error and commit message]
|
|
||||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Signed-off-by: AlexChen <alex.chen@huawei.com>
|
|
||||||
---
|
|
||||||
block/nbd.c | 19 ++++++++++++-------
|
|
||||||
1 file changed, 12 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/nbd.c b/block/nbd.c
|
|
||||||
index 57c1a20..3977b1e 100644
|
|
||||||
--- a/block/nbd.c
|
|
||||||
+++ b/block/nbd.c
|
|
||||||
@@ -73,6 +73,16 @@ typedef struct BDRVNBDState {
|
|
||||||
char *export, *tlscredsid;
|
|
||||||
} BDRVNBDState;
|
|
||||||
|
|
||||||
+static void nbd_clear_bdrvstate(BDRVNBDState *s)
|
|
||||||
+{
|
|
||||||
+ qapi_free_SocketAddress(s->saddr);
|
|
||||||
+ s->saddr = NULL;
|
|
||||||
+ g_free(s->export);
|
|
||||||
+ s->export = NULL;
|
|
||||||
+ g_free(s->tlscredsid);
|
|
||||||
+ s->tlscredsid = NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void nbd_recv_coroutines_wake_all(BDRVNBDState *s)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
@@ -1640,9 +1650,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
|
|
||||||
object_unref(OBJECT(tlscreds));
|
|
||||||
}
|
|
||||||
if (ret < 0) {
|
|
||||||
- qapi_free_SocketAddress(s->saddr);
|
|
||||||
- g_free(s->export);
|
|
||||||
- g_free(s->tlscredsid);
|
|
||||||
+ nbd_clear_bdrvstate(s);
|
|
||||||
}
|
|
||||||
qemu_opts_del(opts);
|
|
||||||
return ret;
|
|
||||||
@@ -1692,10 +1700,7 @@ static void nbd_close(BlockDriverState *bs)
|
|
||||||
BDRVNBDState *s = bs->opaque;
|
|
||||||
|
|
||||||
nbd_client_close(bs);
|
|
||||||
-
|
|
||||||
- qapi_free_SocketAddress(s->saddr);
|
|
||||||
- g_free(s->export);
|
|
||||||
- g_free(s->tlscredsid);
|
|
||||||
+ nbd_clear_bdrvstate(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t nbd_getlength(BlockDriverState *bs)
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
From 0694c489cd240620fee5675e8d24c7ce02d1d67d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Peter Lieven <pl@kamp.de>
|
|
||||||
Date: Tue, 10 Sep 2019 17:41:09 +0200
|
|
||||||
Subject: [PATCH] block/nfs: tear down aio before nfs_close
|
|
||||||
|
|
||||||
nfs_close is a sync call from libnfs and has its own event
|
|
||||||
handler polling on the nfs FD. Avoid that both QEMU and libnfs
|
|
||||||
are intefering here.
|
|
||||||
|
|
||||||
CC: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Peter Lieven <pl@kamp.de>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
(cherry picked from commit 601dc6559725f7a614b6f893611e17ff0908e914)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/nfs.c | 6 ++++--
|
|
||||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/nfs.c b/block/nfs.c
|
|
||||||
index d93241b3bb..2b7a078241 100644
|
|
||||||
--- a/block/nfs.c
|
|
||||||
+++ b/block/nfs.c
|
|
||||||
@@ -390,12 +390,14 @@ static void nfs_attach_aio_context(BlockDriverState *bs,
|
|
||||||
static void nfs_client_close(NFSClient *client)
|
|
||||||
{
|
|
||||||
if (client->context) {
|
|
||||||
+ qemu_mutex_lock(&client->mutex);
|
|
||||||
+ aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
|
||||||
+ false, NULL, NULL, NULL, NULL);
|
|
||||||
+ qemu_mutex_unlock(&client->mutex);
|
|
||||||
if (client->fh) {
|
|
||||||
nfs_close(client->context, client->fh);
|
|
||||||
client->fh = NULL;
|
|
||||||
}
|
|
||||||
- aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
|
|
||||||
- false, NULL, NULL, NULL, NULL);
|
|
||||||
nfs_destroy_context(client->context);
|
|
||||||
client->context = NULL;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,343 +0,0 @@
|
|||||||
From 3d018ff3bdd8aec260254036b600cfa8d694ced4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nir Soffer <nirsof@gmail.com>
|
|
||||||
Date: Tue, 27 Aug 2019 04:05:27 +0300
|
|
||||||
Subject: [PATCH] block: posix: Always allocate the first block
|
|
||||||
|
|
||||||
When creating an image with preallocation "off" or "falloc", the first
|
|
||||||
block of the image is typically not allocated. When using Gluster
|
|
||||||
storage backed by XFS filesystem, reading this block using direct I/O
|
|
||||||
succeeds regardless of request length, fooling alignment detection.
|
|
||||||
|
|
||||||
In this case we fallback to a safe value (4096) instead of the optimal
|
|
||||||
value (512), which may lead to unneeded data copying when aligning
|
|
||||||
requests. Allocating the first block avoids the fallback.
|
|
||||||
|
|
||||||
Since we allocate the first block even with preallocation=off, we no
|
|
||||||
longer create images with zero disk size:
|
|
||||||
|
|
||||||
$ ./qemu-img create -f raw test.raw 1g
|
|
||||||
Formatting 'test.raw', fmt=raw size=1073741824
|
|
||||||
|
|
||||||
$ ls -lhs test.raw
|
|
||||||
4.0K -rw-r--r--. 1 nsoffer nsoffer 1.0G Aug 16 23:48 test.raw
|
|
||||||
|
|
||||||
And converting the image requires additional cluster:
|
|
||||||
|
|
||||||
$ ./qemu-img measure -f raw -O qcow2 test.raw
|
|
||||||
required size: 458752
|
|
||||||
fully allocated size: 1074135040
|
|
||||||
|
|
||||||
When using format like vmdk with multiple files per image, we allocate
|
|
||||||
one block per file:
|
|
||||||
|
|
||||||
$ ./qemu-img create -f vmdk -o subformat=twoGbMaxExtentFlat test.vmdk 4g
|
|
||||||
Formatting 'test.vmdk', fmt=vmdk size=4294967296 compat6=off hwversion=undefined subformat=twoGbMaxExtentFlat
|
|
||||||
|
|
||||||
$ ls -lhs test*.vmdk
|
|
||||||
4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f001.vmdk
|
|
||||||
4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f002.vmdk
|
|
||||||
4.0K -rw-r--r--. 1 nsoffer nsoffer 353 Aug 27 03:23 test.vmdk
|
|
||||||
|
|
||||||
I did quick performance test for copying disks with qemu-img convert to
|
|
||||||
new raw target image to Gluster storage with sector size of 512 bytes:
|
|
||||||
|
|
||||||
for i in $(seq 10); do
|
|
||||||
rm -f dst.raw
|
|
||||||
sleep 10
|
|
||||||
time ./qemu-img convert -f raw -O raw -t none -T none src.raw dst.raw
|
|
||||||
done
|
|
||||||
|
|
||||||
Here is a table comparing the total time spent:
|
|
||||||
|
|
||||||
Type Before(s) After(s) Diff(%)
|
|
||||||
---------------------------------------
|
|
||||||
real 530.028 469.123 -11.4
|
|
||||||
user 17.204 10.768 -37.4
|
|
||||||
sys 17.881 7.011 -60.7
|
|
||||||
|
|
||||||
We can see very clear improvement in CPU usage.
|
|
||||||
|
|
||||||
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
|
|
||||||
Message-id: 20190827010528.8818-2-nsoffer@redhat.com
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
|
|
||||||
(cherry picked from commit 3a20013fbb26d2a1bd11ef148eefdb1508783787)
|
|
||||||
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/file-posix.c | 51 +++++++++++++++++++
|
|
||||||
tests/qemu-iotests/059.out | 2 +-
|
|
||||||
tests/qemu-iotests/{150.out => 150.out.qcow2} | 0
|
|
||||||
tests/qemu-iotests/150.out.raw | 12 +++++
|
|
||||||
tests/qemu-iotests/175 | 19 ++++---
|
|
||||||
tests/qemu-iotests/175.out | 8 +--
|
|
||||||
tests/qemu-iotests/178.out.qcow2 | 4 +-
|
|
||||||
tests/qemu-iotests/221.out | 12 +++--
|
|
||||||
tests/qemu-iotests/253.out | 12 +++--
|
|
||||||
9 files changed, 99 insertions(+), 21 deletions(-)
|
|
||||||
rename tests/qemu-iotests/{150.out => 150.out.qcow2} (100%)
|
|
||||||
create mode 100644 tests/qemu-iotests/150.out.raw
|
|
||||||
|
|
||||||
diff --git a/block/file-posix.c b/block/file-posix.c
|
|
||||||
index be32dd8c51..2184aa980c 100644
|
|
||||||
--- a/block/file-posix.c
|
|
||||||
+++ b/block/file-posix.c
|
|
||||||
@@ -1674,6 +1674,43 @@ static int handle_aiocb_discard(void *opaque)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Help alignment probing by allocating the first block.
|
|
||||||
+ *
|
|
||||||
+ * When reading with direct I/O from unallocated area on Gluster backed by XFS,
|
|
||||||
+ * reading succeeds regardless of request length. In this case we fallback to
|
|
||||||
+ * safe alignment which is not optimal. Allocating the first block avoids this
|
|
||||||
+ * fallback.
|
|
||||||
+ *
|
|
||||||
+ * fd may be opened with O_DIRECT, but we don't know the buffer alignment or
|
|
||||||
+ * request alignment, so we use safe values.
|
|
||||||
+ *
|
|
||||||
+ * Returns: 0 on success, -errno on failure. Since this is an optimization,
|
|
||||||
+ * caller may ignore failures.
|
|
||||||
+ */
|
|
||||||
+static int allocate_first_block(int fd, size_t max_size)
|
|
||||||
+{
|
|
||||||
+ size_t write_size = (max_size < MAX_BLOCKSIZE)
|
|
||||||
+ ? BDRV_SECTOR_SIZE
|
|
||||||
+ : MAX_BLOCKSIZE;
|
|
||||||
+ size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize());
|
|
||||||
+ void *buf;
|
|
||||||
+ ssize_t n;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ buf = qemu_memalign(max_align, write_size);
|
|
||||||
+ memset(buf, 0, write_size);
|
|
||||||
+
|
|
||||||
+ do {
|
|
||||||
+ n = pwrite(fd, buf, write_size, 0);
|
|
||||||
+ } while (n == -1 && errno == EINTR);
|
|
||||||
+
|
|
||||||
+ ret = (n == -1) ? -errno : 0;
|
|
||||||
+
|
|
||||||
+ qemu_vfree(buf);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int handle_aiocb_truncate(void *opaque)
|
|
||||||
{
|
|
||||||
RawPosixAIOData *aiocb = opaque;
|
|
||||||
@@ -1713,6 +1750,17 @@ static int handle_aiocb_truncate(void *opaque)
|
|
||||||
/* posix_fallocate() doesn't set errno. */
|
|
||||||
error_setg_errno(errp, -result,
|
|
||||||
"Could not preallocate new data");
|
|
||||||
+ } else if (current_length == 0) {
|
|
||||||
+ /*
|
|
||||||
+ * posix_fallocate() uses fallocate() if the filesystem
|
|
||||||
+ * supports it, or fallback to manually writing zeroes. If
|
|
||||||
+ * fallocate() was used, unaligned reads from the fallocated
|
|
||||||
+ * area in raw_probe_alignment() will succeed, hence we need to
|
|
||||||
+ * allocate the first block.
|
|
||||||
+ *
|
|
||||||
+ * Optimize future alignment probing; ignore failures.
|
|
||||||
+ */
|
|
||||||
+ allocate_first_block(fd, offset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = 0;
|
|
||||||
@@ -1774,6 +1822,9 @@ static int handle_aiocb_truncate(void *opaque)
|
|
||||||
if (ftruncate(fd, offset) != 0) {
|
|
||||||
result = -errno;
|
|
||||||
error_setg_errno(errp, -result, "Could not resize file");
|
|
||||||
+ } else if (current_length == 0 && offset > current_length) {
|
|
||||||
+ /* Optimize future alignment probing; ignore failures. */
|
|
||||||
+ allocate_first_block(fd, offset);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
default:
|
|
||||||
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
|
|
||||||
index 4fab42a28c..fe3f861f3c 100644
|
|
||||||
--- a/tests/qemu-iotests/059.out
|
|
||||||
+++ b/tests/qemu-iotests/059.out
|
|
||||||
@@ -27,7 +27,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMax
|
|
||||||
image: TEST_DIR/t.vmdk
|
|
||||||
file format: vmdk
|
|
||||||
virtual size: 0.977 TiB (1073741824000 bytes)
|
|
||||||
-disk size: 16 KiB
|
|
||||||
+disk size: 1.97 MiB
|
|
||||||
Format specific information:
|
|
||||||
cid: XXXXXXXX
|
|
||||||
parent cid: XXXXXXXX
|
|
||||||
diff --git a/tests/qemu-iotests/150.out b/tests/qemu-iotests/150.out.qcow2
|
|
||||||
similarity index 100%
|
|
||||||
rename from tests/qemu-iotests/150.out
|
|
||||||
rename to tests/qemu-iotests/150.out.qcow2
|
|
||||||
diff --git a/tests/qemu-iotests/150.out.raw b/tests/qemu-iotests/150.out.raw
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..3cdc7727a5
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tests/qemu-iotests/150.out.raw
|
|
||||||
@@ -0,0 +1,12 @@
|
|
||||||
+QA output created by 150
|
|
||||||
+
|
|
||||||
+=== Mapping sparse conversion ===
|
|
||||||
+
|
|
||||||
+Offset Length File
|
|
||||||
+0 0x1000 TEST_DIR/t.IMGFMT
|
|
||||||
+
|
|
||||||
+=== Mapping non-sparse conversion ===
|
|
||||||
+
|
|
||||||
+Offset Length File
|
|
||||||
+0 0x100000 TEST_DIR/t.IMGFMT
|
|
||||||
+*** done
|
|
||||||
diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175
|
|
||||||
index 51e62c8276..7ba28b3c1b 100755
|
|
||||||
--- a/tests/qemu-iotests/175
|
|
||||||
+++ b/tests/qemu-iotests/175
|
|
||||||
@@ -37,14 +37,16 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
||||||
# the file size. This function hides the resulting difference in the
|
|
||||||
# stat -c '%b' output.
|
|
||||||
# Parameter 1: Number of blocks an empty file occupies
|
|
||||||
-# Parameter 2: Image size in bytes
|
|
||||||
+# Parameter 2: Minimal number of blocks in an image
|
|
||||||
+# Parameter 3: Image size in bytes
|
|
||||||
_filter_blocks()
|
|
||||||
{
|
|
||||||
extra_blocks=$1
|
|
||||||
- img_size=$2
|
|
||||||
+ min_blocks=$2
|
|
||||||
+ img_size=$3
|
|
||||||
|
|
||||||
- sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \
|
|
||||||
- -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/"
|
|
||||||
+ sed -e "s/blocks=$min_blocks\\(\$\\|[^0-9]\\)/min allocation/" \
|
|
||||||
+ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/"
|
|
||||||
}
|
|
||||||
|
|
||||||
# get standard environment, filters and checks
|
|
||||||
@@ -60,16 +62,21 @@ size=$((1 * 1024 * 1024))
|
|
||||||
touch "$TEST_DIR/empty"
|
|
||||||
extra_blocks=$(stat -c '%b' "$TEST_DIR/empty")
|
|
||||||
|
|
||||||
+# We always write the first byte; check how many blocks this filesystem
|
|
||||||
+# allocates to match empty image alloation.
|
|
||||||
+printf "\0" > "$TEST_DIR/empty"
|
|
||||||
+min_blocks=$(stat -c '%b' "$TEST_DIR/empty")
|
|
||||||
+
|
|
||||||
echo
|
|
||||||
echo "== creating image with default preallocation =="
|
|
||||||
_make_test_img $size | _filter_imgfmt
|
|
||||||
-stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size
|
|
||||||
+stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
|
|
||||||
|
|
||||||
for mode in off full falloc; do
|
|
||||||
echo
|
|
||||||
echo "== creating image with preallocation $mode =="
|
|
||||||
IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt
|
|
||||||
- stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size
|
|
||||||
+ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size
|
|
||||||
done
|
|
||||||
|
|
||||||
# success, all done
|
|
||||||
diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out
|
|
||||||
index 6d9a5ed84e..263e521262 100644
|
|
||||||
--- a/tests/qemu-iotests/175.out
|
|
||||||
+++ b/tests/qemu-iotests/175.out
|
|
||||||
@@ -2,17 +2,17 @@ QA output created by 175
|
|
||||||
|
|
||||||
== creating image with default preallocation ==
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
|
||||||
-size=1048576, nothing allocated
|
|
||||||
+size=1048576, min allocation
|
|
||||||
|
|
||||||
== creating image with preallocation off ==
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off
|
|
||||||
-size=1048576, nothing allocated
|
|
||||||
+size=1048576, min allocation
|
|
||||||
|
|
||||||
== creating image with preallocation full ==
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full
|
|
||||||
-size=1048576, everything allocated
|
|
||||||
+size=1048576, max allocation
|
|
||||||
|
|
||||||
== creating image with preallocation falloc ==
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc
|
|
||||||
-size=1048576, everything allocated
|
|
||||||
+size=1048576, max allocation
|
|
||||||
*** done
|
|
||||||
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
|
|
||||||
index 55a8dc926f..9e7d8c44df 100644
|
|
||||||
--- a/tests/qemu-iotests/178.out.qcow2
|
|
||||||
+++ b/tests/qemu-iotests/178.out.qcow2
|
|
||||||
@@ -101,7 +101,7 @@ converted image file size in bytes: 196608
|
|
||||||
== raw input image with data (human) ==
|
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824
|
|
||||||
-required size: 393216
|
|
||||||
+required size: 458752
|
|
||||||
fully allocated size: 1074135040
|
|
||||||
wrote 512/512 bytes at offset 512
|
|
||||||
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
||||||
@@ -257,7 +257,7 @@ converted image file size in bytes: 196608
|
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824
|
|
||||||
{
|
|
||||||
- "required": 393216,
|
|
||||||
+ "required": 458752,
|
|
||||||
"fully-allocated": 1074135040
|
|
||||||
}
|
|
||||||
wrote 512/512 bytes at offset 512
|
|
||||||
diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out
|
|
||||||
index 9f9dd52bb0..dca024a0c3 100644
|
|
||||||
--- a/tests/qemu-iotests/221.out
|
|
||||||
+++ b/tests/qemu-iotests/221.out
|
|
||||||
@@ -3,14 +3,18 @@ QA output created by 221
|
|
||||||
=== Check mapping of unaligned raw image ===
|
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537
|
|
||||||
-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
wrote 1/1 bytes at offset 65536
|
|
||||||
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
||||||
-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
*** done
|
|
||||||
diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out
|
|
||||||
index 607c0baa0b..3d08b305d7 100644
|
|
||||||
--- a/tests/qemu-iotests/253.out
|
|
||||||
+++ b/tests/qemu-iotests/253.out
|
|
||||||
@@ -3,12 +3,16 @@ QA output created by 253
|
|
||||||
=== Check mapping of unaligned raw image ===
|
|
||||||
|
|
||||||
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575
|
|
||||||
-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}]
|
|
||||||
wrote 65535/65535 bytes at offset 983040
|
|
||||||
63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
|
||||||
-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
|
|
||||||
-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
|
|
||||||
+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET},
|
|
||||||
{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
|
|
||||||
*** done
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
From 84f22c728520792f1010074e0d5ac2ec8e2e372c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Maxim Levitsky <mlevitsk@redhat.com>
|
|
||||||
Date: Sun, 15 Sep 2019 23:36:53 +0300
|
|
||||||
Subject: [PATCH] block/qcow2: Fix corruption introduced by commit 8ac0f15f335
|
|
||||||
|
|
||||||
This fixes subtle corruption introduced by luks threaded encryption
|
|
||||||
in commit 8ac0f15f335
|
|
||||||
|
|
||||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1745922
|
|
||||||
|
|
||||||
The corruption happens when we do a write that
|
|
||||||
* writes to two or more unallocated clusters at once
|
|
||||||
* doesn't fully cover the first sector
|
|
||||||
* doesn't fully cover the last sector
|
|
||||||
* uses luks encryption
|
|
||||||
|
|
||||||
In this case, when allocating the new clusters we COW both areas
|
|
||||||
prior to the write and after the write, and we encrypt them.
|
|
||||||
|
|
||||||
The above mentioned commit accidentally made it so we encrypt the
|
|
||||||
second COW area using the physical cluster offset of the first area.
|
|
||||||
|
|
||||||
The problem is that offset_in_cluster in do_perform_cow_encrypt
|
|
||||||
can be larger that the cluster size, thus cluster_offset
|
|
||||||
will no longer point to the start of the cluster at which encrypted
|
|
||||||
area starts.
|
|
||||||
|
|
||||||
Next patch in this series will refactor the code to avoid all these
|
|
||||||
assumptions.
|
|
||||||
|
|
||||||
In the bugreport that was triggered by rebasing a luks image to new,
|
|
||||||
zero filled base, which lot of such writes, and causes some files
|
|
||||||
with zero areas to contain garbage there instead.
|
|
||||||
But as described above it can happen elsewhere as well
|
|
||||||
|
|
||||||
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
|
|
||||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-id: 20190915203655.21638-2-mlevitsk@redhat.com
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit 38e7d54bdc518b5a05a922467304bcace2396945)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/qcow2-cluster.c | 7 ++++---
|
|
||||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
|
|
||||||
index cc5609e27a..760564c8fb 100644
|
|
||||||
--- a/block/qcow2-cluster.c
|
|
||||||
+++ b/block/qcow2-cluster.c
|
|
||||||
@@ -473,9 +473,10 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs,
|
|
||||||
assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0);
|
|
||||||
assert((bytes & ~BDRV_SECTOR_MASK) == 0);
|
|
||||||
assert(s->crypto);
|
|
||||||
- if (qcow2_co_encrypt(bs, cluster_offset,
|
|
||||||
- src_cluster_offset + offset_in_cluster,
|
|
||||||
- buffer, bytes) < 0) {
|
|
||||||
+ if (qcow2_co_encrypt(bs,
|
|
||||||
+ start_of_cluster(s, cluster_offset + offset_in_cluster),
|
|
||||||
+ src_cluster_offset + offset_in_cluster,
|
|
||||||
+ buffer, bytes) < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
From 88ef4e1862987227f8b87228cff94be3af66d054 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
Date: Thu, 27 Feb 2020 09:29:49 +0800
|
|
||||||
Subject: [PATCH 01/14] block/qcow2: do free crypto_opts in qcow2_close()
|
|
||||||
|
|
||||||
'crypto_opts' forgot to free in qcow2_close(), this patch fix the bellow leak stack:
|
|
||||||
|
|
||||||
Direct leak of 24 byte(s) in 1 object(s) allocated from:
|
|
||||||
#0 0x7f0edd81f970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970)
|
|
||||||
#1 0x7f0edc6d149d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d)
|
|
||||||
#2 0x55d7eaede63d in qobject_input_start_struct /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qobject-input-visitor.c:295
|
|
||||||
#3 0x55d7eaed78b8 in visit_start_struct /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qapi-visit-core.c:49
|
|
||||||
#4 0x55d7eaf5140b in visit_type_QCryptoBlockOpenOptions qapi/qapi-visit-crypto.c:290
|
|
||||||
#5 0x55d7eae43af3 in block_crypto_open_opts_init /mnt/sdb/qemu-new/qemu_test/qemu/block/crypto.c:163
|
|
||||||
#6 0x55d7eacd2924 in qcow2_update_options_prepare /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1148
|
|
||||||
#7 0x55d7eacd33f7 in qcow2_update_options /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1232
|
|
||||||
#8 0x55d7eacd9680 in qcow2_do_open /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1512
|
|
||||||
#9 0x55d7eacdc55e in qcow2_open_entry /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1792
|
|
||||||
#10 0x55d7eacdc8fe in qcow2_open /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1819
|
|
||||||
#11 0x55d7eac3742d in bdrv_open_driver /mnt/sdb/qemu-new/qemu_test/qemu/block.c:1317
|
|
||||||
#12 0x55d7eac3e990 in bdrv_open_common /mnt/sdb/qemu-new/qemu_test/qemu/block.c:1575
|
|
||||||
#13 0x55d7eac4442c in bdrv_open_inherit /mnt/sdb/qemu-new/qemu_test/qemu/block.c:3126
|
|
||||||
#14 0x55d7eac45c3f in bdrv_open /mnt/sdb/qemu-new/qemu_test/qemu/block.c:3219
|
|
||||||
#15 0x55d7ead8e8a4 in blk_new_open /mnt/sdb/qemu-new/qemu_test/qemu/block/block-backend.c:397
|
|
||||||
#16 0x55d7eacde74c in qcow2_co_create /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:3534
|
|
||||||
#17 0x55d7eacdfa6d in qcow2_co_create_opts /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:3668
|
|
||||||
#18 0x55d7eac1c678 in bdrv_create_co_entry /mnt/sdb/qemu-new/qemu_test/qemu/block.c:485
|
|
||||||
#19 0x55d7eb0024d2 in coroutine_trampoline /mnt/sdb/qemu-new/qemu_test/qemu/util/coroutine-ucontext.c:115
|
|
||||||
|
|
||||||
Reported-by: Euler Robot <euler.robot@huawei.com>
|
|
||||||
Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-Id: <20200227012950.12256-2-pannengyuan@huawei.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
|
||||||
---
|
|
||||||
block/qcow2.c | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/block/qcow2.c b/block/qcow2.c
|
|
||||||
index 1909df6e1d24..27c54b9905aa 100644
|
|
||||||
--- a/block/qcow2.c
|
|
||||||
+++ b/block/qcow2.c
|
|
||||||
@@ -2408,6 +2408,7 @@ static void qcow2_close(BlockDriverState *bs)
|
|
||||||
|
|
||||||
qcrypto_block_free(s->crypto);
|
|
||||||
s->crypto = NULL;
|
|
||||||
+ qapi_free_QCryptoBlockOpenOptions(s->crypto_opts);
|
|
||||||
|
|
||||||
g_free(s->unknown_header_fields);
|
|
||||||
cleanup_unknown_header_ext(bs);
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
From a583b6b616b086d3fdce93e255d24ab2c865efd3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Date: Mon, 2 Mar 2020 18:09:30 +0300
|
|
||||||
Subject: [PATCH 03/14] block/qcow2-threads: fix qcow2_decompress
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
On success path we return what inflate() returns instead of 0. And it
|
|
||||||
most probably works for Z_STREAM_END as it is positive, but is
|
|
||||||
definitely broken for Z_BUF_ERROR.
|
|
||||||
|
|
||||||
While being here, switch to errno return code, to be closer to
|
|
||||||
qcow2_compress API (and usual expectations).
|
|
||||||
|
|
||||||
Revert condition in if to be more positive. Drop dead initialization of
|
|
||||||
ret.
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org # v4.0
|
|
||||||
Fixes: 341926ab83e2b
|
|
||||||
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
||||||
Message-Id: <20200302150930.16218-1-vsementsov@virtuozzo.com>
|
|
||||||
Reviewed-by: Alberto Garcia <berto@igalia.com>
|
|
||||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Peng Liang <liangpeng10@huawei.com>
|
|
||||||
---
|
|
||||||
block/qcow2-threads.c | 12 +++++++-----
|
|
||||||
1 file changed, 7 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
|
|
||||||
index 3b1e63fe414d..449cd3c0a1f4 100644
|
|
||||||
--- a/block/qcow2-threads.c
|
|
||||||
+++ b/block/qcow2-threads.c
|
|
||||||
@@ -128,12 +128,12 @@ static ssize_t qcow2_compress(void *dest, size_t dest_size,
|
|
||||||
* @src - source buffer, @src_size bytes
|
|
||||||
*
|
|
||||||
* Returns: 0 on success
|
|
||||||
- * -1 on fail
|
|
||||||
+ * -EIO on fail
|
|
||||||
*/
|
|
||||||
static ssize_t qcow2_decompress(void *dest, size_t dest_size,
|
|
||||||
const void *src, size_t src_size)
|
|
||||||
{
|
|
||||||
- int ret = 0;
|
|
||||||
+ int ret;
|
|
||||||
z_stream strm;
|
|
||||||
|
|
||||||
memset(&strm, 0, sizeof(strm));
|
|
||||||
@@ -144,17 +144,19 @@ static ssize_t qcow2_decompress(void *dest, size_t dest_size,
|
|
||||||
|
|
||||||
ret = inflateInit2(&strm, -12);
|
|
||||||
if (ret != Z_OK) {
|
|
||||||
- return -1;
|
|
||||||
+ return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = inflate(&strm, Z_FINISH);
|
|
||||||
- if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || strm.avail_out != 0) {
|
|
||||||
+ if ((ret == Z_STREAM_END || ret == Z_BUF_ERROR) && strm.avail_out == 0) {
|
|
||||||
/*
|
|
||||||
* We approve Z_BUF_ERROR because we need @dest buffer to be filled, but
|
|
||||||
* @src buffer may be processed partly (because in qcow2 we know size of
|
|
||||||
* compressed data with precision of one sector)
|
|
||||||
*/
|
|
||||||
- ret = -1;
|
|
||||||
+ ret = 0;
|
|
||||||
+ } else {
|
|
||||||
+ ret = -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
inflateEnd(&strm);
|
|
||||||
--
|
|
||||||
2.26.2
|
|
||||||
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
From 7a8aa6c734bb1c2927ad0cc1d10bcacb53cf4ae3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Date: Tue, 17 Sep 2019 12:26:23 +0200
|
|
||||||
Subject: [PATCH] block/snapshot: Restrict set of snapshot nodes
|
|
||||||
|
|
||||||
Nodes involved in internal snapshots were those that were returned by
|
|
||||||
bdrv_next(), inserted and not read-only. bdrv_next() in turn returns all
|
|
||||||
nodes that are either the root node of a BlockBackend or monitor-owned
|
|
||||||
nodes.
|
|
||||||
|
|
||||||
With the typical -drive use, this worked well enough. However, in the
|
|
||||||
typical -blockdev case, the user defines one node per option, making all
|
|
||||||
nodes monitor-owned nodes. This includes protocol nodes etc. which often
|
|
||||||
are not snapshottable, so "savevm" only returns an error.
|
|
||||||
|
|
||||||
Change the conditions so that internal snapshot still include all nodes
|
|
||||||
that have a BlockBackend attached (we definitely want to snapshot
|
|
||||||
anything attached to a guest device and probably also the built-in NBD
|
|
||||||
server; snapshotting block job BlockBackends is more of an accident, but
|
|
||||||
a preexisting one), but other monitor-owned nodes are only included if
|
|
||||||
they have no parents.
|
|
||||||
|
|
||||||
This makes internal snapshots usable again with typical -blockdev
|
|
||||||
configurations.
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
|
|
||||||
Tested-by: Peter Krempa <pkrempa@redhat.com>
|
|
||||||
(cherry picked from commit 05f4aced658a02b02d3e89a6c7a2281008fcf26c)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
block/snapshot.c | 26 +++++++++++++++++++-------
|
|
||||||
1 file changed, 19 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/snapshot.c b/block/snapshot.c
|
|
||||||
index f2f48f926a..8081616ae9 100644
|
|
||||||
--- a/block/snapshot.c
|
|
||||||
+++ b/block/snapshot.c
|
|
||||||
@@ -31,6 +31,7 @@
|
|
||||||
#include "qapi/qmp/qerror.h"
|
|
||||||
#include "qapi/qmp/qstring.h"
|
|
||||||
#include "qemu/option.h"
|
|
||||||
+#include "sysemu/block-backend.h"
|
|
||||||
|
|
||||||
QemuOptsList internal_snapshot_opts = {
|
|
||||||
.name = "snapshot",
|
|
||||||
@@ -384,6 +385,16 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs)
|
|
||||||
+{
|
|
||||||
+ if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Include all nodes that are either in use by a BlockBackend, or that
|
|
||||||
+ * aren't attached to any node, but owned by the monitor. */
|
|
||||||
+ return bdrv_has_blk(bs) || QLIST_EMPTY(&bs->parents);
|
|
||||||
+}
|
|
||||||
|
|
||||||
/* Group operations. All block drivers are involved.
|
|
||||||
* These functions will properly handle dataplane (take aio_context_acquire
|
|
||||||
@@ -399,7 +410,7 @@ bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs)
|
|
||||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
|
||||||
- if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) {
|
|
||||||
+ if (bdrv_all_snapshots_includes_bs(bs)) {
|
|
||||||
ok = bdrv_can_snapshot(bs);
|
|
||||||
}
|
|
||||||
aio_context_release(ctx);
|
|
||||||
@@ -426,8 +437,9 @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
|
|
||||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
|
||||||
- if (bdrv_can_snapshot(bs) &&
|
|
||||||
- bdrv_snapshot_find(bs, snapshot, name) >= 0) {
|
|
||||||
+ if (bdrv_all_snapshots_includes_bs(bs) &&
|
|
||||||
+ bdrv_snapshot_find(bs, snapshot, name) >= 0)
|
|
||||||
+ {
|
|
||||||
ret = bdrv_snapshot_delete(bs, snapshot->id_str,
|
|
||||||
snapshot->name, err);
|
|
||||||
}
|
|
||||||
@@ -455,7 +467,7 @@ int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs,
|
|
||||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
|
||||||
- if (bdrv_can_snapshot(bs)) {
|
|
||||||
+ if (bdrv_all_snapshots_includes_bs(bs)) {
|
|
||||||
ret = bdrv_snapshot_goto(bs, name, errp);
|
|
||||||
}
|
|
||||||
aio_context_release(ctx);
|
|
||||||
@@ -481,7 +493,7 @@ int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs)
|
|
||||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
|
||||||
- if (bdrv_can_snapshot(bs)) {
|
|
||||||
+ if (bdrv_all_snapshots_includes_bs(bs)) {
|
|
||||||
err = bdrv_snapshot_find(bs, &sn, name);
|
|
||||||
}
|
|
||||||
aio_context_release(ctx);
|
|
||||||
@@ -512,7 +524,7 @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
|
|
||||||
if (bs == vm_state_bs) {
|
|
||||||
sn->vm_state_size = vm_state_size;
|
|
||||||
err = bdrv_snapshot_create(bs, sn);
|
|
||||||
- } else if (bdrv_can_snapshot(bs)) {
|
|
||||||
+ } else if (bdrv_all_snapshots_includes_bs(bs)) {
|
|
||||||
sn->vm_state_size = 0;
|
|
||||||
err = bdrv_snapshot_create(bs, sn);
|
|
||||||
}
|
|
||||||
@@ -538,7 +550,7 @@ BlockDriverState *bdrv_all_find_vmstate_bs(void)
|
|
||||||
bool found;
|
|
||||||
|
|
||||||
aio_context_acquire(ctx);
|
|
||||||
- found = bdrv_can_snapshot(bs);
|
|
||||||
+ found = bdrv_all_snapshots_includes_bs(bs) && bdrv_can_snapshot(bs);
|
|
||||||
aio_context_release(ctx);
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
From c9a4e85610bffe1803648c431e4cff4539a42323 Mon Sep 17 00:00:00 2001
|
|
||||||
From: AlexChen <alex.chen@huawei.com>
|
|
||||||
Date: Tue, 3 Nov 2020 17:42:56 +0800
|
|
||||||
Subject: [PATCH] block/vvfat: Fix bad printf format specifiers
|
|
||||||
|
|
||||||
We should use printf format specifier "%u" instead of "%d" for
|
|
||||||
argument of type "unsigned int".
|
|
||||||
In addition, fix two error format problems found by checkpatch.pl:
|
|
||||||
ERROR: space required after that ',' (ctx:VxV)
|
|
||||||
+ fprintf(stderr,"%s attributes=0x%02x begin=%u size=%d\n",
|
|
||||||
^
|
|
||||||
ERROR: line over 90 characters
|
|
||||||
+ fprintf(stderr, "%d, %s (%u, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
|
|
||||||
|
|
||||||
Reported-by: Euler Robot <euler.robot@huawei.com>
|
|
||||||
Signed-off-by: Alex Chen <alex.chen@huawei.com>
|
|
||||||
Message-Id: <5FA12620.6030705@huawei.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
(cherry-picked from commit c9eb2f3e38)
|
|
||||||
---
|
|
||||||
block/vvfat.c | 12 +++++++-----
|
|
||||||
1 file changed, 7 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/vvfat.c b/block/vvfat.c
|
|
||||||
index f6c28805dd..5dc8d6eb4c 100644
|
|
||||||
--- a/block/vvfat.c
|
|
||||||
+++ b/block/vvfat.c
|
|
||||||
@@ -1453,7 +1453,7 @@ static void print_direntry(const direntry_t* direntry)
|
|
||||||
for(i=0;i<11;i++)
|
|
||||||
ADD_CHAR(direntry->name[i]);
|
|
||||||
buffer[j] = 0;
|
|
||||||
- fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n",
|
|
||||||
+ fprintf(stderr, "%s attributes=0x%02x begin=%u size=%u\n",
|
|
||||||
buffer,
|
|
||||||
direntry->attributes,
|
|
||||||
begin_of_direntry(direntry),le32_to_cpu(direntry->size));
|
|
||||||
@@ -1462,7 +1462,7 @@ static void print_direntry(const direntry_t* direntry)
|
|
||||||
|
|
||||||
static void print_mapping(const mapping_t* mapping)
|
|
||||||
{
|
|
||||||
- fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
|
|
||||||
+ fprintf(stderr, "mapping (%p): begin, end = %u, %u, dir_index = %u, "
|
|
||||||
"first_mapping_index = %d, name = %s, mode = 0x%x, " ,
|
|
||||||
mapping, mapping->begin, mapping->end, mapping->dir_index,
|
|
||||||
mapping->first_mapping_index, mapping->path, mapping->mode);
|
|
||||||
@@ -1470,7 +1470,7 @@ static void print_mapping(const mapping_t* mapping)
|
|
||||||
if (mapping->mode & MODE_DIRECTORY)
|
|
||||||
fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
|
|
||||||
else
|
|
||||||
- fprintf(stderr, "offset = %d\n", mapping->info.file.offset);
|
|
||||||
+ fprintf(stderr, "offset = %u\n", mapping->info.file.offset);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1604,7 +1604,7 @@ typedef struct commit_t {
|
|
||||||
static void clear_commits(BDRVVVFATState* s)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
-DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next));
|
|
||||||
+DLOG(fprintf(stderr, "clear_commits (%u commits)\n", s->commits.next));
|
|
||||||
for (i = 0; i < s->commits.next; i++) {
|
|
||||||
commit_t* commit = array_get(&(s->commits), i);
|
|
||||||
assert(commit->path || commit->action == ACTION_WRITEOUT);
|
|
||||||
@@ -2660,7 +2660,9 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
|
|
||||||
fprintf(stderr, "handle_renames\n");
|
|
||||||
for (i = 0; i < s->commits.next; i++) {
|
|
||||||
commit_t* commit = array_get(&(s->commits), i);
|
|
||||||
- fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action);
|
|
||||||
+ fprintf(stderr, "%d, %s (%u, %d)\n", i,
|
|
||||||
+ commit->path ? commit->path : "(null)",
|
|
||||||
+ commit->param.rename.cluster, commit->action);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
From dc6b61f12750b3ab5a3965af2ec758750389233d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sergio Lopez <slp@redhat.com>
|
|
||||||
Date: Wed, 8 Jan 2020 15:31:37 +0100
|
|
||||||
Subject: [PATCH] blockdev: Return bs to the proper context on snapshot abort
|
|
||||||
|
|
||||||
external_snapshot_abort() calls to bdrv_set_backing_hd(), which
|
|
||||||
returns state->old_bs to the main AioContext, as it's intended to be
|
|
||||||
used then the BDS is going to be released. As that's not the case when
|
|
||||||
aborting an external snapshot, return it to the AioContext it was
|
|
||||||
before the call.
|
|
||||||
|
|
||||||
This issue can be triggered by issuing a transaction with two actions,
|
|
||||||
a proper blockdev-snapshot-sync and a bogus one, so the second will
|
|
||||||
trigger a transaction abort. This results in a crash with an stack
|
|
||||||
trace like this one:
|
|
||||||
|
|
||||||
#0 0x00007fa1048b28df in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
|
|
||||||
#1 0x00007fa10489ccf5 in __GI_abort () at abort.c:79
|
|
||||||
#2 0x00007fa10489cbc9 in __assert_fail_base
|
|
||||||
(fmt=0x7fa104a03300 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=0x557224014d30 "block.c", line=2240, function=<optimized out>) at assert.c:92
|
|
||||||
#3 0x00007fa1048aae96 in __GI___assert_fail
|
|
||||||
(assertion=assertion@entry=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=file@entry=0x557224014d30 "block.c", line=line@entry=2240, function=function@entry=0x5572240b5d60 <__PRETTY_FUNCTION__.31620> "bdrv_replace_child_noperm") at assert.c:101
|
|
||||||
#4 0x0000557223e631f8 in bdrv_replace_child_noperm (child=0x557225b9c980, new_bs=new_bs@entry=0x557225c42e40) at block.c:2240
|
|
||||||
#5 0x0000557223e68be7 in bdrv_replace_node (from=0x557226951a60, to=0x557225c42e40, errp=0x5572247d6138 <error_abort>) at block.c:4196
|
|
||||||
#6 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1731
|
|
||||||
#7 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1717
|
|
||||||
#8 0x0000557223d09013 in qmp_transaction (dev_list=<optimized out>, has_props=<optimized out>, props=0x557225cc7d70, errp=errp@entry=0x7ffe704c0c98) at blockdev.c:2360
|
|
||||||
#9 0x0000557223e32085 in qmp_marshal_transaction (args=<optimized out>, ret=<optimized out>, errp=0x7ffe704c0d08) at qapi/qapi-commands-transaction.c:44
|
|
||||||
#10 0x0000557223ee798c in do_qmp_dispatch (errp=0x7ffe704c0d00, allow_oob=<optimized out>, request=<optimized out>, cmds=0x5572247d3cc0 <qmp_commands>) at qapi/qmp-dispatch.c:132
|
|
||||||
#11 0x0000557223ee798c in qmp_dispatch (cmds=0x5572247d3cc0 <qmp_commands>, request=<optimized out>, allow_oob=<optimized out>) at qapi/qmp-dispatch.c:175
|
|
||||||
#12 0x0000557223e06141 in monitor_qmp_dispatch (mon=0x557225c69ff0, req=<optimized out>) at monitor/qmp.c:120
|
|
||||||
#13 0x0000557223e0678a in monitor_qmp_bh_dispatcher (data=<optimized out>) at monitor/qmp.c:209
|
|
||||||
#14 0x0000557223f2f366 in aio_bh_call (bh=0x557225b9dc60) at util/async.c:117
|
|
||||||
#15 0x0000557223f2f366 in aio_bh_poll (ctx=ctx@entry=0x557225b9c840) at util/async.c:117
|
|
||||||
#16 0x0000557223f32754 in aio_dispatch (ctx=0x557225b9c840) at util/aio-posix.c:459
|
|
||||||
#17 0x0000557223f2f242 in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:260
|
|
||||||
#18 0x00007fa10913467d in g_main_dispatch (context=0x557225c28e80) at gmain.c:3176
|
|
||||||
#19 0x00007fa10913467d in g_main_context_dispatch (context=context@entry=0x557225c28e80) at gmain.c:3829
|
|
||||||
#20 0x0000557223f31808 in glib_pollfds_poll () at util/main-loop.c:219
|
|
||||||
#21 0x0000557223f31808 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:242
|
|
||||||
#22 0x0000557223f31808 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:518
|
|
||||||
#23 0x0000557223d13201 in main_loop () at vl.c:1828
|
|
||||||
#24 0x0000557223bbfb82 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4504
|
|
||||||
|
|
||||||
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1779036
|
|
||||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
blockdev.c | 21 +++++++++++++++++++++
|
|
||||||
1 file changed, 21 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 5088541591..79112be2e6 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -1774,6 +1774,8 @@ static void external_snapshot_abort(BlkActionState *common)
|
|
||||||
if (state->new_bs) {
|
|
||||||
if (state->overlay_appended) {
|
|
||||||
AioContext *aio_context;
|
|
||||||
+ AioContext *tmp_context;
|
|
||||||
+ int ret;
|
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(state->old_bs);
|
|
||||||
aio_context_acquire(aio_context);
|
|
||||||
@@ -1781,6 +1783,25 @@ static void external_snapshot_abort(BlkActionState *common)
|
|
||||||
bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd()
|
|
||||||
close state->old_bs; we need it */
|
|
||||||
bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * The call to bdrv_set_backing_hd() above returns state->old_bs to
|
|
||||||
+ * the main AioContext. As we're still going to be using it, return
|
|
||||||
+ * it to the AioContext it was before.
|
|
||||||
+ */
|
|
||||||
+ tmp_context = bdrv_get_aio_context(state->old_bs);
|
|
||||||
+ if (aio_context != tmp_context) {
|
|
||||||
+ aio_context_release(aio_context);
|
|
||||||
+ aio_context_acquire(tmp_context);
|
|
||||||
+
|
|
||||||
+ ret = bdrv_try_set_aio_context(state->old_bs,
|
|
||||||
+ aio_context, NULL);
|
|
||||||
+ assert(ret == 0);
|
|
||||||
+
|
|
||||||
+ aio_context_release(tmp_context);
|
|
||||||
+ aio_context_acquire(aio_context);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
|
|
||||||
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
From e5456acf2332efd0ed6106eb13cf24e6bca1ee64 Mon Sep 17 00:00:00 2001
|
|
||||||
From: John Snow <jsnow@redhat.com>
|
|
||||||
Date: Mon, 29 Jul 2019 16:35:52 -0400
|
|
||||||
Subject: [PATCH] blockdev-backup: utilize do_backup_common
|
|
||||||
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20190709232550.10724-4-jsnow@redhat.com
|
|
||||||
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
||||||
---
|
|
||||||
blockdev.c | 65 +++++-------------------------------------------------
|
|
||||||
1 file changed, 6 insertions(+), 59 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index a29838a1c8..aa15ed1f00 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -3668,78 +3668,25 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
|
|
||||||
{
|
|
||||||
BlockDriverState *bs;
|
|
||||||
BlockDriverState *target_bs;
|
|
||||||
- Error *local_err = NULL;
|
|
||||||
- BdrvDirtyBitmap *bmap = NULL;
|
|
||||||
AioContext *aio_context;
|
|
||||||
- BlockJob *job = NULL;
|
|
||||||
- int job_flags = JOB_DEFAULT;
|
|
||||||
- int ret;
|
|
||||||
-
|
|
||||||
- if (!backup->has_speed) {
|
|
||||||
- backup->speed = 0;
|
|
||||||
- }
|
|
||||||
- if (!backup->has_on_source_error) {
|
|
||||||
- backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT;
|
|
||||||
- }
|
|
||||||
- if (!backup->has_on_target_error) {
|
|
||||||
- backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
|
||||||
- }
|
|
||||||
- if (!backup->has_job_id) {
|
|
||||||
- backup->job_id = NULL;
|
|
||||||
- }
|
|
||||||
- if (!backup->has_auto_finalize) {
|
|
||||||
- backup->auto_finalize = true;
|
|
||||||
- }
|
|
||||||
- if (!backup->has_auto_dismiss) {
|
|
||||||
- backup->auto_dismiss = true;
|
|
||||||
- }
|
|
||||||
- if (!backup->has_compress) {
|
|
||||||
- backup->compress = false;
|
|
||||||
- }
|
|
||||||
+ BlockJob *job;
|
|
||||||
|
|
||||||
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
|
||||||
if (!bs) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- aio_context = bdrv_get_aio_context(bs);
|
|
||||||
- aio_context_acquire(aio_context);
|
|
||||||
-
|
|
||||||
target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
|
|
||||||
if (!target_bs) {
|
|
||||||
- goto out;
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
+ aio_context = bdrv_get_aio_context(bs);
|
|
||||||
+ aio_context_acquire(aio_context);
|
|
||||||
|
|
||||||
- if (backup->has_bitmap) {
|
|
||||||
- bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
|
|
||||||
- if (!bmap) {
|
|
||||||
- error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ job = do_backup_common(qapi_BlockdevBackup_base(backup),
|
|
||||||
+ bs, target_bs, aio_context, txn, errp);
|
|
||||||
|
|
||||||
- if (!backup->auto_finalize) {
|
|
||||||
- job_flags |= JOB_MANUAL_FINALIZE;
|
|
||||||
- }
|
|
||||||
- if (!backup->auto_dismiss) {
|
|
||||||
- job_flags |= JOB_MANUAL_DISMISS;
|
|
||||||
- }
|
|
||||||
- job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
|
|
||||||
- backup->sync, bmap, backup->compress,
|
|
||||||
- backup->on_source_error, backup->on_target_error,
|
|
||||||
- job_flags, NULL, NULL, txn, &local_err);
|
|
||||||
- if (local_err != NULL) {
|
|
||||||
- error_propagate(errp, local_err);
|
|
||||||
- }
|
|
||||||
-out:
|
|
||||||
aio_context_release(aio_context);
|
|
||||||
return job;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
From ffbf1e237d0311512c411e195278e69d710fb9cf Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sergio Lopez <slp@redhat.com>
|
|
||||||
Date: Wed, 8 Jan 2020 15:31:31 +0100
|
|
||||||
Subject: [PATCH] blockdev: fix coding style issues in drive_backup_prepare
|
|
||||||
|
|
||||||
Fix a couple of minor coding style issues in drive_backup_prepare.
|
|
||||||
|
|
||||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
blockdev.c | 8 +++++---
|
|
||||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 4435795b6d..99b1cafb8f 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -3597,7 +3597,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
|
||||||
|
|
||||||
if (!backup->has_format) {
|
|
||||||
backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
|
|
||||||
- NULL : (char*) bs->drv->format_name;
|
|
||||||
+ NULL : (char *) bs->drv->format_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Early check to avoid creating target */
|
|
||||||
@@ -3607,8 +3607,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
|
||||||
|
|
||||||
flags = bs->open_flags | BDRV_O_RDWR;
|
|
||||||
|
|
||||||
- /* See if we have a backing HD we can use to create our new image
|
|
||||||
- * on top of. */
|
|
||||||
+ /*
|
|
||||||
+ * See if we have a backing HD we can use to create our new image
|
|
||||||
+ * on top of.
|
|
||||||
+ */
|
|
||||||
if (backup->sync == MIRROR_SYNC_MODE_TOP) {
|
|
||||||
source = backing_bs(bs);
|
|
||||||
if (!source) {
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,191 +0,0 @@
|
|||||||
From 64c6b3b911f65c19f3a235c8394f5db894c1ee6a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sergio Lopez <slp@redhat.com>
|
|
||||||
Date: Wed, 8 Jan 2020 15:31:34 +0100
|
|
||||||
Subject: [PATCH] blockdev: honor bdrv_try_set_aio_context() context
|
|
||||||
requirements
|
|
||||||
|
|
||||||
bdrv_try_set_aio_context() requires that the old context is held, and
|
|
||||||
the new context is not held. Fix all the occurrences where it's not
|
|
||||||
done this way.
|
|
||||||
|
|
||||||
Suggested-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
blockdev.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-------
|
|
||||||
1 file changed, 60 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index d3309c205a..5088541591 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -1578,6 +1578,7 @@ static void external_snapshot_prepare(BlkActionState *common,
|
|
||||||
DO_UPCAST(ExternalSnapshotState, common, common);
|
|
||||||
TransactionAction *action = common->action;
|
|
||||||
AioContext *aio_context;
|
|
||||||
+ AioContext *old_context;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
|
|
||||||
@@ -1718,7 +1719,16 @@ static void external_snapshot_prepare(BlkActionState *common,
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
|
||||||
+ old_context = bdrv_get_aio_context(state->new_bs);
|
|
||||||
+ aio_context_release(aio_context);
|
|
||||||
+ aio_context_acquire(old_context);
|
|
||||||
+
|
|
||||||
ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
|
|
||||||
+
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
+ aio_context_acquire(aio_context);
|
|
||||||
+
|
|
||||||
if (ret < 0) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
@@ -1818,11 +1828,13 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
BlockDriverState *target_bs;
|
|
||||||
BlockDriverState *source = NULL;
|
|
||||||
AioContext *aio_context;
|
|
||||||
+ AioContext *old_context;
|
|
||||||
QDict *options;
|
|
||||||
Error *local_err = NULL;
|
|
||||||
int flags;
|
|
||||||
int64_t size;
|
|
||||||
bool set_backing_hd = false;
|
|
||||||
+ int ret;
|
|
||||||
|
|
||||||
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
|
||||||
backup = common->action->u.drive_backup.data;
|
|
||||||
@@ -1911,6 +1923,21 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
|
||||||
+ old_context = bdrv_get_aio_context(target_bs);
|
|
||||||
+ aio_context_release(aio_context);
|
|
||||||
+ aio_context_acquire(old_context);
|
|
||||||
+
|
|
||||||
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ bdrv_unref(target_bs);
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
+ aio_context_acquire(aio_context);
|
|
||||||
+
|
|
||||||
if (set_backing_hd) {
|
|
||||||
bdrv_set_backing_hd(target_bs, source, &local_err);
|
|
||||||
if (local_err) {
|
|
||||||
@@ -1990,6 +2017,8 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
BlockDriverState *bs;
|
|
||||||
BlockDriverState *target_bs;
|
|
||||||
AioContext *aio_context;
|
|
||||||
+ AioContext *old_context;
|
|
||||||
+ int ret;
|
|
||||||
|
|
||||||
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
|
||||||
backup = common->action->u.blockdev_backup.data;
|
|
||||||
@@ -2004,7 +2033,18 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
|
||||||
+ old_context = bdrv_get_aio_context(target_bs);
|
|
||||||
+ aio_context_acquire(old_context);
|
|
||||||
+
|
|
||||||
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
aio_context_acquire(aio_context);
|
|
||||||
state->bs = bs;
|
|
||||||
|
|
||||||
@@ -3562,7 +3602,6 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
BlockJob *job = NULL;
|
|
||||||
BdrvDirtyBitmap *bmap = NULL;
|
|
||||||
int job_flags = JOB_DEFAULT;
|
|
||||||
- int ret;
|
|
||||||
|
|
||||||
if (!backup->has_speed) {
|
|
||||||
backup->speed = 0;
|
|
||||||
@@ -3586,11 +3625,6 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
backup->compress = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
|
|
||||||
(backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) {
|
|
||||||
/* done before desugaring 'incremental' to print the right message */
|
|
||||||
@@ -3802,6 +3836,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
|
||||||
BlockDriverState *bs;
|
|
||||||
BlockDriverState *source, *target_bs;
|
|
||||||
AioContext *aio_context;
|
|
||||||
+ AioContext *old_context;
|
|
||||||
BlockMirrorBackingMode backing_mode;
|
|
||||||
Error *local_err = NULL;
|
|
||||||
QDict *options = NULL;
|
|
||||||
@@ -3914,12 +3949,22 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
|
|
||||||
(arg->mode == NEW_IMAGE_MODE_EXISTING ||
|
|
||||||
!bdrv_has_zero_init(target_bs)));
|
|
||||||
|
|
||||||
+
|
|
||||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
|
||||||
+ old_context = bdrv_get_aio_context(target_bs);
|
|
||||||
+ aio_context_release(aio_context);
|
|
||||||
+ aio_context_acquire(old_context);
|
|
||||||
+
|
|
||||||
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
|
||||||
if (ret < 0) {
|
|
||||||
bdrv_unref(target_bs);
|
|
||||||
- goto out;
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
+ return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
+ aio_context_acquire(aio_context);
|
|
||||||
+
|
|
||||||
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
|
|
||||||
arg->has_replaces, arg->replaces, arg->sync,
|
|
||||||
backing_mode, zero_target,
|
|
||||||
@@ -3961,6 +4006,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
|
||||||
BlockDriverState *bs;
|
|
||||||
BlockDriverState *target_bs;
|
|
||||||
AioContext *aio_context;
|
|
||||||
+ AioContext *old_context;
|
|
||||||
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
|
|
||||||
Error *local_err = NULL;
|
|
||||||
bool zero_target;
|
|
||||||
@@ -3978,10 +4024,16 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
|
|
||||||
|
|
||||||
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
|
|
||||||
|
|
||||||
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
|
|
||||||
+ old_context = bdrv_get_aio_context(target_bs);
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
|
||||||
- aio_context_acquire(aio_context);
|
|
||||||
+ aio_context_acquire(old_context);
|
|
||||||
|
|
||||||
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
|
|
||||||
+
|
|
||||||
+ aio_context_release(old_context);
|
|
||||||
+ aio_context_acquire(aio_context);
|
|
||||||
+
|
|
||||||
if (ret < 0) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
From 6d89e4923e9c341975dbfdd2bae153ba367a1b79 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sergio Lopez <slp@redhat.com>
|
|
||||||
Date: Wed, 8 Jan 2020 15:31:33 +0100
|
|
||||||
Subject: [PATCH] blockdev: unify qmp_blockdev_backup and blockdev-backup
|
|
||||||
transaction paths
|
|
||||||
|
|
||||||
Issuing a blockdev-backup from qmp_blockdev_backup takes a slightly
|
|
||||||
different path than when it's issued from a transaction. In the code,
|
|
||||||
this is manifested as some redundancy between do_blockdev_backup() and
|
|
||||||
blockdev_backup_prepare().
|
|
||||||
|
|
||||||
This change unifies both paths, merging do_blockdev_backup() and
|
|
||||||
blockdev_backup_prepare(), and changing qmp_blockdev_backup() to
|
|
||||||
create a transaction instead of calling do_backup_common() direcly.
|
|
||||||
|
|
||||||
As a side-effect, now qmp_blockdev_backup() is executed inside a
|
|
||||||
drained section, as it happens when creating a blockdev-backup
|
|
||||||
transaction. This change is visible from the user's perspective, as
|
|
||||||
the job gets paused and immediately resumed before starting the actual
|
|
||||||
work.
|
|
||||||
|
|
||||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
||||||
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
blockdev.c | 60 ++++++++++++------------------------------------------
|
|
||||||
1 file changed, 13 insertions(+), 47 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 7016054688..d3309c205a 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -1983,16 +1983,13 @@ typedef struct BlockdevBackupState {
|
|
||||||
BlockJob *job;
|
|
||||||
} BlockdevBackupState;
|
|
||||||
|
|
||||||
-static BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
|
|
||||||
- Error **errp);
|
|
||||||
-
|
|
||||||
static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
{
|
|
||||||
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
|
|
||||||
BlockdevBackup *backup;
|
|
||||||
- BlockDriverState *bs, *target;
|
|
||||||
+ BlockDriverState *bs;
|
|
||||||
+ BlockDriverState *target_bs;
|
|
||||||
AioContext *aio_context;
|
|
||||||
- Error *local_err = NULL;
|
|
||||||
|
|
||||||
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
|
|
||||||
backup = common->action->u.blockdev_backup.data;
|
|
||||||
@@ -2002,8 +1999,8 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- target = bdrv_lookup_bs(backup->target, backup->target, errp);
|
|
||||||
- if (!target) {
|
|
||||||
+ target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
|
|
||||||
+ if (!target_bs) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2014,13 +2011,10 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
/* Paired with .clean() */
|
|
||||||
bdrv_drained_begin(state->bs);
|
|
||||||
|
|
||||||
- state->job = do_blockdev_backup(backup, common->block_job_txn, &local_err);
|
|
||||||
- if (local_err) {
|
|
||||||
- error_propagate(errp, local_err);
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
+ state->job = do_backup_common(qapi_BlockdevBackup_base(backup),
|
|
||||||
+ bs, target_bs, aio_context,
|
|
||||||
+ common->block_job_txn, errp);
|
|
||||||
|
|
||||||
-out:
|
|
||||||
aio_context_release(aio_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -3672,41 +3666,13 @@ XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp)
|
|
||||||
return bdrv_get_xdbg_block_graph(errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
-BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
|
|
||||||
- Error **errp)
|
|
||||||
+void qmp_blockdev_backup(BlockdevBackup *backup, Error **errp)
|
|
||||||
{
|
|
||||||
- BlockDriverState *bs;
|
|
||||||
- BlockDriverState *target_bs;
|
|
||||||
- AioContext *aio_context;
|
|
||||||
- BlockJob *job;
|
|
||||||
-
|
|
||||||
- bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
|
||||||
- if (!bs) {
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
|
|
||||||
- if (!target_bs) {
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- aio_context = bdrv_get_aio_context(bs);
|
|
||||||
- aio_context_acquire(aio_context);
|
|
||||||
-
|
|
||||||
- job = do_backup_common(qapi_BlockdevBackup_base(backup),
|
|
||||||
- bs, target_bs, aio_context, txn, errp);
|
|
||||||
-
|
|
||||||
- aio_context_release(aio_context);
|
|
||||||
- return job;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-void qmp_blockdev_backup(BlockdevBackup *arg, Error **errp)
|
|
||||||
-{
|
|
||||||
- BlockJob *job;
|
|
||||||
- job = do_blockdev_backup(arg, NULL, errp);
|
|
||||||
- if (job) {
|
|
||||||
- job_start(&job->job);
|
|
||||||
- }
|
|
||||||
+ TransactionAction action = {
|
|
||||||
+ .type = TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP,
|
|
||||||
+ .u.blockdev_backup.data = backup,
|
|
||||||
+ };
|
|
||||||
+ blockdev_do_action(&action, errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parameter check and block job starting for drive mirroring.
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,406 +0,0 @@
|
|||||||
From 952f7f53cdd4320d1a0328481fa578dd199eb1ce Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sergio Lopez <slp@redhat.com>
|
|
||||||
Date: Wed, 8 Jan 2020 15:31:32 +0100
|
|
||||||
Subject: [PATCH] blockdev: unify qmp_drive_backup and drive-backup transaction
|
|
||||||
paths
|
|
||||||
|
|
||||||
Issuing a drive-backup from qmp_drive_backup takes a slightly
|
|
||||||
different path than when it's issued from a transaction. In the code,
|
|
||||||
this is manifested as some redundancy between do_drive_backup() and
|
|
||||||
drive_backup_prepare().
|
|
||||||
|
|
||||||
This change unifies both paths, merging do_drive_backup() and
|
|
||||||
drive_backup_prepare(), and changing qmp_drive_backup() to create a
|
|
||||||
transaction instead of calling do_backup_common() direcly.
|
|
||||||
|
|
||||||
As a side-effect, now qmp_drive_backup() is executed inside a drained
|
|
||||||
section, as it happens when creating a drive-backup transaction. This
|
|
||||||
change is visible from the user's perspective, as the job gets paused
|
|
||||||
and immediately resumed before starting the actual work.
|
|
||||||
|
|
||||||
Also fix tests 141, 185 and 219 to cope with the extra
|
|
||||||
JOB_STATUS_CHANGE lines.
|
|
||||||
|
|
||||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
blockdev.c | 224 +++++++++++++++++--------------------
|
|
||||||
tests/qemu-iotests/141.out | 2 +
|
|
||||||
tests/qemu-iotests/185.out | 2 +
|
|
||||||
tests/qemu-iotests/219 | 7 +-
|
|
||||||
tests/qemu-iotests/219.out | 8 ++
|
|
||||||
5 files changed, 117 insertions(+), 126 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 99b1cafb8f..7016054688 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -1804,39 +1804,128 @@ typedef struct DriveBackupState {
|
|
||||||
BlockJob *job;
|
|
||||||
} DriveBackupState;
|
|
||||||
|
|
||||||
-static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
|
||||||
- Error **errp);
|
|
||||||
+static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
+ BlockDriverState *bs,
|
|
||||||
+ BlockDriverState *target_bs,
|
|
||||||
+ AioContext *aio_context,
|
|
||||||
+ JobTxn *txn, Error **errp);
|
|
||||||
|
|
||||||
static void drive_backup_prepare(BlkActionState *common, Error **errp)
|
|
||||||
{
|
|
||||||
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
|
|
||||||
- BlockDriverState *bs;
|
|
||||||
DriveBackup *backup;
|
|
||||||
+ BlockDriverState *bs;
|
|
||||||
+ BlockDriverState *target_bs;
|
|
||||||
+ BlockDriverState *source = NULL;
|
|
||||||
AioContext *aio_context;
|
|
||||||
+ QDict *options;
|
|
||||||
Error *local_err = NULL;
|
|
||||||
+ int flags;
|
|
||||||
+ int64_t size;
|
|
||||||
+ bool set_backing_hd = false;
|
|
||||||
|
|
||||||
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
|
|
||||||
backup = common->action->u.drive_backup.data;
|
|
||||||
|
|
||||||
+ if (!backup->has_mode) {
|
|
||||||
+ backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
|
||||||
if (!bs) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (!bs->drv) {
|
|
||||||
+ error_setg(errp, "Device has no medium");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
|
||||||
aio_context_acquire(aio_context);
|
|
||||||
|
|
||||||
/* Paired with .clean() */
|
|
||||||
bdrv_drained_begin(bs);
|
|
||||||
|
|
||||||
- state->bs = bs;
|
|
||||||
+ if (!backup->has_format) {
|
|
||||||
+ backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
|
|
||||||
+ NULL : (char *) bs->drv->format_name;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Early check to avoid creating target */
|
|
||||||
+ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ flags = bs->open_flags | BDRV_O_RDWR;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * See if we have a backing HD we can use to create our new image
|
|
||||||
+ * on top of.
|
|
||||||
+ */
|
|
||||||
+ if (backup->sync == MIRROR_SYNC_MODE_TOP) {
|
|
||||||
+ source = backing_bs(bs);
|
|
||||||
+ if (!source) {
|
|
||||||
+ backup->sync = MIRROR_SYNC_MODE_FULL;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ if (backup->sync == MIRROR_SYNC_MODE_NONE) {
|
|
||||||
+ source = bs;
|
|
||||||
+ flags |= BDRV_O_NO_BACKING;
|
|
||||||
+ set_backing_hd = true;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ size = bdrv_getlength(bs);
|
|
||||||
+ if (size < 0) {
|
|
||||||
+ error_setg_errno(errp, -size, "bdrv_getlength failed");
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
|
|
||||||
+ assert(backup->format);
|
|
||||||
+ if (source) {
|
|
||||||
+ bdrv_refresh_filename(source);
|
|
||||||
+ bdrv_img_create(backup->target, backup->format, source->filename,
|
|
||||||
+ source->drv->format_name, NULL,
|
|
||||||
+ size, flags, false, &local_err);
|
|
||||||
+ } else {
|
|
||||||
+ bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
|
|
||||||
+ size, flags, false, &local_err);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- state->job = do_drive_backup(backup, common->block_job_txn, &local_err);
|
|
||||||
if (local_err) {
|
|
||||||
error_propagate(errp, local_err);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ options = qdict_new();
|
|
||||||
+ qdict_put_str(options, "discard", "unmap");
|
|
||||||
+ qdict_put_str(options, "detect-zeroes", "unmap");
|
|
||||||
+ if (backup->format) {
|
|
||||||
+ qdict_put_str(options, "driver", backup->format);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
|
|
||||||
+ if (!target_bs) {
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (set_backing_hd) {
|
|
||||||
+ bdrv_set_backing_hd(target_bs, source, &local_err);
|
|
||||||
+ if (local_err) {
|
|
||||||
+ goto unref;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ state->bs = bs;
|
|
||||||
+
|
|
||||||
+ state->job = do_backup_common(qapi_DriveBackup_base(backup),
|
|
||||||
+ bs, target_bs, aio_context,
|
|
||||||
+ common->block_job_txn, errp);
|
|
||||||
+
|
|
||||||
+unref:
|
|
||||||
+ bdrv_unref(target_bs);
|
|
||||||
out:
|
|
||||||
aio_context_release(aio_context);
|
|
||||||
}
|
|
||||||
@@ -3564,126 +3653,13 @@ static BlockJob *do_backup_common(BackupCommon *backup,
|
|
||||||
return job;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
|
|
||||||
- Error **errp)
|
|
||||||
-{
|
|
||||||
- BlockDriverState *bs;
|
|
||||||
- BlockDriverState *target_bs;
|
|
||||||
- BlockDriverState *source = NULL;
|
|
||||||
- BlockJob *job = NULL;
|
|
||||||
- AioContext *aio_context;
|
|
||||||
- QDict *options;
|
|
||||||
- Error *local_err = NULL;
|
|
||||||
- int flags;
|
|
||||||
- int64_t size;
|
|
||||||
- bool set_backing_hd = false;
|
|
||||||
-
|
|
||||||
- if (!backup->has_mode) {
|
|
||||||
- backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- bs = bdrv_lookup_bs(backup->device, backup->device, errp);
|
|
||||||
- if (!bs) {
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (!bs->drv) {
|
|
||||||
- error_setg(errp, "Device has no medium");
|
|
||||||
- return NULL;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- aio_context = bdrv_get_aio_context(bs);
|
|
||||||
- aio_context_acquire(aio_context);
|
|
||||||
-
|
|
||||||
- if (!backup->has_format) {
|
|
||||||
- backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
|
|
||||||
- NULL : (char *) bs->drv->format_name;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* Early check to avoid creating target */
|
|
||||||
- if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- flags = bs->open_flags | BDRV_O_RDWR;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * See if we have a backing HD we can use to create our new image
|
|
||||||
- * on top of.
|
|
||||||
- */
|
|
||||||
- if (backup->sync == MIRROR_SYNC_MODE_TOP) {
|
|
||||||
- source = backing_bs(bs);
|
|
||||||
- if (!source) {
|
|
||||||
- backup->sync = MIRROR_SYNC_MODE_FULL;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
- if (backup->sync == MIRROR_SYNC_MODE_NONE) {
|
|
||||||
- source = bs;
|
|
||||||
- flags |= BDRV_O_NO_BACKING;
|
|
||||||
- set_backing_hd = true;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- size = bdrv_getlength(bs);
|
|
||||||
- if (size < 0) {
|
|
||||||
- error_setg_errno(errp, -size, "bdrv_getlength failed");
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
|
|
||||||
- assert(backup->format);
|
|
||||||
- if (source) {
|
|
||||||
- bdrv_refresh_filename(source);
|
|
||||||
- bdrv_img_create(backup->target, backup->format, source->filename,
|
|
||||||
- source->drv->format_name, NULL,
|
|
||||||
- size, flags, false, &local_err);
|
|
||||||
- } else {
|
|
||||||
- bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
|
|
||||||
- size, flags, false, &local_err);
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (local_err) {
|
|
||||||
- error_propagate(errp, local_err);
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- options = qdict_new();
|
|
||||||
- qdict_put_str(options, "discard", "unmap");
|
|
||||||
- qdict_put_str(options, "detect-zeroes", "unmap");
|
|
||||||
- if (backup->format) {
|
|
||||||
- qdict_put_str(options, "driver", backup->format);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
|
|
||||||
- if (!target_bs) {
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (set_backing_hd) {
|
|
||||||
- bdrv_set_backing_hd(target_bs, source, &local_err);
|
|
||||||
- if (local_err) {
|
|
||||||
- goto unref;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- job = do_backup_common(qapi_DriveBackup_base(backup),
|
|
||||||
- bs, target_bs, aio_context, txn, errp);
|
|
||||||
-
|
|
||||||
-unref:
|
|
||||||
- bdrv_unref(target_bs);
|
|
||||||
-out:
|
|
||||||
- aio_context_release(aio_context);
|
|
||||||
- return job;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-void qmp_drive_backup(DriveBackup *arg, Error **errp)
|
|
||||||
+void qmp_drive_backup(DriveBackup *backup, Error **errp)
|
|
||||||
{
|
|
||||||
-
|
|
||||||
- BlockJob *job;
|
|
||||||
- job = do_drive_backup(arg, NULL, errp);
|
|
||||||
- if (job) {
|
|
||||||
- job_start(&job->job);
|
|
||||||
- }
|
|
||||||
+ TransactionAction action = {
|
|
||||||
+ .type = TRANSACTION_ACTION_KIND_DRIVE_BACKUP,
|
|
||||||
+ .u.drive_backup.data = backup,
|
|
||||||
+ };
|
|
||||||
+ blockdev_do_action(&action, errp);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
|
|
||||||
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
|
|
||||||
index 4d71d9dcae..07e0ec66d7 100644
|
|
||||||
--- a/tests/qemu-iotests/141.out
|
|
||||||
+++ b/tests/qemu-iotests/141.out
|
|
||||||
@@ -10,6 +10,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
|
|
||||||
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
|
||||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
|
|
||||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
|
|
||||||
{"return": {}}
|
|
||||||
{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
|
|
||||||
{"return": {}}
|
|
||||||
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
|
|
||||||
index ddfbf3c765..a233be7f58 100644
|
|
||||||
--- a/tests/qemu-iotests/185.out
|
|
||||||
+++ b/tests/qemu-iotests/185.out
|
|
||||||
@@ -51,6 +51,8 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l
|
|
||||||
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
|
||||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
|
|
||||||
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
|
|
||||||
{"return": {}}
|
|
||||||
{"return": {}}
|
|
||||||
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
|
|
||||||
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
|
|
||||||
index e0c51662c0..655f54d881 100755
|
|
||||||
--- a/tests/qemu-iotests/219
|
|
||||||
+++ b/tests/qemu-iotests/219
|
|
||||||
@@ -63,7 +63,7 @@ def test_pause_resume(vm):
|
|
||||||
# logged immediately
|
|
||||||
iotests.log(vm.qmp('query-jobs'))
|
|
||||||
|
|
||||||
-def test_job_lifecycle(vm, job, job_args, has_ready=False):
|
|
||||||
+def test_job_lifecycle(vm, job, job_args, has_ready=False, is_mirror=False):
|
|
||||||
global img_size
|
|
||||||
|
|
||||||
iotests.log('')
|
|
||||||
@@ -135,6 +135,9 @@ def test_job_lifecycle(vm, job, job_args, has_ready=False):
|
|
||||||
iotests.log('Waiting for PENDING state...')
|
|
||||||
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
|
||||||
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
|
||||||
+ if is_mirror:
|
|
||||||
+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
|
||||||
+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
|
|
||||||
|
|
||||||
if not job_args.get('auto-finalize', True):
|
|
||||||
# PENDING state:
|
|
||||||
@@ -218,7 +221,7 @@ with iotests.FilePath('disk.img') as disk_path, \
|
|
||||||
|
|
||||||
for auto_finalize in [True, False]:
|
|
||||||
for auto_dismiss in [True, False]:
|
|
||||||
- test_job_lifecycle(vm, 'drive-backup', job_args={
|
|
||||||
+ test_job_lifecycle(vm, 'drive-backup', is_mirror=True, job_args={
|
|
||||||
'device': 'drive0-node',
|
|
||||||
'target': copy_path,
|
|
||||||
'sync': 'full',
|
|
||||||
diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out
|
|
||||||
index 8ebd3fee60..0ea5d0b9d5 100644
|
|
||||||
--- a/tests/qemu-iotests/219.out
|
|
||||||
+++ b/tests/qemu-iotests/219.out
|
|
||||||
@@ -135,6 +135,8 @@ Pause/resume in RUNNING
|
|
||||||
{"return": {}}
|
|
||||||
|
|
||||||
Waiting for PENDING state...
|
|
||||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
@@ -186,6 +188,8 @@ Pause/resume in RUNNING
|
|
||||||
{"return": {}}
|
|
||||||
|
|
||||||
Waiting for PENDING state...
|
|
||||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
@@ -245,6 +249,8 @@ Pause/resume in RUNNING
|
|
||||||
{"return": {}}
|
|
||||||
|
|
||||||
Waiting for PENDING state...
|
|
||||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]}
|
|
||||||
@@ -304,6 +310,8 @@ Pause/resume in RUNNING
|
|
||||||
{"return": {}}
|
|
||||||
|
|
||||||
Waiting for PENDING state...
|
|
||||||
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
|
||||||
{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,114 +0,0 @@
|
|||||||
From e37cda3452309d147f1f7aec3c74249001e3db0c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Michael Qiu <qiudayu@huayun.com>
|
|
||||||
Date: Wed, 12 May 2021 21:54:37 +0800
|
|
||||||
Subject: [PATCH] blockjob: Fix crash with IOthread when block commit after
|
|
||||||
snapshot
|
|
||||||
|
|
||||||
Currently, if guest has workloads, IO thread will acquire aio_context
|
|
||||||
lock before do io_submit, it leads to segmentfault when do block commit
|
|
||||||
after snapshot. Just like below:
|
|
||||||
|
|
||||||
Program received signal SIGSEGV, Segmentation fault.
|
|
||||||
|
|
||||||
[Switching to Thread 0x7f7c7d91f700 (LWP 99907)]
|
|
||||||
0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437
|
|
||||||
1437 ../block/mirror.c: No such file or directory.
|
|
||||||
(gdb) p s->job
|
|
||||||
$17 = (MirrorBlockJob *) 0x0
|
|
||||||
(gdb) p s->stop
|
|
||||||
$18 = false
|
|
||||||
|
|
||||||
Call trace of IO thread:
|
|
||||||
0 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437
|
|
||||||
1 0x00005576d0f7f3ab in bdrv_driver_pwritev at ../block/io.c:1174
|
|
||||||
2 0x00005576d0f8139d in bdrv_aligned_pwritev at ../block/io.c:1988
|
|
||||||
3 0x00005576d0f81b65 in bdrv_co_pwritev_part at ../block/io.c:2156
|
|
||||||
4 0x00005576d0f8e6b7 in blk_do_pwritev_part at ../block/block-backend.c:1260
|
|
||||||
5 0x00005576d0f8e84d in blk_aio_write_entry at ../block/block-backend.c:1476
|
|
||||||
...
|
|
||||||
|
|
||||||
Switch to qemu main thread:
|
|
||||||
0 0x00007f903be704ed in __lll_lock_wait at
|
|
||||||
/lib/../lib64/libpthread.so.0
|
|
||||||
1 0x00007f903be6bde6 in _L_lock_941 at /lib/../lib64/libpthread.so.0
|
|
||||||
2 0x00007f903be6bcdf in pthread_mutex_lock at
|
|
||||||
/lib/../lib64/libpthread.so.0
|
|
||||||
3 0x0000564b21456889 in qemu_mutex_lock_impl at
|
|
||||||
../util/qemu-thread-posix.c:79
|
|
||||||
4 0x0000564b213af8a5 in block_job_add_bdrv at ../blockjob.c:224
|
|
||||||
5 0x0000564b213b00ad in block_job_create at ../blockjob.c:440
|
|
||||||
6 0x0000564b21357c0a in mirror_start_job at ../block/mirror.c:1622
|
|
||||||
7 0x0000564b2135a9af in commit_active_start at ../block/mirror.c:1867
|
|
||||||
8 0x0000564b2133d132 in qmp_block_commit at ../blockdev.c:2768
|
|
||||||
9 0x0000564b2141fef3 in qmp_marshal_block_commit at
|
|
||||||
qapi/qapi-commands-block-core.c:346
|
|
||||||
10 0x0000564b214503c9 in do_qmp_dispatch_bh at
|
|
||||||
../qapi/qmp-dispatch.c:110
|
|
||||||
11 0x0000564b21451996 in aio_bh_poll at ../util/async.c:164
|
|
||||||
12 0x0000564b2146018e in aio_dispatch at ../util/aio-posix.c:381
|
|
||||||
13 0x0000564b2145187e in aio_ctx_dispatch at ../util/async.c:306
|
|
||||||
14 0x00007f9040239049 in g_main_context_dispatch at
|
|
||||||
/lib/../lib64/libglib-2.0.so.0
|
|
||||||
15 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:232
|
|
||||||
16 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:255
|
|
||||||
17 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:531
|
|
||||||
18 0x0000564b212304e1 in qemu_main_loop at ../softmmu/runstate.c:721
|
|
||||||
19 0x0000564b20f7975e in main at ../softmmu/main.c:50
|
|
||||||
|
|
||||||
In IO thread when do bdrv_mirror_top_pwritev, the job is NULL, and stop field
|
|
||||||
is false, this means the MirrorBDSOpaque "s" object has not been initialized
|
|
||||||
yet, and this object is initialized by block_job_create(), but the initialize
|
|
||||||
process is stuck in acquiring the lock.
|
|
||||||
|
|
||||||
In this situation, IO thread come to bdrv_mirror_top_pwritev(),which means that
|
|
||||||
mirror-top node is already inserted into block graph, but its bs->opaque->job
|
|
||||||
is not initialized.
|
|
||||||
|
|
||||||
The root cause is that qemu main thread do release/acquire when hold the lock,
|
|
||||||
at the same time, IO thread get the lock after release stage, and the crash
|
|
||||||
occured.
|
|
||||||
|
|
||||||
Actually, in this situation, job->job.aio_context will not equal to
|
|
||||||
qemu_get_aio_context(), and will be the same as bs->aio_context,
|
|
||||||
thus, no need to release the lock, becasue bdrv_root_attach_child()
|
|
||||||
will not change the context.
|
|
||||||
|
|
||||||
This patch fix this issue.
|
|
||||||
|
|
||||||
Fixes: 132ada80 "block: Adjust AioContexts when attaching nodes"
|
|
||||||
|
|
||||||
Signed-off-by: Michael Qiu <qiudayu@huayun.com>
|
|
||||||
Message-Id: <20210203024059.52683-1-08005325@163.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
blockjob.c | 8 ++++++--
|
|
||||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/blockjob.c b/blockjob.c
|
|
||||||
index 74abb97bfd..72865a4a6e 100644
|
|
||||||
--- a/blockjob.c
|
|
||||||
+++ b/blockjob.c
|
|
||||||
@@ -223,14 +223,18 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
|
||||||
uint64_t perm, uint64_t shared_perm, Error **errp)
|
|
||||||
{
|
|
||||||
BdrvChild *c;
|
|
||||||
+ bool need_context_ops;
|
|
||||||
|
|
||||||
bdrv_ref(bs);
|
|
||||||
- if (job->job.aio_context != qemu_get_aio_context()) {
|
|
||||||
+
|
|
||||||
+ need_context_ops = bdrv_get_aio_context(bs) != job->job.aio_context;
|
|
||||||
+
|
|
||||||
+ if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) {
|
|
||||||
aio_context_release(job->job.aio_context);
|
|
||||||
}
|
|
||||||
c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context,
|
|
||||||
perm, shared_perm, job, errp);
|
|
||||||
- if (job->job.aio_context != qemu_get_aio_context()) {
|
|
||||||
+ if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) {
|
|
||||||
aio_context_acquire(job->job.aio_context);
|
|
||||||
}
|
|
||||||
if (c == NULL) {
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
From 86b0f4022bb43b16979ba5300e8d40a1e6d44b79 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Sergio Lopez <slp@redhat.com>
|
|
||||||
Date: Wed, 11 Sep 2019 12:03:16 +0200
|
|
||||||
Subject: [PATCH] blockjob: update nodes head while removing all bdrv
|
|
||||||
|
|
||||||
block_job_remove_all_bdrv() iterates through job->nodes, calling
|
|
||||||
bdrv_root_unref_child() for each entry. The call to the latter may
|
|
||||||
reach child_job_[can_]set_aio_ctx(), which will also attempt to
|
|
||||||
traverse job->nodes, potentially finding entries that where freed
|
|
||||||
on previous iterations.
|
|
||||||
|
|
||||||
To avoid this situation, update job->nodes head on each iteration to
|
|
||||||
ensure that already freed entries are no longer linked to the list.
|
|
||||||
|
|
||||||
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631
|
|
||||||
Signed-off-by: Sergio Lopez <slp@redhat.com>
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
Message-id: 20190911100316.32282-1-mreitz@redhat.com
|
|
||||||
Reviewed-by: Sergio Lopez <slp@redhat.com>
|
|
||||||
Signed-off-by: Max Reitz <mreitz@redhat.com>
|
|
||||||
(cherry picked from commit d876bf676f5e7c6aa9ac64555e48cba8734ecb2f)
|
|
||||||
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
||||||
---
|
|
||||||
blockjob.c | 17 +++++++++++++----
|
|
||||||
1 file changed, 13 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/blockjob.c b/blockjob.c
|
|
||||||
index 20b7f557da..74abb97bfd 100644
|
|
||||||
--- a/blockjob.c
|
|
||||||
+++ b/blockjob.c
|
|
||||||
@@ -186,14 +186,23 @@ static const BdrvChildRole child_job = {
|
|
||||||
|
|
||||||
void block_job_remove_all_bdrv(BlockJob *job)
|
|
||||||
{
|
|
||||||
- GSList *l;
|
|
||||||
- for (l = job->nodes; l; l = l->next) {
|
|
||||||
+ /*
|
|
||||||
+ * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(),
|
|
||||||
+ * which will also traverse job->nodes, so consume the list one by
|
|
||||||
+ * one to make sure that such a concurrent access does not attempt
|
|
||||||
+ * to process an already freed BdrvChild.
|
|
||||||
+ */
|
|
||||||
+ while (job->nodes) {
|
|
||||||
+ GSList *l = job->nodes;
|
|
||||||
BdrvChild *c = l->data;
|
|
||||||
+
|
|
||||||
+ job->nodes = l->next;
|
|
||||||
+
|
|
||||||
bdrv_op_unblock_all(c->bs, job->blocker);
|
|
||||||
bdrv_root_unref_child(c);
|
|
||||||
+
|
|
||||||
+ g_slist_free_1(l);
|
|
||||||
}
|
|
||||||
- g_slist_free(job->nodes);
|
|
||||||
- job->nodes = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs)
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
From ab454ca5f45a842b2517a0f4eb786b6ea3019d5a Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
|
||||||
Date: Fri, 4 Jun 2021 16:15:14 +0400
|
|
||||||
Subject: [PATCH 3/6] bootp: check bootp_input buffer size
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
Fixes: CVE-2021-3592
|
|
||||||
Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44
|
|
||||||
|
|
||||||
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
|
||||||
Signed-off-by: imxcc <xingchaochao@huawei.com>
|
|
||||||
---
|
|
||||||
slirp/src/bootp.c | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/slirp/src/bootp.c b/slirp/src/bootp.c
|
|
||||||
index 57543271..57891871 100644
|
|
||||||
--- a/slirp/src/bootp.c
|
|
||||||
+++ b/slirp/src/bootp.c
|
|
||||||
@@ -366,9 +366,9 @@ udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
|
||||||
|
|
||||||
void bootp_input(struct mbuf *m)
|
|
||||||
{
|
|
||||||
- struct bootp_t *bp = mtod(m, struct bootp_t *);
|
|
||||||
+ struct bootp_t *bp = mtod_check(m, sizeof(struct bootp_t));
|
|
||||||
|
|
||||||
- if (bp->bp_op == BOOTP_REQUEST) {
|
|
||||||
+ if (bp && bp->bp_op == BOOTP_REQUEST) {
|
|
||||||
bootp_reply(m->slirp, bp, m_end(m));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,161 +0,0 @@
|
|||||||
From 3369988416bd98e97dc3d0400af165c0d9e536e0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
|
||||||
Date: Fri, 4 Jun 2021 19:25:28 +0400
|
|
||||||
Subject: [PATCH 2/6] bootp: limit vendor-specific area to input packet memory
|
|
||||||
buffer
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
sizeof(bootp_t) currently holds DHCP_OPT_LEN. Remove this optional field
|
|
||||||
from the structure, to help with the following patch checking for
|
|
||||||
minimal header size. Modify the bootp_reply() function to take the
|
|
||||||
buffer boundaries and avoiding potential buffer overflow.
|
|
||||||
|
|
||||||
Related to CVE-2021-3592.
|
|
||||||
|
|
||||||
https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44
|
|
||||||
|
|
||||||
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
|
||||||
Signed-off-by: imxcc <xingchaochao@huawei.com>
|
|
||||||
---
|
|
||||||
slirp/src/bootp.c | 26 +++++++++++++++-----------
|
|
||||||
slirp/src/bootp.h | 2 +-
|
|
||||||
slirp/src/mbuf.c | 5 +++++
|
|
||||||
slirp/src/mbuf.h | 1 +
|
|
||||||
4 files changed, 22 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/slirp/src/bootp.c b/slirp/src/bootp.c
|
|
||||||
index 3f9ce255..57543271 100644
|
|
||||||
--- a/slirp/src/bootp.c
|
|
||||||
+++ b/slirp/src/bootp.c
|
|
||||||
@@ -92,21 +92,22 @@ found:
|
|
||||||
return bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
|
||||||
+static void dhcp_decode(const struct bootp_t *bp,
|
|
||||||
+ const uint8_t *bp_end,
|
|
||||||
+ int *pmsg_type,
|
|
||||||
struct in_addr *preq_addr)
|
|
||||||
{
|
|
||||||
- const uint8_t *p, *p_end;
|
|
||||||
+ const uint8_t *p;
|
|
||||||
int len, tag;
|
|
||||||
|
|
||||||
*pmsg_type = 0;
|
|
||||||
preq_addr->s_addr = htonl(0L);
|
|
||||||
|
|
||||||
p = bp->bp_vend;
|
|
||||||
- p_end = p + DHCP_OPT_LEN;
|
|
||||||
if (memcmp(p, rfc1533_cookie, 4) != 0)
|
|
||||||
return;
|
|
||||||
p += 4;
|
|
||||||
- while (p < p_end) {
|
|
||||||
+ while (p < bp_end) {
|
|
||||||
tag = p[0];
|
|
||||||
if (tag == RFC1533_PAD) {
|
|
||||||
p++;
|
|
||||||
@@ -114,10 +115,10 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
p++;
|
|
||||||
- if (p >= p_end)
|
|
||||||
+ if (p >= bp_end)
|
|
||||||
break;
|
|
||||||
len = *p++;
|
|
||||||
- if (p + len > p_end) {
|
|
||||||
+ if (p + len > bp_end) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
DPRINTF("dhcp: tag=%d len=%d\n", tag, len);
|
|
||||||
@@ -144,7 +145,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
|
||||||
+static void bootp_reply(Slirp *slirp,
|
|
||||||
+ const struct bootp_t *bp,
|
|
||||||
+ const uint8_t *bp_end)
|
|
||||||
{
|
|
||||||
BOOTPClient *bc = NULL;
|
|
||||||
struct mbuf *m;
|
|
||||||
@@ -157,7 +160,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
|
||||||
uint8_t client_ethaddr[ETH_ALEN];
|
|
||||||
|
|
||||||
/* extract exact DHCP msg type */
|
|
||||||
- dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
|
|
||||||
+ dhcp_decode(bp, bp_end, &dhcp_msg_type, &preq_addr);
|
|
||||||
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
|
|
||||||
if (preq_addr.s_addr != htonl(0L))
|
|
||||||
DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
|
|
||||||
@@ -179,9 +182,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m->m_data += IF_MAXLINKHDR;
|
|
||||||
+ m_inc(m, sizeof(struct bootp_t) + DHCP_OPT_LEN);
|
|
||||||
rbp = (struct bootp_t *)m->m_data;
|
|
||||||
m->m_data += sizeof(struct udpiphdr);
|
|
||||||
- memset(rbp, 0, sizeof(struct bootp_t));
|
|
||||||
+ memset(rbp, 0, sizeof(struct bootp_t) + DHCP_OPT_LEN);
|
|
||||||
|
|
||||||
if (dhcp_msg_type == DHCPDISCOVER) {
|
|
||||||
if (preq_addr.s_addr != htonl(0L)) {
|
|
||||||
@@ -235,7 +239,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
|
||||||
rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
|
|
||||||
|
|
||||||
q = rbp->bp_vend;
|
|
||||||
- end = (uint8_t *)&rbp[1];
|
|
||||||
+ end = rbp->bp_vend + DHCP_OPT_LEN;
|
|
||||||
memcpy(q, rfc1533_cookie, 4);
|
|
||||||
q += 4;
|
|
||||||
|
|
||||||
@@ -365,6 +369,6 @@ void bootp_input(struct mbuf *m)
|
|
||||||
struct bootp_t *bp = mtod(m, struct bootp_t *);
|
|
||||||
|
|
||||||
if (bp->bp_op == BOOTP_REQUEST) {
|
|
||||||
- bootp_reply(m->slirp, bp);
|
|
||||||
+ bootp_reply(m->slirp, bp, m_end(m));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/slirp/src/bootp.h b/slirp/src/bootp.h
|
|
||||||
index 03ece9bf..0d20a944 100644
|
|
||||||
--- a/slirp/src/bootp.h
|
|
||||||
+++ b/slirp/src/bootp.h
|
|
||||||
@@ -114,7 +114,7 @@ struct bootp_t {
|
|
||||||
uint8_t bp_hwaddr[16];
|
|
||||||
uint8_t bp_sname[64];
|
|
||||||
uint8_t bp_file[128];
|
|
||||||
- uint8_t bp_vend[DHCP_OPT_LEN];
|
|
||||||
+ uint8_t bp_vend[];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
diff --git a/slirp/src/mbuf.c b/slirp/src/mbuf.c
|
|
||||||
index 6d0653ed..7db07c08 100644
|
|
||||||
--- a/slirp/src/mbuf.c
|
|
||||||
+++ b/slirp/src/mbuf.c
|
|
||||||
@@ -233,3 +233,8 @@ void *mtod_check(struct mbuf *m, size_t len)
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+void *m_end(struct mbuf *m)
|
|
||||||
+{
|
|
||||||
+ return m->m_data + m->m_len;
|
|
||||||
+}
|
|
||||||
diff --git a/slirp/src/mbuf.h b/slirp/src/mbuf.h
|
|
||||||
index 2015e323..a9752a36 100644
|
|
||||||
--- a/slirp/src/mbuf.h
|
|
||||||
+++ b/slirp/src/mbuf.h
|
|
||||||
@@ -119,6 +119,7 @@ void m_adj(struct mbuf *, int);
|
|
||||||
int m_copy(struct mbuf *, struct mbuf *, int, int);
|
|
||||||
struct mbuf *dtom(Slirp *, void *);
|
|
||||||
void *mtod_check(struct mbuf *, size_t len);
|
|
||||||
+void *m_end(struct mbuf *);
|
|
||||||
|
|
||||||
static inline void ifs_init(struct mbuf *ifm)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
@ -1,794 +0,0 @@
|
|||||||
From f9ab92373813cfccd31f29c0d963232f65cb5f88 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
|
||||||
Date: Fri, 22 May 2020 12:22:26 +0800
|
|
||||||
Subject: [PATCH] bt: use size_t type for length parameters instead of int
|
|
||||||
|
|
||||||
From: Prasad J Pandit <pjp@fedoraproject.org>
|
|
||||||
|
|
||||||
The length parameter values are not negative, thus use an unsigned
|
|
||||||
type 'size_t' for them. Many routines pass 'len' values to memcpy(3)
|
|
||||||
calls. If it was negative, it could lead to memory corruption issues.
|
|
||||||
Add check to avoid it.
|
|
||||||
|
|
||||||
Reported-by: Arash TC <tohidi.arash@gmail.com>
|
|
||||||
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
|
|
||||||
|
|
||||||
diff --git a/bt-host.c b/bt-host.c
|
|
||||||
index 2f8f631..b73a44d 100644
|
|
||||||
--- a/bt-host.c
|
|
||||||
+++ b/bt-host.c
|
|
||||||
@@ -43,7 +43,7 @@ struct bt_host_hci_s {
|
|
||||||
};
|
|
||||||
|
|
||||||
static void bt_host_send(struct HCIInfo *hci,
|
|
||||||
- int type, const uint8_t *data, int len)
|
|
||||||
+ int type, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct bt_host_hci_s *s = (struct bt_host_hci_s *) hci;
|
|
||||||
uint8_t pkt = type;
|
|
||||||
@@ -63,17 +63,17 @@ static void bt_host_send(struct HCIInfo *hci,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, int len)
|
|
||||||
+static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
bt_host_send(hci, HCI_COMMAND_PKT, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, int len)
|
|
||||||
+static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
bt_host_send(hci, HCI_ACLDATA_PKT, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, int len)
|
|
||||||
+static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
bt_host_send(hci, HCI_SCODATA_PKT, data, len);
|
|
||||||
}
|
|
||||||
diff --git a/bt-vhci.c b/bt-vhci.c
|
|
||||||
index 886e146..32ef1c5 100644
|
|
||||||
--- a/bt-vhci.c
|
|
||||||
+++ b/bt-vhci.c
|
|
||||||
@@ -89,7 +89,7 @@ static void vhci_read(void *opaque)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vhci_host_send(void *opaque,
|
|
||||||
- int type, const uint8_t *data, int len)
|
|
||||||
+ int type, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct bt_vhci_s *s = (struct bt_vhci_s *) opaque;
|
|
||||||
#if 0
|
|
||||||
@@ -112,6 +112,7 @@ static void vhci_host_send(void *opaque,
|
|
||||||
static uint8_t buf[4096];
|
|
||||||
|
|
||||||
buf[0] = type;
|
|
||||||
+ assert(len < sizeof(buf));
|
|
||||||
memcpy(buf + 1, data, len);
|
|
||||||
|
|
||||||
while (write(s->fd, buf, len + 1) < 0)
|
|
||||||
@@ -124,13 +125,13 @@ static void vhci_host_send(void *opaque,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vhci_out_hci_packet_event(void *opaque,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
vhci_host_send(opaque, HCI_EVENT_PKT, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vhci_out_hci_packet_acl(void *opaque,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
vhci_host_send(opaque, HCI_ACLDATA_PKT, data, len);
|
|
||||||
}
|
|
||||||
diff --git a/hw/bt/core.c b/hw/bt/core.c
|
|
||||||
index dfb196e..f548b3d 100644
|
|
||||||
--- a/hw/bt/core.c
|
|
||||||
+++ b/hw/bt/core.c
|
|
||||||
@@ -44,7 +44,7 @@ static void bt_dummy_lmp_disconnect_master(struct bt_link_s *link)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_dummy_lmp_acl_resp(struct bt_link_s *link,
|
|
||||||
- const uint8_t *data, int start, int len)
|
|
||||||
+ const uint8_t *data, int start, size_t len)
|
|
||||||
{
|
|
||||||
error_report("%s: stray ACL response PDU, fixme", __func__);
|
|
||||||
exit(-1);
|
|
||||||
diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c
|
|
||||||
index 3d60654..f7a74c0 100644
|
|
||||||
--- a/hw/bt/hci-csr.c
|
|
||||||
+++ b/hw/bt/hci-csr.c
|
|
||||||
@@ -103,7 +103,7 @@ static inline void csrhci_fifo_wake(struct csrhci_s *s)
|
|
||||||
}
|
|
||||||
|
|
||||||
#define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len)
|
|
||||||
-static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
|
|
||||||
+static uint8_t *csrhci_out_packet(struct csrhci_s *s, size_t len)
|
|
||||||
{
|
|
||||||
int off = s->out_start + s->out_len;
|
|
||||||
|
|
||||||
@@ -112,14 +112,14 @@ static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
|
|
||||||
|
|
||||||
if (off < FIFO_LEN) {
|
|
||||||
if (off + len > FIFO_LEN && (s->out_size = off + len) > FIFO_LEN * 2) {
|
|
||||||
- error_report("%s: can't alloc %i bytes", __func__, len);
|
|
||||||
+ error_report("%s: can't alloc %zu bytes", __func__, len);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
return s->outfifo + off;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->out_len > s->out_size) {
|
|
||||||
- error_report("%s: can't alloc %i bytes", __func__, len);
|
|
||||||
+ error_report("%s: can't alloc %zu bytes", __func__, len);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s,
|
|
||||||
- int type, int len)
|
|
||||||
+ int type, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *ret = csrhci_out_packetz(s, len + 2);
|
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s,
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s,
|
|
||||||
- int evt, int len)
|
|
||||||
+ int evt, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *ret = csrhci_out_packetz(s,
|
|
||||||
len + 1 + sizeof(struct hci_event_hdr));
|
|
||||||
@@ -151,7 +151,7 @@ static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void csrhci_in_packet_vendor(struct csrhci_s *s, int ocf,
|
|
||||||
- uint8_t *data, int len)
|
|
||||||
+ uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
int offset;
|
|
||||||
uint8_t *rpkt;
|
|
||||||
@@ -320,18 +320,18 @@ static int csrhci_write(struct Chardev *chr,
|
|
||||||
struct csrhci_s *s = (struct csrhci_s *)chr;
|
|
||||||
int total = 0;
|
|
||||||
|
|
||||||
- if (!s->enable)
|
|
||||||
+ if (!s->enable || len <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
int cnt = MIN(len, s->in_needed - s->in_len);
|
|
||||||
- if (cnt) {
|
|
||||||
- memcpy(s->inpkt + s->in_len, buf, cnt);
|
|
||||||
- s->in_len += cnt;
|
|
||||||
- buf += cnt;
|
|
||||||
- len -= cnt;
|
|
||||||
- total += cnt;
|
|
||||||
- }
|
|
||||||
+ assert(cnt > 0);
|
|
||||||
+
|
|
||||||
+ memcpy(s->inpkt + s->in_len, buf, cnt);
|
|
||||||
+ s->in_len += cnt;
|
|
||||||
+ buf += cnt;
|
|
||||||
+ len -= cnt;
|
|
||||||
+ total += cnt;
|
|
||||||
|
|
||||||
if (s->in_len < s->in_needed) {
|
|
||||||
break;
|
|
||||||
@@ -363,7 +363,7 @@ static int csrhci_write(struct Chardev *chr,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void csrhci_out_hci_packet_event(void *opaque,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct csrhci_s *s = (struct csrhci_s *) opaque;
|
|
||||||
uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1); /* Align */
|
|
||||||
@@ -375,7 +375,7 @@ static void csrhci_out_hci_packet_event(void *opaque,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void csrhci_out_hci_packet_acl(void *opaque,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct csrhci_s *s = (struct csrhci_s *) opaque;
|
|
||||||
uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1); /* Align */
|
|
||||||
diff --git a/hw/bt/hci.c b/hw/bt/hci.c
|
|
||||||
index c7958f6..9c4f957 100644
|
|
||||||
--- a/hw/bt/hci.c
|
|
||||||
+++ b/hw/bt/hci.c
|
|
||||||
@@ -31,7 +31,7 @@
|
|
||||||
|
|
||||||
struct bt_hci_s {
|
|
||||||
uint8_t *(*evt_packet)(void *opaque);
|
|
||||||
- void (*evt_submit)(void *opaque, int len);
|
|
||||||
+ void (*evt_submit)(void *opaque, size_t len);
|
|
||||||
void *opaque;
|
|
||||||
uint8_t evt_buf[256];
|
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ struct bt_hci_s {
|
|
||||||
struct bt_hci_master_link_s {
|
|
||||||
struct bt_link_s *link;
|
|
||||||
void (*lmp_acl_data)(struct bt_link_s *link,
|
|
||||||
- const uint8_t *data, int start, int len);
|
|
||||||
+ const uint8_t *data, int start, size_t len);
|
|
||||||
QEMUTimer *acl_mode_timer;
|
|
||||||
} handle[HCI_HANDLES_MAX];
|
|
||||||
uint32_t role_bmp;
|
|
||||||
@@ -433,7 +433,7 @@ static const uint8_t bt_event_reserved_mask[8] = {
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
-static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
|
|
||||||
+static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -451,13 +451,13 @@ struct HCIInfo null_hci = {
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
|
|
||||||
- int evt, int len)
|
|
||||||
+ int evt, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *packet, mask;
|
|
||||||
int mask_byte;
|
|
||||||
|
|
||||||
if (len > 255) {
|
|
||||||
- error_report("%s: HCI event params too long (%ib)", __func__, len);
|
|
||||||
+ error_report("%s: HCI event params too long (%zub)", __func__, len);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -474,7 +474,7 @@ static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bt_hci_event(struct bt_hci_s *hci, int evt,
|
|
||||||
- void *params, int len)
|
|
||||||
+ void *params, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *packet = bt_hci_event_start(hci, evt, len);
|
|
||||||
|
|
||||||
@@ -499,7 +499,7 @@ static inline void bt_hci_event_status(struct bt_hci_s *hci, int status)
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bt_hci_event_complete(struct bt_hci_s *hci,
|
|
||||||
- void *ret, int len)
|
|
||||||
+ void *ret, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *packet = bt_hci_event_start(hci, EVT_CMD_COMPLETE,
|
|
||||||
len + EVT_CMD_COMPLETE_SIZE);
|
|
||||||
@@ -1476,7 +1476,7 @@ static inline void bt_hci_event_num_comp_pkts(struct bt_hci_s *hci,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_submit_hci(struct HCIInfo *info,
|
|
||||||
- const uint8_t *data, int length)
|
|
||||||
+ const uint8_t *data, size_t length)
|
|
||||||
{
|
|
||||||
struct bt_hci_s *hci = hci_from_info(info);
|
|
||||||
uint16_t cmd;
|
|
||||||
@@ -1970,7 +1970,7 @@ static void bt_submit_hci(struct HCIInfo *info,
|
|
||||||
break;
|
|
||||||
|
|
||||||
short_hci:
|
|
||||||
- error_report("%s: HCI packet too short (%iB)", __func__, length);
|
|
||||||
+ error_report("%s: HCI packet too short (%zuB)", __func__, length);
|
|
||||||
bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
@@ -1981,7 +1981,7 @@ static void bt_submit_hci(struct HCIInfo *info,
|
|
||||||
* know that a packet contained the last fragment of the SDU when the next
|
|
||||||
* SDU starts. */
|
|
||||||
static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
|
|
||||||
- const uint8_t *data, int start, int len)
|
|
||||||
+ const uint8_t *data, int start, size_t len)
|
|
||||||
{
|
|
||||||
struct hci_acl_hdr *pkt = (void *) hci->acl_buf;
|
|
||||||
|
|
||||||
@@ -1989,7 +1989,7 @@ static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
|
|
||||||
/* TODO: avoid memcpy'ing */
|
|
||||||
|
|
||||||
if (len + HCI_ACL_HDR_SIZE > sizeof(hci->acl_buf)) {
|
|
||||||
- error_report("%s: can't take ACL packets %i bytes long",
|
|
||||||
+ error_report("%s: can't take ACL packets %zu bytes long",
|
|
||||||
__func__, len);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -2003,7 +2003,7 @@ static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink,
|
|
||||||
- const uint8_t *data, int start, int len)
|
|
||||||
+ const uint8_t *data, int start, size_t len)
|
|
||||||
{
|
|
||||||
struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
|
|
||||||
|
|
||||||
@@ -2012,14 +2012,14 @@ static void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_hci_lmp_acl_data_host(struct bt_link_s *link,
|
|
||||||
- const uint8_t *data, int start, int len)
|
|
||||||
+ const uint8_t *data, int start, size_t len)
|
|
||||||
{
|
|
||||||
bt_hci_lmp_acl_data(hci_from_device(link->host),
|
|
||||||
link->handle, data, start, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_submit_acl(struct HCIInfo *info,
|
|
||||||
- const uint8_t *data, int length)
|
|
||||||
+ const uint8_t *data, size_t length)
|
|
||||||
{
|
|
||||||
struct bt_hci_s *hci = hci_from_info(info);
|
|
||||||
uint16_t handle;
|
|
||||||
@@ -2027,7 +2027,7 @@ static void bt_submit_acl(struct HCIInfo *info,
|
|
||||||
struct bt_link_s *link;
|
|
||||||
|
|
||||||
if (length < HCI_ACL_HDR_SIZE) {
|
|
||||||
- error_report("%s: ACL packet too short (%iB)", __func__, length);
|
|
||||||
+ error_report("%s: ACL packet too short (%zuB)", __func__, length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2045,7 +2045,7 @@ static void bt_submit_acl(struct HCIInfo *info,
|
|
||||||
handle &= ~HCI_HANDLE_OFFSET;
|
|
||||||
|
|
||||||
if (datalen > length) {
|
|
||||||
- error_report("%s: ACL packet too short (%iB < %iB)",
|
|
||||||
+ error_report("%s: ACL packet too short (%zuB < %iB)",
|
|
||||||
__func__, length, datalen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -2087,7 +2087,7 @@ static void bt_submit_acl(struct HCIInfo *info,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_submit_sco(struct HCIInfo *info,
|
|
||||||
- const uint8_t *data, int length)
|
|
||||||
+ const uint8_t *data, size_t length)
|
|
||||||
{
|
|
||||||
struct bt_hci_s *hci = hci_from_info(info);
|
|
||||||
uint16_t handle;
|
|
||||||
@@ -2106,7 +2106,7 @@ static void bt_submit_sco(struct HCIInfo *info,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datalen > length) {
|
|
||||||
- error_report("%s: SCO packet too short (%iB < %iB)",
|
|
||||||
+ error_report("%s: SCO packet too short (%zuB < %iB)",
|
|
||||||
__func__, length, datalen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -2127,7 +2127,7 @@ static uint8_t *bt_hci_evt_packet(void *opaque)
|
|
||||||
return s->evt_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bt_hci_evt_submit(void *opaque, int len)
|
|
||||||
+static void bt_hci_evt_submit(void *opaque, size_t len)
|
|
||||||
{
|
|
||||||
/* TODO: notify upper layer */
|
|
||||||
struct bt_hci_s *s = opaque;
|
|
||||||
diff --git a/hw/bt/hid.c b/hw/bt/hid.c
|
|
||||||
index 066ca99..fe15434 100644
|
|
||||||
--- a/hw/bt/hid.c
|
|
||||||
+++ b/hw/bt/hid.c
|
|
||||||
@@ -95,7 +95,7 @@ struct bt_hid_device_s {
|
|
||||||
int data_type;
|
|
||||||
int intr_state;
|
|
||||||
struct {
|
|
||||||
- int len;
|
|
||||||
+ size_t len;
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
} dataother, datain, dataout, feature, intrdataout;
|
|
||||||
enum {
|
|
||||||
@@ -168,7 +168,7 @@ static void bt_hid_disconnect(struct bt_hid_device_s *s)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *pkt, hdr = (BT_DATA << 4) | type;
|
|
||||||
int plen;
|
|
||||||
@@ -189,7 +189,7 @@ static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bt_hid_control_transaction(struct bt_hid_device_s *s,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t type, parameter;
|
|
||||||
int rlen, ret = -1;
|
|
||||||
@@ -361,7 +361,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s,
|
|
||||||
bt_hid_send_handshake(s, ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len)
|
|
||||||
+static void bt_hid_control_sdu(void *opaque, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct bt_hid_device_s *hid = opaque;
|
|
||||||
|
|
||||||
@@ -387,7 +387,7 @@ static void bt_hid_datain(HIDState *hs)
|
|
||||||
hid->datain.buffer, hid->datain.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, int len)
|
|
||||||
+static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct bt_hid_device_s *hid = opaque;
|
|
||||||
|
|
||||||
diff --git a/hw/bt/l2cap.c b/hw/bt/l2cap.c
|
|
||||||
index d67098a..2f70a03 100644
|
|
||||||
--- a/hw/bt/l2cap.c
|
|
||||||
+++ b/hw/bt/l2cap.c
|
|
||||||
@@ -31,10 +31,10 @@ struct l2cap_instance_s {
|
|
||||||
int role;
|
|
||||||
|
|
||||||
uint8_t frame_in[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4)));
|
|
||||||
- int frame_in_len;
|
|
||||||
+ uint32_t frame_in_len;
|
|
||||||
|
|
||||||
uint8_t frame_out[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4)));
|
|
||||||
- int frame_out_len;
|
|
||||||
+ uint32_t frame_out_len;
|
|
||||||
|
|
||||||
/* Signalling channel timers. They exist per-request but we can make
|
|
||||||
* sure we have no more than one outstanding request at any time. */
|
|
||||||
@@ -48,7 +48,7 @@ struct l2cap_instance_s {
|
|
||||||
struct bt_l2cap_conn_params_s params;
|
|
||||||
|
|
||||||
void (*frame_in)(struct l2cap_chan_s *chan, uint16_t cid,
|
|
||||||
- const l2cap_hdr *hdr, int len);
|
|
||||||
+ const l2cap_hdr *hdr, size_t len);
|
|
||||||
int mps;
|
|
||||||
int min_mtu;
|
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ struct l2cap_instance_s {
|
|
||||||
|
|
||||||
/* Only flow-controlled, connection-oriented channels */
|
|
||||||
uint8_t sdu[65536]; /* TODO: dynamically allocate */
|
|
||||||
- int len_cur, len_total;
|
|
||||||
+ uint32_t len_cur, len_total;
|
|
||||||
int rexmit;
|
|
||||||
int monitor_timeout;
|
|
||||||
QEMUTimer *monitor_timer;
|
|
||||||
@@ -139,7 +139,7 @@ static const uint16_t l2cap_fcs16_table[256] = {
|
|
||||||
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
|
|
||||||
};
|
|
||||||
|
|
||||||
-static uint16_t l2cap_fcs16(const uint8_t *message, int len)
|
|
||||||
+static uint16_t l2cap_fcs16(const uint8_t *message, size_t len)
|
|
||||||
{
|
|
||||||
uint16_t fcs = 0x0000;
|
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ static void l2cap_monitor_timer_update(struct l2cap_chan_s *ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_command_reject(struct l2cap_instance_s *l2cap, int id,
|
|
||||||
- uint16_t reason, const void *data, int plen)
|
|
||||||
+ uint16_t reason, const void *data, size_t plen)
|
|
||||||
{
|
|
||||||
uint8_t *pkt;
|
|
||||||
l2cap_cmd_hdr *hdr;
|
|
||||||
@@ -246,7 +246,7 @@ static void l2cap_connection_response(struct l2cap_instance_s *l2cap,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_configuration_request(struct l2cap_instance_s *l2cap,
|
|
||||||
- int dcid, int flag, const uint8_t *data, int len)
|
|
||||||
+ int dcid, int flag, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *pkt;
|
|
||||||
l2cap_cmd_hdr *hdr;
|
|
||||||
@@ -274,7 +274,7 @@ static void l2cap_configuration_request(struct l2cap_instance_s *l2cap,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_configuration_response(struct l2cap_instance_s *l2cap,
|
|
||||||
- int scid, int flag, int result, const uint8_t *data, int len)
|
|
||||||
+ int scid, int flag, int result, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *pkt;
|
|
||||||
l2cap_cmd_hdr *hdr;
|
|
||||||
@@ -321,7 +321,7 @@ static void l2cap_disconnection_response(struct l2cap_instance_s *l2cap,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_echo_response(struct l2cap_instance_s *l2cap,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *pkt;
|
|
||||||
l2cap_cmd_hdr *hdr;
|
|
||||||
@@ -342,7 +342,7 @@ static void l2cap_echo_response(struct l2cap_instance_s *l2cap,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_info_response(struct l2cap_instance_s *l2cap, int type,
|
|
||||||
- int result, const uint8_t *data, int len)
|
|
||||||
+ int result, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t *pkt;
|
|
||||||
l2cap_cmd_hdr *hdr;
|
|
||||||
@@ -365,16 +365,18 @@ static void l2cap_info_response(struct l2cap_instance_s *l2cap, int type,
|
|
||||||
l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len);
|
|
||||||
+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm,
|
|
||||||
+ size_t len);
|
|
||||||
static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms);
|
|
||||||
#if 0
|
|
||||||
-static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len);
|
|
||||||
+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm,
|
|
||||||
+ size_t len);
|
|
||||||
static void l2cap_iframe_submit(struct bt_l2cap_conn_params_s *parm);
|
|
||||||
#endif
|
|
||||||
static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
|
|
||||||
- const l2cap_hdr *hdr, int len);
|
|
||||||
+ const l2cap_hdr *hdr, size_t len);
|
|
||||||
static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
|
|
||||||
- const l2cap_hdr *hdr, int len);
|
|
||||||
+ const l2cap_hdr *hdr, size_t len);
|
|
||||||
|
|
||||||
static int l2cap_cid_new(struct l2cap_instance_s *l2cap)
|
|
||||||
{
|
|
||||||
@@ -498,7 +500,7 @@ static void l2cap_channel_config_req_event(struct l2cap_instance_s *l2cap,
|
|
||||||
|
|
||||||
static int l2cap_channel_config(struct l2cap_instance_s *l2cap,
|
|
||||||
struct l2cap_chan_s *ch, int flag,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
l2cap_conf_opt *opt;
|
|
||||||
l2cap_conf_opt_qos *qos;
|
|
||||||
@@ -683,7 +685,7 @@ static int l2cap_channel_config(struct l2cap_instance_s *l2cap,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_channel_config_req_msg(struct l2cap_instance_s *l2cap,
|
|
||||||
- int flag, int cid, const uint8_t *data, int len)
|
|
||||||
+ int flag, int cid, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct l2cap_chan_s *ch;
|
|
||||||
|
|
||||||
@@ -715,7 +717,7 @@ static void l2cap_channel_config_req_msg(struct l2cap_instance_s *l2cap,
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l2cap_channel_config_rsp_msg(struct l2cap_instance_s *l2cap,
|
|
||||||
- int result, int flag, int cid, const uint8_t *data, int len)
|
|
||||||
+ int result, int flag, int cid, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct l2cap_chan_s *ch;
|
|
||||||
|
|
||||||
@@ -783,7 +785,7 @@ static void l2cap_info(struct l2cap_instance_s *l2cap, int type)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_command(struct l2cap_instance_s *l2cap, int code, int id,
|
|
||||||
- const uint8_t *params, int len)
|
|
||||||
+ const uint8_t *params, size_t len)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
@@ -938,7 +940,7 @@ static void l2cap_rexmit_enable(struct l2cap_chan_s *ch, int enable)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Command frame SDU */
|
|
||||||
-static void l2cap_cframe_in(void *opaque, const uint8_t *data, int len)
|
|
||||||
+static void l2cap_cframe_in(void *opaque, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct l2cap_instance_s *l2cap = opaque;
|
|
||||||
const l2cap_cmd_hdr *hdr;
|
|
||||||
@@ -966,7 +968,7 @@ static void l2cap_cframe_in(void *opaque, const uint8_t *data, int len)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Group frame SDU */
|
|
||||||
-static void l2cap_gframe_in(void *opaque, const uint8_t *data, int len)
|
|
||||||
+static void l2cap_gframe_in(void *opaque, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -977,7 +979,7 @@ static void l2cap_sframe_in(struct l2cap_chan_s *ch, uint16_t ctrl)
|
|
||||||
|
|
||||||
/* Basic L2CAP mode Information frame */
|
|
||||||
static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
|
|
||||||
- const l2cap_hdr *hdr, int len)
|
|
||||||
+ const l2cap_hdr *hdr, size_t len)
|
|
||||||
{
|
|
||||||
/* We have a full SDU, no further processing */
|
|
||||||
ch->params.sdu_in(ch->params.opaque, hdr->data, len);
|
|
||||||
@@ -985,7 +987,7 @@ static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
|
|
||||||
|
|
||||||
/* Flow Control and Retransmission mode frame */
|
|
||||||
static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
|
|
||||||
- const l2cap_hdr *hdr, int len)
|
|
||||||
+ const l2cap_hdr *hdr, size_t len)
|
|
||||||
{
|
|
||||||
uint16_t fcs = lduw_le_p(hdr->data + len - 2);
|
|
||||||
|
|
||||||
@@ -1076,7 +1078,7 @@ static void l2cap_frame_in(struct l2cap_instance_s *l2cap,
|
|
||||||
|
|
||||||
/* "Recombination" */
|
|
||||||
static void l2cap_pdu_in(struct l2cap_instance_s *l2cap,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
const l2cap_hdr *hdr = (void *) l2cap->frame_in;
|
|
||||||
|
|
||||||
@@ -1123,7 +1125,7 @@ static inline void l2cap_pdu_submit(struct l2cap_instance_s *l2cap)
|
|
||||||
(l2cap->link, l2cap->frame_out, 1, l2cap->frame_out_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len)
|
|
||||||
+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, size_t len)
|
|
||||||
{
|
|
||||||
struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm;
|
|
||||||
|
|
||||||
@@ -1146,7 +1148,7 @@ static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms)
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Stub: Only used if an emulated device requests outgoing flow control */
|
|
||||||
-static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len)
|
|
||||||
+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, size_t len)
|
|
||||||
{
|
|
||||||
struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm;
|
|
||||||
|
|
||||||
@@ -1291,7 +1293,7 @@ static void l2cap_lmp_disconnect_slave(struct bt_link_s *link)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void l2cap_lmp_acl_data_slave(struct bt_link_s *link,
|
|
||||||
- const uint8_t *data, int start, int len)
|
|
||||||
+ const uint8_t *data, int start, size_t len)
|
|
||||||
{
|
|
||||||
struct slave_l2cap_instance_s *l2cap =
|
|
||||||
(struct slave_l2cap_instance_s *) link;
|
|
||||||
@@ -1304,7 +1306,7 @@ static void l2cap_lmp_acl_data_slave(struct bt_link_s *link,
|
|
||||||
|
|
||||||
/* Stub */
|
|
||||||
static void l2cap_lmp_acl_data_host(struct bt_link_s *link,
|
|
||||||
- const uint8_t *data, int start, int len)
|
|
||||||
+ const uint8_t *data, int start, size_t len)
|
|
||||||
{
|
|
||||||
struct bt_l2cap_device_s *dev = (struct bt_l2cap_device_s *) link->host;
|
|
||||||
struct l2cap_instance_s *l2cap =
|
|
||||||
diff --git a/hw/bt/sdp.c b/hw/bt/sdp.c
|
|
||||||
index 2860d76..6bfb174 100644
|
|
||||||
--- a/hw/bt/sdp.c
|
|
||||||
+++ b/hw/bt/sdp.c
|
|
||||||
@@ -496,7 +496,7 @@ static ssize_t sdp_svc_search_attr_get(struct bt_l2cap_sdp_state_s *sdp,
|
|
||||||
return end + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
|
|
||||||
+static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct bt_l2cap_sdp_state_s *sdp = opaque;
|
|
||||||
enum bt_sdp_cmd pdu_id;
|
|
||||||
@@ -506,7 +506,7 @@ static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
|
|
||||||
int rsp_len = 0;
|
|
||||||
|
|
||||||
if (len < 5) {
|
|
||||||
- error_report("%s: short SDP PDU (%iB).", __func__, len);
|
|
||||||
+ error_report("%s: short SDP PDU (%zuB).", __func__, len);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -517,7 +517,7 @@ static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
|
|
||||||
len -= 5;
|
|
||||||
|
|
||||||
if (len != plen) {
|
|
||||||
- error_report("%s: wrong SDP PDU length (%iB != %iB).",
|
|
||||||
+ error_report("%s: wrong SDP PDU length (%iB != %zuB).",
|
|
||||||
__func__, plen, len);
|
|
||||||
err = SDP_INVALID_PDU_SIZE;
|
|
||||||
goto respond;
|
|
||||||
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
|
|
||||||
index 670ba32..240a901 100644
|
|
||||||
--- a/hw/usb/dev-bluetooth.c
|
|
||||||
+++ b/hw/usb/dev-bluetooth.c
|
|
||||||
@@ -265,7 +265,7 @@ static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
int off = fifo->dstart + fifo->dlen;
|
|
||||||
uint8_t *buf;
|
|
||||||
@@ -274,13 +274,13 @@ static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
|
|
||||||
if (off <= DFIFO_LEN_MASK) {
|
|
||||||
if (off + len > DFIFO_LEN_MASK + 1 &&
|
|
||||||
(fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) {
|
|
||||||
- fprintf(stderr, "%s: can't alloc %i bytes\n", __func__, len);
|
|
||||||
+ fprintf(stderr, "%s: can't alloc %zu bytes\n", __func__, len);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
buf = fifo->data + off;
|
|
||||||
} else {
|
|
||||||
if (fifo->dlen > fifo->dsize) {
|
|
||||||
- fprintf(stderr, "%s: can't alloc %i bytes\n", __func__, len);
|
|
||||||
+ fprintf(stderr, "%s: can't alloc %zu bytes\n", __func__, len);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
buf = fifo->data + off - fifo->dsize;
|
|
||||||
@@ -319,7 +319,7 @@ static inline void usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
|
|
||||||
|
|
||||||
static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
|
|
||||||
struct usb_hci_out_fifo_s *fifo,
|
|
||||||
- void (*send)(struct HCIInfo *, const uint8_t *, int),
|
|
||||||
+ void (*send)(struct HCIInfo *, const uint8_t *, size_t),
|
|
||||||
int (*complete)(const uint8_t *, int),
|
|
||||||
USBPacket *p)
|
|
||||||
{
|
|
||||||
@@ -478,7 +478,7 @@ static void usb_bt_handle_data(USBDevice *dev, USBPacket *p)
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usb_bt_out_hci_packet_event(void *opaque,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct USBBtState *s = (struct USBBtState *) opaque;
|
|
||||||
|
|
||||||
@@ -489,7 +489,7 @@ static void usb_bt_out_hci_packet_event(void *opaque,
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usb_bt_out_hci_packet_acl(void *opaque,
|
|
||||||
- const uint8_t *data, int len)
|
|
||||||
+ const uint8_t *data, size_t len)
|
|
||||||
{
|
|
||||||
struct USBBtState *s = (struct USBBtState *) opaque;
|
|
||||||
|
|
||||||
diff --git a/include/hw/bt.h b/include/hw/bt.h
|
|
||||||
index b5e11d4..bc362aa 100644
|
|
||||||
--- a/include/hw/bt.h
|
|
||||||
+++ b/include/hw/bt.h
|
|
||||||
@@ -94,9 +94,9 @@ struct bt_device_s {
|
|
||||||
void (*lmp_disconnect_master)(struct bt_link_s *link);
|
|
||||||
void (*lmp_disconnect_slave)(struct bt_link_s *link);
|
|
||||||
void (*lmp_acl_data)(struct bt_link_s *link, const uint8_t *data,
|
|
||||||
- int start, int len);
|
|
||||||
+ int start, size_t len);
|
|
||||||
void (*lmp_acl_resp)(struct bt_link_s *link, const uint8_t *data,
|
|
||||||
- int start, int len);
|
|
||||||
+ int start, size_t len);
|
|
||||||
void (*lmp_mode_change)(struct bt_link_s *link);
|
|
||||||
|
|
||||||
void (*handle_destroy)(struct bt_device_s *device);
|
|
||||||
@@ -148,12 +148,12 @@ struct bt_l2cap_device_s {
|
|
||||||
|
|
||||||
struct bt_l2cap_conn_params_s {
|
|
||||||
/* Input */
|
|
||||||
- uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, int len);
|
|
||||||
+ uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, size_t len);
|
|
||||||
void (*sdu_submit)(struct bt_l2cap_conn_params_s *chan);
|
|
||||||
int remote_mtu;
|
|
||||||
/* Output */
|
|
||||||
void *opaque;
|
|
||||||
- void (*sdu_in)(void *opaque, const uint8_t *data, int len);
|
|
||||||
+ void (*sdu_in)(void *opaque, const uint8_t *data, size_t len);
|
|
||||||
void (*close)(void *opaque);
|
|
||||||
};
|
|
||||||
|
|
||||||
diff --git a/include/sysemu/bt.h b/include/sysemu/bt.h
|
|
||||||
index 2fd8c0f..df8fb63 100644
|
|
||||||
--- a/include/sysemu/bt.h
|
|
||||||
+++ b/include/sysemu/bt.h
|
|
||||||
@@ -5,12 +5,12 @@
|
|
||||||
|
|
||||||
typedef struct HCIInfo {
|
|
||||||
int (*bdaddr_set)(struct HCIInfo *hci, const uint8_t *bd_addr);
|
|
||||||
- void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, int len);
|
|
||||||
- void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, int len);
|
|
||||||
- void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, int len);
|
|
||||||
+ void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, size_t len);
|
|
||||||
+ void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, size_t len);
|
|
||||||
+ void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, size_t len);
|
|
||||||
void *opaque;
|
|
||||||
- void (*evt_recv)(void *opaque, const uint8_t *data, int len);
|
|
||||||
- void (*acl_recv)(void *opaque, const uint8_t *data, int len);
|
|
||||||
+ void (*evt_recv)(void *opaque, const uint8_t *data, size_t len);
|
|
||||||
+ void (*acl_recv)(void *opaque, const uint8_t *data, size_t len);
|
|
||||||
} HCIInfo;
|
|
||||||
|
|
||||||
/* bt-host.c */
|
|
||||||
--
|
|
||||||
1.8.3.1
|
|
||||||
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
From b9e4a4ff6f3292927adb1463777c86cd4063a6ef Mon Sep 17 00:00:00 2001
|
|
||||||
From: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
Date: Sat, 18 Apr 2020 12:10:11 +0800
|
|
||||||
Subject: [PATCH] bugfix: Use gicr_typer in arm_gicv3_icc_reset
|
|
||||||
|
|
||||||
The KVM_VGIC_ATTR macro expect the second parameter as gicr_typer,
|
|
||||||
of which high 32bit is constructed by mp_affinity. For most case,
|
|
||||||
the high 32bit of mp_affinity is zero, so it will always access the
|
|
||||||
ICC_CTLR_EL1 of CPU0.
|
|
||||||
|
|
||||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
|
||||||
---
|
|
||||||
hw/intc/arm_gicv3_kvm.c | 4 +---
|
|
||||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
|
|
||||||
index d9c72f85be..b1e74147ba 100644
|
|
||||||
--- a/hw/intc/arm_gicv3_kvm.c
|
|
||||||
+++ b/hw/intc/arm_gicv3_kvm.c
|
|
||||||
@@ -661,13 +661,11 @@ static void kvm_arm_gicv3_get(GICv3State *s)
|
|
||||||
|
|
||||||
static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
|
|
||||||
{
|
|
||||||
- ARMCPU *cpu;
|
|
||||||
GICv3State *s;
|
|
||||||
GICv3CPUState *c;
|
|
||||||
|
|
||||||
c = (GICv3CPUState *)env->gicv3state;
|
|
||||||
s = c->gic;
|
|
||||||
- cpu = ARM_CPU(c->cpu);
|
|
||||||
|
|
||||||
c->icc_pmr_el1 = 0;
|
|
||||||
c->icc_bpr[GICV3_G0] = GIC_MIN_BPR;
|
|
||||||
@@ -684,7 +682,7 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
|
|
||||||
|
|
||||||
/* Initialize to actual HW supported configuration */
|
|
||||||
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
|
|
||||||
- KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity),
|
|
||||||
+ KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer),
|
|
||||||
&c->icc_ctlr_el1[GICV3_NS], false, &error_abort);
|
|
||||||
|
|
||||||
c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
|
|
||||||
--
|
|
||||||
2.19.1
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
From af8740502815be450709e88df44ad322da2b071f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Henglong Fan <fanhenglong@huawei.com>
|
|
||||||
Date: Tue, 18 Aug 2020 21:42:33 +0800
|
|
||||||
Subject: [PATCH] build smt processor structure to support smt topology
|
|
||||||
|
|
||||||
if vcpu support smt, create new smt hierarchy according to
|
|
||||||
Processor Properties Topology Table(PPTT) in acpi spec 6.3.
|
|
||||||
Threads sharing a core must be grouped under a unique Processor
|
|
||||||
hierarchy node structure for each group of threads
|
|
||||||
|
|
||||||
Signed-off-by: Henglong Fan <fanhenglong@huawei.com>
|
|
||||||
---
|
|
||||||
hw/acpi/aml-build.c | 40 ++++++++++++++++++++++++++++++++--------
|
|
||||||
1 file changed, 32 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
|
||||||
index 74e95005..8a3b51c8 100644
|
|
||||||
--- a/hw/acpi/aml-build.c
|
|
||||||
+++ b/hw/acpi/aml-build.c
|
|
||||||
@@ -53,7 +53,7 @@ static void build_append_array(GArray *array, GArray *val)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * ACPI 6.2 Processor Properties Topology Table (PPTT)
|
|
||||||
+ * ACPI 6.3 Processor Properties Topology Table (PPTT)
|
|
||||||
*/
|
|
||||||
#ifdef __aarch64__
|
|
||||||
static void build_cache_head(GArray *tbl, uint32_t next_level)
|
|
||||||
@@ -126,7 +126,7 @@ static void build_arm_socket_hierarchy(GArray *tbl,
|
|
||||||
build_append_int_noprefix(tbl, offset, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void build_arm_cpu_hierarchy(GArray *tbl,
|
|
||||||
+static void build_arm_core_hierarchy(GArray *tbl,
|
|
||||||
struct offset_status *offset, uint32_t id)
|
|
||||||
{
|
|
||||||
if (!offset) {
|
|
||||||
@@ -144,18 +144,35 @@ static void build_arm_cpu_hierarchy(GArray *tbl,
|
|
||||||
build_append_int_noprefix(tbl, offset->l2_offset, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void build_arm_smt_hierarchy(GArray *tbl,
|
|
||||||
+ uint32_t offset, uint32_t id)
|
|
||||||
+{
|
|
||||||
+ if (!offset) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ build_append_byte(tbl, 0); /* Type 0 - processor */
|
|
||||||
+ build_append_byte(tbl, 20); /* Length, add private resources */
|
|
||||||
+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */
|
|
||||||
+ build_append_int_noprefix(tbl, 14, 4); /* Valid id*/
|
|
||||||
+ build_append_int_noprefix(tbl, offset, 4);
|
|
||||||
+ build_append_int_noprefix(tbl, id, 4);
|
|
||||||
+ build_append_int_noprefix(tbl, 0, 4); /* Num private resources */
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus)
|
|
||||||
{
|
|
||||||
int pptt_start = table_data->len;
|
|
||||||
- int uid = 0, cpus = 0, socket;
|
|
||||||
+ int uid = 0, socket;
|
|
||||||
+ uint32_t core_offset;
|
|
||||||
struct offset_status offset;
|
|
||||||
const MachineState *ms = MACHINE(qdev_get_machine());
|
|
||||||
unsigned int smp_cores = ms->smp.cores;
|
|
||||||
+ unsigned int smp_sockets = ms->smp.cpus / (smp_cores * ms->smp.threads);
|
|
||||||
|
|
||||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
|
||||||
|
|
||||||
- for (socket = 0; cpus < possible_cpus; socket++) {
|
|
||||||
- int core;
|
|
||||||
+ for (socket = 0; socket < smp_sockets; socket++) {
|
|
||||||
+ int core,thread;
|
|
||||||
uint32_t l3_offset = table_data->len - pptt_start;
|
|
||||||
build_cache_hierarchy(table_data, 0, ARM_L3_CACHE);
|
|
||||||
|
|
||||||
@@ -169,14 +186,21 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus)
|
|
||||||
build_cache_hierarchy(table_data, offset.l2_offset, ARM_L1D_CACHE);
|
|
||||||
offset.l1i_offset = table_data->len - pptt_start;
|
|
||||||
build_cache_hierarchy(table_data, offset.l2_offset, ARM_L1I_CACHE);
|
|
||||||
- build_arm_cpu_hierarchy(table_data, &offset, uid++);
|
|
||||||
- cpus++;
|
|
||||||
+ core_offset = table_data->len - pptt_start;
|
|
||||||
+ if (ms->smp.threads <= 1) {
|
|
||||||
+ build_arm_core_hierarchy(table_data, &offset, uid++);
|
|
||||||
+ } else {
|
|
||||||
+ build_arm_core_hierarchy(table_data, &offset, core);
|
|
||||||
+ for (thread = 0; thread < ms->smp.threads; thread++) {
|
|
||||||
+ build_arm_smt_hierarchy(table_data, core_offset, uid++);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
build_header(linker, table_data,
|
|
||||||
(void *)(table_data->data + pptt_start), "PPTT",
|
|
||||||
- table_data->len - pptt_start, 1, NULL, NULL);
|
|
||||||
+ table_data->len - pptt_start, 2, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
@ -1,126 +0,0 @@
|
|||||||
From 902a8192600ff81681a162509e23bf95619d1f04 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
|
||||||
Date: Mon, 20 Apr 2020 13:20:12 +0200
|
|
||||||
Subject: [PATCH] char: fix use-after-free with dup chardev & reconnect
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
With a reconnect socket, qemu_char_open() will start a background
|
|
||||||
thread. It should keep a reference on the chardev.
|
|
||||||
|
|
||||||
Fixes invalid read:
|
|
||||||
READ of size 8 at 0x6040000ac858 thread T7
|
|
||||||
#0 0x5555598d37b8 in unix_connect_saddr /home/elmarco/src/qq/util/qemu-sockets.c:954
|
|
||||||
#1 0x5555598d4751 in socket_connect /home/elmarco/src/qq/util/qemu-sockets.c:1109
|
|
||||||
#2 0x555559707c34 in qio_channel_socket_connect_sync /home/elmarco/src/qq/io/channel-socket.c:145
|
|
||||||
#3 0x5555596adebb in tcp_chr_connect_client_task /home/elmarco/src/qq/chardev/char-socket.c:1104
|
|
||||||
#4 0x555559723d55 in qio_task_thread_worker /home/elmarco/src/qq/io/task.c:123
|
|
||||||
#5 0x5555598a6731 in qemu_thread_start /home/elmarco/src/qq/util/qemu-thread-posix.c:519
|
|
||||||
#6 0x7ffff40d4431 in start_thread (/lib64/libpthread.so.0+0x9431)
|
|
||||||
#7 0x7ffff40029d2 in __clone (/lib64/libc.so.6+0x1019d2)
|
|
||||||
|
|
||||||
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
|
||||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
||||||
Message-Id: <20200420112012.567284-1-marcandre.lureau@redhat.com>
|
|
||||||
Signed-off-by: Zhenyu Ye <yezhenyu2@huawei.com>
|
|
||||||
---
|
|
||||||
chardev/char-socket.c | 3 ++-
|
|
||||||
tests/test-char.c | 53 ++++++++++++++++++++++++++++++++++++++++++-
|
|
||||||
2 files changed, 54 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
|
|
||||||
index 7ca5d97a..701b62f9 100644
|
|
||||||
--- a/chardev/char-socket.c
|
|
||||||
+++ b/chardev/char-socket.c
|
|
||||||
@@ -1118,7 +1118,8 @@ static void tcp_chr_connect_client_async(Chardev *chr)
|
|
||||||
*/
|
|
||||||
s->connect_task = qio_task_new(OBJECT(sioc),
|
|
||||||
qemu_chr_socket_connected,
|
|
||||||
- chr, NULL);
|
|
||||||
+ object_ref(OBJECT(chr)),
|
|
||||||
+ (GDestroyNotify)object_unref);
|
|
||||||
qio_task_run_in_thread(s->connect_task,
|
|
||||||
tcp_chr_connect_client_task,
|
|
||||||
s->addr,
|
|
||||||
diff --git a/tests/test-char.c b/tests/test-char.c
|
|
||||||
index f9440cdc..0e4069fb 100644
|
|
||||||
--- a/tests/test-char.c
|
|
||||||
+++ b/tests/test-char.c
|
|
||||||
@@ -871,6 +871,53 @@ typedef struct {
|
|
||||||
} CharSocketClientTestConfig;
|
|
||||||
|
|
||||||
|
|
||||||
+static void char_socket_client_dupid_test(gconstpointer opaque)
|
|
||||||
+{
|
|
||||||
+ const CharSocketClientTestConfig *config = opaque;
|
|
||||||
+ QIOChannelSocket *ioc;
|
|
||||||
+ char *optstr;
|
|
||||||
+ Chardev *chr1, *chr2;
|
|
||||||
+ SocketAddress *addr;
|
|
||||||
+ QemuOpts *opts;
|
|
||||||
+ Error *local_err = NULL;
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Setup a listener socket and determine get its address
|
|
||||||
+ * so we know the TCP port for the client later
|
|
||||||
+ */
|
|
||||||
+ ioc = qio_channel_socket_new();
|
|
||||||
+ g_assert_nonnull(ioc);
|
|
||||||
+ qio_channel_socket_listen_sync(ioc, config->addr, &error_abort);
|
|
||||||
+ addr = qio_channel_socket_get_local_address(ioc, &error_abort);
|
|
||||||
+ g_assert_nonnull(addr);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Populate the chardev address based on what the server
|
|
||||||
+ * is actually listening on
|
|
||||||
+ */
|
|
||||||
+ optstr = char_socket_addr_to_opt_str(addr,
|
|
||||||
+ config->fd_pass,
|
|
||||||
+ config->reconnect,
|
|
||||||
+ false);
|
|
||||||
+
|
|
||||||
+ opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
|
|
||||||
+ optstr, true);
|
|
||||||
+ g_assert_nonnull(opts);
|
|
||||||
+ chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort);
|
|
||||||
+ g_assert_nonnull(chr1);
|
|
||||||
+
|
|
||||||
+ chr2 = qemu_chr_new_from_opts(opts, NULL, &local_err);
|
|
||||||
+ g_assert_null(chr2);
|
|
||||||
+ error_free_or_abort(&local_err);
|
|
||||||
+
|
|
||||||
+ object_unref(OBJECT(ioc));
|
|
||||||
+ qemu_opts_del(opts);
|
|
||||||
+ object_unparent(OBJECT(chr1));
|
|
||||||
+ qapi_free_SocketAddress(addr);
|
|
||||||
+ g_free(optstr);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
static void char_socket_client_test(gconstpointer opaque)
|
|
||||||
{
|
|
||||||
const CharSocketClientTestConfig *config = opaque;
|
|
||||||
@@ -1425,6 +1472,8 @@ int main(int argc, char **argv)
|
|
||||||
{ addr, NULL, false, true }; \
|
|
||||||
CharSocketClientTestConfig client6 ## name = \
|
|
||||||
{ addr, NULL, true, true }; \
|
|
||||||
+ CharSocketClientTestConfig client7 ## name = \
|
|
||||||
+ { addr, ",reconnect=1", false, false }; \
|
|
||||||
g_test_add_data_func("/char/socket/client/mainloop/" # name, \
|
|
||||||
&client1 ##name, char_socket_client_test); \
|
|
||||||
g_test_add_data_func("/char/socket/client/wait-conn/" # name, \
|
|
||||||
@@ -1436,7 +1485,9 @@ int main(int argc, char **argv)
|
|
||||||
g_test_add_data_func("/char/socket/client/mainloop-fdpass/" # name, \
|
|
||||||
&client5 ##name, char_socket_client_test); \
|
|
||||||
g_test_add_data_func("/char/socket/client/wait-conn-fdpass/" # name, \
|
|
||||||
- &client6 ##name, char_socket_client_test)
|
|
||||||
+ &client6 ##name, char_socket_client_test); \
|
|
||||||
+ g_test_add_data_func("/char/socket/client/dupid-reconnect/" # name, \
|
|
||||||
+ &client7 ##name, char_socket_client_dupid_test)
|
|
||||||
|
|
||||||
SOCKET_SERVER_TEST(tcp, &tcpaddr);
|
|
||||||
SOCKET_CLIENT_TEST(tcp, &tcpaddr);
|
|
||||||
--
|
|
||||||
2.22.0.windows.1
|
|
||||||
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
From 4488ab4700d344b049ddef808a64eda4b5867902 Mon Sep 17 00:00:00 2001
|
|
||||||
From: lichun <lichun@ruijie.com.cn>
|
|
||||||
Date: Mon, 22 Jun 2020 05:30:17 +0800
|
|
||||||
Subject: [PATCH 06/11] chardev/tcp: Fix error message double free error
|
|
||||||
|
|
||||||
Errors are already freed by error_report_err, so we only need to call
|
|
||||||
error_free when that function is not called.
|
|
||||||
|
|
||||||
Cc: qemu-stable@nongnu.org
|
|
||||||
Signed-off-by: lichun <lichun@ruijie.com.cn>
|
|
||||||
Message-Id: <20200621213017.17978-1-lichun@ruijie.com.cn>
|
|
||||||
Reviewed-by: Markus Armbruster <armbru@redhat.com>
|
|
||||||
[Commit message improved, cc: qemu-stable]
|
|
||||||
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
|
||||||
Signed-off-by: BiaoXiang Ye <yebiaoxiang@huawei.com>
|
|
||||||
---
|
|
||||||
chardev/char-socket.c | 3 ++-
|
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
|
|
||||||
index 701b62f9..9b06c8aa 100644
|
|
||||||
--- a/chardev/char-socket.c
|
|
||||||
+++ b/chardev/char-socket.c
|
|
||||||
@@ -141,6 +141,8 @@ static void check_report_connect_error(Chardev *chr,
|
|
||||||
error_report("Unable to connect character device %s: %s",
|
|
||||||
chr->label, error_get_pretty(err));
|
|
||||||
s->connect_err_reported = true;
|
|
||||||
+ } else {
|
|
||||||
+ error_free(err);
|
|
||||||
}
|
|
||||||
qemu_chr_socket_restart_timer(chr);
|
|
||||||
}
|
|
||||||
@@ -1074,7 +1076,6 @@ static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
|
|
||||||
if (qio_task_propagate_error(task, &err)) {
|
|
||||||
tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
|
|
||||||
check_report_connect_error(chr, err);
|
|
||||||
- error_free(err);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.27.0.dirty
|
|
||||||
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
From 19afb1431bd730a1e4e09e3c0835c35572517268 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Derek Su <dereksu@qnap.com>
|
|
||||||
Date: Fri, 22 May 2020 15:53:57 +0800
|
|
||||||
Subject: [PATCH 07/11] colo-compare: Fix memory leak in packet_enqueue()
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
The patch is to fix the "pkt" memory leak in packet_enqueue().
|
|
||||||
The allocated "pkt" needs to be freed if the colo compare
|
|
||||||
primary or secondary queue is too big.
|
|
||||||
|
|
||||||
Replace the error_report of full queue with a trace event.
|
|
||||||
|
|
||||||
Signed-off-by: Derek Su <dereksu@qnap.com>
|
|
||||||
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
||||||
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
|
|
||||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
|
||||||
Signed-off-by: BiaoXiang Ye <yebiaoxiang@huawei.com>
|
|
||||||
---
|
|
||||||
net/colo-compare.c | 23 +++++++++++++++--------
|
|
||||||
net/trace-events | 1 +
|
|
||||||
2 files changed, 16 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/net/colo-compare.c b/net/colo-compare.c
|
|
||||||
index 7ee17f2c..3168407e 100644
|
|
||||||
--- a/net/colo-compare.c
|
|
||||||
+++ b/net/colo-compare.c
|
|
||||||
@@ -120,6 +120,10 @@ enum {
|
|
||||||
SECONDARY_IN,
|
|
||||||
};
|
|
||||||
|
|
||||||
+static const char *colo_mode[] = {
|
|
||||||
+ [PRIMARY_IN] = "primary",
|
|
||||||
+ [SECONDARY_IN] = "secondary",
|
|
||||||
+};
|
|
||||||
|
|
||||||
static int compare_chr_send(CompareState *s,
|
|
||||||
const uint8_t *buf,
|
|
||||||
@@ -215,6 +219,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
|
|
||||||
ConnectionKey key;
|
|
||||||
Packet *pkt = NULL;
|
|
||||||
Connection *conn;
|
|
||||||
+ int ret;
|
|
||||||
|
|
||||||
if (mode == PRIMARY_IN) {
|
|
||||||
pkt = packet_new(s->pri_rs.buf,
|
|
||||||
@@ -243,16 +248,18 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == PRIMARY_IN) {
|
|
||||||
- if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) {
|
|
||||||
- error_report("colo compare primary queue size too big,"
|
|
||||||
- "drop packet");
|
|
||||||
- }
|
|
||||||
+ ret = colo_insert_packet(&conn->primary_list, pkt, &conn->pack);
|
|
||||||
} else {
|
|
||||||
- if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) {
|
|
||||||
- error_report("colo compare secondary queue size too big,"
|
|
||||||
- "drop packet");
|
|
||||||
- }
|
|
||||||
+ ret = colo_insert_packet(&conn->secondary_list, pkt, &conn->sack);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if (!ret) {
|
|
||||||
+ trace_colo_compare_drop_packet(colo_mode[mode],
|
|
||||||
+ "queue size too big, drop packet");
|
|
||||||
+ packet_destroy(pkt, NULL);
|
|
||||||
+ pkt = NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
*con = conn;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
diff --git a/net/trace-events b/net/trace-events
|
|
||||||
index ac570564..a9995387 100644
|
|
||||||
--- a/net/trace-events
|
|
||||||
+++ b/net/trace-events
|
|
||||||
@@ -12,6 +12,7 @@ colo_proxy_main(const char *chr) ": %s"
|
|
||||||
|
|
||||||
# colo-compare.c
|
|
||||||
colo_compare_main(const char *chr) ": %s"
|
|
||||||
+colo_compare_drop_packet(const char *queue, const char *chr) ": %s: %s"
|
|
||||||
colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d"
|
|
||||||
colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d"
|
|
||||||
colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s"
|
|
||||||
--
|
|
||||||
2.27.0.dirty
|
|
||||||
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
From 5a79ccd388ee09dc1db93d26791d1e4a6b2ced47 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Juan Quintela <quintela@redhat.com>
|
|
||||||
Date: Wed, 3 Feb 2021 17:33:44 +0800
|
|
||||||
Subject: [PATCH] configure: Enable test and libs for zstd
|
|
||||||
|
|
||||||
configure: Enable test and libs for zstd
|
|
||||||
Add it to several build systems to make testing good.
|
|
||||||
|
|
||||||
Signed-off-by: Juan Quintela <quintela@redhat.com>
|
|
||||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
||||||
|
|
||||||
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
|
|
||||||
---
|
|
||||||
.gitlab-ci.yml | 1 +
|
|
||||||
.travis.yml | 1 +
|
|
||||||
configure | 30 ++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 32 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
|
|
||||||
index c63bf2f822..3d9b7f9262 100644
|
|
||||||
--- a/.gitlab-ci.yml
|
|
||||||
+++ b/.gitlab-ci.yml
|
|
||||||
@@ -16,6 +16,7 @@ build-system2:
|
|
||||||
script:
|
|
||||||
- apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
|
|
||||||
libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
|
|
||||||
+ libzstd-dev
|
|
||||||
- ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
|
|
||||||
microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
|
|
||||||
sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
|
|
||||||
diff --git a/.travis.yml b/.travis.yml
|
|
||||||
index caf0a1f8fa..f3fe04fba9 100644
|
|
||||||
--- a/.travis.yml
|
|
||||||
+++ b/.travis.yml
|
|
||||||
@@ -35,6 +35,7 @@ addons:
|
|
||||||
- liburcu-dev
|
|
||||||
- libusb-1.0-0-dev
|
|
||||||
- libvte-2.91-dev
|
|
||||||
+ - libzstd-dev
|
|
||||||
- sparse
|
|
||||||
- uuid-dev
|
|
||||||
- gcovr
|
|
||||||
diff --git a/configure b/configure
|
|
||||||
index 714e7fb6a1..577533e9ed 100755
|
|
||||||
--- a/configure
|
|
||||||
+++ b/configure
|
|
||||||
@@ -446,6 +446,7 @@ lzo=""
|
|
||||||
snappy=""
|
|
||||||
bzip2=""
|
|
||||||
lzfse=""
|
|
||||||
+zstd=""
|
|
||||||
guest_agent=""
|
|
||||||
guest_agent_with_vss="no"
|
|
||||||
guest_agent_ntddscsi="no"
|
|
||||||
@@ -1358,6 +1359,10 @@ for opt do
|
|
||||||
;;
|
|
||||||
--disable-lzfse) lzfse="no"
|
|
||||||
;;
|
|
||||||
+ --disable-zstd) zstd="no"
|
|
||||||
+ ;;
|
|
||||||
+ --enable-zstd) zstd="yes"
|
|
||||||
+ ;;
|
|
||||||
--enable-guest-agent) guest_agent="yes"
|
|
||||||
;;
|
|
||||||
--disable-guest-agent) guest_agent="no"
|
|
||||||
@@ -1812,6 +1817,8 @@ disabled with --disable-FEATURE, default is enabled if available:
|
|
||||||
(for reading bzip2-compressed dmg images)
|
|
||||||
lzfse support of lzfse compression library
|
|
||||||
(for reading lzfse-compressed dmg images)
|
|
||||||
+ zstd support for zstd compression library
|
|
||||||
+ (for migration compression)
|
|
||||||
seccomp seccomp support
|
|
||||||
coroutine-pool coroutine freelist (better performance)
|
|
||||||
glusterfs GlusterFS backend
|
|
||||||
@@ -2407,6 +2414,24 @@ EOF
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
+##########################################
|
|
||||||
+# zstd check
|
|
||||||
+
|
|
||||||
+if test "$zstd" != "no" ; then
|
|
||||||
+ if $pkg_config --exist libzstd ; then
|
|
||||||
+ zstd_cflags="$($pkg_config --cflags libzstd)"
|
|
||||||
+ zstd_libs="$($pkg_config --libs libzstd)"
|
|
||||||
+ LIBS="$zstd_libs $LIBS"
|
|
||||||
+ QEMU_CFLAGS="$QEMU_CFLAGS $zstd_cflags"
|
|
||||||
+ zstd="yes"
|
|
||||||
+ else
|
|
||||||
+ if test "$zstd" = "yes" ; then
|
|
||||||
+ feature_not_found "libzstd" "Install libzstd devel"
|
|
||||||
+ fi
|
|
||||||
+ zstd="no"
|
|
||||||
+ fi
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
##########################################
|
|
||||||
# libseccomp check
|
|
||||||
|
|
||||||
@@ -6460,6 +6485,7 @@ echo "lzo support $lzo"
|
|
||||||
echo "snappy support $snappy"
|
|
||||||
echo "bzip2 support $bzip2"
|
|
||||||
echo "lzfse support $lzfse"
|
|
||||||
+echo "zstd support $zstd"
|
|
||||||
echo "NUMA host support $numa"
|
|
||||||
echo "libxml2 $libxml2"
|
|
||||||
echo "tcmalloc support $tcmalloc"
|
|
||||||
@@ -7024,6 +7050,10 @@ if test "$lzfse" = "yes" ; then
|
|
||||||
echo "LZFSE_LIBS=-llzfse" >> $config_host_mak
|
|
||||||
fi
|
|
||||||
|
|
||||||
+if test "$zstd" = "yes" ; then
|
|
||||||
+ echo "CONFIG_ZSTD=y" >> $config_host_mak
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
if test "$libiscsi" = "yes" ; then
|
|
||||||
echo "CONFIG_LIBISCSI=m" >> $config_host_mak
|
|
||||||
echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak
|
|
||||||
--
|
|
||||||
2.27.0
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user