Browse Source

Add ability to shut down iSCSI connection

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
ab242a760d
4 changed files with 49 additions and 24 deletions
  1. 16
    1
      src/drivers/scsi/iscsidev.c
  2. 5
    0
      src/include/gpxe/iscsi.h
  3. 25
    22
      src/net/tcp/iscsi.c
  4. 3
    1
      src/tests/iscsiboot.c

+ 16
- 1
src/drivers/scsi/iscsidev.c View File

46
  * @v iscsidev		iSCSI device
46
  * @v iscsidev		iSCSI device
47
  */
47
  */
48
 int init_iscsidev ( struct iscsi_device *iscsidev ) {
48
 int init_iscsidev ( struct iscsi_device *iscsidev ) {
49
+	int rc;
50
+
49
 	iscsidev->scsi.command = iscsi_command;
51
 	iscsidev->scsi.command = iscsi_command;
50
 	iscsidev->scsi.lun = iscsidev->iscsi.lun;
52
 	iscsidev->scsi.lun = iscsidev->iscsi.lun;
51
-	return init_scsidev ( &iscsidev->scsi );
53
+	rc = init_scsidev ( &iscsidev->scsi );
54
+	if ( rc != 0 ) {
55
+		fini_iscsidev ( iscsidev );
56
+	}
57
+	return rc;
58
+}
59
+
60
+/**
61
+ * Shut down iSCSI device
62
+ *
63
+ * @v iscsidev		iSCSI device
64
+ */
65
+void fini_iscsidev ( struct iscsi_device *iscsidev ) {
66
+	async_wait ( iscsi_shutdown ( &iscsidev->iscsi ) );
52
 }
67
 }

+ 5
- 0
src/include/gpxe/iscsi.h View File

626
 /** Mask for all iSCSI "needs to send" flags */
626
 /** Mask for all iSCSI "needs to send" flags */
627
 #define ISCSI_STATUS_STRINGS_MASK 0xff00
627
 #define ISCSI_STATUS_STRINGS_MASK 0xff00
628
 
628
 
629
+/** iSCSI session is closing down */
630
+#define ISCSI_STATUS_CLOSING 0x00010000
631
+
629
 /** Maximum number of retries at connecting */
632
 /** Maximum number of retries at connecting */
630
 #define ISCSI_MAX_RETRIES 2
633
 #define ISCSI_MAX_RETRIES 2
631
 
634
 
632
 extern struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
635
 extern struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
633
 					      struct scsi_command *command );
636
 					      struct scsi_command *command );
637
+extern struct async_operation * iscsi_shutdown ( struct iscsi_session *iscsi );
634
 
638
 
635
 /** An iSCSI device */
639
 /** An iSCSI device */
636
 struct iscsi_device {
640
 struct iscsi_device {
641
 };
645
 };
642
 
646
 
643
 extern int init_iscsidev ( struct iscsi_device *iscsidev );
647
 extern int init_iscsidev ( struct iscsi_device *iscsidev );
648
+extern void fini_iscsidev ( struct iscsi_device *iscsidev );
644
 
649
 
645
 #endif /* _GPXE_ISCSI_H */
650
 #endif /* _GPXE_ISCSI_H */

+ 25
- 22
src/net/tcp/iscsi.c View File

104
 	async_done ( &iscsi->aop, rc );
104
 	async_done ( &iscsi->aop, rc );
105
 }
105
 }
106
 
106
 
107
-/**
108
- * Mark iSCSI operation as complete, and close TCP connection
109
- *
110
- * @v iscsi		iSCSI session
111
- * @v rc		Return status code
112
- */
113
-static void iscsi_close ( struct iscsi_session *iscsi, int rc ) {
114
-
115
-	/* Clear session status */
116
-	iscsi->status = 0;
117
-
118
-	/* Close TCP connection */
119
-	tcp_close ( &iscsi->tcp );
120
-
121
-	/* Mark iSCSI operation as complete */
122
-	iscsi_done ( iscsi, rc );
123
-}
124
-
125
 /****************************************************************************
107
 /****************************************************************************
126
  *
108
  *
127
  * iSCSI SCSI command issuing
109
  * iSCSI SCSI command issuing
564
 	/* Prepare for CHAP with MD5 */
546
 	/* Prepare for CHAP with MD5 */
565
 	if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
547
 	if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
566
 		DBG ( "iSCSI %p could not initialise CHAP\n", iscsi );
548
 		DBG ( "iSCSI %p could not initialise CHAP\n", iscsi );
567
-		iscsi_close ( iscsi, rc );
549
+		iscsi_done ( iscsi, rc );
568
 	}
550
 	}
