root/drivers/target/iscsi/iscsi_target_tmr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iscsit_tmr_abort_task
  2. iscsit_tmr_task_warm_reset
  3. iscsit_tmr_task_cold_reset
  4. iscsit_tmr_task_reassign
  5. iscsit_task_reassign_remove_cmd
  6. iscsit_task_reassign_complete_nop_out
  7. iscsit_task_reassign_complete_write
  8. iscsit_task_reassign_complete_read
  9. iscsit_task_reassign_complete_none
  10. iscsit_task_reassign_complete_scsi_cmnd
  11. iscsit_task_reassign_complete
  12. iscsit_tmr_post_handler
  13. iscsit_task_reassign_prepare_read
  14. iscsit_task_reassign_prepare_unsolicited_dataout
  15. iscsit_task_reassign_prepare_write
  16. iscsit_check_task_reassign_expdatasn

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*******************************************************************************
   3  * This file contains the iSCSI Target specific Task Management functions.
   4  *
   5  * (c) Copyright 2007-2013 Datera, Inc.
   6  *
   7  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
   8  *
   9  ******************************************************************************/
  10 
  11 #include <asm/unaligned.h>
  12 #include <scsi/scsi_proto.h>
  13 #include <scsi/iscsi_proto.h>
  14 #include <target/target_core_base.h>
  15 #include <target/target_core_fabric.h>
  16 #include <target/iscsi/iscsi_transport.h>
  17 
  18 #include <target/iscsi/iscsi_target_core.h>
  19 #include "iscsi_target_seq_pdu_list.h"
  20 #include "iscsi_target_datain_values.h"
  21 #include "iscsi_target_device.h"
  22 #include "iscsi_target_erl0.h"
  23 #include "iscsi_target_erl1.h"
  24 #include "iscsi_target_erl2.h"
  25 #include "iscsi_target_tmr.h"
  26 #include "iscsi_target_tpg.h"
  27 #include "iscsi_target_util.h"
  28 #include "iscsi_target.h"
  29 
  30 u8 iscsit_tmr_abort_task(
  31         struct iscsi_cmd *cmd,
  32         unsigned char *buf)
  33 {
  34         struct iscsi_cmd *ref_cmd;
  35         struct iscsi_conn *conn = cmd->conn;
  36         struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
  37         struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
  38         struct iscsi_tm *hdr = (struct iscsi_tm *) buf;
  39 
  40         ref_cmd = iscsit_find_cmd_from_itt(conn, hdr->rtt);
  41         if (!ref_cmd) {
  42                 pr_err("Unable to locate RefTaskTag: 0x%08x on CID:"
  43                         " %hu.\n", hdr->rtt, conn->cid);
  44                 return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) &&
  45                         iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), (u32) atomic_read(&conn->sess->max_cmd_sn))) ?
  46                         ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK;
  47         }
  48         if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) {
  49                 pr_err("RefCmdSN 0x%08x does not equal"
  50                         " task's CmdSN 0x%08x. Rejecting ABORT_TASK.\n",
  51                         hdr->refcmdsn, ref_cmd->cmd_sn);
  52                 return ISCSI_TMF_RSP_REJECTED;
  53         }
  54 
  55         se_tmr->ref_task_tag            = (__force u32)hdr->rtt;
  56         tmr_req->ref_cmd                = ref_cmd;
  57         tmr_req->exp_data_sn            = be32_to_cpu(hdr->exp_datasn);
  58 
  59         return ISCSI_TMF_RSP_COMPLETE;
  60 }
  61 
  62 /*
  63  *      Called from iscsit_handle_task_mgt_cmd().
  64  */
  65 int iscsit_tmr_task_warm_reset(
  66         struct iscsi_conn *conn,
  67         struct iscsi_tmr_req *tmr_req,
  68         unsigned char *buf)
  69 {
  70         struct iscsi_session *sess = conn->sess;
  71         struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
  72 
  73         if (!na->tmr_warm_reset) {
  74                 pr_err("TMR Opcode TARGET_WARM_RESET authorization"
  75                         " failed for Initiator Node: %s\n",
  76                         sess->se_sess->se_node_acl->initiatorname);
  77                 return -1;
  78         }
  79         /*
  80          * Do the real work in transport_generic_do_tmr().
  81          */
  82         return 0;
  83 }
  84 
  85 int iscsit_tmr_task_cold_reset(
  86         struct iscsi_conn *conn,
  87         struct iscsi_tmr_req *tmr_req,
  88         unsigned char *buf)
  89 {
  90         struct iscsi_session *sess = conn->sess;
  91         struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
  92 
  93         if (!na->tmr_cold_reset) {
  94                 pr_err("TMR Opcode TARGET_COLD_RESET authorization"
  95                         " failed for Initiator Node: %s\n",
  96                         sess->se_sess->se_node_acl->initiatorname);
  97                 return -1;
  98         }
  99         /*
 100          * Do the real work in transport_generic_do_tmr().
 101          */
 102         return 0;
 103 }
 104 
 105 u8 iscsit_tmr_task_reassign(
 106         struct iscsi_cmd *cmd,
 107         unsigned char *buf)
 108 {
 109         struct iscsi_cmd *ref_cmd = NULL;
 110         struct iscsi_conn *conn = cmd->conn;
 111         struct iscsi_conn_recovery *cr = NULL;
 112         struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
 113         struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
 114         struct iscsi_tm *hdr = (struct iscsi_tm *) buf;
 115         u64 ret, ref_lun;
 116 
 117         pr_debug("Got TASK_REASSIGN TMR ITT: 0x%08x,"
 118                 " RefTaskTag: 0x%08x, ExpDataSN: 0x%08x, CID: %hu\n",
 119                 hdr->itt, hdr->rtt, hdr->exp_datasn, conn->cid);
 120 
 121         if (conn->sess->sess_ops->ErrorRecoveryLevel != 2) {
 122                 pr_err("TMR TASK_REASSIGN not supported in ERL<2,"
 123                                 " ignoring request.\n");
 124                 return ISCSI_TMF_RSP_NOT_SUPPORTED;
 125         }
 126 
 127         ret = iscsit_find_cmd_for_recovery(conn->sess, &ref_cmd, &cr, hdr->rtt);
 128         if (ret == -2) {
 129                 pr_err("Command ITT: 0x%08x is still alligent to CID:"
 130                         " %hu\n", ref_cmd->init_task_tag, cr->cid);
 131                 return ISCSI_TMF_RSP_TASK_ALLEGIANT;
 132         } else if (ret == -1) {
 133                 pr_err("Unable to locate RefTaskTag: 0x%08x in"
 134                         " connection recovery command list.\n", hdr->rtt);
 135                 return ISCSI_TMF_RSP_NO_TASK;
 136         }
 137         /*
 138          * Temporary check to prevent connection recovery for
 139          * connections with a differing Max*DataSegmentLength.
 140          */
 141         if (cr->maxrecvdatasegmentlength !=
 142             conn->conn_ops->MaxRecvDataSegmentLength) {
 143                 pr_err("Unable to perform connection recovery for"
 144                         " differing MaxRecvDataSegmentLength, rejecting"
 145                         " TMR TASK_REASSIGN.\n");
 146                 return ISCSI_TMF_RSP_REJECTED;
 147         }
 148         if (cr->maxxmitdatasegmentlength !=
 149             conn->conn_ops->MaxXmitDataSegmentLength) {
 150                 pr_err("Unable to perform connection recovery for"
 151                         " differing MaxXmitDataSegmentLength, rejecting"
 152                         " TMR TASK_REASSIGN.\n");
 153                 return ISCSI_TMF_RSP_REJECTED;
 154         }
 155 
 156         ref_lun = scsilun_to_int(&hdr->lun);
 157         if (ref_lun != ref_cmd->se_cmd.orig_fe_lun) {
 158                 pr_err("Unable to perform connection recovery for"
 159                         " differing ref_lun: %llu ref_cmd orig_fe_lun: %llu\n",
 160                         ref_lun, ref_cmd->se_cmd.orig_fe_lun);
 161                 return ISCSI_TMF_RSP_REJECTED;
 162         }
 163 
 164         se_tmr->ref_task_tag            = (__force u32)hdr->rtt;
 165         tmr_req->ref_cmd                = ref_cmd;
 166         tmr_req->exp_data_sn            = be32_to_cpu(hdr->exp_datasn);
 167         tmr_req->conn_recovery          = cr;
 168         tmr_req->task_reassign          = 1;
 169         /*
 170          * Command can now be reassigned to a new connection.
 171          * The task management response must be sent before the
 172          * reassignment actually happens.  See iscsi_tmr_post_handler().
 173          */
 174         return ISCSI_TMF_RSP_COMPLETE;
 175 }
 176 
 177 static void iscsit_task_reassign_remove_cmd(
 178         struct iscsi_cmd *cmd,
 179         struct iscsi_conn_recovery *cr,
 180         struct iscsi_session *sess)
 181 {
 182         int ret;
 183 
 184         spin_lock(&cr->conn_recovery_cmd_lock);
 185         ret = iscsit_remove_cmd_from_connection_recovery(cmd, sess);
 186         spin_unlock(&cr->conn_recovery_cmd_lock);
 187         if (!ret) {
 188                 pr_debug("iSCSI connection recovery successful for CID:"
 189                         " %hu on SID: %u\n", cr->cid, sess->sid);
 190                 iscsit_remove_active_connection_recovery_entry(cr, sess);
 191         }
 192 }
 193 
 194 static int iscsit_task_reassign_complete_nop_out(
 195         struct iscsi_tmr_req *tmr_req,
 196         struct iscsi_conn *conn)
 197 {
 198         struct iscsi_cmd *cmd = tmr_req->ref_cmd;
 199         struct iscsi_conn_recovery *cr;
 200 
 201         if (!cmd->cr) {
 202                 pr_err("struct iscsi_conn_recovery pointer for ITT: 0x%08x"
 203                         " is NULL!\n", cmd->init_task_tag);
 204                 return -1;
 205         }
 206         cr = cmd->cr;
 207 
 208         /*
 209          * Reset the StatSN so a new one for this commands new connection
 210          * will be assigned.
 211          * Reset the ExpStatSN as well so we may receive Status SNACKs.
 212          */
 213         cmd->stat_sn = cmd->exp_stat_sn = 0;
 214 
 215         iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
 216 
 217         spin_lock_bh(&conn->cmd_lock);
 218         list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
 219         spin_unlock_bh(&conn->cmd_lock);
 220 
 221         cmd->i_state = ISTATE_SEND_NOPIN;
 222         iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 223         return 0;
 224 }
 225 
 226 static int iscsit_task_reassign_complete_write(
 227         struct iscsi_cmd *cmd,
 228         struct iscsi_tmr_req *tmr_req)
 229 {
 230         int no_build_r2ts = 0;
 231         u32 length = 0, offset = 0;
 232         struct iscsi_conn *conn = cmd->conn;
 233         struct se_cmd *se_cmd = &cmd->se_cmd;
 234         /*
 235          * The Initiator must not send a R2T SNACK with a Begrun less than
 236          * the TMR TASK_REASSIGN's ExpDataSN.
 237          */
 238         if (!tmr_req->exp_data_sn) {
 239                 cmd->cmd_flags &= ~ICF_GOT_DATACK_SNACK;
 240                 cmd->acked_data_sn = 0;
 241         } else {
 242                 cmd->cmd_flags |= ICF_GOT_DATACK_SNACK;
 243                 cmd->acked_data_sn = (tmr_req->exp_data_sn - 1);
 244         }
 245 
 246         /*
 247          * The TMR TASK_REASSIGN's ExpDataSN contains the next R2TSN the
 248          * Initiator is expecting.  The Target controls all WRITE operations
 249          * so if we have received all DataOUT we can safety ignore Initiator.
 250          */
 251         if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
 252                 if (!(cmd->se_cmd.transport_state & CMD_T_SENT)) {
 253                         pr_debug("WRITE ITT: 0x%08x: t_state: %d"
 254                                 " never sent to transport\n",
 255                                 cmd->init_task_tag, cmd->se_cmd.t_state);
 256                         target_execute_cmd(se_cmd);
 257                         return 0;
 258                 }
 259 
 260                 cmd->i_state = ISTATE_SEND_STATUS;
 261                 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 262                 return 0;
 263         }
 264 
 265         /*
 266          * Special case to deal with DataSequenceInOrder=No and Non-Immeidate
 267          * Unsolicited DataOut.
 268          */
 269         if (cmd->unsolicited_data) {
 270                 cmd->unsolicited_data = 0;
 271 
 272                 offset = cmd->next_burst_len = cmd->write_data_done;
 273 
 274                 if ((conn->sess->sess_ops->FirstBurstLength - offset) >=
 275                      cmd->se_cmd.data_length) {
 276                         no_build_r2ts = 1;
 277                         length = (cmd->se_cmd.data_length - offset);
 278                 } else
 279                         length = (conn->sess->sess_ops->FirstBurstLength - offset);
 280 
 281                 spin_lock_bh(&cmd->r2t_lock);
 282                 if (iscsit_add_r2t_to_list(cmd, offset, length, 0, 0) < 0) {
 283                         spin_unlock_bh(&cmd->r2t_lock);
 284                         return -1;
 285                 }
 286                 cmd->outstanding_r2ts++;
 287                 spin_unlock_bh(&cmd->r2t_lock);
 288 
 289                 if (no_build_r2ts)
 290                         return 0;
 291         }
 292         /*
 293          * iscsit_build_r2ts_for_cmd() can handle the rest from here.
 294          */
 295         return conn->conn_transport->iscsit_get_dataout(conn, cmd, true);
 296 }
 297 
 298 static int iscsit_task_reassign_complete_read(
 299         struct iscsi_cmd *cmd,
 300         struct iscsi_tmr_req *tmr_req)
 301 {
 302         struct iscsi_conn *conn = cmd->conn;
 303         struct iscsi_datain_req *dr;
 304         struct se_cmd *se_cmd = &cmd->se_cmd;
 305         /*
 306          * The Initiator must not send a Data SNACK with a BegRun less than
 307          * the TMR TASK_REASSIGN's ExpDataSN.
 308          */
 309         if (!tmr_req->exp_data_sn) {
 310                 cmd->cmd_flags &= ~ICF_GOT_DATACK_SNACK;
 311                 cmd->acked_data_sn = 0;
 312         } else {
 313                 cmd->cmd_flags |= ICF_GOT_DATACK_SNACK;
 314                 cmd->acked_data_sn = (tmr_req->exp_data_sn - 1);
 315         }
 316 
 317         if (!(cmd->se_cmd.transport_state & CMD_T_SENT)) {
 318                 pr_debug("READ ITT: 0x%08x: t_state: %d never sent to"
 319                         " transport\n", cmd->init_task_tag,
 320                         cmd->se_cmd.t_state);
 321                 transport_handle_cdb_direct(se_cmd);
 322                 return 0;
 323         }
 324 
 325         if (!(se_cmd->transport_state & CMD_T_COMPLETE)) {
 326                 pr_err("READ ITT: 0x%08x: t_state: %d, never returned"
 327                         " from transport\n", cmd->init_task_tag,
 328                         cmd->se_cmd.t_state);
 329                 return -1;
 330         }
 331 
 332         dr = iscsit_allocate_datain_req();
 333         if (!dr)
 334                 return -1;
 335         /*
 336          * The TMR TASK_REASSIGN's ExpDataSN contains the next DataSN the
 337          * Initiator is expecting.
 338          */
 339         dr->data_sn = dr->begrun = tmr_req->exp_data_sn;
 340         dr->runlength = 0;
 341         dr->generate_recovery_values = 1;
 342         dr->recovery = DATAIN_CONNECTION_RECOVERY;
 343 
 344         iscsit_attach_datain_req(cmd, dr);
 345 
 346         cmd->i_state = ISTATE_SEND_DATAIN;
 347         iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 348         return 0;
 349 }
 350 
 351 static int iscsit_task_reassign_complete_none(
 352         struct iscsi_cmd *cmd,
 353         struct iscsi_tmr_req *tmr_req)
 354 {
 355         struct iscsi_conn *conn = cmd->conn;
 356 
 357         cmd->i_state = ISTATE_SEND_STATUS;
 358         iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 359         return 0;
 360 }
 361 
 362 static int iscsit_task_reassign_complete_scsi_cmnd(
 363         struct iscsi_tmr_req *tmr_req,
 364         struct iscsi_conn *conn)
 365 {
 366         struct iscsi_cmd *cmd = tmr_req->ref_cmd;
 367         struct iscsi_conn_recovery *cr;
 368 
 369         if (!cmd->cr) {
 370                 pr_err("struct iscsi_conn_recovery pointer for ITT: 0x%08x"
 371                         " is NULL!\n", cmd->init_task_tag);
 372                 return -1;
 373         }
 374         cr = cmd->cr;
 375 
 376         /*
 377          * Reset the StatSN so a new one for this commands new connection
 378          * will be assigned.
 379          * Reset the ExpStatSN as well so we may receive Status SNACKs.
 380          */
 381         cmd->stat_sn = cmd->exp_stat_sn = 0;
 382 
 383         iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
 384 
 385         spin_lock_bh(&conn->cmd_lock);
 386         list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
 387         spin_unlock_bh(&conn->cmd_lock);
 388 
 389         if (cmd->se_cmd.se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
 390                 cmd->i_state = ISTATE_SEND_STATUS;
 391                 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
 392                 return 0;
 393         }
 394 
 395         switch (cmd->data_direction) {
 396         case DMA_TO_DEVICE:
 397                 return iscsit_task_reassign_complete_write(cmd, tmr_req);
 398         case DMA_FROM_DEVICE:
 399                 return iscsit_task_reassign_complete_read(cmd, tmr_req);
 400         case DMA_NONE:
 401                 return iscsit_task_reassign_complete_none(cmd, tmr_req);
 402         default:
 403                 pr_err("Unknown cmd->data_direction: 0x%02x\n",
 404                                 cmd->data_direction);
 405                 return -1;
 406         }
 407 
 408         return 0;
 409 }
 410 
 411 static int iscsit_task_reassign_complete(
 412         struct iscsi_tmr_req *tmr_req,
 413         struct iscsi_conn *conn)
 414 {
 415         struct iscsi_cmd *cmd;
 416         int ret = 0;
 417 
 418         if (!tmr_req->ref_cmd) {
 419                 pr_err("TMR Request is missing a RefCmd struct iscsi_cmd.\n");
 420                 return -1;
 421         }
 422         cmd = tmr_req->ref_cmd;
 423 
 424         cmd->conn = conn;
 425 
 426         switch (cmd->iscsi_opcode) {
 427         case ISCSI_OP_NOOP_OUT:
 428                 ret = iscsit_task_reassign_complete_nop_out(tmr_req, conn);
 429                 break;
 430         case ISCSI_OP_SCSI_CMD:
 431                 ret = iscsit_task_reassign_complete_scsi_cmnd(tmr_req, conn);
 432                 break;
 433         default:
 434                  pr_err("Illegal iSCSI Opcode 0x%02x during"
 435                         " command reallegiance\n", cmd->iscsi_opcode);
 436                 return -1;
 437         }
 438 
 439         if (ret != 0)
 440                 return ret;
 441 
 442         pr_debug("Completed connection reallegiance for Opcode: 0x%02x,"
 443                 " ITT: 0x%08x to CID: %hu.\n", cmd->iscsi_opcode,
 444                         cmd->init_task_tag, conn->cid);
 445 
 446         return 0;
 447 }
 448 
 449 /*
 450  *      Handles special after-the-fact actions related to TMRs.
 451  *      Right now the only one that its really needed for is
 452  *      connection recovery releated TASK_REASSIGN.
 453  */
 454 int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 455 {
 456         struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
 457         struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
 458 
 459         if (tmr_req->task_reassign &&
 460            (se_tmr->response == ISCSI_TMF_RSP_COMPLETE))
 461                 return iscsit_task_reassign_complete(tmr_req, conn);
 462 
 463         return 0;
 464 }
 465 EXPORT_SYMBOL(iscsit_tmr_post_handler);
 466 
 467 /*
 468  *      Nothing to do here, but leave it for good measure. :-)
 469  */
 470 static int iscsit_task_reassign_prepare_read(
 471         struct iscsi_tmr_req *tmr_req,
 472         struct iscsi_conn *conn)
 473 {
 474         return 0;
 475 }
 476 
 477 static void iscsit_task_reassign_prepare_unsolicited_dataout(
 478         struct iscsi_cmd *cmd,
 479         struct iscsi_conn *conn)
 480 {
 481         int i, j;
 482         struct iscsi_pdu *pdu = NULL;
 483         struct iscsi_seq *seq = NULL;
 484 
 485         if (conn->sess->sess_ops->DataSequenceInOrder) {
 486                 cmd->data_sn = 0;
 487 
 488                 if (cmd->immediate_data)
 489                         cmd->r2t_offset += (cmd->first_burst_len -
 490                                 cmd->seq_start_offset);
 491 
 492                 if (conn->sess->sess_ops->DataPDUInOrder) {
 493                         cmd->write_data_done -= (cmd->immediate_data) ?
 494                                                 (cmd->first_burst_len -
 495                                                  cmd->seq_start_offset) :
 496                                                  cmd->first_burst_len;
 497                         cmd->first_burst_len = 0;
 498                         return;
 499                 }
 500 
 501                 for (i = 0; i < cmd->pdu_count; i++) {
 502                         pdu = &cmd->pdu_list[i];
 503 
 504                         if (pdu->status != ISCSI_PDU_RECEIVED_OK)
 505                                 continue;
 506 
 507                         if ((pdu->offset >= cmd->seq_start_offset) &&
 508                            ((pdu->offset + pdu->length) <=
 509                              cmd->seq_end_offset)) {
 510                                 cmd->first_burst_len -= pdu->length;
 511                                 cmd->write_data_done -= pdu->length;
 512                                 pdu->status = ISCSI_PDU_NOT_RECEIVED;
 513                         }
 514                 }
 515         } else {
 516                 for (i = 0; i < cmd->seq_count; i++) {
 517                         seq = &cmd->seq_list[i];
 518 
 519                         if (seq->type != SEQTYPE_UNSOLICITED)
 520                                 continue;
 521 
 522                         cmd->write_data_done -=
 523                                         (seq->offset - seq->orig_offset);
 524                         cmd->first_burst_len = 0;
 525                         seq->data_sn = 0;
 526                         seq->offset = seq->orig_offset;
 527                         seq->next_burst_len = 0;
 528                         seq->status = DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY;
 529 
 530                         if (conn->sess->sess_ops->DataPDUInOrder)
 531                                 continue;
 532 
 533                         for (j = 0; j < seq->pdu_count; j++) {
 534                                 pdu = &cmd->pdu_list[j+seq->pdu_start];
 535 
 536                                 if (pdu->status != ISCSI_PDU_RECEIVED_OK)
 537                                         continue;
 538 
 539                                 pdu->status = ISCSI_PDU_NOT_RECEIVED;
 540                         }
 541                 }
 542         }
 543 }
 544 
 545 static int iscsit_task_reassign_prepare_write(
 546         struct iscsi_tmr_req *tmr_req,
 547         struct iscsi_conn *conn)
 548 {
 549         struct iscsi_cmd *cmd = tmr_req->ref_cmd;
 550         struct iscsi_pdu *pdu = NULL;
 551         struct iscsi_r2t *r2t = NULL, *r2t_tmp;
 552         int first_incomplete_r2t = 1, i = 0;
 553 
 554         /*
 555          * The command was in the process of receiving Unsolicited DataOUT when
 556          * the connection failed.
 557          */
 558         if (cmd->unsolicited_data)
 559                 iscsit_task_reassign_prepare_unsolicited_dataout(cmd, conn);
 560 
 561         /*
 562          * The Initiator is requesting R2Ts starting from zero,  skip
 563          * checking acknowledged R2Ts and start checking struct iscsi_r2ts
 564          * greater than zero.
 565          */
 566         if (!tmr_req->exp_data_sn)
 567                 goto drop_unacknowledged_r2ts;
 568 
 569         /*
 570          * We now check that the PDUs in DataOUT sequences below
 571          * the TMR TASK_REASSIGN ExpDataSN (R2TSN the Initiator is
 572          * expecting next) have all the DataOUT they require to complete
 573          * the DataOUT sequence.  First scan from R2TSN 0 to TMR
 574          * TASK_REASSIGN ExpDataSN-1.
 575          *
 576          * If we have not received all DataOUT in question,  we must
 577          * make sure to make the appropriate changes to values in
 578          * struct iscsi_cmd (and elsewhere depending on session parameters)
 579          * so iscsit_build_r2ts_for_cmd() in iscsit_task_reassign_complete_write()
 580          * will resend a new R2T for the DataOUT sequences in question.
 581          */
 582         spin_lock_bh(&cmd->r2t_lock);
 583         if (list_empty(&cmd->cmd_r2t_list)) {
 584                 spin_unlock_bh(&cmd->r2t_lock);
 585                 return -1;
 586         }
 587 
 588         list_for_each_entry(r2t, &cmd->cmd_r2t_list, r2t_list) {
 589 
 590                 if (r2t->r2t_sn >= tmr_req->exp_data_sn)
 591                         continue;
 592                 /*
 593                  * Safely ignore Recovery R2Ts and R2Ts that have completed
 594                  * DataOUT sequences.
 595                  */
 596                 if (r2t->seq_complete)
 597                         continue;
 598 
 599                 if (r2t->recovery_r2t)
 600                         continue;
 601 
 602                 /*
 603                  *                 DataSequenceInOrder=Yes:
 604                  *
 605                  * Taking into account the iSCSI implementation requirement of
 606                  * MaxOutstandingR2T=1 while ErrorRecoveryLevel>0 and
 607                  * DataSequenceInOrder=Yes, we must take into consideration
 608                  * the following:
 609                  *
 610                  *                  DataSequenceInOrder=No:
 611                  *
 612                  * Taking into account that the Initiator controls the (possibly
 613                  * random) PDU Order in (possibly random) Sequence Order of
 614                  * DataOUT the target requests with R2Ts,  we must take into
 615                  * consideration the following:
 616                  *
 617                  *      DataPDUInOrder=Yes for DataSequenceInOrder=[Yes,No]:
 618                  *
 619                  * While processing non-complete R2T DataOUT sequence requests
 620                  * the Target will re-request only the total sequence length
 621                  * minus current received offset.  This is because we must
 622                  * assume the initiator will continue sending DataOUT from the
 623                  * last PDU before the connection failed.
 624                  *
 625                  *      DataPDUInOrder=No for DataSequenceInOrder=[Yes,No]:
 626                  *
 627                  * While processing non-complete R2T DataOUT sequence requests
 628                  * the Target will re-request the entire DataOUT sequence if
 629                  * any single PDU is missing from the sequence.  This is because
 630                  * we have no logical method to determine the next PDU offset,
 631                  * and we must assume the Initiator will be sending any random
 632                  * PDU offset in the current sequence after TASK_REASSIGN
 633                  * has completed.
 634                  */
 635                 if (conn->sess->sess_ops->DataSequenceInOrder) {
 636                         if (!first_incomplete_r2t) {
 637                                 cmd->r2t_offset -= r2t->xfer_len;
 638                                 goto next;
 639                         }
 640 
 641                         if (conn->sess->sess_ops->DataPDUInOrder) {
 642                                 cmd->data_sn = 0;
 643                                 cmd->r2t_offset -= (r2t->xfer_len -
 644                                         cmd->next_burst_len);
 645                                 first_incomplete_r2t = 0;
 646                                 goto next;
 647                         }
 648 
 649                         cmd->data_sn = 0;
 650                         cmd->r2t_offset -= r2t->xfer_len;
 651 
 652                         for (i = 0; i < cmd->pdu_count; i++) {
 653                                 pdu = &cmd->pdu_list[i];
 654 
 655                                 if (pdu->status != ISCSI_PDU_RECEIVED_OK)
 656                                         continue;
 657 
 658                                 if ((pdu->offset >= r2t->offset) &&
 659                                     (pdu->offset < (r2t->offset +
 660                                                 r2t->xfer_len))) {
 661                                         cmd->next_burst_len -= pdu->length;
 662                                         cmd->write_data_done -= pdu->length;
 663                                         pdu->status = ISCSI_PDU_NOT_RECEIVED;
 664                                 }
 665                         }
 666 
 667                         first_incomplete_r2t = 0;
 668                 } else {
 669                         struct iscsi_seq *seq;
 670 
 671                         seq = iscsit_get_seq_holder(cmd, r2t->offset,
 672                                         r2t->xfer_len);
 673                         if (!seq) {
 674                                 spin_unlock_bh(&cmd->r2t_lock);
 675                                 return -1;
 676                         }
 677 
 678                         cmd->write_data_done -=
 679                                         (seq->offset - seq->orig_offset);
 680                         seq->data_sn = 0;
 681                         seq->offset = seq->orig_offset;
 682                         seq->next_burst_len = 0;
 683                         seq->status = DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY;
 684 
 685                         cmd->seq_send_order--;
 686 
 687                         if (conn->sess->sess_ops->DataPDUInOrder)
 688                                 goto next;
 689 
 690                         for (i = 0; i < seq->pdu_count; i++) {
 691                                 pdu = &cmd->pdu_list[i+seq->pdu_start];
 692 
 693                                 if (pdu->status != ISCSI_PDU_RECEIVED_OK)
 694                                         continue;
 695 
 696                                 pdu->status = ISCSI_PDU_NOT_RECEIVED;
 697                         }
 698                 }
 699 
 700 next:
 701                 cmd->outstanding_r2ts--;
 702         }
 703         spin_unlock_bh(&cmd->r2t_lock);
 704 
 705         /*
 706          * We now drop all unacknowledged R2Ts, ie: ExpDataSN from TMR
 707          * TASK_REASSIGN to the last R2T in the list..  We are also careful
 708          * to check that the Initiator is not requesting R2Ts for DataOUT
 709          * sequences it has already completed.
 710          *
 711          * Free each R2T in question and adjust values in struct iscsi_cmd
 712          * accordingly so iscsit_build_r2ts_for_cmd() do the rest of
 713          * the work after the TMR TASK_REASSIGN Response is sent.
 714          */
 715 drop_unacknowledged_r2ts:
 716 
 717         cmd->cmd_flags &= ~ICF_SENT_LAST_R2T;
 718         cmd->r2t_sn = tmr_req->exp_data_sn;
 719 
 720         spin_lock_bh(&cmd->r2t_lock);
 721         list_for_each_entry_safe(r2t, r2t_tmp, &cmd->cmd_r2t_list, r2t_list) {
 722                 /*
 723                  * Skip up to the R2T Sequence number provided by the
 724                  * iSCSI TASK_REASSIGN TMR
 725                  */
 726                 if (r2t->r2t_sn < tmr_req->exp_data_sn)
 727                         continue;
 728 
 729                 if (r2t->seq_complete) {
 730                         pr_err("Initiator is requesting R2Ts from"
 731                                 " R2TSN: 0x%08x, but R2TSN: 0x%08x, Offset: %u,"
 732                                 " Length: %u is already complete."
 733                                 "   BAD INITIATOR ERL=2 IMPLEMENTATION!\n",
 734                                 tmr_req->exp_data_sn, r2t->r2t_sn,
 735                                 r2t->offset, r2t->xfer_len);
 736                         spin_unlock_bh(&cmd->r2t_lock);
 737                         return -1;
 738                 }
 739 
 740                 if (r2t->recovery_r2t) {
 741                         iscsit_free_r2t(r2t, cmd);
 742                         continue;
 743                 }
 744 
 745                 /*                 DataSequenceInOrder=Yes:
 746                  *
 747                  * Taking into account the iSCSI implementation requirement of
 748                  * MaxOutstandingR2T=1 while ErrorRecoveryLevel>0 and
 749                  * DataSequenceInOrder=Yes, it's safe to subtract the R2Ts
 750                  * entire transfer length from the commands R2T offset marker.
 751                  *
 752                  *                 DataSequenceInOrder=No:
 753                  *
 754                  * We subtract the difference from struct iscsi_seq between the
 755                  * current offset and original offset from cmd->write_data_done
 756                  * for account for DataOUT PDUs already received.  Then reset
 757                  * the current offset to the original and zero out the current
 758                  * burst length,  to make sure we re-request the entire DataOUT
 759                  * sequence.
 760                  */
 761                 if (conn->sess->sess_ops->DataSequenceInOrder)
 762                         cmd->r2t_offset -= r2t->xfer_len;
 763                 else
 764                         cmd->seq_send_order--;
 765 
 766                 cmd->outstanding_r2ts--;
 767                 iscsit_free_r2t(r2t, cmd);
 768         }
 769         spin_unlock_bh(&cmd->r2t_lock);
 770 
 771         return 0;
 772 }
 773 
 774 /*
 775  *      Performs sanity checks TMR TASK_REASSIGN's ExpDataSN for
 776  *      a given struct iscsi_cmd.
 777  */
 778 int iscsit_check_task_reassign_expdatasn(
 779         struct iscsi_tmr_req *tmr_req,
 780         struct iscsi_conn *conn)
 781 {
 782         struct iscsi_cmd *ref_cmd = tmr_req->ref_cmd;
 783 
 784         if (ref_cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD)
 785                 return 0;
 786 
 787         if (ref_cmd->se_cmd.se_cmd_flags & SCF_SENT_CHECK_CONDITION)
 788                 return 0;
 789 
 790         if (ref_cmd->data_direction == DMA_NONE)
 791                 return 0;
 792 
 793         /*
 794          * For READs the TMR TASK_REASSIGNs ExpDataSN contains the next DataSN
 795          * of DataIN the Initiator is expecting.
 796          *
 797          * Also check that the Initiator is not re-requesting DataIN that has
 798          * already been acknowledged with a DataAck SNACK.
 799          */
 800         if (ref_cmd->data_direction == DMA_FROM_DEVICE) {
 801                 if (tmr_req->exp_data_sn > ref_cmd->data_sn) {
 802                         pr_err("Received ExpDataSN: 0x%08x for READ"
 803                                 " in TMR TASK_REASSIGN greater than command's"
 804                                 " DataSN: 0x%08x.\n", tmr_req->exp_data_sn,
 805                                 ref_cmd->data_sn);
 806                         return -1;
 807                 }
 808                 if ((ref_cmd->cmd_flags & ICF_GOT_DATACK_SNACK) &&
 809                     (tmr_req->exp_data_sn <= ref_cmd->acked_data_sn)) {
 810                         pr_err("Received ExpDataSN: 0x%08x for READ"
 811                                 " in TMR TASK_REASSIGN for previously"
 812                                 " acknowledged DataIN: 0x%08x,"
 813                                 " protocol error\n", tmr_req->exp_data_sn,
 814                                 ref_cmd->acked_data_sn);
 815                         return -1;
 816                 }
 817                 return iscsit_task_reassign_prepare_read(tmr_req, conn);
 818         }
 819 
 820         /*
 821          * For WRITEs the TMR TASK_REASSIGNs ExpDataSN contains the next R2TSN
 822          * for R2Ts the Initiator is expecting.
 823          *
 824          * Do the magic in iscsit_task_reassign_prepare_write().
 825          */
 826         if (ref_cmd->data_direction == DMA_TO_DEVICE) {
 827                 if (tmr_req->exp_data_sn > ref_cmd->r2t_sn) {
 828                         pr_err("Received ExpDataSN: 0x%08x for WRITE"
 829                                 " in TMR TASK_REASSIGN greater than command's"
 830                                 " R2TSN: 0x%08x.\n", tmr_req->exp_data_sn,
 831                                         ref_cmd->r2t_sn);
 832                         return -1;
 833                 }
 834                 return iscsit_task_reassign_prepare_write(tmr_req, conn);
 835         }
 836 
 837         pr_err("Unknown iSCSI data_direction: 0x%02x\n",
 838                         ref_cmd->data_direction);
 839 
 840         return -1;
 841 }

/* [<][>][^][v][top][bottom][index][help] */