mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 15:23:53 -06:00
Introduce VLANClientState::cleanup() (Mark McLoughlin)
We're currently leaking memory and file descriptors on device hot-unplug. Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7150 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
32a8f6ae93
commit
b946a15332
19 changed files with 347 additions and 66 deletions
71
net.c
71
net.c
|
@ -333,6 +333,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
|||
const char *name,
|
||||
IOReadHandler *fd_read,
|
||||
IOCanRWHandler *fd_can_read,
|
||||
NetCleanup *cleanup,
|
||||
void *opaque)
|
||||
{
|
||||
VLANClientState *vc, **pvc;
|
||||
|
@ -344,6 +345,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
|||
vc->name = assign_name(vc, model);
|
||||
vc->fd_read = fd_read;
|
||||
vc->fd_can_read = fd_can_read;
|
||||
vc->cleanup = cleanup;
|
||||
vc->opaque = opaque;
|
||||
vc->vlan = vlan;
|
||||
|
||||
|
@ -362,6 +364,9 @@ void qemu_del_vlan_client(VLANClientState *vc)
|
|||
while (*pvc != NULL)
|
||||
if (*pvc == vc) {
|
||||
*pvc = vc->next;
|
||||
if (vc->cleanup) {
|
||||
vc->cleanup(vc);
|
||||
}
|
||||
free(vc->name);
|
||||
free(vc->model);
|
||||
free(vc);
|
||||
|
@ -521,7 +526,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
|
|||
slirp_init(slirp_restrict, slirp_ip);
|
||||
}
|
||||
slirp_vc = qemu_new_vlan_client(vlan, model, name,
|
||||
slirp_receive, NULL, NULL);
|
||||
slirp_receive, NULL, NULL, NULL);
|
||||
slirp_vc->info_str[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
@ -702,6 +707,8 @@ typedef struct TAPState {
|
|||
char down_script_arg[128];
|
||||
} TAPState;
|
||||
|
||||
static int launch_script(const char *setup_script, const char *ifname, int fd);
|
||||
|
||||
static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov,
|
||||
int iovcnt)
|
||||
{
|
||||
|
@ -748,6 +755,18 @@ static void tap_send(void *opaque)
|
|||
}
|
||||
}
|
||||
|
||||
static void tap_cleanup(VLANClientState *vc)
|
||||
{
|
||||
TAPState *s = vc->opaque;
|
||||
|
||||
if (s->down_script[0])
|
||||
launch_script(s->down_script, s->down_script_arg, s->fd);
|
||||
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
close(s->fd);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
/* fd support */
|
||||
|
||||
static TAPState *net_tap_fd_init(VLANState *vlan,
|
||||
|
@ -759,7 +778,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
|
|||
|
||||
s = qemu_mallocz(sizeof(TAPState));
|
||||
s->fd = fd;
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive,
|
||||
NULL, tap_cleanup, s);
|
||||
s->vc->fd_readv = tap_receive_iov;
|
||||
qemu_set_fd_handler(s->fd, tap_send, NULL, s);
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd);
|
||||
|
@ -1058,6 +1078,14 @@ static void vde_from_qemu(void *opaque, const uint8_t *buf, int size)
|
|||
}
|
||||
}
|
||||
|
||||
static void vde_cleanup(VLANClientState *vc)
|
||||
{
|
||||
VDEState *s = vc->opaque;
|
||||
qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL);
|
||||
vde_close(s->vde);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static int net_vde_init(VLANState *vlan, const char *model,
|
||||
const char *name, const char *sock,
|
||||
int port, const char *group, int mode)
|
||||
|
@ -1078,7 +1106,8 @@ static int net_vde_init(VLANState *vlan, const char *model,
|
|||
free(s);
|
||||
return -1;
|
||||
}
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu,
|
||||
NULL, vde_cleanup, s);
|
||||
qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d",
|
||||
sock, vde_datafd(s->vde));
|
||||
|
@ -1263,6 +1292,14 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void net_socket_cleanup(VLANClientState *vc)
|
||||
{
|
||||
NetSocketState *s = vc->opaque;
|
||||
qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
||||
close(s->fd);
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
|
||||
const char *model,
|
||||
const char *name,
|
||||
|
@ -1307,7 +1344,8 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
|
|||
s = qemu_mallocz(sizeof(NetSocketState));
|
||||
s->fd = fd;
|
||||
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram,
|
||||
NULL, net_socket_cleanup, s);
|
||||
qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
|
||||
|
||||
/* mcast: save bound address as dst */
|
||||
|
@ -1334,8 +1372,8 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
|
|||
NetSocketState *s;
|
||||
s = qemu_mallocz(sizeof(NetSocketState));
|
||||
s->fd = fd;
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name,
|
||||
net_socket_receive, NULL, s);
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive,
|
||||
NULL, net_socket_cleanup, s);
|
||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||
"socket: fd=%d", fd);
|
||||
if (is_connected) {
|
||||
|
@ -1895,29 +1933,20 @@ done:
|
|||
|
||||
void net_cleanup(void)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
VLANState *vlan;
|
||||
|
||||
/* close network clients */
|
||||
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
|
||||
VLANClientState *vc;
|
||||
VLANClientState *vc = vlan->first_client;
|
||||
|
||||
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
||||
if (vc->fd_read == tap_receive) {
|
||||
TAPState *s = vc->opaque;
|
||||
while (vc) {
|
||||
VLANClientState *next = vc->next;
|
||||
|
||||
if (s->down_script[0])
|
||||
launch_script(s->down_script, s->down_script_arg, s->fd);
|
||||
}
|
||||
#if defined(CONFIG_VDE)
|
||||
if (vc->fd_read == vde_from_qemu) {
|
||||
VDEState *s = vc->opaque;
|
||||
vde_close(s->vde);
|
||||
}
|
||||
#endif
|
||||
qemu_del_vlan_client(vc);
|
||||
|
||||
vc = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void net_client_check(void)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue