Browse Source

Fix TX state machine and miscellaneous other bits.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
fabd0f5fec
1 changed files with 70 additions and 38 deletions
  1. 70
    38
      src/net/tcp/iscsi.c

+ 70
- 38
src/net/tcp/iscsi.c View File

924
 	iscsi->tx_state = ISCSI_TX_BHS;
924
 	iscsi->tx_state = ISCSI_TX_BHS;
925
 }
925
 }
926
 
926
 
927
+/**
928
+ * Transmit nothing
929
+ *
930
+ * @v iscsi		iSCSI session
931
+ * @ret rc		Return status code
932
+ */
933
+static int iscsi_tx_nothing ( struct iscsi_session *iscsi __unused ) {
934
+	return 0;
935
+}
936
+
927
 /**
937
 /**
928
  * Transmit basic header segment of an iSCSI PDU
938
  * Transmit basic header segment of an iSCSI PDU
929
  *
939
  *
953
 	case ISCSI_OPCODE_LOGIN_REQUEST:
963
 	case ISCSI_OPCODE_LOGIN_REQUEST:
954
 		return iscsi_tx_login_request ( iscsi );
964
 		return iscsi_tx_login_request ( iscsi );
955
 	default:
965
 	default:
956
-		assert ( 0 );
957
-		return -EINVAL;
966
+		/* Nothing to send in other states */
967
+		return 0;
958
 	}
968
 	}
959
 }
969
 }
960
 
970
 
1014
 static void iscsi_tx_step ( struct process *process ) {
1024
 static void iscsi_tx_step ( struct process *process ) {
1015
 	struct iscsi_session *iscsi =
1025
 	struct iscsi_session *iscsi =
1016
 		container_of ( process, struct iscsi_session, process );
1026
 		container_of ( process, struct iscsi_session, process );
1017
-	int rc = 0;
1018
-
1019
-	if ( xfer_window ( &iscsi->socket ) == 0 )
1020
-		return;
1027
+	struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1028
+	int ( * tx ) ( struct iscsi_session *iscsi );
1029
+	enum iscsi_tx_state next_state;
1030
+	size_t tx_len;
1031
+	int rc;
1021
 
1032
 
1022
-	switch ( iscsi->tx_state ) {
1023
-	case ISCSI_TX_IDLE:
1024
-		/* Nothing to send */
1025
-		break;
1026
-	case ISCSI_TX_BHS:
1027
-		if ( ( rc = iscsi_tx_bhs ( iscsi ) ) != 0 )
1033
+	/* Select fragment to transmit */
1034
+	while ( 1 ) {
1035
+		switch ( iscsi->tx_state ) {
1036
+		case ISCSI_TX_IDLE:
1037
+			/* Stop processing */
1038
+			return;
1039
+		case ISCSI_TX_BHS:
1040
+			tx = iscsi_tx_bhs;
1041
+			tx_len = sizeof ( iscsi->tx_bhs );
1042
+			next_state = ISCSI_TX_AHS;
1028
 			break;
1043
 			break;
1029
-		iscsi->tx_state = ISCSI_TX_AHS;
1030
-		break;
1031
-	case ISCSI_TX_AHS:
1032
-		/* We don't yet have an AHS transmission mechanism */
1033
-		iscsi->tx_state = ISCSI_TX_DATA;
1034
-		break;
1035
-	case ISCSI_TX_DATA:
1036
-		if ( ( rc = iscsi_tx_data ( iscsi ) ) != 0 )
1044
+		case ISCSI_TX_AHS:
1045
+			tx = iscsi_tx_nothing;
1046
+			tx_len = 0;
1047
+			next_state = ISCSI_TX_DATA;
1037
 			break;
1048
 			break;
1038
-		iscsi->tx_state = ISCSI_TX_DATA_PADDING;
1039
-		break;
1040
-	case ISCSI_TX_DATA_PADDING:
1041
-		if ( ( rc = iscsi_tx_data_padding ( iscsi ) ) != 0 )
1049
+		case ISCSI_TX_DATA:
1050
+			tx = iscsi_tx_data;
1051
+			tx_len = ISCSI_DATA_LEN ( common->lengths );
1052
+			next_state = ISCSI_TX_DATA_PADDING;
1042
 			break;
1053
 			break;
1043
-		iscsi->tx_state = ISCSI_TX_IDLE;
1044
-		iscsi_tx_done ( iscsi );
1045
-		break;
1046
-	default:
1047
-		assert ( 0 );
1048
-		break;
1054
+		case ISCSI_TX_DATA_PADDING:
1055
+			tx = iscsi_tx_data_padding;
1056
+			tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1057
+			next_state = ISCSI_TX_IDLE;
1058
+			break;
1059
+		default:
1060
+			assert ( 0 );
1061
+			return;
1062
+		}
1063
+
1064
+		/* Check for window availability, if needed */
1065
+		if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
1066
+			/* Cannot transmit at this point; stop processing */
1067
+			return;
1068
+		}
1069
+
1070
+		/* Transmit data */
1071
+		if ( ( rc = tx ( iscsi ) ) != 0 ) {
1072
+			DBGC ( iscsi, "iSCSI %p could not transmit: %s\n",
1073
+			       iscsi, strerror ( rc ) );
1074
+			return;
1075
+		}
1076
+
1077
+		/* Move to next state */
1078
+		iscsi->tx_state = next_state;
1079
+		if ( next_state == ISCSI_TX_IDLE )
1080
+			iscsi_tx_done ( iscsi );
1049
 	}
1081
 	}
1050
 }
