1 | The following changes since commit 418fa86dd465b4fd8394373cf83db8fa65d7611c: | 1 | The following changes since commit eaefea537b476cb853e2edbdc68e969ec777e4bb: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-040220-1' into staging (2020-02-04 18:55:06 +0000) | 3 | Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-fetch' into staging (2017-12-18 14:17:42 +0000) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | https://github.com/XanClic/qemu.git tags/pull-block-2020-02-06 | 7 | git://github.com/stefanha/qemu.git tags/block-pull-request |
8 | 8 | ||
9 | for you to fetch changes up to a541fcc27c98b96da187c7d4573f3270f3ddd283: | 9 | for you to fetch changes up to 7a9dda0d7f9831c2432620dcfefdadbb7ae888dc: |
10 | 10 | ||
11 | iotests: add test for backup-top failure on permission activation (2020-02-06 13:47:45 +0100) | 11 | qemu-iotests: add 203 savevm with IOThreads test (2017-12-19 10:25:09 +0000) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block patches: | 14 | Pull request |
15 | - Drop BDRV_SECTOR_SIZE from qcow2 | 15 | |
16 | - Allow Python iotests to be added to the auto group | 16 | v2: |
17 | (and add some) | 17 | * Fixed incorrect virtio_blk_data_plane_create() local_err refactoring in |
18 | - Fix for the backup job | 18 | "hw/block: Use errp directly rather than local_err" that broke virtio-blk |
19 | - Fix memleak in bdrv_refresh_filename() | 19 | over virtio-mmio [Peter] |
20 | - Use GStrings in two places for greater efficiency (than manually | ||
21 | handling string allocation) | ||
22 | 20 | ||
23 | ---------------------------------------------------------------- | 21 | ---------------------------------------------------------------- |
24 | Alberto Garcia (8): | ||
25 | qcow2: Assert that host cluster offsets fit in L2 table entries | ||
26 | block: Use a GString in bdrv_perm_names() | ||
27 | qcow2: Use a GString in report_unsupported_feature() | ||
28 | qcow2: Don't round the L1 table allocation up to the sector size | ||
29 | qcow2: Tighten cluster_offset alignment assertions | ||
30 | qcow2: Use bs->bl.request_alignment when updating an L1 entry | ||
31 | qcow2: Don't require aligned offsets in qcow2_co_copy_range_from() | ||
32 | qcow2: Use BDRV_SECTOR_SIZE instead of the hardcoded value | ||
33 | 22 | ||
34 | John Snow (1): | 23 | Mao Zhongyi (4): |
35 | iotests: remove 'linux' from default supported platforms | 24 | hw/block/nvme: Convert to realize |
25 | hw/block: Fix the return type | ||
26 | hw/block: Use errp directly rather than local_err | ||
27 | dev-storage: Fix the unusual function name | ||
36 | 28 | ||
37 | Pan Nengyuan (1): | 29 | Mark Kanda (2): |
38 | block: fix memleaks in bdrv_refresh_filename | 30 | virtio-blk: make queue size configurable |
31 | virtio-blk: reject configs with logical block size > physical block | ||
32 | size | ||
39 | 33 | ||
40 | Thomas Huth (5): | 34 | Paolo Bonzini (1): |
41 | iotests: Test 041 only works on certain systems | 35 | block: avoid recursive AioContext acquire in bdrv_inactivate_all() |
42 | iotests: Test 183 does not work on macOS and OpenBSD | ||
43 | iotests: Check for the availability of the required devices in 267 and | ||
44 | 127 | ||
45 | iotests: Skip Python-based tests if QEMU does not support virtio-blk | ||
46 | iotests: Enable more tests in the 'auto' group to improve test | ||
47 | coverage | ||
48 | 36 | ||
49 | Vladimir Sementsov-Ogievskiy (2): | 37 | Stefan Hajnoczi (16): |
50 | block/backup-top: fix failure path | 38 | coroutine: simplify co_aio_sleep_ns() prototype |
51 | iotests: add test for backup-top failure on permission activation | 39 | qdev: drop unused #include "sysemu/iothread.h" |
40 | blockdev: hold AioContext for bdrv_unref() in | ||
41 | external_snapshot_clean() | ||
42 | block: don't keep AioContext acquired after | ||
43 | external_snapshot_prepare() | ||
44 | block: don't keep AioContext acquired after drive_backup_prepare() | ||
45 | block: don't keep AioContext acquired after blockdev_backup_prepare() | ||
46 | block: don't keep AioContext acquired after | ||
47 | internal_snapshot_prepare() | ||
48 | block: drop unused BlockDirtyBitmapState->aio_context field | ||
49 | iothread: add iothread_by_id() API | ||
50 | blockdev: add x-blockdev-set-iothread testing command | ||
51 | qemu-iotests: add 202 external snapshots IOThread test | ||
52 | docs: mark nested AioContext locking as a legacy API | ||
53 | blockdev: add x-blockdev-set-iothread force boolean | ||
54 | iotests: add VM.add_object() | ||
55 | iothread: fix iothread_stop() race condition | ||
56 | qemu-iotests: add 203 savevm with IOThreads test | ||
52 | 57 | ||
53 | block.c | 12 +++-- | 58 | docs/devel/multiple-iothreads.txt | 7 +- |
54 | block/backup-top.c | 21 ++++---- | 59 | qapi/block-core.json | 40 ++++++ |
55 | block/qcow2-cluster.c | 44 +++++++++++------ | 60 | hw/block/dataplane/virtio-blk.h | 2 +- |
56 | block/qcow2-refcount.c | 2 +- | 61 | include/hw/block/block.h | 4 +- |
57 | block/qcow2-snapshot.c | 3 +- | 62 | include/hw/virtio/virtio-blk.h | 1 + |
58 | block/qcow2.c | 46 ++++++++---------- | 63 | include/qemu/coroutine.h | 6 +- |
59 | tests/qemu-iotests/041 | 3 +- | 64 | include/sysemu/iothread.h | 4 +- |
60 | tests/qemu-iotests/127 | 2 + | 65 | block.c | 14 ++- |
61 | tests/qemu-iotests/183 | 1 + | 66 | block/null.c | 3 +- |
62 | tests/qemu-iotests/267 | 2 + | 67 | block/sheepdog.c | 3 +- |
63 | tests/qemu-iotests/283 | 92 +++++++++++++++++++++++++++++++++++ | 68 | blockdev.c | 259 +++++++++++++++++++++++++++----------- |
64 | tests/qemu-iotests/283.out | 8 +++ | 69 | hw/block/block.c | 15 ++- |
65 | tests/qemu-iotests/check | 12 ++++- | 70 | hw/block/dataplane/virtio-blk.c | 12 +- |
66 | tests/qemu-iotests/common.rc | 14 ++++++ | 71 | hw/block/fdc.c | 17 +-- |
67 | tests/qemu-iotests/group | 15 +++--- | 72 | hw/block/nvme.c | 23 ++-- |
68 | tests/qemu-iotests/iotests.py | 16 ++++-- | 73 | hw/block/virtio-blk.c | 30 +++-- |
69 | 16 files changed, 220 insertions(+), 73 deletions(-) | 74 | hw/core/qdev-properties-system.c | 1 - |
70 | create mode 100644 tests/qemu-iotests/283 | 75 | hw/ide/qdev.c | 12 +- |
71 | create mode 100644 tests/qemu-iotests/283.out | 76 | hw/scsi/scsi-disk.c | 13 +- |
77 | hw/usb/dev-storage.c | 29 ++--- | ||
78 | iothread.c | 27 +++- | ||
79 | util/qemu-coroutine-sleep.c | 4 +- | ||
80 | tests/qemu-iotests/202 | 95 ++++++++++++++ | ||
81 | tests/qemu-iotests/202.out | 11 ++ | ||
82 | tests/qemu-iotests/203 | 59 +++++++++ | ||
83 | tests/qemu-iotests/203.out | 6 + | ||
84 | tests/qemu-iotests/group | 2 + | ||
85 | tests/qemu-iotests/iotests.py | 5 + | ||
86 | 28 files changed, 531 insertions(+), 173 deletions(-) | ||
87 | create mode 100755 tests/qemu-iotests/202 | ||
88 | create mode 100644 tests/qemu-iotests/202.out | ||
89 | create mode 100755 tests/qemu-iotests/203 | ||
90 | create mode 100644 tests/qemu-iotests/203.out | ||
72 | 91 | ||
73 | -- | 92 | -- |
74 | 2.24.1 | 93 | 2.14.3 |
75 | 94 | ||
76 | 95 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The AioContext pointer argument to co_aio_sleep_ns() is only used for | ||
2 | the sleep timer. It does not affect where the caller coroutine is | ||
3 | resumed. | ||
1 | 4 | ||
5 | Due to changes to coroutine and AIO APIs it is now possible to drop the | ||
6 | AioContext pointer argument. This is safe to do since no caller has | ||
7 | specific requirements for which AioContext the timer must run in. | ||
8 | |||
9 | This patch drops the AioContext pointer argument and renames the | ||
10 | function to simplify the API. | ||
11 | |||
12 | Reported-by: Paolo Bonzini <pbonzini@redhat.com> | ||
13 | Reported-by: Eric Blake <eblake@redhat.com> | ||
14 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
15 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
16 | Message-id: 20171109102652.6360-1-stefanha@redhat.com | ||
17 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
18 | --- | ||
19 | include/qemu/coroutine.h | 6 +----- | ||
20 | block/null.c | 3 +-- | ||
21 | block/sheepdog.c | 3 +-- | ||
22 | util/qemu-coroutine-sleep.c | 4 ++-- | ||
23 | 4 files changed, 5 insertions(+), 11 deletions(-) | ||
24 | |||
25 | diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/include/qemu/coroutine.h | ||
28 | +++ b/include/qemu/coroutine.h | ||
29 | @@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_unlock(CoRwlock *lock); | ||
30 | |||
31 | /** | ||
32 | * Yield the coroutine for a given duration | ||
33 | - * | ||
34 | - * Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be | ||
35 | - * resumed when using aio_poll(). | ||
36 | */ | ||
37 | -void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type, | ||
38 | - int64_t ns); | ||
39 | +void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns); | ||
40 | |||
41 | /** | ||
42 | * Yield until a file descriptor becomes readable | ||
43 | diff --git a/block/null.c b/block/null.c | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/block/null.c | ||
46 | +++ b/block/null.c | ||
47 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int null_co_common(BlockDriverState *bs) | ||
48 | BDRVNullState *s = bs->opaque; | ||
49 | |||
50 | if (s->latency_ns) { | ||
51 | - co_aio_sleep_ns(bdrv_get_aio_context(bs), QEMU_CLOCK_REALTIME, | ||
52 | - s->latency_ns); | ||
53 | + qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, s->latency_ns); | ||
54 | } | ||
55 | return 0; | ||
56 | } | ||
57 | diff --git a/block/sheepdog.c b/block/sheepdog.c | ||
58 | index XXXXXXX..XXXXXXX 100644 | ||
59 | --- a/block/sheepdog.c | ||
60 | +++ b/block/sheepdog.c | ||
61 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn void reconnect_to_sdog(void *opaque) | ||
62 | if (s->fd < 0) { | ||
63 | DPRINTF("Wait for connection to be established\n"); | ||
64 | error_report_err(local_err); | ||
65 | - co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME, | ||
66 | - 1000000000ULL); | ||
67 | + qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000000ULL); | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/util/qemu-coroutine-sleep.c | ||
74 | +++ b/util/qemu-coroutine-sleep.c | ||
75 | @@ -XXX,XX +XXX,XX @@ static void co_sleep_cb(void *opaque) | ||
76 | aio_co_wake(sleep_cb->co); | ||
77 | } | ||
78 | |||
79 | -void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type, | ||
80 | - int64_t ns) | ||
81 | +void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns) | ||
82 | { | ||
83 | + AioContext *ctx = qemu_get_current_aio_context(); | ||
84 | CoSleepCB sleep_cb = { | ||
85 | .co = qemu_coroutine_self(), | ||
86 | }; | ||
87 | -- | ||
88 | 2.14.3 | ||
89 | |||
90 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> |
---|---|---|---|
2 | 2 | ||
3 | This is a bit more efficient than having to allocate and free memory | 3 | Convert nvme_init() to realize and rename it to nvme_realize(). |
4 | for each item. | ||
5 | 4 | ||
6 | The default size (60) is enough for all the existing incompatible | 5 | Cc: John Snow <jsnow@redhat.com> |
7 | features or the "Unknown incompatible feature" message. | 6 | Cc: Keith Busch <keith.busch@intel.com> |
7 | Cc: Kevin Wolf <kwolf@redhat.com> | ||
8 | Cc: Max Reitz <mreitz@redhat.com> | ||
9 | Cc: Markus Armbruster <armbru@redhat.com> | ||
8 | 10 | ||
9 | Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com> | 11 | Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> |
10 | Signed-off-by: Alberto Garcia <berto@igalia.com> | 12 | Message-id: 2882e72d795e04cbe2120f569d551aef2467ac60.1511317952.git.maozy.fnst@cn.fujitsu.com |
11 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
12 | Message-id: 20200115135626.19442-1-berto@igalia.com | ||
13 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
14 | Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
16 | --- | 14 | --- |
17 | block/qcow2.c | 23 +++++++++++------------ | 15 | hw/block/nvme.c | 18 ++++++++++-------- |
18 | 1 file changed, 11 insertions(+), 12 deletions(-) | 16 | 1 file changed, 10 insertions(+), 8 deletions(-) |
19 | 17 | ||
20 | diff --git a/block/qcow2.c b/block/qcow2.c | 18 | diff --git a/hw/block/nvme.c b/hw/block/nvme.c |
21 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/block/qcow2.c | 20 | --- a/hw/block/nvme.c |
23 | +++ b/block/qcow2.c | 21 | +++ b/hw/block/nvme.c |
24 | @@ -XXX,XX +XXX,XX @@ static void cleanup_unknown_header_ext(BlockDriverState *bs) | 22 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvme_cmb_ops = { |
25 | static void report_unsupported_feature(Error **errp, Qcow2Feature *table, | 23 | }, |
26 | uint64_t mask) | 24 | }; |
25 | |||
26 | -static int nvme_init(PCIDevice *pci_dev) | ||
27 | +static void nvme_realize(PCIDevice *pci_dev, Error **errp) | ||
27 | { | 28 | { |
28 | - char *features = g_strdup(""); | 29 | NvmeCtrl *n = NVME(pci_dev); |
29 | - char *old; | 30 | NvmeIdCtrl *id = &n->id_ctrl; |
30 | + g_autoptr(GString) features = g_string_sized_new(60); | 31 | @@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev) |
31 | 32 | Error *local_err = NULL; | |
32 | while (table && table->name[0] != '\0') { | 33 | |
33 | if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) { | 34 | if (!n->conf.blk) { |
34 | if (mask & (1ULL << table->bit)) { | 35 | - return -1; |
35 | - old = features; | 36 | + error_setg(errp, "drive property not set"); |
36 | - features = g_strdup_printf("%s%s%.46s", old, *old ? ", " : "", | 37 | + return; |
37 | - table->name); | ||
38 | - g_free(old); | ||
39 | + if (features->len > 0) { | ||
40 | + g_string_append(features, ", "); | ||
41 | + } | ||
42 | + g_string_append_printf(features, "%.46s", table->name); | ||
43 | mask &= ~(1ULL << table->bit); | ||
44 | } | ||
45 | } | ||
46 | @@ -XXX,XX +XXX,XX @@ static void report_unsupported_feature(Error **errp, Qcow2Feature *table, | ||
47 | } | 38 | } |
48 | 39 | ||
49 | if (mask) { | 40 | bs_size = blk_getlength(n->conf.blk); |
50 | - old = features; | 41 | if (bs_size < 0) { |
51 | - features = g_strdup_printf("%s%sUnknown incompatible feature: %" PRIx64, | 42 | - return -1; |
52 | - old, *old ? ", " : "", mask); | 43 | + error_setg(errp, "could not get backing file size"); |
53 | - g_free(old); | 44 | + return; |
54 | + if (features->len > 0) { | ||
55 | + g_string_append(features, ", "); | ||
56 | + } | ||
57 | + g_string_append_printf(features, | ||
58 | + "Unknown incompatible feature: %" PRIx64, mask); | ||
59 | } | 45 | } |
60 | 46 | ||
61 | - error_setg(errp, "Unsupported qcow2 feature(s): %s", features); | 47 | blkconf_serial(&n->conf, &n->serial); |
62 | - g_free(features); | 48 | if (!n->serial) { |
63 | + error_setg(errp, "Unsupported qcow2 feature(s): %s", features->str); | 49 | - return -1; |
50 | + error_setg(errp, "serial property not set"); | ||
51 | + return; | ||
52 | } | ||
53 | blkconf_blocksizes(&n->conf); | ||
54 | blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk), | ||
55 | false, &local_err); | ||
56 | if (local_err) { | ||
57 | - error_report_err(local_err); | ||
58 | - return -1; | ||
59 | + error_propagate(errp, local_err); | ||
60 | + return; | ||
61 | } | ||
62 | |||
63 | pci_conf = pci_dev->config; | ||
64 | @@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev) | ||
65 | cpu_to_le64(n->ns_size >> | ||
66 | id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas)].ds); | ||
67 | } | ||
68 | - return 0; | ||
64 | } | 69 | } |
65 | 70 | ||
66 | /* | 71 | static void nvme_exit(PCIDevice *pci_dev) |
72 | @@ -XXX,XX +XXX,XX @@ static void nvme_class_init(ObjectClass *oc, void *data) | ||
73 | DeviceClass *dc = DEVICE_CLASS(oc); | ||
74 | PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); | ||
75 | |||
76 | - pc->init = nvme_init; | ||
77 | + pc->realize = nvme_realize; | ||
78 | pc->exit = nvme_exit; | ||
79 | pc->class_id = PCI_CLASS_STORAGE_EXPRESS; | ||
80 | pc->vendor_id = PCI_VENDOR_ID_INTEL; | ||
67 | -- | 81 | -- |
68 | 2.24.1 | 82 | 2.14.3 |
69 | 83 | ||
70 | 84 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> | ||
1 | 2 | ||
3 | When the function no success value to transmit, it usually make the | ||
4 | function return void. It has turned out not to be a success, because | ||
5 | it means that the extra local_err variable and error_propagate() will | ||
6 | be needed. It leads to cumbersome code, therefore, transmit success/ | ||
7 | failure in the return value is worth. | ||
8 | |||
9 | So fix the return type of blkconf_apply_backend_options(), | ||
10 | blkconf_geometry() and virtio_blk_data_plane_create() to avoid it. | ||
11 | |||
12 | Cc: John Snow <jsnow@redhat.com> | ||
13 | Cc: Kevin Wolf <kwolf@redhat.com> | ||
14 | Cc: Max Reitz <mreitz@redhat.com> | ||
15 | Cc: Stefan Hajnoczi <stefanha@redhat.com> | ||
16 | |||
17 | Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> | ||
18 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
19 | Message-id: ac0edc1fc70c4457e5cec94405eb7d1f89f9c2c1.1511317952.git.maozy.fnst@cn.fujitsu.com | ||
20 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
21 | --- | ||
22 | hw/block/dataplane/virtio-blk.h | 2 +- | ||
23 | include/hw/block/block.h | 4 ++-- | ||
24 | hw/block/block.c | 15 +++++++++------ | ||
25 | hw/block/dataplane/virtio-blk.c | 12 +++++++----- | ||
26 | 4 files changed, 19 insertions(+), 14 deletions(-) | ||
27 | |||
28 | diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/hw/block/dataplane/virtio-blk.h | ||
31 | +++ b/hw/block/dataplane/virtio-blk.h | ||
32 | @@ -XXX,XX +XXX,XX @@ | ||
33 | |||
34 | typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane; | ||
35 | |||
36 | -void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, | ||
37 | +bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, | ||
38 | VirtIOBlockDataPlane **dataplane, | ||
39 | Error **errp); | ||
40 | void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s); | ||
41 | diff --git a/include/hw/block/block.h b/include/hw/block/block.h | ||
42 | index XXXXXXX..XXXXXXX 100644 | ||
43 | --- a/include/hw/block/block.h | ||
44 | +++ b/include/hw/block/block.h | ||
45 | @@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) | ||
46 | /* Configuration helpers */ | ||
47 | |||
48 | void blkconf_serial(BlockConf *conf, char **serial); | ||
49 | -void blkconf_geometry(BlockConf *conf, int *trans, | ||
50 | +bool blkconf_geometry(BlockConf *conf, int *trans, | ||
51 | unsigned cyls_max, unsigned heads_max, unsigned secs_max, | ||
52 | Error **errp); | ||
53 | void blkconf_blocksizes(BlockConf *conf); | ||
54 | -void blkconf_apply_backend_options(BlockConf *conf, bool readonly, | ||
55 | +bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, | ||
56 | bool resizable, Error **errp); | ||
57 | |||
58 | /* Hard disk geometry */ | ||
59 | diff --git a/hw/block/block.c b/hw/block/block.c | ||
60 | index XXXXXXX..XXXXXXX 100644 | ||
61 | --- a/hw/block/block.c | ||
62 | +++ b/hw/block/block.c | ||
63 | @@ -XXX,XX +XXX,XX @@ void blkconf_blocksizes(BlockConf *conf) | ||
64 | } | ||
65 | } | ||
66 | |||
67 | -void blkconf_apply_backend_options(BlockConf *conf, bool readonly, | ||
68 | +bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, | ||
69 | bool resizable, Error **errp) | ||
70 | { | ||
71 | BlockBackend *blk = conf->blk; | ||
72 | @@ -XXX,XX +XXX,XX @@ void blkconf_apply_backend_options(BlockConf *conf, bool readonly, | ||
73 | |||
74 | ret = blk_set_perm(blk, perm, shared_perm, errp); | ||
75 | if (ret < 0) { | ||
76 | - return; | ||
77 | + return false; | ||
78 | } | ||
79 | |||
80 | switch (conf->wce) { | ||
81 | @@ -XXX,XX +XXX,XX @@ void blkconf_apply_backend_options(BlockConf *conf, bool readonly, | ||
82 | |||
83 | blk_set_enable_write_cache(blk, wce); | ||
84 | blk_set_on_error(blk, rerror, werror); | ||
85 | + | ||
86 | + return true; | ||
87 | } | ||
88 | |||
89 | -void blkconf_geometry(BlockConf *conf, int *ptrans, | ||
90 | +bool blkconf_geometry(BlockConf *conf, int *ptrans, | ||
91 | unsigned cyls_max, unsigned heads_max, unsigned secs_max, | ||
92 | Error **errp) | ||
93 | { | ||
94 | @@ -XXX,XX +XXX,XX @@ void blkconf_geometry(BlockConf *conf, int *ptrans, | ||
95 | if (conf->cyls || conf->heads || conf->secs) { | ||
96 | if (conf->cyls < 1 || conf->cyls > cyls_max) { | ||
97 | error_setg(errp, "cyls must be between 1 and %u", cyls_max); | ||
98 | - return; | ||
99 | + return false; | ||
100 | } | ||
101 | if (conf->heads < 1 || conf->heads > heads_max) { | ||
102 | error_setg(errp, "heads must be between 1 and %u", heads_max); | ||
103 | - return; | ||
104 | + return false; | ||
105 | } | ||
106 | if (conf->secs < 1 || conf->secs > secs_max) { | ||
107 | error_setg(errp, "secs must be between 1 and %u", secs_max); | ||
108 | - return; | ||
109 | + return false; | ||
110 | } | ||
111 | } | ||
112 | + return true; | ||
113 | } | ||
114 | diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c | ||
115 | index XXXXXXX..XXXXXXX 100644 | ||
116 | --- a/hw/block/dataplane/virtio-blk.c | ||
117 | +++ b/hw/block/dataplane/virtio-blk.c | ||
118 | @@ -XXX,XX +XXX,XX @@ static void notify_guest_bh(void *opaque) | ||
119 | } | ||
120 | |||
121 | /* Context: QEMU global mutex held */ | ||
122 | -void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, | ||
123 | +bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, | ||
124 | VirtIOBlockDataPlane **dataplane, | ||
125 | Error **errp) | ||
126 | { | ||
127 | @@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, | ||
128 | error_setg(errp, | ||
129 | "device is incompatible with iothread " | ||
130 | "(transport does not support notifiers)"); | ||
131 | - return; | ||
132 | + return false; | ||
133 | } | ||
134 | if (!virtio_device_ioeventfd_enabled(vdev)) { | ||
135 | error_setg(errp, "ioeventfd is required for iothread"); | ||
136 | - return; | ||
137 | + return false; | ||
138 | } | ||
139 | |||
140 | /* If dataplane is (re-)enabled while the guest is running there could | ||
141 | @@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, | ||
142 | */ | ||
143 | if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { | ||
144 | error_prepend(errp, "cannot start virtio-blk dataplane: "); | ||
145 | - return; | ||
146 | + return false; | ||
147 | } | ||
148 | } | ||
149 | /* Don't try if transport does not support notifiers. */ | ||
150 | if (!virtio_device_ioeventfd_enabled(vdev)) { | ||
151 | - return; | ||
152 | + return false; | ||
153 | } | ||
154 | |||
155 | s = g_new0(VirtIOBlockDataPlane, 1); | ||
156 | @@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, | ||
157 | s->batch_notify_vqs = bitmap_new(conf->num_queues); | ||
158 | |||
159 | *dataplane = s; | ||
160 | + | ||
161 | + return true; | ||
162 | } | ||
163 | |||
164 | /* Context: QEMU global mutex held */ | ||
165 | -- | ||
166 | 2.14.3 | ||
167 | |||
168 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> | |
2 | |||
3 | [Drop virtio_blk_data_plane_create() change that misinterprets return | ||
4 | value when the virtio transport does not support dataplane. | ||
5 | --Stefan] | ||
6 | |||
7 | Cc: John Snow <jsnow@redhat.com> | ||
8 | Cc: Kevin Wolf <kwolf@redhat.com> | ||
9 | Cc: Max Reitz <mreitz@redhat.com> | ||
10 | Cc: Keith Busch <keith.busch@intel.com> | ||
11 | Cc: Stefan Hajnoczi <stefanha@redhat.com> | ||
12 | Cc: "Michael S. Tsirkin" <mst@redhat.com> | ||
13 | Cc: Paolo Bonzini <pbonzini@redhat.com> | ||
14 | Cc: Gerd Hoffmann <kraxel@redhat.com> | ||
15 | Cc: Markus Armbruster <armbru@redhat.com> | ||
16 | |||
17 | Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> | ||
18 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
19 | Message-id: e77848d3735ba590f23ffbf8094379c646c33d79.1511317952.git.maozy.fnst@cn.fujitsu.com | ||
20 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
21 | --- | ||
22 | hw/block/fdc.c | 17 ++++++----------- | ||
23 | hw/block/nvme.c | 7 ++----- | ||
24 | hw/block/virtio-blk.c | 13 +++++-------- | ||
25 | hw/ide/qdev.c | 12 ++++-------- | ||
26 | hw/scsi/scsi-disk.c | 13 ++++--------- | ||
27 | hw/usb/dev-storage.c | 9 +++------ | ||
28 | 6 files changed, 24 insertions(+), 47 deletions(-) | ||
29 | |||
30 | diff --git a/hw/block/fdc.c b/hw/block/fdc.c | ||
31 | index XXXXXXX..XXXXXXX 100644 | ||
32 | --- a/hw/block/fdc.c | ||
33 | +++ b/hw/block/fdc.c | ||
34 | @@ -XXX,XX +XXX,XX @@ static void fd_revalidate(FDrive *drv) | ||
35 | static void fd_change_cb(void *opaque, bool load, Error **errp) | ||
36 | { | ||
37 | FDrive *drive = opaque; | ||
38 | - Error *local_err = NULL; | ||
39 | |||
40 | if (!load) { | ||
41 | blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort); | ||
42 | } else { | ||
43 | - blkconf_apply_backend_options(drive->conf, | ||
44 | - blk_is_read_only(drive->blk), false, | ||
45 | - &local_err); | ||
46 | - if (local_err) { | ||
47 | - error_propagate(errp, local_err); | ||
48 | + if (!blkconf_apply_backend_options(drive->conf, | ||
49 | + blk_is_read_only(drive->blk), false, | ||
50 | + errp)) { | ||
51 | return; | ||
52 | } | ||
53 | } | ||
54 | @@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp) | ||
55 | FloppyDrive *dev = FLOPPY_DRIVE(qdev); | ||
56 | FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus); | ||
57 | FDrive *drive; | ||
58 | - Error *local_err = NULL; | ||
59 | int ret; | ||
60 | |||
61 | if (dev->unit == -1) { | ||
62 | @@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp) | ||
63 | dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO; | ||
64 | dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO; | ||
65 | |||
66 | - blkconf_apply_backend_options(&dev->conf, blk_is_read_only(dev->conf.blk), | ||
67 | - false, &local_err); | ||
68 | - if (local_err) { | ||
69 | - error_propagate(errp, local_err); | ||
70 | + if (!blkconf_apply_backend_options(&dev->conf, | ||
71 | + blk_is_read_only(dev->conf.blk), | ||
72 | + false, errp)) { | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | diff --git a/hw/block/nvme.c b/hw/block/nvme.c | ||
77 | index XXXXXXX..XXXXXXX 100644 | ||
78 | --- a/hw/block/nvme.c | ||
79 | +++ b/hw/block/nvme.c | ||
80 | @@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) | ||
81 | int i; | ||
82 | int64_t bs_size; | ||
83 | uint8_t *pci_conf; | ||
84 | - Error *local_err = NULL; | ||
85 | |||
86 | if (!n->conf.blk) { | ||
87 | error_setg(errp, "drive property not set"); | ||
88 | @@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) | ||
89 | return; | ||
90 | } | ||
91 | blkconf_blocksizes(&n->conf); | ||
92 | - blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk), | ||
93 | - false, &local_err); | ||
94 | - if (local_err) { | ||
95 | - error_propagate(errp, local_err); | ||
96 | + if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk), | ||
97 | + false, errp)) { | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c | ||
102 | index XXXXXXX..XXXXXXX 100644 | ||
103 | --- a/hw/block/virtio-blk.c | ||
104 | +++ b/hw/block/virtio-blk.c | ||
105 | @@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) | ||
106 | } | ||
107 | |||
108 | blkconf_serial(&conf->conf, &conf->serial); | ||
109 | - blkconf_apply_backend_options(&conf->conf, | ||
110 | - blk_is_read_only(conf->conf.blk), true, | ||
111 | - &err); | ||
112 | - if (err) { | ||
113 | - error_propagate(errp, err); | ||
114 | + if (!blkconf_apply_backend_options(&conf->conf, | ||
115 | + blk_is_read_only(conf->conf.blk), true, | ||
116 | + errp)) { | ||
117 | return; | ||
118 | } | ||
119 | s->original_wce = blk_enable_write_cache(conf->conf.blk); | ||
120 | - blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err); | ||
121 | - if (err) { | ||
122 | - error_propagate(errp, err); | ||
123 | + if (!blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, errp)) { | ||
124 | return; | ||
125 | } | ||
126 | + | ||
127 | blkconf_blocksizes(&conf->conf); | ||
128 | |||
129 | virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, | ||
130 | diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c | ||
131 | index XXXXXXX..XXXXXXX 100644 | ||
132 | --- a/hw/ide/qdev.c | ||
133 | +++ b/hw/ide/qdev.c | ||
134 | @@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp) | ||
135 | { | ||
136 | IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); | ||
137 | IDEState *s = bus->ifs + dev->unit; | ||
138 | - Error *err = NULL; | ||
139 | int ret; | ||
140 | |||
141 | if (!dev->conf.blk) { | ||
142 | @@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp) | ||
143 | |||
144 | blkconf_serial(&dev->conf, &dev->serial); | ||
145 | if (kind != IDE_CD) { | ||
146 | - blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, &err); | ||
147 | - if (err) { | ||
148 | - error_propagate(errp, err); | ||
149 | + if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, | ||
150 | + errp)) { | ||
151 | return; | ||
152 | } | ||
153 | } | ||
154 | - blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, kind != IDE_CD, | ||
155 | - &err); | ||
156 | - if (err) { | ||
157 | - error_propagate(errp, err); | ||
158 | + if (!blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, | ||
159 | + kind != IDE_CD, errp)) { | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c | ||
164 | index XXXXXXX..XXXXXXX 100644 | ||
165 | --- a/hw/scsi/scsi-disk.c | ||
166 | +++ b/hw/scsi/scsi-disk.c | ||
167 | @@ -XXX,XX +XXX,XX @@ static void scsi_disk_unit_attention_reported(SCSIDevice *dev) | ||
168 | static void scsi_realize(SCSIDevice *dev, Error **errp) | ||
169 | { | ||
170 | SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); | ||
171 | - Error *err = NULL; | ||
172 | |||
173 | if (!s->qdev.conf.blk) { | ||
174 | error_setg(errp, "drive property not set"); | ||
175 | @@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp) | ||
176 | } | ||
177 | |||
178 | if (dev->type == TYPE_DISK) { | ||
179 | - blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, &err); | ||
180 | - if (err) { | ||
181 | - error_propagate(errp, err); | ||
182 | + if (!blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, errp)) { | ||
183 | return; | ||
184 | } | ||
185 | } | ||
186 | - blkconf_apply_backend_options(&dev->conf, | ||
187 | - blk_is_read_only(s->qdev.conf.blk), | ||
188 | - dev->type == TYPE_DISK, &err); | ||
189 | - if (err) { | ||
190 | - error_propagate(errp, err); | ||
191 | + if (!blkconf_apply_backend_options(&dev->conf, | ||
192 | + blk_is_read_only(s->qdev.conf.blk), | ||
193 | + dev->type == TYPE_DISK, errp)) { | ||
194 | return; | ||
195 | } | ||
196 | |||
197 | diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c | ||
198 | index XXXXXXX..XXXXXXX 100644 | ||
199 | --- a/hw/usb/dev-storage.c | ||
200 | +++ b/hw/usb/dev-storage.c | ||
201 | @@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) | ||
202 | MSDState *s = USB_STORAGE_DEV(dev); | ||
203 | BlockBackend *blk = s->conf.blk; | ||
204 | SCSIDevice *scsi_dev; | ||
205 | - Error *err = NULL; | ||
206 | |||
207 | if (!blk) { | ||
208 | error_setg(errp, "drive property not set"); | ||
209 | @@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) | ||
210 | |||
211 | blkconf_serial(&s->conf, &dev->serial); | ||
212 | blkconf_blocksizes(&s->conf); | ||
213 | - blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true, &err); | ||
214 | - if (err) { | ||
215 | - error_propagate(errp, err); | ||
216 | + if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true, | ||
217 | + errp)) { | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | @@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) | ||
222 | &usb_msd_scsi_info_storage, NULL); | ||
223 | scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable, | ||
224 | s->conf.bootindex, dev->serial, | ||
225 | - &err); | ||
226 | + errp); | ||
227 | blk_unref(blk); | ||
228 | if (!scsi_dev) { | ||
229 | - error_propagate(errp, err); | ||
230 | return; | ||
231 | } | ||
232 | usb_msd_handle_reset(dev); | ||
233 | -- | ||
234 | 2.14.3 | ||
235 | |||
236 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> | ||
1 | 2 | ||
3 | The function name of usb_msd_{realize,unrealize}_*, | ||
4 | usb_msd_class_initfn_* are unusual. Rename it to | ||
5 | usb_msd_*_{realize,unrealize}, usb_msd_class_*_initfn. | ||
6 | |||
7 | Cc: Gerd Hoffmann <kraxel@redhat.com> | ||
8 | |||
9 | Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
11 | Message-id: 11e6003433abce35f3f4970e1acc71ee92dbcf51.1511317952.git.maozy.fnst@cn.fujitsu.com | ||
12 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
13 | --- | ||
14 | hw/usb/dev-storage.c | 20 ++++++++++---------- | ||
15 | 1 file changed, 10 insertions(+), 10 deletions(-) | ||
16 | |||
17 | diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/hw/usb/dev-storage.c | ||
20 | +++ b/hw/usb/dev-storage.c | ||
21 | @@ -XXX,XX +XXX,XX @@ static void usb_msd_unrealize_storage(USBDevice *dev, Error **errp) | ||
22 | object_unref(OBJECT(&s->bus)); | ||
23 | } | ||
24 | |||
25 | -static void usb_msd_realize_storage(USBDevice *dev, Error **errp) | ||
26 | +static void usb_msd_storage_realize(USBDevice *dev, Error **errp) | ||
27 | { | ||
28 | MSDState *s = USB_STORAGE_DEV(dev); | ||
29 | BlockBackend *blk = s->conf.blk; | ||
30 | @@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) | ||
31 | s->scsi_dev = scsi_dev; | ||
32 | } | ||
33 | |||
34 | -static void usb_msd_unrealize_bot(USBDevice *dev, Error **errp) | ||
35 | +static void usb_msd_bot_unrealize(USBDevice *dev, Error **errp) | ||
36 | { | ||
37 | MSDState *s = USB_STORAGE_DEV(dev); | ||
38 | |||
39 | object_unref(OBJECT(&s->bus)); | ||
40 | } | ||
41 | |||
42 | -static void usb_msd_realize_bot(USBDevice *dev, Error **errp) | ||
43 | +static void usb_msd_bot_realize(USBDevice *dev, Error **errp) | ||
44 | { | ||
45 | MSDState *s = USB_STORAGE_DEV(dev); | ||
46 | DeviceState *d = DEVICE(dev); | ||
47 | @@ -XXX,XX +XXX,XX @@ static void usb_msd_class_initfn_common(ObjectClass *klass, void *data) | ||
48 | dc->vmsd = &vmstate_usb_msd; | ||
49 | } | ||
50 | |||
51 | -static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data) | ||
52 | +static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data) | ||
53 | { | ||
54 | DeviceClass *dc = DEVICE_CLASS(klass); | ||
55 | USBDeviceClass *uc = USB_DEVICE_CLASS(klass); | ||
56 | |||
57 | - uc->realize = usb_msd_realize_storage; | ||
58 | + uc->realize = usb_msd_storage_realize; | ||
59 | uc->unrealize = usb_msd_unrealize_storage; | ||
60 | dc->props = msd_properties; | ||
61 | } | ||
62 | @@ -XXX,XX +XXX,XX @@ static void usb_msd_instance_init(Object *obj) | ||
63 | object_property_set_int(obj, -1, "bootindex", NULL); | ||
64 | } | ||
65 | |||
66 | -static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data) | ||
67 | +static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data) | ||
68 | { | ||
69 | USBDeviceClass *uc = USB_DEVICE_CLASS(klass); | ||
70 | |||
71 | - uc->realize = usb_msd_realize_bot; | ||
72 | - uc->unrealize = usb_msd_unrealize_bot; | ||
73 | + uc->realize = usb_msd_bot_realize; | ||
74 | + uc->unrealize = usb_msd_bot_unrealize; | ||
75 | uc->attached_settable = true; | ||
76 | } | ||
77 | |||
78 | static const TypeInfo msd_info = { | ||
79 | .name = "usb-storage", | ||
80 | .parent = TYPE_USB_STORAGE, | ||
81 | - .class_init = usb_msd_class_initfn_storage, | ||
82 | + .class_init = usb_msd_class_storage_initfn, | ||
83 | .instance_init = usb_msd_instance_init, | ||
84 | }; | ||
85 | |||
86 | static const TypeInfo bot_info = { | ||
87 | .name = "usb-bot", | ||
88 | .parent = TYPE_USB_STORAGE, | ||
89 | - .class_init = usb_msd_class_initfn_bot, | ||
90 | + .class_init = usb_msd_class_bot_initfn, | ||
91 | }; | ||
92 | |||
93 | static void usb_msd_register_types(void) | ||
94 | -- | ||
95 | 2.14.3 | ||
96 | |||
97 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Commit 1351d1ec89eabebc9fdff20451a62c413d7accc1 ("qdev: drop iothread | ||
2 | property type") forgot to remove this include. | ||
1 | 3 | ||
4 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
5 | Message-id: 20171205133954.31006-1-stefanha@redhat.com | ||
6 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
7 | --- | ||
8 | hw/core/qdev-properties-system.c | 1 - | ||
9 | 1 file changed, 1 deletion(-) | ||
10 | |||
11 | diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/hw/core/qdev-properties-system.c | ||
14 | +++ b/hw/core/qdev-properties-system.c | ||
15 | @@ -XXX,XX +XXX,XX @@ | ||
16 | #include "qapi/visitor.h" | ||
17 | #include "chardev/char-fe.h" | ||
18 | #include "sysemu/tpm_backend.h" | ||
19 | -#include "sysemu/iothread.h" | ||
20 | |||
21 | static void get_pointer(Object *obj, Visitor *v, Property *prop, | ||
22 | char *(*print)(void *ptr), | ||
23 | -- | ||
24 | 2.14.3 | ||
25 | |||
26 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | bdrv_unref() requires the AioContext lock because bdrv_flush() uses |
---|---|---|---|
2 | BDRV_POLL_WHILE(), which assumes the AioContext is currently held. If | ||
3 | BDRV_POLL_WHILE() runs without AioContext held the | ||
4 | pthread_mutex_unlock() call in aio_context_release() fails. | ||
2 | 5 | ||
3 | qemu-img's convert_co_copy_range() operates at the sector level and | 6 | This patch moves bdrv_unref() into the AioContext locked region to solve |
4 | block_copy() operates at the cluster level so this condition is always | 7 | the following pthread_mutex_unlock() failure: |
5 | true, but it is not necessary to restrict this here, so let's leave it | ||
6 | to the driver implementation return an error if there is any. | ||
7 | 8 | ||
8 | Signed-off-by: Alberto Garcia <berto@igalia.com> | 9 | #0 0x00007f566181969b in raise () at /lib64/libc.so.6 |
9 | Message-id: a4264aaee656910c84161a2965f7a501437379ca.1579374329.git.berto@igalia.com | 10 | #1 0x00007f566181b3b1 in abort () at /lib64/libc.so.6 |
10 | Reviewed-by: Max Reitz <mreitz@redhat.com> | 11 | #2 0x00005592cd590458 in error_exit (err=<optimized out>, msg=msg@entry=0x5592cdaf6d60 <__func__.23977> "qemu_mutex_unlock") at util/qemu-thread-posix.c:36 |
11 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 12 | #3 0x00005592cd96e738 in qemu_mutex_unlock (mutex=mutex@entry=0x5592ce9505e0) at util/qemu-thread-posix.c:96 |
13 | #4 0x00005592cd969b69 in aio_context_release (ctx=ctx@entry=0x5592ce950580) at util/async.c:507 | ||
14 | #5 0x00005592cd8ead78 in bdrv_flush (bs=bs@entry=0x5592cfa87210) at block/io.c:2478 | ||
15 | #6 0x00005592cd89df30 in bdrv_close (bs=0x5592cfa87210) at block.c:3207 | ||
16 | #7 0x00005592cd89df30 in bdrv_delete (bs=0x5592cfa87210) at block.c:3395 | ||
17 | #8 0x00005592cd89df30 in bdrv_unref (bs=0x5592cfa87210) at block.c:4418 | ||
18 | #9 0x00005592cd6b7f86 in qmp_transaction (dev_list=<optimized out>, has_props=<optimized out>, props=<optimized out>, errp=errp@entry=0x7ffe4a1fc9d8) at blockdev.c:2308 | ||
19 | |||
20 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
21 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
22 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
23 | Message-id: 20171206144550.22295-2-stefanha@redhat.com | ||
24 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
12 | --- | 25 | --- |
13 | block/qcow2.c | 4 ---- | 26 | blockdev.c | 2 +- |
14 | 1 file changed, 4 deletions(-) | 27 | 1 file changed, 1 insertion(+), 1 deletion(-) |
15 | 28 | ||
16 | diff --git a/block/qcow2.c b/block/qcow2.c | 29 | diff --git a/blockdev.c b/blockdev.c |
17 | index XXXXXXX..XXXXXXX 100644 | 30 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/block/qcow2.c | 31 | --- a/blockdev.c |
19 | +++ b/block/qcow2.c | 32 | +++ b/blockdev.c |
20 | @@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs, | 33 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common) |
21 | case QCOW2_CLUSTER_NORMAL: | 34 | DO_UPCAST(ExternalSnapshotState, common, common); |
22 | child = s->data_file; | 35 | if (state->aio_context) { |
23 | copy_offset += offset_into_cluster(s, src_offset); | 36 | bdrv_drained_end(state->old_bs); |
24 | - if ((copy_offset & 511) != 0) { | 37 | - aio_context_release(state->aio_context); |
25 | - ret = -EIO; | 38 | bdrv_unref(state->new_bs); |
26 | - goto out; | 39 | + aio_context_release(state->aio_context); |
27 | - } | 40 | } |
28 | break; | 41 | } |
29 | 42 | ||
30 | default: | ||
31 | -- | 43 | -- |
32 | 2.24.1 | 44 | 2.14.3 |
33 | 45 | ||
34 | 46 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | 1 | It is not necessary to hold AioContext across transactions anymore since | |
2 | bdrv_drained_begin/end() is used to keep the nodes quiesced. In fact, | ||
3 | using the AioContext lock for this purpose was always buggy. | ||
4 | |||
5 | This patch reduces the scope of AioContext locked regions. This is not | ||
6 | just a cleanup but also fixes hangs that occur in BDRV_POLL_WHILE() | ||
7 | because it is unware of recursive locking and does not release the | ||
8 | AioContext the necessary number of times to allow progress to be made. | ||
9 | |||
10 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
11 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
13 | Message-id: 20171206144550.22295-3-stefanha@redhat.com | ||
14 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
15 | --- | ||
16 | blockdev.c | 71 ++++++++++++++++++++++++++++++++++++++++++-------------------- | ||
17 | 1 file changed, 48 insertions(+), 23 deletions(-) | ||
18 | |||
19 | diff --git a/blockdev.c b/blockdev.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/blockdev.c | ||
22 | +++ b/blockdev.c | ||
23 | @@ -XXX,XX +XXX,XX @@ typedef struct ExternalSnapshotState { | ||
24 | BlkActionState common; | ||
25 | BlockDriverState *old_bs; | ||
26 | BlockDriverState *new_bs; | ||
27 | - AioContext *aio_context; | ||
28 | bool overlay_appended; | ||
29 | } ExternalSnapshotState; | ||
30 | |||
31 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
32 | ExternalSnapshotState *state = | ||
33 | DO_UPCAST(ExternalSnapshotState, common, common); | ||
34 | TransactionAction *action = common->action; | ||
35 | + AioContext *aio_context; | ||
36 | |||
37 | /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar | ||
38 | * purpose but a different set of parameters */ | ||
39 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
40 | return; | ||
41 | } | ||
42 | |||
43 | - /* Acquire AioContext now so any threads operating on old_bs stop */ | ||
44 | - state->aio_context = bdrv_get_aio_context(state->old_bs); | ||
45 | - aio_context_acquire(state->aio_context); | ||
46 | + aio_context = bdrv_get_aio_context(state->old_bs); | ||
47 | + aio_context_acquire(aio_context); | ||
48 | + | ||
49 | + /* Paired with .clean() */ | ||
50 | bdrv_drained_begin(state->old_bs); | ||
51 | |||
52 | if (!bdrv_is_inserted(state->old_bs)) { | ||
53 | error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); | ||
54 | - return; | ||
55 | + goto out; | ||
56 | } | ||
57 | |||
58 | if (bdrv_op_is_blocked(state->old_bs, | ||
59 | BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) { | ||
60 | - return; | ||
61 | + goto out; | ||
62 | } | ||
63 | |||
64 | if (!bdrv_is_read_only(state->old_bs)) { | ||
65 | if (bdrv_flush(state->old_bs)) { | ||
66 | error_setg(errp, QERR_IO_ERROR); | ||
67 | - return; | ||
68 | + goto out; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | if (!bdrv_is_first_non_filter(state->old_bs)) { | ||
73 | error_setg(errp, QERR_FEATURE_DISABLED, "snapshot"); | ||
74 | - return; | ||
75 | + goto out; | ||
76 | } | ||
77 | |||
78 | if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) { | ||
79 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
80 | |||
81 | if (node_name && !snapshot_node_name) { | ||
82 | error_setg(errp, "New snapshot node name missing"); | ||
83 | - return; | ||
84 | + goto out; | ||
85 | } | ||
86 | |||
87 | if (snapshot_node_name && | ||
88 | bdrv_lookup_bs(snapshot_node_name, snapshot_node_name, NULL)) { | ||
89 | error_setg(errp, "New snapshot node name already in use"); | ||
90 | - return; | ||
91 | + goto out; | ||
92 | } | ||
93 | |||
94 | flags = state->old_bs->open_flags; | ||
95 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
96 | int64_t size = bdrv_getlength(state->old_bs); | ||
97 | if (size < 0) { | ||
98 | error_setg_errno(errp, -size, "bdrv_getlength failed"); | ||
99 | - return; | ||
100 | + goto out; | ||
101 | } | ||
102 | bdrv_img_create(new_image_file, format, | ||
103 | state->old_bs->filename, | ||
104 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
105 | NULL, size, flags, false, &local_err); | ||
106 | if (local_err) { | ||
107 | error_propagate(errp, local_err); | ||
108 | - return; | ||
109 | + goto out; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
114 | errp); | ||
115 | /* We will manually add the backing_hd field to the bs later */ | ||
116 | if (!state->new_bs) { | ||
117 | - return; | ||
118 | + goto out; | ||
119 | } | ||
120 | |||
121 | if (bdrv_has_blk(state->new_bs)) { | ||
122 | error_setg(errp, "The snapshot is already in use"); | ||
123 | - return; | ||
124 | + goto out; | ||
125 | } | ||
126 | |||
127 | if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, | ||
128 | errp)) { | ||
129 | - return; | ||
130 | + goto out; | ||
131 | } | ||
132 | |||
133 | if (state->new_bs->backing != NULL) { | ||
134 | error_setg(errp, "The snapshot already has a backing image"); | ||
135 | - return; | ||
136 | + goto out; | ||
137 | } | ||
138 | |||
139 | if (!state->new_bs->drv->supports_backing) { | ||
140 | error_setg(errp, "The snapshot does not support backing images"); | ||
141 | - return; | ||
142 | + goto out; | ||
143 | } | ||
144 | |||
145 | - bdrv_set_aio_context(state->new_bs, state->aio_context); | ||
146 | + bdrv_set_aio_context(state->new_bs, aio_context); | ||
147 | |||
148 | /* This removes our old bs and adds the new bs. This is an operation that | ||
149 | * can fail, so we need to do it in .prepare; undoing it for abort is | ||
150 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
151 | bdrv_append(state->new_bs, state->old_bs, &local_err); | ||
152 | if (local_err) { | ||
153 | error_propagate(errp, local_err); | ||
154 | - return; | ||
155 | + goto out; | ||
156 | } | ||
157 | state->overlay_appended = true; | ||
158 | + | ||
159 | +out: | ||
160 | + aio_context_release(aio_context); | ||
161 | } | ||
162 | |||
163 | static void external_snapshot_commit(BlkActionState *common) | ||
164 | { | ||
165 | ExternalSnapshotState *state = | ||
166 | DO_UPCAST(ExternalSnapshotState, common, common); | ||
167 | + AioContext *aio_context; | ||
168 | + | ||
169 | + aio_context = bdrv_get_aio_context(state->old_bs); | ||
170 | + aio_context_acquire(aio_context); | ||
171 | |||
172 | /* We don't need (or want) to use the transactional | ||
173 | * bdrv_reopen_multiple() across all the entries at once, because we | ||
174 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_commit(BlkActionState *common) | ||
175 | bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDWR, | ||
176 | NULL); | ||
177 | } | ||
178 | + | ||
179 | + aio_context_release(aio_context); | ||
180 | } | ||
181 | |||
182 | static void external_snapshot_abort(BlkActionState *common) | ||
183 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common) | ||
184 | DO_UPCAST(ExternalSnapshotState, common, common); | ||
185 | if (state->new_bs) { | ||
186 | if (state->overlay_appended) { | ||
187 | + AioContext *aio_context; | ||
188 | + | ||
189 | + aio_context = bdrv_get_aio_context(state->old_bs); | ||
190 | + aio_context_acquire(aio_context); | ||
191 | + | ||
192 | bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd() | ||
193 | close state->old_bs; we need it */ | ||
194 | bdrv_set_backing_hd(state->new_bs, NULL, &error_abort); | ||
195 | bdrv_replace_node(state->new_bs, state->old_bs, &error_abort); | ||
196 | bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */ | ||
197 | + | ||
198 | + aio_context_release(aio_context); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common) | ||
203 | { | ||
204 | ExternalSnapshotState *state = | ||
205 | DO_UPCAST(ExternalSnapshotState, common, common); | ||
206 | - if (state->aio_context) { | ||
207 | - bdrv_drained_end(state->old_bs); | ||
208 | - bdrv_unref(state->new_bs); | ||
209 | - aio_context_release(state->aio_context); | ||
210 | + AioContext *aio_context; | ||
211 | + | ||
212 | + if (!state->old_bs) { | ||
213 | + return; | ||
214 | } | ||
215 | + | ||
216 | + aio_context = bdrv_get_aio_context(state->old_bs); | ||
217 | + aio_context_acquire(aio_context); | ||
218 | + | ||
219 | + bdrv_drained_end(state->old_bs); | ||
220 | + bdrv_unref(state->new_bs); | ||
221 | + | ||
222 | + aio_context_release(aio_context); | ||
223 | } | ||
224 | |||
225 | typedef struct DriveBackupState { | ||
226 | -- | ||
227 | 2.14.3 | ||
228 | |||
229 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
---|---|---|---|
2 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
3 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
4 | Message-id: 20171206144550.22295-4-stefanha@redhat.com | ||
5 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
6 | --- | ||
7 | blockdev.c | 42 ++++++++++++++++++++++++++++++++++-------- | ||
8 | 1 file changed, 34 insertions(+), 8 deletions(-) | ||
2 | 9 | ||
3 | qcow2_alloc_cluster_offset() and qcow2_get_cluster_offset() always | 10 | diff --git a/blockdev.c b/blockdev.c |
4 | return offsets that are cluster-aligned so don't just check that they | ||
5 | are sector-aligned. | ||
6 | |||
7 | The check in qcow2_co_preadv_task() is also replaced by an assertion | ||
8 | for the same reason. | ||
9 | |||
10 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
11 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
12 | Message-id: 558ba339965f858bede4c73ce3f50f0c0493597d.1579374329.git.berto@igalia.com | ||
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
14 | --- | ||
15 | block/qcow2.c | 9 +++------ | ||
16 | 1 file changed, 3 insertions(+), 6 deletions(-) | ||
17 | |||
18 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/block/qcow2.c | 12 | --- a/blockdev.c |
21 | +++ b/block/qcow2.c | 13 | +++ b/blockdev.c |
22 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs, | 14 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common) |
23 | offset, bytes, qiov, qiov_offset); | 15 | typedef struct DriveBackupState { |
24 | 16 | BlkActionState common; | |
25 | case QCOW2_CLUSTER_NORMAL: | 17 | BlockDriverState *bs; |
26 | - if ((file_cluster_offset & 511) != 0) { | 18 | - AioContext *aio_context; |
27 | - return -EIO; | 19 | BlockJob *job; |
28 | - } | 20 | } DriveBackupState; |
29 | - | 21 | |
30 | + assert(offset_into_cluster(s, file_cluster_offset) == 0); | 22 | @@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp) |
31 | if (bs->encrypted) { | 23 | DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); |
32 | return qcow2_co_preadv_encrypted(bs, file_cluster_offset, | 24 | BlockDriverState *bs; |
33 | offset, bytes, qiov, qiov_offset); | 25 | DriveBackup *backup; |
34 | @@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part( | 26 | + AioContext *aio_context; |
35 | goto out_locked; | 27 | Error *local_err = NULL; |
36 | } | 28 | |
37 | 29 | assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); | |
38 | - assert((cluster_offset & 511) == 0); | 30 | @@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp) |
39 | + assert(offset_into_cluster(s, cluster_offset) == 0); | 31 | return; |
40 | 32 | } | |
41 | ret = qcow2_pre_write_overlap_check(bs, 0, | 33 | |
42 | cluster_offset + offset_in_cluster, | 34 | - /* AioContext is released in .clean() */ |
43 | @@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs, | 35 | - state->aio_context = bdrv_get_aio_context(bs); |
44 | goto fail; | 36 | - aio_context_acquire(state->aio_context); |
45 | } | 37 | + aio_context = bdrv_get_aio_context(bs); |
46 | 38 | + aio_context_acquire(aio_context); | |
47 | - assert((cluster_offset & 511) == 0); | 39 | + |
48 | + assert(offset_into_cluster(s, cluster_offset) == 0); | 40 | + /* Paired with .clean() */ |
49 | 41 | bdrv_drained_begin(bs); | |
50 | ret = qcow2_pre_write_overlap_check(bs, 0, | 42 | + |
51 | cluster_offset + offset_in_cluster, cur_bytes, true); | 43 | state->bs = bs; |
44 | |||
45 | state->job = do_drive_backup(backup, common->block_job_txn, &local_err); | ||
46 | if (local_err) { | ||
47 | error_propagate(errp, local_err); | ||
48 | - return; | ||
49 | + goto out; | ||
50 | } | ||
51 | + | ||
52 | +out: | ||
53 | + aio_context_release(aio_context); | ||
54 | } | ||
55 | |||
56 | static void drive_backup_commit(BlkActionState *common) | ||
57 | { | ||
58 | DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); | ||
59 | + AioContext *aio_context; | ||
60 | + | ||
61 | + aio_context = bdrv_get_aio_context(state->bs); | ||
62 | + aio_context_acquire(aio_context); | ||
63 | + | ||
64 | assert(state->job); | ||
65 | block_job_start(state->job); | ||
66 | + | ||
67 | + aio_context_release(aio_context); | ||
68 | } | ||
69 | |||
70 | static void drive_backup_abort(BlkActionState *common) | ||
71 | @@ -XXX,XX +XXX,XX @@ static void drive_backup_abort(BlkActionState *common) | ||
72 | DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); | ||
73 | |||
74 | if (state->job) { | ||
75 | + AioContext *aio_context; | ||
76 | + | ||
77 | + aio_context = bdrv_get_aio_context(state->bs); | ||
78 | + aio_context_acquire(aio_context); | ||
79 | + | ||
80 | block_job_cancel_sync(state->job); | ||
81 | + | ||
82 | + aio_context_release(aio_context); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | static void drive_backup_clean(BlkActionState *common) | ||
87 | { | ||
88 | DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); | ||
89 | + AioContext *aio_context; | ||
90 | |||
91 | - if (state->aio_context) { | ||
92 | - bdrv_drained_end(state->bs); | ||
93 | - aio_context_release(state->aio_context); | ||
94 | + if (!state->bs) { | ||
95 | + return; | ||
96 | } | ||
97 | + | ||
98 | + aio_context = bdrv_get_aio_context(state->bs); | ||
99 | + aio_context_acquire(aio_context); | ||
100 | + | ||
101 | + bdrv_drained_end(state->bs); | ||
102 | + | ||
103 | + aio_context_release(aio_context); | ||
104 | } | ||
105 | |||
106 | typedef struct BlockdevBackupState { | ||
52 | -- | 107 | -- |
53 | 2.24.1 | 108 | 2.14.3 |
54 | 109 | ||
55 | 110 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
---|---|---|---|
2 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
3 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
4 | Message-id: 20171206144550.22295-5-stefanha@redhat.com | ||
5 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
6 | --- | ||
7 | blockdev.c | 44 ++++++++++++++++++++++++++++++++++---------- | ||
8 | 1 file changed, 34 insertions(+), 10 deletions(-) | ||
2 | 9 | ||
3 | The L1 table is read from disk using the byte-based bdrv_pread() and | 10 | diff --git a/blockdev.c b/blockdev.c |
4 | is never accessed beyond its last element, so there's no need to | ||
5 | allocate more memory than that. | ||
6 | |||
7 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
8 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
9 | Message-id: b2e27214ec7b03a585931bcf383ee1ac3a641a10.1579374329.git.berto@igalia.com | ||
10 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
11 | --- | ||
12 | block/qcow2-cluster.c | 5 ++--- | ||
13 | block/qcow2-refcount.c | 2 +- | ||
14 | block/qcow2-snapshot.c | 3 +-- | ||
15 | block/qcow2.c | 2 +- | ||
16 | 4 files changed, 5 insertions(+), 7 deletions(-) | ||
17 | |||
18 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
19 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/block/qcow2-cluster.c | 12 | --- a/blockdev.c |
21 | +++ b/block/qcow2-cluster.c | 13 | +++ b/blockdev.c |
22 | @@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, | 14 | @@ -XXX,XX +XXX,XX @@ typedef struct BlockdevBackupState { |
23 | #endif | 15 | BlkActionState common; |
24 | 16 | BlockDriverState *bs; | |
25 | new_l1_size2 = sizeof(uint64_t) * new_l1_size; | 17 | BlockJob *job; |
26 | - new_l1_table = qemu_try_blockalign(bs->file->bs, | 18 | - AioContext *aio_context; |
27 | - ROUND_UP(new_l1_size2, 512)); | 19 | } BlockdevBackupState; |
28 | + new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_size2); | 20 | |
29 | if (new_l1_table == NULL) { | 21 | static BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn, |
30 | return -ENOMEM; | 22 | @@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) |
23 | BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); | ||
24 | BlockdevBackup *backup; | ||
25 | BlockDriverState *bs, *target; | ||
26 | + AioContext *aio_context; | ||
27 | Error *local_err = NULL; | ||
28 | |||
29 | assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); | ||
30 | @@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) | ||
31 | return; | ||
31 | } | 32 | } |
32 | - memset(new_l1_table, 0, ROUND_UP(new_l1_size2, 512)); | 33 | |
33 | + memset(new_l1_table, 0, new_l1_size2); | 34 | - /* AioContext is released in .clean() */ |
34 | 35 | - state->aio_context = bdrv_get_aio_context(bs); | |
35 | if (s->l1_size) { | 36 | - if (state->aio_context != bdrv_get_aio_context(target)) { |
36 | memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); | 37 | - state->aio_context = NULL; |
37 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | 38 | + aio_context = bdrv_get_aio_context(bs); |
38 | index XXXXXXX..XXXXXXX 100644 | 39 | + if (aio_context != bdrv_get_aio_context(target)) { |
39 | --- a/block/qcow2-refcount.c | 40 | error_setg(errp, "Backup between two IO threads is not implemented"); |
40 | +++ b/block/qcow2-refcount.c | 41 | return; |
41 | @@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, | ||
42 | * l1_table_offset when it is the current s->l1_table_offset! Be careful | ||
43 | * when changing this! */ | ||
44 | if (l1_table_offset != s->l1_table_offset) { | ||
45 | - l1_table = g_try_malloc0(ROUND_UP(l1_size2, 512)); | ||
46 | + l1_table = g_try_malloc0(l1_size2); | ||
47 | if (l1_size2 && l1_table == NULL) { | ||
48 | ret = -ENOMEM; | ||
49 | goto fail; | ||
50 | diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/block/qcow2-snapshot.c | ||
53 | +++ b/block/qcow2-snapshot.c | ||
54 | @@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, | ||
55 | return ret; | ||
56 | } | 42 | } |
57 | new_l1_bytes = sn->l1_size * sizeof(uint64_t); | 43 | - aio_context_acquire(state->aio_context); |
58 | - new_l1_table = qemu_try_blockalign(bs->file->bs, | 44 | + aio_context_acquire(aio_context); |
59 | - ROUND_UP(new_l1_bytes, 512)); | 45 | state->bs = bs; |
60 | + new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes); | 46 | + |
61 | if (new_l1_table == NULL) { | 47 | + /* Paired with .clean() */ |
62 | return -ENOMEM; | 48 | bdrv_drained_begin(state->bs); |
49 | |||
50 | state->job = do_blockdev_backup(backup, common->block_job_txn, &local_err); | ||
51 | if (local_err) { | ||
52 | error_propagate(errp, local_err); | ||
53 | - return; | ||
54 | + goto out; | ||
63 | } | 55 | } |
64 | diff --git a/block/qcow2.c b/block/qcow2.c | 56 | + |
65 | index XXXXXXX..XXXXXXX 100644 | 57 | +out: |
66 | --- a/block/qcow2.c | 58 | + aio_context_release(aio_context); |
67 | +++ b/block/qcow2.c | 59 | } |
68 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, | 60 | |
69 | 61 | static void blockdev_backup_commit(BlkActionState *common) | |
70 | if (s->l1_size > 0) { | 62 | { |
71 | s->l1_table = qemu_try_blockalign(bs->file->bs, | 63 | BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); |
72 | - ROUND_UP(s->l1_size * sizeof(uint64_t), 512)); | 64 | + AioContext *aio_context; |
73 | + s->l1_size * sizeof(uint64_t)); | 65 | + |
74 | if (s->l1_table == NULL) { | 66 | + aio_context = bdrv_get_aio_context(state->bs); |
75 | error_setg(errp, "Could not allocate L1 table"); | 67 | + aio_context_acquire(aio_context); |
76 | ret = -ENOMEM; | 68 | + |
69 | assert(state->job); | ||
70 | block_job_start(state->job); | ||
71 | + | ||
72 | + aio_context_release(aio_context); | ||
73 | } | ||
74 | |||
75 | static void blockdev_backup_abort(BlkActionState *common) | ||
76 | @@ -XXX,XX +XXX,XX @@ static void blockdev_backup_abort(BlkActionState *common) | ||
77 | BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); | ||
78 | |||
79 | if (state->job) { | ||
80 | + AioContext *aio_context; | ||
81 | + | ||
82 | + aio_context = bdrv_get_aio_context(state->bs); | ||
83 | + aio_context_acquire(aio_context); | ||
84 | + | ||
85 | block_job_cancel_sync(state->job); | ||
86 | + | ||
87 | + aio_context_release(aio_context); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | static void blockdev_backup_clean(BlkActionState *common) | ||
92 | { | ||
93 | BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); | ||
94 | + AioContext *aio_context; | ||
95 | |||
96 | - if (state->aio_context) { | ||
97 | - bdrv_drained_end(state->bs); | ||
98 | - aio_context_release(state->aio_context); | ||
99 | + if (!state->bs) { | ||
100 | + return; | ||
101 | } | ||
102 | + | ||
103 | + aio_context = bdrv_get_aio_context(state->bs); | ||
104 | + aio_context_acquire(aio_context); | ||
105 | + | ||
106 | + bdrv_drained_end(state->bs); | ||
107 | + | ||
108 | + aio_context_release(aio_context); | ||
109 | } | ||
110 | |||
111 | typedef struct BlockDirtyBitmapState { | ||
77 | -- | 112 | -- |
78 | 2.24.1 | 113 | 2.14.3 |
79 | 114 | ||
80 | 115 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
---|---|---|---|
2 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
3 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
4 | Message-id: 20171206144550.22295-6-stefanha@redhat.com | ||
5 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
6 | --- | ||
7 | blockdev.c | 47 +++++++++++++++++++++++++++++++---------------- | ||
8 | 1 file changed, 31 insertions(+), 16 deletions(-) | ||
2 | 9 | ||
3 | This replaces all remaining instances in the qcow2 code. | 10 | diff --git a/blockdev.c b/blockdev.c |
4 | |||
5 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
6 | Message-id: b5f74b606c2d9873b12d29acdb7fd498029c4025.1579374329.git.berto@igalia.com | ||
7 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | block/qcow2.c | 8 +++++--- | ||
11 | 1 file changed, 5 insertions(+), 3 deletions(-) | ||
12 | |||
13 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/block/qcow2.c | 12 | --- a/blockdev.c |
16 | +++ b/block/qcow2.c | 13 | +++ b/blockdev.c |
17 | @@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp) | 14 | @@ -XXX,XX +XXX,XX @@ struct BlkActionState { |
18 | 15 | typedef struct InternalSnapshotState { | |
19 | /* Validate options and set default values */ | 16 | BlkActionState common; |
20 | if (!QEMU_IS_ALIGNED(qcow2_opts->size, BDRV_SECTOR_SIZE)) { | 17 | BlockDriverState *bs; |
21 | - error_setg(errp, "Image size must be a multiple of 512 bytes"); | 18 | - AioContext *aio_context; |
22 | + error_setg(errp, "Image size must be a multiple of %u bytes", | 19 | QEMUSnapshotInfo sn; |
23 | + (unsigned) BDRV_SECTOR_SIZE); | 20 | bool created; |
24 | ret = -EINVAL; | 21 | } InternalSnapshotState; |
25 | goto out; | 22 | @@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common, |
23 | qemu_timeval tv; | ||
24 | BlockdevSnapshotInternal *internal; | ||
25 | InternalSnapshotState *state; | ||
26 | + AioContext *aio_context; | ||
27 | int ret1; | ||
28 | |||
29 | g_assert(common->action->type == | ||
30 | @@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common, | ||
31 | return; | ||
26 | } | 32 | } |
27 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset, | 33 | |
28 | return -ENOTSUP; | 34 | - /* AioContext is released in .clean() */ |
35 | - state->aio_context = bdrv_get_aio_context(bs); | ||
36 | - aio_context_acquire(state->aio_context); | ||
37 | + aio_context = bdrv_get_aio_context(bs); | ||
38 | + aio_context_acquire(aio_context); | ||
39 | |||
40 | state->bs = bs; | ||
41 | + | ||
42 | + /* Paired with .clean() */ | ||
43 | bdrv_drained_begin(bs); | ||
44 | |||
45 | if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) { | ||
46 | - return; | ||
47 | + goto out; | ||
29 | } | 48 | } |
30 | 49 | ||
31 | - if (offset & 511) { | 50 | if (bdrv_is_read_only(bs)) { |
32 | - error_setg(errp, "The new size must be a multiple of 512"); | 51 | error_setg(errp, "Device '%s' is read only", device); |
33 | + if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) { | 52 | - return; |
34 | + error_setg(errp, "The new size must be a multiple of %u", | 53 | + goto out; |
35 | + (unsigned) BDRV_SECTOR_SIZE); | ||
36 | return -EINVAL; | ||
37 | } | 54 | } |
38 | 55 | ||
56 | if (!bdrv_can_snapshot(bs)) { | ||
57 | error_setg(errp, "Block format '%s' used by device '%s' " | ||
58 | "does not support internal snapshots", | ||
59 | bs->drv->format_name, device); | ||
60 | - return; | ||
61 | + goto out; | ||
62 | } | ||
63 | |||
64 | if (!strlen(name)) { | ||
65 | error_setg(errp, "Name is empty"); | ||
66 | - return; | ||
67 | + goto out; | ||
68 | } | ||
69 | |||
70 | /* check whether a snapshot with name exist */ | ||
71 | @@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common, | ||
72 | &local_err); | ||
73 | if (local_err) { | ||
74 | error_propagate(errp, local_err); | ||
75 | - return; | ||
76 | + goto out; | ||
77 | } else if (ret) { | ||
78 | error_setg(errp, | ||
79 | "Snapshot with name '%s' already exists on device '%s'", | ||
80 | name, device); | ||
81 | - return; | ||
82 | + goto out; | ||
83 | } | ||
84 | |||
85 | /* 3. take the snapshot */ | ||
86 | @@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common, | ||
87 | error_setg_errno(errp, -ret1, | ||
88 | "Failed to create snapshot '%s' on device '%s'", | ||
89 | name, device); | ||
90 | - return; | ||
91 | + goto out; | ||
92 | } | ||
93 | |||
94 | /* 4. succeed, mark a snapshot is created */ | ||
95 | state->created = true; | ||
96 | + | ||
97 | +out: | ||
98 | + aio_context_release(aio_context); | ||
99 | } | ||
100 | |||
101 | static void internal_snapshot_abort(BlkActionState *common) | ||
102 | @@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(BlkActionState *common) | ||
103 | DO_UPCAST(InternalSnapshotState, common, common); | ||
104 | BlockDriverState *bs = state->bs; | ||
105 | QEMUSnapshotInfo *sn = &state->sn; | ||
106 | + AioContext *aio_context; | ||
107 | Error *local_error = NULL; | ||
108 | |||
109 | if (!state->created) { | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | + aio_context = bdrv_get_aio_context(state->bs); | ||
114 | + aio_context_acquire(aio_context); | ||
115 | + | ||
116 | if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) { | ||
117 | error_reportf_err(local_error, | ||
118 | "Failed to delete snapshot with id '%s' and " | ||
119 | @@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(BlkActionState *common) | ||
120 | sn->id_str, sn->name, | ||
121 | bdrv_get_device_name(bs)); | ||
122 | } | ||
123 | + | ||
124 | + aio_context_release(aio_context); | ||
125 | } | ||
126 | |||
127 | static void internal_snapshot_clean(BlkActionState *common) | ||
128 | { | ||
129 | InternalSnapshotState *state = DO_UPCAST(InternalSnapshotState, | ||
130 | common, common); | ||
131 | + AioContext *aio_context; | ||
132 | |||
133 | - if (state->aio_context) { | ||
134 | - if (state->bs) { | ||
135 | - bdrv_drained_end(state->bs); | ||
136 | - } | ||
137 | - aio_context_release(state->aio_context); | ||
138 | + if (!state->bs) { | ||
139 | + return; | ||
140 | } | ||
141 | + | ||
142 | + aio_context = bdrv_get_aio_context(state->bs); | ||
143 | + aio_context_acquire(aio_context); | ||
144 | + | ||
145 | + bdrv_drained_end(state->bs); | ||
146 | + | ||
147 | + aio_context_release(aio_context); | ||
148 | } | ||
149 | |||
150 | /* external snapshot private data */ | ||
39 | -- | 151 | -- |
40 | 2.24.1 | 152 | 2.14.3 |
41 | 153 | ||
42 | 154 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | The dirty bitmap actions in qmp_transaction have not used AioContext |
---|---|---|---|
2 | since the dirty bitmap locking discipline was introduced in commit | ||
3 | 2119882c7eb7e2c612b24fc0c8d86f5887d6f1c3 ("block: introduce | ||
4 | dirty_bitmap_mutex"). Remove the unused field. | ||
2 | 5 | ||
3 | This is a bit more efficient than having to allocate and free memory | 6 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
4 | for each new permission. | 7 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> |
8 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
9 | Message-id: 20171206144550.22295-7-stefanha@redhat.com | ||
10 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
11 | --- | ||
12 | blockdev.c | 13 ------------- | ||
13 | 1 file changed, 13 deletions(-) | ||
5 | 14 | ||
6 | The default size (30) is enough for "consistent read, write, resize". | 15 | diff --git a/blockdev.c b/blockdev.c |
7 | |||
8 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
9 | Message-id: 20200110171518.22168-1-berto@igalia.com | ||
10 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
11 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
12 | --- | ||
13 | block.c | 11 ++++++----- | ||
14 | 1 file changed, 6 insertions(+), 5 deletions(-) | ||
15 | |||
16 | diff --git a/block.c b/block.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/block.c | 17 | --- a/blockdev.c |
19 | +++ b/block.c | 18 | +++ b/blockdev.c |
20 | @@ -XXX,XX +XXX,XX @@ char *bdrv_perm_names(uint64_t perm) | 19 | @@ -XXX,XX +XXX,XX @@ typedef struct BlockDirtyBitmapState { |
21 | { 0, NULL } | 20 | BlkActionState common; |
22 | }; | 21 | BdrvDirtyBitmap *bitmap; |
23 | 22 | BlockDriverState *bs; | |
24 | - char *result = g_strdup(""); | 23 | - AioContext *aio_context; |
25 | + GString *result = g_string_sized_new(30); | 24 | HBitmap *backup; |
26 | struct perm_name *p; | 25 | bool prepared; |
27 | 26 | } BlockDirtyBitmapState; | |
28 | for (p = permissions; p->name; p++) { | 27 | @@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common, |
29 | if (perm & p->perm) { | ||
30 | - char *old = result; | ||
31 | - result = g_strdup_printf("%s%s%s", old, *old ? ", " : "", p->name); | ||
32 | - g_free(old); | ||
33 | + if (result->len > 0) { | ||
34 | + g_string_append(result, ", "); | ||
35 | + } | ||
36 | + g_string_append(result, p->name); | ||
37 | } | ||
38 | } | 28 | } |
39 | 29 | ||
40 | - return result; | 30 | bdrv_clear_dirty_bitmap(state->bitmap, &state->backup); |
41 | + return g_string_free(result, FALSE); | 31 | - /* AioContext is released in .clean() */ |
42 | } | 32 | } |
43 | 33 | ||
44 | /* | 34 | static void block_dirty_bitmap_clear_abort(BlkActionState *common) |
35 | @@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_commit(BlkActionState *common) | ||
36 | hbitmap_free(state->backup); | ||
37 | } | ||
38 | |||
39 | -static void block_dirty_bitmap_clear_clean(BlkActionState *common) | ||
40 | -{ | ||
41 | - BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState, | ||
42 | - common, common); | ||
43 | - | ||
44 | - if (state->aio_context) { | ||
45 | - aio_context_release(state->aio_context); | ||
46 | - } | ||
47 | -} | ||
48 | - | ||
49 | static void abort_prepare(BlkActionState *common, Error **errp) | ||
50 | { | ||
51 | error_setg(errp, "Transaction aborted using Abort action"); | ||
52 | @@ -XXX,XX +XXX,XX @@ static const BlkActionOps actions[] = { | ||
53 | .prepare = block_dirty_bitmap_clear_prepare, | ||
54 | .commit = block_dirty_bitmap_clear_commit, | ||
55 | .abort = block_dirty_bitmap_clear_abort, | ||
56 | - .clean = block_dirty_bitmap_clear_clean, | ||
57 | } | ||
58 | }; | ||
59 | |||
45 | -- | 60 | -- |
46 | 2.24.1 | 61 | 2.14.3 |
47 | 62 | ||
48 | 63 | diff view generated by jsdifflib |
1 | From: Thomas Huth <thuth@redhat.com> | 1 | Encapsulate IOThread QOM object lookup so that callers don't need to |
---|---|---|---|
2 | know how and where IOThread objects live. | ||
2 | 3 | ||
3 | We are going to enable some of the python-based tests in the "auto" group, | 4 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
4 | and these tests require virtio-blk to work properly. Running iotests | 5 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> |
5 | without virtio-blk likely does not make too much sense anyway, so instead | 6 | Reviewed-by: Eric Blake <eblake@redhat.com> |
6 | of adding a check for the availability of virtio-blk to each and every | 7 | Message-id: 20171206144550.22295-8-stefanha@redhat.com |
7 | test (which does not sound very appealing), let's rather add a check for | 8 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
8 | this a central spot in the "check" script instead (so that it is still | 9 | --- |
9 | possible to run "make check" for qemu-system-tricore for example). | 10 | include/sysemu/iothread.h | 1 + |
11 | iothread.c | 7 +++++++ | ||
12 | 2 files changed, 8 insertions(+) | ||
10 | 13 | ||
11 | Signed-off-by: Thomas Huth <thuth@redhat.com> | 14 | diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h |
12 | Message-id: 20200121095205.26323-6-thuth@redhat.com | 15 | index XXXXXXX..XXXXXXX 100644 |
13 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 16 | --- a/include/sysemu/iothread.h |
14 | --- | 17 | +++ b/include/sysemu/iothread.h |
15 | tests/qemu-iotests/check | 12 ++++++++++-- | 18 | @@ -XXX,XX +XXX,XX @@ typedef struct { |
16 | 1 file changed, 10 insertions(+), 2 deletions(-) | 19 | OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD) |
17 | 20 | ||
18 | diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check | 21 | char *iothread_get_id(IOThread *iothread); |
19 | index XXXXXXX..XXXXXXX 100755 | 22 | +IOThread *iothread_by_id(const char *id); |
20 | --- a/tests/qemu-iotests/check | 23 | AioContext *iothread_get_aio_context(IOThread *iothread); |
21 | +++ b/tests/qemu-iotests/check | 24 | void iothread_stop_all(void); |
22 | @@ -XXX,XX +XXX,XX @@ fi | 25 | GMainContext *iothread_get_g_main_context(IOThread *iothread); |
23 | python_usable=false | 26 | diff --git a/iothread.c b/iothread.c |
24 | if $PYTHON -c 'import sys; sys.exit(0 if sys.version_info >= (3,6) else 1)' | 27 | index XXXXXXX..XXXXXXX 100644 |
25 | then | 28 | --- a/iothread.c |
26 | - python_usable=true | 29 | +++ b/iothread.c |
27 | + # Our python framework also requires virtio-blk | 30 | @@ -XXX,XX +XXX,XX @@ void iothread_destroy(IOThread *iothread) |
28 | + if "$QEMU_PROG" -M none -device help | grep -q virtio-blk >/dev/null 2>&1 | 31 | { |
29 | + then | 32 | object_unparent(OBJECT(iothread)); |
30 | + python_usable=true | 33 | } |
31 | + else | 34 | + |
32 | + python_unusable_because="Missing virtio-blk in QEMU binary" | 35 | +/* Lookup IOThread by its id. Only finds user-created objects, not internal |
33 | + fi | 36 | + * iothread_create() objects. */ |
34 | +else | 37 | +IOThread *iothread_by_id(const char *id) |
35 | + python_unusable_because="Unsupported Python version" | 38 | +{ |
36 | fi | 39 | + return IOTHREAD(object_resolve_path_type(id, TYPE_IOTHREAD, NULL)); |
37 | 40 | +} | |
38 | default_machine=$($QEMU_PROG -machine help | sed -n '/(default)/ s/ .*//p') | ||
39 | @@ -XXX,XX +XXX,XX @@ do | ||
40 | run_command="$PYTHON $seq" | ||
41 | else | ||
42 | run_command="false" | ||
43 | - echo "Unsupported Python version" > $seq.notrun | ||
44 | + echo "$python_unusable_because" > $seq.notrun | ||
45 | fi | ||
46 | else | ||
47 | run_command="./$seq" | ||
48 | -- | 41 | -- |
49 | 2.24.1 | 42 | 2.14.3 |
50 | 43 | ||
51 | 44 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | Currently there is no easy way for iotests to ensure that a BDS is bound |
---|---|---|---|
2 | to a particular IOThread. Normally the virtio-blk device calls | ||
3 | blk_set_aio_context() when dataplane is enabled during guest driver | ||
4 | initialization. This never happens in iotests since -machine | ||
5 | accel=qtest means there is no guest activity (including device driver | ||
6 | initialization). | ||
2 | 7 | ||
3 | When updating an L1 entry the qcow2 driver writes a (512-byte) sector | 8 | This patch adds a QMP command to explicitly assign IOThreads in test |
4 | worth of data to avoid a read-modify-write cycle. Instead of always | 9 | cases. See qapi/block-core.json for a description of the command. |
5 | writing 512 bytes we should follow the alignment requirements of the | ||
6 | storage backend. | ||
7 | 10 | ||
8 | (the only exception is when the alignment is larger than the cluster | 11 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
9 | size because then we could be overwriting data after the L1 table) | 12 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> |
13 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
14 | Message-id: 20171206144550.22295-9-stefanha@redhat.com | ||
15 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
16 | --- | ||
17 | qapi/block-core.json | 36 ++++++++++++++++++++++++++++++++++++ | ||
18 | blockdev.c | 41 +++++++++++++++++++++++++++++++++++++++++ | ||
19 | 2 files changed, 77 insertions(+) | ||
10 | 20 | ||
11 | Signed-off-by: Alberto Garcia <berto@igalia.com> | 21 | diff --git a/qapi/block-core.json b/qapi/block-core.json |
12 | Message-id: 71f34d4ae4b367b32fb36134acbf4f4f7ee681f4.1579374329.git.berto@igalia.com | ||
13 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
14 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
15 | --- | ||
16 | block/qcow2-cluster.c | 25 +++++++++++++++---------- | ||
17 | 1 file changed, 15 insertions(+), 10 deletions(-) | ||
18 | |||
19 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/block/qcow2-cluster.c | 23 | --- a/qapi/block-core.json |
22 | +++ b/block/qcow2-cluster.c | 24 | +++ b/qapi/block-core.json |
23 | @@ -XXX,XX +XXX,XX @@ static int l2_load(BlockDriverState *bs, uint64_t offset, | 25 | @@ -XXX,XX +XXX,XX @@ |
26 | 'data' : { 'parent': 'str', | ||
27 | '*child': 'str', | ||
28 | '*node': 'str' } } | ||
29 | + | ||
30 | +## | ||
31 | +# @x-blockdev-set-iothread: | ||
32 | +# | ||
33 | +# Move @node and its children into the @iothread. If @iothread is null then | ||
34 | +# move @node and its children into the main loop. | ||
35 | +# | ||
36 | +# The node must not be attached to a BlockBackend. | ||
37 | +# | ||
38 | +# @node-name: the name of the block driver node | ||
39 | +# | ||
40 | +# @iothread: the name of the IOThread object or null for the main loop | ||
41 | +# | ||
42 | +# Note: this command is experimental and intended for test cases that need | ||
43 | +# control over IOThreads only. | ||
44 | +# | ||
45 | +# Since: 2.12 | ||
46 | +# | ||
47 | +# Example: | ||
48 | +# | ||
49 | +# 1. Move a node into an IOThread | ||
50 | +# -> { "execute": "x-blockdev-set-iothread", | ||
51 | +# "arguments": { "node-name": "disk1", | ||
52 | +# "iothread": "iothread0" } } | ||
53 | +# <- { "return": {} } | ||
54 | +# | ||
55 | +# 2. Move a node into the main loop | ||
56 | +# -> { "execute": "x-blockdev-set-iothread", | ||
57 | +# "arguments": { "node-name": "disk1", | ||
58 | +# "iothread": null } } | ||
59 | +# <- { "return": {} } | ||
60 | +# | ||
61 | +## | ||
62 | +{ 'command': 'x-blockdev-set-iothread', | ||
63 | + 'data' : { 'node-name': 'str', | ||
64 | + 'iothread': 'StrOrNull' } } | ||
65 | diff --git a/blockdev.c b/blockdev.c | ||
66 | index XXXXXXX..XXXXXXX 100644 | ||
67 | --- a/blockdev.c | ||
68 | +++ b/blockdev.c | ||
69 | @@ -XXX,XX +XXX,XX @@ | ||
70 | #include "qapi/qmp/qerror.h" | ||
71 | #include "qapi/qobject-output-visitor.h" | ||
72 | #include "sysemu/sysemu.h" | ||
73 | +#include "sysemu/iothread.h" | ||
74 | #include "block/block_int.h" | ||
75 | #include "qmp-commands.h" | ||
76 | #include "block/trace.h" | ||
77 | @@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp) | ||
78 | return head; | ||
24 | } | 79 | } |
25 | 80 | ||
26 | /* | 81 | +void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread, |
27 | - * Writes one sector of the L1 table to the disk (can't update single entries | 82 | + Error **errp) |
28 | - * and we really don't want bdrv_pread to perform a read-modify-write) | 83 | +{ |
29 | + * Writes an L1 entry to disk (note that depending on the alignment | 84 | + AioContext *old_context; |
30 | + * requirements this function may write more that just one entry in | 85 | + AioContext *new_context; |
31 | + * order to prevent bdrv_pwrite from performing a read-modify-write) | 86 | + BlockDriverState *bs; |
32 | */ | 87 | + |
33 | -#define L1_ENTRIES_PER_SECTOR (512 / 8) | 88 | + bs = bdrv_find_node(node_name); |
34 | int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) | 89 | + if (!bs) { |
35 | { | 90 | + error_setg(errp, "Cannot find node %s", node_name); |
36 | BDRVQcow2State *s = bs->opaque; | 91 | + return; |
37 | - uint64_t buf[L1_ENTRIES_PER_SECTOR] = { 0 }; | ||
38 | int l1_start_index; | ||
39 | int i, ret; | ||
40 | + int bufsize = MAX(sizeof(uint64_t), | ||
41 | + MIN(bs->file->bs->bl.request_alignment, s->cluster_size)); | ||
42 | + int nentries = bufsize / sizeof(uint64_t); | ||
43 | + g_autofree uint64_t *buf = g_try_new0(uint64_t, nentries); | ||
44 | |||
45 | - l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1); | ||
46 | - for (i = 0; i < L1_ENTRIES_PER_SECTOR && l1_start_index + i < s->l1_size; | ||
47 | - i++) | ||
48 | - { | ||
49 | + if (buf == NULL) { | ||
50 | + return -ENOMEM; | ||
51 | + } | 92 | + } |
52 | + | 93 | + |
53 | + l1_start_index = QEMU_ALIGN_DOWN(l1_index, nentries); | 94 | + /* If we want to allow more extreme test scenarios this guard could be |
54 | + for (i = 0; i < MIN(nentries, s->l1_size - l1_start_index); i++) { | 95 | + * removed. For now it protects against accidents. */ |
55 | buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); | 96 | + if (bdrv_has_blk(bs)) { |
56 | } | 97 | + error_setg(errp, "Node %s is in use", node_name); |
57 | 98 | + return; | |
58 | ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1, | 99 | + } |
59 | - s->l1_table_offset + 8 * l1_start_index, sizeof(buf), false); | 100 | + |
60 | + s->l1_table_offset + 8 * l1_start_index, bufsize, false); | 101 | + if (iothread->type == QTYPE_QSTRING) { |
61 | if (ret < 0) { | 102 | + IOThread *obj = iothread_by_id(iothread->u.s); |
62 | return ret; | 103 | + if (!obj) { |
63 | } | 104 | + error_setg(errp, "Cannot find iothread %s", iothread->u.s); |
64 | @@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) | 105 | + return; |
65 | BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); | 106 | + } |
66 | ret = bdrv_pwrite_sync(bs->file, | 107 | + |
67 | s->l1_table_offset + 8 * l1_start_index, | 108 | + new_context = iothread_get_aio_context(obj); |
68 | - buf, sizeof(buf)); | 109 | + } else { |
69 | + buf, bufsize); | 110 | + new_context = qemu_get_aio_context(); |
70 | if (ret < 0) { | 111 | + } |
71 | return ret; | 112 | + |
72 | } | 113 | + old_context = bdrv_get_aio_context(bs); |
114 | + aio_context_acquire(old_context); | ||
115 | + | ||
116 | + bdrv_set_aio_context(bs, new_context); | ||
117 | + | ||
118 | + aio_context_release(old_context); | ||
119 | +} | ||
120 | + | ||
121 | QemuOptsList qemu_common_drive_opts = { | ||
122 | .name = "drive", | ||
123 | .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head), | ||
73 | -- | 124 | -- |
74 | 2.24.1 | 125 | 2.14.3 |
75 | 126 | ||
76 | 127 | diff view generated by jsdifflib |
1 | From: Thomas Huth <thuth@redhat.com> | 1 | QMP 'transaction' blockdev-snapshot-sync with multiple disks in an |
---|---|---|---|
2 | IOThread is an untested code path. Several bugs have been found in | ||
3 | connection with this command. This patch adds a test case to prevent | ||
4 | future regressions. | ||
2 | 5 | ||
3 | According to Kevin, tests 030, 040 and 041 are among the most valuable | 6 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
4 | tests that we have, so we should always run them if possible, even if | 7 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> |
5 | they take a little bit longer. | 8 | Reviewed-by: Eric Blake <eblake@redhat.com> |
9 | Message-id: 20171206144550.22295-10-stefanha@redhat.com | ||
10 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
11 | --- | ||
12 | tests/qemu-iotests/202 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
13 | tests/qemu-iotests/202.out | 11 ++++++ | ||
14 | tests/qemu-iotests/group | 1 + | ||
15 | 3 files changed, 107 insertions(+) | ||
16 | create mode 100755 tests/qemu-iotests/202 | ||
17 | create mode 100644 tests/qemu-iotests/202.out | ||
6 | 18 | ||
7 | According to Max, it would be good to have a test for iothreads and | 19 | diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202 |
8 | migration. 127 and 256 seem to be good candidates for iothreads. For | 20 | new file mode 100755 |
9 | migration, let's enable 181 and 203 (which also tests iothreads). | 21 | index XXXXXXX..XXXXXXX |
10 | (091 would be a good candidate for migration, too, but Alex Bennée | 22 | --- /dev/null |
11 | reported that this test fails on ZFS file systems, so it can't be | 23 | +++ b/tests/qemu-iotests/202 |
12 | included yet) | 24 | @@ -XXX,XX +XXX,XX @@ |
13 | 25 | +#!/usr/bin/env python | |
14 | Reviewed-by: Max Reitz <mreitz@redhat.com> | 26 | +# |
15 | Signed-off-by: Thomas Huth <thuth@redhat.com> | 27 | +# Copyright (C) 2017 Red Hat, Inc. |
16 | Message-id: 20200121095205.26323-7-thuth@redhat.com | 28 | +# |
17 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 29 | +# This program is free software; you can redistribute it and/or modify |
18 | --- | 30 | +# it under the terms of the GNU General Public License as published by |
19 | tests/qemu-iotests/group | 14 +++++++------- | 31 | +# the Free Software Foundation; either version 2 of the License, or |
20 | 1 file changed, 7 insertions(+), 7 deletions(-) | 32 | +# (at your option) any later version. |
21 | 33 | +# | |
34 | +# This program is distributed in the hope that it will be useful, | ||
35 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
36 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
37 | +# GNU General Public License for more details. | ||
38 | +# | ||
39 | +# You should have received a copy of the GNU General Public License | ||
40 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
41 | +# | ||
42 | +# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com> | ||
43 | +# | ||
44 | +# Check that QMP 'transaction' blockdev-snapshot-sync with multiple drives on a | ||
45 | +# single IOThread completes successfully. This particular command triggered a | ||
46 | +# hang due to recursive AioContext locking and BDRV_POLL_WHILE(). Protect | ||
47 | +# against regressions. | ||
48 | + | ||
49 | +import iotests | ||
50 | + | ||
51 | +iotests.verify_image_format(supported_fmts=['qcow2']) | ||
52 | +iotests.verify_platform(['linux']) | ||
53 | + | ||
54 | +with iotests.FilePath('disk0.img') as disk0_img_path, \ | ||
55 | + iotests.FilePath('disk1.img') as disk1_img_path, \ | ||
56 | + iotests.FilePath('disk0-snap.img') as disk0_snap_img_path, \ | ||
57 | + iotests.FilePath('disk1-snap.img') as disk1_snap_img_path, \ | ||
58 | + iotests.VM() as vm: | ||
59 | + | ||
60 | + img_size = '10M' | ||
61 | + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk0_img_path, img_size) | ||
62 | + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk1_img_path, img_size) | ||
63 | + | ||
64 | + iotests.log('Launching VM...') | ||
65 | + vm.launch() | ||
66 | + | ||
67 | + iotests.log('Adding IOThread...') | ||
68 | + iotests.log(vm.qmp('object-add', | ||
69 | + qom_type='iothread', | ||
70 | + id='iothread0')) | ||
71 | + | ||
72 | + iotests.log('Adding blockdevs...') | ||
73 | + iotests.log(vm.qmp('blockdev-add', | ||
74 | + driver=iotests.imgfmt, | ||
75 | + node_name='disk0', | ||
76 | + file={ | ||
77 | + 'driver': 'file', | ||
78 | + 'filename': disk0_img_path, | ||
79 | + })) | ||
80 | + iotests.log(vm.qmp('blockdev-add', | ||
81 | + driver=iotests.imgfmt, | ||
82 | + node_name='disk1', | ||
83 | + file={ | ||
84 | + 'driver': 'file', | ||
85 | + 'filename': disk1_img_path, | ||
86 | + })) | ||
87 | + | ||
88 | + iotests.log('Setting iothread...') | ||
89 | + iotests.log(vm.qmp('x-blockdev-set-iothread', | ||
90 | + node_name='disk0', | ||
91 | + iothread='iothread0')) | ||
92 | + iotests.log(vm.qmp('x-blockdev-set-iothread', | ||
93 | + node_name='disk1', | ||
94 | + iothread='iothread0')) | ||
95 | + | ||
96 | + iotests.log('Creating external snapshots...') | ||
97 | + iotests.log(vm.qmp( | ||
98 | + 'transaction', | ||
99 | + actions=[ | ||
100 | + { | ||
101 | + 'data': { | ||
102 | + 'node-name': 'disk0', | ||
103 | + 'snapshot-file': disk0_snap_img_path, | ||
104 | + 'snapshot-node-name': 'disk0-snap', | ||
105 | + 'mode': 'absolute-paths', | ||
106 | + 'format': iotests.imgfmt, | ||
107 | + }, | ||
108 | + 'type': 'blockdev-snapshot-sync' | ||
109 | + }, { | ||
110 | + 'data': { | ||
111 | + 'node-name': 'disk1', | ||
112 | + 'snapshot-file': disk1_snap_img_path, | ||
113 | + 'snapshot-node-name': 'disk1-snap', | ||
114 | + 'mode': 'absolute-paths', | ||
115 | + 'format': iotests.imgfmt | ||
116 | + }, | ||
117 | + 'type': 'blockdev-snapshot-sync' | ||
118 | + } | ||
119 | + ])) | ||
120 | diff --git a/tests/qemu-iotests/202.out b/tests/qemu-iotests/202.out | ||
121 | new file mode 100644 | ||
122 | index XXXXXXX..XXXXXXX | ||
123 | --- /dev/null | ||
124 | +++ b/tests/qemu-iotests/202.out | ||
125 | @@ -XXX,XX +XXX,XX @@ | ||
126 | +Launching VM... | ||
127 | +Adding IOThread... | ||
128 | +{u'return': {}} | ||
129 | +Adding blockdevs... | ||
130 | +{u'return': {}} | ||
131 | +{u'return': {}} | ||
132 | +Setting iothread... | ||
133 | +{u'return': {}} | ||
134 | +{u'return': {}} | ||
135 | +Creating external snapshots... | ||
136 | +{u'return': {}} | ||
22 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | 137 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group |
23 | index XXXXXXX..XXXXXXX 100644 | 138 | index XXXXXXX..XXXXXXX 100644 |
24 | --- a/tests/qemu-iotests/group | 139 | --- a/tests/qemu-iotests/group |
25 | +++ b/tests/qemu-iotests/group | 140 | +++ b/tests/qemu-iotests/group |
26 | @@ -XXX,XX +XXX,XX @@ | 141 | @@ -XXX,XX +XXX,XX @@ |
27 | 027 rw auto quick | 142 | 197 rw auto quick |
28 | 028 rw backing quick | 143 | 198 rw auto |
29 | 029 rw auto quick | 144 | 200 rw auto |
30 | -030 rw backing | 145 | +202 rw auto quick |
31 | +030 rw auto backing | ||
32 | 031 rw auto quick | ||
33 | 032 rw auto quick | ||
34 | 033 rw auto quick | ||
35 | @@ -XXX,XX +XXX,XX @@ | ||
36 | 037 rw auto backing quick | ||
37 | 038 rw auto backing quick | ||
38 | 039 rw auto quick | ||
39 | -040 rw | ||
40 | -041 rw backing | ||
41 | +040 rw auto | ||
42 | +041 rw auto backing | ||
43 | 042 rw auto quick | ||
44 | 043 rw auto backing | ||
45 | 044 rw | ||
46 | @@ -XXX,XX +XXX,XX @@ | ||
47 | 124 rw backing | ||
48 | 125 rw | ||
49 | 126 rw auto backing | ||
50 | -127 rw backing quick | ||
51 | +127 rw auto backing quick | ||
52 | 128 rw quick | ||
53 | 129 rw quick | ||
54 | 130 rw quick | ||
55 | @@ -XXX,XX +XXX,XX @@ | ||
56 | 177 rw auto quick | ||
57 | 178 img | ||
58 | 179 rw auto quick | ||
59 | -181 rw migration | ||
60 | +181 rw auto migration | ||
61 | 182 rw quick | ||
62 | 183 rw migration | ||
63 | 184 rw auto quick | ||
64 | @@ -XXX,XX +XXX,XX @@ | ||
65 | 200 rw | ||
66 | 201 rw migration | ||
67 | 202 rw quick | ||
68 | -203 rw migration | ||
69 | +203 rw auto migration | ||
70 | 204 rw quick | ||
71 | 205 rw quick | ||
72 | 206 rw | ||
73 | @@ -XXX,XX +XXX,XX @@ | ||
74 | 253 rw quick | ||
75 | 254 rw backing quick | ||
76 | 255 rw quick | ||
77 | -256 rw quick | ||
78 | +256 rw auto quick | ||
79 | 257 rw | ||
80 | 258 rw quick | ||
81 | 260 rw quick | ||
82 | -- | 146 | -- |
83 | 2.24.1 | 147 | 2.14.3 |
84 | 148 | ||
85 | 149 | diff view generated by jsdifflib |
1 | From: Thomas Huth <thuth@redhat.com> | 1 | From: Mark Kanda <mark.kanda@oracle.com> |
---|---|---|---|
2 | 2 | ||
3 | 041 works fine on Linux, FreeBSD, NetBSD and OpenBSD, but fails on macOS. | 3 | Depending on the configuration, it can be beneficial to adjust the virtio-blk |
4 | Let's mark it as only supported on the systems where we know that it is | 4 | queue size to something other than the current default of 128. Add a new |
5 | working fine. | 5 | property to make the queue size configurable. |
6 | 6 | ||
7 | Reviewed-by: Max Reitz <mreitz@redhat.com> | 7 | Signed-off-by: Mark Kanda <mark.kanda@oracle.com> |
8 | Signed-off-by: Thomas Huth <thuth@redhat.com> | 8 | Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> |
9 | Message-id: 20200121095205.26323-3-thuth@redhat.com | 9 | Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> |
10 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 10 | Reviewed-by: Ameya More <ameya.more@oracle.com> |
11 | Message-id: 52e6d742811f10dbd16e996e86cf375b9577c187.1513005190.git.mark.kanda@oracle.com | ||
12 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
11 | --- | 13 | --- |
12 | tests/qemu-iotests/041 | 3 ++- | 14 | include/hw/virtio/virtio-blk.h | 1 + |
13 | 1 file changed, 2 insertions(+), 1 deletion(-) | 15 | hw/block/virtio-blk.c | 10 +++++++++- |
16 | 2 files changed, 10 insertions(+), 1 deletion(-) | ||
14 | 17 | ||
15 | diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 | 18 | diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h |
16 | index XXXXXXX..XXXXXXX 100755 | 19 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/tests/qemu-iotests/041 | 20 | --- a/include/hw/virtio/virtio-blk.h |
18 | +++ b/tests/qemu-iotests/041 | 21 | +++ b/include/hw/virtio/virtio-blk.h |
19 | @@ -XXX,XX +XXX,XX @@ class TestOrphanedSource(iotests.QMPTestCase): | 22 | @@ -XXX,XX +XXX,XX @@ struct VirtIOBlkConf |
20 | 23 | uint32_t config_wce; | |
21 | if __name__ == '__main__': | 24 | uint32_t request_merging; |
22 | iotests.main(supported_fmts=['qcow2', 'qed'], | 25 | uint16_t num_queues; |
23 | - supported_protocols=['file']) | 26 | + uint16_t queue_size; |
24 | + supported_protocols=['file'], | 27 | }; |
25 | + supported_platforms=['linux', 'freebsd', 'netbsd', 'openbsd']) | 28 | |
29 | struct VirtIOBlockDataPlane; | ||
30 | diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c | ||
31 | index XXXXXXX..XXXXXXX 100644 | ||
32 | --- a/hw/block/virtio-blk.c | ||
33 | +++ b/hw/block/virtio-blk.c | ||
34 | @@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) | ||
35 | error_setg(errp, "num-queues property must be larger than 0"); | ||
36 | return; | ||
37 | } | ||
38 | + if (!is_power_of_2(conf->queue_size) || | ||
39 | + conf->queue_size > VIRTQUEUE_MAX_SIZE) { | ||
40 | + error_setg(errp, "invalid queue-size property (%" PRIu16 "), " | ||
41 | + "must be a power of 2 (max %d)", | ||
42 | + conf->queue_size, VIRTQUEUE_MAX_SIZE); | ||
43 | + return; | ||
44 | + } | ||
45 | |||
46 | blkconf_serial(&conf->conf, &conf->serial); | ||
47 | if (!blkconf_apply_backend_options(&conf->conf, | ||
48 | @@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) | ||
49 | s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1; | ||
50 | |||
51 | for (i = 0; i < conf->num_queues; i++) { | ||
52 | - virtio_add_queue(vdev, 128, virtio_blk_handle_output); | ||
53 | + virtio_add_queue(vdev, conf->queue_size, virtio_blk_handle_output); | ||
54 | } | ||
55 | virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err); | ||
56 | if (err != NULL) { | ||
57 | @@ -XXX,XX +XXX,XX @@ static Property virtio_blk_properties[] = { | ||
58 | DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0, | ||
59 | true), | ||
60 | DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1), | ||
61 | + DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128), | ||
62 | DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD, | ||
63 | IOThread *), | ||
64 | DEFINE_PROP_END_OF_LIST(), | ||
26 | -- | 65 | -- |
27 | 2.24.1 | 66 | 2.14.3 |
28 | 67 | ||
29 | 68 | diff view generated by jsdifflib |
1 | From: Thomas Huth <thuth@redhat.com> | 1 | From: Mark Kanda <mark.kanda@oracle.com> |
---|---|---|---|
2 | 2 | ||
3 | In the long run, we might want to add test 183 to the "auto" group | 3 | virtio-blk logical block size should never be larger than physical block |
4 | (but it still fails occasionally, so we cannot do that yet). However, | 4 | size because it doesn't make sense to have such configurations. QEMU doesn't |
5 | when running 183 in Cirrus-CI on macOS, or with our vm-build-openbsd | 5 | have a way to effectively express this condition; the best it can do is |
6 | target, it currently always fails with an "Timeout waiting for return | 6 | report the physical block exponent as 0 - indicating the logical block size |
7 | on handle 0" error. | 7 | equals the physical block size. |
8 | 8 | ||
9 | Let's mark it as supported only on systems where the test is working | 9 | This is identical to commit 3da023b5827543ee4c022986ea2ad9d1274410b2 |
10 | most of the time (i.e. Linux, FreeBSD and NetBSD). | 10 | but applied to virtio-blk (instead of virtio-scsi). |
11 | 11 | ||
12 | Reviewed-by: Max Reitz <mreitz@redhat.com> | 12 | Signed-off-by: Mark Kanda <mark.kanda@oracle.com> |
13 | Signed-off-by: Thomas Huth <thuth@redhat.com> | 13 | Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
14 | Message-id: 20200121095205.26323-4-thuth@redhat.com | 14 | Reviewed-by: Ameya More <ameya.more@oracle.com> |
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 15 | Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> |
16 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
17 | Message-id: 773169891f9f2deb4cb7c4ef2655580dbe24c1d1.1513005190.git.mark.kanda@oracle.com | ||
18 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
16 | --- | 19 | --- |
17 | tests/qemu-iotests/183 | 1 + | 20 | hw/block/virtio-blk.c | 7 +++++++ |
18 | 1 file changed, 1 insertion(+) | 21 | 1 file changed, 7 insertions(+) |
19 | 22 | ||
20 | diff --git a/tests/qemu-iotests/183 b/tests/qemu-iotests/183 | 23 | diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c |
21 | index XXXXXXX..XXXXXXX 100755 | 24 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/tests/qemu-iotests/183 | 25 | --- a/hw/block/virtio-blk.c |
23 | +++ b/tests/qemu-iotests/183 | 26 | +++ b/hw/block/virtio-blk.c |
24 | @@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15 | 27 | @@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) |
25 | . ./common.filter | 28 | |
26 | . ./common.qemu | 29 | blkconf_blocksizes(&conf->conf); |
27 | 30 | ||
28 | +_supported_os Linux FreeBSD NetBSD | 31 | + if (conf->conf.logical_block_size > |
29 | _supported_fmt qcow2 raw qed quorum | 32 | + conf->conf.physical_block_size) { |
30 | _supported_proto file | 33 | + error_setg(errp, |
34 | + "logical_block_size > physical_block_size not supported"); | ||
35 | + return; | ||
36 | + } | ||
37 | + | ||
38 | virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, | ||
39 | sizeof(struct virtio_blk_config)); | ||
31 | 40 | ||
32 | -- | 41 | -- |
33 | 2.24.1 | 42 | 2.14.3 |
34 | 43 | ||
35 | 44 | diff view generated by jsdifflib |
1 | From: Pan Nengyuan <pannengyuan@huawei.com> | 1 | From: Paolo Bonzini <pbonzini@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | If we call the qmp 'query-block' while qemu is working on | 3 | BDRV_POLL_WHILE() does not support recursive AioContext locking. It |
4 | 'block-commit', it will cause memleaks, the memory leak stack is as | 4 | only releases the AioContext lock once regardless of how many times the |
5 | follow: | 5 | caller has acquired it. This results in a hang since the IOThread does |
6 | not make progress while the AioContext is still locked. | ||
6 | 7 | ||
7 | Indirect leak of 12360 byte(s) in 3 object(s) allocated from: | 8 | The following steps trigger the hang: |
8 | #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) | ||
9 | #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) | ||
10 | #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu-4.2.0-rc0/qobject/qdict.c:29 | ||
11 | #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6427 | ||
12 | #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
13 | #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
14 | #6 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | ||
15 | #7 0x55ea958818ea in bdrv_block_device_info /mnt/sdb/qemu-4.2.0-rc0/block/qapi.c:56 | ||
16 | #8 0x55ea958879de in bdrv_query_info /mnt/sdb/qemu-4.2.0-rc0/block/qapi.c:392 | ||
17 | #9 0x55ea9588b58f in qmp_query_block /mnt/sdb/qemu-4.2.0-rc0/block/qapi.c:578 | ||
18 | #10 0x55ea95567392 in qmp_marshal_query_block qapi/qapi-commands-block-core.c:95 | ||
19 | 9 | ||
20 | Indirect leak of 4120 byte(s) in 1 object(s) allocated from: | 10 | $ qemu-system-x86_64 -M accel=kvm -m 1G -cpu host \ |
21 | #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) | 11 | -object iothread,id=iothread0 \ |
22 | #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) | 12 | -device virtio-scsi-pci,iothread=iothread0 \ |
23 | #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu-4.2.0-rc0/qobject/qdict.c:29 | 13 | -drive if=none,id=drive0,file=test.img,format=raw \ |
24 | #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6427 | 14 | -device scsi-hd,drive=drive0 \ |
25 | #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | 15 | -drive if=none,id=drive1,file=test.img,format=raw \ |
26 | #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu-4.2.0-rc0/block.c:6399 | 16 | -device scsi-hd,drive=drive1 |
27 | #6 0x55ea9569f301 in bdrv_backing_attach /mnt/sdb/qemu-4.2.0-rc0/block.c:1064 | 17 | $ qemu-system-x86_64 ...same options... \ |
28 | #7 0x55ea956a99dd in bdrv_replace_child_noperm /mnt/sdb/qemu-4.2.0-rc0/block.c:2283 | 18 | -incoming tcp::1234 |
29 | #8 0x55ea956b9b53 in bdrv_replace_node /mnt/sdb/qemu-4.2.0-rc0/block.c:4196 | 19 | (qemu) migrate tcp:127.0.0.1:1234 |
30 | #9 0x55ea956b9e49 in bdrv_append /mnt/sdb/qemu-4.2.0-rc0/block.c:4236 | 20 | ...hang... |
31 | #10 0x55ea958c3472 in commit_start /mnt/sdb/qemu-4.2.0-rc0/block/commit.c:306 | ||
32 | #11 0x55ea94b68ab0 in qmp_block_commit /mnt/sdb/qemu-4.2.0-rc0/blockdev.c:3459 | ||
33 | #12 0x55ea9556a7a7 in qmp_marshal_block_commit qapi/qapi-commands-block-core.c:407 | ||
34 | 21 | ||
35 | Fixes: bb808d5f5c0978828a974d547e6032402c339555 | 22 | Tested-by: Stefan Hajnoczi <stefanha@redhat.com> |
36 | Reported-by: Euler Robot <euler.robot@huawei.com> | 23 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
37 | Signed-off-by: Pan Nengyuan <pannengyuan@huawei.com> | 24 | Reviewed-by: Eric Blake <eblake@redhat.com> |
38 | Message-id: 20200116085600.24056-1-pannengyuan@huawei.com | 25 | Message-id: 20171207201320.19284-2-stefanha@redhat.com |
39 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 26 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
40 | --- | 27 | --- |
41 | block.c | 1 + | 28 | block.c | 14 +++++++++++--- |
42 | 1 file changed, 1 insertion(+) | 29 | 1 file changed, 11 insertions(+), 3 deletions(-) |
43 | 30 | ||
44 | diff --git a/block.c b/block.c | 31 | diff --git a/block.c b/block.c |
45 | index XXXXXXX..XXXXXXX 100644 | 32 | index XXXXXXX..XXXXXXX 100644 |
46 | --- a/block.c | 33 | --- a/block.c |
47 | +++ b/block.c | 34 | +++ b/block.c |
48 | @@ -XXX,XX +XXX,XX @@ void bdrv_refresh_filename(BlockDriverState *bs) | 35 | @@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void) |
49 | child->bs->exact_filename); | 36 | BdrvNextIterator it; |
50 | pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename); | 37 | int ret = 0; |
51 | 38 | int pass; | |
52 | + qobject_unref(bs->full_open_options); | 39 | + GSList *aio_ctxs = NULL, *ctx; |
53 | bs->full_open_options = qobject_ref(child->bs->full_open_options); | 40 | |
54 | 41 | for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { | |
55 | return; | 42 | - aio_context_acquire(bdrv_get_aio_context(bs)); |
43 | + AioContext *aio_context = bdrv_get_aio_context(bs); | ||
44 | + | ||
45 | + if (!g_slist_find(aio_ctxs, aio_context)) { | ||
46 | + aio_ctxs = g_slist_prepend(aio_ctxs, aio_context); | ||
47 | + aio_context_acquire(aio_context); | ||
48 | + } | ||
49 | } | ||
50 | |||
51 | /* We do two passes of inactivation. The first pass calls to drivers' | ||
52 | @@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void) | ||
53 | } | ||
54 | |||
55 | out: | ||
56 | - for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) { | ||
57 | - aio_context_release(bdrv_get_aio_context(bs)); | ||
58 | + for (ctx = aio_ctxs; ctx != NULL; ctx = ctx->next) { | ||
59 | + AioContext *aio_context = ctx->data; | ||
60 | + aio_context_release(aio_context); | ||
61 | } | ||
62 | + g_slist_free(aio_ctxs); | ||
63 | |||
64 | return ret; | ||
65 | } | ||
56 | -- | 66 | -- |
57 | 2.24.1 | 67 | 2.14.3 |
58 | 68 | ||
59 | 69 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | See the patch for why nested AioContext locking is no longer allowed. |
---|---|---|---|
2 | 2 | ||
3 | The standard cluster descriptor in L2 table entries has a field to | 3 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
4 | store the host cluster offset. When we need to get that offset from an | 4 | Reviewed-by: Eric Blake <eblake@redhat.com> |
5 | entry we use L2E_OFFSET_MASK to ensure that we only use the bits that | 5 | Message-id: 20171207201320.19284-3-stefanha@redhat.com |
6 | belong to that field. | 6 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
7 | --- | ||
8 | docs/devel/multiple-iothreads.txt | 7 ++++--- | ||
9 | 1 file changed, 4 insertions(+), 3 deletions(-) | ||
7 | 10 | ||
8 | But while that mask is used every time we read from an L2 entry, it | 11 | diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt |
9 | is never used when we write to it. Due to the QCOW_MAX_CLUSTER_OFFSET | ||
10 | limit set in the cluster allocation code QEMU can never produce | ||
11 | offsets that don't fit in that field so any such offset would indicate | ||
12 | a bug in QEMU. | ||
13 | |||
14 | Compressed cluster descriptors contain two fields (host cluster offset | ||
15 | and size of the compressed data) and the situation with them is | ||
16 | similar. In this case the masks are not constant but are stored in the | ||
17 | csize_mask and cluster_offset_mask fields of BDRVQcow2State. | ||
18 | |||
19 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
20 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
21 | Message-id: 20200113161146.20099-1-berto@igalia.com | ||
22 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
23 | --- | ||
24 | block/qcow2-cluster.c | 14 ++++++++++++-- | ||
25 | 1 file changed, 12 insertions(+), 2 deletions(-) | ||
26 | |||
27 | diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
29 | --- a/block/qcow2-cluster.c | 13 | --- a/docs/devel/multiple-iothreads.txt |
30 | +++ b/block/qcow2-cluster.c | 14 | +++ b/docs/devel/multiple-iothreads.txt |
31 | @@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, | 15 | @@ -XXX,XX +XXX,XX @@ |
32 | (cluster_offset + compressed_size - 1) / QCOW2_COMPRESSED_SECTOR_SIZE - | 16 | -Copyright (c) 2014 Red Hat Inc. |
33 | (cluster_offset / QCOW2_COMPRESSED_SECTOR_SIZE); | 17 | +Copyright (c) 2014-2017 Red Hat Inc. |
34 | 18 | ||
35 | + /* The offset and size must fit in their fields of the L2 table entry */ | 19 | This work is licensed under the terms of the GNU GPL, version 2 or later. See |
36 | + assert((cluster_offset & s->cluster_offset_mask) == cluster_offset); | 20 | the COPYING file in the top-level directory. |
37 | + assert((nb_csectors & s->csize_mask) == nb_csectors); | 21 | @@ -XXX,XX +XXX,XX @@ aio_context_acquire()/aio_context_release() for mutual exclusion. Once the |
38 | + | 22 | context is acquired no other thread can access it or run event loop iterations |
39 | cluster_offset |= QCOW_OFLAG_COMPRESSED | | 23 | in this AioContext. |
40 | ((uint64_t)nb_csectors << s->csize_shift); | 24 | |
41 | 25 | -aio_context_acquire()/aio_context_release() calls may be nested. This | |
42 | @@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) | 26 | -means you can call them if you're not sure whether #2 applies. |
43 | 27 | +Legacy code sometimes nests aio_context_acquire()/aio_context_release() calls. | |
44 | assert(l2_index + m->nb_clusters <= s->l2_slice_size); | 28 | +Do not use nesting anymore, it is incompatible with the BDRV_POLL_WHILE() macro |
45 | for (i = 0; i < m->nb_clusters; i++) { | 29 | +used in the block layer and can lead to hangs. |
46 | + uint64_t offset = cluster_offset + (i << s->cluster_bits); | 30 | |
47 | /* if two concurrent writes happen to the same unallocated cluster | 31 | There is currently no lock ordering rule if a thread needs to acquire multiple |
48 | * each write allocates separate cluster and writes data concurrently. | 32 | AioContexts simultaneously. Therefore, it is only safe for code holding the |
49 | * The first one to complete updates l2 table with pointer to its | ||
50 | @@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) | ||
51 | old_cluster[j++] = l2_slice[l2_index + i]; | ||
52 | } | ||
53 | |||
54 | - l2_slice[l2_index + i] = cpu_to_be64((cluster_offset + | ||
55 | - (i << s->cluster_bits)) | QCOW_OFLAG_COPIED); | ||
56 | + /* The offset must fit in the offset field of the L2 table entry */ | ||
57 | + assert((offset & L2E_OFFSET_MASK) == offset); | ||
58 | + | ||
59 | + l2_slice[l2_index + i] = cpu_to_be64(offset | QCOW_OFLAG_COPIED); | ||
60 | } | ||
61 | |||
62 | |||
63 | @@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, | ||
64 | goto fail; | ||
65 | } | ||
66 | |||
67 | + /* The offset must fit in the offset field */ | ||
68 | + assert((offset & L2E_OFFSET_MASK) == offset); | ||
69 | + | ||
70 | if (l2_refcount > 1) { | ||
71 | /* For shared L2 tables, set the refcount accordingly | ||
72 | * (it is already 1 and needs to be l2_refcount) */ | ||
73 | -- | 33 | -- |
74 | 2.24.1 | 34 | 2.14.3 |
75 | 35 | ||
76 | 36 | diff view generated by jsdifflib |
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 1 | When a node is already associated with a BlockBackend the |
---|---|---|---|
2 | x-blockdev-set-iothread command refuses to set the IOThread. This is to | ||
3 | prevent accidentally changing the IOThread when the nodes are in use. | ||
2 | 4 | ||
3 | We can't access top after call bdrv_backup_top_drop, as it is already | 5 | When the nodes are created with -drive they automatically get a |
4 | freed at this time. | 6 | BlockBackend. In that case we know nothing is using them yet and it's |
7 | safe to set the IOThread. Add a force boolean to override the check. | ||
5 | 8 | ||
6 | Also, no needs to unref target child by hand, it will be unrefed on | 9 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
7 | bdrv_close() automatically. | 10 | Reviewed-by: Eric Blake <eblake@redhat.com> |
11 | Message-id: 20171207201320.19284-4-stefanha@redhat.com | ||
12 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
13 | --- | ||
14 | qapi/block-core.json | 6 +++++- | ||
15 | blockdev.c | 11 ++++++----- | ||
16 | 2 files changed, 11 insertions(+), 6 deletions(-) | ||
8 | 17 | ||
9 | So, just do bdrv_backup_top_drop if append succeed and one bdrv_unref | 18 | diff --git a/qapi/block-core.json b/qapi/block-core.json |
10 | otherwise. | ||
11 | |||
12 | Note, that in !appended case bdrv_unref(top) moved into drained section | ||
13 | on source. It doesn't really matter, but just for code simplicity. | ||
14 | |||
15 | Fixes: 7df7868b96404 | ||
16 | Cc: qemu-stable@nongnu.org # v4.2.0 | ||
17 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
18 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
19 | Message-id: 20200121142802.21467-2-vsementsov@virtuozzo.com | ||
20 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
21 | --- | ||
22 | block/backup-top.c | 21 ++++++++++++--------- | ||
23 | 1 file changed, 12 insertions(+), 9 deletions(-) | ||
24 | |||
25 | diff --git a/block/backup-top.c b/block/backup-top.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/block/backup-top.c | 20 | --- a/qapi/block-core.json |
28 | +++ b/block/backup-top.c | 21 | +++ b/qapi/block-core.json |
29 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | 22 | @@ -XXX,XX +XXX,XX @@ |
30 | BlockDriverState *top = bdrv_new_open_driver(&bdrv_backup_top_filter, | 23 | # |
31 | filter_node_name, | 24 | # @iothread: the name of the IOThread object or null for the main loop |
32 | BDRV_O_RDWR, errp); | 25 | # |
33 | + bool appended = false; | 26 | +# @force: true if the node and its children should be moved when a BlockBackend |
34 | 27 | +# is already attached | |
35 | if (!top) { | 28 | +# |
36 | return NULL; | 29 | # Note: this command is experimental and intended for test cases that need |
37 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | 30 | # control over IOThreads only. |
38 | bdrv_append(top, source, &local_err); | 31 | # |
39 | if (local_err) { | 32 | @@ -XXX,XX +XXX,XX @@ |
40 | error_prepend(&local_err, "Cannot append backup-top filter: "); | 33 | ## |
41 | - goto append_failed; | 34 | { 'command': 'x-blockdev-set-iothread', |
42 | + goto fail; | 35 | 'data' : { 'node-name': 'str', |
36 | - 'iothread': 'StrOrNull' } } | ||
37 | + 'iothread': 'StrOrNull', | ||
38 | + '*force': 'bool' } } | ||
39 | diff --git a/blockdev.c b/blockdev.c | ||
40 | index XXXXXXX..XXXXXXX 100644 | ||
41 | --- a/blockdev.c | ||
42 | +++ b/blockdev.c | ||
43 | @@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp) | ||
44 | } | ||
45 | |||
46 | void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread, | ||
47 | - Error **errp) | ||
48 | + bool has_force, bool force, Error **errp) | ||
49 | { | ||
50 | AioContext *old_context; | ||
51 | AioContext *new_context; | ||
52 | @@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread, | ||
53 | return; | ||
43 | } | 54 | } |
44 | + appended = true; | 55 | |
45 | 56 | - /* If we want to allow more extreme test scenarios this guard could be | |
46 | /* | 57 | - * removed. For now it protects against accidents. */ |
47 | * bdrv_append() finished successfully, now we can require permissions | 58 | - if (bdrv_has_blk(bs)) { |
48 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | 59 | - error_setg(errp, "Node %s is in use", node_name); |
49 | if (local_err) { | 60 | + /* Protects against accidents. */ |
50 | error_prepend(&local_err, | 61 | + if (!(has_force && force) && bdrv_has_blk(bs)) { |
51 | "Cannot set permissions for backup-top filter: "); | 62 | + error_setg(errp, "Node %s is associated with a BlockBackend and could " |
52 | - goto failed_after_append; | 63 | + "be in use (use force=true to override this check)", |
53 | + goto fail; | 64 | + node_name); |
65 | return; | ||
54 | } | 66 | } |
55 | 67 | ||
56 | state->bcs = block_copy_state_new(top->backing, state->target, | ||
57 | cluster_size, write_flags, &local_err); | ||
58 | if (local_err) { | ||
59 | error_prepend(&local_err, "Cannot create block-copy-state: "); | ||
60 | - goto failed_after_append; | ||
61 | + goto fail; | ||
62 | } | ||
63 | *bcs = state->bcs; | ||
64 | |||
65 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source, | ||
66 | |||
67 | return top; | ||
68 | |||
69 | -failed_after_append: | ||
70 | - state->active = false; | ||
71 | - bdrv_backup_top_drop(top); | ||
72 | +fail: | ||
73 | + if (appended) { | ||
74 | + state->active = false; | ||
75 | + bdrv_backup_top_drop(top); | ||
76 | + } else { | ||
77 | + bdrv_unref(top); | ||
78 | + } | ||
79 | |||
80 | -append_failed: | ||
81 | bdrv_drained_end(source); | ||
82 | - bdrv_unref_child(top, state->target); | ||
83 | - bdrv_unref(top); | ||
84 | error_propagate(errp, local_err); | ||
85 | |||
86 | return NULL; | ||
87 | -- | 68 | -- |
88 | 2.24.1 | 69 | 2.14.3 |
89 | 70 | ||
90 | 71 | diff view generated by jsdifflib |
1 | From: John Snow <jsnow@redhat.com> | 1 | The VM.add_object() method can be used to add IOThreads or memory |
---|---|---|---|
2 | backend objects. | ||
2 | 3 | ||
3 | verify_platform will check an explicit whitelist and blacklist instead. | 4 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
4 | The default will now be assumed to be allowed to run anywhere. | 5 | Reviewed-by: Eric Blake <eblake@redhat.com> |
5 | 6 | Message-id: 20171207201320.19284-5-stefanha@redhat.com | |
6 | For tests that do not specify their platforms explicitly, this has the effect of | 7 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
7 | enabling these tests on non-linux platforms. For tests that always specified | ||
8 | linux explicitly, there is no change. | ||
9 | |||
10 | For Python tests on FreeBSD at least; only seven python tests fail: | ||
11 | 045 147 149 169 194 199 211 | ||
12 | |||
13 | 045 and 149 appear to be misconfigurations, | ||
14 | 147 and 194 are the AF_UNIX path too long error, | ||
15 | 169 and 199 are bitmap migration bugs, and | ||
16 | 211 is a bug that shows up on Linux platforms, too. | ||
17 | |||
18 | This is at least good evidence that these tests are not Linux-only. If | ||
19 | they aren't suitable for other platforms, they should be disabled on a | ||
20 | per-platform basis as appropriate. | ||
21 | |||
22 | Therefore, let's switch these on and deal with the failures. | ||
23 | |||
24 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
25 | Signed-off-by: John Snow <jsnow@redhat.com> | ||
26 | Message-id: 20200121095205.26323-2-thuth@redhat.com | ||
27 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
28 | --- | 8 | --- |
29 | tests/qemu-iotests/iotests.py | 16 +++++++++++----- | 9 | tests/qemu-iotests/iotests.py | 5 +++++ |
30 | 1 file changed, 11 insertions(+), 5 deletions(-) | 10 | 1 file changed, 5 insertions(+) |
31 | 11 | ||
32 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | 12 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py |
33 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
34 | --- a/tests/qemu-iotests/iotests.py | 14 | --- a/tests/qemu-iotests/iotests.py |
35 | +++ b/tests/qemu-iotests/iotests.py | 15 | +++ b/tests/qemu-iotests/iotests.py |
36 | @@ -XXX,XX +XXX,XX @@ def verify_protocol(supported=[], unsupported=[]): | 16 | @@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine): |
37 | if not_sup or (imgproto in unsupported): | 17 | socket_scm_helper=socket_scm_helper) |
38 | notrun('not suitable for this protocol: %s' % imgproto) | 18 | self._num_drives = 0 |
39 | 19 | ||
40 | -def verify_platform(supported_oses=['linux']): | 20 | + def add_object(self, opts): |
41 | - if True not in [sys.platform.startswith(x) for x in supported_oses]: | 21 | + self._args.append('-object') |
42 | - notrun('not suitable for this OS: %s' % sys.platform) | 22 | + self._args.append(opts) |
43 | +def verify_platform(supported=None, unsupported=None): | 23 | + return self |
44 | + if unsupported is not None: | ||
45 | + if any((sys.platform.startswith(x) for x in unsupported)): | ||
46 | + notrun('not suitable for this OS: %s' % sys.platform) | ||
47 | + | 24 | + |
48 | + if supported is not None: | 25 | def add_device(self, opts): |
49 | + if not any((sys.platform.startswith(x) for x in supported)): | 26 | self._args.append('-device') |
50 | + notrun('not suitable for this OS: %s' % sys.platform) | 27 | self._args.append(opts) |
51 | |||
52 | def verify_cache_mode(supported_cache_modes=[]): | ||
53 | if supported_cache_modes and (cachemode not in supported_cache_modes): | ||
54 | @@ -XXX,XX +XXX,XX @@ def execute_unittest(output, verbosity, debug): | ||
55 | sys.stderr.write(out) | ||
56 | |||
57 | def execute_test(test_function=None, | ||
58 | - supported_fmts=[], supported_oses=['linux'], | ||
59 | + supported_fmts=[], | ||
60 | + supported_platforms=None, | ||
61 | supported_cache_modes=[], supported_aio_modes={}, | ||
62 | unsupported_fmts=[], supported_protocols=[], | ||
63 | unsupported_protocols=[]): | ||
64 | @@ -XXX,XX +XXX,XX @@ def execute_test(test_function=None, | ||
65 | verbosity = 1 | ||
66 | verify_image_format(supported_fmts, unsupported_fmts) | ||
67 | verify_protocol(supported_protocols, unsupported_protocols) | ||
68 | - verify_platform(supported_oses) | ||
69 | + verify_platform(supported=supported_platforms) | ||
70 | verify_cache_mode(supported_cache_modes) | ||
71 | verify_aio_mode(supported_aio_modes) | ||
72 | |||
73 | -- | 28 | -- |
74 | 2.24.1 | 29 | 2.14.3 |
75 | 30 | ||
76 | 31 | diff view generated by jsdifflib |
1 | From: Thomas Huth <thuth@redhat.com> | 1 | There is a small chance that iothread_stop() hangs as follows: |
---|---|---|---|
2 | 2 | ||
3 | We are going to enable 127 in the "auto" group, but it only works if | 3 | Thread 3 (Thread 0x7f63eba5f700 (LWP 16105)): |
4 | virtio-scsi and scsi-hd are available - which is not the case with | 4 | #0 0x00007f64012c09b6 in ppoll () at /lib64/libc.so.6 |
5 | QEMU binaries like qemu-system-tricore for example, so we need a | 5 | #1 0x000055959992eac9 in ppoll (__ss=0x0, __timeout=0x0, __nfds=<optimized out>, __fds=<optimized out>) at /usr/include/bits/poll2.h:77 |
6 | proper check for the availability of these devices here. | 6 | #2 0x000055959992eac9 in qemu_poll_ns (fds=<optimized out>, nfds=<optimized out>, timeout=<optimized out>) at util/qemu-timer.c:322 |
7 | #3 0x0000559599930711 in aio_poll (ctx=0x55959bdb83c0, blocking=blocking@entry=true) at util/aio-posix.c:629 | ||
8 | #4 0x00005595996806fe in iothread_run (opaque=0x55959bd78400) at iothread.c:59 | ||
9 | #5 0x00007f640159f609 in start_thread () at /lib64/libpthread.so.0 | ||
10 | #6 0x00007f64012cce6f in clone () at /lib64/libc.so.6 | ||
7 | 11 | ||
8 | A very similar problem exists in iotest 267 - it has been added to | 12 | Thread 1 (Thread 0x7f640b45b280 (LWP 16103)): |
9 | the "auto" group already, but requires virtio-blk and thus currently | 13 | #0 0x00007f64015a0b6d in pthread_join () at /lib64/libpthread.so.0 |
10 | fails with qemu-system-tricore for example. Let's also add aproper | 14 | #1 0x00005595999332ef in qemu_thread_join (thread=<optimized out>) at util/qemu-thread-posix.c:547 |
11 | check there. | 15 | #2 0x00005595996808ae in iothread_stop (iothread=<optimized out>) at iothread.c:91 |
16 | #3 0x000055959968094d in iothread_stop_iter (object=<optimized out>, opaque=<optimized out>) at iothread.c:102 | ||
17 | #4 0x0000559599857d97 in do_object_child_foreach (obj=obj@entry=0x55959bdb8100, fn=fn@entry=0x559599680930 <iothread_stop_iter>, opaque=opaque@entry=0x0, recurse=recurse@entry=false) at qom/object.c:852 | ||
18 | #5 0x0000559599859477 in object_child_foreach (obj=obj@entry=0x55959bdb8100, fn=fn@entry=0x559599680930 <iothread_stop_iter>, opaque=opaque@entry=0x0) at qom/object.c:867 | ||
19 | #6 0x0000559599680a6e in iothread_stop_all () at iothread.c:341 | ||
20 | #7 0x000055959955b1d5 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4913 | ||
12 | 21 | ||
13 | Reviewed-by: Max Reitz <mreitz@redhat.com> | 22 | The relevant code from iothread_run() is: |
14 | Signed-off-by: Thomas Huth <thuth@redhat.com> | 23 | |
15 | Message-id: 20200121095205.26323-5-thuth@redhat.com | 24 | while (!atomic_read(&iothread->stopping)) { |
16 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 25 | aio_poll(iothread->ctx, true); |
26 | |||
27 | and iothread_stop(): | ||
28 | |||
29 | iothread->stopping = true; | ||
30 | aio_notify(iothread->ctx); | ||
31 | ... | ||
32 | qemu_thread_join(&iothread->thread); | ||
33 | |||
34 | The following scenario can occur: | ||
35 | |||
36 | 1. IOThread: | ||
37 | while (!atomic_read(&iothread->stopping)) -> stopping=false | ||
38 | |||
39 | 2. Main loop: | ||
40 | iothread->stopping = true; | ||
41 | aio_notify(iothread->ctx); | ||
42 | |||
43 | 3. IOThread: | ||
44 | aio_poll(iothread->ctx, true); -> hang | ||
45 | |||
46 | The bug is explained by the AioContext->notify_me doc comments: | ||
47 | |||
48 | "If this field is 0, everything (file descriptors, bottom halves, | ||
49 | timers) will be re-evaluated before the next blocking poll(), thus the | ||
50 | event_notifier_set call can be skipped." | ||
51 | |||
52 | The problem is that "everything" does not include checking | ||
53 | iothread->stopping. This means iothread_run() will block in aio_poll() | ||
54 | if aio_notify() was called just before aio_poll(). | ||
55 | |||
56 | This patch fixes the hang by replacing aio_notify() with | ||
57 | aio_bh_schedule_oneshot(). This makes aio_poll() or g_main_loop_run() | ||
58 | to return. | ||
59 | |||
60 | Implementing this properly required a new bool running flag. The new | ||
61 | flag prevents races that are tricky if we try to use iothread->stopping. | ||
62 | Now iothread->stopping is purely for iothread_stop() and | ||
63 | iothread->running is purely for the iothread_run() thread. | ||
64 | |||
65 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
66 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
67 | Message-id: 20171207201320.19284-6-stefanha@redhat.com | ||
68 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
17 | --- | 69 | --- |
18 | tests/qemu-iotests/127 | 2 ++ | 70 | include/sysemu/iothread.h | 3 ++- |
19 | tests/qemu-iotests/267 | 2 ++ | 71 | iothread.c | 20 +++++++++++++++----- |
20 | tests/qemu-iotests/common.rc | 14 ++++++++++++++ | 72 | 2 files changed, 17 insertions(+), 6 deletions(-) |
21 | 3 files changed, 18 insertions(+) | ||
22 | 73 | ||
23 | diff --git a/tests/qemu-iotests/127 b/tests/qemu-iotests/127 | 74 | diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h |
24 | index XXXXXXX..XXXXXXX 100755 | 75 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/tests/qemu-iotests/127 | 76 | --- a/include/sysemu/iothread.h |
26 | +++ b/tests/qemu-iotests/127 | 77 | +++ b/include/sysemu/iothread.h |
27 | @@ -XXX,XX +XXX,XX @@ trap "_cleanup; exit \$status" 0 1 2 3 15 | 78 | @@ -XXX,XX +XXX,XX @@ typedef struct { |
28 | _supported_fmt qcow2 | 79 | GOnce once; |
29 | _supported_proto file | 80 | QemuMutex init_done_lock; |
30 | 81 | QemuCond init_done_cond; /* is thread initialization done? */ | |
31 | +_require_devices virtio-scsi scsi-hd | 82 | - bool stopping; |
83 | + bool stopping; /* has iothread_stop() been called? */ | ||
84 | + bool running; /* should iothread_run() continue? */ | ||
85 | int thread_id; | ||
86 | |||
87 | /* AioContext poll parameters */ | ||
88 | diff --git a/iothread.c b/iothread.c | ||
89 | index XXXXXXX..XXXXXXX 100644 | ||
90 | --- a/iothread.c | ||
91 | +++ b/iothread.c | ||
92 | @@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque) | ||
93 | qemu_cond_signal(&iothread->init_done_cond); | ||
94 | qemu_mutex_unlock(&iothread->init_done_lock); | ||
95 | |||
96 | - while (!atomic_read(&iothread->stopping)) { | ||
97 | + while (iothread->running) { | ||
98 | aio_poll(iothread->ctx, true); | ||
99 | |||
100 | if (atomic_read(&iothread->worker_context)) { | ||
101 | @@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque) | ||
102 | return NULL; | ||
103 | } | ||
104 | |||
105 | +/* Runs in iothread_run() thread */ | ||
106 | +static void iothread_stop_bh(void *opaque) | ||
107 | +{ | ||
108 | + IOThread *iothread = opaque; | ||
32 | + | 109 | + |
33 | IMG_SIZE=64K | 110 | + iothread->running = false; /* stop iothread_run() */ |
34 | |||
35 | _make_test_img $IMG_SIZE | ||
36 | diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267 | ||
37 | index XXXXXXX..XXXXXXX 100755 | ||
38 | --- a/tests/qemu-iotests/267 | ||
39 | +++ b/tests/qemu-iotests/267 | ||
40 | @@ -XXX,XX +XXX,XX @@ _require_drivers copy-on-read | ||
41 | # and generally impossible with external data files | ||
42 | _unsupported_imgopts 'refcount_bits=1[^0-9]' data_file | ||
43 | |||
44 | +_require_devices virtio-blk | ||
45 | + | 111 | + |
46 | do_run_qemu() | 112 | + if (iothread->main_loop) { |
47 | { | 113 | + g_main_loop_quit(iothread->main_loop); |
48 | echo Testing: "$@" | 114 | + } |
49 | diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc | ||
50 | index XXXXXXX..XXXXXXX 100644 | ||
51 | --- a/tests/qemu-iotests/common.rc | ||
52 | +++ b/tests/qemu-iotests/common.rc | ||
53 | @@ -XXX,XX +XXX,XX @@ _require_large_file() | ||
54 | rm "$TEST_IMG" | ||
55 | } | ||
56 | |||
57 | +# Check that a set of devices is available in the QEMU binary | ||
58 | +# | ||
59 | +_require_devices() | ||
60 | +{ | ||
61 | + available=$($QEMU -M none -device help | \ | ||
62 | + grep ^name | sed -e 's/^name "//' -e 's/".*$//') | ||
63 | + for device | ||
64 | + do | ||
65 | + if ! echo "$available" | grep -q "$device" ; then | ||
66 | + _notrun "$device not available" | ||
67 | + fi | ||
68 | + done | ||
69 | +} | 115 | +} |
70 | + | 116 | + |
71 | # make sure this script returns success | 117 | void iothread_stop(IOThread *iothread) |
72 | true | 118 | { |
119 | if (!iothread->ctx || iothread->stopping) { | ||
120 | return; | ||
121 | } | ||
122 | iothread->stopping = true; | ||
123 | - aio_notify(iothread->ctx); | ||
124 | - if (atomic_read(&iothread->main_loop)) { | ||
125 | - g_main_loop_quit(iothread->main_loop); | ||
126 | - } | ||
127 | + aio_bh_schedule_oneshot(iothread->ctx, iothread_stop_bh, iothread); | ||
128 | qemu_thread_join(&iothread->thread); | ||
129 | } | ||
130 | |||
131 | @@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp) | ||
132 | char *name, *thread_name; | ||
133 | |||
134 | iothread->stopping = false; | ||
135 | + iothread->running = true; | ||
136 | iothread->thread_id = -1; | ||
137 | iothread->ctx = aio_context_new(&local_error); | ||
138 | if (!iothread->ctx) { | ||
73 | -- | 139 | -- |
74 | 2.24.1 | 140 | 2.14.3 |
75 | 141 | ||
76 | 142 | diff view generated by jsdifflib |
1 | From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 1 | This test case will prevent future regressions with savevm and |
---|---|---|---|
2 | IOThreads. | ||
2 | 3 | ||
3 | This test checks that bug is really fixed by previous commit. | 4 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
5 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
6 | Message-id: 20171207201320.19284-7-stefanha@redhat.com | ||
7 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
8 | --- | ||
9 | tests/qemu-iotests/203 | 59 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
10 | tests/qemu-iotests/203.out | 6 +++++ | ||
11 | tests/qemu-iotests/group | 1 + | ||
12 | 3 files changed, 66 insertions(+) | ||
13 | create mode 100755 tests/qemu-iotests/203 | ||
14 | create mode 100644 tests/qemu-iotests/203.out | ||
4 | 15 | ||
5 | Cc: qemu-stable@nongnu.org # v4.2.0 | 16 | diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203 |
6 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | 17 | new file mode 100755 |
7 | Message-id: 20200121142802.21467-3-vsementsov@virtuozzo.com | ||
8 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
9 | --- | ||
10 | tests/qemu-iotests/283 | 92 ++++++++++++++++++++++++++++++++++++++ | ||
11 | tests/qemu-iotests/283.out | 8 ++++ | ||
12 | tests/qemu-iotests/group | 1 + | ||
13 | 3 files changed, 101 insertions(+) | ||
14 | create mode 100644 tests/qemu-iotests/283 | ||
15 | create mode 100644 tests/qemu-iotests/283.out | ||
16 | |||
17 | diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283 | ||
18 | new file mode 100644 | ||
19 | index XXXXXXX..XXXXXXX | 18 | index XXXXXXX..XXXXXXX |
20 | --- /dev/null | 19 | --- /dev/null |
21 | +++ b/tests/qemu-iotests/283 | 20 | +++ b/tests/qemu-iotests/203 |
22 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ |
23 | +#!/usr/bin/env python | 22 | +#!/usr/bin/env python |
24 | +# | 23 | +# |
25 | +# Test for backup-top filter permission activation failure | 24 | +# Copyright (C) 2017 Red Hat, Inc. |
26 | +# | ||
27 | +# Copyright (c) 2019 Virtuozzo International GmbH. | ||
28 | +# | 25 | +# |
29 | +# This program is free software; you can redistribute it and/or modify | 26 | +# This program is free software; you can redistribute it and/or modify |
30 | +# it under the terms of the GNU General Public License as published by | 27 | +# it under the terms of the GNU General Public License as published by |
31 | +# the Free Software Foundation; either version 2 of the License, or | 28 | +# the Free Software Foundation; either version 2 of the License, or |
32 | +# (at your option) any later version. | 29 | +# (at your option) any later version. |
... | ... | ||
37 | +# GNU General Public License for more details. | 34 | +# GNU General Public License for more details. |
38 | +# | 35 | +# |
39 | +# You should have received a copy of the GNU General Public License | 36 | +# You should have received a copy of the GNU General Public License |
40 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | 37 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
41 | +# | 38 | +# |
39 | +# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com> | ||
40 | +# | ||
41 | +# Check that QMP 'migrate' with multiple drives on a single IOThread completes | ||
42 | +# successfully. This particular command triggered a hang in the source QEMU | ||
43 | +# process due to recursive AioContext locking in bdrv_invalidate_all() and | ||
44 | +# BDRV_POLL_WHILE(). | ||
42 | + | 45 | + |
43 | +import iotests | 46 | +import iotests |
44 | + | 47 | + |
45 | +# The test is unrelated to formats, restrict it to qcow2 to avoid extra runs | ||
46 | +iotests.verify_image_format(supported_fmts=['qcow2']) | 48 | +iotests.verify_image_format(supported_fmts=['qcow2']) |
49 | +iotests.verify_platform(['linux']) | ||
47 | + | 50 | + |
48 | +size = 1024 * 1024 | 51 | +with iotests.FilePath('disk0.img') as disk0_img_path, \ |
52 | + iotests.FilePath('disk1.img') as disk1_img_path, \ | ||
53 | + iotests.VM() as vm: | ||
49 | + | 54 | + |
50 | +""" Test description | 55 | + img_size = '10M' |
56 | + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk0_img_path, img_size) | ||
57 | + iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk1_img_path, img_size) | ||
51 | + | 58 | + |
52 | +When performing a backup, all writes on the source subtree must go through the | 59 | + iotests.log('Launching VM...') |
53 | +backup-top filter so it can copy all data to the target before it is changed. | 60 | + (vm.add_object('iothread,id=iothread0') |
54 | +backup-top filter is appended above source node, to achieve this thing, so all | 61 | + .add_drive(disk0_img_path, 'node-name=drive0-node', interface='none') |
55 | +parents of source node are handled. A configuration with side parents of source | 62 | + .add_drive(disk1_img_path, 'node-name=drive1-node', interface='none') |
56 | +sub-tree with write permission is unsupported (we'd have append several | 63 | + .launch()) |
57 | +backup-top filter like nodes to handle such parents). The test create an | ||
58 | +example of such configuration and checks that a backup is then not allowed | ||
59 | +(blockdev-backup command should fail). | ||
60 | + | 64 | + |
61 | +The configuration: | 65 | + iotests.log('Setting IOThreads...') |
66 | + iotests.log(vm.qmp('x-blockdev-set-iothread', | ||
67 | + node_name='drive0-node', iothread='iothread0', | ||
68 | + force=True)) | ||
69 | + iotests.log(vm.qmp('x-blockdev-set-iothread', | ||
70 | + node_name='drive1-node', iothread='iothread0', | ||
71 | + force=True)) | ||
62 | + | 72 | + |
63 | + ┌────────┐ target ┌─────────────┐ | 73 | + iotests.log('Starting migration...') |
64 | + │ target │ ◀─────── │ backup_top │ | 74 | + iotests.log(vm.qmp('migrate', uri='exec:cat >/dev/null')) |
65 | + └────────┘ └─────────────┘ | 75 | + while True: |
66 | + │ | 76 | + vm.get_qmp_event(wait=60.0) |
67 | + │ backing | 77 | + result = vm.qmp('query-migrate') |
68 | + ▼ | 78 | + status = result.get('return', {}).get('status', None) |
69 | + ┌─────────────┐ | 79 | + if status == 'completed': |
70 | + │ source │ | 80 | + break |
71 | + └─────────────┘ | 81 | diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out |
72 | + │ | ||
73 | + │ file | ||
74 | + ▼ | ||
75 | + ┌─────────────┐ write perm ┌───────┐ | ||
76 | + │ base │ ◀──────────── │ other │ | ||
77 | + └─────────────┘ └───────┘ | ||
78 | + | ||
79 | +On activation (see .active field of backup-top state in block/backup-top.c), | ||
80 | +backup-top is going to unshare write permission on its source child. Write | ||
81 | +unsharing will be propagated to the "source->base" link and will conflict with | ||
82 | +other node write permission. So permission update will fail and backup job will | ||
83 | +not be started. | ||
84 | + | ||
85 | +Note, that the only thing which prevents backup of running on such | ||
86 | +configuration is default permission propagation scheme. It may be altered by | ||
87 | +different block drivers, so backup will run in invalid configuration. But | ||
88 | +something is better than nothing. Also, before the previous commit (commit | ||
89 | +preceding this test creation), starting backup on such configuration led to | ||
90 | +crash, so current "something" is a lot better, and this test actual goal is | ||
91 | +to check that crash is fixed :) | ||
92 | +""" | ||
93 | + | ||
94 | +vm = iotests.VM() | ||
95 | +vm.launch() | ||
96 | + | ||
97 | +vm.qmp_log('blockdev-add', **{'node-name': 'target', 'driver': 'null-co'}) | ||
98 | + | ||
99 | +vm.qmp_log('blockdev-add', **{ | ||
100 | + 'node-name': 'source', | ||
101 | + 'driver': 'blkdebug', | ||
102 | + 'image': {'node-name': 'base', 'driver': 'null-co', 'size': size} | ||
103 | +}) | ||
104 | + | ||
105 | +vm.qmp_log('blockdev-add', **{ | ||
106 | + 'node-name': 'other', | ||
107 | + 'driver': 'blkdebug', | ||
108 | + 'image': 'base', | ||
109 | + 'take-child-perms': ['write'] | ||
110 | +}) | ||
111 | + | ||
112 | +vm.qmp_log('blockdev-backup', sync='full', device='source', target='target') | ||
113 | + | ||
114 | +vm.shutdown() | ||
115 | diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out | ||
116 | new file mode 100644 | 82 | new file mode 100644 |
117 | index XXXXXXX..XXXXXXX | 83 | index XXXXXXX..XXXXXXX |
118 | --- /dev/null | 84 | --- /dev/null |
119 | +++ b/tests/qemu-iotests/283.out | 85 | +++ b/tests/qemu-iotests/203.out |
120 | @@ -XXX,XX +XXX,XX @@ | 86 | @@ -XXX,XX +XXX,XX @@ |
121 | +{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "target"}} | 87 | +Launching VM... |
122 | +{"return": {}} | 88 | +Setting IOThreads... |
123 | +{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": {"driver": "null-co", "node-name": "base", "size": 1048576}, "node-name": "source"}} | 89 | +{u'return': {}} |
124 | +{"return": {}} | 90 | +{u'return': {}} |
125 | +{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}} | 91 | +Starting migration... |
126 | +{"return": {}} | 92 | +{u'return': {}} |
127 | +{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}} | ||
128 | +{"error": {"class": "GenericError", "desc": "Cannot set permissions for backup-top filter: Conflicts with use by other as 'image', which uses 'write' on base"}} | ||
129 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group | 93 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group |
130 | index XXXXXXX..XXXXXXX 100644 | 94 | index XXXXXXX..XXXXXXX 100644 |
131 | --- a/tests/qemu-iotests/group | 95 | --- a/tests/qemu-iotests/group |
132 | +++ b/tests/qemu-iotests/group | 96 | +++ b/tests/qemu-iotests/group |
133 | @@ -XXX,XX +XXX,XX @@ | 97 | @@ -XXX,XX +XXX,XX @@ |
134 | 279 rw backing quick | 98 | 198 rw auto |
135 | 280 rw migration quick | 99 | 200 rw auto |
136 | 281 rw quick | 100 | 202 rw auto quick |
137 | +283 auto quick | 101 | +203 rw auto |
138 | -- | 102 | -- |
139 | 2.24.1 | 103 | 2.14.3 |
140 | 104 | ||
141 | 105 | diff view generated by jsdifflib |