[PATCH] iseries_veth: Make init_connection() & destroy_connection() symmetrical
This patch makes veth_init_connection() and veth_destroy_connection() symmetrical in that they allocate/deallocate the same data. Currently if there's an error while initialising connections (ie. ENOMEM) we call veth_module_cleanup(), however this will oops because we call driver_unregister() before we've called driver_register(). I've never seen this actually happen though. So instead we explicitly call veth_destroy_connection() for each connection, any that have been set up will be deallocated. We also fix a potential leak if vio_register_driver() fails. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
parent
cbf9074cc3
commit
ec60beebed
|
@ -683,6 +683,14 @@ static void veth_stop_connection(u8 rlp)
|
||||||
|
|
||||||
/* Wait for the state machine to run. */
|
/* Wait for the state machine to run. */
|
||||||
flush_scheduled_work();
|
flush_scheduled_work();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void veth_destroy_connection(u8 rlp)
|
||||||
|
{
|
||||||
|
struct veth_lpar_connection *cnx = veth_cnx[rlp];
|
||||||
|
|
||||||
|
if (! cnx)
|
||||||
|
return;
|
||||||
|
|
||||||
if (cnx->num_events > 0)
|
if (cnx->num_events > 0)
|
||||||
mf_deallocate_lp_events(cnx->remote_lp,
|
mf_deallocate_lp_events(cnx->remote_lp,
|
||||||
|
@ -694,14 +702,6 @@ static void veth_stop_connection(u8 rlp)
|
||||||
HvLpEvent_Type_VirtualLan,
|
HvLpEvent_Type_VirtualLan,
|
||||||
cnx->num_ack_events,
|
cnx->num_ack_events,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
static void veth_destroy_connection(u8 rlp)
|
|
||||||
{
|
|
||||||
struct veth_lpar_connection *cnx = veth_cnx[rlp];
|
|
||||||
|
|
||||||
if (! cnx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
kfree(cnx->msgs);
|
kfree(cnx->msgs);
|
||||||
kfree(cnx);
|
kfree(cnx);
|
||||||
|
@ -1441,15 +1441,24 @@ int __init veth_module_init(void)
|
||||||
|
|
||||||
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
|
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
|
||||||
rc = veth_init_connection(i);
|
rc = veth_init_connection(i);
|
||||||
if (rc != 0) {
|
if (rc != 0)
|
||||||
veth_module_cleanup();
|
goto error;
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan,
|
HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan,
|
||||||
&veth_handle_event);
|
&veth_handle_event);
|
||||||
|
|
||||||
return vio_register_driver(&veth_driver);
|
rc = vio_register_driver(&veth_driver);
|
||||||
|
if (rc != 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) {
|
||||||
|
veth_destroy_connection(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
module_init(veth_module_init);
|
module_init(veth_module_init);
|
||||||
|
|
Reference in New Issue