569
 }
551
 }
570
 
552
 
722
 	/* Buffer up the PDU data */
704
 	/* Buffer up the PDU data */
723
 	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
705
 	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
724
 		DBG ( "iSCSI %p could not buffer login response\n", iscsi );
706
 		DBG ( "iSCSI %p could not buffer login response\n", iscsi );
725
-		iscsi_close ( iscsi, rc );
707
+		iscsi_done ( iscsi, rc );
726
 		return;
708
 		return;
727
 	}
709
 	}
728
 	if ( remaining )
710
 	if ( remaining )
747
 	if ( response->status_class != 0 ) {
729
 	if ( response->status_class != 0 ) {
748
 		printf ( "iSCSI login failure: class %02x detail %02x\n",
730
 		printf ( "iSCSI login failure: class %02x detail %02x\n",
749
 			 response->status_class, response->status_detail );
731
 			 response->status_class, response->status_detail );
750
-		iscsi_close ( iscsi, -EPERM );
732
+		iscsi_done ( iscsi, -EPERM );
751
 		return;
733
 		return;
752
 	}
734
 	}
753
 
735
 
765
 		default:
747
 		default:
766
 			DBG ( "iSCSI %p got invalid response flags %02x\n",
748
 			DBG ( "iSCSI %p got invalid response flags %02x\n",
767
 			      iscsi, response->flags );
749
 			      iscsi, response->flags );
768
-			iscsi_close ( iscsi, -EIO );
750
+			iscsi_done ( iscsi, -EIO );
769
 			return;
751
 			return;
770
 		}
752
 		}
771
 	}
753
 	}
1122
  */
1104
  */
1123
 static void iscsi_closed ( struct tcp_connection *conn, int status ) {
1105
 static void iscsi_closed ( struct tcp_connection *conn, int status ) {
1124
 	struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
1106
 	struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
1107
+	int session_status = iscsi->status;
1125
 
1108
 
1126
 	/* Clear session status */
1109
 	/* Clear session status */
1127
 	iscsi->status = 0;
1110
 	iscsi->status = 0;
1128
 
1111
 
1112
+	/* If we are deliberately closing down, exit cleanly */
1113
+	if ( session_status & ISCSI_STATUS_CLOSING ) {
1114
+		iscsi_done ( iscsi, status );
1115
+		return;
1116
+	}
1117
+
1129
 	/* Retry connection if within the retry limit, otherwise fail */
1118
 	/* Retry connection if within the retry limit, otherwise fail */
1130
 	if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
1119
 	if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
1131
 		DBG ( "iSCSI %p retrying connection\n", iscsi );
1120
 		DBG ( "iSCSI %p retrying connection\n", iscsi );
1192
 
1181
 
1193
 	return &iscsi->aop;
1182
 	return &iscsi->aop;
1194
 }
1183
 }
1184
+
1185
+/**
1186
+ * Close down iSCSI session
1187
+ *
1188
+ * @v iscsi		iSCSI session
1189
+ * @ret aop		Asynchronous operation
1190
+ */
1191
+struct async_operation * iscsi_shutdown ( struct iscsi_session *iscsi ) {
1192
+	if ( iscsi->status ) {
1193
+		iscsi->status |= ISCSI_STATUS_CLOSING;
1194
+		tcp_close ( &iscsi->tcp );
1195
+	}
1196
+	return &iscsi->aop;
1197
+}

+ 3
- 1
src/tests/iscsiboot.c View File

32
 	printf ( "Initialising %s\n", target_iqn );
32
 	printf ( "Initialising %s\n", target_iqn );
33
 	if ( ( rc = init_iscsidev ( &test_iscsidev ) ) != 0 ) {
33
 	if ( ( rc = init_iscsidev ( &test_iscsidev ) ) != 0 ) {
34
 		printf ( "Could not reach %s: %s\n", target_iqn,
34
 		printf ( "Could not reach %s: %s\n", target_iqn,
35
-			 strerror ( errno ) );
35
+			 strerror ( rc ) );
36
 		return rc;
36
 		return rc;
37
 	}
37
 	}
38
 	ibft_fill_data ( netdev, initiator_iqn, target, target_iqn );
38
 	ibft_fill_data ( netdev, initiator_iqn, target, target_iqn );
49
 	printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
49
 	printf ( "Unregistering BIOS drive %#02x\n", drive.drive );
50
 	unregister_int13_drive ( &drive );
50
 	unregister_int13_drive ( &drive );
51
 
51
 
52
+	fini_iscsidev ( &test_iscsidev );
53
+
52
 	return rc;
54
 	return rc;
53
 }
55
 }

Loading…
Cancel
Save