Преглед на файлове

Fix TX state machine and miscellaneous other bits.

tags/v0.9.3
Michael Brown преди 17 години
родител
ревизия
fabd0f5fec
променени са 1 файла, в които са добавени 70 реда и са изтрити 38 реда
  1. 70
    38
      src/net/tcp/iscsi.c

+ 70
- 38
src/net/tcp/iscsi.c Целия файл

@@ -924,6 +924,16 @@ static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
924 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 938
  * Transmit basic header segment of an iSCSI PDU
929 939
  *
@@ -953,8 +963,8 @@ static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
953 963
 	case ISCSI_OPCODE_LOGIN_REQUEST:
954 964
 		return iscsi_tx_login_request ( iscsi );
955 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,38 +1024,60 @@ static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
1014 1024
 static void iscsi_tx_step ( struct process *process ) {
1015 1025
 	struct iscsi_session *iscsi =
1016 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 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 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 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,8 +1181,8 @@ static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
1149 1181
 	struct iscsi_session *iscsi =
1150 1182
 		container_of ( socket, struct iscsi_session, socket );
1151 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 1186
 	enum iscsi_rx_state next_state;
1155 1187
 	size_t frag_len;
1156 1188
 	size_t remaining;
@@ -1159,22 +1191,22 @@ static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
1159 1191
 	while ( 1 ) {
1160 1192
 		switch ( iscsi->rx_state ) {
1161 1193
 		case ISCSI_RX_BHS:
1162
-			process = iscsi_rx_bhs;
1194
+			rx = iscsi_rx_bhs;
1163 1195
 			iscsi->rx_len = sizeof ( iscsi->rx_bhs );
1164 1196
 			next_state = ISCSI_RX_AHS;			
1165 1197
 			break;
1166 1198
 		case ISCSI_RX_AHS:
1167
-			process = iscsi_rx_discard;
1199
+			rx = iscsi_rx_discard;
1168 1200
 			iscsi->rx_len = 4 * ISCSI_AHS_LEN ( common->lengths );
1169 1201
 			next_state = ISCSI_RX_DATA;
1170 1202
 			break;
1171 1203
 		case ISCSI_RX_DATA:
1172
-			process = iscsi_rx_data;
1204
+			rx = iscsi_rx_data;
1173 1205
 			iscsi->rx_len = ISCSI_DATA_LEN ( common->lengths );
1174 1206
 			next_state = ISCSI_RX_DATA_PADDING;
1175 1207
 			break;
1176 1208
 		case ISCSI_RX_DATA_PADDING:
1177
-			process = iscsi_rx_discard;
1209
+			rx = iscsi_rx_discard;
1178 1210
 			iscsi->rx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1179 1211
 			next_state = ISCSI_RX_BHS;
1180 1212
 			break;
@@ -1187,8 +1219,7 @@ static int iscsi_socket_deliver_raw ( struct xfer_interface *socket,
1187 1219
 		if ( frag_len > len )
1188 1220
 			frag_len = len;
1189 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 1223
 			DBGC ( iscsi, "iSCSI %p could not process received "
1193 1224
 			       "data: %s\n", iscsi, strerror ( rc ) );
1194 1225
 			iscsi_close_connection ( iscsi, rc );
@@ -1320,6 +1351,7 @@ void iscsi_detach ( struct scsi_device *scsi ) {
1320 1351
 	struct iscsi_session *iscsi =
1321 1352
 		container_of ( scsi->backend, struct iscsi_session, refcnt );
1322 1353
 
1354
+	xfer_nullify ( &iscsi->socket );
1323 1355
 	iscsi_close_connection ( iscsi, 0 );
1324 1356
 	process_del ( &iscsi->process );
1325 1357
 	scsi->command = iscsi_detached_command;

Loading…
Отказ
Запис