vmnet: stop recieving events when VM is stopped
When the VM is stopped using the HMP command "stop", soon the handler will stop reading from the vmnet interface. This causes a flood of `VMNET_INTERFACE_PACKETS_AVAILABLE` events to arrive and puts the host CPU at 100%. We fix this by removing the event handler from vmnet when the VM is no longer in a running state and restore it when we return to a running state. Signed-off-by: Joelle van Dyne <j@getutm.app> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
0c65ef4fbb
commit
993f71ee33
@ -17,6 +17,7 @@
|
|||||||
#include "clients.h"
|
#include "clients.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
#include "sysemu/runstate.h"
|
||||||
|
|
||||||
#include <vmnet/vmnet.h>
|
#include <vmnet/vmnet.h>
|
||||||
#include <dispatch/dispatch.h>
|
#include <dispatch/dispatch.h>
|
||||||
@ -242,6 +243,35 @@ static void vmnet_bufs_init(VmnetState *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on state change to un-register/re-register handlers
|
||||||
|
*/
|
||||||
|
static void vmnet_vm_state_change_cb(void *opaque, bool running, RunState state)
|
||||||
|
{
|
||||||
|
VmnetState *s = opaque;
|
||||||
|
|
||||||
|
if (running) {
|
||||||
|
vmnet_interface_set_event_callback(
|
||||||
|
s->vmnet_if,
|
||||||
|
VMNET_INTERFACE_PACKETS_AVAILABLE,
|
||||||
|
s->if_queue,
|
||||||
|
^(interface_event_t event_id, xpc_object_t event) {
|
||||||
|
assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
|
||||||
|
/*
|
||||||
|
* This function is being called from a non qemu thread, so
|
||||||
|
* we only schedule a BH, and do the rest of the io completion
|
||||||
|
* handling from vmnet_send_bh() which runs in a qemu context.
|
||||||
|
*/
|
||||||
|
qemu_bh_schedule(s->send_bh);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
vmnet_interface_set_event_callback(
|
||||||
|
s->vmnet_if,
|
||||||
|
VMNET_INTERFACE_PACKETS_AVAILABLE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int vmnet_if_create(NetClientState *nc,
|
int vmnet_if_create(NetClientState *nc,
|
||||||
xpc_object_t if_desc,
|
xpc_object_t if_desc,
|
||||||
@ -329,19 +359,9 @@ int vmnet_if_create(NetClientState *nc,
|
|||||||
s->packets_send_current_pos = 0;
|
s->packets_send_current_pos = 0;
|
||||||
s->packets_send_end_pos = 0;
|
s->packets_send_end_pos = 0;
|
||||||
|
|
||||||
vmnet_interface_set_event_callback(
|
vmnet_vm_state_change_cb(s, 1, RUN_STATE_RUNNING);
|
||||||
s->vmnet_if,
|
|
||||||
VMNET_INTERFACE_PACKETS_AVAILABLE,
|
s->change = qemu_add_vm_change_state_handler(vmnet_vm_state_change_cb, s);
|
||||||
s->if_queue,
|
|
||||||
^(interface_event_t event_id, xpc_object_t event) {
|
|
||||||
assert(event_id == VMNET_INTERFACE_PACKETS_AVAILABLE);
|
|
||||||
/*
|
|
||||||
* This function is being called from a non qemu thread, so
|
|
||||||
* we only schedule a BH, and do the rest of the io completion
|
|
||||||
* handling from vmnet_send_bh() which runs in a qemu context.
|
|
||||||
*/
|
|
||||||
qemu_bh_schedule(s->send_bh);
|
|
||||||
});
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -356,6 +376,8 @@ void vmnet_cleanup_common(NetClientState *nc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vmnet_vm_state_change_cb(s, 0, RUN_STATE_SHUTDOWN);
|
||||||
|
qemu_del_vm_change_state_handler(s->change);
|
||||||
if_stopped_sem = dispatch_semaphore_create(0);
|
if_stopped_sem = dispatch_semaphore_create(0);
|
||||||
vmnet_stop_interface(
|
vmnet_stop_interface(
|
||||||
s->vmnet_if,
|
s->vmnet_if,
|
||||||
|
@ -45,6 +45,8 @@ typedef struct VmnetState {
|
|||||||
int packets_send_end_pos;
|
int packets_send_end_pos;
|
||||||
|
|
||||||
struct iovec iov_buf[VMNET_PACKETS_LIMIT];
|
struct iovec iov_buf[VMNET_PACKETS_LIMIT];
|
||||||
|
|
||||||
|
VMChangeStateEntry *change;
|
||||||
} VmnetState;
|
} VmnetState;
|
||||||
|
|
||||||
const char *vmnet_status_map_str(vmnet_return_t status);
|
const char *vmnet_status_map_str(vmnet_return_t status);
|
||||||
|
Loading…
Reference in New Issue
Block a user