]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fc] Hold ULP's peer reference while ULP exists
authorMichael Brown <mcb30@ipxe.org>
Fri, 5 Nov 2010 23:13:22 +0000 (23:13 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 8 Nov 2010 03:35:36 +0000 (03:35 +0000)
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>
src/net/fc.c

index fb930f1f6e3edb4f6b4a11b1f9515354add73887..d321c1fd9aa2b93fd48084632b834a1767f7fd46 100644 (file)
@@ -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 );