@@ -1994,6 +1994,7 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
19941994 cmd -> cmd_sn = be32_to_cpu (hdr -> cmdsn );
19951995 cmd -> exp_stat_sn = be32_to_cpu (hdr -> exp_statsn );
19961996 cmd -> data_direction = DMA_NONE ;
1997+ cmd -> text_in_ptr = NULL ;
19971998
19981999 return 0 ;
19992000}
@@ -2007,9 +2008,13 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
20072008 int cmdsn_ret ;
20082009
20092010 if (!text_in ) {
2010- pr_err ("Unable to locate text_in buffer for sendtargets"
2011- " discovery\n" );
2012- goto reject ;
2011+ cmd -> targ_xfer_tag = be32_to_cpu (hdr -> ttt );
2012+ if (cmd -> targ_xfer_tag == 0xFFFFFFFF ) {
2013+ pr_err ("Unable to locate text_in buffer for sendtargets"
2014+ " discovery\n" );
2015+ goto reject ;
2016+ }
2017+ goto empty_sendtargets ;
20132018 }
20142019 if (strncmp ("SendTargets" , text_in , 11 ) != 0 ) {
20152020 pr_err ("Received Text Data that is not"
@@ -2036,6 +2041,7 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
20362041 list_add_tail (& cmd -> i_conn_node , & conn -> conn_cmd_list );
20372042 spin_unlock_bh (& conn -> cmd_lock );
20382043
2044+ empty_sendtargets :
20392045 iscsit_ack_from_expstatsn (conn , be32_to_cpu (hdr -> exp_statsn ));
20402046
20412047 if (!(hdr -> opcode & ISCSI_OP_IMMEDIATE )) {
@@ -3385,7 +3391,8 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
33853391
33863392static int
33873393iscsit_build_sendtargets_response (struct iscsi_cmd * cmd ,
3388- enum iscsit_transport_type network_transport )
3394+ enum iscsit_transport_type network_transport ,
3395+ int skip_bytes , bool * completed )
33893396{
33903397 char * payload = NULL ;
33913398 struct iscsi_conn * conn = cmd -> conn ;
@@ -3476,9 +3483,16 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
34763483 end_of_buf = 1 ;
34773484 goto eob ;
34783485 }
3479- memcpy (payload + payload_len , buf , len );
3480- payload_len += len ;
3481- target_name_printed = 1 ;
3486+
3487+ if (skip_bytes && len <= skip_bytes ) {
3488+ skip_bytes -= len ;
3489+ } else {
3490+ memcpy (payload + payload_len , buf , len );
3491+ payload_len += len ;
3492+ target_name_printed = 1 ;
3493+ if (len > skip_bytes )
3494+ skip_bytes = 0 ;
3495+ }
34823496 }
34833497
34843498 len = sprintf (buf , "TargetAddress="
@@ -3494,15 +3508,24 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
34943508 end_of_buf = 1 ;
34953509 goto eob ;
34963510 }
3497- memcpy (payload + payload_len , buf , len );
3498- payload_len += len ;
3511+
3512+ if (skip_bytes && len <= skip_bytes ) {
3513+ skip_bytes -= len ;
3514+ } else {
3515+ memcpy (payload + payload_len , buf , len );
3516+ payload_len += len ;
3517+ if (len > skip_bytes )
3518+ skip_bytes = 0 ;
3519+ }
34993520 }
35003521 spin_unlock (& tpg -> tpg_np_lock );
35013522 }
35023523 spin_unlock (& tiqn -> tiqn_tpg_lock );
35033524eob :
3504- if (end_of_buf )
3525+ if (end_of_buf ) {
3526+ * completed = false;
35053527 break ;
3528+ }
35063529
35073530 if (cmd -> cmd_flags & IFC_SENDTARGETS_SINGLE )
35083531 break ;
@@ -3520,13 +3543,23 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
35203543 enum iscsit_transport_type network_transport )
35213544{
35223545 int text_length , padding ;
3546+ bool completed = true;
35233547
3524- text_length = iscsit_build_sendtargets_response (cmd , network_transport );
3548+ text_length = iscsit_build_sendtargets_response (cmd , network_transport ,
3549+ cmd -> read_data_done ,
3550+ & completed );
35253551 if (text_length < 0 )
35263552 return text_length ;
35273553
3554+ if (completed ) {
3555+ hdr -> flags |= ISCSI_FLAG_CMD_FINAL ;
3556+ } else {
3557+ hdr -> flags |= ISCSI_FLAG_TEXT_CONTINUE ;
3558+ cmd -> read_data_done += text_length ;
3559+ if (cmd -> targ_xfer_tag == 0xFFFFFFFF )
3560+ cmd -> targ_xfer_tag = session_get_next_ttt (conn -> sess );
3561+ }
35283562 hdr -> opcode = ISCSI_OP_TEXT_RSP ;
3529- hdr -> flags |= ISCSI_FLAG_CMD_FINAL ;
35303563 padding = ((- text_length ) & 3 );
35313564 hton24 (hdr -> dlength , text_length );
35323565 hdr -> itt = cmd -> init_task_tag ;
@@ -3535,21 +3568,25 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
35353568 hdr -> statsn = cpu_to_be32 (cmd -> stat_sn );
35363569
35373570 iscsit_increment_maxcmdsn (cmd , conn -> sess );
3571+ /*
3572+ * Reset maxcmdsn_inc in multi-part text payload exchanges to
3573+ * correctly increment MaxCmdSN for each response answering a
3574+ * non immediate text request with a valid CmdSN.
3575+ */
3576+ cmd -> maxcmdsn_inc = 0 ;
35383577 hdr -> exp_cmdsn = cpu_to_be32 (conn -> sess -> exp_cmd_sn );
35393578 hdr -> max_cmdsn = cpu_to_be32 (conn -> sess -> max_cmd_sn );
35403579
3541- pr_debug ("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x,"
3542- " Length: %u, CID: %hu\n" , cmd -> init_task_tag , cmd -> stat_sn ,
3543- text_length , conn -> cid );
3580+ pr_debug ("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
3581+ " Length: %u, CID: %hu F: %d C: %d\n" , cmd -> init_task_tag ,
3582+ cmd -> targ_xfer_tag , cmd -> stat_sn , text_length , conn -> cid ,
3583+ !!(hdr -> flags & ISCSI_FLAG_CMD_FINAL ),
3584+ !!(hdr -> flags & ISCSI_FLAG_TEXT_CONTINUE ));
35443585
35453586 return text_length + padding ;
35463587}
35473588EXPORT_SYMBOL (iscsit_build_text_rsp );
35483589
3549- /*
3550- * FIXME: Add support for F_BIT and C_BIT when the length is longer than
3551- * MaxRecvDataSegmentLength.
3552- */
35533590static int iscsit_send_text_rsp (
35543591 struct iscsi_cmd * cmd ,
35553592 struct iscsi_conn * conn )
@@ -4013,9 +4050,15 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
40134050 ret = iscsit_handle_task_mgt_cmd (conn , cmd , buf );
40144051 break ;
40154052 case ISCSI_OP_TEXT :
4016- cmd = iscsit_allocate_cmd (conn , TASK_INTERRUPTIBLE );
4017- if (!cmd )
4018- goto reject ;
4053+ if (hdr -> ttt != cpu_to_be32 (0xFFFFFFFF )) {
4054+ cmd = iscsit_find_cmd_from_itt (conn , hdr -> itt );
4055+ if (!cmd )
4056+ goto reject ;
4057+ } else {
4058+ cmd = iscsit_allocate_cmd (conn , TASK_INTERRUPTIBLE );
4059+ if (!cmd )
4060+ goto reject ;
4061+ }
40194062
40204063 ret = iscsit_handle_text_cmd (conn , cmd , buf );
40214064 break ;
0 commit comments