1082
 }
1051
 
1083
 
1149
 	struct iscsi_session *iscsi =
1181
 	struct iscsi_session *iscsi =
1150
 		container_of ( socket, struct iscsi_session, socket );
1182
 		container_of ( socket, struct iscsi_session, socket );
1151
 	struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
1183
 	struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
1152
-	int ( *process ) ( struct iscsi_session *iscsi, const void *data,
1153
-			   size_t len, size_t remaining );
1184
+	int ( * rx ) ( struct iscsi_session *iscsi, const void *data,
1185
+		       size_t len, size_t remaining );
1154
 	enum iscsi_rx_state next_state;
1186
 	enum iscsi_rx_state next_state;
1155
 	size_t frag_len;
1187
 	size_t frag_len;
1156
 	size_t remaining;
1188
 	size_t remaining;
1159
 	while ( 1 ) {
1191
 	while ( 1 ) {
1160
 		switch ( iscsi->rx_state ) {
1192
 		switch ( iscsi->rx_state ) {
1161
 		case ISCSI_RX_BHS:
1193
 		case ISCSI_RX_BHS:
1162
-			process = iscsi_rx_bhs;
1194
+			rx = iscsi_rx_bhs;
1163
 			iscsi->rx_len = sizeof ( iscsi->rx_bhs );
1195
 			iscsi->rx_len = sizeof ( iscsi->rx_bhs );
1164
 			next_state = ISCSI_RX_AHS;			
1196
 			next_state = ISCSI_RX_AHS;			
1165
 			break;
1197
 			break;
1166
 		case ISCSI_RX_AHS:
1198
 		case ISCSI_RX_AHS:
1167
-			process = iscsi_rx_discard;
1199
+			rx = iscsi_rx_discard;
1168
 			iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
1200
 			iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
1169
 			next_state = ISCSI_RX_DATA;
1201
 			next_state = ISCSI_RX_DATA;
1170
 			break;
1202
 			break;
1171
 		case ISCSI_RX_DATA:
1203
 		case ISCSI_RX_DATA:
1172
-			process = iscsi_rx_data;
1204
+			rx = iscsi_rx_data;
1173
 			iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
1205
 			iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
1174
 			next_state = ISCSI_RX_DATA_PADDING;
1206
 			next_state = ISCSI_RX_DATA_PADDING;
1175
 			break;
1207
 			break;
1176
 		case ISCSI_RX_DATA_PADDING:
1208
 		case ISCSI_RX_DATA_PADDING:
1177
-			process = iscsi_rx_discard;
1209
+			rx = iscsi_rx_discard;
1178
 			iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1210
 			iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1179
 			next_state = ISCSI_RX_BHS;
1211
 			next_state = ISCSI_RX_BHS;
1180
 			break;
1212
 			break;
1187
 		if ( frag_len > len )
1219
 		if ( frag_len > len )
1188
 			frag_len = len;
1220
 			frag_len = len;
1189
 		remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
1221
 		remaining = iscsi->rx_len - iscsi->rx_offset - frag_len;
1190
-		if ( ( rc = process ( iscsi, data, frag_len,
1191
-				      remaining ) ) != 0 ) {
1222
+		if ( ( rc = rx ( iscsi, data, frag_len, remaining ) ) != 0 ) {
1192
 			DBGC ( iscsi, "iSCSI %p could not process received "
1223
 			DBGC ( iscsi, "iSCSI %p could not process received "
1193
 			       "data: %s\n", iscsi, strerror ( rc ) );
1224
 			       "data: %s\n", iscsi, strerror ( rc ) );
1194
 			iscsi_close_connection ( iscsi, rc );
1225
 			iscsi_close_connection ( iscsi, rc );
1320
 	struct iscsi_session *iscsi =
1351
 	struct iscsi_session *iscsi =
1321
 		container_of ( scsi->backend, struct iscsi_session, refcnt );
1352
 		container_of ( scsi->backend, struct iscsi_session, refcnt );
1322
 
1353
 
1354
+	xfer_nullify ( &iscsi->socket );
1323
 	iscsi_close_connection ( iscsi, 0 );
1355
 	iscsi_close_connection ( iscsi, 0 );
1324
 	process_del ( &iscsi->process );
1356
 	process_del ( &iscsi->process );
1325
 	scsi->command = iscsi_detached_command;
1357
 	scsi->command = iscsi_detached_command;

Loading…
Cancel
Save