aboutsummaryrefslogtreecommitdiff
path: root/net.c
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-04-17 17:11:08 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2009-04-17 17:11:08 +0000
commitb946a1533209f61a93e34898aebb5b43154b99c3 (patch)
tree36b0017910ca42cc5a41671b8edc7faa5da0a452 /net.c
parent32a8f6ae93f175518f86f99249177c35d1a85114 (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.c71
1 files changed, 50 insertions, 21 deletions
diff --git a/net.c b/net.c
index 34ec4c810b..5a8f824055 100644
--- a/net.c
+++ b/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)