1 | In vhost-user protocol we have VHOST_USER_BACKEND_CONFIG_CHANGE_MSG, | 1 | v4: |
---|---|---|---|
2 | which backend may send to notify Qemu, that we should re-read the | 2 | Fixes 01-02 from v3 are already merged. |
3 | config, and notify the guest. | 3 | 02: new, split out from 03 |
4 | 03: refacting vhost_user_blk_handle_config_change() split out to 02 | ||
5 | drop current_run_state_str() helper | ||
6 | some rewordings (Markus) | ||
4 | 7 | ||
5 | Still that's not always convenient: backend may not support this | 8 | Vladimir Sementsov-Ogievskiy (3): |
6 | message. Also, having QMP command to force config sync is more reliable | 9 | qdev-monitor: add option to report GenericError from find_device_state |
7 | than waiting for notification from external program. It also may be | 10 | vhost-user-blk: split vhost_user_blk_sync_config() |
8 | helpful for debug/restore: if we have changed disk size, but guest | 11 | qapi: introduce device-sync-config |
9 | doesn't see that, it's good to have a separate QMP command to trigger | ||
10 | resync of the config. | ||
11 | 12 | ||
12 | So, the series proposes two experimental APIs: | 13 | hw/block/vhost-user-blk.c | 27 ++++++++++++----- |
13 | 14 | hw/virtio/virtio-pci.c | 9 ++++++ | |
14 | 1. x-device-sync-config command, to trigger config synchronization | 15 | include/hw/qdev-core.h | 3 ++ |
15 | 16 | qapi/qdev.json | 23 ++++++++++++++ | |
16 | 2. X_CONFIG_READ event, which notify management tool that guest read the | 17 | system/qdev-monitor.c | 63 ++++++++++++++++++++++++++++++++++++--- |
17 | updated config. Of course, that can't guarantee that the guest correctly | 18 | 5 files changed, 114 insertions(+), 11 deletions(-) |
18 | handled the updated config, but it's still better than nothing: for sure | ||
19 | guest will not show new disk size until it read the updated config. So, | ||
20 | management tool may wait for this event to report success to the user. | ||
21 | |||
22 | |||
23 | The series is based on "[PATCH v8 0/4] pci hotplug tracking": it doesn't | ||
24 | depend on it, but just modify same files, so I just to avoid extra | ||
25 | conflicts. | ||
26 | Based-on: <20231005092926.56231-1-vsementsov@yandex-team.ru> | ||
27 | |||
28 | Vladimir Sementsov-Ogievskiy (4): | ||
29 | vhost-user-blk: simplify and fix vhost_user_blk_handle_config_change | ||
30 | qapi: introduce device-sync-config | ||
31 | qapi: device-sync-config: check runstate | ||
32 | qapi: introduce CONFIG_READ event | ||
33 | |||
34 | hw/block/vhost-user-blk.c | 32 ++++++++++++++--------- | ||
35 | hw/virtio/virtio-pci.c | 18 +++++++++++++ | ||
36 | include/hw/qdev-core.h | 3 +++ | ||
37 | include/monitor/qdev.h | 1 + | ||
38 | include/sysemu/runstate.h | 1 + | ||
39 | monitor/monitor.c | 1 + | ||
40 | qapi/qdev.json | 36 ++++++++++++++++++++++++++ | ||
41 | softmmu/qdev-monitor.c | 53 +++++++++++++++++++++++++++++++++++++++ | ||
42 | softmmu/runstate.c | 5 ++++ | ||
43 | 9 files changed, 138 insertions(+), 12 deletions(-) | ||
44 | 19 | ||
45 | -- | 20 | -- |
46 | 2.34.1 | 21 | 2.34.1 | diff view generated by jsdifflib |
1 | Command result is racy if allow it during migration. Let's allow the | 1 | Here we just prepare for the following patch, making possible to report |
---|---|---|---|
2 | sync only in RUNNING state. | 2 | GenericError as recommended. |
3 | |||
4 | This patch doesn't aim to prevent further use of DeviceNotFound by | ||
5 | future interfaces: | ||
6 | |||
7 | - find_device_state() is used in blk_by_qdev_id() and qmp_get_blk() | ||
8 | functions, which may lead to spread of DeviceNotFound anyway | ||
9 | - also, nothing prevent simply copy-pasting find_device_state() calls | ||
10 | with false argument | ||
3 | 11 | ||
4 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | 12 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> |
5 | --- | 13 | --- |
6 | include/sysemu/runstate.h | 1 + | 14 | system/qdev-monitor.c | 15 +++++++++++---- |
7 | softmmu/qdev-monitor.c | 27 ++++++++++++++++++++++++++- | 15 | 1 file changed, 11 insertions(+), 4 deletions(-) |
8 | softmmu/runstate.c | 5 +++++ | ||
9 | 3 files changed, 32 insertions(+), 1 deletion(-) | ||
10 | 16 | ||
11 | diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h | 17 | diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c |
12 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/include/sysemu/runstate.h | 19 | --- a/system/qdev-monitor.c |
14 | +++ b/include/sysemu/runstate.h | 20 | +++ b/system/qdev-monitor.c |
15 | @@ -XXX,XX +XXX,XX @@ | 21 | @@ -XXX,XX +XXX,XX @@ void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp) |
16 | #include "qemu/notify.h" | 22 | object_unref(OBJECT(dev)); |
17 | 23 | } | |
18 | bool runstate_check(RunState state); | 24 | |
19 | +const char *current_run_state_str(void); | 25 | -static DeviceState *find_device_state(const char *id, Error **errp) |
20 | void runstate_set(RunState new_state); | 26 | +/* |
21 | RunState runstate_get(void); | 27 | + * Note that creating new APIs using error classes other than GenericError is |
22 | bool runstate_is_running(void); | 28 | + * not recommended. Set use_generic_error=true for new interfaces. |
23 | diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c | 29 | + */ |
24 | index XXXXXXX..XXXXXXX 100644 | 30 | +static DeviceState *find_device_state(const char *id, bool use_generic_error, |
25 | --- a/softmmu/qdev-monitor.c | 31 | + Error **errp) |
26 | +++ b/softmmu/qdev-monitor.c | 32 | { |
27 | @@ -XXX,XX +XXX,XX @@ | 33 | Object *obj = object_resolve_path_at(qdev_get_peripheral(), id); |
28 | #include "monitor/monitor.h" | 34 | DeviceState *dev; |
29 | #include "monitor/qdev.h" | 35 | |
30 | #include "sysemu/arch_init.h" | 36 | if (!obj) { |
31 | +#include "sysemu/runstate.h" | 37 | - error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, |
32 | #include "qapi/error.h" | 38 | + error_set(errp, |
33 | #include "qapi/qapi-commands-qdev.h" | 39 | + (use_generic_error ? |
34 | #include "qapi/qapi-events-qdev.h" | 40 | + ERROR_CLASS_GENERIC_ERROR : ERROR_CLASS_DEVICE_NOT_FOUND), |
35 | @@ -XXX,XX +XXX,XX @@ int qdev_sync_config(DeviceState *dev, Error **errp) | 41 | "Device '%s' not found", id); |
36 | 42 | return NULL; | |
37 | void qmp_x_device_sync_config(const char *id, Error **errp) | 43 | } |
44 | @@ -XXX,XX +XXX,XX @@ void qdev_unplug(DeviceState *dev, Error **errp) | ||
45 | |||
46 | void qmp_device_del(const char *id, Error **errp) | ||
38 | { | 47 | { |
39 | - DeviceState *dev = find_device_state(id, errp); | 48 | - DeviceState *dev = find_device_state(id, errp); |
40 | + MigrationState *s = migrate_get_current(); | 49 | + DeviceState *dev = find_device_state(id, false, errp); |
41 | + DeviceState *dev; | 50 | if (dev != NULL) { |
42 | + | 51 | if (dev->pending_deleted_event && |
43 | + /* | 52 | (dev->pending_deleted_expires_ms == 0 || |
44 | + * During migration there is a race between syncing`config and migrating it, | 53 | @@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_qdev_id(const char *id, Error **errp) |
45 | + * so let's just not allow it. | 54 | |
46 | + * | 55 | GLOBAL_STATE_CODE(); |
47 | + * Moreover, let's not rely on setting up interrupts in paused state, which | 56 | |
48 | + * may be a part of migration process. | 57 | - dev = find_device_state(id, errp); |
49 | + */ | 58 | + dev = find_device_state(id, false, errp); |
50 | + | 59 | if (dev == NULL) { |
51 | + if (migration_is_running(s->state)) { | 60 | return NULL; |
52 | + error_setg(errp, "Config synchronization is not allowed " | ||
53 | + "during migration."); | ||
54 | + return; | ||
55 | + } | ||
56 | + | ||
57 | + if (!runstate_is_running()) { | ||
58 | + error_setg(errp, "Config synchronization allowed only in '%s' state, " | ||
59 | + "current state is '%s'", RunState_str(RUN_STATE_RUNNING), | ||
60 | + current_run_state_str()); | ||
61 | + return; | ||
62 | + } | ||
63 | + | ||
64 | + dev = find_device_state(id, errp); | ||
65 | if (!dev) { | ||
66 | return; | ||
67 | } | 61 | } |
68 | diff --git a/softmmu/runstate.c b/softmmu/runstate.c | ||
69 | index XXXXXXX..XXXXXXX 100644 | ||
70 | --- a/softmmu/runstate.c | ||
71 | +++ b/softmmu/runstate.c | ||
72 | @@ -XXX,XX +XXX,XX @@ bool runstate_check(RunState state) | ||
73 | return current_run_state == state; | ||
74 | } | ||
75 | |||
76 | +const char *current_run_state_str(void) | ||
77 | +{ | ||
78 | + return RunState_str(current_run_state); | ||
79 | +} | ||
80 | + | ||
81 | static void runstate_init(void) | ||
82 | { | ||
83 | const RunStateTransition *p; | ||
84 | -- | 62 | -- |
85 | 2.34.1 | 63 | 2.34.1 | diff view generated by jsdifflib |
1 | Let's not care about what was changed and update the whole config, | 1 | Split vhost_user_blk_sync_config() out from |
---|---|---|---|
2 | reasons: | 2 | vhost_user_blk_handle_config_change(), to be reused in the following |
3 | 3 | commit. | |
4 | 1. config->geometry should be updated together with capacity, so we fix | ||
5 | a bug. | ||
6 | |||
7 | 2. Vhost-user protocol doesn't say anything about config change | ||
8 | limitation. Silent ignore of changes doesn't seem to be correct. | ||
9 | |||
10 | 3. vhost-user-vsock reads the whole config | ||
11 | |||
12 | 4. on realize we don't do any checks on retrieved config, so no reason | ||
13 | to care here | ||
14 | |||
15 | Also, let's notify guest unconditionally: | ||
16 | |||
17 | 1. So does vhost-user-vsock | ||
18 | |||
19 | 2. We are going to reuse the functionality in new cases when we do want | ||
20 | to notify the guest unconditionally. So, no reason to create extra | ||
21 | branches in the logic. | ||
22 | 4 | ||
23 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | 5 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> |
24 | --- | 6 | --- |
25 | hw/block/vhost-user-blk.c | 11 +++-------- | 7 | hw/block/vhost-user-blk.c | 26 +++++++++++++++++++------- |
26 | 1 file changed, 3 insertions(+), 8 deletions(-) | 8 | 1 file changed, 19 insertions(+), 7 deletions(-) |
27 | 9 | ||
28 | diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c | 10 | diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c |
29 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
30 | --- a/hw/block/vhost-user-blk.c | 12 | --- a/hw/block/vhost-user-blk.c |
31 | +++ b/hw/block/vhost-user-blk.c | 13 | +++ b/hw/block/vhost-user-blk.c |
32 | @@ -XXX,XX +XXX,XX @@ static void vhost_user_blk_set_config(VirtIODevice *vdev, const uint8_t *config) | 14 | @@ -XXX,XX +XXX,XX @@ static void vhost_user_blk_set_config(VirtIODevice *vdev, const uint8_t *config) |
15 | s->blkcfg.wce = blkcfg->wce; | ||
16 | } | ||
17 | |||
18 | +static int vhost_user_blk_sync_config(DeviceState *dev, Error **errp) | ||
19 | +{ | ||
20 | + int ret; | ||
21 | + VirtIODevice *vdev = VIRTIO_DEVICE(dev); | ||
22 | + VHostUserBlk *s = VHOST_USER_BLK(vdev); | ||
23 | + | ||
24 | + ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg, | ||
25 | + vdev->config_len, errp); | ||
26 | + if (ret < 0) { | ||
27 | + return ret; | ||
28 | + } | ||
29 | + | ||
30 | + memcpy(vdev->config, &s->blkcfg, vdev->config_len); | ||
31 | + virtio_notify_config(vdev); | ||
32 | + | ||
33 | + return 0; | ||
34 | +} | ||
35 | + | ||
33 | static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) | 36 | static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) |
34 | { | 37 | { |
35 | int ret; | 38 | int ret; |
36 | - struct virtio_blk_config blkcfg; | 39 | - VirtIODevice *vdev = dev->vdev; |
37 | VirtIODevice *vdev = dev->vdev; | 40 | - VHostUserBlk *s = VHOST_USER_BLK(dev->vdev); |
38 | VHostUserBlk *s = VHOST_USER_BLK(dev->vdev); | ||
39 | Error *local_err = NULL; | 41 | Error *local_err = NULL; |
40 | @@ -XXX,XX +XXX,XX @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) | 42 | |
43 | if (!dev->started) { | ||
41 | return 0; | 44 | return 0; |
42 | } | 45 | } |
43 | 46 | ||
44 | - ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg, | 47 | - ret = vhost_dev_get_config(dev, (uint8_t *)&s->blkcfg, |
45 | + ret = vhost_dev_get_config(dev, (uint8_t *)&s->blkcfg, | 48 | - vdev->config_len, &local_err); |
46 | vdev->config_len, &local_err); | 49 | + ret = vhost_user_blk_sync_config(DEVICE(dev->vdev), &local_err); |
47 | if (ret < 0) { | 50 | if (ret < 0) { |
48 | error_report_err(local_err); | 51 | error_report_err(local_err); |
49 | return ret; | 52 | return ret; |
50 | } | 53 | } |
51 | 54 | ||
52 | - /* valid for resize only */ | 55 | - memcpy(dev->vdev->config, &s->blkcfg, vdev->config_len); |
53 | - if (blkcfg.capacity != s->blkcfg.capacity) { | 56 | - virtio_notify_config(dev->vdev); |
54 | - s->blkcfg.capacity = blkcfg.capacity; | 57 | - |
55 | - memcpy(dev->vdev->config, &s->blkcfg, vdev->config_len); | ||
56 | - virtio_notify_config(dev->vdev); | ||
57 | - } | ||
58 | + memcpy(dev->vdev->config, &s->blkcfg, vdev->config_len); | ||
59 | + virtio_notify_config(dev->vdev); | ||
60 | |||
61 | return 0; | 58 | return 0; |
62 | } | 59 | } |
60 | |||
63 | -- | 61 | -- |
64 | 2.34.1 | 62 | 2.34.1 | diff view generated by jsdifflib |
1 | Add command to sync config from vhost-user backend to the device. It | 1 | Add command to sync config from vhost-user backend to the device. It |
---|---|---|---|
2 | may be helpful when VHOST_USER_SLAVE_CONFIG_CHANGE_MSG failed or not | 2 | may be helpful when VHOST_USER_SLAVE_CONFIG_CHANGE_MSG failed or not |
3 | triggered interrupt to the guest or just not available (not supported | 3 | triggered interrupt to the guest or just not available (not supported |
4 | by vhost-user server). | 4 | by vhost-user server). |
5 | 5 | ||
6 | Command result is racy if allow it during migration. Let's allow the | ||
7 | sync only in RUNNING state. | ||
8 | |||
6 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | 9 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> |
7 | --- | 10 | --- |
8 | hw/block/vhost-user-blk.c | 27 ++++++++++++++++++++------- | 11 | hw/block/vhost-user-blk.c | 1 + |
9 | hw/virtio/virtio-pci.c | 9 +++++++++ | 12 | hw/virtio/virtio-pci.c | 9 ++++++++ |
10 | include/hw/qdev-core.h | 3 +++ | 13 | include/hw/qdev-core.h | 3 +++ |
11 | qapi/qdev.json | 14 ++++++++++++++ | 14 | qapi/qdev.json | 23 +++++++++++++++++++ |
12 | softmmu/qdev-monitor.c | 23 +++++++++++++++++++++++ | 15 | system/qdev-monitor.c | 48 +++++++++++++++++++++++++++++++++++++++ |
13 | 5 files changed, 69 insertions(+), 7 deletions(-) | 16 | 5 files changed, 84 insertions(+) |
14 | 17 | ||
15 | diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c | 18 | diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c |
16 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/hw/block/vhost-user-blk.c | 20 | --- a/hw/block/vhost-user-blk.c |
18 | +++ b/hw/block/vhost-user-blk.c | 21 | +++ b/hw/block/vhost-user-blk.c |
19 | @@ -XXX,XX +XXX,XX @@ static void vhost_user_blk_set_config(VirtIODevice *vdev, const uint8_t *config) | ||
20 | s->blkcfg.wce = blkcfg->wce; | ||
21 | } | ||
22 | |||
23 | +static int vhost_user_blk_sync_config(DeviceState *dev, Error **errp) | ||
24 | +{ | ||
25 | + int ret; | ||
26 | + VirtIODevice *vdev = VIRTIO_DEVICE(dev); | ||
27 | + VHostUserBlk *s = VHOST_USER_BLK(vdev); | ||
28 | + | ||
29 | + ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg, | ||
30 | + vdev->config_len, errp); | ||
31 | + if (ret < 0) { | ||
32 | + return ret; | ||
33 | + } | ||
34 | + | ||
35 | + memcpy(vdev->config, &s->blkcfg, vdev->config_len); | ||
36 | + virtio_notify_config(vdev); | ||
37 | + | ||
38 | + return 0; | ||
39 | +} | ||
40 | + | ||
41 | static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) | ||
42 | { | ||
43 | int ret; | ||
44 | - VirtIODevice *vdev = dev->vdev; | ||
45 | - VHostUserBlk *s = VHOST_USER_BLK(dev->vdev); | ||
46 | Error *local_err = NULL; | ||
47 | |||
48 | if (!dev->started) { | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | - ret = vhost_dev_get_config(dev, (uint8_t *)&s->blkcfg, | ||
53 | - vdev->config_len, &local_err); | ||
54 | + ret = vhost_user_blk_sync_config(DEVICE(dev->vdev), &local_err); | ||
55 | if (ret < 0) { | ||
56 | error_report_err(local_err); | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | - memcpy(dev->vdev->config, &s->blkcfg, vdev->config_len); | ||
61 | - virtio_notify_config(dev->vdev); | ||
62 | - | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | @@ -XXX,XX +XXX,XX @@ static void vhost_user_blk_class_init(ObjectClass *klass, void *data) | 22 | @@ -XXX,XX +XXX,XX @@ static void vhost_user_blk_class_init(ObjectClass *klass, void *data) |
67 | 23 | ||
68 | device_class_set_props(dc, vhost_user_blk_properties); | 24 | device_class_set_props(dc, vhost_user_blk_properties); |
69 | dc->vmsd = &vmstate_vhost_user_blk; | 25 | dc->vmsd = &vmstate_vhost_user_blk; |
70 | + dc->sync_config = vhost_user_blk_sync_config; | 26 | + dc->sync_config = vhost_user_blk_sync_config; |
... | ... | ||
129 | diff --git a/qapi/qdev.json b/qapi/qdev.json | 85 | diff --git a/qapi/qdev.json b/qapi/qdev.json |
130 | index XXXXXXX..XXXXXXX 100644 | 86 | index XXXXXXX..XXXXXXX 100644 |
131 | --- a/qapi/qdev.json | 87 | --- a/qapi/qdev.json |
132 | +++ b/qapi/qdev.json | 88 | +++ b/qapi/qdev.json |
133 | @@ -XXX,XX +XXX,XX @@ | 89 | @@ -XXX,XX +XXX,XX @@ |
134 | # Since: 8.2 | ||
135 | ## | 90 | ## |
136 | { 'event': 'X_DEVICE_ON', 'data': 'DeviceAndPath' } | 91 | { 'event': 'DEVICE_UNPLUG_GUEST_ERROR', |
92 | 'data': { '*device': 'str', 'path': 'str' } } | ||
137 | + | 93 | + |
138 | +## | 94 | +## |
139 | +# @x-device-sync-config: | 95 | +# @device-sync-config: |
140 | +# | 96 | +# |
141 | +# Sync config from backend to the guest. | 97 | +# Synchronize device configuration from host to guest part. First, |
98 | +# copy the configuration from the host part (backend) to the guest | ||
99 | +# part (frontend). Then notify guest software that device | ||
100 | +# configuration changed. | ||
101 | +# The command may be used to notify the guest about block device | ||
102 | +# capcity change. Currently only vhost-user-blk device supports | ||
103 | +# this. | ||
142 | +# | 104 | +# |
143 | +# @id: the device's ID or QOM path | 105 | +# @id: the device's ID or QOM path |
144 | +# | 106 | +# |
145 | +# Returns: Nothing on success | 107 | +# Features: |
146 | +# If @id is not a valid device, DeviceNotFound | ||
147 | +# | 108 | +# |
148 | +# Since: 8.2 | 109 | +# @unstable: The command is experimental. |
110 | +# | ||
111 | +# Since: 9.1 | ||
149 | +## | 112 | +## |
150 | +{ 'command': 'x-device-sync-config', 'data': {'id': 'str'} } | 113 | +{ 'command': 'device-sync-config', |
151 | diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c | 114 | + 'features': [ 'unstable' ], |
115 | + 'data': {'id': 'str'} } | ||
116 | diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c | ||
152 | index XXXXXXX..XXXXXXX 100644 | 117 | index XXXXXXX..XXXXXXX 100644 |
153 | --- a/softmmu/qdev-monitor.c | 118 | --- a/system/qdev-monitor.c |
154 | +++ b/softmmu/qdev-monitor.c | 119 | +++ b/system/qdev-monitor.c |
155 | @@ -XXX,XX +XXX,XX @@ HotplugInfo *qmp_x_query_hotplug(const char *id, Error **errp) | 120 | @@ -XXX,XX +XXX,XX @@ |
156 | return hotplug_handler_get_state(hotplug_ctrl, dev, errp); | 121 | #include "monitor/monitor.h" |
122 | #include "monitor/qdev.h" | ||
123 | #include "sysemu/arch_init.h" | ||
124 | +#include "sysemu/runstate.h" | ||
125 | #include "qapi/error.h" | ||
126 | #include "qapi/qapi-commands-qdev.h" | ||
127 | #include "qapi/qmp/dispatch.h" | ||
128 | @@ -XXX,XX +XXX,XX @@ void qmp_device_del(const char *id, Error **errp) | ||
129 | } | ||
157 | } | 130 | } |
158 | 131 | ||
159 | +int qdev_sync_config(DeviceState *dev, Error **errp) | 132 | +int qdev_sync_config(DeviceState *dev, Error **errp) |
160 | +{ | 133 | +{ |
161 | + DeviceClass *dc = DEVICE_GET_CLASS(dev); | 134 | + DeviceClass *dc = DEVICE_GET_CLASS(dev); |
... | ... | ||
167 | + } | 140 | + } |
168 | + | 141 | + |
169 | + return dc->sync_config(dev, errp); | 142 | + return dc->sync_config(dev, errp); |
170 | +} | 143 | +} |
171 | + | 144 | + |
172 | +void qmp_x_device_sync_config(const char *id, Error **errp) | 145 | +void qmp_device_sync_config(const char *id, Error **errp) |
173 | +{ | 146 | +{ |
174 | + DeviceState *dev = find_device_state(id, errp); | 147 | + DeviceState *dev; |
148 | + | ||
149 | + /* | ||
150 | + * During migration there is a race between syncing`configuration and | ||
151 | + * migrating it (if migrate first, that target would get outdated version), | ||
152 | + * so let's just not allow it. | ||
153 | + * | ||
154 | + * Moreover, let's not rely on setting up interrupts in paused | ||
155 | + * state, which may be a part of migration process. | ||
156 | + */ | ||
157 | + | ||
158 | + if (migration_is_running()) { | ||
159 | + error_setg(errp, "Config synchronization is not allowed " | ||
160 | + "during migration"); | ||
161 | + return; | ||
162 | + } | ||
163 | + | ||
164 | + if (!runstate_is_running()) { | ||
165 | + error_setg(errp, "Config synchronization allowed only in '%s' state, " | ||
166 | + "current state is '%s'", RunState_str(RUN_STATE_RUNNING), | ||
167 | + RunState_str(runstate_get())); | ||
168 | + return; | ||
169 | + } | ||
170 | + | ||
171 | + dev = find_device_state(id, true, errp); | ||
175 | + if (!dev) { | 172 | + if (!dev) { |
176 | + return; | 173 | + return; |
177 | + } | 174 | + } |
178 | + | 175 | + |
179 | + qdev_sync_config(dev, errp); | 176 | + qdev_sync_config(dev, errp); |
... | ... | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Send a new event when guest reads virtio-pci config after | ||
2 | virtio_notify_config() call. | ||
3 | 1 | ||
4 | That's useful to check that guest fetched modified config, for example | ||
5 | after resizing disk backend. | ||
6 | |||
7 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | ||
8 | --- | ||
9 | hw/virtio/virtio-pci.c | 9 +++++++++ | ||
10 | include/monitor/qdev.h | 1 + | ||
11 | monitor/monitor.c | 1 + | ||
12 | qapi/qdev.json | 22 ++++++++++++++++++++++ | ||
13 | softmmu/qdev-monitor.c | 5 +++++ | ||
14 | 5 files changed, 38 insertions(+) | ||
15 | |||
16 | diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/virtio/virtio-pci.c | ||
19 | +++ b/hw/virtio/virtio-pci.c | ||
20 | @@ -XXX,XX +XXX,XX @@ | ||
21 | #include "hw/boards.h" | ||
22 | #include "hw/virtio/virtio.h" | ||
23 | #include "migration/qemu-file-types.h" | ||
24 | +#include "monitor/qdev.h" | ||
25 | #include "hw/pci/pci.h" | ||
26 | #include "hw/pci/pci_bus.h" | ||
27 | #include "hw/qdev-properties.h" | ||
28 | @@ -XXX,XX +XXX,XX @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr, | ||
29 | } | ||
30 | addr -= config; | ||
31 | |||
32 | + if (vdev->generation > 0) { | ||
33 | + qdev_config_read_event(DEVICE(proxy)); | ||
34 | + } | ||
35 | + | ||
36 | switch (size) { | ||
37 | case 1: | ||
38 | val = virtio_config_readb(vdev, addr); | ||
39 | @@ -XXX,XX +XXX,XX @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, | ||
40 | return UINT64_MAX; | ||
41 | } | ||
42 | |||
43 | + if (vdev->generation > 0) { | ||
44 | + qdev_config_read_event(DEVICE(proxy)); | ||
45 | + } | ||
46 | + | ||
47 | switch (size) { | ||
48 | case 1: | ||
49 | val = virtio_config_modern_readb(vdev, addr); | ||
50 | diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h | ||
51 | index XXXXXXX..XXXXXXX 100644 | ||
52 | --- a/include/monitor/qdev.h | ||
53 | +++ b/include/monitor/qdev.h | ||
54 | @@ -XXX,XX +XXX,XX @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, | ||
55 | const char *qdev_set_id(DeviceState *dev, char *id, Error **errp); | ||
56 | |||
57 | void qdev_hotplug_device_on_event(DeviceState *dev); | ||
58 | +void qdev_config_read_event(DeviceState *dev); | ||
59 | |||
60 | DeviceAndPath *qdev_new_device_and_path(DeviceState *dev); | ||
61 | |||
62 | diff --git a/monitor/monitor.c b/monitor/monitor.c | ||
63 | index XXXXXXX..XXXXXXX 100644 | ||
64 | --- a/monitor/monitor.c | ||
65 | +++ b/monitor/monitor.c | ||
66 | @@ -XXX,XX +XXX,XX @@ static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = { | ||
67 | [QAPI_EVENT_QUORUM_FAILURE] = { 1000 * SCALE_MS }, | ||
68 | [QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS }, | ||
69 | [QAPI_EVENT_MEMORY_DEVICE_SIZE_CHANGE] = { 1000 * SCALE_MS }, | ||
70 | + [QAPI_EVENT_X_CONFIG_READ] = { 300 * SCALE_MS }, | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | diff --git a/qapi/qdev.json b/qapi/qdev.json | ||
75 | index XXXXXXX..XXXXXXX 100644 | ||
76 | --- a/qapi/qdev.json | ||
77 | +++ b/qapi/qdev.json | ||
78 | @@ -XXX,XX +XXX,XX @@ | ||
79 | # Since: 8.2 | ||
80 | ## | ||
81 | { 'command': 'x-device-sync-config', 'data': {'id': 'str'} } | ||
82 | + | ||
83 | +## | ||
84 | +# @X_CONFIG_READ: | ||
85 | +# | ||
86 | +# Emitted whenever guest reads virtio device config after config change. | ||
87 | +# | ||
88 | +# @device: device name | ||
89 | +# | ||
90 | +# @path: device path | ||
91 | +# | ||
92 | +# Since: 5.0.1-24 | ||
93 | +# | ||
94 | +# Example: | ||
95 | +# | ||
96 | +# <- { "event": "X_CONFIG_READ", | ||
97 | +# "data": { "device": "virtio-net-pci-0", | ||
98 | +# "path": "/machine/peripheral/virtio-net-pci-0" }, | ||
99 | +# "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } | ||
100 | +# | ||
101 | +## | ||
102 | +{ 'event': 'X_CONFIG_READ', | ||
103 | + 'data': { '*device': 'str', 'path': 'str' } } | ||
104 | diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c | ||
105 | index XXXXXXX..XXXXXXX 100644 | ||
106 | --- a/softmmu/qdev-monitor.c | ||
107 | +++ b/softmmu/qdev-monitor.c | ||
108 | @@ -XXX,XX +XXX,XX @@ void qdev_hotplug_device_on_event(DeviceState *dev) | ||
109 | dev->device_on_event_sent = true; | ||
110 | qapi_event_send_x_device_on(dev->id, dev->canonical_path); | ||
111 | } | ||
112 | + | ||
113 | +void qdev_config_read_event(DeviceState *dev) | ||
114 | +{ | ||
115 | + qapi_event_send_x_config_read(dev->id, dev->canonical_path); | ||
116 | +} | ||
117 | -- | ||
118 | 2.34.1 | diff view generated by jsdifflib |