From 41231fda9c6989c2e1fcc41abef307531926a804 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 5 Nov 2010 23:13:22 +0000 Subject: [PATCH] [fc] Hold ULP's peer reference while ULP exists Allow fc_ulp_decrement() to guarantee to fc_peer_decrement() that the peer reference remains valid for the duration of the call, by ensuring that ulp->peer remains valid while ulp is valid. Signed-off-by: Michael Brown --- src/net/fc.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/net/fc.c b/src/net/fc.c index fb930f1f6..d321c1fd9 100644 --- a/src/net/fc.c +++ b/src/net/fc.c @@ -1476,6 +1476,18 @@ struct fc_peer * fc_peer_get_port_id ( struct fc_port *port, ****************************************************************************** */ +/** + * Free Fibre Channel upper-layer protocol + * + * @v refcnt Reference count + */ +static void fc_ulp_free ( struct refcnt *refcnt ) { + struct fc_ulp *ulp = container_of ( refcnt, struct fc_ulp, refcnt ); + + fc_peer_put ( ulp->peer ); + free ( ulp ); +} + /** * Close Fibre Channel upper-layer protocol * @@ -1499,10 +1511,6 @@ static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) { /* Remove from list of ULPs */ list_del ( &ulp->list ); INIT_LIST_HEAD ( &ulp->list ); - - /* Drop peer reference */ - fc_peer_put ( ulp->peer ); - ulp->peer = NULL; } /** @@ -1525,7 +1533,6 @@ void fc_ulp_increment ( struct fc_ulp *ulp ) { * @v ulp Fibre Channel ulp */ void fc_ulp_decrement ( struct fc_ulp *ulp ) { - struct fc_peer *peer = ulp->peer; /* Sanity check */ assert ( ulp->usage > 0 ); @@ -1535,7 +1542,7 @@ void fc_ulp_decrement ( struct fc_ulp *ulp ) { fc_ulp_logout ( ulp, 0 ); /* Decrement our peer's usage count */ - fc_peer_decrement ( peer ); + fc_peer_decrement ( ulp->peer ); } /** @@ -1702,7 +1709,7 @@ static struct fc_ulp * fc_ulp_create ( struct fc_peer *peer, ulp = zalloc ( sizeof ( *ulp ) ); if ( ! ulp ) return NULL; - ref_init ( &ulp->refcnt, NULL ); + ref_init ( &ulp->refcnt, fc_ulp_free ); fc_link_init ( &ulp->link, fc_ulp_examine, &ulp->refcnt ); intf_init ( &ulp->prli, &fc_ulp_prli_desc, &ulp->refcnt ); ulp->peer = fc_peer_get ( peer );