1 | The following changes since commit ba29883206d92a29ad5a466e679ccfc2ee6132ef: | 1 | The following changes since commit 77d472291812cf04f97974dadbda767e59e31fde: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20200310' into staging (2020-03-10 16:50:28 +0000) | 3 | Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20170707-tag' into staging (2017-07-10 10:29:11 +0100) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the git repository at: |
6 | |||
6 | 7 | ||
7 | git://repo.or.cz/qemu/kevin.git tags/for-upstream | 8 | git://repo.or.cz/qemu/kevin.git tags/for-upstream |
8 | 9 | ||
9 | for you to fetch changes up to 8bb3b023f2055054ee119cb45b42d2b14be7fc8a: | 10 | for you to fetch changes up to 51b0a488882328f8f02519bb47ca7e0e7fbe12ff: |
10 | 11 | ||
11 | qemu-iotests: adding LUKS cleanup for non-UTF8 secret error (2020-03-11 15:54:38 +0100) | 12 | block: Make bdrv_is_allocated_above() byte-based (2017-07-10 13:18:07 +0200) |
12 | 13 | ||
13 | ---------------------------------------------------------------- | 14 | ---------------------------------------------------------------- |
14 | Block layer patches: | 15 | Block layer patches |
15 | |||
16 | - Relax restrictions for blockdev-snapshot (allows libvirt to do live | ||
17 | storage migration with blockdev-mirror) | ||
18 | - luks: Delete created files when block_crypto_co_create_opts_luks fails | ||
19 | - Fix memleaks in qmp_object_add | ||
20 | 16 | ||
21 | ---------------------------------------------------------------- | 17 | ---------------------------------------------------------------- |
22 | Daniel Henrique Barboza (4): | 18 | Daniel P. Berrange (1): |
23 | block: introducing 'bdrv_co_delete_file' interface | 19 | qemu-img: drop -e and -6 options from the 'create' & 'convert' commands |
24 | block.c: adding bdrv_co_delete_file | ||
25 | crypto.c: cleanup created file when block_crypto_co_create_opts_luks fails | ||
26 | qemu-iotests: adding LUKS cleanup for non-UTF8 secret error | ||
27 | 20 | ||
28 | Kevin Wolf (6): | 21 | Eric Blake (25): |
29 | block: Make bdrv_get_cumulative_perm() public | 22 | qemu-io: Don't die on second open |
30 | block: Relax restrictions for blockdev-snapshot | 23 | block: Guarantee that *file is set on bdrv_get_block_status() |
31 | iotests: Fix run_job() with use_log=False | 24 | block: Simplify use of BDRV_BLOCK_RAW |
32 | iotests: Test mirror with temporarily disabled target backing file | 25 | blkdebug: Support .bdrv_co_get_block_status |
33 | block: Fix cross-AioContext blockdev-snapshot | 26 | blockjob: Track job ratelimits via bytes, not sectors |
34 | iotests: Add iothread cases to 155 | 27 | trace: Show blockjob actions via bytes, not sectors |
28 | stream: Switch stream_populate() to byte-based | ||
29 | stream: Drop reached_end for stream_complete() | ||
30 | stream: Switch stream_run() to byte-based | ||
31 | commit: Switch commit_populate() to byte-based | ||
32 | commit: Switch commit_run() to byte-based | ||
33 | mirror: Switch MirrorBlockJob to byte-based | ||
34 | mirror: Switch mirror_do_zero_or_discard() to byte-based | ||
35 | mirror: Update signature of mirror_clip_sectors() | ||
36 | mirror: Switch mirror_cow_align() to byte-based | ||
37 | mirror: Switch mirror_do_read() to byte-based | ||
38 | mirror: Switch mirror_iteration() to byte-based | ||
39 | block: Drop unused bdrv_round_sectors_to_clusters() | ||
40 | backup: Switch BackupBlockJob to byte-based | ||
41 | backup: Switch block_backup.h to byte-based | ||
42 | backup: Switch backup_do_cow() to byte-based | ||
43 | backup: Switch backup_run() to byte-based | ||
44 | block: Make bdrv_is_allocated() byte-based | ||
45 | block: Minimize raw use of bds->total_sectors | ||
46 | block: Make bdrv_is_allocated_above() byte-based | ||
35 | 47 | ||
36 | Pan Nengyuan (1): | 48 | Hervé Poussineau (13): |
37 | qom-qmp-cmds: fix two memleaks in qmp_object_add | 49 | vvfat: fix qemu-img map and qemu-img convert |
50 | vvfat: replace tabs by 8 spaces | ||
51 | vvfat: fix typos | ||
52 | vvfat: rename useless enumeration values | ||
53 | vvfat: introduce offset_to_bootsector, offset_to_fat and offset_to_root_dir | ||
54 | vvfat: fix field names in FAT12/FAT16 and FAT32 boot sectors | ||
55 | vvfat: always create . and .. entries at first and in that order | ||
56 | vvfat: correctly create long names for non-ASCII filenames | ||
57 | vvfat: correctly create base short names for non-ASCII filenames | ||
58 | vvfat: correctly generate numeric-tail of short file names | ||
59 | vvfat: limit number of entries in root directory in FAT12/FAT16 | ||
60 | vvfat: handle KANJI lead byte 0xe5 | ||
61 | vvfat: change OEM name to 'MSWIN4.1' | ||
38 | 62 | ||
39 | Peter Krempa (1): | 63 | Thomas Huth (1): |
40 | qapi: Add '@allow-write-only-overlay' feature for 'blockdev-snapshot' | 64 | blockdev: Print a warning for legacy drive options that belong to -device |
41 | 65 | ||
42 | Philippe Mathieu-Daudé (1): | 66 | block/backup.c | 128 +-- |
43 | tests/qemu-iotests: Fix socket_scm_helper build path | 67 | block/blkdebug.c | 11 + |
68 | block/commit.c | 56 +- | ||
69 | block/io.c | 102 +- | ||
70 | block/mirror.c | 310 +++--- | ||
71 | block/raw-format.c | 2 +- | ||
72 | block/replication.c | 29 +- | ||
73 | block/stream.c | 37 +- | ||
74 | block/trace-events | 14 +- | ||
75 | block/vpc.c | 2 +- | ||
76 | block/vvfat.c | 2336 ++++++++++++++++++++++-------------------- | ||
77 | blockdev.c | 14 + | ||
78 | include/block/block.h | 16 +- | ||
79 | include/block/block_backup.h | 11 +- | ||
80 | include/qemu/ratelimit.h | 3 +- | ||
81 | migration/block.c | 16 +- | ||
82 | qemu-img.c | 41 +- | ||
83 | qemu-io-cmds.c | 70 +- | ||
84 | qemu-io.c | 7 +- | ||
85 | qemu-options.hx | 9 +- | ||
86 | tests/qemu-iotests/060.out | 1 + | ||
87 | tests/qemu-iotests/114.out | 5 +- | ||
88 | tests/qemu-iotests/153.out | 6 + | ||
89 | tests/qemu-iotests/177 | 3 + | ||
90 | tests/qemu-iotests/177.out | 5 + | ||
91 | 25 files changed, 1675 insertions(+), 1559 deletions(-) | ||
44 | 92 | ||
45 | qapi/block-core.json | 9 ++++- | ||
46 | include/block/block.h | 1 + | ||
47 | include/block/block_int.h | 7 ++++ | ||
48 | block.c | 33 ++++++++++++++-- | ||
49 | block/crypto.c | 18 +++++++++ | ||
50 | block/file-posix.c | 23 +++++++++++ | ||
51 | blockdev.c | 30 ++++----------- | ||
52 | qom/qom-qmp-cmds.c | 16 +++----- | ||
53 | tests/qemu-iotests/iotests.py | 5 ++- | ||
54 | tests/Makefile.include | 1 + | ||
55 | tests/qemu-iotests/085.out | 4 +- | ||
56 | tests/qemu-iotests/155 | 88 ++++++++++++++++++++++++++++++++++++------- | ||
57 | tests/qemu-iotests/155.out | 4 +- | ||
58 | tests/qemu-iotests/282 | 67 ++++++++++++++++++++++++++++++++ | ||
59 | tests/qemu-iotests/282.out | 11 ++++++ | ||
60 | tests/qemu-iotests/group | 1 + | ||
61 | tests/qtest/Makefile.include | 1 - | ||
62 | 17 files changed, 262 insertions(+), 57 deletions(-) | ||
63 | create mode 100755 tests/qemu-iotests/282 | ||
64 | create mode 100644 tests/qemu-iotests/282.out | ||
65 | |||
66 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Pan Nengyuan <pannengyuan@huawei.com> | ||
2 | 1 | ||
3 | 'type/id' forgot to free in qmp_object_add, this patch fix that. | ||
4 | |||
5 | The leak stack: | ||
6 | Direct leak of 84 byte(s) in 6 object(s) allocated from: | ||
7 | #0 0x7fe2a5ebf768 in __interceptor_malloc (/lib64/libasan.so.5+0xef768) | ||
8 | #1 0x7fe2a5044445 in g_malloc (/lib64/libglib-2.0.so.0+0x52445) | ||
9 | #2 0x7fe2a505dd92 in g_strdup (/lib64/libglib-2.0.so.0+0x6bd92) | ||
10 | #3 0x56344954e692 in qmp_object_add /mnt/sdb/qemu-new/qemu_test/qemu/qom/qom-qmp-cmds.c:258 | ||
11 | #4 0x563449960f5a in do_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:132 | ||
12 | #5 0x563449960f5a in qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:175 | ||
13 | #6 0x563449498a30 in monitor_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:145 | ||
14 | #7 0x56344949a64f in monitor_qmp_bh_dispatcher /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:234 | ||
15 | #8 0x563449a92a3a in aio_bh_call /mnt/sdb/qemu-new/qemu_test/qemu/util/async.c:136 | ||
16 | |||
17 | Direct leak of 54 byte(s) in 6 object(s) allocated from: | ||
18 | #0 0x7fe2a5ebf768 in __interceptor_malloc (/lib64/libasan.so.5+0xef768) | ||
19 | #1 0x7fe2a5044445 in g_malloc (/lib64/libglib-2.0.so.0+0x52445) | ||
20 | #2 0x7fe2a505dd92 in g_strdup (/lib64/libglib-2.0.so.0+0x6bd92) | ||
21 | #3 0x56344954e6c4 in qmp_object_add /mnt/sdb/qemu-new/qemu_test/qemu/qom/qom-qmp-cmds.c:267 | ||
22 | #4 0x563449960f5a in do_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:132 | ||
23 | #5 0x563449960f5a in qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qmp-dispatch.c:175 | ||
24 | #6 0x563449498a30 in monitor_qmp_dispatch /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:145 | ||
25 | #7 0x56344949a64f in monitor_qmp_bh_dispatcher /mnt/sdb/qemu-new/qemu_test/qemu/monitor/qmp.c:234 | ||
26 | #8 0x563449a92a3a in aio_bh_call /mnt/sdb/qemu-new/qemu_test/qemu/util/async.c:136 | ||
27 | |||
28 | Fixes: 5f07c4d60d091320186e7b0edaf9ed2cc16b2d1e | ||
29 | Reported-by: Euler Robot <euler.robot@huawei.com> | ||
30 | Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com> | ||
31 | Message-Id: <20200310064640.5059-1-pannengyuan@huawei.com> | ||
32 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
33 | Acked-by: Igor Mammedov <imammedo@redhat.com> | ||
34 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
35 | --- | ||
36 | qom/qom-qmp-cmds.c | 16 ++++++---------- | ||
37 | 1 file changed, 6 insertions(+), 10 deletions(-) | ||
38 | |||
39 | diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c | ||
40 | index XXXXXXX..XXXXXXX 100644 | ||
41 | --- a/qom/qom-qmp-cmds.c | ||
42 | +++ b/qom/qom-qmp-cmds.c | ||
43 | @@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp) | ||
44 | QDict *pdict; | ||
45 | Visitor *v; | ||
46 | Object *obj; | ||
47 | - const char *type; | ||
48 | - const char *id; | ||
49 | + g_autofree char *type = NULL; | ||
50 | + g_autofree char *id = NULL; | ||
51 | |||
52 | - type = qdict_get_try_str(qdict, "qom-type"); | ||
53 | + type = g_strdup(qdict_get_try_str(qdict, "qom-type")); | ||
54 | if (!type) { | ||
55 | error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); | ||
56 | return; | ||
57 | - } else { | ||
58 | - type = g_strdup(type); | ||
59 | - qdict_del(qdict, "qom-type"); | ||
60 | } | ||
61 | + qdict_del(qdict, "qom-type"); | ||
62 | |||
63 | - id = qdict_get_try_str(qdict, "id"); | ||
64 | + id = g_strdup(qdict_get_try_str(qdict, "id")); | ||
65 | if (!id) { | ||
66 | error_setg(errp, QERR_MISSING_PARAMETER, "id"); | ||
67 | return; | ||
68 | - } else { | ||
69 | - id = g_strdup(id); | ||
70 | - qdict_del(qdict, "id"); | ||
71 | } | ||
72 | + qdict_del(qdict, "id"); | ||
73 | |||
74 | props = qdict_get(qdict, "props"); | ||
75 | if (props) { | ||
76 | -- | ||
77 | 2.20.1 | ||
78 | |||
79 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
2 | Message-Id: <20200310113831.27293-2-kwolf@redhat.com> | ||
3 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | ||
4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
5 | --- | ||
6 | include/block/block_int.h | 3 +++ | ||
7 | block.c | 6 ++---- | ||
8 | 2 files changed, 5 insertions(+), 4 deletions(-) | ||
9 | 1 | ||
10 | diff --git a/include/block/block_int.h b/include/block/block_int.h | ||
11 | index XXXXXXX..XXXXXXX 100644 | ||
12 | --- a/include/block/block_int.h | ||
13 | +++ b/include/block/block_int.h | ||
14 | @@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, | ||
15 | void *opaque, Error **errp); | ||
16 | void bdrv_root_unref_child(BdrvChild *child); | ||
17 | |||
18 | +void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm, | ||
19 | + uint64_t *shared_perm); | ||
20 | + | ||
21 | /** | ||
22 | * Sets a BdrvChild's permissions. Avoid if the parent is a BDS; use | ||
23 | * bdrv_child_refresh_perms() instead and make the parent's | ||
24 | diff --git a/block.c b/block.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/block.c | ||
27 | +++ b/block.c | ||
28 | @@ -XXX,XX +XXX,XX @@ static int bdrv_child_check_perm(BdrvChild *c, BlockReopenQueue *q, | ||
29 | bool *tighten_restrictions, Error **errp); | ||
30 | static void bdrv_child_abort_perm_update(BdrvChild *c); | ||
31 | static void bdrv_child_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared); | ||
32 | -static void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm, | ||
33 | - uint64_t *shared_perm); | ||
34 | |||
35 | typedef struct BlockReopenQueueEntry { | ||
36 | bool prepared; | ||
37 | @@ -XXX,XX +XXX,XX @@ static void bdrv_set_perm(BlockDriverState *bs, uint64_t cumulative_perms, | ||
38 | } | ||
39 | } | ||
40 | |||
41 | -static void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm, | ||
42 | - uint64_t *shared_perm) | ||
43 | +void bdrv_get_cumulative_perm(BlockDriverState *bs, uint64_t *perm, | ||
44 | + uint64_t *shared_perm) | ||
45 | { | ||
46 | BdrvChild *c; | ||
47 | uint64_t cumulative_perms = 0; | ||
48 | -- | ||
49 | 2.20.1 | ||
50 | |||
51 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | blockdev-snapshot returned an error if the overlay was already in use, | ||
2 | which it defined as having any BlockBackend parent. This is in fact both | ||
3 | too strict (some parents can tolerate the change of visible data caused | ||
4 | by attaching a backing file) and too loose (some non-BlockBackend | ||
5 | parents may not be happy with it). | ||
6 | 1 | ||
7 | One important use case that is prevented by the too strict check is live | ||
8 | storage migration with blockdev-mirror. Here, the target node is | ||
9 | usually opened without a backing file so that the active layer is | ||
10 | mirrored while its backing chain can be copied in the background. | ||
11 | |||
12 | The backing chain should be attached to the mirror target node when | ||
13 | finalising the job, just before switching the users of the source node | ||
14 | to the new copy (at which point the mirror job still has a reference to | ||
15 | the node). drive-mirror did this automatically, but with blockdev-mirror | ||
16 | this is the job of the QMP client, so it needs a way to do this. | ||
17 | |||
18 | blockdev-snapshot is the obvious way, so this patch makes it work in | ||
19 | this scenario. The new condition is that no parent uses CONSISTENT_READ | ||
20 | permissions. This will ensure that the operation will still be blocked | ||
21 | when the node is attached to the guest device, so blockdev-snapshot | ||
22 | remains safe. | ||
23 | |||
24 | (For the sake of completeness, x-blockdev-reopen can be used to achieve | ||
25 | the same, however it is a big hammer, performs the graph change | ||
26 | completely unchecked and is still experimental. So even with the option | ||
27 | of using x-blockdev-reopen, there are reasons why blockdev-snapshot | ||
28 | should be able to perform this operation.) | ||
29 | |||
30 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
31 | Message-Id: <20200310113831.27293-3-kwolf@redhat.com> | ||
32 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | ||
33 | Tested-by: Peter Krempa <pkrempa@redhat.com> | ||
34 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
35 | --- | ||
36 | blockdev.c | 14 ++++++++------ | ||
37 | tests/qemu-iotests/085.out | 4 ++-- | ||
38 | 2 files changed, 10 insertions(+), 8 deletions(-) | ||
39 | |||
40 | diff --git a/blockdev.c b/blockdev.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/blockdev.c | ||
43 | +++ b/blockdev.c | ||
44 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
45 | TransactionAction *action = common->action; | ||
46 | AioContext *aio_context; | ||
47 | AioContext *old_context; | ||
48 | + uint64_t perm, shared; | ||
49 | int ret; | ||
50 | |||
51 | /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar | ||
52 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
53 | goto out; | ||
54 | } | ||
55 | |||
56 | - if (bdrv_has_blk(state->new_bs)) { | ||
57 | + /* | ||
58 | + * Allow attaching a backing file to an overlay that's already in use only | ||
59 | + * if the parents don't assume that they are already seeing a valid image. | ||
60 | + * (Specifically, allow it as a mirror target, which is write-only access.) | ||
61 | + */ | ||
62 | + bdrv_get_cumulative_perm(state->new_bs, &perm, &shared); | ||
63 | + if (perm & BLK_PERM_CONSISTENT_READ) { | ||
64 | error_setg(errp, "The overlay is already in use"); | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | - if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, | ||
69 | - errp)) { | ||
70 | - goto out; | ||
71 | - } | ||
72 | - | ||
73 | if (state->new_bs->backing != NULL) { | ||
74 | error_setg(errp, "The overlay already has a backing image"); | ||
75 | goto out; | ||
76 | diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out | ||
77 | index XXXXXXX..XXXXXXX 100644 | ||
78 | --- a/tests/qemu-iotests/085.out | ||
79 | +++ b/tests/qemu-iotests/085.out | ||
80 | @@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f | ||
81 | === Invalid command - cannot create a snapshot using a file BDS === | ||
82 | |||
83 | { 'execute': 'blockdev-snapshot', 'arguments': { 'node':'virtio0', 'overlay':'file_12' } } | ||
84 | -{"error": {"class": "GenericError", "desc": "The overlay does not support backing images"}} | ||
85 | +{"error": {"class": "GenericError", "desc": "The overlay is already in use"}} | ||
86 | |||
87 | === Invalid command - snapshot node used as active layer === | ||
88 | |||
89 | @@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/12-snapshot-v0.IMGFMT', fmt=IMGFMT size=134217728 backing_f | ||
90 | === Invalid command - snapshot node used as backing hd === | ||
91 | |||
92 | { 'execute': 'blockdev-snapshot', 'arguments': { 'node': 'virtio0', 'overlay':'snap_11' } } | ||
93 | -{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node is used as backing hd of 'snap_12'"}} | ||
94 | +{"error": {"class": "GenericError", "desc": "The overlay is already in use"}} | ||
95 | |||
96 | === Invalid command - snapshot node has a backing image === | ||
97 | |||
98 | -- | ||
99 | 2.20.1 | ||
100 | |||
101 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The 'job-complete' QMP command should be run with qmp() rather than | ||
2 | qmp_log() if use_log=False is passed. | ||
3 | 1 | ||
4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
5 | Message-Id: <20200310113831.27293-4-kwolf@redhat.com> | ||
6 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
8 | --- | ||
9 | tests/qemu-iotests/iotests.py | 5 ++++- | ||
10 | 1 file changed, 4 insertions(+), 1 deletion(-) | ||
11 | |||
12 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/tests/qemu-iotests/iotests.py | ||
15 | +++ b/tests/qemu-iotests/iotests.py | ||
16 | @@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine): | ||
17 | if use_log: | ||
18 | log('Job failed: %s' % (j['error'])) | ||
19 | elif status == 'ready': | ||
20 | - self.qmp_log('job-complete', id=job) | ||
21 | + if use_log: | ||
22 | + self.qmp_log('job-complete', id=job) | ||
23 | + else: | ||
24 | + self.qmp('job-complete', id=job) | ||
25 | elif status == 'pending' and not auto_finalize: | ||
26 | if pre_finalize: | ||
27 | pre_finalize() | ||
28 | -- | ||
29 | 2.20.1 | ||
30 | |||
31 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The newly tested scenario is a common live storage migration scenario: | ||
2 | The target node is opened without a backing file so that the active | ||
3 | layer is mirrored while its backing chain can be copied in the | ||
4 | background. | ||
5 | 1 | ||
6 | The backing chain should be attached to the mirror target node when | ||
7 | finalising the job, just before switching the users of the source node | ||
8 | to the new copy (at which point the mirror job still has a reference to | ||
9 | the node). drive-mirror did this automatically, but with blockdev-mirror | ||
10 | this is the job of the QMP client. | ||
11 | |||
12 | This patch adds test cases for two ways to achieve the desired result, | ||
13 | using either x-blockdev-reopen or blockdev-snapshot. | ||
14 | |||
15 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
16 | Message-Id: <20200310113831.27293-5-kwolf@redhat.com> | ||
17 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | ||
18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
19 | --- | ||
20 | tests/qemu-iotests/155 | 56 ++++++++++++++++++++++++++++++++++---- | ||
21 | tests/qemu-iotests/155.out | 4 +-- | ||
22 | 2 files changed, 53 insertions(+), 7 deletions(-) | ||
23 | |||
24 | diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155 | ||
25 | index XXXXXXX..XXXXXXX 100755 | ||
26 | --- a/tests/qemu-iotests/155 | ||
27 | +++ b/tests/qemu-iotests/155 | ||
28 | @@ -XXX,XX +XXX,XX @@ target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt) | ||
29 | # image during runtime, only makes sense if | ||
30 | # target_blockdev_backing is not None | ||
31 | # (None: same as target_backing) | ||
32 | +# target_open_with_backing: If True, the target image is added with its backing | ||
33 | +# chain opened right away. If False, blockdev-add | ||
34 | +# opens it without a backing file and job completion | ||
35 | +# is supposed to open the backing chain. | ||
36 | |||
37 | class BaseClass(iotests.QMPTestCase): | ||
38 | target_blockdev_backing = None | ||
39 | target_real_backing = None | ||
40 | + target_open_with_backing = True | ||
41 | |||
42 | def setUp(self): | ||
43 | qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K') | ||
44 | @@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase): | ||
45 | options = { 'node-name': 'target', | ||
46 | 'driver': iotests.imgfmt, | ||
47 | 'file': { 'driver': 'file', | ||
48 | + 'node-name': 'target-file', | ||
49 | 'filename': target_img } } | ||
50 | - if self.target_blockdev_backing: | ||
51 | - options['backing'] = self.target_blockdev_backing | ||
52 | + | ||
53 | + if not self.target_open_with_backing: | ||
54 | + options['backing'] = None | ||
55 | + elif self.target_blockdev_backing: | ||
56 | + options['backing'] = self.target_blockdev_backing | ||
57 | |||
58 | result = self.vm.qmp('blockdev-add', **options) | ||
59 | self.assert_qmp(result, 'return', {}) | ||
60 | @@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase): | ||
61 | # cmd: Mirroring command to execute, either drive-mirror or blockdev-mirror | ||
62 | |||
63 | class MirrorBaseClass(BaseClass): | ||
64 | + def openBacking(self): | ||
65 | + pass | ||
66 | + | ||
67 | def runMirror(self, sync): | ||
68 | if self.cmd == 'blockdev-mirror': | ||
69 | result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source', | ||
70 | - sync=sync, target='target') | ||
71 | + sync=sync, target='target', | ||
72 | + auto_finalize=False) | ||
73 | else: | ||
74 | if self.existing: | ||
75 | mode = 'existing' | ||
76 | @@ -XXX,XX +XXX,XX @@ class MirrorBaseClass(BaseClass): | ||
77 | result = self.vm.qmp(self.cmd, job_id='mirror-job', device='source', | ||
78 | sync=sync, target=target_img, | ||
79 | format=iotests.imgfmt, mode=mode, | ||
80 | - node_name='target') | ||
81 | + node_name='target', auto_finalize=False) | ||
82 | |||
83 | self.assert_qmp(result, 'return', {}) | ||
84 | |||
85 | - self.complete_and_wait('mirror-job') | ||
86 | + self.vm.run_job('mirror-job', use_log=False, auto_finalize=False, | ||
87 | + pre_finalize=self.openBacking, auto_dismiss=True) | ||
88 | |||
89 | def testFull(self): | ||
90 | self.runMirror('full') | ||
91 | @@ -XXX,XX +XXX,XX @@ class TestBlockdevMirrorForcedBacking(MirrorBaseClass): | ||
92 | target_blockdev_backing = { 'driver': 'null-co' } | ||
93 | target_real_backing = 'null-co://' | ||
94 | |||
95 | +# Attach the backing chain only during completion, with blockdev-reopen | ||
96 | +class TestBlockdevMirrorReopen(MirrorBaseClass): | ||
97 | + cmd = 'blockdev-mirror' | ||
98 | + existing = True | ||
99 | + target_backing = 'null-co://' | ||
100 | + target_open_with_backing = False | ||
101 | + | ||
102 | + def openBacking(self): | ||
103 | + if not self.target_open_with_backing: | ||
104 | + result = self.vm.qmp('blockdev-add', node_name="backing", | ||
105 | + driver="null-co") | ||
106 | + self.assert_qmp(result, 'return', {}) | ||
107 | + result = self.vm.qmp('x-blockdev-reopen', node_name="target", | ||
108 | + driver=iotests.imgfmt, file="target-file", | ||
109 | + backing="backing") | ||
110 | + self.assert_qmp(result, 'return', {}) | ||
111 | + | ||
112 | +# Attach the backing chain only during completion, with blockdev-snapshot | ||
113 | +class TestBlockdevMirrorSnapshot(MirrorBaseClass): | ||
114 | + cmd = 'blockdev-mirror' | ||
115 | + existing = True | ||
116 | + target_backing = 'null-co://' | ||
117 | + target_open_with_backing = False | ||
118 | + | ||
119 | + def openBacking(self): | ||
120 | + if not self.target_open_with_backing: | ||
121 | + result = self.vm.qmp('blockdev-add', node_name="backing", | ||
122 | + driver="null-co") | ||
123 | + self.assert_qmp(result, 'return', {}) | ||
124 | + result = self.vm.qmp('blockdev-snapshot', node="backing", | ||
125 | + overlay="target") | ||
126 | + self.assert_qmp(result, 'return', {}) | ||
127 | |||
128 | class TestCommit(BaseClass): | ||
129 | existing = False | ||
130 | diff --git a/tests/qemu-iotests/155.out b/tests/qemu-iotests/155.out | ||
131 | index XXXXXXX..XXXXXXX 100644 | ||
132 | --- a/tests/qemu-iotests/155.out | ||
133 | +++ b/tests/qemu-iotests/155.out | ||
134 | @@ -XXX,XX +XXX,XX @@ | ||
135 | -................... | ||
136 | +......................... | ||
137 | ---------------------------------------------------------------------- | ||
138 | -Ran 19 tests | ||
139 | +Ran 25 tests | ||
140 | |||
141 | OK | ||
142 | -- | ||
143 | 2.20.1 | ||
144 | |||
145 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | external_snapshot_prepare() tries to move the overlay to the AioContext | ||
2 | of the backing file (the snapshotted node). However, it's possible that | ||
3 | this doesn't work, but the backing file can instead be moved to the | ||
4 | overlay's AioContext (e.g. opening the backing chain for a mirror | ||
5 | target). | ||
6 | 1 | ||
7 | bdrv_append() already indirectly uses bdrv_attach_node(), which takes | ||
8 | care to move nodes to make sure they use the same AioContext and which | ||
9 | tries both directions. | ||
10 | |||
11 | So the problem has a simple fix: Just delete the unnecessary extra | ||
12 | bdrv_try_set_aio_context() call in external_snapshot_prepare() and | ||
13 | instead assert in bdrv_append() that both nodes were indeed moved to the | ||
14 | same AioContext. | ||
15 | |||
16 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
17 | Message-Id: <20200310113831.27293-6-kwolf@redhat.com> | ||
18 | Tested-by: Peter Krempa <pkrempa@redhat.com> | ||
19 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
20 | --- | ||
21 | block.c | 1 + | ||
22 | blockdev.c | 16 ---------------- | ||
23 | 2 files changed, 1 insertion(+), 16 deletions(-) | ||
24 | |||
25 | diff --git a/block.c b/block.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/block.c | ||
28 | +++ b/block.c | ||
29 | @@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, | ||
30 | bdrv_ref(from); | ||
31 | |||
32 | assert(qemu_get_current_aio_context() == qemu_get_aio_context()); | ||
33 | + assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to)); | ||
34 | bdrv_drained_begin(from); | ||
35 | |||
36 | /* Put all parents into @list and calculate their cumulative permissions */ | ||
37 | diff --git a/blockdev.c b/blockdev.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/blockdev.c | ||
40 | +++ b/blockdev.c | ||
41 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
42 | DO_UPCAST(ExternalSnapshotState, common, common); | ||
43 | TransactionAction *action = common->action; | ||
44 | AioContext *aio_context; | ||
45 | - AioContext *old_context; | ||
46 | uint64_t perm, shared; | ||
47 | - int ret; | ||
48 | |||
49 | /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar | ||
50 | * purpose but a different set of parameters */ | ||
51 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
52 | goto out; | ||
53 | } | ||
54 | |||
55 | - /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ | ||
56 | - old_context = bdrv_get_aio_context(state->new_bs); | ||
57 | - aio_context_release(aio_context); | ||
58 | - aio_context_acquire(old_context); | ||
59 | - | ||
60 | - ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp); | ||
61 | - | ||
62 | - aio_context_release(old_context); | ||
63 | - aio_context_acquire(aio_context); | ||
64 | - | ||
65 | - if (ret < 0) { | ||
66 | - goto out; | ||
67 | - } | ||
68 | - | ||
69 | /* This removes our old bs and adds the new bs. This is an operation that | ||
70 | * can fail, so we need to do it in .prepare; undoing it for abort is | ||
71 | * always possible. */ | ||
72 | -- | ||
73 | 2.20.1 | ||
74 | |||
75 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | This patch adds test cases for attaching the backing chain to a mirror | ||
2 | job target right before finalising the job, where the image is in a | ||
3 | non-mainloop AioContext (i.e. the backing chain needs to be moved to the | ||
4 | AioContext of the mirror target). | ||
5 | 1 | ||
6 | This requires switching the test case from virtio-blk to virtio-scsi | ||
7 | because virtio-blk only actually starts using the iothreads when the | ||
8 | guest driver initialises the device (which never happens in a test case | ||
9 | without a guest OS). virtio-scsi always keeps its block nodes in the | ||
10 | AioContext of the the requested iothread without guest interaction. | ||
11 | |||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | Message-Id: <20200310113831.27293-7-kwolf@redhat.com> | ||
14 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | ||
15 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
16 | --- | ||
17 | tests/qemu-iotests/155 | 32 +++++++++++++++++++++++--------- | ||
18 | tests/qemu-iotests/155.out | 4 ++-- | ||
19 | 2 files changed, 25 insertions(+), 11 deletions(-) | ||
20 | |||
21 | diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155 | ||
22 | index XXXXXXX..XXXXXXX 100755 | ||
23 | --- a/tests/qemu-iotests/155 | ||
24 | +++ b/tests/qemu-iotests/155 | ||
25 | @@ -XXX,XX +XXX,XX @@ target_img = os.path.join(iotests.test_dir, 'target.' + iotests.imgfmt) | ||
26 | # chain opened right away. If False, blockdev-add | ||
27 | # opens it without a backing file and job completion | ||
28 | # is supposed to open the backing chain. | ||
29 | +# use_iothread: If True, an iothread is configured for the virtio-blk device | ||
30 | +# that uses the image being mirrored | ||
31 | |||
32 | class BaseClass(iotests.QMPTestCase): | ||
33 | target_blockdev_backing = None | ||
34 | target_real_backing = None | ||
35 | target_open_with_backing = True | ||
36 | + use_iothread = False | ||
37 | |||
38 | def setUp(self): | ||
39 | qemu_img('create', '-f', iotests.imgfmt, back0_img, '1440K') | ||
40 | @@ -XXX,XX +XXX,XX @@ class BaseClass(iotests.QMPTestCase): | ||
41 | 'file': {'driver': 'file', | ||
42 | 'filename': source_img}} | ||
43 | self.vm.add_blockdev(self.vm.qmp_to_opts(blockdev)) | ||
44 | - self.vm.add_device('virtio-blk,id=qdev0,drive=source') | ||
45 | + | ||
46 | + if self.use_iothread: | ||
47 | + self.vm.add_object('iothread,id=iothread0') | ||
48 | + iothread = ",iothread=iothread0" | ||
49 | + else: | ||
50 | + iothread = "" | ||
51 | + | ||
52 | + self.vm.add_device('virtio-scsi%s' % iothread) | ||
53 | + self.vm.add_device('scsi-hd,id=qdev0,drive=source') | ||
54 | + | ||
55 | self.vm.launch() | ||
56 | |||
57 | self.assertIntactSourceBackingChain() | ||
58 | @@ -XXX,XX +XXX,XX @@ class MirrorBaseClass(BaseClass): | ||
59 | def testFull(self): | ||
60 | self.runMirror('full') | ||
61 | |||
62 | - node = self.findBlockNode('target', | ||
63 | - '/machine/peripheral/qdev0/virtio-backend') | ||
64 | + node = self.findBlockNode('target', 'qdev0') | ||
65 | self.assertCorrectBackingImage(node, None) | ||
66 | self.assertIntactSourceBackingChain() | ||
67 | |||
68 | def testTop(self): | ||
69 | self.runMirror('top') | ||
70 | |||
71 | - node = self.findBlockNode('target', | ||
72 | - '/machine/peripheral/qdev0/virtio-backend') | ||
73 | + node = self.findBlockNode('target', 'qdev0') | ||
74 | self.assertCorrectBackingImage(node, back2_img) | ||
75 | self.assertIntactSourceBackingChain() | ||
76 | |||
77 | def testNone(self): | ||
78 | self.runMirror('none') | ||
79 | |||
80 | - node = self.findBlockNode('target', | ||
81 | - '/machine/peripheral/qdev0/virtio-backend') | ||
82 | + node = self.findBlockNode('target', 'qdev0') | ||
83 | self.assertCorrectBackingImage(node, source_img) | ||
84 | self.assertIntactSourceBackingChain() | ||
85 | |||
86 | @@ -XXX,XX +XXX,XX @@ class TestBlockdevMirrorReopen(MirrorBaseClass): | ||
87 | backing="backing") | ||
88 | self.assert_qmp(result, 'return', {}) | ||
89 | |||
90 | +class TestBlockdevMirrorReopenIothread(TestBlockdevMirrorReopen): | ||
91 | + use_iothread = True | ||
92 | + | ||
93 | # Attach the backing chain only during completion, with blockdev-snapshot | ||
94 | class TestBlockdevMirrorSnapshot(MirrorBaseClass): | ||
95 | cmd = 'blockdev-mirror' | ||
96 | @@ -XXX,XX +XXX,XX @@ class TestBlockdevMirrorSnapshot(MirrorBaseClass): | ||
97 | overlay="target") | ||
98 | self.assert_qmp(result, 'return', {}) | ||
99 | |||
100 | +class TestBlockdevMirrorSnapshotIothread(TestBlockdevMirrorSnapshot): | ||
101 | + use_iothread = True | ||
102 | + | ||
103 | class TestCommit(BaseClass): | ||
104 | existing = False | ||
105 | |||
106 | @@ -XXX,XX +XXX,XX @@ class TestCommit(BaseClass): | ||
107 | |||
108 | self.vm.event_wait('BLOCK_JOB_COMPLETED') | ||
109 | |||
110 | - node = self.findBlockNode(None, | ||
111 | - '/machine/peripheral/qdev0/virtio-backend') | ||
112 | + node = self.findBlockNode(None, 'qdev0') | ||
113 | self.assert_qmp(node, 'image' + '/backing-image' * 0 + '/filename', | ||
114 | back1_img) | ||
115 | self.assert_qmp(node, 'image' + '/backing-image' * 1 + '/filename', | ||
116 | diff --git a/tests/qemu-iotests/155.out b/tests/qemu-iotests/155.out | ||
117 | index XXXXXXX..XXXXXXX 100644 | ||
118 | --- a/tests/qemu-iotests/155.out | ||
119 | +++ b/tests/qemu-iotests/155.out | ||
120 | @@ -XXX,XX +XXX,XX @@ | ||
121 | -......................... | ||
122 | +............................... | ||
123 | ---------------------------------------------------------------------- | ||
124 | -Ran 25 tests | ||
125 | +Ran 31 tests | ||
126 | |||
127 | OK | ||
128 | -- | ||
129 | 2.20.1 | ||
130 | |||
131 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Peter Krempa <pkrempa@redhat.com> | ||
2 | 1 | ||
3 | Anounce that 'blockdev-snapshot' command's permissions allow changing | ||
4 | of the backing file if the 'consistent_read' permission is not required. | ||
5 | |||
6 | This is useful for libvirt to allow late opening of the backing chain | ||
7 | during a blockdev-mirror. | ||
8 | |||
9 | Signed-off-by: Peter Krempa <pkrempa@redhat.com> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | Message-Id: <20200310113831.27293-8-kwolf@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | qapi/block-core.json | 9 ++++++++- | ||
15 | 1 file changed, 8 insertions(+), 1 deletion(-) | ||
16 | |||
17 | diff --git a/qapi/block-core.json b/qapi/block-core.json | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/qapi/block-core.json | ||
20 | +++ b/qapi/block-core.json | ||
21 | @@ -XXX,XX +XXX,XX @@ | ||
22 | # | ||
23 | # For the arguments, see the documentation of BlockdevSnapshot. | ||
24 | # | ||
25 | +# Features: | ||
26 | +# @allow-write-only-overlay: If present, the check whether this operation is safe | ||
27 | +# was relaxed so that it can be used to change | ||
28 | +# backing file of a destination of a blockdev-mirror. | ||
29 | +# (since 5.0) | ||
30 | +# | ||
31 | # Since: 2.5 | ||
32 | # | ||
33 | # Example: | ||
34 | @@ -XXX,XX +XXX,XX @@ | ||
35 | # | ||
36 | ## | ||
37 | { 'command': 'blockdev-snapshot', | ||
38 | - 'data': 'BlockdevSnapshot' } | ||
39 | + 'data': 'BlockdevSnapshot', | ||
40 | + 'features': [ 'allow-write-only-overlay' ] } | ||
41 | |||
42 | ## | ||
43 | # @change-backing-file: | ||
44 | -- | ||
45 | 2.20.1 | ||
46 | |||
47 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
2 | 1 | ||
3 | The socket_scm_helper path got corrupted during the mechanical | ||
4 | refactor moving the qtests files into their own sub-directory. | ||
5 | |||
6 | Fixes: 1e8a1fae7 ("test: Move qtests to a separate directory") | ||
7 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
8 | Message-Id: <20200306165751.18986-1-philmd@redhat.com> | ||
9 | Reviewed-by: Laurent Vivier <laurent@vivier.eu> | ||
10 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
11 | --- | ||
12 | tests/Makefile.include | 1 + | ||
13 | tests/qtest/Makefile.include | 1 - | ||
14 | 2 files changed, 1 insertion(+), 1 deletion(-) | ||
15 | |||
16 | diff --git a/tests/Makefile.include b/tests/Makefile.include | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/tests/Makefile.include | ||
19 | +++ b/tests/Makefile.include | ||
20 | @@ -XXX,XX +XXX,XX @@ include $(SRC_PATH)/tests/qtest/Makefile.include | ||
21 | tests/test-qga$(EXESUF): qemu-ga$(EXESUF) | ||
22 | tests/test-qga$(EXESUF): tests/test-qga.o $(qtest-obj-y) | ||
23 | tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o $(test-util-obj-y) libvhost-user.a | ||
24 | +tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o | ||
25 | |||
26 | SPEED = quick | ||
27 | |||
28 | diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/tests/qtest/Makefile.include | ||
31 | +++ b/tests/qtest/Makefile.include | ||
32 | @@ -XXX,XX +XXX,XX @@ tests/qtest/usb-hcd-ehci-test$(EXESUF): tests/qtest/usb-hcd-ehci-test.o $(libqos | ||
33 | tests/qtest/usb-hcd-xhci-test$(EXESUF): tests/qtest/usb-hcd-xhci-test.o $(libqos-usb-obj-y) | ||
34 | tests/qtest/cpu-plug-test$(EXESUF): tests/qtest/cpu-plug-test.o | ||
35 | tests/qtest/migration-test$(EXESUF): tests/qtest/migration-test.o tests/qtest/migration-helpers.o | ||
36 | -tests/qtest/qemu-iotests/qtest/socket_scm_helper$(EXESUF): tests/qtest/qemu-iotests/qtest/socket_scm_helper.o | ||
37 | tests/qtest/test-netfilter$(EXESUF): tests/qtest/test-netfilter.o $(qtest-obj-y) | ||
38 | tests/qtest/test-filter-mirror$(EXESUF): tests/qtest/test-filter-mirror.o $(qtest-obj-y) | ||
39 | tests/qtest/test-filter-redirector$(EXESUF): tests/qtest/test-filter-redirector.o $(qtest-obj-y) | ||
40 | -- | ||
41 | 2.20.1 | ||
42 | |||
43 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
2 | 1 | ||
3 | Adding to Block Drivers the capability of being able to clean up | ||
4 | its created files can be useful in certain situations. For the | ||
5 | LUKS driver, for instance, a failure in one of its authentication | ||
6 | steps can leave files in the host that weren't there before. | ||
7 | |||
8 | This patch adds the 'bdrv_co_delete_file' interface to block | ||
9 | drivers and add it to the 'file' driver in file-posix.c. The | ||
10 | implementation is given by 'raw_co_delete_file'. | ||
11 | |||
12 | Suggested-by: Daniel P. Berrangé <berrange@redhat.com> | ||
13 | Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
14 | Message-Id: <20200130213907.2830642-2-danielhb413@gmail.com> | ||
15 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
16 | --- | ||
17 | include/block/block_int.h | 4 ++++ | ||
18 | block/file-posix.c | 23 +++++++++++++++++++++++ | ||
19 | 2 files changed, 27 insertions(+) | ||
20 | |||
21 | diff --git a/include/block/block_int.h b/include/block/block_int.h | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/include/block/block_int.h | ||
24 | +++ b/include/block/block_int.h | ||
25 | @@ -XXX,XX +XXX,XX @@ struct BlockDriver { | ||
26 | */ | ||
27 | int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs); | ||
28 | |||
29 | + /* Delete a created file. */ | ||
30 | + int coroutine_fn (*bdrv_co_delete_file)(BlockDriverState *bs, | ||
31 | + Error **errp); | ||
32 | + | ||
33 | /* | ||
34 | * Flushes all data that was already written to the OS all the way down to | ||
35 | * the disk (for example file-posix.c calls fsync()). | ||
36 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/block/file-posix.c | ||
39 | +++ b/block/file-posix.c | ||
40 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_create_opts(const char *filename, QemuOpts *opts, | ||
41 | return raw_co_create(&options, errp); | ||
42 | } | ||
43 | |||
44 | +static int coroutine_fn raw_co_delete_file(BlockDriverState *bs, | ||
45 | + Error **errp) | ||
46 | +{ | ||
47 | + struct stat st; | ||
48 | + int ret; | ||
49 | + | ||
50 | + if (!(stat(bs->filename, &st) == 0) || !S_ISREG(st.st_mode)) { | ||
51 | + error_setg_errno(errp, ENOENT, "%s is not a regular file", | ||
52 | + bs->filename); | ||
53 | + return -ENOENT; | ||
54 | + } | ||
55 | + | ||
56 | + ret = unlink(bs->filename); | ||
57 | + if (ret < 0) { | ||
58 | + ret = -errno; | ||
59 | + error_setg_errno(errp, -ret, "Error when deleting file %s", | ||
60 | + bs->filename); | ||
61 | + } | ||
62 | + | ||
63 | + return ret; | ||
64 | +} | ||
65 | + | ||
66 | /* | ||
67 | * Find allocation range in @bs around offset @start. | ||
68 | * May change underlying file descriptor's file offset. | ||
69 | @@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = { | ||
70 | .bdrv_co_block_status = raw_co_block_status, | ||
71 | .bdrv_co_invalidate_cache = raw_co_invalidate_cache, | ||
72 | .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes, | ||
73 | + .bdrv_co_delete_file = raw_co_delete_file, | ||
74 | |||
75 | .bdrv_co_preadv = raw_co_preadv, | ||
76 | .bdrv_co_pwritev = raw_co_pwritev, | ||
77 | -- | ||
78 | 2.20.1 | ||
79 | |||
80 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
2 | 1 | ||
3 | Using the new 'bdrv_co_delete_file' interface, a pure co_routine function | ||
4 | 'bdrv_co_delete_file' inside block.c can can be used in a way similar of | ||
5 | the existing bdrv_create_file to to clean up a created file. | ||
6 | |||
7 | We're creating a pure co_routine because the only caller of | ||
8 | 'bdrv_co_delete_file' will be already in co_routine context, thus there | ||
9 | is no need to add all the machinery to check for qemu_in_coroutine() and | ||
10 | create a separated co_routine to do the job. | ||
11 | |||
12 | Suggested-by: Daniel P. Berrangé <berrange@redhat.com> | ||
13 | Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
14 | Message-Id: <20200130213907.2830642-3-danielhb413@gmail.com> | ||
15 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
16 | --- | ||
17 | include/block/block.h | 1 + | ||
18 | block.c | 26 ++++++++++++++++++++++++++ | ||
19 | 2 files changed, 27 insertions(+) | ||
20 | |||
21 | diff --git a/include/block/block.h b/include/block/block.h | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/include/block/block.h | ||
24 | +++ b/include/block/block.h | ||
25 | @@ -XXX,XX +XXX,XX @@ bool bdrv_is_backing_chain_frozen(BlockDriverState *bs, BlockDriverState *base, | ||
26 | int bdrv_freeze_backing_chain(BlockDriverState *bs, BlockDriverState *base, | ||
27 | Error **errp); | ||
28 | void bdrv_unfreeze_backing_chain(BlockDriverState *bs, BlockDriverState *base); | ||
29 | +int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp); | ||
30 | |||
31 | |||
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 bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp) | ||
38 | } | ||
39 | } | ||
40 | |||
41 | +int coroutine_fn bdrv_co_delete_file(BlockDriverState *bs, Error **errp) | ||
42 | +{ | ||
43 | + Error *local_err = NULL; | ||
44 | + int ret; | ||
45 | + | ||
46 | + assert(bs != NULL); | ||
47 | + | ||
48 | + if (!bs->drv) { | ||
49 | + error_setg(errp, "Block node '%s' is not opened", bs->filename); | ||
50 | + return -ENOMEDIUM; | ||
51 | + } | ||
52 | + | ||
53 | + if (!bs->drv->bdrv_co_delete_file) { | ||
54 | + error_setg(errp, "Driver '%s' does not support image deletion", | ||
55 | + bs->drv->format_name); | ||
56 | + return -ENOTSUP; | ||
57 | + } | ||
58 | + | ||
59 | + ret = bs->drv->bdrv_co_delete_file(bs, &local_err); | ||
60 | + if (ret < 0) { | ||
61 | + error_propagate(errp, local_err); | ||
62 | + } | ||
63 | + | ||
64 | + return ret; | ||
65 | +} | ||
66 | + | ||
67 | /** | ||
68 | * Try to get @bs's logical and physical block size. | ||
69 | * On success, store them in @bsz struct and return 0. | ||
70 | -- | ||
71 | 2.20.1 | ||
72 | |||
73 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
2 | 1 | ||
3 | When using a non-UTF8 secret to create a volume using qemu-img, the | ||
4 | following error happens: | ||
5 | |||
6 | $ qemu-img create -f luks --object secret,id=vol_1_encrypt0,file=vol_resize_pool.vol_1.secret.qzVQrI -o key-secret=vol_1_encrypt0 /var/tmp/pool_target/vol_1 10240K | ||
7 | |||
8 | Formatting '/var/tmp/pool_target/vol_1', fmt=luks size=10485760 key-secret=vol_1_encrypt0 | ||
9 | qemu-img: /var/tmp/pool_target/vol_1: Data from secret vol_1_encrypt0 is not valid UTF-8 | ||
10 | |||
11 | However, the created file '/var/tmp/pool_target/vol_1' is left behind in the | ||
12 | file system after the failure. This behavior can be observed when creating | ||
13 | the volume using Libvirt, via 'virsh vol-create', and then getting "volume | ||
14 | target path already exist" errors when trying to re-create the volume. | ||
15 | |||
16 | The volume file is created inside block_crypto_co_create_opts_luks(), in | ||
17 | block/crypto.c. If the bdrv_create_file() call is successful but any | ||
18 | succeeding step fails*, the existing 'fail' label does not take into | ||
19 | account the created file, leaving it behind. | ||
20 | |||
21 | This patch changes block_crypto_co_create_opts_luks() to delete | ||
22 | 'filename' in case of failure. A failure in this point means that | ||
23 | the volume is now truncated/corrupted, so even if 'filename' was an | ||
24 | existing volume before calling qemu-img, it is now unusable. Deleting | ||
25 | the file it is not much worse than leaving it in the filesystem in | ||
26 | this scenario, and we don't have to deal with checking the file | ||
27 | pre-existence in the code. | ||
28 | |||
29 | * in our case, block_crypto_co_create_generic calls qcrypto_block_create, | ||
30 | which calls qcrypto_block_luks_create, and this function fails when | ||
31 | calling qcrypto_secret_lookup_as_utf8. | ||
32 | |||
33 | Reported-by: Srikanth Aithal <bssrikanth@in.ibm.com> | ||
34 | Suggested-by: Kevin Wolf <kwolf@redhat.com> | ||
35 | Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
36 | Message-Id: <20200130213907.2830642-4-danielhb413@gmail.com> | ||
37 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
38 | --- | ||
39 | block/crypto.c | 18 ++++++++++++++++++ | ||
40 | 1 file changed, 18 insertions(+) | ||
41 | |||
42 | diff --git a/block/crypto.c b/block/crypto.c | ||
43 | index XXXXXXX..XXXXXXX 100644 | ||
44 | --- a/block/crypto.c | ||
45 | +++ b/block/crypto.c | ||
46 | @@ -XXX,XX +XXX,XX @@ | ||
47 | #include "qapi/error.h" | ||
48 | #include "qemu/module.h" | ||
49 | #include "qemu/option.h" | ||
50 | +#include "qemu/cutils.h" | ||
51 | #include "crypto.h" | ||
52 | |||
53 | typedef struct BlockCrypto BlockCrypto; | ||
54 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn block_crypto_co_create_opts_luks(const char *filename, | ||
55 | |||
56 | ret = 0; | ||
57 | fail: | ||
58 | + /* | ||
59 | + * If an error occurred, delete 'filename'. Even if the file existed | ||
60 | + * beforehand, it has been truncated and corrupted in the process. | ||
61 | + */ | ||
62 | + if (ret && bs) { | ||
63 | + Error *local_delete_err = NULL; | ||
64 | + int r_del = bdrv_co_delete_file(bs, &local_delete_err); | ||
65 | + /* | ||
66 | + * ENOTSUP will happen if the block driver doesn't support | ||
67 | + * the 'bdrv_co_delete_file' interface. This is a predictable | ||
68 | + * scenario and shouldn't be reported back to the user. | ||
69 | + */ | ||
70 | + if ((r_del < 0) && (r_del != -ENOTSUP)) { | ||
71 | + error_report_err(local_delete_err); | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | bdrv_unref(bs); | ||
76 | qapi_free_QCryptoBlockCreateOptions(create_opts); | ||
77 | qobject_unref(cryptoopts); | ||
78 | -- | ||
79 | 2.20.1 | ||
80 | |||
81 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
2 | 1 | ||
3 | This patch adds a new test file to exercise the case where | ||
4 | qemu-img fails to complete for the LUKS format when a non-UTF8 | ||
5 | secret is used. | ||
6 | |||
7 | Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> | ||
8 | Message-Id: <20200130213907.2830642-5-danielhb413@gmail.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | tests/qemu-iotests/282 | 67 ++++++++++++++++++++++++++++++++++++++ | ||
12 | tests/qemu-iotests/282.out | 11 +++++++ | ||
13 | tests/qemu-iotests/group | 1 + | ||
14 | 3 files changed, 79 insertions(+) | ||
15 | create mode 100755 tests/qemu-iotests/282 | ||
16 | create mode 100644 tests/qemu-iotests/282.out | ||
17 | |||
18 | diff --git a/tests/qemu-iotests/282 b/tests/qemu-iotests/282 | ||
19 | new file mode 100755 | ||
20 | index XXXXXXX..XXXXXXX | ||
21 | --- /dev/null | ||
22 | +++ b/tests/qemu-iotests/282 | ||
23 | @@ -XXX,XX +XXX,XX @@ | ||
24 | +#!/usr/bin/env bash | ||
25 | +# | ||
26 | +# Test qemu-img file cleanup for LUKS when using a non-UTF8 secret | ||
27 | +# | ||
28 | +# Copyright (C) 2020, IBM Corporation. | ||
29 | +# | ||
30 | +# This program is free software; you can redistribute it and/or modify | ||
31 | +# it under the terms of the GNU General Public License as published by | ||
32 | +# the Free Software Foundation; either version 2 of the License, or | ||
33 | +# (at your option) any later version. | ||
34 | +# | ||
35 | +# This program is distributed in the hope that it will be useful, | ||
36 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
37 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
38 | +# GNU General Public License for more details. | ||
39 | +# | ||
40 | +# You should have received a copy of the GNU General Public License | ||
41 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
42 | +# | ||
43 | + | ||
44 | +seq=`basename $0` | ||
45 | +echo "QA output created by $seq" | ||
46 | + | ||
47 | +status=1 # failure is the default! | ||
48 | +TEST_IMAGE_FILE='vol.img' | ||
49 | + | ||
50 | +_cleanup() | ||
51 | +{ | ||
52 | + _cleanup_test_img | ||
53 | + rm non_utf8_secret | ||
54 | + rm -f $TEST_IMAGE_FILE | ||
55 | +} | ||
56 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
57 | + | ||
58 | +# get standard environment, filters and checks | ||
59 | +. ./common.rc | ||
60 | +. ./common.filter | ||
61 | + | ||
62 | +_supported_fmt luks | ||
63 | +_supported_proto generic | ||
64 | +_unsupported_proto vxhs | ||
65 | + | ||
66 | +echo "== Create non-UTF8 secret ==" | ||
67 | +echo -n -e '\x3a\x3c\x3b\xff' > non_utf8_secret | ||
68 | +SECRET="secret,id=sec0,file=non_utf8_secret" | ||
69 | + | ||
70 | +echo "== Throws an error because of invalid UTF-8 secret ==" | ||
71 | +$QEMU_IMG create -f $IMGFMT --object $SECRET -o "key-secret=sec0" $TEST_IMAGE_FILE 4M | ||
72 | + | ||
73 | +echo "== Image file should not exist after the error ==" | ||
74 | +if test -f "$TEST_IMAGE_FILE"; then | ||
75 | + exit 1 | ||
76 | +fi | ||
77 | + | ||
78 | +echo "== Create a stub image file and run qemu-img again ==" | ||
79 | +touch $TEST_IMAGE_FILE | ||
80 | +$QEMU_IMG create -f $IMGFMT --object $SECRET -o "key-secret=sec0" $TEST_IMAGE_FILE 4M | ||
81 | + | ||
82 | +echo "== Pre-existing image file should also be deleted after the error ==" | ||
83 | +if test -f "$TEST_IMAGE_FILE"; then | ||
84 | + exit 1 | ||
85 | +fi | ||
86 | + | ||
87 | +# success, all done | ||
88 | +echo "*** done" | ||
89 | +rm -f $seq.full | ||
90 | +status=0 | ||
91 | diff --git a/tests/qemu-iotests/282.out b/tests/qemu-iotests/282.out | ||
92 | new file mode 100644 | ||
93 | index XXXXXXX..XXXXXXX | ||
94 | --- /dev/null | ||
95 | +++ b/tests/qemu-iotests/282.out | ||
96 | @@ -XXX,XX +XXX,XX @@ | ||
97 | +QA output created by 282 | ||
98 | +== Create non-UTF8 secret == | ||
99 | +== Throws an error because of invalid UTF-8 secret == | ||
100 | +qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 | ||
101 | +Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0 | ||
102 | +== Image file should not exist after the error == | ||
103 | +== Create a stub image file and run qemu-img again == | ||
104 | +qemu-img: vol.img: Data from secret sec0 is not valid UTF-8 | ||
105 | +Formatting 'vol.img', fmt=luks size=4194304 key-secret=sec0 | ||
106 | +== Pre-existing image file should also be deleted after the error == | ||
107 | + *** done | ||
108 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | ||
109 | index XXXXXXX..XXXXXXX 100644 | ||
110 | --- a/tests/qemu-iotests/group | ||
111 | +++ b/tests/qemu-iotests/group | ||
112 | @@ -XXX,XX +XXX,XX @@ | ||
113 | 279 rw backing quick | ||
114 | 280 rw migration quick | ||
115 | 281 rw quick | ||
116 | +282 rw img quick | ||
117 | 283 auto quick | ||
118 | 284 rw | ||
119 | 286 rw quick | ||
120 | -- | ||
121 | 2.20.1 | ||
122 | |||
123 | diff view generated by jsdifflib |