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