1 | The following changes since commit 508ba0f7e2092d3ca56e3f75e894d52d8b94818e: | 1 | The following changes since commit 013a18edbbc59cdad019100c7d03c0494642b74c: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20171109' into staging (2017-11-13 11:41:47 +0000) | 3 | Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-2020051= |
4 | 4' into staging (2020-05-14 16:17:55 +0100) | ||
4 | 5 | ||
5 | are available in the git repository at: | 6 | are available in the Git repository at: |
6 | 7 | ||
7 | git://github.com/stefanha/qemu.git tags/block-pull-request | 8 | https://github.com/stefanha/qemu.git tags/block-pull-request |
8 | 9 | ||
9 | for you to fetch changes up to 0761562687e0d8135310a94b1d3e08376387c027: | 10 | for you to fetch changes up to ba607ca8bff4d2c2062902f8355657c865ac7c29: |
10 | 11 | ||
11 | qemu-iotests: Test I/O limits with removable media (2017-11-13 15:46:26 +0000) | 12 | aio-posix: disable fdmon-io_uring when GSource is used (2020-05-18 18:16:00= |
13 | +0100) | ||
12 | 14 | ||
13 | ---------------------------------------------------------------- | 15 | ---------------------------------------------------------------- |
14 | Pull request | 16 | Pull request |
15 | 17 | ||
16 | The following disk I/O throttling fixes solve recent bugs. | ||
17 | |||
18 | ---------------------------------------------------------------- | 18 | ---------------------------------------------------------------- |
19 | 19 | ||
20 | Alberto Garcia (3): | 20 | Philippe Mathieu-Daud=C3=A9 (6): |
21 | block: Check for inserted BlockDriverState in blk_io_limits_disable() | 21 | tests/fuzz/Makefile: Do not link code using unavailable devices |
22 | block: Leave valid throttle timers when removing a BDS from a backend | 22 | Makefile: List fuzz targets in 'make help' |
23 | qemu-iotests: Test I/O limits with removable media | 23 | tests/fuzz: Add missing space in test description |
24 | tests/fuzz: Remove unuseful/unused typedefs | ||
25 | tests/fuzz: Extract pciconfig_fuzz_qos() method | ||
26 | tests/fuzz: Extract ioport_fuzz_qtest() method | ||
24 | 27 | ||
25 | Stefan Hajnoczi (1): | 28 | Stefan Hajnoczi (2): |
26 | throttle-groups: drain before detaching ThrottleState | 29 | aio-posix: don't duplicate fd handler deletion in |
30 | fdmon_io_uring_destroy() | ||
31 | aio-posix: disable fdmon-io_uring when GSource is used | ||
27 | 32 | ||
28 | Zhengui (1): | 33 | Makefile | 6 +++- |
29 | block: all I/O should be completed before removing throttle timers. | 34 | tests/qtest/fuzz/Makefile.include | 6 ++-- |
35 | include/block/aio.h | 3 ++ | ||
36 | tests/qtest/fuzz/i440fx_fuzz.c | 47 ++++++++++++++++++++----------- | ||
37 | util/aio-posix.c | 13 +++++++++ | ||
38 | util/aio-win32.c | 4 +++ | ||
39 | util/async.c | 1 + | ||
40 | util/fdmon-io_uring.c | 13 +++++++-- | ||
41 | 8 files changed, 69 insertions(+), 24 deletions(-) | ||
30 | 42 | ||
31 | block/block-backend.c | 36 ++++++++++++++++++--------- | 43 | --=20 |
32 | block/throttle-groups.c | 6 +++++ | 44 | 2.25.3 |
33 | tests/qemu-iotests/093 | 62 ++++++++++++++++++++++++++++++++++++++++++++++ | ||
34 | tests/qemu-iotests/093.out | 4 +-- | ||
35 | 4 files changed, 94 insertions(+), 14 deletions(-) | ||
36 | 45 | ||
37 | -- | ||
38 | 2.13.6 | ||
39 | |||
40 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
1 | 2 | ||
3 | Some devices availability depends on CONFIG options. | ||
4 | Use these options to only link tests when requested device | ||
5 | is available. | ||
6 | |||
7 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
8 | Message-id: 20200514143433.18569-2-philmd@redhat.com | ||
9 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
10 | --- | ||
11 | tests/qtest/fuzz/Makefile.include | 6 +++--- | ||
12 | 1 file changed, 3 insertions(+), 3 deletions(-) | ||
13 | |||
14 | diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/tests/qtest/fuzz/Makefile.include | ||
17 | +++ b/tests/qtest/fuzz/Makefile.include | ||
18 | @@ -XXX,XX +XXX,XX @@ fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o | ||
19 | fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o | ||
20 | |||
21 | # Targets | ||
22 | -fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o | ||
23 | -fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o | ||
24 | -fuzz-obj-y += tests/qtest/fuzz/virtio_scsi_fuzz.o | ||
25 | +fuzz-obj-$(CONFIG_PCI_I440FX) += tests/qtest/fuzz/i440fx_fuzz.o | ||
26 | +fuzz-obj-$(CONFIG_VIRTIO_NET) += tests/qtest/fuzz/virtio_net_fuzz.o | ||
27 | +fuzz-obj-$(CONFIG_SCSI) += tests/qtest/fuzz/virtio_scsi_fuzz.o | ||
28 | |||
29 | FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest | ||
30 | |||
31 | -- | ||
32 | 2.25.3 | ||
33 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
1 | 2 | ||
3 | List softmmu fuzz targets in 'make help' output: | ||
4 | |||
5 | $ make help | ||
6 | ... | ||
7 | Architecture specific targets: | ||
8 | aarch64-softmmu/all - Build for aarch64-softmmu | ||
9 | aarch64-softmmu/fuzz - Build fuzzer for aarch64-softmmu | ||
10 | alpha-softmmu/all - Build for alpha-softmmu | ||
11 | alpha-softmmu/fuzz - Build fuzzer for alpha-softmmu | ||
12 | arm-softmmu/all - Build for arm-softmmu | ||
13 | arm-softmmu/fuzz - Build fuzzer for arm-softmmu | ||
14 | ... | ||
15 | |||
16 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
17 | Message-id: 20200514143433.18569-3-philmd@redhat.com | ||
18 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
19 | --- | ||
20 | Makefile | 6 +++++- | ||
21 | 1 file changed, 5 insertions(+), 1 deletion(-) | ||
22 | |||
23 | diff --git a/Makefile b/Makefile | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/Makefile | ||
26 | +++ b/Makefile | ||
27 | @@ -XXX,XX +XXX,XX @@ endif | ||
28 | @$(if $(TARGET_DIRS), \ | ||
29 | echo 'Architecture specific targets:'; \ | ||
30 | $(foreach t, $(TARGET_DIRS), \ | ||
31 | - $(call print-help-run,$(t)/all,Build for $(t));) \ | ||
32 | + $(call print-help-run,$(t)/all,Build for $(t)); \ | ||
33 | + $(if $(CONFIG_FUZZ), \ | ||
34 | + $(if $(findstring softmmu,$(t)), \ | ||
35 | + $(call print-help-run,$(t)/fuzz,Build fuzzer for $(t)); \ | ||
36 | + ))) \ | ||
37 | echo '') | ||
38 | @$(if $(TOOLS), \ | ||
39 | echo 'Tools targets:'; \ | ||
40 | -- | ||
41 | 2.25.3 | ||
42 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
1 | 2 | ||
3 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
4 | Message-id: 20200514143433.18569-4-philmd@redhat.com | ||
5 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
6 | --- | ||
7 | tests/qtest/fuzz/i440fx_fuzz.c | 6 +++--- | ||
8 | 1 file changed, 3 insertions(+), 3 deletions(-) | ||
9 | |||
10 | diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c | ||
11 | index XXXXXXX..XXXXXXX 100644 | ||
12 | --- a/tests/qtest/fuzz/i440fx_fuzz.c | ||
13 | +++ b/tests/qtest/fuzz/i440fx_fuzz.c | ||
14 | @@ -XXX,XX +XXX,XX @@ static void register_pci_fuzz_targets(void) | ||
15 | /* Uses simple qtest commands and reboots to reset state */ | ||
16 | fuzz_add_target(&(FuzzTarget){ | ||
17 | .name = "i440fx-qtest-reboot-fuzz", | ||
18 | - .description = "Fuzz the i440fx using raw qtest commands and" | ||
19 | + .description = "Fuzz the i440fx using raw qtest commands and " | ||
20 | "rebooting after each run", | ||
21 | .get_init_cmdline = i440fx_argv, | ||
22 | .fuzz = i440fx_fuzz_qtest}); | ||
23 | @@ -XXX,XX +XXX,XX @@ static void register_pci_fuzz_targets(void) | ||
24 | /* Uses libqos and forks to prevent state leakage */ | ||
25 | fuzz_add_qos_target(&(FuzzTarget){ | ||
26 | .name = "i440fx-qos-fork-fuzz", | ||
27 | - .description = "Fuzz the i440fx using raw qtest commands and" | ||
28 | + .description = "Fuzz the i440fx using raw qtest commands and " | ||
29 | "rebooting after each run", | ||
30 | .pre_vm_init = &fork_init, | ||
31 | .fuzz = i440fx_fuzz_qos_fork,}, | ||
32 | @@ -XXX,XX +XXX,XX @@ static void register_pci_fuzz_targets(void) | ||
33 | */ | ||
34 | fuzz_add_qos_target(&(FuzzTarget){ | ||
35 | .name = "i440fx-qos-noreset-fuzz", | ||
36 | - .description = "Fuzz the i440fx using raw qtest commands and" | ||
37 | + .description = "Fuzz the i440fx using raw qtest commands and " | ||
38 | "rebooting after each run", | ||
39 | .fuzz = i440fx_fuzz_qos,}, | ||
40 | "i440FX-pcihost", | ||
41 | -- | ||
42 | 2.25.3 | ||
43 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | If a BlockBackend has I/O limits set then its ThrottleGroupMember | 3 | These typedefs are not used. Use a simple structure, |
4 | structure uses the AioContext from its attached BlockDriverState. | 4 | remote the typedefs. |
5 | Those two contexts must be kept in sync manually. This is not | ||
6 | ideal and will be fixed in the future by removing the throttling | ||
7 | configuration from the BlockBackend and storing it in an implicit | ||
8 | filter node instead, but for now we have to live with this. | ||
9 | 5 | ||
10 | When you remove the BlockDriverState from the backend then the | 6 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
11 | throttle timers are destroyed. If a new BlockDriverState is later | 7 | Message-id: 20200514143433.18569-5-philmd@redhat.com |
12 | inserted then they are created again using the new AioContext. | ||
13 | |||
14 | There are a couple of problems with this: | ||
15 | |||
16 | a) The code manipulates the timers directly, leaving the | ||
17 | ThrottleGroupMember.aio_context field in an inconsisent state. | ||
18 | |||
19 | b) If you remove the I/O limits (e.g by destroying the backend) | ||
20 | when the timers are gone then throttle_group_unregister_tgm() | ||
21 | will attempt to destroy them again, crashing QEMU. | ||
22 | |||
23 | While b) could be fixed easily by allowing the timers to be freed | ||
24 | twice, this would result in a situation in which we can no longer | ||
25 | guarantee that a valid ThrottleState has a valid AioContext and | ||
26 | timers. | ||
27 | |||
28 | This patch ensures that the timers and AioContext are always valid | ||
29 | when I/O limits are set, regardless of whether the BlockBackend has a | ||
30 | BlockDriverState inserted or not. | ||
31 | |||
32 | [Fixed "There'a" typo as suggested by Max Reitz <mreitz@redhat.com> | ||
33 | --Stefan] | ||
34 | |||
35 | Reported-by: sochin jiang <sochin.jiang@huawei.com> | ||
36 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
37 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
38 | Message-id: e089c66e7c20289b046d782cea4373b765c5bc1d.1510339534.git.berto@igalia.com | ||
39 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 8 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
40 | --- | 9 | --- |
41 | block/block-backend.c | 16 ++++++++-------- | 10 | tests/qtest/fuzz/i440fx_fuzz.c | 10 ++++------ |
42 | 1 file changed, 8 insertions(+), 8 deletions(-) | 11 | 1 file changed, 4 insertions(+), 6 deletions(-) |
43 | 12 | ||
44 | diff --git a/block/block-backend.c b/block/block-backend.c | 13 | diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c |
45 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
46 | --- a/block/block-backend.c | 15 | --- a/tests/qtest/fuzz/i440fx_fuzz.c |
47 | +++ b/block/block-backend.c | 16 | +++ b/tests/qtest/fuzz/i440fx_fuzz.c |
48 | @@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public) | 17 | @@ -XXX,XX +XXX,XX @@ static void i440fx_fuzz_qtest(QTestState *s, |
49 | */ | 18 | * loop over the Data, breaking it up into actions. each action has an |
50 | void blk_remove_bs(BlockBackend *blk) | 19 | * opcode, address offset and value |
51 | { | 20 | */ |
52 | + ThrottleGroupMember *tgm = &blk->public.throttle_group_member; | 21 | - typedef struct QTestFuzzAction { |
53 | BlockDriverState *bs; | 22 | + struct { |
54 | - ThrottleTimers *tt; | 23 | uint8_t opcode; |
55 | 24 | uint8_t addr; | |
56 | notifier_list_notify(&blk->remove_bs_notifiers, blk); | 25 | uint32_t value; |
57 | - if (blk->public.throttle_group_member.throttle_state) { | 26 | - } QTestFuzzAction; |
58 | - tt = &blk->public.throttle_group_member.throttle_timers; | 27 | - QTestFuzzAction a; |
59 | + if (tgm->throttle_state) { | 28 | + } a; |
60 | bs = blk_bs(blk); | 29 | |
61 | bdrv_drained_begin(bs); | 30 | while (Size >= sizeof(a)) { |
62 | - throttle_timers_detach_aio_context(tt); | 31 | /* make a copy of the action so we can normalize the values in-place */ |
63 | + throttle_group_detach_aio_context(tgm); | 32 | @@ -XXX,XX +XXX,XX @@ static void i440fx_fuzz_qos(QTestState *s, |
64 | + throttle_group_attach_aio_context(tgm, qemu_get_aio_context()); | 33 | * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the |
65 | bdrv_drained_end(bs); | 34 | * value written over Port IO |
35 | */ | ||
36 | - typedef struct QOSFuzzAction { | ||
37 | + struct { | ||
38 | uint8_t opcode; | ||
39 | uint8_t offset; | ||
40 | int devfn; | ||
41 | uint32_t value; | ||
42 | - } QOSFuzzAction; | ||
43 | + } a; | ||
44 | |||
45 | static QPCIBus *bus; | ||
46 | if (!bus) { | ||
47 | bus = qpci_new_pc(s, fuzz_qos_alloc); | ||
66 | } | 48 | } |
67 | 49 | ||
68 | @@ -XXX,XX +XXX,XX @@ void blk_remove_bs(BlockBackend *blk) | 50 | - QOSFuzzAction a; |
69 | */ | 51 | while (Size >= sizeof(a)) { |
70 | int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) | 52 | memcpy(&a, Data, sizeof(a)); |
71 | { | 53 | switch (a.opcode % ACTION_MAX) { |
72 | + ThrottleGroupMember *tgm = &blk->public.throttle_group_member; | ||
73 | blk->root = bdrv_root_attach_child(bs, "root", &child_root, | ||
74 | blk->perm, blk->shared_perm, blk, errp); | ||
75 | if (blk->root == NULL) { | ||
76 | @@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) | ||
77 | bdrv_ref(bs); | ||
78 | |||
79 | notifier_list_notify(&blk->insert_bs_notifiers, blk); | ||
80 | - if (blk->public.throttle_group_member.throttle_state) { | ||
81 | - throttle_timers_attach_aio_context( | ||
82 | - &blk->public.throttle_group_member.throttle_timers, | ||
83 | - bdrv_get_aio_context(bs)); | ||
84 | + if (tgm->throttle_state) { | ||
85 | + throttle_group_detach_aio_context(tgm); | ||
86 | + throttle_group_attach_aio_context(tgm, bdrv_get_aio_context(bs)); | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | -- | 54 | -- |
91 | 2.13.6 | 55 | 2.25.3 |
92 | 56 | ||
93 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | This test hotplugs a CD drive to a VM and checks that I/O limits can | 3 | Extract the generic pciconfig_fuzz_qos() method from |
4 | be set only when the drive has media inserted and that they are kept | 4 | i440fx_fuzz_qos(). This will help to write tests not |
5 | when the media is replaced. | 5 | specific to the i440FX controller. |
6 | 6 | ||
7 | This also tests the removal of a device with valid I/O limits set but | 7 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
8 | no media inserted. This involves deleting and disabling the limits | 8 | Message-id: 20200514143433.18569-6-philmd@redhat.com |
9 | of a BlockBackend without BlockDriverState, a scenario that has been | ||
10 | crashing until the fixes from the last couple of patches. | ||
11 | |||
12 | [Python PEP8 fixup: "Don't use spaces are the = sign when used to | ||
13 | indicate a keyword argument or a default parameter value" | ||
14 | --Stefan] | ||
15 | |||
16 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
17 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
18 | Message-id: 071eb397118ed207c5a7f01d58766e415ee18d6a.1510339534.git.berto@igalia.com | ||
19 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 9 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
20 | --- | 10 | --- |
21 | tests/qemu-iotests/093 | 62 ++++++++++++++++++++++++++++++++++++++++++++++ | 11 | tests/qtest/fuzz/i440fx_fuzz.c | 20 ++++++++++++++------ |
22 | tests/qemu-iotests/093.out | 4 +-- | 12 | 1 file changed, 14 insertions(+), 6 deletions(-) |
23 | 2 files changed, 64 insertions(+), 2 deletions(-) | ||
24 | 13 | ||
25 | diff --git a/tests/qemu-iotests/093 b/tests/qemu-iotests/093 | 14 | diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c |
26 | index XXXXXXX..XXXXXXX 100755 | 15 | index XXXXXXX..XXXXXXX 100644 |
27 | --- a/tests/qemu-iotests/093 | 16 | --- a/tests/qtest/fuzz/i440fx_fuzz.c |
28 | +++ b/tests/qemu-iotests/093 | 17 | +++ b/tests/qtest/fuzz/i440fx_fuzz.c |
29 | @@ -XXX,XX +XXX,XX @@ class ThrottleTestGroupNames(iotests.QMPTestCase): | 18 | @@ -XXX,XX +XXX,XX @@ static void i440fx_fuzz_qtest(QTestState *s, |
30 | groupname = "group%d" % i | 19 | flush_events(s); |
31 | self.verify_name(devname, groupname) | 20 | } |
32 | 21 | ||
33 | +class ThrottleTestRemovableMedia(iotests.QMPTestCase): | 22 | -static void i440fx_fuzz_qos(QTestState *s, |
34 | + def setUp(self): | 23 | +static void pciconfig_fuzz_qos(QTestState *s, QPCIBus *bus, |
35 | + self.vm = iotests.VM() | 24 | const unsigned char *Data, size_t Size) { |
36 | + if iotests.qemu_default_machine == 's390-ccw-virtio': | 25 | /* |
37 | + self.vm.add_device("virtio-scsi-ccw,id=virtio-scsi") | 26 | * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the |
38 | + else: | 27 | @@ -XXX,XX +XXX,XX @@ static void i440fx_fuzz_qos(QTestState *s, |
39 | + self.vm.add_device("virtio-scsi-pci,id=virtio-scsi") | 28 | uint32_t value; |
40 | + self.vm.launch() | 29 | } a; |
30 | |||
31 | - static QPCIBus *bus; | ||
32 | - if (!bus) { | ||
33 | - bus = qpci_new_pc(s, fuzz_qos_alloc); | ||
34 | - } | ||
35 | - | ||
36 | while (Size >= sizeof(a)) { | ||
37 | memcpy(&a, Data, sizeof(a)); | ||
38 | switch (a.opcode % ACTION_MAX) { | ||
39 | @@ -XXX,XX +XXX,XX @@ static void i440fx_fuzz_qos(QTestState *s, | ||
40 | flush_events(s); | ||
41 | } | ||
42 | |||
43 | +static void i440fx_fuzz_qos(QTestState *s, | ||
44 | + const unsigned char *Data, | ||
45 | + size_t Size) | ||
46 | +{ | ||
47 | + static QPCIBus *bus; | ||
41 | + | 48 | + |
42 | + def tearDown(self): | 49 | + if (!bus) { |
43 | + self.vm.shutdown() | 50 | + bus = qpci_new_pc(s, fuzz_qos_alloc); |
51 | + } | ||
44 | + | 52 | + |
45 | + def test_removable_media(self): | 53 | + pciconfig_fuzz_qos(s, bus, Data, Size); |
46 | + # Add a couple of dummy nodes named cd0 and cd1 | 54 | +} |
47 | + result = self.vm.qmp("blockdev-add", driver="null-aio", | ||
48 | + node_name="cd0") | ||
49 | + self.assert_qmp(result, 'return', {}) | ||
50 | + result = self.vm.qmp("blockdev-add", driver="null-aio", | ||
51 | + node_name="cd1") | ||
52 | + self.assert_qmp(result, 'return', {}) | ||
53 | + | 55 | + |
54 | + # Attach a CD drive with cd0 inserted | 56 | static void i440fx_fuzz_qos_fork(QTestState *s, |
55 | + result = self.vm.qmp("device_add", driver="scsi-cd", | 57 | const unsigned char *Data, size_t Size) { |
56 | + id="dev0", drive="cd0") | 58 | if (fork() == 0) { |
57 | + self.assert_qmp(result, 'return', {}) | ||
58 | + | ||
59 | + # Set I/O limits | ||
60 | + args = { "id": "dev0", "iops": 100, "iops_rd": 0, "iops_wr": 0, | ||
61 | + "bps": 50, "bps_rd": 0, "bps_wr": 0 } | ||
62 | + result = self.vm.qmp("block_set_io_throttle", conv_keys=False, **args) | ||
63 | + self.assert_qmp(result, 'return', {}) | ||
64 | + | ||
65 | + # Check that the I/O limits have been set | ||
66 | + result = self.vm.qmp("query-block") | ||
67 | + self.assert_qmp(result, 'return[0]/inserted/iops', 100) | ||
68 | + self.assert_qmp(result, 'return[0]/inserted/bps', 50) | ||
69 | + | ||
70 | + # Now eject cd0 and insert cd1 | ||
71 | + result = self.vm.qmp("blockdev-open-tray", id='dev0') | ||
72 | + self.assert_qmp(result, 'return', {}) | ||
73 | + result = self.vm.qmp("x-blockdev-remove-medium", id='dev0') | ||
74 | + self.assert_qmp(result, 'return', {}) | ||
75 | + result = self.vm.qmp("x-blockdev-insert-medium", id='dev0', node_name='cd1') | ||
76 | + self.assert_qmp(result, 'return', {}) | ||
77 | + | ||
78 | + # Check that the I/O limits are still the same | ||
79 | + result = self.vm.qmp("query-block") | ||
80 | + self.assert_qmp(result, 'return[0]/inserted/iops', 100) | ||
81 | + self.assert_qmp(result, 'return[0]/inserted/bps', 50) | ||
82 | + | ||
83 | + # Eject cd1 | ||
84 | + result = self.vm.qmp("x-blockdev-remove-medium", id='dev0') | ||
85 | + self.assert_qmp(result, 'return', {}) | ||
86 | + | ||
87 | + # Check that we can't set limits if the device has no medium | ||
88 | + result = self.vm.qmp("block_set_io_throttle", conv_keys=False, **args) | ||
89 | + self.assert_qmp(result, 'error/class', 'GenericError') | ||
90 | + | ||
91 | + # Remove the CD drive | ||
92 | + result = self.vm.qmp("device_del", id='dev0') | ||
93 | + self.assert_qmp(result, 'return', {}) | ||
94 | + | ||
95 | |||
96 | if __name__ == '__main__': | ||
97 | iotests.main(supported_fmts=["raw"]) | ||
98 | diff --git a/tests/qemu-iotests/093.out b/tests/qemu-iotests/093.out | ||
99 | index XXXXXXX..XXXXXXX 100644 | ||
100 | --- a/tests/qemu-iotests/093.out | ||
101 | +++ b/tests/qemu-iotests/093.out | ||
102 | @@ -XXX,XX +XXX,XX @@ | ||
103 | -....... | ||
104 | +........ | ||
105 | ---------------------------------------------------------------------- | ||
106 | -Ran 7 tests | ||
107 | +Ran 8 tests | ||
108 | |||
109 | OK | ||
110 | -- | 59 | -- |
111 | 2.13.6 | 60 | 2.25.3 |
112 | 61 | ||
113 | diff view generated by jsdifflib |
1 | From: Zhengui <lizhengui@huawei.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | In blk_remove_bs, all I/O should be completed before removing throttle | 3 | Extract generic ioport_fuzz_qtest() method from |
4 | timers. If there has inflight I/O, removing throttle timers here will | 4 | i440fx_fuzz_qtest(). This will help to write tests |
5 | cause the inflight I/O never return. | 5 | not specific to the i440FX controller. |
6 | This patch add bdrv_drained_begin before throttle_timers_detach_aio_context | ||
7 | to let all I/O completed before removing throttle timers. | ||
8 | 6 | ||
9 | [Moved declaration of bs as suggested by Alberto Garcia | 7 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
10 | <berto@igalia.com>. | 8 | Message-id: 20200514143433.18569-7-philmd@redhat.com |
11 | --Stefan] | ||
12 | |||
13 | Signed-off-by: Zhengui <lizhengui@huawei.com> | ||
14 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
15 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
16 | Message-id: 1508564040-120700-1-git-send-email-lizhengui@huawei.com | ||
17 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 9 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
18 | --- | 10 | --- |
19 | block/block-backend.c | 4 ++++ | 11 | tests/qtest/fuzz/i440fx_fuzz.c | 11 +++++++++-- |
20 | 1 file changed, 4 insertions(+) | 12 | 1 file changed, 9 insertions(+), 2 deletions(-) |
21 | 13 | ||
22 | diff --git a/block/block-backend.c b/block/block-backend.c | 14 | diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c |
23 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
24 | --- a/block/block-backend.c | 16 | --- a/tests/qtest/fuzz/i440fx_fuzz.c |
25 | +++ b/block/block-backend.c | 17 | +++ b/tests/qtest/fuzz/i440fx_fuzz.c |
26 | @@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public) | 18 | @@ -XXX,XX +XXX,XX @@ enum action_id { |
27 | */ | 19 | ACTION_MAX |
28 | void blk_remove_bs(BlockBackend *blk) | 20 | }; |
29 | { | 21 | |
30 | + BlockDriverState *bs; | 22 | -static void i440fx_fuzz_qtest(QTestState *s, |
31 | ThrottleTimers *tt; | 23 | +static void ioport_fuzz_qtest(QTestState *s, |
32 | 24 | const unsigned char *Data, size_t Size) { | |
33 | notifier_list_notify(&blk->remove_bs_notifiers, blk); | 25 | /* |
34 | if (blk->public.throttle_group_member.throttle_state) { | 26 | * loop over the Data, breaking it up into actions. each action has an |
35 | tt = &blk->public.throttle_group_member.throttle_timers; | 27 | @@ -XXX,XX +XXX,XX @@ static void i440fx_fuzz_qtest(QTestState *s, |
36 | + bs = blk_bs(blk); | 28 | flush_events(s); |
37 | + bdrv_drained_begin(bs); | 29 | } |
38 | throttle_timers_detach_aio_context(tt); | 30 | |
39 | + bdrv_drained_end(bs); | 31 | +static void i440fx_fuzz_qtest(QTestState *s, |
40 | } | 32 | + const unsigned char *Data, |
41 | 33 | + size_t Size) | |
42 | blk_update_root_state(blk); | 34 | +{ |
35 | + ioport_fuzz_qtest(s, Data, Size); | ||
36 | +} | ||
37 | + | ||
38 | static void pciconfig_fuzz_qos(QTestState *s, QPCIBus *bus, | ||
39 | const unsigned char *Data, size_t Size) { | ||
40 | /* | ||
41 | - * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the | ||
42 | + * Same as ioport_fuzz_qtest, but using QOS. devfn is incorporated into the | ||
43 | * value written over Port IO | ||
44 | */ | ||
45 | struct { | ||
43 | -- | 46 | -- |
44 | 2.13.6 | 47 | 2.25.3 |
45 | 48 | ||
46 | diff view generated by jsdifflib |
1 | From: Alberto Garcia <berto@igalia.com> | 1 | The io_uring file descriptor monitoring implementation has an internal |
---|---|---|---|
2 | list of fd handlers that are pending submission to io_uring. | ||
3 | fdmon_io_uring_destroy() deletes all fd handlers on the list. | ||
2 | 4 | ||
3 | When you set I/O limits using block_set_io_throttle or the command | 5 | Don't delete fd handlers directly in fdmon_io_uring_destroy() for two |
4 | line throttling.* options they are kept in the BlockBackend regardless | 6 | reasons: |
5 | of whether a BlockDriverState is attached to the backend or not. | 7 | 1. This duplicates the aio-posix.c AioHandler deletion code and could |
8 | become outdated if the struct changes. | ||
9 | 2. Only handlers with the FDMON_IO_URING_REMOVE flag set are safe to | ||
10 | remove. If the flag is not set then something still has a pointer to | ||
11 | the fd handler. Let aio-posix.c and its user worry about that. In | ||
12 | practice this isn't an issue because fdmon_io_uring_destroy() is only | ||
13 | called when shutting down so all users have removed their fd | ||
14 | handlers, but the next patch will need this! | ||
6 | 15 | ||
7 | Therefore when removing the limits using blk_io_limits_disable() we | 16 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
8 | need to check if there's a BDS before attempting to drain it, else it | 17 | Tested-by: Oleksandr Natalenko <oleksandr@redhat.com> |
9 | will crash QEMU. This can be reproduced very easily using HMP: | 18 | Message-id: 20200511183630.279750-2-stefanha@redhat.com |
10 | |||
11 | (qemu) drive_add 0 if=none,throttling.iops-total=5000 | ||
12 | (qemu) drive_del none0 | ||
13 | |||
14 | Reported-by: sochin jiang <sochin.jiang@huawei.com> | ||
15 | Signed-off-by: Alberto Garcia <berto@igalia.com> | ||
16 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
17 | Message-id: 0d3a67ce8d948bb33e08672564714dcfb76a3d8c.1510339534.git.berto@igalia.com | ||
18 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 19 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
19 | --- | 20 | --- |
20 | block/block-backend.c | 14 ++++++++++---- | 21 | util/aio-posix.c | 1 + |
21 | 1 file changed, 10 insertions(+), 4 deletions(-) | 22 | util/fdmon-io_uring.c | 13 ++++++++++--- |
23 | 2 files changed, 11 insertions(+), 3 deletions(-) | ||
22 | 24 | ||
23 | diff --git a/block/block-backend.c b/block/block-backend.c | 25 | diff --git a/util/aio-posix.c b/util/aio-posix.c |
24 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/block/block-backend.c | 27 | --- a/util/aio-posix.c |
26 | +++ b/block/block-backend.c | 28 | +++ b/util/aio-posix.c |
27 | @@ -XXX,XX +XXX,XX @@ void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg) | 29 | @@ -XXX,XX +XXX,XX @@ void aio_context_destroy(AioContext *ctx) |
28 | |||
29 | void blk_io_limits_disable(BlockBackend *blk) | ||
30 | { | 30 | { |
31 | - assert(blk->public.throttle_group_member.throttle_state); | 31 | fdmon_io_uring_destroy(ctx); |
32 | - bdrv_drained_begin(blk_bs(blk)); | 32 | fdmon_epoll_disable(ctx); |
33 | - throttle_group_unregister_tgm(&blk->public.throttle_group_member); | 33 | + aio_free_deleted_handlers(ctx); |
34 | - bdrv_drained_end(blk_bs(blk)); | ||
35 | + BlockDriverState *bs = blk_bs(blk); | ||
36 | + ThrottleGroupMember *tgm = &blk->public.throttle_group_member; | ||
37 | + assert(tgm->throttle_state); | ||
38 | + if (bs) { | ||
39 | + bdrv_drained_begin(bs); | ||
40 | + } | ||
41 | + throttle_group_unregister_tgm(tgm); | ||
42 | + if (bs) { | ||
43 | + bdrv_drained_end(bs); | ||
44 | + } | ||
45 | } | 34 | } |
46 | 35 | ||
47 | /* should be called before blk_set_io_limits if a limit is set */ | 36 | void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, |
37 | diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/util/fdmon-io_uring.c | ||
40 | +++ b/util/fdmon-io_uring.c | ||
41 | @@ -XXX,XX +XXX,XX @@ void fdmon_io_uring_destroy(AioContext *ctx) | ||
42 | |||
43 | io_uring_queue_exit(&ctx->fdmon_io_uring); | ||
44 | |||
45 | - /* No need to submit these anymore, just free them. */ | ||
46 | + /* Move handlers due to be removed onto the deleted list */ | ||
47 | while ((node = QSLIST_FIRST_RCU(&ctx->submit_list))) { | ||
48 | + unsigned flags = atomic_fetch_and(&node->flags, | ||
49 | + ~(FDMON_IO_URING_PENDING | | ||
50 | + FDMON_IO_URING_ADD | | ||
51 | + FDMON_IO_URING_REMOVE)); | ||
52 | + | ||
53 | + if (flags & FDMON_IO_URING_REMOVE) { | ||
54 | + QLIST_INSERT_HEAD_RCU(&ctx->deleted_aio_handlers, node, node_deleted); | ||
55 | + } | ||
56 | + | ||
57 | QSLIST_REMOVE_HEAD_RCU(&ctx->submit_list, node_submitted); | ||
58 | - QLIST_REMOVE(node, node); | ||
59 | - g_free(node); | ||
60 | } | ||
61 | |||
62 | ctx->fdmon_ops = &fdmon_poll_ops; | ||
48 | -- | 63 | -- |
49 | 2.13.6 | 64 | 2.25.3 |
50 | 65 | ||
51 | diff view generated by jsdifflib |
1 | I/O requests hang after stop/cont commands at least since QEMU 2.10.0 | 1 | The glib event loop does not call fdmon_io_uring_wait() so fd handlers |
---|---|---|---|
2 | with -drive iops=100: | 2 | waiting to be submitted build up in the list. There is no benefit is |
3 | using io_uring when the glib GSource is being used, so disable it | ||
4 | instead of implementing a more complex fix. | ||
3 | 5 | ||
4 | (guest)$ dd if=/dev/zero of=/dev/vdb oflag=direct count=1000 | 6 | This fixes a memory leak where AioHandlers would build up and increasing |
5 | (qemu) stop | 7 | amounts of CPU time were spent iterating them in aio_pending(). The |
6 | (qemu) cont | 8 | symptom is that guests become slow when QEMU is built with io_uring |
7 | ...I/O is stuck... | 9 | support. |
8 | 10 | ||
9 | This happens because blk_set_aio_context() detaches the ThrottleState | 11 | Buglink: https://bugs.launchpad.net/qemu/+bug/1877716 |
10 | while requests may still be in flight: | 12 | Fixes: 73fd282e7b6dd4e4ea1c3bbb3d302c8db51e4ccf ("aio-posix: add io_uring fd monitoring implementation") |
11 | |||
12 | if (tgm->throttle_state) { | ||
13 | throttle_group_detach_aio_context(tgm); | ||
14 | throttle_group_attach_aio_context(tgm, new_context); | ||
15 | } | ||
16 | |||
17 | This patch encloses the detach/attach calls in a drained region so no | ||
18 | I/O request is left hanging. Also add assertions so we don't make the | ||
19 | same mistake again in the future. | ||
20 | |||
21 | Reported-by: Yongxue Hong <yhong@redhat.com> | ||
22 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 13 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
23 | Reviewed-by: Alberto Garcia <berto@igalia.com> | 14 | Tested-by: Oleksandr Natalenko <oleksandr@redhat.com> |
24 | Message-id: 20171110151934.16883-1-stefanha@redhat.com | 15 | Message-id: 20200511183630.279750-3-stefanha@redhat.com |
25 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 16 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
26 | --- | 17 | --- |
27 | block/block-backend.c | 2 ++ | 18 | include/block/aio.h | 3 +++ |
28 | block/throttle-groups.c | 6 ++++++ | 19 | util/aio-posix.c | 12 ++++++++++++ |
29 | 2 files changed, 8 insertions(+) | 20 | util/aio-win32.c | 4 ++++ |
21 | util/async.c | 1 + | ||
22 | 4 files changed, 20 insertions(+) | ||
30 | 23 | ||
31 | diff --git a/block/block-backend.c b/block/block-backend.c | 24 | diff --git a/include/block/aio.h b/include/block/aio.h |
32 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
33 | --- a/block/block-backend.c | 26 | --- a/include/block/aio.h |
34 | +++ b/block/block-backend.c | 27 | +++ b/include/block/aio.h |
35 | @@ -XXX,XX +XXX,XX @@ void blk_set_aio_context(BlockBackend *blk, AioContext *new_context) | 28 | @@ -XXX,XX +XXX,XX @@ void aio_context_setup(AioContext *ctx); |
36 | 29 | */ | |
37 | if (bs) { | 30 | void aio_context_destroy(AioContext *ctx); |
38 | if (tgm->throttle_state) { | 31 | |
39 | + bdrv_drained_begin(bs); | 32 | +/* Used internally, do not call outside AioContext code */ |
40 | throttle_group_detach_aio_context(tgm); | 33 | +void aio_context_use_g_source(AioContext *ctx); |
41 | throttle_group_attach_aio_context(tgm, new_context); | 34 | + |
42 | + bdrv_drained_end(bs); | 35 | /** |
43 | } | 36 | * aio_context_set_poll_params: |
44 | bdrv_set_aio_context(bs, new_context); | 37 | * @ctx: the aio context |
45 | } | 38 | diff --git a/util/aio-posix.c b/util/aio-posix.c |
46 | diff --git a/block/throttle-groups.c b/block/throttle-groups.c | ||
47 | index XXXXXXX..XXXXXXX 100644 | 39 | index XXXXXXX..XXXXXXX 100644 |
48 | --- a/block/throttle-groups.c | 40 | --- a/util/aio-posix.c |
49 | +++ b/block/throttle-groups.c | 41 | +++ b/util/aio-posix.c |
50 | @@ -XXX,XX +XXX,XX @@ void throttle_group_attach_aio_context(ThrottleGroupMember *tgm, | 42 | @@ -XXX,XX +XXX,XX @@ void aio_context_destroy(AioContext *ctx) |
51 | void throttle_group_detach_aio_context(ThrottleGroupMember *tgm) | 43 | aio_free_deleted_handlers(ctx); |
44 | } | ||
45 | |||
46 | +void aio_context_use_g_source(AioContext *ctx) | ||
47 | +{ | ||
48 | + /* | ||
49 | + * Disable io_uring when the glib main loop is used because it doesn't | ||
50 | + * support mixed glib/aio_poll() usage. It relies on aio_poll() being | ||
51 | + * called regularly so that changes to the monitored file descriptors are | ||
52 | + * submitted, otherwise a list of pending fd handlers builds up. | ||
53 | + */ | ||
54 | + fdmon_io_uring_destroy(ctx); | ||
55 | + aio_free_deleted_handlers(ctx); | ||
56 | +} | ||
57 | + | ||
58 | void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, | ||
59 | int64_t grow, int64_t shrink, Error **errp) | ||
52 | { | 60 | { |
53 | ThrottleTimers *tt = &tgm->throttle_timers; | 61 | diff --git a/util/aio-win32.c b/util/aio-win32.c |
62 | index XXXXXXX..XXXXXXX 100644 | ||
63 | --- a/util/aio-win32.c | ||
64 | +++ b/util/aio-win32.c | ||
65 | @@ -XXX,XX +XXX,XX @@ void aio_context_destroy(AioContext *ctx) | ||
66 | { | ||
67 | } | ||
68 | |||
69 | +void aio_context_use_g_source(AioContext *ctx) | ||
70 | +{ | ||
71 | +} | ||
54 | + | 72 | + |
55 | + /* Requests must have been drained */ | 73 | void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, |
56 | + assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0); | 74 | int64_t grow, int64_t shrink, Error **errp) |
57 | + assert(qemu_co_queue_empty(&tgm->throttled_reqs[0])); | 75 | { |
58 | + assert(qemu_co_queue_empty(&tgm->throttled_reqs[1])); | 76 | diff --git a/util/async.c b/util/async.c |
59 | + | 77 | index XXXXXXX..XXXXXXX 100644 |
60 | throttle_timers_detach_aio_context(tt); | 78 | --- a/util/async.c |
61 | tgm->aio_context = NULL; | 79 | +++ b/util/async.c |
80 | @@ -XXX,XX +XXX,XX @@ static GSourceFuncs aio_source_funcs = { | ||
81 | |||
82 | GSource *aio_get_g_source(AioContext *ctx) | ||
83 | { | ||
84 | + aio_context_use_g_source(ctx); | ||
85 | g_source_ref(&ctx->source); | ||
86 | return &ctx->source; | ||
62 | } | 87 | } |
63 | -- | 88 | -- |
64 | 2.13.6 | 89 | 2.25.3 |
65 | 90 | ||
66 | diff view generated by jsdifflib |