Browse Source

[fc] Maintain a list of Fibre Channel upper-layer protocol users

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
bf8bfa23e2
4 changed files with 73 additions and 39 deletions
  1. 28
    5
      src/include/ipxe/fc.h
  2. 30
    14
      src/net/fc.c
  3. 14
    18
      src/net/fcp.c
  4. 1
    2
      src/usr/fcmgmt.c

+ 28
- 5
src/include/ipxe/fc.h View File

@@ -357,7 +357,15 @@ struct fc_peer {
357 357
 
358 358
 	/** List of upper-layer protocols */
359 359
 	struct list_head ulps;
360
-	/** Active usage count */
360
+	/** Active usage count
361
+	 *
362
+	 * A peer (and attached ULPs) may be created in response to
363
+	 * unsolicited login requests received via the fabric.  We
364
+	 * track our own active usage count independently of the
365
+	 * existence of the peer, so that if the peer becomes logged
366
+	 * out (e.g. due to a link failure) then we know whether or
367
+	 * not we should attempt to relogin.
368
+	 */
361 369
 	unsigned int usage;
362 370
 };
363 371
 
@@ -424,8 +432,15 @@ struct fc_ulp {
424 432
 	/** Service parameter length */
425 433
 	size_t param_len;
426 434
 
427
-	/** Active usage count */
428
-	unsigned int usage;
435
+	/** Active users of this upper-layer protocol
436
+	 *
437
+	 * As with peers, an upper-layer protocol may be created in
438
+	 * response to an unsolicited login request received via the
439
+	 * fabric.  This list records the number of active users of
440
+	 * the ULP; the number of entries in the list is equivalent to
441
+	 * the peer usage count.
442
+	 */
443
+	struct list_head users;
429 444
 };
430 445
 
431 446
 /** Fibre Channel upper-layer protocol flags */
@@ -434,6 +449,14 @@ enum fc_ulp_flags {
434 449
 	FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
435 450
 };
436 451
 
452
+/** A Fibre Channel upper-layer protocol user */
453
+struct fc_ulp_user {
454
+	/** Fibre Channel upper layer protocol */
455
+	struct fc_ulp *ulp;
456
+	/** List of users */
457
+	struct list_head list;
458
+};
459
+
437 460
 /**
438 461
  * Get reference to Fibre Channel upper-layer protocol
439 462
  *
@@ -462,8 +485,8 @@ extern struct fc_ulp *
462 485
 fc_ulp_get_port_id_type ( struct fc_port *port,
463 486
 			  const struct fc_port_id *peer_port_id,
464 487
 			  unsigned int type );
465
-extern void fc_ulp_increment ( struct fc_ulp *ulp );
466
-extern void fc_ulp_decrement ( struct fc_ulp *ulp );
488
+extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user );
489
+extern void fc_ulp_detach ( struct fc_ulp_user *user );
467 490
 extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
468 491
 			  size_t param_len, int originated );
469 492
 extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );

+ 30
- 14
src/net/fc.c View File

@@ -1580,7 +1580,7 @@ static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) {
1580 1580
 	       fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
1581 1581
 
1582 1582
 	/* Sanity check */
1583
-	assert ( ulp->usage == 0 );
1583
+	assert ( list_empty ( &ulp->users ) );
1584 1584
 
1585 1585
 	/* Stop link monitor */
1586 1586
 	fc_link_stop ( &ulp->link );
@@ -1594,35 +1594,50 @@ static void fc_ulp_close ( struct fc_ulp *ulp, int rc ) {
1594 1594
 }
1595 1595
 
1596 1596
 /**
1597
- * Increment Fibre Channel upper-layer protocol active usage count
1597
+ * Attach Fibre Channel upper-layer protocol user
1598 1598
  *
1599
- * @v ulp		Fibre Channel ulp
1599
+ * @v ulp		Fibre Channel upper-layer protocol
1600
+ * @v user		Fibre Channel upper-layer protocol user
1600 1601
  */
1601
-void fc_ulp_increment ( struct fc_ulp *ulp ) {
1602
+void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user ) {
1603
+
1604
+	/* Sanity check */
1605
+	assert ( user->ulp == NULL );
1602 1606
 
1603 1607
 	/* Increment peer's usage count */
1604 1608
 	fc_peer_increment ( ulp->peer );
1605 1609
 
1606
-	/* Increment our usage count */
1607
-	ulp->usage++;
1610
+	/* Attach user */
1611
+	user->ulp = fc_ulp_get ( ulp );
1612
+	list_add ( &user->list, &ulp->users );
1608 1613
 }
