Commit ec60beeb authored by Michael Ellerman's avatar Michael Ellerman Committed by Jeff Garzik

[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: default avatarMichael Ellerman <michael@ellerman.id.au>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent cbf9074c
...@@ -683,6 +683,14 @@ static void veth_stop_connection(u8 rlp) ...@@ -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) ...@@ -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) ...@@ -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);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment