diff options
author | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-04-17 17:11:08 +0000 |
---|---|---|
committer | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-04-17 17:11:08 +0000 |
commit | b946a1533209f61a93e34898aebb5b43154b99c3 (patch) | |
tree | 36b0017910ca42cc5a41671b8edc7faa5da0a452 /net.c | |
parent | 32a8f6ae93f175518f86f99249177c35d1a85114 (diff) |
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
Diffstat (limited to 'net.c')
-rw-r--r-- | net.c | 71 |
1 files changed, 50 insertions, 21 deletions
@@ -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) |