1609 1614
 
1610 1615
 /**
1611
- * Decrement Fibre Channel upper-layer protocol active usage count
1616
+ * Detach Fibre Channel upper-layer protocol user
1612 1617
  *
1613
- * @v ulp		Fibre Channel ulp
1618
+ * @v user		Fibre Channel upper-layer protocol user
1614 1619
  */
1615
-void fc_ulp_decrement ( struct fc_ulp *ulp ) {
1620
+void fc_ulp_detach ( struct fc_ulp_user *user ) {
1621
+	struct fc_ulp *ulp = user->ulp;
1616 1622
 
1617
-	/* Sanity check */
1618
-	assert ( ulp->usage > 0 );
1623
+	/* Do nothing if not attached */
1624
+	if ( ! ulp )
1625
+		return;
1619 1626
 
1620
-	/* Decrement our usage count and log out if we reach zero */
1621
-	if ( --(ulp->usage) == 0 )
1627
+	/* Sanity checks */
1628
+	list_check_contains ( user, &ulp->users, list );
1629
+
1630
+	/* Detach user and log out if no users remain */
1631
+	list_del ( &user->list );
1632
+	if ( list_empty ( &ulp->users ) )
1622 1633
 		fc_ulp_logout ( ulp, 0 );
1623 1634
 
1624 1635
 	/* Decrement our peer's usage count */
1625 1636
 	fc_peer_decrement ( ulp->peer );
1637
+
1638
+	/* Drop reference */
1639
+	user->ulp = NULL;
1640
+	fc_ulp_put ( ulp );
1626 1641
 }
1627 1642
 
1628 1643
 /**
@@ -1712,7 +1727,7 @@ void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) {
1712 1727
 	fc_link_err ( &ulp->link, rc );
1713 1728
 
1714 1729
 	/* Close ULP if there are no clients attached */
1715
-	if ( ulp->usage == 0 )
1730
+	if ( list_empty ( &ulp->users ) )
1716 1731
 		fc_ulp_close ( ulp, rc );
1717 1732
 }
1718 1733
 
@@ -1795,6 +1810,7 @@ static struct fc_ulp * fc_ulp_create ( struct fc_peer *peer,
1795 1810
 	ulp->peer = fc_peer_get ( peer );
1796 1811
 	list_add_tail ( &ulp->list, &peer->ulps );
1797 1812
 	ulp->type = type;
1813
+	INIT_LIST_HEAD ( &ulp->users );
1798 1814
 
1799 1815
 	/* Start link state monitor */
1800 1816
 	fc_link_start ( &ulp->link );

+ 14
- 18
src/net/fcp.c View File

@@ -146,8 +146,8 @@ struct fc_els_prli_descriptor fcp_prli_descriptor __fc_els_prli_descriptor = {
146 146
 struct fcp_device {
147 147
 	/** Reference count */
148 148
 	struct refcnt refcnt;
149
-	/** Fibre Channel upper-layer protocol */
150
-	struct fc_ulp *ulp;
149
+	/** Fibre Channel upper-layer protocol user */
150
+	struct fc_ulp_user user;
151 151
 	/** SCSI command issuing interface */
152 152
 	struct interface scsi;
153 153
 	/** List of active commands */
@@ -734,13 +734,13 @@ static struct interface_descriptor fcpcmd_xchg_desc =
734 734
 static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
735 735
 				 struct interface *parent,
736 736
 				 struct scsi_cmd *command ) {
737
-	struct fcp_prli_service_parameters *param = fcpdev->ulp->param;
737
+	struct fcp_prli_service_parameters *param = fcpdev->user.ulp->param;
738 738
 	struct fcp_command *fcpcmd;
739 739
 	int xchg_id;
740 740
 	int rc;
741 741
 
742 742
 	/* Check link */
743
-	if ( ( rc = fcpdev->ulp->link.rc ) != 0 ) {
743
+	if ( ( rc = fcpdev->user.ulp->link.rc ) != 0 ) {
744 744
 		DBGC ( fcpdev, "FCP %p could not issue command while link is "
745 745
 		       "down: %s\n", fcpdev, strerror ( rc ) );
746 746
 		goto err_link;
@@ -748,7 +748,7 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
748 748
 
749 749
 	/* Check target capability */
750 750
 	assert ( param != NULL );
751
-	assert ( fcpdev->ulp->param_len >= sizeof ( *param ) );
751
+	assert ( fcpdev->user.ulp->param_len >= sizeof ( *param ) );
752 752
 	if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
753 753
 		DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
754 754
 		       fcpdev );
@@ -772,8 +772,8 @@ static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
772 772
 
773 773
 	/* Create new exchange */
774 774
 	if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
775
-					     fcpdev->ulp->peer->port,
776
-					     &fcpdev->ulp->peer->port_id,
775
+					     fcpdev->user.ulp->peer->port,
776
+					     &fcpdev->user.ulp->peer->port_id,
777 777
 					     FC_TYPE_FCP ) ) < 0 ) {
778 778
 		rc = xchg_id;
779 779
 		DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
@@ -822,11 +822,7 @@ static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) {
822 822
 	}
823 823
 
824 824
 	/* Drop reference to ULP */
825
-	if ( fcpdev->ulp ) {
826
-		fc_ulp_decrement ( fcpdev->ulp );
827
-		fc_ulp_put ( fcpdev->ulp );
828
-		fcpdev->ulp = NULL;
829
-	}
825
+	fc_ulp_detach ( &fcpdev->user );
830 826
 }
