On Tue, Feb 06, 2018 at 07:08:19PM +0800, Wei Wang wrote: > This patch adds a timer to limit the time that host waits for the free > page hints reported by the guest. Users can specify the time in ms via > "free-page-wait-time" command line option. If a user doesn't specify a > time, host waits till the guest finishes reporting all the free page > hints. The policy (wait for all the free page hints to be reported or > use a time limit) is determined by the orchestration layer. > > Signed-off-by: Wei Wang <wei.w.w...@intel.com> > CC: Michael S. Tsirkin <m...@redhat.com>
Looks like an option the migration command should get, as opposed to a device feature. > --- > hw/virtio/virtio-balloon.c | 84 > +++++++++++++++++++++++++++++++++++++- > hw/virtio/virtio-pci.c | 3 ++ > include/hw/virtio/virtio-balloon.h | 4 ++ > 3 files changed, 90 insertions(+), 1 deletion(-) > > diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c > index b424d4e..9ee0de4 100644 > --- a/hw/virtio/virtio-balloon.c > +++ b/hw/virtio/virtio-balloon.c > @@ -207,6 +207,65 @@ static void balloon_stats_set_poll_interval(Object *obj, > Visitor *v, > balloon_stats_change_timer(s, 0); > } > > +static void balloon_free_page_change_timer(VirtIOBalloon *s, int64_t ms) > +{ > + timer_mod(s->free_page_timer, > + qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + ms); > +} > + > +static void balloon_stop_free_page_report(void *opaque) > +{ > + VirtIOBalloon *dev = opaque; > + VirtIODevice *vdev = VIRTIO_DEVICE(dev); > + > + timer_del(dev->free_page_timer); > + timer_free(dev->free_page_timer); > + dev->free_page_timer = NULL; > + > + if (dev->free_page_report_status == FREE_PAGE_REPORT_S_START) { > + dev->host_stop_free_page = true; > + virtio_notify_config(vdev); > + } > +} > + > +static void balloon_free_page_get_wait_time(Object *obj, Visitor *v, > + const char *name, void *opaque, > + Error **errp) > +{ > + VirtIOBalloon *s = opaque; > + > + visit_type_int(v, name, &s->free_page_wait_time, errp); > +} > + > +static void balloon_free_page_set_wait_time(Object *obj, Visitor *v, > + const char *name, void *opaque, > + Error **errp) > +{ > + VirtIOBalloon *s = opaque; > + Error *local_err = NULL; > + int64_t value; > + > + visit_type_int(v, name, &value, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + if (value < 0) { > + error_setg(errp, "free page wait time must be greater than zero"); > + return; > + } > + > + if (value > UINT32_MAX) { > + error_setg(errp, "free page wait time value is too big"); > + return; > + } > + > + s->free_page_wait_time = value; > + g_assert(s->free_page_timer == NULL); > + s->free_page_timer = timer_new_ms(QEMU_CLOCK_REALTIME, > + balloon_stop_free_page_report, s); > +} > + > static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) > { > VirtIOBalloon *s = VIRTIO_BALLOON(vdev); > @@ -330,6 +389,7 @@ static void > virtio_balloon_poll_free_page_hints(VirtIOBalloon *dev) > if (id == dev->free_page_report_cmd_id) { > dev->free_page_report_status = FREE_PAGE_REPORT_S_START; > } else { > + dev->host_stop_free_page = false; > dev->free_page_report_status = FREE_PAGE_REPORT_S_STOP; > break; > } > @@ -385,6 +445,10 @@ static void virtio_balloon_free_page_poll(void *opaque) > virtio_notify_config(vdev); > s->free_page_report_status = FREE_PAGE_REPORT_S_REQUESTED; > > + if (s->free_page_wait_time) { > + balloon_free_page_change_timer(s, s->free_page_wait_time); > + } > + > virtio_balloon_poll_free_page_hints(s); > } > > @@ -395,7 +459,19 @@ static void virtio_balloon_get_config(VirtIODevice > *vdev, uint8_t *config_data) > > config.num_pages = cpu_to_le32(dev->num_pages); > config.actual = cpu_to_le32(dev->actual); > - config.free_page_report_cmd_id = > cpu_to_le32(dev->free_page_report_cmd_id); > + if (dev->host_stop_free_page) { > + /* > + * Host is actively requesting to stop the free page reporting, send > + * the stop sign to the guest. This happens when the migration thread > + * has reached the phase to send pages to the destination while the > + * guest hasn't done the reporting. > + */ > + config.free_page_report_cmd_id = > + VIRTIO_BALLOON_FREE_PAGE_REPORT_STOP_ID; > + } else { > + config.free_page_report_cmd_id = > + > cpu_to_le32(dev->free_page_report_cmd_id); > + } > > trace_virtio_balloon_get_config(config.num_pages, config.actual); > memcpy(config_data, &config, sizeof(struct virtio_balloon_config)); > @@ -539,6 +615,7 @@ static void virtio_balloon_device_realize(DeviceState > *dev, Error **errp) > s->free_page_vq = virtio_add_queue(vdev, VIRTQUEUE_MAX_SIZE, NULL); > s->free_page_report_status = FREE_PAGE_REPORT_S_STOP; > s->free_page_report_cmd_id = VIRTIO_BALLOON_FREE_PAGE_REPORT_STOP_ID; > + s->host_stop_free_page = false; > } > reset_stats(s); > } > @@ -602,6 +679,11 @@ static void virtio_balloon_instance_init(Object *obj) > balloon_stats_get_poll_interval, > balloon_stats_set_poll_interval, > NULL, s, NULL); > + > + object_property_add(obj, "free-page-wait-time", "int", > + balloon_free_page_get_wait_time, > + balloon_free_page_set_wait_time, > + NULL, s, NULL); > } > > static const VMStateDescription vmstate_virtio_balloon = { > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c > index 6c75cca..3345104 100644 > --- a/hw/virtio/virtio-pci.c > +++ b/hw/virtio/virtio-pci.c > @@ -2250,6 +2250,9 @@ static void virtio_balloon_pci_instance_init(Object > *obj) > object_property_add_alias(obj, "guest-stats-polling-interval", > OBJECT(&dev->vdev), > "guest-stats-polling-interval", &error_abort); > + object_property_add_alias(obj, "free-page-wait-time", > + OBJECT(&dev->vdev), > + "free-page-wait-time", &error_abort); > } > > static const TypeInfo virtio_balloon_pci_info = { > diff --git a/include/hw/virtio/virtio-balloon.h > b/include/hw/virtio/virtio-balloon.h > index 11b4e01..c16855b 100644 > --- a/include/hw/virtio/virtio-balloon.h > +++ b/include/hw/virtio/virtio-balloon.h > @@ -40,6 +40,8 @@ enum virtio_balloon_free_page_report_status { > typedef struct VirtIOBalloon { > VirtIODevice parent_obj; > VirtQueue *ivq, *dvq, *svq, *free_page_vq; > + /* Host is requesting the guest to stop free page reporting */ > + bool host_stop_free_page; > uint32_t free_page_report_status; > uint32_t num_pages; > uint32_t actual; > @@ -49,8 +51,10 @@ typedef struct VirtIOBalloon { > VirtQueueElement *stats_vq_elem; > size_t stats_vq_offset; > QEMUTimer *stats_timer; > + QEMUTimer *free_page_timer; > int64_t stats_last_update; > int64_t stats_poll_interval; > + int64_t free_page_wait_time; > uint32_t host_features; > } VirtIOBalloon; > > -- > 1.8.3.1