|
@@ -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;
|