Enable QXL device build
Enable building for ppc64le Re-added Spice support Don't remove slof.bin for ppc64le
This commit is contained in:
parent
35ae37c0e7
commit
81048c7967
121
kvm-blkdebug-Add-delay-ns-option.patch
Normal file
121
kvm-blkdebug-Add-delay-ns-option.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From b37120279fbb5615558dce392365527aae8169ea Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 18:11:26 +0200
|
||||
Subject: [PATCH 1/8] blkdebug: Add 'delay-ns' option
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 562: ide: Fix deadlock between TRIM and drain [10.2.z]
|
||||
RH-Jira: RHEL-190702
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/8] c07ed8a9897c2f8cd8efa5049ed100a1e42b9123 (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
Sometimes reproducing a problem for debugging involves slow I/O, so
|
||||
let's add something to blkdebug to make I/O slow when we need it. This
|
||||
can be used either together with an error so that the request fails
|
||||
after the delay, or with errno=0, which allows the request to succeed
|
||||
after the delay.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <20260421161132.99878-2-kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit d5e4090177ad382e01084a1594a1a60a69f4c1cd)
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
block/blkdebug.c | 15 ++++++++++++++-
|
||||
qapi/block-core.json | 4 ++++
|
||||
2 files changed, 18 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/blkdebug.c b/block/blkdebug.c
|
||||
index c54aee0c84..8954fc2977 100644
|
||||
--- a/block/blkdebug.c
|
||||
+++ b/block/blkdebug.c
|
||||
@@ -95,6 +95,7 @@ typedef struct BlkdebugRule {
|
||||
int immediately;
|
||||
int once;
|
||||
int64_t offset;
|
||||
+ int64_t delay_ns;
|
||||
} inject;
|
||||
struct {
|
||||
int new_state;
|
||||
@@ -144,6 +145,10 @@ static QemuOptsList inject_error_opts = {
|
||||
.name = "immediately",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},
|
||||
+ {
|
||||
+ .name = "delay-ns",
|
||||
+ .type = QEMU_OPT_NUMBER,
|
||||
+ },
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
@@ -216,6 +221,8 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
|
||||
rule->options.inject.once = qemu_opt_get_bool(opts, "once", 0);
|
||||
rule->options.inject.immediately =
|
||||
qemu_opt_get_bool(opts, "immediately", 0);
|
||||
+ rule->options.inject.delay_ns =
|
||||
+ qemu_opt_get_number(opts, "delay-ns", 0);
|
||||
sector = qemu_opt_get_number(opts, "sector", -1);
|
||||
rule->options.inject.offset =
|
||||
sector == -1 ? -1 : sector * BDRV_SECTOR_SIZE;
|
||||
@@ -594,6 +601,7 @@ static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset,
|
||||
BlkdebugRule *rule = NULL;
|
||||
int error;
|
||||
bool immediately;
|
||||
+ int64_t delay_ns;
|
||||
|
||||
qemu_mutex_lock(&s->lock);
|
||||
QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
|
||||
@@ -608,13 +616,14 @@ static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset,
|
||||
}
|
||||
}
|
||||
|
||||
- if (!rule || !rule->options.inject.error) {
|
||||
+ if (!rule) {
|
||||
qemu_mutex_unlock(&s->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
immediately = rule->options.inject.immediately;
|
||||
error = rule->options.inject.error;
|
||||
+ delay_ns = rule->options.inject.delay_ns;
|
||||
|
||||
if (rule->options.inject.once) {
|
||||
QSIMPLEQ_REMOVE(&s->active_rules, rule, BlkdebugRule, active_next);
|
||||
@@ -622,6 +631,10 @@ static int coroutine_fn rule_check(BlockDriverState *bs, uint64_t offset,
|
||||
}
|
||||
|
||||
qemu_mutex_unlock(&s->lock);
|
||||
+
|
||||
+ if (delay_ns) {
|
||||
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, delay_ns);
|
||||
+ }
|
||||
if (!immediately) {
|
||||
aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self());
|
||||
qemu_coroutine_yield();
|
||||
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
||||
index 0236936139..6cf8c1b9c8 100644
|
||||
--- a/qapi/block-core.json
|
||||
+++ b/qapi/block-core.json
|
||||
@@ -3909,6 +3909,9 @@
|
||||
#
|
||||
# @errno: error identifier (errno) to be returned; defaults to EIO
|
||||
#
|
||||
+# @delay-ns: request delay before completion in nanoseconds
|
||||
+# (default: 0, since: 11.1)
|
||||
+#
|
||||
# @sector: specifies the sector index which has to be affected in
|
||||
# order to actually trigger the event; defaults to "any sector"
|
||||
#
|
||||
@@ -3924,6 +3927,7 @@
|
||||
'*state': 'int',
|
||||
'*iotype': 'BlkdebugIOType',
|
||||
'*errno': 'int',
|
||||
+ '*delay-ns': 'int',
|
||||
'*sector': 'int',
|
||||
'*once': 'bool',
|
||||
'*immediately': 'bool' } }
|
||||
--
|
||||
2.52.0
|
||||
|
||||
203
kvm-block-Add-blk_co_start-end_request-and-BDRV_REQ_NO_Q.patch
Normal file
203
kvm-block-Add-blk_co_start-end_request-and-BDRV_REQ_NO_Q.patch
Normal file
@ -0,0 +1,203 @@
|
||||
From bd929a4dbcd20cb9f6314c867726b59e18254994 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 18:11:27 +0200
|
||||
Subject: [PATCH 2/8] block: Add blk_co_start/end_request() and
|
||||
BDRV_REQ_NO_QUEUE
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 562: ide: Fix deadlock between TRIM and drain [10.2.z]
|
||||
RH-Jira: RHEL-190702
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [2/8] 12df3f715235d07f3b45fa3ee56e5e8aa45e866c (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
If a device uses blk_inc/dec_in_flight() in order to build macro
|
||||
operations that involve multiple requests for the block layer and that
|
||||
need to be completed as a unit before the BlockBackend can be considered
|
||||
drained, it sets the stage for a deadlock: When a drain is requested,
|
||||
the inner request at the BlockBackend level will be queued in
|
||||
blk_wait_while_drained() and wait until the drained section ends, but at
|
||||
the same time, drain_begin can only return if the whole macro operation
|
||||
at the device level has completed.
|
||||
|
||||
Introduce a new interface to allow implementing the logic correctly:
|
||||
Instead of queueing individual requests, blk_co_start_request() calls
|
||||
blk_wait_while_drained() once at the beginning. The individual requests
|
||||
must then set BDRV_REQ_NO_QUEUE to avoid being queued and running into
|
||||
the deadlock; being wrapped in blk_co_start/end_request() makes sure
|
||||
that drain_begin waits for them and they don't sneak in when the
|
||||
BlockBackend is supposed to already be quiescent.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <20260421161132.99878-3-kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 34a67637767d3ed1ac813c44effe827bbfba5996)
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
block/block-backend.c | 38 +++++++++++++++++++++++--------
|
||||
include/block/block-common.h | 11 ++++++++-
|
||||
include/system/block-backend-io.h | 2 ++
|
||||
3 files changed, 41 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
||||
index d6df369188..a0f4c841da 100644
|
||||
--- a/block/block-backend.c
|
||||
+++ b/block/block-backend.c
|
||||
@@ -82,6 +82,7 @@ struct BlockBackend {
|
||||
QemuMutex queued_requests_lock; /* protects queued_requests */
|
||||
CoQueue queued_requests;
|
||||
bool disable_request_queuing; /* atomic */
|
||||
+ int start_request_count; /* atomic */
|
||||
|
||||
VMChangeStateEntry *vmsh;
|
||||
bool force_allow_inactivate;
|
||||
@@ -1306,10 +1307,16 @@ bool blk_in_drain(BlockBackend *blk)
|
||||
}
|
||||
|
||||
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
||||
-static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
|
||||
+static void coroutine_fn blk_wait_while_drained(BlockBackend *blk,
|
||||
+ BdrvRequestFlags flags)
|
||||
{
|
||||
assert(blk->in_flight > 0);
|
||||
|
||||
+ if (flags & BDRV_REQ_NO_QUEUE) {
|
||||
+ assert(qatomic_read(&blk->start_request_count));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (qatomic_read(&blk->quiesce_counter) &&
|
||||
!qatomic_read(&blk->disable_request_queuing)) {
|
||||
/*
|
||||
@@ -1335,7 +1342,7 @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
BlockDriverState *bs;
|
||||
IO_CODE();
|
||||
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, flags);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
/* Call blk_bs() only after waiting, the graph may have changed */
|
||||
@@ -1410,7 +1417,7 @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
BlockDriverState *bs;
|
||||
IO_CODE();
|
||||
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, flags);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
/* Call blk_bs() only after waiting, the graph may have changed */
|
||||
@@ -1523,6 +1530,19 @@ void blk_dec_in_flight(BlockBackend *blk)
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
+void coroutine_fn blk_co_start_request(BlockBackend *blk)
|
||||
+{
|
||||
+ blk_inc_in_flight(blk);
|
||||
+ blk_wait_while_drained(blk, 0);
|
||||
+ qatomic_inc(&blk->start_request_count);
|
||||
+}
|
||||
+
|
||||
+void blk_end_request(BlockBackend *blk)
|
||||
+{
|
||||
+ qatomic_dec(&blk->start_request_count);
|
||||
+ blk_dec_in_flight(blk);
|
||||
+}
|
||||
+
|
||||
static void error_callback_bh(void *opaque)
|
||||
{
|
||||
struct BlockBackendAIOCB *acb = opaque;
|
||||
@@ -1741,7 +1761,7 @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
||||
{
|
||||
IO_CODE();
|
||||
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, 0);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
if (!blk_co_is_available(blk)) {
|
||||
@@ -1788,7 +1808,7 @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
|
||||
int ret;
|
||||
IO_CODE();
|
||||
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, 0);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
ret = blk_check_byte_request(blk, offset, bytes);
|
||||
@@ -1834,7 +1854,7 @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
|
||||
static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
|
||||
{
|
||||
IO_CODE();
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, 0);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
if (!blk_co_is_available(blk)) {
|
||||
@@ -2009,7 +2029,7 @@ int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
|
||||
IO_CODE();
|
||||
|
||||
blk_inc_in_flight(blk); /* increase before waiting */
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, 0);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
if (!blk_is_available(blk)) {
|
||||
blk_dec_in_flight(blk);
|
||||
@@ -2034,7 +2054,7 @@ int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
|
||||
IO_CODE();
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, 0);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
ret = blk_check_byte_request(blk, offset, len);
|
||||
@@ -2058,7 +2078,7 @@ int coroutine_fn blk_co_zone_append(BlockBackend *blk, int64_t *offset,
|
||||
IO_CODE();
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
- blk_wait_while_drained(blk);
|
||||
+ blk_wait_while_drained(blk, flags);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
if (!blk_is_available(blk)) {
|
||||
blk_dec_in_flight(blk);
|
||||
diff --git a/include/block/block-common.h b/include/block/block-common.h
|
||||
index c8c626daea..895ea17541 100644
|
||||
--- a/include/block/block-common.h
|
||||
+++ b/include/block/block-common.h
|
||||
@@ -215,8 +215,17 @@ typedef enum {
|
||||
*/
|
||||
BDRV_REQ_NO_WAIT = 0x400,
|
||||
|
||||
+ /*
|
||||
+ * Used between blk_co_start_request() and blk_end_request() to avoid
|
||||
+ * that the request waits in a drained BlockBackend until the drained
|
||||
+ * section ends. Waiting would cause a deadlock because drain waits for
|
||||
+ * blk_end_request() to be called, but the request never completes
|
||||
+ * because it waits for the drain to end.
|
||||
+ */
|
||||
+ BDRV_REQ_NO_QUEUE = 0x800,
|
||||
+
|
||||
/* Mask of valid flags */
|
||||
- BDRV_REQ_MASK = 0x7ff,
|
||||
+ BDRV_REQ_MASK = 0xfff,
|
||||
} BdrvRequestFlags;
|
||||
|
||||
#define BDRV_O_NO_SHARE 0x0001 /* don't share permissions */
|
||||
diff --git a/include/system/block-backend-io.h b/include/system/block-backend-io.h
|
||||
index ba8dfcc7d0..59841e04a8 100644
|
||||
--- a/include/system/block-backend-io.h
|
||||
+++ b/include/system/block-backend-io.h
|
||||
@@ -71,6 +71,8 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
|
||||
|
||||
void blk_inc_in_flight(BlockBackend *blk);
|
||||
void blk_dec_in_flight(BlockBackend *blk);
|
||||
+void coroutine_fn blk_co_start_request(BlockBackend *blk);
|
||||
+void blk_end_request(BlockBackend *blk);
|
||||
|
||||
bool coroutine_fn GRAPH_RDLOCK blk_co_is_inserted(BlockBackend *blk);
|
||||
bool co_wrapper_mixed_bdrv_rdlock blk_is_inserted(BlockBackend *blk);
|
||||
--
|
||||
2.52.0
|
||||
|
||||
174
kvm-block-Add-flags-parameter-to-blk_-_pdiscard.patch
Normal file
174
kvm-block-Add-flags-parameter-to-blk_-_pdiscard.patch
Normal file
@ -0,0 +1,174 @@
|
||||
From f834c37186b266b515c3f7e6b15a5e87e153f699 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 18:11:28 +0200
|
||||
Subject: [PATCH 3/8] block: Add flags parameter to blk_*_pdiscard()
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 562: ide: Fix deadlock between TRIM and drain [10.2.z]
|
||||
RH-Jira: RHEL-190702
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [3/8] 6ce7ccfc577d41eda1283271dd5ee7913a1266c5 (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
All existing callers pass 0, but we need a way to pass BDRV_REQ_NO_QUEUE
|
||||
for discard requests.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <20260421161132.99878-4-kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 53074ba0330ae8831abbae2521c012e1d9072ed3)
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
block/block-backend.c | 11 ++++++-----
|
||||
block/export/virtio-blk-handler.c | 2 +-
|
||||
block/mirror.c | 4 ++--
|
||||
include/system/block-backend-io.h | 4 ++--
|
||||
nbd/server.c | 2 +-
|
||||
qemu-io-cmds.c | 2 +-
|
||||
tests/unit/test-block-iothread.c | 4 ++--
|
||||
7 files changed, 15 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
||||
index a0f4c841da..d97b26b743 100644
|
||||
--- a/block/block-backend.c
|
||||
+++ b/block/block-backend.c
|
||||
@@ -1803,12 +1803,13 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
|
||||
|
||||
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
||||
static int coroutine_fn
|
||||
-blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
|
||||
+blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes,
|
||||
+ BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
IO_CODE();
|
||||
|
||||
- blk_wait_while_drained(blk, 0);
|
||||
+ blk_wait_while_drained(blk, flags);
|
||||
GRAPH_RDLOCK_GUARD();
|
||||
|
||||
ret = blk_check_byte_request(blk, offset, bytes);
|
||||
@@ -1824,7 +1825,7 @@ static void coroutine_fn blk_aio_pdiscard_entry(void *opaque)
|
||||
BlkAioEmAIOCB *acb = opaque;
|
||||
BlkRwCo *rwco = &acb->rwco;
|
||||
|
||||
- rwco->ret = blk_co_do_pdiscard(rwco->blk, rwco->offset, acb->bytes);
|
||||
+ rwco->ret = blk_co_do_pdiscard(rwco->blk, rwco->offset, acb->bytes, 0);
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
|
||||
@@ -1838,13 +1839,13 @@ BlockAIOCB *blk_aio_pdiscard(BlockBackend *blk,
|
||||
}
|
||||
|
||||
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
|
||||
- int64_t bytes)
|
||||
+ int64_t bytes, BdrvRequestFlags flags)
|
||||
{
|
||||
int ret;
|
||||
IO_OR_GS_CODE();
|
||||
|
||||
blk_inc_in_flight(blk);
|
||||
- ret = blk_co_do_pdiscard(blk, offset, bytes);
|
||||
+ ret = blk_co_do_pdiscard(blk, offset, bytes, flags);
|
||||
blk_dec_in_flight(blk);
|
||||
|
||||
return ret;
|
||||
diff --git a/block/export/virtio-blk-handler.c b/block/export/virtio-blk-handler.c
|
||||
index bc1cec6757..b82baae553 100644
|
||||
--- a/block/export/virtio-blk-handler.c
|
||||
+++ b/block/export/virtio-blk-handler.c
|
||||
@@ -121,7 +121,7 @@ virtio_blk_discard_write_zeroes(VirtioBlkHandler *handler, struct iovec *iov,
|
||||
}
|
||||
|
||||
if (blk_co_pdiscard(blk, sector << VIRTIO_BLK_SECTOR_BITS,
|
||||
- bytes) == 0) {
|
||||
+ bytes, 0) == 0) {
|
||||
return VIRTIO_BLK_S_OK;
|
||||
}
|
||||
}
|
||||
diff --git a/block/mirror.c b/block/mirror.c
|
||||
index f01be99b55..c87f1e205b 100644
|
||||
--- a/block/mirror.c
|
||||
+++ b/block/mirror.c
|
||||
@@ -454,7 +454,7 @@ static void coroutine_fn mirror_co_discard(void *opaque)
|
||||
*op->bytes_handled = op->bytes;
|
||||
op->is_in_flight = true;
|
||||
|
||||
- ret = blk_co_pdiscard(op->s->target, op->offset, op->bytes);
|
||||
+ ret = blk_co_pdiscard(op->s->target, op->offset, op->bytes, 0);
|
||||
mirror_write_complete(op, ret);
|
||||
}
|
||||
|
||||
@@ -1527,7 +1527,7 @@ do_sync_target_write(MirrorBlockJob *job, MirrorMethod method,
|
||||
zero_bitmap_end - zero_bitmap_offset);
|
||||
}
|
||||
assert(!qiov);
|
||||
- ret = blk_co_pdiscard(job->target, offset, bytes);
|
||||
+ ret = blk_co_pdiscard(job->target, offset, bytes, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
diff --git a/include/system/block-backend-io.h b/include/system/block-backend-io.h
|
||||
index 59841e04a8..91c48299b7 100644
|
||||
--- a/include/system/block-backend-io.h
|
||||
+++ b/include/system/block-backend-io.h
|
||||
@@ -217,9 +217,9 @@ int co_wrapper_mixed blk_zone_append(BlockBackend *blk, int64_t *offset,
|
||||
BdrvRequestFlags flags);
|
||||
|
||||
int co_wrapper_mixed blk_pdiscard(BlockBackend *blk, int64_t offset,
|
||||
- int64_t bytes);
|
||||
+ int64_t bytes, BdrvRequestFlags flags);
|
||||
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
|
||||
- int64_t bytes);
|
||||
+ int64_t bytes, BdrvRequestFlags flags);
|
||||
|
||||
int co_wrapper_mixed blk_flush(BlockBackend *blk);
|
||||
int coroutine_fn blk_co_flush(BlockBackend *blk);
|
||||
diff --git a/nbd/server.c b/nbd/server.c
|
||||
index d242be9811..c72dee7a3b 100644
|
||||
--- a/nbd/server.c
|
||||
+++ b/nbd/server.c
|
||||
@@ -2982,7 +2982,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
|
||||
"flush failed", errp);
|
||||
|
||||
case NBD_CMD_TRIM:
|
||||
- ret = blk_co_pdiscard(exp->common.blk, request->from, request->len);
|
||||
+ ret = blk_co_pdiscard(exp->common.blk, request->from, request->len, 0);
|
||||
if (ret >= 0 && request->flags & NBD_CMD_FLAG_FUA) {
|
||||
ret = blk_co_flush(exp->common.blk);
|
||||
}
|
||||
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
|
||||
index 13e0330162..f6d077908f 100644
|
||||
--- a/qemu-io-cmds.c
|
||||
+++ b/qemu-io-cmds.c
|
||||
@@ -2201,7 +2201,7 @@ static int discard_f(BlockBackend *blk, int argc, char **argv)
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t1);
|
||||
- ret = blk_pdiscard(blk, offset, bytes);
|
||||
+ ret = blk_pdiscard(blk, offset, bytes, 0);
|
||||
clock_gettime(CLOCK_MONOTONIC, &t2);
|
||||
|
||||
if (ret < 0) {
|
||||
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
|
||||
index e26b3be593..5273ff235a 100644
|
||||
--- a/tests/unit/test-block-iothread.c
|
||||
+++ b/tests/unit/test-block-iothread.c
|
||||
@@ -270,11 +270,11 @@ static void test_sync_op_blk_pdiscard(BlockBackend *blk)
|
||||
int ret;
|
||||
|
||||
/* Early success: UNMAP not supported */
|
||||
- ret = blk_pdiscard(blk, 0, 512);
|
||||
+ ret = blk_pdiscard(blk, 0, 512, 0);
|
||||
g_assert_cmpint(ret, ==, 0);
|
||||
|
||||
/* Early error: Negative offset */
|
||||
- ret = blk_pdiscard(blk, -2, 512);
|
||||
+ ret = blk_pdiscard(blk, -2, 512, 0);
|
||||
g_assert_cmpint(ret, ==, -EIO);
|
||||
}
|
||||
|
||||
--
|
||||
2.52.0
|
||||
|
||||
103
kvm-block-use-pwrite_zeroes_alignment-when-writing-first.patch
Normal file
103
kvm-block-use-pwrite_zeroes_alignment-when-writing-first.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From c92790705ea64e29191ad00bd61e1ad13011c6b4 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Tue, 7 Oct 2025 10:16:59 -0400
|
||||
Subject: [PATCH 2/3] block: use pwrite_zeroes_alignment when writing first
|
||||
sector
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 565: block: Fix image creation on storage with 4k sector size
|
||||
RH-Jira: RHEL-207389
|
||||
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-Commit: [2/3] 1854afab367accbe5a4ffdcbb7cea180595b6bdc (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
Since commit 5634622bcb33 ("file-posix: allow BLKZEROOUT with -t
|
||||
writeback"), qemu-img create errors out on a Linux loop block device
|
||||
with a 4 KB sector size:
|
||||
|
||||
# dd if=/dev/zero of=blockfile bs=1M count=1024
|
||||
# losetup --sector-size 4096 /dev/loop0 blockfile
|
||||
# qemu-img create -f raw /dev/loop0 1G
|
||||
Formatting '/dev/loop0', fmt=raw size=1073741824
|
||||
qemu-img: /dev/loop0: Failed to clear the new image's first sector: Invalid argument
|
||||
|
||||
Use the pwrite_zeroes_alignment block limit to avoid misaligned
|
||||
fallocate(2) or ioctl(BLKZEROOUT) in the block/file-posix.c block
|
||||
driver.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Fixes: 5634622bcb33 ("file-posix: allow BLKZEROOUT with -t writeback")
|
||||
Reported-by: Jean-Louis Dupond <jean-louis@dupond.be>
|
||||
Buglink: https://gitlab.com/qemu-project/qemu/-/issues/3127
|
||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-ID: <20251007141700.71891-3-stefanha@redhat.com>
|
||||
Tested-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Reviewed-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit d704a13d2c025779bc91d04e127427347ddcf3b3)
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
block.c | 3 ++-
|
||||
block/block-backend.c | 11 +++++++++++
|
||||
include/system/block-backend-io.h | 1 +
|
||||
3 files changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index 8848e9a7ed..be77e03904 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -606,12 +606,13 @@ create_file_fallback_zero_first_sector(BlockBackend *blk,
|
||||
int64_t current_size,
|
||||
Error **errp)
|
||||
{
|
||||
+ uint32_t alignment = blk_get_pwrite_zeroes_alignment(blk);
|
||||
int64_t bytes_to_clear;
|
||||
int ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
- bytes_to_clear = MIN(current_size, BDRV_SECTOR_SIZE);
|
||||
+ bytes_to_clear = MIN(current_size, MAX(BDRV_SECTOR_SIZE, alignment));
|
||||
if (bytes_to_clear) {
|
||||
ret = blk_co_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
|
||||
if (ret < 0) {
|
||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
||||
index d97b26b743..850f2ecec2 100644
|
||||
--- a/block/block-backend.c
|
||||
+++ b/block/block-backend.c
|
||||
@@ -2326,6 +2326,17 @@ uint32_t blk_get_request_alignment(BlockBackend *blk)
|
||||
return bs ? bs->bl.request_alignment : BDRV_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
+/* Returns the optimal write zeroes alignment, in bytes; guaranteed nonzero */
|
||||
+uint32_t blk_get_pwrite_zeroes_alignment(BlockBackend *blk)
|
||||
+{
|
||||
+ BlockDriverState *bs = blk_bs(blk);
|
||||
+ IO_CODE();
|
||||
+ if (!bs) {
|
||||
+ return BDRV_SECTOR_SIZE;
|
||||
+ }
|
||||
+ return bs->bl.pwrite_zeroes_alignment ?: bs->bl.request_alignment;
|
||||
+}
|
||||
+
|
||||
/* Returns the maximum hardware transfer length, in bytes; guaranteed nonzero */
|
||||
uint64_t blk_get_max_hw_transfer(BlockBackend *blk)
|
||||
{
|
||||
diff --git a/include/system/block-backend-io.h b/include/system/block-backend-io.h
|
||||
index 91c48299b7..fd84723d9d 100644
|
||||
--- a/include/system/block-backend-io.h
|
||||
+++ b/include/system/block-backend-io.h
|
||||
@@ -118,6 +118,7 @@ BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
|
||||
void *opaque, int ret);
|
||||
|
||||
uint32_t blk_get_request_alignment(BlockBackend *blk);
|
||||
+uint32_t blk_get_pwrite_zeroes_alignment(BlockBackend *blk);
|
||||
uint32_t blk_get_max_transfer(BlockBackend *blk);
|
||||
uint64_t blk_get_max_hw_transfer(BlockBackend *blk);
|
||||
|
||||
--
|
||||
2.52.0
|
||||
|
||||
65
kvm-file-posix-populate-pwrite_zeroes_alignment.patch
Normal file
65
kvm-file-posix-populate-pwrite_zeroes_alignment.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From 9aa4988b7506ff56f7c02ac0794f29b0766adb6f Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Tue, 7 Oct 2025 10:16:58 -0400
|
||||
Subject: [PATCH 1/3] file-posix: populate pwrite_zeroes_alignment
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 565: block: Fix image creation on storage with 4k sector size
|
||||
RH-Jira: RHEL-207389
|
||||
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-Commit: [1/3] dd57fecd1f1d62be600451c47efb061925e89154 (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
Linux block devices require write zeroes alignment whereas files do not.
|
||||
|
||||
It may come as a surprise that block devices opened in buffered I/O mode
|
||||
require the alignment for write zeroes requests although normal
|
||||
read/write requests do not.
|
||||
|
||||
Therefore it is necessary to populate the pwrite_zeroes_alignment field.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-ID: <20251007141700.71891-2-stefanha@redhat.com>
|
||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
|
||||
Tested-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Reviewed-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 98e788b91ad037193b1fb375561ef7e0fef3c2fd)
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
block/file-posix.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/block/file-posix.c b/block/file-posix.c
|
||||
index ffca37130b..0129413273 100644
|
||||
--- a/block/file-posix.c
|
||||
+++ b/block/file-posix.c
|
||||
@@ -1607,6 +1607,22 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
|
||||
bs->bl.pdiscard_alignment = dalign;
|
||||
}
|
||||
+
|
||||
+#ifdef __linux__
|
||||
+ /*
|
||||
+ * Linux requires logical block size alignment for write zeroes even
|
||||
+ * when normal reads/writes do not require alignment.
|
||||
+ */
|
||||
+ if (!s->needs_alignment) {
|
||||
+ ret = probe_logical_blocksize(s->fd,
|
||||
+ &bs->bl.pwrite_zeroes_alignment);
|
||||
+ if (ret < 0) {
|
||||
+ error_setg_errno(errp, -ret,
|
||||
+ "Failed to probe logical block size");
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+#endif /* __linux__ */
|
||||
}
|
||||
|
||||
raw_refresh_zoned_limits(bs, &st, errp);
|
||||
--
|
||||
2.52.0
|
||||
|
||||
163
kvm-ide-Clean-up-ide_trim_co_entry-to-be-idiomatic-corou.patch
Normal file
163
kvm-ide-Clean-up-ide_trim_co_entry-to-be-idiomatic-corou.patch
Normal file
@ -0,0 +1,163 @@
|
||||
From e08abed8efc20906c2aeabeadd36f4f3e3dd3142 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 18:11:30 +0200
|
||||
Subject: [PATCH 5/8] ide: Clean up ide_trim_co_entry() to be idiomatic
|
||||
coroutine code
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 562: ide: Fix deadlock between TRIM and drain [10.2.z]
|
||||
RH-Jira: RHEL-190702
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [5/8] 8ecbfb819ce278daf17904c328464a474ba9c4bc (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
The previous commit did a minimal conversion of the callback based state
|
||||
machine for TRIM to a coroutine in order to fix a bug. Refactor it to
|
||||
actually look like normal coroutine based code, which improves its
|
||||
readability.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <20260421161132.99878-6-kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit c1c71a7e167fdabaa9827d00c0be3aeafebdd921)
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
hw/ide/core.c | 87 +++++++++++++++++++++++----------------------------
|
||||
1 file changed, 39 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/hw/ide/core.c b/hw/ide/core.c
|
||||
index 82c3ada14a..8b9f06547b 100644
|
||||
--- a/hw/ide/core.c
|
||||
+++ b/hw/ide/core.c
|
||||
@@ -420,18 +420,15 @@ typedef struct TrimAIOCB {
|
||||
QEMUBH *bh;
|
||||
int ret;
|
||||
QEMUIOVector *qiov;
|
||||
- int i, j;
|
||||
+ bool canceled;
|
||||
} TrimAIOCB;
|
||||
|
||||
static void trim_aio_cancel(BlockAIOCB *acb)
|
||||
{
|
||||
TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
|
||||
|
||||
- /* Exit the loop so ide_issue_trim_cb will not continue */
|
||||
- iocb->j = iocb->qiov->niov - 1;
|
||||
- iocb->i = (iocb->qiov->iov[iocb->j].iov_len / 8) - 1;
|
||||
-
|
||||
- iocb->ret = -ECANCELED;
|
||||
+ /* Exit the loop so ide_trim_co_entry will not continue */
|
||||
+ iocb->canceled = true;
|
||||
}
|
||||
|
||||
static const AIOCBInfo trim_aiocb_info = {
|
||||
@@ -458,60 +455,55 @@ static void coroutine_fn ide_trim_co_entry(void *opaque)
|
||||
{
|
||||
TrimAIOCB *iocb = opaque;
|
||||
IDEState *s = iocb->s;
|
||||
- int ret = 0;
|
||||
+ int i, j;
|
||||
+ int ret;
|
||||
|
||||
/* Paired with blk_end_request in ide_trim_bh_cb() */
|
||||
blk_co_start_request(s->blk);
|
||||
|
||||
-loop:
|
||||
- if (iocb->i >= 0) {
|
||||
- if (ret >= 0) {
|
||||
- block_acct_done(blk_get_stats(s->blk), &s->acct);
|
||||
- } else {
|
||||
- block_acct_failed(blk_get_stats(s->blk), &s->acct);
|
||||
- }
|
||||
- }
|
||||
+ for (j = 0; j < iocb->qiov->niov; j++) {
|
||||
+ for (i = 0; i < iocb->qiov->iov[j].iov_len / 8; i++) {
|
||||
+ uint64_t *buffer = iocb->qiov->iov[j].iov_base;
|
||||
|
||||
- if (ret >= 0) {
|
||||
- while (iocb->j < iocb->qiov->niov) {
|
||||
- int j = iocb->j;
|
||||
- while (++iocb->i < iocb->qiov->iov[j].iov_len / 8) {
|
||||
- int i = iocb->i;
|
||||
- uint64_t *buffer = iocb->qiov->iov[j].iov_base;
|
||||
+ /* 6-byte LBA + 2-byte range per entry */
|
||||
+ uint64_t entry = le64_to_cpu(buffer[i]);
|
||||
+ uint64_t sector = entry & 0x0000ffffffffffffULL;
|
||||
+ uint16_t count = entry >> 48;
|
||||
|
||||
- /* 6-byte LBA + 2-byte range per entry */
|
||||
- uint64_t entry = le64_to_cpu(buffer[i]);
|
||||
- uint64_t sector = entry & 0x0000ffffffffffffULL;
|
||||
- uint16_t count = entry >> 48;
|
||||
+ if (count == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- if (count == 0) {
|
||||
- continue;
|
||||
- }
|
||||
+ if (iocb->canceled) {
|
||||
+ iocb->ret = -ECANCELED;
|
||||
+ goto done;
|
||||
+ }
|
||||
|
||||
- if (!ide_sect_range_ok(s, sector, count)) {
|
||||
- block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_UNMAP);
|
||||
- iocb->ret = -EINVAL;
|
||||
- goto done;
|
||||
- }
|
||||
+ if (!ide_sect_range_ok(s, sector, count)) {
|
||||
+ block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_UNMAP);
|
||||
+ iocb->ret = -EINVAL;
|
||||
+ goto done;
|
||||
+ }
|
||||
|
||||
- block_acct_start(blk_get_stats(s->blk), &s->acct,
|
||||
- count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
|
||||
+ block_acct_start(blk_get_stats(s->blk), &s->acct,
|
||||
+ count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
|
||||
|
||||
- /* Got an entry! Submit and exit. */
|
||||
- ret = blk_co_pdiscard(s->blk,
|
||||
- sector << BDRV_SECTOR_BITS,
|
||||
- count << BDRV_SECTOR_BITS,
|
||||
- BDRV_REQ_NO_QUEUE);
|
||||
- goto loop;
|
||||
+ /* Got an entry! Submit and exit. */
|
||||
+ ret = blk_co_pdiscard(s->blk,
|
||||
+ sector << BDRV_SECTOR_BITS,
|
||||
+ count << BDRV_SECTOR_BITS,
|
||||
+ BDRV_REQ_NO_QUEUE);
|
||||
+ if (ret >= 0) {
|
||||
+ block_acct_done(blk_get_stats(s->blk), &s->acct);
|
||||
+ } else {
|
||||
+ iocb->ret = ret;
|
||||
+ block_acct_failed(blk_get_stats(s->blk), &s->acct);
|
||||
+ goto done;
|
||||
}
|
||||
-
|
||||
- iocb->j++;
|
||||
- iocb->i = -1;
|
||||
}
|
||||
- } else {
|
||||
- iocb->ret = ret;
|
||||
}
|
||||
|
||||
+ iocb->ret = 0;
|
||||
done:
|
||||
if (iocb->bh) {
|
||||
replay_bh_schedule_event(iocb->bh);
|
||||
@@ -533,8 +525,7 @@ BlockAIOCB *ide_issue_trim(
|
||||
&DEVICE(dev)->mem_reentrancy_guard);
|
||||
iocb->ret = 0;
|
||||
iocb->qiov = qiov;
|
||||
- iocb->i = -1;
|
||||
- iocb->j = 0;
|
||||
+ iocb->canceled = false;
|
||||
|
||||
co = qemu_coroutine_create(ide_trim_co_entry, iocb);
|
||||
aio_co_enter(qemu_get_current_aio_context(), co);
|
||||
--
|
||||
2.52.0
|
||||
|
||||
141
kvm-ide-Minimal-fix-for-deadlock-between-TRIM-and-drain.patch
Normal file
141
kvm-ide-Minimal-fix-for-deadlock-between-TRIM-and-drain.patch
Normal file
@ -0,0 +1,141 @@
|
||||
From 1af428a8371e7c95be02569a551095a93f17a4ac Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 18:11:29 +0200
|
||||
Subject: [PATCH 4/8] ide: Minimal fix for deadlock between TRIM and drain
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 562: ide: Fix deadlock between TRIM and drain [10.2.z]
|
||||
RH-Jira: RHEL-190702
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [4/8] 339ddf749cae0dace22058df1998a80fa570d4b4 (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
The implementation of TRIM in IDE can chain multiple discard requests
|
||||
and uses blk_inc/dec_in_flight() to make sure that the whole TRIM
|
||||
operation has completed when the device needs to be quiescent (e.g. for
|
||||
the drain when performing an IDE reset, it would be bad if an IDE
|
||||
request like TRIM were still in flight).
|
||||
|
||||
The problem is that each drain request calls blk_wait_while_drained()
|
||||
and when draining, it waits until the drained section ends. At the same
|
||||
time, drain_begin can only return if the whole TRIM operation has
|
||||
completed. This is a classic deadlock.
|
||||
|
||||
Use blk_co_start/end_request() and BDRV_REQ_NO_QUEUE to avoid the
|
||||
problem. This requires moving the TRIM state machine to a coroutine.
|
||||
This commit does the minimal conversion so that we do have a coroutine
|
||||
that works for the fix, but it still looks much like a callback-based
|
||||
implementation. This will be cleaned up in the next patch.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Fixes: 7e5cdb345f77 ('ide: Increment BB in-flight counter for TRIM BH')
|
||||
Buglink: https://redhat.atlassian.net/browse/RHEL-121686
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <20260421161132.99878-5-kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 095c08a7ba68cabaa6e0ce7a8a0804a949542c4c)
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
hw/ide/core.c | 37 ++++++++++++++++++-------------------
|
||||
1 file changed, 18 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/hw/ide/core.c b/hw/ide/core.c
|
||||
index b14983ec54..82c3ada14a 100644
|
||||
--- a/hw/ide/core.c
|
||||
+++ b/hw/ide/core.c
|
||||
@@ -420,7 +420,6 @@ typedef struct TrimAIOCB {
|
||||
QEMUBH *bh;
|
||||
int ret;
|
||||
QEMUIOVector *qiov;
|
||||
- BlockAIOCB *aiocb;
|
||||
int i, j;
|
||||
} TrimAIOCB;
|
||||
|
||||
@@ -433,11 +432,6 @@ static void trim_aio_cancel(BlockAIOCB *acb)
|
||||
iocb->i = (iocb->qiov->iov[iocb->j].iov_len / 8) - 1;
|
||||
|
||||
iocb->ret = -ECANCELED;
|
||||
-
|
||||
- if (iocb->aiocb) {
|
||||
- blk_aio_cancel_async(iocb->aiocb);
|
||||
- iocb->aiocb = NULL;
|
||||
- }
|
||||
}
|
||||
|
||||
static const AIOCBInfo trim_aiocb_info = {
|
||||
@@ -456,15 +450,20 @@ static void ide_trim_bh_cb(void *opaque)
|
||||
iocb->bh = NULL;
|
||||
qemu_aio_unref(iocb);
|
||||
|
||||
- /* Paired with an increment in ide_issue_trim() */
|
||||
- blk_dec_in_flight(blk);
|
||||
+ /* Paired with blk_co_start_request in ide_trim_co_entry() */
|
||||
+ blk_end_request(blk);
|
||||
}
|
||||
|
||||
-static void ide_issue_trim_cb(void *opaque, int ret)
|
||||
+static void coroutine_fn ide_trim_co_entry(void *opaque)
|
||||
{
|
||||
TrimAIOCB *iocb = opaque;
|
||||
IDEState *s = iocb->s;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* Paired with blk_end_request in ide_trim_bh_cb() */
|
||||
+ blk_co_start_request(s->blk);
|
||||
|
||||
+loop:
|
||||
if (iocb->i >= 0) {
|
||||
if (ret >= 0) {
|
||||
block_acct_done(blk_get_stats(s->blk), &s->acct);
|
||||
@@ -499,11 +498,11 @@ static void ide_issue_trim_cb(void *opaque, int ret)
|
||||
count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
|
||||
|
||||
/* Got an entry! Submit and exit. */
|
||||
- iocb->aiocb = blk_aio_pdiscard(s->blk,
|
||||
- sector << BDRV_SECTOR_BITS,
|
||||
- count << BDRV_SECTOR_BITS,
|
||||
- ide_issue_trim_cb, opaque);
|
||||
- return;
|
||||
+ ret = blk_co_pdiscard(s->blk,
|
||||
+ sector << BDRV_SECTOR_BITS,
|
||||
+ count << BDRV_SECTOR_BITS,
|
||||
+ BDRV_REQ_NO_QUEUE);
|
||||
+ goto loop;
|
||||
}
|
||||
|
||||
iocb->j++;
|
||||
@@ -514,7 +513,6 @@ static void ide_issue_trim_cb(void *opaque, int ret)
|
||||
}
|
||||
|
||||
done:
|
||||
- iocb->aiocb = NULL;
|
||||
if (iocb->bh) {
|
||||
replay_bh_schedule_event(iocb->bh);
|
||||
}
|
||||
@@ -527,9 +525,7 @@ BlockAIOCB *ide_issue_trim(
|
||||
IDEState *s = opaque;
|
||||
IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master;
|
||||
TrimAIOCB *iocb;
|
||||
-
|
||||
- /* Paired with a decrement in ide_trim_bh_cb() */
|
||||
- blk_inc_in_flight(s->blk);
|
||||
+ Coroutine *co;
|
||||
|
||||
iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque);
|
||||
iocb->s = s;
|
||||
@@ -539,7 +535,10 @@ BlockAIOCB *ide_issue_trim(
|
||||
iocb->qiov = qiov;
|
||||
iocb->i = -1;
|
||||
iocb->j = 0;
|
||||
- ide_issue_trim_cb(iocb, 0);
|
||||
+
|
||||
+ co = qemu_coroutine_create(ide_trim_co_entry, iocb);
|
||||
+ aio_co_enter(qemu_get_current_aio_context(), co);
|
||||
+
|
||||
return &iocb->common;
|
||||
}
|
||||
|
||||
--
|
||||
2.52.0
|
||||
|
||||
91
kvm-ide-test-Factor-out-wait_dma_completion.patch
Normal file
91
kvm-ide-test-Factor-out-wait_dma_completion.patch
Normal file
@ -0,0 +1,91 @@
|
||||
From 16cf591d59298ccc7cc1fe55427f2e2066d852d1 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 18:11:31 +0200
|
||||
Subject: [PATCH 6/8] ide-test: Factor out wait_dma_completion()
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 562: ide: Fix deadlock between TRIM and drain [10.2.z]
|
||||
RH-Jira: RHEL-190702
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [6/8] 52ad17b4233e8589241928f2cbc8def83a0863de (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <20260421161132.99878-7-kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 92854c9c7539bdbf4f9c1abb33dd3ba59ff91e58)
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
tests/qtest/ide-test.c | 48 +++++++++++++++++++++++++-----------------
|
||||
1 file changed, 29 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c
|
||||
index ceee444a9e..c6dcb2c074 100644
|
||||
--- a/tests/qtest/ide-test.c
|
||||
+++ b/tests/qtest/ide-test.c
|
||||
@@ -200,6 +200,34 @@ static uint64_t trim_range_le(uint64_t sector, uint16_t count)
|
||||
return cpu_to_le64(((uint64_t)count << 48) + sector);
|
||||
}
|
||||
|
||||
+static uint8_t wait_dma_completion(QTestState *qts, QPCIDevice *dev,
|
||||
+ QPCIBar bmdma_bar, QPCIBar ide_bar)
|
||||
+{
|
||||
+ uint8_t status;
|
||||
+
|
||||
+ /* Wait for the DMA transfer to complete */
|
||||
+ do {
|
||||
+ status = qpci_io_readb(dev, bmdma_bar, bmreg_status);
|
||||
+ } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);
|
||||
+
|
||||
+ g_assert_cmpint(qtest_get_irq(qts, IDE_PRIMARY_IRQ), ==,
|
||||
+ !!(status & BM_STS_INTR));
|
||||
+
|
||||
+ /* Check IDE status code */
|
||||
+ assert_bit_set(qpci_io_readb(dev, ide_bar, reg_status), DRDY);
|
||||
+ assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), BSY | DRQ);
|
||||
+
|
||||
+ /* Reading the status register clears the IRQ */
|
||||
+ g_assert(!qtest_get_irq(qts, IDE_PRIMARY_IRQ));
|
||||
+
|
||||
+ /* Stop DMA transfer if still active */
|
||||
+ if (status & BM_STS_ACTIVE) {
|
||||
+ qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
|
||||
+ }
|
||||
+
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
static int send_dma_request(QTestState *qts, int cmd, uint64_t sector,
|
||||
int nb_sectors, PrdtEntry *prdt, int prdt_entries,
|
||||
void(*post_exec)(QPCIDevice *dev, QPCIBar ide_bar,
|
||||
@@ -280,25 +308,7 @@ static int send_dma_request(QTestState *qts, int cmd, uint64_t sector,
|
||||
qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
|
||||
}
|
||||
|
||||
- /* Wait for the DMA transfer to complete */
|
||||
- do {
|
||||
- status = qpci_io_readb(dev, bmdma_bar, bmreg_status);
|
||||
- } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE);
|
||||
-
|
||||
- g_assert_cmpint(qtest_get_irq(qts, IDE_PRIMARY_IRQ), ==,
|
||||
- !!(status & BM_STS_INTR));
|
||||
-
|
||||
- /* Check IDE status code */
|
||||
- assert_bit_set(qpci_io_readb(dev, ide_bar, reg_status), DRDY);
|
||||
- assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), BSY | DRQ);
|
||||
-
|
||||
- /* Reading the status register clears the IRQ */
|
||||
- g_assert(!qtest_get_irq(qts, IDE_PRIMARY_IRQ));
|
||||
-
|
||||
- /* Stop DMA transfer if still active */
|
||||
- if (status & BM_STS_ACTIVE) {
|
||||
- qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
|
||||
- }
|
||||
+ status = wait_dma_completion(qts, dev, bmdma_bar, ide_bar);
|
||||
|
||||
free_pci_device(dev);
|
||||
|
||||
--
|
||||
2.52.0
|
||||
|
||||
181
kvm-ide-test-Test-reset-during-TRIM.patch
Normal file
181
kvm-ide-test-Test-reset-during-TRIM.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From ffd0b4cfc9ad6b40eecc982c971bab08d8a3df4d Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Tue, 21 Apr 2026 18:11:32 +0200
|
||||
Subject: [PATCH 7/8] ide-test: Test reset during TRIM
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 562: ide: Fix deadlock between TRIM and drain [10.2.z]
|
||||
RH-Jira: RHEL-190702
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [7/8] e74433de82754973428769f19fb387acc34b0455 (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
This is a regression test for the bug fixed in the previous commits, a
|
||||
deadlock between the drain issued by an IDE reset and the TRIM state
|
||||
machine.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <20260421161132.99878-8-kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 2fa24e9755994f76f08ea2452215eb50f26f4c21)
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
tests/qtest/ide-test.c | 95 ++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 87 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c
|
||||
index c6dcb2c074..721e78170b 100644
|
||||
--- a/tests/qtest/ide-test.c
|
||||
+++ b/tests/qtest/ide-test.c
|
||||
@@ -41,8 +41,11 @@
|
||||
#define IDE_PCI_FUNC 1
|
||||
|
||||
#define IDE_BASE 0x1f0
|
||||
+#define IDE_BASE2 0x3f6
|
||||
#define IDE_PRIMARY_IRQ 14
|
||||
|
||||
+#define IDE_CTRL_RESET 0x04
|
||||
+
|
||||
#define ATAPI_BLOCK_SIZE 2048
|
||||
|
||||
/* How many bytes to receive via ATAPI PIO at one time.
|
||||
@@ -99,6 +102,7 @@ enum {
|
||||
|
||||
CMDF_ABORT = 0x100,
|
||||
CMDF_NO_BM = 0x200,
|
||||
+ CMDF_NO_WAIT = 0x400,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -228,21 +232,21 @@ static uint8_t wait_dma_completion(QTestState *qts, QPCIDevice *dev,
|
||||
return status;
|
||||
}
|
||||
|
||||
-static int send_dma_request(QTestState *qts, int cmd, uint64_t sector,
|
||||
- int nb_sectors, PrdtEntry *prdt, int prdt_entries,
|
||||
- void(*post_exec)(QPCIDevice *dev, QPCIBar ide_bar,
|
||||
- uint64_t sector, int nb_sectors))
|
||||
+static int send_dma_request_dev(QTestState *qts, QPCIDevice *dev,
|
||||
+ QPCIBar bmdma_bar, QPCIBar ide_bar, int cmd,
|
||||
+ uint64_t sector, int nb_sectors,
|
||||
+ PrdtEntry *prdt, int prdt_entries,
|
||||
+ void(*post_exec)(QPCIDevice *dev,
|
||||
+ QPCIBar ide_bar,
|
||||
+ uint64_t sector,
|
||||
+ int nb_sectors))
|
||||
{
|
||||
- QPCIDevice *dev;
|
||||
- QPCIBar bmdma_bar, ide_bar;
|
||||
uintptr_t guest_prdt;
|
||||
size_t len;
|
||||
bool from_dev;
|
||||
uint8_t status;
|
||||
int flags;
|
||||
|
||||
- dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
|
||||
-
|
||||
flags = cmd & ~0xff;
|
||||
cmd &= 0xff;
|
||||
|
||||
@@ -308,8 +312,28 @@ static int send_dma_request(QTestState *qts, int cmd, uint64_t sector,
|
||||
qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
|
||||
}
|
||||
|
||||
+ if (flags & CMDF_NO_WAIT) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
status = wait_dma_completion(qts, dev, bmdma_bar, ide_bar);
|
||||
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+static int send_dma_request(QTestState *qts, int cmd, uint64_t sector,
|
||||
+ int nb_sectors, PrdtEntry *prdt, int prdt_entries,
|
||||
+ void(*post_exec)(QPCIDevice *dev, QPCIBar ide_bar,
|
||||
+ uint64_t sector, int nb_sectors))
|
||||
+{
|
||||
+ QPCIDevice *dev;
|
||||
+ QPCIBar bmdma_bar, ide_bar;
|
||||
+ uint8_t status;
|
||||
+
|
||||
+ dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
|
||||
+ status = send_dma_request_dev(qts, dev, bmdma_bar, ide_bar,
|
||||
+ cmd, sector, nb_sectors, prdt, prdt_entries,
|
||||
+ post_exec);
|
||||
free_pci_device(dev);
|
||||
|
||||
return status;
|
||||
@@ -457,6 +481,60 @@ static void test_bmdma_trim(void)
|
||||
test_bmdma_teardown(qts);
|
||||
}
|
||||
|
||||
+static void test_bmdma_trim_reset(void)
|
||||
+{
|
||||
+ QTestState *qts;
|
||||
+ QPCIDevice *dev;
|
||||
+ QPCIBar bmdma_bar, ide_bar, ide_bar2;
|
||||
+ uint8_t status;
|
||||
+ const uint64_t trim_range[] = {
|
||||
+ trim_range_le(0, 2),
|
||||
+ trim_range_le(6, 8),
|
||||
+ };
|
||||
+ size_t len = 512;
|
||||
+ uint8_t *buf;
|
||||
+ uintptr_t guest_buf;
|
||||
+ PrdtEntry prdt[1];
|
||||
+
|
||||
+ qts = ide_test_start(
|
||||
+ "-blockdev file,filename=%s,node-name=img "
|
||||
+ "-blockdev blkdebug,image=img,node-name=dbg,discard=unmap,"
|
||||
+ "inject-error.0.event=none,inject-error.0.iotype=discard,"
|
||||
+ "inject-error.0.errno=0,inject-error.0.delay-ns=1000000 "
|
||||
+ "-device ide-hd,drive=dbg,bus=ide.0",
|
||||
+ tmp_path[0]);
|
||||
+ qtest_irq_intercept_in(qts, "ioapic");
|
||||
+
|
||||
+ guest_buf = guest_alloc(&guest_malloc, len);
|
||||
+ prdt[0].addr = cpu_to_le32(guest_buf),
|
||||
+ prdt[0].size = cpu_to_le32(len | PRDT_EOT),
|
||||
+
|
||||
+ dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
|
||||
+ ide_bar2 = qpci_legacy_iomap(dev, IDE_BASE2);
|
||||
+
|
||||
+ buf = g_malloc(len);
|
||||
+
|
||||
+ /* TRIM request with two segments */
|
||||
+ *((uint64_t *)buf) = trim_range[0];
|
||||
+ *((uint64_t *)buf + 1) = trim_range[1];
|
||||
+
|
||||
+ qtest_memwrite(qts, guest_buf, buf, 2 * sizeof(uint64_t));
|
||||
+
|
||||
+ send_dma_request_dev(qts, dev, bmdma_bar, ide_bar, CMD_DSM | CMDF_NO_WAIT, 0, 1, prdt,
|
||||
+ ARRAY_SIZE(prdt), NULL);
|
||||
+
|
||||
+ /* Reset the device while the first segment is in flight */
|
||||
+ qpci_io_writeb(dev, ide_bar2, 0, IDE_CTRL_RESET);
|
||||
+
|
||||
+ status = wait_dma_completion(qts, dev, bmdma_bar, ide_bar);
|
||||
+ g_assert_cmphex(status, ==, BM_STS_INTR);
|
||||
+ assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
+
|
||||
+ free_pci_device(dev);
|
||||
+ g_free(buf);
|
||||
+ test_bmdma_teardown(qts);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* This test is developed according to the Programming Interface for
|
||||
* Bus Master IDE Controller (Revision 1.0 5/16/94)
|
||||
@@ -1138,6 +1216,7 @@ int main(int argc, char **argv)
|
||||
|
||||
qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw);
|
||||
qtest_add_func("/ide/bmdma/trim", test_bmdma_trim);
|
||||
+ qtest_add_func("/ide/bmdma/trim_reset", test_bmdma_trim_reset);
|
||||
qtest_add_func("/ide/bmdma/various_prdts", test_bmdma_various_prdts);
|
||||
qtest_add_func("/ide/bmdma/no_busmaster", test_bmdma_no_busmaster);
|
||||
|
||||
--
|
||||
2.52.0
|
||||
|
||||
116
kvm-iotests-add-Linux-loop-device-image-creation-test.patch
Normal file
116
kvm-iotests-add-Linux-loop-device-image-creation-test.patch
Normal file
@ -0,0 +1,116 @@
|
||||
From f55e897a36ddca7116d08445a9237b6d34ceacd6 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Tue, 7 Oct 2025 10:17:00 -0400
|
||||
Subject: [PATCH 3/3] iotests: add Linux loop device image creation test
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 565: block: Fix image creation on storage with 4k sector size
|
||||
RH-Jira: RHEL-207389
|
||||
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
RH-Acked-by: German Maglione <None>
|
||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-Commit: [3/3] b878b225ca4cbe5d1ef012122472d58bda27ffff (kmwolf/rhel-qemu-kvm)
|
||||
|
||||
This qemu-iotests test case is based on the reproducer that Jean-Louis
|
||||
Dupond <jean-louis@dupond.be> shared in
|
||||
https://gitlab.com/qemu-project/qemu/-/issues/3127.
|
||||
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-ID: <20251007141700.71891-4-stefanha@redhat.com>
|
||||
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
|
||||
Tested-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
|
||||
Tested-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Reviewed-by: Fiona Ebner <f.ebner@proxmox.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 59a1cf0cd31597d2f6e2c18dc400a1de8427d47d)
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
tests/qemu-iotests/tests/loop-create-file | 59 +++++++++++++++++++
|
||||
tests/qemu-iotests/tests/loop-create-file.out | 8 +++
|
||||
2 files changed, 67 insertions(+)
|
||||
create mode 100755 tests/qemu-iotests/tests/loop-create-file
|
||||
create mode 100644 tests/qemu-iotests/tests/loop-create-file.out
|
||||
|
||||
diff --git a/tests/qemu-iotests/tests/loop-create-file b/tests/qemu-iotests/tests/loop-create-file
|
||||
new file mode 100755
|
||||
index 0000000000..5ec75b046b
|
||||
--- /dev/null
|
||||
+++ b/tests/qemu-iotests/tests/loop-create-file
|
||||
@@ -0,0 +1,59 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# group: quick
|
||||
+#
|
||||
+# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+#
|
||||
+# Copyright Red Hat, Inc.
|
||||
+#
|
||||
+# Test Linux loop device image creation
|
||||
+#
|
||||
+# This test verifies #3127 "qemu-img create fails on loop device with sector size 4096"
|
||||
+# https://gitlab.com/qemu-project/qemu/-/issues/3127
|
||||
+
|
||||
+seq="$(basename $0)"
|
||||
+echo "QA output created by $seq"
|
||||
+
|
||||
+status=1 # failure is the default!
|
||||
+
|
||||
+_cleanup() {
|
||||
+ if [ -n "$loopdev" ]; then
|
||||
+ sudo losetup --detach "$loopdev"
|
||||
+ fi
|
||||
+
|
||||
+ _cleanup_test_img
|
||||
+}
|
||||
+
|
||||
+trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
+
|
||||
+# get standard environment, filters and checks
|
||||
+cd ..
|
||||
+. ./common.rc
|
||||
+. ./common.filter
|
||||
+
|
||||
+_supported_fmt raw
|
||||
+_supported_proto file
|
||||
+_supported_os Linux
|
||||
+
|
||||
+if ! sudo -n losetup &>/dev/null; then
|
||||
+ _notrun "sudo losetup not available"
|
||||
+fi
|
||||
+
|
||||
+echo
|
||||
+echo "=== Create image on a 4 KB sector size loop device ==="
|
||||
+echo
|
||||
+
|
||||
+_make_test_img -f $IMGFMT 1M
|
||||
+
|
||||
+loopdev=$(sudo losetup --sector-size 4096 --find --show "$TEST_IMG")
|
||||
+if [ -z "$loopdev" ]; then
|
||||
+ _fail
|
||||
+fi
|
||||
+
|
||||
+sudo $QEMU_IMG_PROG create -f raw "$loopdev" 1M | \
|
||||
+ sed -e "s#/dev/loop[0-9]\\+#LOOPDEV#g"
|
||||
+
|
||||
+# success, all done
|
||||
+echo
|
||||
+echo '*** done'
|
||||
+rm -f $seq.full
|
||||
+status=0
|
||||
diff --git a/tests/qemu-iotests/tests/loop-create-file.out b/tests/qemu-iotests/tests/loop-create-file.out
|
||||
new file mode 100644
|
||||
index 0000000000..32d4155695
|
||||
--- /dev/null
|
||||
+++ b/tests/qemu-iotests/tests/loop-create-file.out
|
||||
@@ -0,0 +1,8 @@
|
||||
+QA output created by loop-create-file
|
||||
+
|
||||
+=== Create image on a 4 KB sector size loop device ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+Formatting 'LOOPDEV', fmt=raw size=1048576
|
||||
+
|
||||
+*** done
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
From fb2752faded838bfea82450db6a9a56510ea998f Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Tue, 26 May 2026 11:49:57 -0400
|
||||
Subject: [PATCH] virtio-blk: add missing VIRTIO_BLK_T_SCSI_CMD size check
|
||||
(CVE-2026-48914)
|
||||
|
||||
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-MergeRequest: 560: virtio-blk: add missing VIRTIO_BLK_T_SCSI_CMD size check (CVE-2026-48914)
|
||||
RH-Jira: RHEL-184529
|
||||
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/1] 2c669222671cda70b6fbf30b813e2e927cb8399d
|
||||
|
||||
Check that the iovec containing struct virtio_scsi_inhdr is large enough
|
||||
before storing an error value there.
|
||||
|
||||
Feifan Qian <bea1e@proton.me> pointed out that this can be used to
|
||||
corrupt heap memory when the descriptor uses an MMIO address and a
|
||||
length of 1, forcing QEMU to allocate a 1-byte heap bounce buffer.
|
||||
virtio_stl_p() stores 4 bytes and therefore corrupts whatever is beyond
|
||||
the bounce buffer.
|
||||
|
||||
Fixes: CVE-2026-48914
|
||||
Fixes: f34e73cd69bd ("virtio-blk: report non-zero status when failing SG_IO requests")
|
||||
Reported-by: Feifan Qian <bea1e@proton.me>
|
||||
Cc: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-ID: <20260526154957.1741622-1-stefanha@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit aeea0c2804c42f24915467a1e4c70e649e39b8e0)
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
---
|
||||
hw/block/virtio-blk.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
|
||||
index 9bab2716c1..a0678300b4 100644
|
||||
--- a/hw/block/virtio-blk.c
|
||||
+++ b/hw/block/virtio-blk.c
|
||||
@@ -200,10 +200,16 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
|
||||
/*
|
||||
* The scsi inhdr is placed in the second-to-last input segment, just
|
||||
- * before the regular inhdr.
|
||||
+ * before the regular inhdr. VIRTIO implementations normally do not rely on
|
||||
+ * the precise message framing, but legacy implementations did and so we do
|
||||
+ * too for the legacy virtio-blk SCSI request type.
|
||||
*
|
||||
* Just put anything nonzero so that the ioctl fails in the guest.
|
||||
*/
|
||||
+ if (elem->in_sg[elem->in_num - 2].iov_len != sizeof(*scsi)) {
|
||||
+ status = VIRTIO_BLK_S_IOERR;
|
||||
+ goto fail;
|
||||
+ }
|
||||
scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
|
||||
virtio_stl_p(vdev, &scsi->errors, 255);
|
||||
status = VIRTIO_BLK_S_UNSUPP;
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -158,7 +158,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \
|
||||
Summary: QEMU is a machine emulator and virtualizer
|
||||
Name: qemu-kvm
|
||||
Version: 10.1.0
|
||||
Release: 16%{?rcrel}%{?dist}%{?cc_suffix}.2.alma.1
|
||||
Release: 16%{?rcrel}%{?dist}%{?cc_suffix}.5.alma.1
|
||||
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
|
||||
# Epoch 15 used for RHEL 8
|
||||
# Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5)
|
||||
@ -449,6 +449,28 @@ Patch138: kvm-scsi-register-again-after-PREEMPT-without-reservatio.patch
|
||||
Patch139: kvm-scsi-change-buf_size-to-unsigned-int-in-scsi_SG_IO.patch
|
||||
# For RHEL-166033 - live migration failed or get failed WSFC test result during WSFC testing [rhel-10.2.z]
|
||||
Patch140: kvm-scsi-handle-reservation-changes-across-migration.patch
|
||||
# For RHEL-184529 - CVE-2026-48914 qemu-kvm: Heap buffer overflow in virtio-blk SCSI request handling [rhel-10.2.z]
|
||||
Patch141: kvm-virtio-blk-add-missing-VIRTIO_BLK_T_SCSI_CMD-size-ch.patch
|
||||
# For RHEL-190702 - qemu-kvm hung during drain after double pause [rhel-10.2.z]
|
||||
Patch142: kvm-blkdebug-Add-delay-ns-option.patch
|
||||
# For RHEL-190702 - qemu-kvm hung during drain after double pause [rhel-10.2.z]
|
||||
Patch143: kvm-block-Add-blk_co_start-end_request-and-BDRV_REQ_NO_Q.patch
|
||||
# For RHEL-190702 - qemu-kvm hung during drain after double pause [rhel-10.2.z]
|
||||
Patch144: kvm-block-Add-flags-parameter-to-blk_-_pdiscard.patch
|
||||
# For RHEL-190702 - qemu-kvm hung during drain after double pause [rhel-10.2.z]
|
||||
Patch145: kvm-ide-Minimal-fix-for-deadlock-between-TRIM-and-drain.patch
|
||||
# For RHEL-190702 - qemu-kvm hung during drain after double pause [rhel-10.2.z]
|
||||
Patch146: kvm-ide-Clean-up-ide_trim_co_entry-to-be-idiomatic-corou.patch
|
||||
# For RHEL-190702 - qemu-kvm hung during drain after double pause [rhel-10.2.z]
|
||||
Patch147: kvm-ide-test-Factor-out-wait_dma_completion.patch
|
||||
# For RHEL-190702 - qemu-kvm hung during drain after double pause [rhel-10.2.z]
|
||||
Patch148: kvm-ide-test-Test-reset-during-TRIM.patch
|
||||
# For RHEL-207389 - qemu-img create/convert fails on target block device with 4k sector size [rhel-10.2.z]
|
||||
Patch149: kvm-file-posix-populate-pwrite_zeroes_alignment.patch
|
||||
# For RHEL-207389 - qemu-img create/convert fails on target block device with 4k sector size [rhel-10.2.z]
|
||||
Patch150: kvm-block-use-pwrite_zeroes_alignment-when-writing-first.patch
|
||||
# For RHEL-207389 - qemu-img create/convert fails on target block device with 4k sector size [rhel-10.2.z]
|
||||
Patch151: kvm-iotests-add-Linux-loop-device-image-creation-test.patch
|
||||
|
||||
# AlmaLinux Patch
|
||||
Patch2001: 2001-Add-ppc64-support.patch
|
||||
@ -1177,6 +1199,7 @@ install -D -p -m 0644 %{modprobe_kvm_conf} $RPM_BUILD_ROOT%{_sysconfdir}/modprob
|
||||
mkdir -p %{buildroot}%{testsdir}/python
|
||||
mkdir -p %{buildroot}%{testsdir}/tests
|
||||
mkdir -p %{buildroot}%{testsdir}/tests/qemu-iotests
|
||||
mkdir -p %{buildroot}%{testsdir}/tests/qtest
|
||||
mkdir -p %{buildroot}%{testsdir}/scripts/qmp
|
||||
|
||||
|
||||
@ -1195,6 +1218,9 @@ cp -ur %{qemu_kvm_build}/tests/qemu-iotests/* %{buildroot}%{testsdir}/tests/qemu
|
||||
|
||||
install -p -m 0644 %{_sourcedir}/README.tests %{buildroot}%{testsdir}/README
|
||||
|
||||
# Install qtests
|
||||
find %{qemu_kvm_build}/tests/qtest/ -type f -executable -exec install -p -m 0755 {} %{buildroot}%{testsdir}/tests/qtest/ \;
|
||||
|
||||
# Do the actual qemu tree install
|
||||
pushd %{qemu_kvm_build}
|
||||
%make_install
|
||||
@ -1577,12 +1603,36 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Jul 21 2026 Eduard Abdullin <eabdullin@almalinux.org> - 18:10.1.0-16.2.alma.1
|
||||
* Mon Aug 24 2026 Eduard Abdullin <eabdullin@almalinux.org> - 18:10.1.0-16.5.alma.1
|
||||
- Enable QXL device build
|
||||
- Enable building for ppc64le
|
||||
- Re-added Spice support
|
||||
- Don't remove slof.bin for ppc64le
|
||||
|
||||
* Tue Aug 04 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-16.el10_2.5
|
||||
- kvm-file-posix-populate-pwrite_zeroes_alignment.patch [RHEL-207389]
|
||||
- kvm-block-use-pwrite_zeroes_alignment-when-writing-first.patch [RHEL-207389]
|
||||
- kvm-iotests-add-Linux-loop-device-image-creation-test.patch [RHEL-207389]
|
||||
- Resolves: RHEL-207389
|
||||
(qemu-img create/convert fails on target block device with 4k sector size [rhel-10.2.z])
|
||||
|
||||
* Thu Jul 09 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-16.el10_2.4
|
||||
- kvm-blkdebug-Add-delay-ns-option.patch [RHEL-190702]
|
||||
- kvm-block-Add-blk_co_start-end_request-and-BDRV_REQ_NO_Q.patch [RHEL-190702]
|
||||
- kvm-block-Add-flags-parameter-to-blk_-_pdiscard.patch [RHEL-190702]
|
||||
- kvm-ide-Minimal-fix-for-deadlock-between-TRIM-and-drain.patch [RHEL-190702]
|
||||
- kvm-ide-Clean-up-ide_trim_co_entry-to-be-idiomatic-corou.patch [RHEL-190702]
|
||||
- kvm-ide-test-Factor-out-wait_dma_completion.patch [RHEL-190702]
|
||||
- kvm-ide-test-Test-reset-during-TRIM.patch [RHEL-190702]
|
||||
- kvm-spec-Install-qtests-into-qemu-kvm-tests-package.patch [RHEL-190702]
|
||||
- Resolves: RHEL-190702
|
||||
(qemu-kvm hung during drain after double pause [rhel-10.2.z])
|
||||
|
||||
* Fri Jun 19 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-16.el10_2.3
|
||||
- kvm-virtio-blk-add-missing-VIRTIO_BLK_T_SCSI_CMD-size-ch.patch [RHEL-184529]
|
||||
- Resolves: RHEL-184529
|
||||
(CVE-2026-48914 qemu-kvm: Heap buffer overflow in virtio-blk SCSI request handling [rhel-10.2.z])
|
||||
|
||||
* Mon Jun 15 2026 Miroslav Rezanina <mrezanin@redhat.com> - 10.1.0-16.el10_2.2
|
||||
- kvm-scsi-adjust-error_prepend-formatting.patch [RHEL-166007]
|
||||
- kvm-scsi-always-send-valid-PREEMPT-TYPE-field.patch [RHEL-166007]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user