[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 9/9] Introduce VLANClientState::cleanup()
From: |
Mark McLoughlin |
Subject: |
[Qemu-devel] [PATCH 9/9] Introduce VLANClientState::cleanup() |
Date: |
Wed, 15 Apr 2009 17:29:29 +0100 |
We're currently leaking memory and file descriptors on device
hot-unplug.
Signed-off-by: Mark McLoughlin <address@hidden>
---
hw/e1000.c | 12 +++++-----
hw/eepro100.c | 12 ++++++++++
hw/etraxfs_eth.c | 11 +++++++++
hw/mcf_fec.c | 18 ++++++++++++---
hw/mipsnet.c | 14 ++++++++++++
hw/musicpal.c | 18 ++++++++++++---
hw/ne2000.c | 24 +++++++++++++++++++++
hw/pcnet.c | 43 ++++++++++++++++++++++++++++++++++---
hw/rtl8139.c | 20 +++++++++++++++++
hw/smc91c111.c | 17 +++++++++++---
hw/stellaris_enet.c | 20 ++++++++++++++---
hw/usb-net.c | 11 ++++++++-
hw/virtio-net.c | 14 ++++++++++++
net.c | 57 +++++++++++++++++++++++++++++++++++++-------------
net.h | 2 +
tap-win32.c | 13 +++++++++++
16 files changed, 263 insertions(+), 43 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index 2d16774..978f789 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1033,14 +1033,14 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
excluded_regs[i] - 4);
}
-static int
-pci_e1000_uninit(PCIDevice *dev)
+static void
+e1000_cleanup(VLANClientState *vc)
{
- E1000State *d = (E1000State *) dev;
+ E1000State *d = vc->opaque;
- cpu_unregister_io_memory(d->mmio_index);
+ unregister_savevm("e1000", d);
- return 0;
+ cpu_unregister_io_memory(d->mmio_index);
}
PCIDevice *
@@ -1095,12 +1095,12 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
e1000_receive, e1000_can_receive, d);
+ d->vc->cleanup = e1000_cleanup;
d->vc->link_status_changed = e1000_set_link_status;
qemu_format_nic_info_str(d->vc, nd->macaddr);
register_savevm(info_str, -1, 2, nic_save, nic_load, d);
- d->dev.unregister = pci_e1000_uninit;
return (PCIDevice *)d;
}
diff --git a/hw/eepro100.c b/hw/eepro100.c
index c72b990..a54287a 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1710,6 +1710,17 @@ static void nic_save(QEMUFile * f, void *opaque)
qemu_put_buffer(f, s->configuration, sizeof(s->configuration));
}
+static void nic_cleanup(VLANClientState *vc)
+{
+ EEPRO100State *s = vc->opaque;
+
+ unregister_savevm(vc->model, s);
+
+ cpu_unregister_io_memory(s->mmio_index);
+
+ eeprom93xx_free(s->eeprom);
+}
+
static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd, uint32_t device)
{
PCIEEPRO100State *d;
@@ -1751,6 +1762,7 @@ static PCIDevice *nic_init(PCIBus * bus, NICInfo * nd,
uint32_t device)
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
nic_receive, nic_can_receive, s);
+ s->vc->cleanup = nic_cleanup;
qemu_format_nic_info_str(s->vc, s->macaddr);
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index c87e55f..b0f7f6d 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -554,6 +554,16 @@ static CPUWriteMemoryFunc *eth_write[] = {
ð_writel,
};
+static void etraxfs_eth_cleanup(VLANClientState *vc)
+{
+ struct fs_eth *eth = vc->opaque;
+
+ cpu_unregister_io_memory(eth->ethregs);
+
+ qemu_free(eth->dma_out);
+ qemu_free(eth);
+}
+
void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
qemu_irq *irq, target_phys_addr_t base, int phyaddr)
{
@@ -586,6 +596,7 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
eth_receive, eth_can_receive, eth);
+ eth->vc->cleanup = etraxfs_eth_cleanup;
eth->vc->opaque = eth;
eth->vc->link_status_changed = eth_set_link;
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 413c569..6204772 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -24,6 +24,7 @@ do { printf("mcf_fec: " fmt , ##args); } while (0)
typedef struct {
qemu_irq *irq;
+ int mmio_index;
VLANClientState *vc;
uint32_t irq_state;
uint32_t eir;
@@ -441,21 +442,30 @@ static CPUWriteMemoryFunc *mcf_fec_writefn[] = {
mcf_fec_write
};
+static void mcf_fec_cleanup(VLANClientState *vc)
+{
+ mcf_fec_state *s = vc->opaque;
+
+ cpu_unregister_io_memory(s->mmio_index);
+
+ qemu_free(s);
+}
+
void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
{
mcf_fec_state *s;
- int iomemtype;
qemu_check_nic_model(nd, "mcf_fec");
s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
s->irq = irq;
- iomemtype = cpu_register_io_memory(0, mcf_fec_readfn,
- mcf_fec_writefn, s);
- cpu_register_physical_memory(base, 0x400, iomemtype);
+ s->mmio_index = cpu_register_io_memory(0, mcf_fec_readfn,
+ mcf_fec_writefn, s);
+ cpu_register_physical_memory(base, 0x400, s->mmio_index);
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
mcf_fec_receive, mcf_fec_can_receive, s);
+ s->vc->cleanup = mcf_fec_cleanup;
memcpy(s->macaddr, nd->macaddr, 6);
qemu_format_nic_info_str(s->vc, s->macaddr);
}
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 415b04e..f10356a 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -33,6 +33,7 @@ typedef struct MIPSnetState {
uint32_t intctl;
uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
+ int io_base;
qemu_irq irq;
VLANClientState *vc;
} MIPSnetState;
@@ -231,6 +232,17 @@ static int mipsnet_load(QEMUFile *f, void *opaque, int
version_id)
return 0;
}
+static void mipsnet_cleanup(VLANClientState *vc)
+{
+ MIPSnetState *s = vc->opaque;
+
+ unregister_savevm("mipsnet", s);
+
+ isa_unassign_ioport(s->io_base, 36);
+
+ qemu_free(s);
+}
+
void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
{
MIPSnetState *s;
@@ -246,10 +258,12 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
+ s->io_base = base;
s->irq = irq;
if (nd && nd->vlan) {
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
mipsnet_receive, mipsnet_can_receive, s);
+ s->vc->cleanup = mipsnet_cleanup;
} else {
s->vc = NULL;
}
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 5de1691..c4b73eb 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -536,6 +536,7 @@ typedef struct mv88w8618_eth_state {
uint32_t smir;
uint32_t icr;
uint32_t imr;
+ int mmio_index;
int vlan_header;
uint32_t tx_queue[2];
uint32_t rx_queue[4];
@@ -745,10 +746,18 @@ static CPUWriteMemoryFunc *mv88w8618_eth_writefn[] = {
mv88w8618_eth_write
};
+static void mv88w8618_eth_cleanup(VLANClientState *vc)
+{
+ mv88w8618_eth_state *s = vc->opaque;
+
+ cpu_unregister_io_memory(s->mmio_index);
+
+ qemu_free(s);
+}
+
static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq)
{
mv88w8618_eth_state *s;
- int iomemtype;
qemu_check_nic_model(nd, "mv88w8618");
@@ -756,9 +765,10 @@ static void mv88w8618_eth_init(NICInfo *nd, uint32_t base,
qemu_irq irq)
s->irq = irq;
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
eth_receive, eth_can_receive, s);
- iomemtype = cpu_register_io_memory(0, mv88w8618_eth_readfn,
- mv88w8618_eth_writefn, s);
- cpu_register_physical_memory(base, MP_ETH_SIZE, iomemtype);
+ s->vc->cleanup = mv88w8618_eth_cleanup;
+ s->mmio_index = cpu_register_io_memory(0, mv88w8618_eth_readfn,
+ mv88w8618_eth_writefn, s);
+ cpu_register_physical_memory(base, MP_ETH_SIZE, s->mmio_index);
}
/* LCD register offsets */
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 24a66bb..7fe3975 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -140,6 +140,7 @@ typedef struct NE2000State {
uint8_t curpag;
uint8_t mult[8]; /* multicast mask array */
qemu_irq irq;
+ int isa_io_base;
PCIDevice *pci_dev;
VLANClientState *vc;
uint8_t macaddr[6];
@@ -718,6 +719,19 @@ static int ne2000_load(QEMUFile* f,void* opaque,int
version_id)
return 0;
}
+static void isa_ne2000_cleanup(VLANClientState *vc)
+{
+ NE2000State *s = vc->opaque;
+
+ unregister_savevm("ne2000", s);
+
+ isa_unassign_ioport(s->isa_io_base, 16);
+ isa_unassign_ioport(s->isa_io_base + 0x10, 2);
+ isa_unassign_ioport(s->isa_io_base + 0x1f, 1);
+
+ qemu_free(s);
+}
+
void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
{
NE2000State *s;
@@ -736,6 +750,7 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
+ s->isa_io_base = base;
s->irq = irq;
memcpy(s->macaddr, nd->macaddr, 6);
@@ -743,6 +758,7 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
ne2000_receive, ne2000_can_receive, s);
+ s->vc->cleanup = isa_ne2000_cleanup;
qemu_format_nic_info_str(s->vc, s->macaddr);
@@ -777,6 +793,13 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
}
+static void ne2000_cleanup(VLANClientState *vc)
+{
+ NE2000State *s = vc->opaque;
+
+ unregister_savevm("ne2000", s);
+}
+
PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCINE2000State *d;
@@ -803,6 +826,7 @@ PCIDevice *pci_ne2000_init(PCIBus *bus, NICInfo *nd, int
devfn)
ne2000_reset(s);
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
ne2000_receive, ne2000_can_receive, s);
+ s->vc->cleanup = ne2000_cleanup;
qemu_format_nic_info_str(s->vc, s->macaddr);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index be68f28..7bd150a 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -75,6 +75,7 @@ struct PCNetState_st {
uint8_t buffer[4096];
int tx_busy;
qemu_irq irq;
+ qemu_irq *reset_irq;
void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
uint8_t *buf, int len, int do_bswap);
void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
@@ -1929,6 +1930,13 @@ static int pcnet_load(QEMUFile *f, void *opaque, int
version_id)
return 0;
}
+static void pcnet_common_cleanup(PCNetState *d)
+{
+ unregister_savevm("pcnet", d);
+ qemu_del_timer(d->poll_timer);
+ qemu_free_timer(d->poll_timer);
+}
+
static void pcnet_common_init(PCNetState *d, NICInfo *nd)
{
d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
@@ -1985,6 +1993,15 @@ static void pci_physical_memory_read(void *dma_opaque,
target_phys_addr_t addr,
cpu_physical_memory_read(addr, buf, len);
}
+static void pci_pcnet_cleanup(VLANClientState *vc)
+{
+ PCNetState *d = vc->opaque;
+
+ pcnet_common_cleanup(d);
+
+ cpu_unregister_io_memory(d->mmio_index);
+}
+
PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCNetState *d;
@@ -2032,6 +2049,9 @@ PCIDevice *pci_pcnet_init(PCIBus *bus, NICInfo *nd, int
devfn)
d->pci_dev = &d->dev;
pcnet_common_init(d, nd);
+
+ d->vc->cleanup = pci_pcnet_cleanup;
+
return (PCIDevice *)d;
}
@@ -2081,29 +2101,44 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
NULL,
};
+static void lance_cleanup(VLANClientState *vc)
+{
+ PCNetState *d = vc->opaque;
+
+ pcnet_common_cleanup(d);
+
+ qemu_free_irqs(d->reset_irq);
+
+ cpu_unregister_io_memory(d->mmio_index);
+
+ qemu_free(d);
+}
+
void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
qemu_irq irq, qemu_irq *reset)
{
PCNetState *d;
- int lance_io_memory;
qemu_check_nic_model(nd, "lance");
d = qemu_mallocz(sizeof(PCNetState));
- lance_io_memory =
+ d->mmio_index =
cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d);
d->dma_opaque = dma_opaque;
- *reset = *qemu_allocate_irqs(parent_lance_reset, d, 1);
+ d->reset_irq = qemu_allocate_irqs(parent_lance_reset, d, 1);
+ *reset = *d->reset_irq;
- cpu_register_physical_memory(leaddr, 4, lance_io_memory);
+ cpu_register_physical_memory(leaddr, 4, d->mmio_index);
d->irq = irq;
d->phys_mem_read = ledma_memory_read;
d->phys_mem_write = ledma_memory_write;
pcnet_common_init(d, nd);
+
+ d->vc->cleanup = lance_cleanup;
}
#endif /* TARGET_SPARC */
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 9fa69db..e381ab0 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3414,6 +3414,25 @@ static void rtl8139_timer(void *opaque)
}
#endif /* RTL8139_ONBOARD_TIMER */
+static void rtl8139_cleanup(VLANClientState *vc)
+{
+ RTL8139State *s = vc->opaque;
+
+ if (s->cplus_txbuffer) {
+ qemu_free(s->cplus_txbuffer);
+ s->cplus_txbuffer = NULL;
+ }
+
+#ifdef RTL8139_ONBOARD_TIMER
+ qemu_del_timer(s->timer);
+ qemu_free_timer(s->timer);
+#endif
+
+ unregister_savevm("rtl8139", s);
+
+ cpu_unregister_io_memory(s->rtl8139_mmio_io_addr);
+}
+
PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
{
PCIRTL8139State *d;
@@ -3451,6 +3470,7 @@ PCIDevice *pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int
devfn)
rtl8139_reset(s);
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
rtl8139_receive, rtl8139_can_receive, s);
+ s->vc->cleanup = rtl8139_cleanup;
qemu_format_nic_info_str(s->vc, s->macaddr);
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index f5b29a7..b132ca3 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -42,6 +42,7 @@ typedef struct {
uint8_t int_level;
uint8_t int_mask;
uint8_t macaddr[6];
+ int mmio_index;
} smc91c111_state;
#define RCR_SOFT_RST 0x8000
@@ -690,17 +691,24 @@ static CPUWriteMemoryFunc *smc91c111_writefn[] = {
smc91c111_writel
};
+static void smc91c111_cleanup(VLANClientState *vc)
+{
+ smc91c111_state *s = vc->opaque;
+
+ cpu_unregister_io_memory(s->mmio_index);
+ qemu_free(s);
+}
+
void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
{
smc91c111_state *s;
- int iomemtype;
qemu_check_nic_model(nd, "smc91c111");
s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state));
- iomemtype = cpu_register_io_memory(0, smc91c111_readfn,
- smc91c111_writefn, s);
- cpu_register_physical_memory(base, 16, iomemtype);
+ s->mmio_index = cpu_register_io_memory(0, smc91c111_readfn,
+ smc91c111_writefn, s);
+ cpu_register_physical_memory(base, 16, s->mmio_index);
s->irq = irq;
memcpy(s->macaddr, nd->macaddr, 6);
@@ -708,6 +716,7 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq
irq)
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
smc91c111_receive, smc91c111_can_receive, s);
+ s->vc->cleanup = smc91c111_cleanup;
qemu_format_nic_info_str(s->vc, s->macaddr);
/* ??? Save/restore. */
}
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index 88c5620..48826d8 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -69,6 +69,7 @@ typedef struct {
VLANClientState *vc;
qemu_irq irq;
uint8_t macaddr[6];
+ int mmio_index;
} stellaris_enet_state;
static void stellaris_enet_update(stellaris_enet_state *s)
@@ -384,23 +385,34 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque,
int version_id)
return 0;
}
+static void stellaris_enet_cleanup(VLANClientState *vc)
+{
+ stellaris_enet_state *s = vc->opaque;
+
+ unregister_savevm("stellaris_enet", s);
+
+ cpu_unregister_io_memory(s->mmio_index);
+
+ qemu_free(s);
+}
+
void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq)
{
stellaris_enet_state *s;
- int iomemtype;
qemu_check_nic_model(nd, "stellaris");
s = (stellaris_enet_state *)qemu_mallocz(sizeof(stellaris_enet_state));
- iomemtype = cpu_register_io_memory(0, stellaris_enet_readfn,
- stellaris_enet_writefn, s);
- cpu_register_physical_memory(base, 0x00001000, iomemtype);
+ s->mmio_index = cpu_register_io_memory(0, stellaris_enet_readfn,
+ stellaris_enet_writefn, s);
+ cpu_register_physical_memory(base, 0x00001000, s->mmio_index);
s->irq = irq;
memcpy(s->macaddr, nd->macaddr, 6);
if (nd->vlan) {
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
stellaris_enet_receive,
stellaris_enet_can_receive, s);
+ s->vc->cleanup = stellaris_enet_cleanup;
qemu_format_nic_info_str(s->vc, s->macaddr);
}
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 863c25f..99c132f 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1415,14 +1415,20 @@ static int usbnet_can_receive(void *opaque)
return !s->in_len;
}
+static void usbnet_cleanup(VLANClientState *vc)
+{
+ USBNetState *s = vc->opaque;
+
+ rndis_clear_responsequeue(s);
+ qemu_free(s);
+}
+
static void usb_net_handle_destroy(USBDevice *dev)
{
USBNetState *s = (USBNetState *) dev;
/* TODO: remove the nd_table[] entry */
qemu_del_vlan_client(s->vc);
- rndis_clear_responsequeue(s);
- qemu_free(s);
}
USBDevice *usb_net_init(NICInfo *nd)
@@ -1453,6 +1459,7 @@ USBDevice *usb_net_init(NICInfo *nd)
"QEMU USB Network Interface");
s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
usbnet_receive, usbnet_can_receive, s);
+ s->vc->cleanup = usbnet_cleanup;
qemu_format_nic_info_str(s->vc, s->mac);
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 5e7db0d..201872d 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -570,6 +570,19 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int
version_id)
return 0;
}
+static void virtio_net_cleanup(VLANClientState *vc)
+{
+ VirtIONet *n = vc->opaque;
+
+ unregister_savevm("virtio-net", n);
+
+ qemu_free(n->mac_table.macs);
+ qemu_free(n->vlans);
+
+ qemu_del_timer(n->tx_timer);
+ qemu_free_timer(n->tx_timer);
+}
+
PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
{
VirtIONet *n;
@@ -599,6 +612,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int
devfn)
n->status = VIRTIO_NET_S_LINK_UP;
n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
virtio_net_receive, virtio_net_can_receive,
n);
+ n->vc->cleanup = virtio_net_cleanup;
n->vc->link_status_changed = virtio_net_set_link_status;
qemu_format_nic_info_str(n->vc, n->mac);
diff --git a/net.c b/net.c
index 34ec4c8..1378ea8 100644
--- a/net.c
+++ b/net.c
@@ -362,6 +362,8 @@ 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);
@@ -702,6 +704,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 +752,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);
+ free(s);
+}
+
/* fd support */
static TAPState *net_tap_fd_init(VLANState *vlan,
@@ -760,6 +776,7 @@ 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->cleanup = tap_cleanup;
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 +1075,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);
+ 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)
@@ -1079,6 +1104,7 @@ static int net_vde_init(VLANState *vlan, const char
*model,
return -1;
}
s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s);
+ s->vc->cleanup = vde_cleanup;
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 +1289,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);
+ free(s);
+}
+
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
const char *model,
const char *name,
@@ -1308,6 +1342,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState
*vlan,
s->fd = fd;
s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram,
NULL, s);
+ s->vc->cleanup = net_socket_cleanup;
qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
/* mcast: save bound address as dst */
@@ -1336,6 +1371,7 @@ static NetSocketState
*net_socket_fd_init_stream(VLANState *vlan,
s->fd = fd;
s->vc = qemu_new_vlan_client(vlan, model, name,
net_socket_receive, NULL, s);
+ s->vc->cleanup = net_socket_cleanup;
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
"socket: fd=%d", fd);
if (is_connected) {
@@ -1895,29 +1931,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)
diff --git a/net.h b/net.h
index 1a51be7..5def263 100644
--- a/net.h
+++ b/net.h
@@ -9,6 +9,7 @@ typedef ssize_t (IOReadvHandler)(void *, const struct iovec *,
int);
typedef struct VLANClientState VLANClientState;
+typedef void (NetCleanup) (VLANClientState *);
typedef void (LinkStatusChanged)(VLANClientState *);
struct VLANClientState {
@@ -17,6 +18,7 @@ struct VLANClientState {
/* Packets may still be sent if this returns zero. It's used to
rate-limit the slirp code. */
IOCanRWHandler *fd_can_read;
+ NetCleanup *cleanup;
LinkStatusChanged *link_status_changed;
int link_down;
void *opaque;
diff --git a/tap-win32.c b/tap-win32.c
index e8a04dc..5948060 100644
--- a/tap-win32.c
+++ b/tap-win32.c
@@ -638,6 +638,18 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle,
tap_win32_overlapped_t *handle;
} TAPState;
+static void tap_cleanup(VLANClientState *vc)
+{
+ TAPState *s = vc->opaque;
+
+ qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL);
+
+ /* FIXME: need to kill thread and close file handle:
+ tap_win32_close(s);
+ */
+ free(s);
+}
+
static void tap_receive(void *opaque, const uint8_t *buf, int size)
{
TAPState *s = opaque;
@@ -673,6 +685,7 @@ int tap_win32_init(VLANState *vlan, const char *model,
}
s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s);
+ s->vc->cleanup = tap_cleanup;
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
"tap: ifname=%s", ifname);
--
1.6.0.6
- [Qemu-devel] [PATCH 0/9] Misc networking fixes, Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 1/9] Remove stray GSO code from virtio_net, Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 2/9] struct iovec is now universally available, Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 3/9] Fix error handling in net_client_init(), Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 4/9] Don't fail PCI hotplug if no NIC model is supplied, Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 5/9] Remove some useless malloc() checking, Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 6/9] Remove NICInfo from e1000 and mipsnet state, Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 7/9] Add unregister_savevm(), Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 8/9] Use NICInfo::model for eepro100 savevm ID string, Mark McLoughlin, 2009/04/15
- [Qemu-devel] [PATCH 9/9] Introduce VLANClientState::cleanup(),
Mark McLoughlin <=
- [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), Jan Kiszka, 2009/04/15
- Re: [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), Marcelo Tosatti, 2009/04/15
- Re: [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), M. Warner Losh, 2009/04/15
- Re: [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), Mark McLoughlin, 2009/04/16
- [Qemu-devel] [PATCH 09/09 v2] Introduce VLANClientState::cleanup(), Mark McLoughlin, 2009/04/16
- [Qemu-devel] [PATCH 10/09] Free VLANClientState using qemu_free(), Mark McLoughlin, 2009/04/16
- Re: [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), Marcelo Tosatti, 2009/04/16
- Re: [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), Paul Brook, 2009/04/28
- Re: [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), Anthony Liguori, 2009/04/28
- Re: [Qemu-devel] Re: [PATCH 9/9] Introduce VLANClientState::cleanup(), Paul Brook, 2009/04/28