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