Polling when VM is stopped doesn't make real sense, as stopped VM can't handle incoming traffic anyway.
And it's critical for introduction of local TAP migration feature in the next commit: the TAP device will be transferred to the target (open fd will be passed through migration channel), and if we continue polling on source, we may get a package, which we'll never handle on source (already stopped), it will be lost. Better is save this package for target VM to handle. Signed-off-by: Vladimir Sementsov-Ogievskiy <[email protected]> --- net/tap.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/net/tap.c b/net/tap.c index dd0d134875b..51d028d9567 100644 --- a/net/tap.c +++ b/net/tap.c @@ -36,6 +36,7 @@ #include "net/net.h" #include "clients.h" #include "monitor/monitor.h" +#include "system/runstate.h" #include "system/system.h" #include "qapi/error.h" #include "qemu/cutils.h" @@ -92,6 +93,8 @@ struct TAPState { Notifier exit; int queue_index; + bool enable_poll_on_resume; + VMChangeStateEntry *vmstate; }; static void launch_script(const char *setup_script, const char *ifname, @@ -145,10 +148,31 @@ static void tap_update_fd_handler(TAPState *s) static void tap_read_poll(TAPState *s, bool enable) { + if (enable && runstate_check(RUN_STATE_FINISH_MIGRATE)) { + s->enable_poll_on_resume = true; + return; + } s->read_poll = enable; tap_update_fd_handler(s); } +static void tap_vm_state_change(void *opaque, bool running, RunState state) +{ + TAPState *s = opaque; + + if (running) { + if (s->enable_poll_on_resume) { + tap_read_poll(s, true); + s->enable_poll_on_resume = false; + } + } else if (state == RUN_STATE_FINISH_MIGRATE) { + if (s->read_poll) { + s->enable_poll_on_resume = true; + tap_read_poll(s, false); + } + } +} + static void tap_write_poll(TAPState *s, bool enable) { s->write_poll = enable; @@ -379,6 +403,11 @@ static void tap_cleanup(NetClientState *nc) s->exit.notify = NULL; } + if (s->vmstate) { + qemu_del_vm_change_state_handler(s->vmstate); + s->vmstate = NULL; + } + tap_read_poll(s, false); tap_write_poll(s, false); close(s->fd); @@ -818,6 +847,9 @@ static bool net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, int sndbuf = (tap->has_sndbuf && tap->sndbuf) ? MIN(tap->sndbuf, INT_MAX) : INT_MAX; + s->enable_poll_on_resume = false; + s->vmstate = qemu_add_vm_change_state_handler(tap_vm_state_change, s); + if (!tap_set_sndbuf(fd, sndbuf, sndbuf_required ? errp : NULL) && sndbuf_required) { goto failed; -- 2.43.0
