summaryrefslogtreecommitdiffstats
path: root/src/net/fc.c
diff options
context:
space:
mode:
authorMichael Brown2010-11-06 00:13:22 +0100
committerMichael Brown2010-11-08 04:35:36 +0100
commit41231fda9c6989c2e1fcc41abef307531926a804 (patch)
tree032a3ac48ca092e8dce106435599013d5b0a6940 /src/net/fc.c
parent[fc] Allow peers and ULPs to log out when usage count reaches zero (diff)
downloadipxe-41231fda9c6989c2e1fcc41abef307531926a804.tar.gz
ipxe-41231fda9c6989c2e1fcc41abef307531926a804.tar.xz
ipxe-41231fda9c6989c2e1fcc41abef307531926a804.zip
[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 <mcb30@ipxe.org>
Diffstat (limited to 'src/net/fc.c')
-rw-r--r--src/net/fc.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/src/net/fc.c b/src/net/fc.c
index fb930f1f..d321c1fd 100644
--- a/src/net/fc.c
+++ b/src/net/fc.c
@@ -1477,6 +1477,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
*
* @v ulp 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 );