831 827
 
832 828
 /**
@@ -836,7 +832,8 @@ static void fcpdev_close ( struct fcp_device *fcpdev, int rc ) {
836 832
  * @ret len		Length of window
837 833
  */
838 834
 static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
839
-	return ( fc_link_ok ( &fcpdev->ulp->link ) ? ~( ( size_t ) 0 ) : 0 );
835
+	return ( fc_link_ok ( &fcpdev->user.ulp->link ) ?
836
+		 ~( ( size_t ) 0 ) : 0 );
840 837
 }
841 838
 
842 839
 /**
@@ -897,15 +894,15 @@ static struct device * fcpdev_identify_device ( struct fcp_device *fcpdev ) {
897 894
 	/* We know the underlying device only if the link is up;
898 895
 	 * otherwise we don't have a port to examine.
899 896
 	 */
900
-	if ( ! fc_link_ok ( &fcpdev->ulp->link ) ) {
897
+	if ( ! fc_link_ok ( &fcpdev->user.ulp->link ) ) {
901 898
 		DBGC ( fcpdev, "FCP %p doesn't know underlying device "
902 899
 		       "until link is up\n", fcpdev );
903 900
 		return NULL;
904 901
 	}
905 902
 
906 903
 	/* Hand off to port's transport interface */
907
-	assert ( fcpdev->ulp->peer->port != NULL );
908
-	return identify_device ( &fcpdev->ulp->peer->port->transport );
904
+	assert ( fcpdev->user.ulp->peer->port != NULL );
905
+	return identify_device ( &fcpdev->user.ulp->peer->port->transport );
909 906
 }
910 907
 
911 908
 /** FCP device SCSI interface operations */
@@ -953,8 +950,7 @@ static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
953 950
 	ref_init ( &fcpdev->refcnt, NULL );
954 951
 	intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
955 952
 	INIT_LIST_HEAD ( &fcpdev->fcpcmds );
956
-	fcpdev->ulp = fc_ulp_get ( ulp );
957
-	fc_ulp_increment ( fcpdev->ulp );
953
+	fc_ulp_attach ( ulp, &fcpdev->user );
958 954
 
959 955
 	DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
960 956
 

+ 1
- 2
src/usr/fcmgmt.c View File

@@ -74,8 +74,7 @@ void fcpeerstat ( struct fc_peer *peer ) {
74 74
 	}
75 75
 
76 76
 	list_for_each_entry ( ulp, &peer->ulps, list ) {
77
-		printf ( "  [Type %02x usage %d link:",
78
-			 ulp->type, ulp->usage );
77
+		printf ( "  [Type %02x link:", ulp->type );
79 78
 		if ( fc_link_ok ( &ulp->link ) ) {
80 79
 			printf ( " up, params" );
81 80
 			param = ulp->param;

Loading…
Cancel
Save