1 | The following changes since commit 527266f324def9f7f392fe3b0dd940cb8dc699d9: | 1 | The following changes since commit 0280396a33c7210c4df5306afeab63411a41535a: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/armbru/tags/pull-pflash-2019-03-26' into staging (2019-03-26 09:57:07 +0000) | 3 | Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-gdbstub-150221-1' into staging (2021-02-15 10:13:13 +0000) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | git://repo.or.cz/qemu/kevin.git tags/for-upstream | 7 | git://repo.or.cz/qemu/kevin.git tags/for-upstream |
8 | 8 | ||
9 | for you to fetch changes up to c6e3f520c802c5cb2de80576aba7f9f1fe985d8b: | 9 | for you to fetch changes up to b248e61652e20c3353af4b0ccb90f17d76f4db21: |
10 | 10 | ||
11 | qemu-io: Add write -n for BDRV_REQ_NO_FALLBACK (2019-03-26 11:37:51 +0100) | 11 | monitor/qmp: Stop processing requests when shutdown is requested (2021-02-15 15:10:14 +0100) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block layer patches: | 14 | Block layer patches: |
15 | 15 | ||
16 | - Fix slow pre-zeroing in qemu-img convert | 16 | - qemu-storage-daemon: Enable object-add |
17 | - Test case for block job pausing on I/O errors | 17 | - blockjob: Fix crash with IOthread when block commit after snapshot |
18 | - monitor: Shutdown fixes | ||
19 | - xen-block: fix reporting of discard feature | ||
20 | - qcow2: Remove half-initialised image file after failed image creation | ||
21 | - ahci: Fix DMA direction | ||
22 | - iotests fixes | ||
18 | 23 | ||
19 | ---------------------------------------------------------------- | 24 | ---------------------------------------------------------------- |
20 | Kevin Wolf (6): | 25 | Alexander Bulekov (1): |
21 | block: Remove error messages in bdrv_make_zero() | 26 | hw/ide/ahci: map cmd_fis as DMA_DIRECTION_TO_DEVICE |
22 | block: Add BDRV_REQ_NO_FALLBACK | ||
23 | block: Advertise BDRV_REQ_NO_FALLBACK in filter drivers | ||
24 | file-posix: Support BDRV_REQ_NO_FALLBACK for zero writes | ||
25 | qemu-img: Use BDRV_REQ_NO_FALLBACK for pre-zeroing | ||
26 | qemu-io: Add write -n for BDRV_REQ_NO_FALLBACK | ||
27 | 27 | ||
28 | Vladimir Sementsov-Ogievskiy (1): | 28 | Kevin Wolf (3): |
29 | iotests: add 248: test resume mirror after auto pause on ENOSPC | 29 | qemu-storage-daemon: Enable object-add |
30 | monitor: Fix assertion failure on shutdown | ||
31 | monitor/qmp: Stop processing requests when shutdown is requested | ||
30 | 32 | ||
31 | include/block/block.h | 7 ++++- | 33 | Max Reitz (1): |
32 | include/block/raw-aio.h | 1 + | 34 | iotests: Consistent $IMGOPTS boundary matching |
33 | block/blkdebug.c | 2 +- | ||
34 | block/copy-on-read.c | 7 ++--- | ||
35 | block/file-posix.c | 24 ++++++++++------ | ||
36 | block/io.c | 16 +++++++---- | ||
37 | block/mirror.c | 3 +- | ||
38 | block/raw-format.c | 2 +- | ||
39 | qemu-img.c | 2 +- | ||
40 | qemu-io-cmds.c | 13 +++++++-- | ||
41 | tests/qemu-iotests/248 | 71 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
42 | tests/qemu-iotests/248.out | 8 ++++++ | ||
43 | tests/qemu-iotests/group | 1 + | ||
44 | 13 files changed, 133 insertions(+), 24 deletions(-) | ||
45 | create mode 100755 tests/qemu-iotests/248 | ||
46 | create mode 100644 tests/qemu-iotests/248.out | ||
47 | 35 | ||
36 | Maxim Levitsky (3): | ||
37 | crypto: luks: Fix tiny memory leak | ||
38 | block: add bdrv_co_delete_file_noerr | ||
39 | block: qcow2: remove the created file on initialization error | ||
40 | |||
41 | Michael Qiu (1): | ||
42 | blockjob: Fix crash with IOthread when block commit after snapshot | ||
43 | |||
44 | Roger Pau Monné (1): | ||
45 | xen-block: fix reporting of discard feature | ||
46 | |||
47 | Thomas Huth (1): | ||
48 | tests/qemu-iotests: Remove test 259 from the "auto" group | ||
49 | |||
50 | include/block/block.h | 1 + | ||
51 | block.c | 22 ++++++++++++++++++++++ | ||
52 | block/crypto.c | 13 ++----------- | ||
53 | block/qcow2.c | 8 +++++--- | ||
54 | blockjob.c | 8 ++++++-- | ||
55 | hw/block/xen-block.c | 1 + | ||
56 | hw/ide/ahci.c | 12 ++++++------ | ||
57 | monitor/monitor.c | 25 +++++++++++++++---------- | ||
58 | monitor/qmp.c | 5 +++++ | ||
59 | storage-daemon/qemu-storage-daemon.c | 2 ++ | ||
60 | tests/qemu-iotests/259 | 2 +- | ||
61 | tests/qemu-iotests/common.rc | 4 +++- | ||
62 | 12 files changed, 69 insertions(+), 34 deletions(-) | ||
63 | |||
64 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | As we don't have a fully QAPIfied version of object-add yet and it still | ||
2 | has 'gen': false in the schema, it needs to be registered explicitly in | ||
3 | init_qmp_commands() to be available for users. | ||
1 | 4 | ||
5 | Fixes: 2af282ec51a27116d0402cab237b8970800f870c | ||
6 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
7 | Message-Id: <20210204072137.19663-1-kwolf@redhat.com> | ||
8 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | storage-daemon/qemu-storage-daemon.c | 2 ++ | ||
12 | 1 file changed, 2 insertions(+) | ||
13 | |||
14 | diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/storage-daemon/qemu-storage-daemon.c | ||
17 | +++ b/storage-daemon/qemu-storage-daemon.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static void init_qmp_commands(void) | ||
19 | qmp_init_marshal(&qmp_commands); | ||
20 | qmp_register_command(&qmp_commands, "query-qmp-schema", | ||
21 | qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG); | ||
22 | + qmp_register_command(&qmp_commands, "object-add", qmp_object_add, | ||
23 | + QCO_NO_OPTIONS); | ||
24 | |||
25 | QTAILQ_INIT(&qmp_cap_negotiation_commands); | ||
26 | qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities", | ||
27 | -- | ||
28 | 2.29.2 | ||
29 | |||
30 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Max Reitz <mreitz@redhat.com> | ||
1 | 2 | ||
3 | To disallow certain refcount_bits values, some _unsupported_imgopts | ||
4 | invocations look like "refcount_bits=1[^0-9]", i.e. they match an | ||
5 | integer boundary with [^0-9]. This expression does not match the end of | ||
6 | the string, though, so it breaks down when refcount_bits is the last | ||
7 | option (which it tends to be after the rewrite of the check script in | ||
8 | Python). | ||
9 | |||
10 | Those invocations could use \b or \> instead, but those are not | ||
11 | portable. They could use something like \([^0-9]\|$\), but that would | ||
12 | be cumbersome. To make it simple and keep the existing invocations | ||
13 | working, just let _unsupported_imgopts match the regex against $IMGOPTS | ||
14 | plus a trailing space. | ||
15 | |||
16 | Suggested-by: Eric Blake <eblake@redhat.com> | ||
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
18 | Message-Id: <20210210095128.22732-1-mreitz@redhat.com> | ||
19 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
20 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
21 | --- | ||
22 | tests/qemu-iotests/common.rc | 4 +++- | ||
23 | 1 file changed, 3 insertions(+), 1 deletion(-) | ||
24 | |||
25 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/tests/qemu-iotests/common.rc | ||
28 | +++ b/tests/qemu-iotests/common.rc | ||
29 | @@ -XXX,XX +XXX,XX @@ _unsupported_imgopts() | ||
30 | { | ||
31 | for bad_opt | ||
32 | do | ||
33 | - if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt" | ||
34 | + # Add a space so tests can match for whitespace that marks the | ||
35 | + # end of an option (\b or \> are not portable) | ||
36 | + if echo "$IMGOPTS " | grep -q 2>/dev/null "$bad_opt" | ||
37 | then | ||
38 | _notrun "not suitable for image option: $bad_opt" | ||
39 | fi | ||
40 | -- | ||
41 | 2.29.2 | ||
42 | |||
43 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Michael Qiu <qiudayu@huayun.com> | ||
1 | 2 | ||
3 | Currently, if guest has workloads, IO thread will acquire aio_context | ||
4 | lock before do io_submit, it leads to segmentfault when do block commit | ||
5 | after snapshot. Just like below: | ||
6 | |||
7 | Program received signal SIGSEGV, Segmentation fault. | ||
8 | |||
9 | [Switching to Thread 0x7f7c7d91f700 (LWP 99907)] | ||
10 | 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 | ||
11 | 1437 ../block/mirror.c: No such file or directory. | ||
12 | (gdb) p s->job | ||
13 | $17 = (MirrorBlockJob *) 0x0 | ||
14 | (gdb) p s->stop | ||
15 | $18 = false | ||
16 | |||
17 | Call trace of IO thread: | ||
18 | 0 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 | ||
19 | 1 0x00005576d0f7f3ab in bdrv_driver_pwritev at ../block/io.c:1174 | ||
20 | 2 0x00005576d0f8139d in bdrv_aligned_pwritev at ../block/io.c:1988 | ||
21 | 3 0x00005576d0f81b65 in bdrv_co_pwritev_part at ../block/io.c:2156 | ||
22 | 4 0x00005576d0f8e6b7 in blk_do_pwritev_part at ../block/block-backend.c:1260 | ||
23 | 5 0x00005576d0f8e84d in blk_aio_write_entry at ../block/block-backend.c:1476 | ||
24 | ... | ||
25 | |||
26 | Switch to qemu main thread: | ||
27 | 0 0x00007f903be704ed in __lll_lock_wait at | ||
28 | /lib/../lib64/libpthread.so.0 | ||
29 | 1 0x00007f903be6bde6 in _L_lock_941 at /lib/../lib64/libpthread.so.0 | ||
30 | 2 0x00007f903be6bcdf in pthread_mutex_lock at | ||
31 | /lib/../lib64/libpthread.so.0 | ||
32 | 3 0x0000564b21456889 in qemu_mutex_lock_impl at | ||
33 | ../util/qemu-thread-posix.c:79 | ||
34 | 4 0x0000564b213af8a5 in block_job_add_bdrv at ../blockjob.c:224 | ||
35 | 5 0x0000564b213b00ad in block_job_create at ../blockjob.c:440 | ||
36 | 6 0x0000564b21357c0a in mirror_start_job at ../block/mirror.c:1622 | ||
37 | 7 0x0000564b2135a9af in commit_active_start at ../block/mirror.c:1867 | ||
38 | 8 0x0000564b2133d132 in qmp_block_commit at ../blockdev.c:2768 | ||
39 | 9 0x0000564b2141fef3 in qmp_marshal_block_commit at | ||
40 | qapi/qapi-commands-block-core.c:346 | ||
41 | 10 0x0000564b214503c9 in do_qmp_dispatch_bh at | ||
42 | ../qapi/qmp-dispatch.c:110 | ||
43 | 11 0x0000564b21451996 in aio_bh_poll at ../util/async.c:164 | ||
44 | 12 0x0000564b2146018e in aio_dispatch at ../util/aio-posix.c:381 | ||
45 | 13 0x0000564b2145187e in aio_ctx_dispatch at ../util/async.c:306 | ||
46 | 14 0x00007f9040239049 in g_main_context_dispatch at | ||
47 | /lib/../lib64/libglib-2.0.so.0 | ||
48 | 15 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:232 | ||
49 | 16 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:255 | ||
50 | 17 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:531 | ||
51 | 18 0x0000564b212304e1 in qemu_main_loop at ../softmmu/runstate.c:721 | ||
52 | 19 0x0000564b20f7975e in main at ../softmmu/main.c:50 | ||
53 | |||
54 | In IO thread when do bdrv_mirror_top_pwritev, the job is NULL, and stop field | ||
55 | is false, this means the MirrorBDSOpaque "s" object has not been initialized | ||
56 | yet, and this object is initialized by block_job_create(), but the initialize | ||
57 | process is stuck in acquiring the lock. | ||
58 | |||
59 | In this situation, IO thread come to bdrv_mirror_top_pwritev(),which means that | ||
60 | mirror-top node is already inserted into block graph, but its bs->opaque->job | ||
61 | is not initialized. | ||
62 | |||
63 | The root cause is that qemu main thread do release/acquire when hold the lock, | ||
64 | at the same time, IO thread get the lock after release stage, and the crash | ||
65 | occured. | ||
66 | |||
67 | Actually, in this situation, job->job.aio_context will not equal to | ||
68 | qemu_get_aio_context(), and will be the same as bs->aio_context, | ||
69 | thus, no need to release the lock, becasue bdrv_root_attach_child() | ||
70 | will not change the context. | ||
71 | |||
72 | This patch fix this issue. | ||
73 | |||
74 | Fixes: 132ada80 "block: Adjust AioContexts when attaching nodes" | ||
75 | |||
76 | Signed-off-by: Michael Qiu <qiudayu@huayun.com> | ||
77 | Message-Id: <20210203024059.52683-1-08005325@163.com> | ||
78 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
79 | --- | ||
80 | blockjob.c | 8 ++++++-- | ||
81 | 1 file changed, 6 insertions(+), 2 deletions(-) | ||
82 | |||
83 | diff --git a/blockjob.c b/blockjob.c | ||
84 | index XXXXXXX..XXXXXXX 100644 | ||
85 | --- a/blockjob.c | ||
86 | +++ b/blockjob.c | ||
87 | @@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, | ||
88 | uint64_t perm, uint64_t shared_perm, Error **errp) | ||
89 | { | ||
90 | BdrvChild *c; | ||
91 | + bool need_context_ops; | ||
92 | |||
93 | bdrv_ref(bs); | ||
94 | - if (job->job.aio_context != qemu_get_aio_context()) { | ||
95 | + | ||
96 | + need_context_ops = bdrv_get_aio_context(bs) != job->job.aio_context; | ||
97 | + | ||
98 | + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { | ||
99 | aio_context_release(job->job.aio_context); | ||
100 | } | ||
101 | c = bdrv_root_attach_child(bs, name, &child_job, 0, | ||
102 | job->job.aio_context, perm, shared_perm, job, | ||
103 | errp); | ||
104 | - if (job->job.aio_context != qemu_get_aio_context()) { | ||
105 | + if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { | ||
106 | aio_context_acquire(job->job.aio_context); | ||
107 | } | ||
108 | if (c == NULL) { | ||
109 | -- | ||
110 | 2.29.2 | ||
111 | |||
112 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alexander Bulekov <alxndr@bu.edu> | ||
1 | 2 | ||
3 | cmd_fis is mapped as DMA_DIRECTION_FROM_DEVICE, however, it is read | ||
4 | from, and not written to anywhere. Fix the DMA_DIRECTION and mark | ||
5 | cmd_fis as read-only in the code. | ||
6 | |||
7 | Signed-off-by: Alexander Bulekov <alxndr@bu.edu> | ||
8 | Message-Id: <20210119164051.89268-1-alxndr@bu.edu> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | hw/ide/ahci.c | 12 ++++++------ | ||
12 | 1 file changed, 6 insertions(+), 6 deletions(-) | ||
13 | |||
14 | diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/ide/ahci.c | ||
17 | +++ b/hw/ide/ahci.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static void ahci_reset_port(AHCIState *s, int port) | ||
19 | } | ||
20 | |||
21 | /* Buffer pretty output based on a raw FIS structure. */ | ||
22 | -static char *ahci_pretty_buffer_fis(uint8_t *fis, int cmd_len) | ||
23 | +static char *ahci_pretty_buffer_fis(const uint8_t *fis, int cmd_len) | ||
24 | { | ||
25 | int i; | ||
26 | GString *s = g_string_new("FIS:"); | ||
27 | @@ -XXX,XX +XXX,XX @@ static void execute_ncq_command(NCQTransferState *ncq_tfs) | ||
28 | } | ||
29 | |||
30 | |||
31 | -static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, | ||
32 | +static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis, | ||
33 | uint8_t slot) | ||
34 | { | ||
35 | AHCIDevice *ad = &s->dev[port]; | ||
36 | - NCQFrame *ncq_fis = (NCQFrame*)cmd_fis; | ||
37 | + const NCQFrame *ncq_fis = (NCQFrame *)cmd_fis; | ||
38 | uint8_t tag = ncq_fis->tag >> 3; | ||
39 | NCQTransferState *ncq_tfs = &ad->ncq_tfs[tag]; | ||
40 | size_t size; | ||
41 | @@ -XXX,XX +XXX,XX @@ static AHCICmdHdr *get_cmd_header(AHCIState *s, uint8_t port, uint8_t slot) | ||
42 | } | ||
43 | |||
44 | static void handle_reg_h2d_fis(AHCIState *s, int port, | ||
45 | - uint8_t slot, uint8_t *cmd_fis) | ||
46 | + uint8_t slot, const uint8_t *cmd_fis) | ||
47 | { | ||
48 | IDEState *ide_state = &s->dev[port].port.ifs[0]; | ||
49 | AHCICmdHdr *cmd = get_cmd_header(s, port, slot); | ||
50 | @@ -XXX,XX +XXX,XX @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) | ||
51 | tbl_addr = le64_to_cpu(cmd->tbl_addr); | ||
52 | cmd_len = 0x80; | ||
53 | cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len, | ||
54 | - DMA_DIRECTION_FROM_DEVICE); | ||
55 | + DMA_DIRECTION_TO_DEVICE); | ||
56 | if (!cmd_fis) { | ||
57 | trace_handle_cmd_badfis(s, port); | ||
58 | return -1; | ||
59 | @@ -XXX,XX +XXX,XX @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) | ||
60 | } | ||
61 | |||
62 | out: | ||
63 | - dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE, | ||
64 | + dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_TO_DEVICE, | ||
65 | cmd_len); | ||
66 | |||
67 | if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { | ||
68 | -- | ||
69 | 2.29.2 | ||
70 | |||
71 | diff view generated by jsdifflib |
1 | This makes the new BDRV_REQ_NO_FALLBACK flag available in the qemu-io | 1 | From: Roger Pau Monne <roger.pau@citrix.com> |
---|---|---|---|
2 | write command. | ||
3 | 2 | ||
3 | Linux blkfront expects both "discard-granularity" and | ||
4 | "discard-alignment" present on xenbus in order to properly enable the | ||
5 | feature, not exposing "discard-alignment" left some Linux blkfront | ||
6 | versions with a broken discard setup. This has also been addressed in | ||
7 | Linux with: | ||
8 | |||
9 | https://lore.kernel.org/lkml/20210118151528.81668-1-roger.pau@citrix.com/T/#u | ||
10 | |||
11 | Fix QEMU to report a "discard-alignment" of 0, in order for it to work | ||
12 | with older Linux frontends. | ||
13 | |||
14 | Reported-by: Arthur Borsboom <arthurborsboom@gmail.com> | ||
15 | Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> | ||
16 | Message-Id: <20210118153330.82324-1-roger.pau@citrix.com> | ||
17 | Reviewed-by: Paul Durrant <paul@xen.org> | ||
4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
5 | Acked-by: Eric Blake <eblake@redhat.com> | ||
6 | --- | 19 | --- |
7 | qemu-io-cmds.c | 13 +++++++++++-- | 20 | hw/block/xen-block.c | 1 + |
8 | 1 file changed, 11 insertions(+), 2 deletions(-) | 21 | 1 file changed, 1 insertion(+) |
9 | 22 | ||
10 | diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c | 23 | diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c |
11 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
12 | --- a/qemu-io-cmds.c | 25 | --- a/hw/block/xen-block.c |
13 | +++ b/qemu-io-cmds.c | 26 | +++ b/hw/block/xen-block.c |
14 | @@ -XXX,XX +XXX,XX @@ static void write_help(void) | 27 | @@ -XXX,XX +XXX,XX @@ static void xen_block_realize(XenDevice *xendev, Error **errp) |
15 | " -b, -- write to the VM state rather than the virtual disk\n" | 28 | xen_device_backend_printf(xendev, "feature-discard", "%u", 1); |
16 | " -c, -- write compressed data with blk_write_compressed\n" | 29 | xen_device_backend_printf(xendev, "discard-granularity", "%u", |
17 | " -f, -- use Force Unit Access semantics\n" | 30 | conf->discard_granularity); |
18 | +" -n, -- with -z, don't allow slow fallback\n" | 31 | + xen_device_backend_printf(xendev, "discard-alignment", "%u", 0); |
19 | " -p, -- ignored for backwards compatibility\n" | ||
20 | " -P, -- use different pattern to fill file\n" | ||
21 | " -C, -- report statistics in a machine parsable format\n" | ||
22 | @@ -XXX,XX +XXX,XX @@ static const cmdinfo_t write_cmd = { | ||
23 | .perm = BLK_PERM_WRITE, | ||
24 | .argmin = 2, | ||
25 | .argmax = -1, | ||
26 | - .args = "[-bcCfquz] [-P pattern] off len", | ||
27 | + .args = "[-bcCfnquz] [-P pattern] off len", | ||
28 | .oneline = "writes a number of bytes at a specified offset", | ||
29 | .help = write_help, | ||
30 | }; | ||
31 | @@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv) | ||
32 | int64_t total = 0; | ||
33 | int pattern = 0xcd; | ||
34 | |||
35 | - while ((c = getopt(argc, argv, "bcCfpP:quz")) != -1) { | ||
36 | + while ((c = getopt(argc, argv, "bcCfnpP:quz")) != -1) { | ||
37 | switch (c) { | ||
38 | case 'b': | ||
39 | bflag = true; | ||
40 | @@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv) | ||
41 | case 'f': | ||
42 | flags |= BDRV_REQ_FUA; | ||
43 | break; | ||
44 | + case 'n': | ||
45 | + flags |= BDRV_REQ_NO_FALLBACK; | ||
46 | + break; | ||
47 | case 'p': | ||
48 | /* Ignored for backwards compatibility */ | ||
49 | break; | ||
50 | @@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv) | ||
51 | return -EINVAL; | ||
52 | } | 32 | } |
53 | 33 | ||
54 | + if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) { | 34 | xen_device_backend_printf(xendev, "feature-flush-cache", "%u", 1); |
55 | + printf("-n requires -z to be specified\n"); | ||
56 | + return -EINVAL; | ||
57 | + } | ||
58 | + | ||
59 | if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) { | ||
60 | printf("-u requires -z to be specified\n"); | ||
61 | return -EINVAL; | ||
62 | -- | 35 | -- |
63 | 2.20.1 | 36 | 2.29.2 |
64 | 37 | ||
65 | 38 | diff view generated by jsdifflib |
1 | If qemu-img convert sees that the target image isn't zero-initialised | 1 | From: Thomas Huth <thuth@redhat.com> |
---|---|---|---|
2 | yet, it tries to do an efficient zero write for the whole image first | ||
3 | to save the overhead of repeated explicit zero writes during the | ||
4 | conversion. Obviously, this provides only an advantage if the | ||
5 | pre-zeroing is actually efficient. Otherwise, we can end up writing | ||
6 | zeroes slowly while zeroing out the whole image, and then overwrite the | ||
7 | same blocks again with real data, potentially doubling the written data. | ||
8 | 2 | ||
9 | Pass BDRV_REQ_NO_FALLBACK to blk_make_zero() to avoid this case. If we | 3 | Tests in the "auto" group should support qcow2 so that they can |
10 | can't efficiently zero out, we'll instead write explicit zeroes only if | 4 | be run during "make check-block". Test 259 only supports "raw", so |
11 | there is no data to be written to a block. | 5 | it currently always gets skipped when running "make check-block". |
6 | Let's skip this unnecessary step and remove it from the auto group. | ||
12 | 7 | ||
8 | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||
9 | Message-Id: <20210215103835.1129145-1-thuth@redhat.com> | ||
13 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
14 | Acked-by: Eric Blake <eblake@redhat.com> | ||
15 | --- | 11 | --- |
16 | qemu-img.c | 2 +- | 12 | tests/qemu-iotests/259 | 2 +- |
17 | 1 file changed, 1 insertion(+), 1 deletion(-) | 13 | 1 file changed, 1 insertion(+), 1 deletion(-) |
18 | 14 | ||
19 | diff --git a/qemu-img.c b/qemu-img.c | 15 | diff --git a/tests/qemu-iotests/259 b/tests/qemu-iotests/259 |
20 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100755 |
21 | --- a/qemu-img.c | 17 | --- a/tests/qemu-iotests/259 |
22 | +++ b/qemu-img.c | 18 | +++ b/tests/qemu-iotests/259 |
23 | @@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s) | 19 | @@ -XXX,XX +XXX,XX @@ |
24 | if (!s->has_zero_init && !s->target_has_backing && | 20 | #!/usr/bin/env bash |
25 | bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) | 21 | -# group: rw auto quick |
26 | { | 22 | +# group: rw quick |
27 | - ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP); | 23 | # |
28 | + ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK); | 24 | # Test generic image creation fallback (by using NBD) |
29 | if (ret == 0) { | 25 | # |
30 | s->has_zero_init = true; | ||
31 | } | ||
32 | -- | 26 | -- |
33 | 2.20.1 | 27 | 2.29.2 |
34 | 28 | ||
35 | 29 | diff view generated by jsdifflib |
1 | We know that the kernel implements a slow fallback code path for | 1 | From: Maxim Levitsky <mlevitsk@redhat.com> |
---|---|---|---|
2 | BLKZEROOUT, so if BDRV_REQ_NO_FALLBACK is given, we shouldn't call it. | ||
3 | The other operations we call in the context of .bdrv_co_pwrite_zeroes | ||
4 | should usually be quick, so no modification should be needed for them. | ||
5 | If we ever notice that there are additional problematic cases, we can | ||
6 | still make these conditional as well. | ||
7 | 2 | ||
3 | When the underlying block device doesn't support the | ||
4 | bdrv_co_delete_file interface, an 'Error' object was leaked. | ||
5 | |||
6 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | ||
7 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
8 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
9 | Message-Id: <20201217170904.946013-2-mlevitsk@redhat.com> | ||
8 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
9 | Acked-by: Eric Blake <eblake@redhat.com> | ||
10 | --- | 11 | --- |
11 | include/block/raw-aio.h | 1 + | 12 | block/crypto.c | 2 ++ |
12 | block/file-posix.c | 24 ++++++++++++++++-------- | 13 | 1 file changed, 2 insertions(+) |
13 | 2 files changed, 17 insertions(+), 8 deletions(-) | ||
14 | 14 | ||
15 | diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h | 15 | diff --git a/block/crypto.c b/block/crypto.c |
16 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/include/block/raw-aio.h | 17 | --- a/block/crypto.c |
18 | +++ b/include/block/raw-aio.h | 18 | +++ b/block/crypto.c |
19 | @@ -XXX,XX +XXX,XX @@ | 19 | @@ -XXX,XX +XXX,XX @@ fail: |
20 | /* AIO flags */ | 20 | */ |
21 | #define QEMU_AIO_MISALIGNED 0x1000 | 21 | if ((r_del < 0) && (r_del != -ENOTSUP)) { |
22 | #define QEMU_AIO_BLKDEV 0x2000 | 22 | error_report_err(local_delete_err); |
23 | +#define QEMU_AIO_NO_FALLBACK 0x4000 | 23 | + } else { |
24 | 24 | + error_free(local_delete_err); | |
25 | 25 | } | |
26 | /* linux-aio.c - Linux native implementation */ | ||
27 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/block/file-posix.c | ||
30 | +++ b/block/file-posix.c | ||
31 | @@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options, | ||
32 | } | 26 | } |
33 | #endif | 27 | |
34 | |||
35 | - bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP; | ||
36 | + bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; | ||
37 | ret = 0; | ||
38 | fail: | ||
39 | if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { | ||
40 | @@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb) | ||
41 | } | ||
42 | |||
43 | #ifdef BLKZEROOUT | ||
44 | - do { | ||
45 | - uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes }; | ||
46 | - if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) { | ||
47 | - return 0; | ||
48 | - } | ||
49 | - } while (errno == EINTR); | ||
50 | + /* The BLKZEROOUT implementation in the kernel doesn't set | ||
51 | + * BLKDEV_ZERO_NOFALLBACK, so we can't call this if we have to avoid slow | ||
52 | + * fallbacks. */ | ||
53 | + if (!(aiocb->aio_type & QEMU_AIO_NO_FALLBACK)) { | ||
54 | + do { | ||
55 | + uint64_t range[2] = { aiocb->aio_offset, aiocb->aio_nbytes }; | ||
56 | + if (ioctl(aiocb->aio_fildes, BLKZEROOUT, range) == 0) { | ||
57 | + return 0; | ||
58 | + } | ||
59 | + } while (errno == EINTR); | ||
60 | |||
61 | - ret = translate_err(-errno); | ||
62 | + ret = translate_err(-errno); | ||
63 | + } | ||
64 | #endif | ||
65 | |||
66 | if (ret == -ENOTSUP) { | ||
67 | @@ -XXX,XX +XXX,XX @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes, | ||
68 | if (blkdev) { | ||
69 | acb.aio_type |= QEMU_AIO_BLKDEV; | ||
70 | } | ||
71 | + if (flags & BDRV_REQ_NO_FALLBACK) { | ||
72 | + acb.aio_type |= QEMU_AIO_NO_FALLBACK; | ||
73 | + } | ||
74 | |||
75 | if (flags & BDRV_REQ_MAY_UNMAP) { | ||
76 | acb.aio_type |= QEMU_AIO_DISCARD; | ||
77 | -- | 28 | -- |
78 | 2.20.1 | 29 | 2.29.2 |
79 | 30 | ||
80 | 31 | diff view generated by jsdifflib |
1 | For qemu-img convert, we want an operation that zeroes out the whole | 1 | From: Maxim Levitsky <mlevitsk@redhat.com> |
---|---|---|---|
2 | image if this can be done efficiently, but that returns an error | ||
3 | otherwise so we don't write explicit zeroes and immediately overwrite | ||
4 | them with the real data, potentially doubling the amount of data to be | ||
5 | written. | ||
6 | 2 | ||
3 | This function wraps bdrv_co_delete_file for the common case of removing a file, | ||
4 | which was just created by format driver, on an error condition. | ||
5 | |||
6 | It hides the -ENOTSUPP error, and reports all other errors otherwise. | ||
7 | |||
8 | Use it in luks driver | ||
9 | |||
10 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | ||
11 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
12 | Message-Id: <20201217170904.946013-3-mlevitsk@redhat.com> | ||
13 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 14 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
8 | Acked-by: Eric Blake <eblake@redhat.com> | ||
9 | --- | 15 | --- |
10 | include/block/block.h | 7 ++++++- | 16 | include/block/block.h | 1 + |
11 | block/io.c | 12 +++++++++++- | 17 | block.c | 22 ++++++++++++++++++++++ |
12 | 2 files changed, 17 insertions(+), 2 deletions(-) | 18 | block/crypto.c | 15 ++------------- |
19 | 3 files changed, 25 insertions(+), 13 deletions(-) | ||
13 | 20 | ||
14 | diff --git a/include/block/block.h b/include/block/block.h | 21 | diff --git a/include/block/block.h b/include/block/block.h |
15 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/include/block/block.h | 23 | --- a/include/block/block.h |
17 | +++ b/include/block/block.h | 24 | +++ b/include/block/block.h |
18 | @@ -XXX,XX +XXX,XX @@ typedef enum { | 25 | @@ -XXX,XX +XXX,XX @@ int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, |
19 | */ | 26 | Error **errp); |
20 | BDRV_REQ_SERIALISING = 0x80, | 27 | void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base); |
21 | 28 | int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp); | |
22 | + /* Execute the request only if the operation can be offloaded or otherwise | 29 | +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs); |
23 | + * be executed efficiently, but return an error instead of using a slow | 30 | |
24 | + * fallback. */ | 31 | |
25 | + BDRV_REQ_NO_FALLBACK = 0x100, | 32 | typedef struct BdrvCheckResult { |
33 | diff --git a/block.c b/block.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/block.c | ||
36 | +++ b/block.c | ||
37 | @@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) | ||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | +void coroutine_fn bdrv_co_delete_file_noerr(BlockDriverState *bs) | ||
42 | +{ | ||
43 | + Error *local_err = NULL; | ||
44 | + int ret; | ||
26 | + | 45 | + |
27 | /* Mask of valid flags */ | 46 | + if (!bs) { |
28 | - BDRV_REQ_MASK = 0xff, | 47 | + return; |
29 | + BDRV_REQ_MASK = 0x1ff, | ||
30 | } BdrvRequestFlags; | ||
31 | |||
32 | typedef struct BlockSizes { | ||
33 | diff --git a/block/io.c b/block/io.c | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/block/io.c | ||
36 | +++ b/block/io.c | ||
37 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs, | ||
38 | unsigned int nb_sectors; | ||
39 | |||
40 | assert(!(flags & ~BDRV_REQ_MASK)); | ||
41 | + assert(!(flags & BDRV_REQ_NO_FALLBACK)); | ||
42 | |||
43 | if (!drv) { | ||
44 | return -ENOMEDIUM; | ||
45 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs, | ||
46 | int ret; | ||
47 | |||
48 | assert(!(flags & ~BDRV_REQ_MASK)); | ||
49 | + assert(!(flags & BDRV_REQ_NO_FALLBACK)); | ||
50 | |||
51 | if (!drv) { | ||
52 | return -ENOMEDIUM; | ||
53 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, | ||
54 | return -ENOMEDIUM; | ||
55 | } | ||
56 | |||
57 | + if ((flags & ~bs->supported_zero_flags) & BDRV_REQ_NO_FALLBACK) { | ||
58 | + return -ENOTSUP; | ||
59 | + } | 48 | + } |
60 | + | 49 | + |
61 | assert(alignment % bs->bl.request_alignment == 0); | 50 | + ret = bdrv_co_delete_file(bs, &local_err); |
62 | head = offset % alignment; | 51 | + /* |
63 | tail = (offset + bytes) % alignment; | 52 | + * ENOTSUP will happen if the block driver doesn't support |
64 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, | 53 | + * the 'bdrv_co_delete_file' interface. This is a predictable |
65 | assert(!bs->supported_zero_flags); | 54 | + * scenario and shouldn't be reported back to the user. |
66 | } | 55 | + */ |
67 | 56 | + if (ret == -ENOTSUP) { | |
68 | - if (ret == -ENOTSUP) { | 57 | + error_free(local_err); |
69 | + if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) { | 58 | + } else if (ret < 0) { |
70 | /* Fall back to bounce buffer if write zeroes is unsupported */ | 59 | + error_report_err(local_err); |
71 | BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE; | 60 | + } |
72 | 61 | +} | |
73 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_copy_range_internal( | ||
74 | BdrvTrackedRequest req; | ||
75 | int ret; | ||
76 | |||
77 | + /* TODO We can support BDRV_REQ_NO_FALLBACK here */ | ||
78 | + assert(!(read_flags & BDRV_REQ_NO_FALLBACK)); | ||
79 | + assert(!(write_flags & BDRV_REQ_NO_FALLBACK)); | ||
80 | + | 62 | + |
81 | if (!dst || !dst->bs) { | 63 | /** |
82 | return -ENOMEDIUM; | 64 | * Try to get @bs's logical and physical block size. |
65 | * On success, store them in @bsz struct and return 0. | ||
66 | diff --git a/block/crypto.c b/block/crypto.c | ||
67 | index XXXXXXX..XXXXXXX 100644 | ||
68 | --- a/block/crypto.c | ||
69 | +++ b/block/crypto.c | ||
70 | @@ -XXX,XX +XXX,XX @@ fail: | ||
71 | * If an error occurred, delete 'filename'. Even if the file existed | ||
72 | * beforehand, it has been truncated and corrupted in the process. | ||
73 | */ | ||
74 | - if (ret && bs) { | ||
75 | - Error *local_delete_err = NULL; | ||
76 | - int r_del = bdrv_co_delete_file(bs, &local_delete_err); | ||
77 | - /* | ||
78 | - * ENOTSUP will happen if the block driver doesn't support | ||
79 | - * the 'bdrv_co_delete_file' interface. This is a predictable | ||
80 | - * scenario and shouldn't be reported back to the user. | ||
81 | - */ | ||
82 | - if ((r_del < 0) && (r_del != -ENOTSUP)) { | ||
83 | - error_report_err(local_delete_err); | ||
84 | - } else { | ||
85 | - error_free(local_delete_err); | ||
86 | - } | ||
87 | + if (ret) { | ||
88 | + bdrv_co_delete_file_noerr(bs); | ||
83 | } | 89 | } |
90 | |||
91 | bdrv_unref(bs); | ||
84 | -- | 92 | -- |
85 | 2.20.1 | 93 | 2.29.2 |
86 | 94 | ||
87 | 95 | diff view generated by jsdifflib |
1 | Filter drivers that support .bdrv_co_pwrite_zeroes can safely advertise | 1 | From: Maxim Levitsky <mlevitsk@redhat.com> |
---|---|---|---|
2 | BDRV_REQ_NO_FALLBACK because they just forward the request flags to | ||
3 | their child node. | ||
4 | 2 | ||
3 | If the qcow initialization fails, we should remove the file if it was | ||
4 | already created, to avoid leaving stale files around. | ||
5 | |||
6 | We already do this for luks raw images. | ||
7 | |||
8 | Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> | ||
9 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
10 | Message-Id: <20201217170904.946013-4-mlevitsk@redhat.com> | ||
11 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
5 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
6 | Acked-by: Eric Blake <eblake@redhat.com> | ||
7 | --- | 13 | --- |
8 | block/blkdebug.c | 2 +- | 14 | block/qcow2.c | 8 +++++--- |
9 | block/copy-on-read.c | 7 +++---- | 15 | 1 file changed, 5 insertions(+), 3 deletions(-) |
10 | block/mirror.c | 3 ++- | ||
11 | block/raw-format.c | 2 +- | ||
12 | 4 files changed, 7 insertions(+), 7 deletions(-) | ||
13 | 16 | ||
14 | diff --git a/block/blkdebug.c b/block/blkdebug.c | 17 | diff --git a/block/qcow2.c b/block/qcow2.c |
15 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/block/blkdebug.c | 19 | --- a/block/qcow2.c |
17 | +++ b/block/blkdebug.c | 20 | +++ b/block/qcow2.c |
18 | @@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, | 21 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv, |
19 | bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | | 22 | |
20 | (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); | 23 | /* Create the qcow2 image (format layer) */ |
21 | bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | 24 | ret = qcow2_co_create(create_options, errp); |
22 | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & | 25 | +finish: |
23 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & | 26 | if (ret < 0) { |
24 | bs->file->bs->supported_zero_flags); | 27 | - goto finish; |
25 | ret = -EINVAL; | 28 | + bdrv_co_delete_file_noerr(bs); |
26 | 29 | + bdrv_co_delete_file_noerr(data_bs); | |
27 | diff --git a/block/copy-on-read.c b/block/copy-on-read.c | 30 | + } else { |
28 | index XXXXXXX..XXXXXXX 100644 | 31 | + ret = 0; |
29 | --- a/block/copy-on-read.c | ||
30 | +++ b/block/copy-on-read.c | ||
31 | @@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags, | ||
32 | } | 32 | } |
33 | 33 | ||
34 | bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | | 34 | - ret = 0; |
35 | - (BDRV_REQ_FUA & | 35 | -finish: |
36 | - bs->file->bs->supported_write_flags); | 36 | qobject_unref(qdict); |
37 | + (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); | 37 | bdrv_unref(bs); |
38 | 38 | bdrv_unref(data_bs); | |
39 | bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
40 | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & | ||
41 | - bs->file->bs->supported_zero_flags); | ||
42 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & | ||
43 | + bs->file->bs->supported_zero_flags); | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | diff --git a/block/mirror.c b/block/mirror.c | ||
48 | index XXXXXXX..XXXXXXX 100644 | ||
49 | --- a/block/mirror.c | ||
50 | +++ b/block/mirror.c | ||
51 | @@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs, | ||
52 | } | ||
53 | mirror_top_bs->total_sectors = bs->total_sectors; | ||
54 | mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED; | ||
55 | - mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED; | ||
56 | + mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
57 | + BDRV_REQ_NO_FALLBACK; | ||
58 | bs_opaque = g_new0(MirrorBDSOpaque, 1); | ||
59 | mirror_top_bs->opaque = bs_opaque; | ||
60 | bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs)); | ||
61 | diff --git a/block/raw-format.c b/block/raw-format.c | ||
62 | index XXXXXXX..XXXXXXX 100644 | ||
63 | --- a/block/raw-format.c | ||
64 | +++ b/block/raw-format.c | ||
65 | @@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, | ||
66 | bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
67 | (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); | ||
68 | bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | | ||
69 | - ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) & | ||
70 | + ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & | ||
71 | bs->file->bs->supported_zero_flags); | ||
72 | |||
73 | if (bs->probed && !bdrv_is_read_only(bs)) { | ||
74 | -- | 39 | -- |
75 | 2.20.1 | 40 | 2.29.2 |
76 | 41 | ||
77 | 42 | diff view generated by jsdifflib |
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 1 | Commit 357bda95 already tried to fix the order in monitor_cleanup() by |
---|---|---|---|
2 | moving shutdown of the dispatcher coroutine further to the start. | ||
3 | However, it didn't go far enough: | ||
2 | 4 | ||
3 | Test that mirror job actually resume on resume command after being | 5 | iothread_stop() makes sure that all pending work (bottom halves) in the |
4 | automatically paused on ENOSPC error. | 6 | AioContext of the monitor iothread is completed. iothread_destroy() |
7 | depends on this and fails an assertion if there is still a pending BH. | ||
5 | 8 | ||
6 | It's a follow-up test for 8d9648cbf3e | 9 | While the dispatcher coroutine is running, it will try to resume the |
7 | "blockjob: fix user pause in block_job_error_action" | 10 | monitor after taking a request out of the queue, which involves a BH. |
11 | The dispatcher is run until it terminates in the AIO_WAIT_WHILE() loop. | ||
12 | However, adding new BHs between iothread_stop() and iothread_destroy() | ||
13 | is forbidden. | ||
8 | 14 | ||
9 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 15 | Fix this by stopping the dispatcher first before shutting down the other |
10 | Tested-by: John Snow <jsnow@redhat.com> | 16 | parts of the monitor. This means we can now receive requests that aren't |
11 | Reviewed-by: John Snow <jsnow@redhat.com> | 17 | handled any more when QEMU is shutting down, but this is unlikely to be |
18 | a problem for QMP clients. | ||
19 | |||
20 | Fixes: 357bda9590784ff75803d52de43150d4107ed98e | ||
21 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
22 | Message-Id: <20210212172028.288825-2-kwolf@redhat.com> | ||
23 | Tested-by: Markus Armbruster <armbru@redhat.com> | ||
24 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 25 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
13 | --- | 26 | --- |
14 | tests/qemu-iotests/248 | 71 ++++++++++++++++++++++++++++++++++++++ | 27 | monitor/monitor.c | 25 +++++++++++++++---------- |
15 | tests/qemu-iotests/248.out | 8 +++++ | 28 | 1 file changed, 15 insertions(+), 10 deletions(-) |
16 | tests/qemu-iotests/group | 1 + | ||
17 | 3 files changed, 80 insertions(+) | ||
18 | create mode 100755 tests/qemu-iotests/248 | ||
19 | create mode 100644 tests/qemu-iotests/248.out | ||
20 | 29 | ||
21 | diff --git a/tests/qemu-iotests/248 b/tests/qemu-iotests/248 | 30 | diff --git a/monitor/monitor.c b/monitor/monitor.c |
22 | new file mode 100755 | 31 | index XXXXXXX..XXXXXXX 100644 |
23 | index XXXXXXX..XXXXXXX | 32 | --- a/monitor/monitor.c |
24 | --- /dev/null | 33 | +++ b/monitor/monitor.c |
25 | +++ b/tests/qemu-iotests/248 | 34 | @@ -XXX,XX +XXX,XX @@ void monitor_data_destroy(Monitor *mon) |
26 | @@ -XXX,XX +XXX,XX @@ | 35 | |
27 | +#!/usr/bin/env python | 36 | void monitor_cleanup(void) |
28 | +# | 37 | { |
29 | +# Test resume mirror after auto pause on ENOSPC | 38 | - /* |
30 | +# | 39 | - * We need to explicitly stop the I/O thread (but not destroy it), |
31 | +# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved. | 40 | - * clean up the monitor resources, then destroy the I/O thread since |
32 | +# | 41 | - * we need to unregister from chardev below in |
33 | +# This program is free software; you can redistribute it and/or modify | 42 | - * monitor_data_destroy(), and chardev is not thread-safe yet |
34 | +# it under the terms of the GNU General Public License as published by | 43 | - */ |
35 | +# the Free Software Foundation; either version 2 of the License, or | 44 | - if (mon_iothread) { |
36 | +# (at your option) any later version. | 45 | - iothread_stop(mon_iothread); |
37 | +# | 46 | - } |
38 | +# This program is distributed in the hope that it will be useful, | 47 | - |
39 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | 48 | /* |
40 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 49 | * The dispatcher needs to stop before destroying the monitor and |
41 | +# GNU General Public License for more details. | 50 | * the I/O thread. |
42 | +# | 51 | @@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void) |
43 | +# You should have received a copy of the GNU General Public License | 52 | * eventually terminates. qemu_aio_context is automatically |
44 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | 53 | * polled by calling AIO_WAIT_WHILE on it, but we must poll |
45 | +# | 54 | * iohandler_ctx manually. |
55 | + * | ||
56 | + * Letting the iothread continue while shutting down the dispatcher | ||
57 | + * means that new requests may still be coming in. This is okay, | ||
58 | + * we'll just leave them in the queue without sending a response | ||
59 | + * and monitor_data_destroy() will free them. | ||
60 | */ | ||
61 | qmp_dispatcher_co_shutdown = true; | ||
62 | if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) { | ||
63 | @@ -XXX,XX +XXX,XX @@ void monitor_cleanup(void) | ||
64 | (aio_poll(iohandler_get_aio_context(), false), | ||
65 | qatomic_mb_read(&qmp_dispatcher_co_busy))); | ||
66 | |||
67 | + /* | ||
68 | + * We need to explicitly stop the I/O thread (but not destroy it), | ||
69 | + * clean up the monitor resources, then destroy the I/O thread since | ||
70 | + * we need to unregister from chardev below in | ||
71 | + * monitor_data_destroy(), and chardev is not thread-safe yet | ||
72 | + */ | ||
73 | + if (mon_iothread) { | ||
74 | + iothread_stop(mon_iothread); | ||
75 | + } | ||
46 | + | 76 | + |
47 | +import iotests | 77 | /* Flush output buffers and destroy monitors */ |
48 | +from iotests import qemu_img_create, qemu_io, file_path, filter_qmp_testfiles | 78 | qemu_mutex_lock(&monitor_lock); |
49 | + | 79 | monitor_destroyed = true; |
50 | +iotests.verify_image_format(supported_fmts=['qcow2']) | ||
51 | + | ||
52 | +source, target = file_path('source', 'target') | ||
53 | +size = 5 * 1024 * 1024 | ||
54 | +limit = 2 * 1024 * 1024 | ||
55 | + | ||
56 | +qemu_img_create('-f', iotests.imgfmt, source, str(size)) | ||
57 | +qemu_img_create('-f', iotests.imgfmt, target, str(size)) | ||
58 | +qemu_io('-c', 'write 0 {}'.format(size), source) | ||
59 | + | ||
60 | +# raw format don't like empty files | ||
61 | +qemu_io('-c', 'write 0 {}'.format(size), target) | ||
62 | + | ||
63 | +vm = iotests.VM().add_drive(source) | ||
64 | +vm.launch() | ||
65 | + | ||
66 | +blockdev_opts = { | ||
67 | + 'driver': iotests.imgfmt, | ||
68 | + 'node-name': 'target', | ||
69 | + 'file': { | ||
70 | + 'driver': 'raw', | ||
71 | + 'size': limit, | ||
72 | + 'file': { | ||
73 | + 'driver': 'file', | ||
74 | + 'filename': target | ||
75 | + } | ||
76 | + } | ||
77 | +} | ||
78 | +vm.qmp_log('blockdev-add', filters=[filter_qmp_testfiles], **blockdev_opts) | ||
79 | + | ||
80 | +vm.qmp_log('blockdev-mirror', device='drive0', sync='full', target='target', | ||
81 | + on_target_error='enospc') | ||
82 | + | ||
83 | +vm.event_wait('JOB_STATUS_CHANGE', timeout=3.0, | ||
84 | + match={'data': {'status': 'paused'}}) | ||
85 | + | ||
86 | +# drop other cached events, to not interfere with further wait for 'running' | ||
87 | +vm.get_qmp_events() | ||
88 | + | ||
89 | +del blockdev_opts['file']['size'] | ||
90 | +vm.qmp_log('x-blockdev-reopen', filters=[filter_qmp_testfiles], | ||
91 | + **blockdev_opts) | ||
92 | + | ||
93 | +vm.qmp_log('block-job-resume', device='drive0') | ||
94 | +vm.event_wait('JOB_STATUS_CHANGE', timeout=1.0, | ||
95 | + match={'data': {'status': 'running'}}) | ||
96 | + | ||
97 | +vm.shutdown() | ||
98 | diff --git a/tests/qemu-iotests/248.out b/tests/qemu-iotests/248.out | ||
99 | new file mode 100644 | ||
100 | index XXXXXXX..XXXXXXX | ||
101 | --- /dev/null | ||
102 | +++ b/tests/qemu-iotests/248.out | ||
103 | @@ -XXX,XX +XXX,XX @@ | ||
104 | +{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}, "size": 2097152}, "node-name": "target"}} | ||
105 | +{"return": {}} | ||
106 | +{"execute": "blockdev-mirror", "arguments": {"device": "drive0", "on-target-error": "enospc", "sync": "full", "target": "target"}} | ||
107 | +{"return": {}} | ||
108 | +{"execute": "x-blockdev-reopen", "arguments": {"driver": "qcow2", "file": {"driver": "raw", "file": {"driver": "file", "filename": "TEST_DIR/PID-target"}}, "node-name": "target"}} | ||
109 | +{"return": {}} | ||
110 | +{"execute": "block-job-resume", "arguments": {"device": "drive0"}} | ||
111 | +{"return": {}} | ||
112 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
113 | index XXXXXXX..XXXXXXX 100644 | ||
114 | --- a/tests/qemu-iotests/group | ||
115 | +++ b/tests/qemu-iotests/group | ||
116 | @@ -XXX,XX +XXX,XX @@ | ||
117 | 245 rw auto | ||
118 | 246 rw auto quick | ||
119 | 247 rw auto quick | ||
120 | +248 rw auto quick | ||
121 | -- | 80 | -- |
122 | 2.20.1 | 81 | 2.29.2 |
123 | 82 | ||
124 | 83 | diff view generated by jsdifflib |
1 | There is only a single caller of bdrv_make_zero(), which is qemu-img | 1 | Before this patch, monitor_qmp_dispatcher_co() used to check whether |
---|---|---|---|
2 | convert. If the function fails, we just fall back to a different method | 2 | shutdown is requested only when it would have to wait for new requests. |
3 | of zeroing out blocks on the target image. There is no good reason to | 3 | If there were still some queued requests, it would try to execute all of |
4 | print error messages on stderr when the higher level operation will | 4 | them before shutting down. |
5 | actually succeed. | 5 | |
6 | This can be surprising when the queued QMP commands take long or hang | ||
7 | because Ctrl-C may not actually exit QEMU as soon as possible. | ||
8 | |||
9 | Change monitor_qmp_dispatcher_co() so that it additionally checks | ||
10 | whether shutdown is request before it gets a new request from the queue. | ||
6 | 11 | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
8 | Acked-by: Eric Blake <eblake@redhat.com> | 13 | Message-Id: <20210212172028.288825-3-kwolf@redhat.com> |
14 | Tested-by: Markus Armbruster <armbru@redhat.com> | ||
15 | Reviewed-by: Markus Armbruster <armbru@redhat.com> | ||
16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
9 | --- | 17 | --- |
10 | block/io.c | 4 ---- | 18 | monitor/qmp.c | 5 +++++ |
11 | 1 file changed, 4 deletions(-) | 19 | 1 file changed, 5 insertions(+) |
12 | 20 | ||
13 | diff --git a/block/io.c b/block/io.c | 21 | diff --git a/monitor/qmp.c b/monitor/qmp.c |
14 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/block/io.c | 23 | --- a/monitor/qmp.c |
16 | +++ b/block/io.c | 24 | +++ b/monitor/qmp.c |
17 | @@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) | 25 | @@ -XXX,XX +XXX,XX @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) |
18 | } | 26 | */ |
19 | ret = bdrv_block_status(bs, offset, bytes, &bytes, NULL, NULL); | 27 | qatomic_mb_set(&qmp_dispatcher_co_busy, false); |
20 | if (ret < 0) { | 28 | |
21 | - error_report("error getting block status at offset %" PRId64 ": %s", | 29 | + /* On shutdown, don't take any more requests from the queue */ |
22 | - offset, strerror(-ret)); | 30 | + if (qmp_dispatcher_co_shutdown) { |
23 | return ret; | 31 | + return; |
24 | } | 32 | + } |
25 | if (ret & BDRV_BLOCK_ZERO) { | 33 | + |
26 | @@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags) | 34 | while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) { |
27 | } | 35 | /* |
28 | ret = bdrv_pwrite_zeroes(child, offset, bytes, flags); | 36 | * No more requests to process. Wait to be reentered from |
29 | if (ret < 0) { | ||
30 | - error_report("error writing zeroes at offset %" PRId64 ": %s", | ||
31 | - offset, strerror(-ret)); | ||
32 | return ret; | ||
33 | } | ||
34 | offset += bytes; | ||
35 | -- | 37 | -- |
36 | 2.20.1 | 38 | 2.29.2 |
37 | 39 | ||
38 | 40 | diff view generated by jsdifflib |