linux/drivers/target/iscsi/iscsi_target_erl0.c
<<
>>
Prefs
   1/******************************************************************************
   2 * This file contains error recovery level zero functions used by
   3 * the iSCSI Target driver.
   4 *
   5 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
   6 *
   7 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
   8 *
   9 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; either version 2 of the License, or
  14 * (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 ******************************************************************************/
  21
  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_tq.h"
  29#include "iscsi_target_erl0.h"
  30#include "iscsi_target_erl1.h"
  31#include "iscsi_target_erl2.h"
  32#include "iscsi_target_util.h"
  33#include "iscsi_target.h"
  34
  35/*
  36 *      Used to set values in struct iscsi_cmd that iscsit_dataout_check_sequence()
  37 *      checks against to determine a PDU's Offset+Length is within the current
  38 *      DataOUT Sequence.  Used for DataSequenceInOrder=Yes only.
  39 */
  40void iscsit_set_dataout_sequence_values(
  41        struct iscsi_cmd *cmd)
  42{
  43        struct iscsi_conn *conn = cmd->conn;
  44        /*
  45         * Still set seq_start_offset and seq_end_offset for Unsolicited
  46         * DataOUT, even if DataSequenceInOrder=No.
  47         */
  48        if (cmd->unsolicited_data) {
  49                cmd->seq_start_offset = cmd->write_data_done;
  50                cmd->seq_end_offset = (cmd->write_data_done +
  51                        ((cmd->se_cmd.data_length >
  52                          conn->sess->sess_ops->FirstBurstLength) ?
  53                         conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length));
  54                return;
  55        }
  56
  57        if (!conn->sess->sess_ops->DataSequenceInOrder)
  58                return;
  59
  60        if (!cmd->seq_start_offset && !cmd->seq_end_offset) {
  61                cmd->seq_start_offset = cmd->write_data_done;
  62                cmd->seq_end_offset = (cmd->se_cmd.data_length >
  63                        conn->sess->sess_ops->MaxBurstLength) ?
  64                        (cmd->write_data_done +
  65                        conn->sess->sess_ops->MaxBurstLength) : cmd->se_cmd.data_length;
  66        } else {
  67                cmd->seq_start_offset = cmd->seq_end_offset;
  68                cmd->seq_end_offset = ((cmd->seq_end_offset +
  69                        conn->sess->sess_ops->MaxBurstLength) >=
  70                        cmd->se_cmd.data_length) ? cmd->se_cmd.data_length :
  71                        (cmd->seq_end_offset +
  72                         conn->sess->sess_ops->MaxBurstLength);
  73        }
  74}
  75
  76static int iscsit_dataout_within_command_recovery_check(
  77        struct iscsi_cmd *cmd,
  78        unsigned char *buf)
  79{
  80        struct iscsi_conn *conn = cmd->conn;
  81        struct iscsi_data *hdr = (struct iscsi_data *) buf;
  82        u32 payload_length = ntoh24(hdr->dlength);
  83
  84        /*
  85         * We do the within-command recovery checks here as it is
  86         * the first function called in iscsi_check_pre_dataout().
  87         * Basically, if we are in within-command recovery and
  88         * the PDU does not contain the offset the sequence needs,
  89         * dump the payload.
  90         *
  91         * This only applies to DataPDUInOrder=Yes, for
  92         * DataPDUInOrder=No we only re-request the failed PDU
  93         * and check that all PDUs in a sequence are received
  94         * upon end of sequence.
  95         */
  96        if (conn->sess->sess_ops->DataSequenceInOrder) {
  97                if ((cmd->cmd_flags & ICF_WITHIN_COMMAND_RECOVERY) &&
  98                    cmd->write_data_done != be32_to_cpu(hdr->offset))
  99                        goto dump;
 100
 101                cmd->cmd_flags &= ~ICF_WITHIN_COMMAND_RECOVERY;
 102        } else {
 103                struct iscsi_seq *seq;
 104
 105                seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
 106                                            payload_length);
 107                if (!seq)
 108                        return DATAOUT_CANNOT_RECOVER;
 109                /*
 110                 * Set the struct iscsi_seq pointer to reuse later.
 111                 */
 112                cmd->seq_ptr = seq;
 113
 114                if (conn->sess->sess_ops->DataPDUInOrder) {
 115                        if (seq->status ==
 116                            DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
 117                           (seq->offset != be32_to_cpu(hdr->offset) ||
 118                            seq->data_sn != be32_to_cpu(hdr->datasn)))
 119                                goto dump;
 120                } else {
 121                        if (seq->status ==
 122                             DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
 123                            seq->data_sn != be32_to_cpu(hdr->datasn))
 124                                goto dump;
 125                }
 126
 127                if (seq->status == DATAOUT_SEQUENCE_COMPLETE)
 128                        goto dump;
 129
 130                if (seq->status != DATAOUT_SEQUENCE_COMPLETE)
 131                        seq->status = 0;
 132        }
 133
 134        return DATAOUT_NORMAL;
 135
 136dump:
 137        pr_err("Dumping DataOUT PDU Offset: %u Length: %d DataSN:"
 138                " 0x%08x\n", hdr->offset, payload_length, hdr->datasn);
 139        return iscsit_dump_data_payload(conn, payload_length, 1);
 140}
 141
 142static int iscsit_dataout_check_unsolicited_sequence(
 143        struct iscsi_cmd *cmd,
 144        unsigned char *buf)
 145{
 146        u32 first_burst_len;
 147        struct iscsi_conn *conn = cmd->conn;
 148        struct iscsi_data *hdr = (struct iscsi_data *) buf;
 149        u32 payload_length = ntoh24(hdr->dlength);
 150
 151
 152        if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
 153           ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
 154                pr_err("Command ITT: 0x%08x with Offset: %u,"
 155                " Length: %u outside of Unsolicited Sequence %u:%u while"
 156                " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
 157                be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
 158                        cmd->seq_end_offset);
 159                return DATAOUT_CANNOT_RECOVER;
 160        }
 161
 162        first_burst_len = (cmd->first_burst_len + payload_length);
 163
 164        if (first_burst_len > conn->sess->sess_ops->FirstBurstLength) {
 165                pr_err("Total %u bytes exceeds FirstBurstLength: %u"
 166                        " for this Unsolicited DataOut Burst.\n",
 167                        first_burst_len, conn->sess->sess_ops->FirstBurstLength);
 168                transport_send_check_condition_and_sense(&cmd->se_cmd,
 169                                TCM_INCORRECT_AMOUNT_OF_DATA, 0);
 170                return DATAOUT_CANNOT_RECOVER;
 171        }
 172
 173        /*
 174         * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
 175         * checks for the current Unsolicited DataOUT Sequence.
 176         */
 177        if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
 178                /*
 179                 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
 180                 * sequence checks are handled in
 181                 * iscsit_dataout_datapduinorder_no_fbit().
 182                 */
 183                if (!conn->sess->sess_ops->DataPDUInOrder)
 184                        goto out;
 185
 186                if ((first_burst_len != cmd->se_cmd.data_length) &&
 187                    (first_burst_len != conn->sess->sess_ops->FirstBurstLength)) {
 188                        pr_err("Unsolicited non-immediate data"
 189                        " received %u does not equal FirstBurstLength: %u, and"
 190                        " does not equal ExpXferLen %u.\n", first_burst_len,
 191                                conn->sess->sess_ops->FirstBurstLength,
 192                                cmd->se_cmd.data_length);
 193                        transport_send_check_condition_and_sense(&cmd->se_cmd,
 194                                        TCM_INCORRECT_AMOUNT_OF_DATA, 0);
 195                        return DATAOUT_CANNOT_RECOVER;
 196                }
 197        } else {
 198                if (first_burst_len == conn->sess->sess_ops->FirstBurstLength) {
 199                        pr_err("Command ITT: 0x%08x reached"
 200                        " FirstBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
 201                                " error.\n", cmd->init_task_tag,
 202                                conn->sess->sess_ops->FirstBurstLength);
 203                        return DATAOUT_CANNOT_RECOVER;
 204                }
 205                if (first_burst_len == cmd->se_cmd.data_length) {
 206                        pr_err("Command ITT: 0x%08x reached"
 207                        " ExpXferLen: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
 208                        " error.\n", cmd->init_task_tag, cmd->se_cmd.data_length);
 209                        return DATAOUT_CANNOT_RECOVER;
 210                }
 211        }
 212
 213out:
 214        return DATAOUT_NORMAL;
 215}
 216
 217static int iscsit_dataout_check_sequence(
 218        struct iscsi_cmd *cmd,
 219        unsigned char *buf)
 220{
 221        u32 next_burst_len;
 222        struct iscsi_conn *conn = cmd->conn;
 223        struct iscsi_seq *seq = NULL;
 224        struct iscsi_data *hdr = (struct iscsi_data *) buf;
 225        u32 payload_length = ntoh24(hdr->dlength);
 226
 227        /*
 228         * For DataSequenceInOrder=Yes: Check that the offset and offset+length
 229         * is within range as defined by iscsi_set_dataout_sequence_values().
 230         *
 231         * For DataSequenceInOrder=No: Check that an struct iscsi_seq exists for
 232         * offset+length tuple.
 233         */
 234        if (conn->sess->sess_ops->DataSequenceInOrder) {
 235                /*
 236                 * Due to possibility of recovery DataOUT sent by the initiator
 237                 * fullfilling an Recovery R2T, it's best to just dump the
 238                 * payload here, instead of erroring out.
 239                 */
 240                if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
 241                   ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
 242                        pr_err("Command ITT: 0x%08x with Offset: %u,"
 243                        " Length: %u outside of Sequence %u:%u while"
 244                        " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
 245                        be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
 246                                cmd->seq_end_offset);
 247
 248                        if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
 249                                return DATAOUT_CANNOT_RECOVER;
 250                        return DATAOUT_WITHIN_COMMAND_RECOVERY;
 251                }
 252
 253                next_burst_len = (cmd->next_burst_len + payload_length);
 254        } else {
 255                seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
 256                                            payload_length);
 257                if (!seq)
 258                        return DATAOUT_CANNOT_RECOVER;
 259                /*
 260                 * Set the struct iscsi_seq pointer to reuse later.
 261                 */
 262                cmd->seq_ptr = seq;
 263
 264                if (seq->status == DATAOUT_SEQUENCE_COMPLETE) {
 265                        if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
 266                                return DATAOUT_CANNOT_RECOVER;
 267                        return DATAOUT_WITHIN_COMMAND_RECOVERY;
 268                }
 269
 270                next_burst_len = (seq->next_burst_len + payload_length);
 271        }
 272
 273        if (next_burst_len > conn->sess->sess_ops->MaxBurstLength) {
 274                pr_err("Command ITT: 0x%08x, NextBurstLength: %u and"
 275                        " Length: %u exceeds MaxBurstLength: %u. protocol"
 276                        " error.\n", cmd->init_task_tag,
 277                        (next_burst_len - payload_length),
 278                        payload_length, conn->sess->sess_ops->MaxBurstLength);
 279                return DATAOUT_CANNOT_RECOVER;
 280        }
 281
 282        /*
 283         * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
 284         * checks for the current DataOUT Sequence.
 285         */
 286        if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
 287                /*
 288                 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
 289                 * sequence checks are handled in
 290                 * iscsit_dataout_datapduinorder_no_fbit().
 291                 */
 292                if (!conn->sess->sess_ops->DataPDUInOrder)
 293                        goto out;
 294
 295                if (conn->sess->sess_ops->DataSequenceInOrder) {
 296                        if ((next_burst_len <
 297                             conn->sess->sess_ops->MaxBurstLength) &&
 298                           ((cmd->write_data_done + payload_length) <
 299                             cmd->se_cmd.data_length)) {
 300                                pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
 301                                " before end of DataOUT sequence, protocol"
 302                                " error.\n", cmd->init_task_tag);
 303                                return DATAOUT_CANNOT_RECOVER;
 304                        }
 305                } else {
 306                        if (next_burst_len < seq->xfer_len) {
 307                                pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
 308                                " before end of DataOUT sequence, protocol"
 309                                " error.\n", cmd->init_task_tag);
 310                                return DATAOUT_CANNOT_RECOVER;
 311                        }
 312                }
 313        } else {
 314                if (conn->sess->sess_ops->DataSequenceInOrder) {
 315                        if (next_burst_len ==
 316                                        conn->sess->sess_ops->MaxBurstLength) {
 317                                pr_err("Command ITT: 0x%08x reached"
 318                                " MaxBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is"
 319                                " not set, protocol error.", cmd->init_task_tag,
 320                                        conn->sess->sess_ops->MaxBurstLength);
 321                                return DATAOUT_CANNOT_RECOVER;
 322                        }
 323                        if ((cmd->write_data_done + payload_length) ==
 324                                        cmd->se_cmd.data_length) {
 325                                pr_err("Command ITT: 0x%08x reached"
 326                                " last DataOUT PDU in sequence but ISCSI_FLAG_"
 327                                "CMD_FINAL is not set, protocol error.\n",
 328                                        cmd->init_task_tag);
 329                                return DATAOUT_CANNOT_RECOVER;
 330                        }
 331                } else {
 332                        if (next_burst_len == seq->xfer_len) {
 333                                pr_err("Command ITT: 0x%08x reached"
 334                                " last DataOUT PDU in sequence but ISCSI_FLAG_"
 335                                "CMD_FINAL is not set, protocol error.\n",
 336                                        cmd->init_task_tag);
 337                                return DATAOUT_CANNOT_RECOVER;
 338                        }
 339                }
 340        }
 341
 342out:
 343        return DATAOUT_NORMAL;
 344}
 345
 346static int iscsit_dataout_check_datasn(
 347        struct iscsi_cmd *cmd,
 348        unsigned char *buf)
 349{
 350        int dump = 0, recovery = 0;
 351        u32 data_sn = 0;
 352        struct iscsi_conn *conn = cmd->conn;
 353        struct iscsi_data *hdr = (struct iscsi_data *) buf;
 354        u32 payload_length = ntoh24(hdr->dlength);
 355
 356        /*
 357         * Considering the target has no method of re-requesting DataOUT
 358         * by DataSN, if we receieve a greater DataSN than expected we
 359         * assume the functions for DataPDUInOrder=[Yes,No] below will
 360         * handle it.
 361         *
 362         * If the DataSN is less than expected, dump the payload.
 363         */
 364        if (conn->sess->sess_ops->DataSequenceInOrder)
 365                data_sn = cmd->data_sn;
 366        else {
 367                struct iscsi_seq *seq = cmd->seq_ptr;
 368                data_sn = seq->data_sn;
 369        }
 370
 371        if (be32_to_cpu(hdr->datasn) > data_sn) {
 372                pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
 373                        " higher than expected 0x%08x.\n", cmd->init_task_tag,
 374                                be32_to_cpu(hdr->datasn), data_sn);
 375                recovery = 1;
 376                goto recover;
 377        } else if (be32_to_cpu(hdr->datasn) < data_sn) {
 378                pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
 379                        " lower than expected 0x%08x, discarding payload.\n",
 380                        cmd->init_task_tag, be32_to_cpu(hdr->datasn), data_sn);
 381                dump = 1;
 382                goto dump;
 383        }
 384
 385        return DATAOUT_NORMAL;
 386
 387recover:
 388        if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
 389                pr_err("Unable to perform within-command recovery"
 390                                " while ERL=0.\n");
 391                return DATAOUT_CANNOT_RECOVER;
 392        }
 393dump:
 394        if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
 395                return DATAOUT_CANNOT_RECOVER;
 396
 397        return (recovery || dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY :
 398                                DATAOUT_NORMAL;
 399}
 400
 401static int iscsit_dataout_pre_datapduinorder_yes(
 402        struct iscsi_cmd *cmd,
 403        unsigned char *buf)
 404{
 405        int dump = 0, recovery = 0;
 406        struct iscsi_conn *conn = cmd->conn;
 407        struct iscsi_data *hdr = (struct iscsi_data *) buf;
 408        u32 payload_length = ntoh24(hdr->dlength);
 409
 410        /*
 411         * For DataSequenceInOrder=Yes: If the offset is greater than the global
 412         * DataPDUInOrder=Yes offset counter in struct iscsi_cmd a protcol error has
 413         * occurred and fail the connection.
 414         *
 415         * For DataSequenceInOrder=No: If the offset is greater than the per
 416         * sequence DataPDUInOrder=Yes offset counter in struct iscsi_seq a protocol
 417         * error has occurred and fail the connection.
 418         */
 419        if (conn->sess->sess_ops->DataSequenceInOrder) {
 420                if (be32_to_cpu(hdr->offset) != cmd->write_data_done) {
 421                        pr_err("Command ITT: 0x%08x, received offset"
 422                        " %u different than expected %u.\n", cmd->init_task_tag,
 423                                be32_to_cpu(hdr->offset), cmd->write_data_done);
 424                        recovery = 1;
 425                        goto recover;
 426                }
 427        } else {
 428                struct iscsi_seq *seq = cmd->seq_ptr;
 429
 430                if (be32_to_cpu(hdr->offset) > seq->offset) {
 431                        pr_err("Command ITT: 0x%08x, received offset"
 432                        " %u greater than expected %u.\n", cmd->init_task_tag,
 433                                be32_to_cpu(hdr->offset), seq->offset);
 434                        recovery = 1;
 435                        goto recover;
 436                } else if (be32_to_cpu(hdr->offset) < seq->offset) {
 437                        pr_err("Command ITT: 0x%08x, received offset"
 438                        " %u less than expected %u, discarding payload.\n",
 439                                cmd->init_task_tag, be32_to_cpu(hdr->offset),
 440                                seq->offset);
 441                        dump = 1;
 442                        goto dump;
 443                }
 444        }
 445
 446        return DATAOUT_NORMAL;
 447
 448recover:
 449        if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
 450                pr_err("Unable to perform within-command recovery"
 451                                " while ERL=0.\n");
 452                return DATAOUT_CANNOT_RECOVER;
 453        }
 454dump:
 455        if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
 456                return DATAOUT_CANNOT_RECOVER;
 457
 458        return (recovery) ? iscsit_recover_dataout_sequence(cmd,
 459                be32_to_cpu(hdr->offset), payload_length) :
 460               (dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY : DATAOUT_NORMAL;
 461}
 462
 463static int iscsit_dataout_pre_datapduinorder_no(
 464        struct iscsi_cmd *cmd,
 465        unsigned char *buf)
 466{
 467        struct iscsi_pdu *pdu;
 468        struct iscsi_data *hdr = (struct iscsi_data *) buf;
 469        u32 payload_length = ntoh24(hdr->dlength);
 470
 471        pdu = iscsit_get_pdu_holder(cmd, be32_to_cpu(hdr->offset),
 472                                    payload_length);
 473        if (!pdu)
 474                return DATAOUT_CANNOT_RECOVER;
 475
 476        cmd->pdu_ptr = pdu;
 477
 478        switch (pdu->status) {
 479        case ISCSI_PDU_NOT_RECEIVED:
 480        case ISCSI_PDU_CRC_FAILED:
 481        case ISCSI_PDU_TIMED_OUT:
 482                break;
 483        case ISCSI_PDU_RECEIVED_OK:
 484                pr_err("Command ITT: 0x%08x received already gotten"
 485                        " Offset: %u, Length: %u\n", cmd->init_task_tag,
 486                                be32_to_cpu(hdr->offset), payload_length);
 487                return iscsit_dump_data_payload(cmd->conn, payload_length, 1);
 488        default:
 489                return DATAOUT_CANNOT_RECOVER;
 490        }
 491
 492        return DATAOUT_NORMAL;
 493}
 494
 495static int iscsit_dataout_update_r2t(struct iscsi_cmd *cmd, u32 offset, u32 length)
 496{
 497        struct iscsi_r2t *r2t;
 498
 499        if (cmd->unsolicited_data)
 500                return 0;
 501
 502        r2t = iscsit_get_r2t_for_eos(cmd, offset, length);
 503        if (!r2t)
 504                return -1;
 505
 506        spin_lock_bh(&cmd->r2t_lock);
 507        r2t->seq_complete = 1;
 508        cmd->outstanding_r2ts--;
 509        spin_unlock_bh(&cmd->r2t_lock);
 510
 511        return 0;
 512}
 513
 514static int iscsit_dataout_update_datapduinorder_no(
 515        struct iscsi_cmd *cmd,
 516        u32 data_sn,
 517        int f_bit)
 518{
 519        int ret = 0;
 520        struct iscsi_pdu *pdu = cmd->pdu_ptr;
 521
 522        pdu->data_sn = data_sn;
 523
 524        switch (pdu->status) {
 525        case ISCSI_PDU_NOT_RECEIVED:
 526                pdu->status = ISCSI_PDU_RECEIVED_OK;
 527                break;
 528        case ISCSI_PDU_CRC_FAILED:
 529                pdu->status = ISCSI_PDU_RECEIVED_OK;
 530                break;
 531        case ISCSI_PDU_TIMED_OUT:
 532                pdu->status = ISCSI_PDU_RECEIVED_OK;
 533                break;
 534        default:
 535                return DATAOUT_CANNOT_RECOVER;
 536        }
 537
 538        if (f_bit) {
 539                ret = iscsit_dataout_datapduinorder_no_fbit(cmd, pdu);
 540                if (ret == DATAOUT_CANNOT_RECOVER)
 541                        return ret;
 542        }
 543
 544        return DATAOUT_NORMAL;
 545}
 546
 547static int iscsit_dataout_post_crc_passed(
 548        struct iscsi_cmd *cmd,
 549        unsigned char *buf)
 550{
 551        int ret, send_r2t = 0;
 552        struct iscsi_conn *conn = cmd->conn;
 553        struct iscsi_seq *seq = NULL;
 554        struct iscsi_data *hdr = (struct iscsi_data *) buf;
 555        u32 payload_length = ntoh24(hdr->dlength);
 556
 557        if (cmd->unsolicited_data) {
 558                if ((cmd->first_burst_len + payload_length) ==
 559                     conn->sess->sess_ops->FirstBurstLength) {
 560                        if (iscsit_dataout_update_r2t(cmd, be32_to_cpu(hdr->offset),
 561                                        payload_length) < 0)
 562                                return DATAOUT_CANNOT_RECOVER;
 563                        send_r2t = 1;
 564                }
 565
 566                if (!conn->sess->sess_ops->DataPDUInOrder) {
 567                        ret = iscsit_dataout_update_datapduinorder_no(cmd,
 568                                be32_to_cpu(hdr->datasn),
 569                                (hdr->flags & ISCSI_FLAG_CMD_FINAL));
 570                        if (ret == DATAOUT_CANNOT_RECOVER)
 571                                return ret;
 572                }
 573
 574                cmd->first_burst_len += payload_length;
 575
 576                if (conn->sess->sess_ops->DataSequenceInOrder)
 577                        cmd->data_sn++;
 578                else {
 579                        seq = cmd->seq_ptr;
 580                        seq->data_sn++;
 581                        seq->offset += payload_length;
 582                }
 583
 584                if (send_r2t) {
 585                        if (seq)
 586                                seq->status = DATAOUT_SEQUENCE_COMPLETE;
 587                        cmd->first_burst_len = 0;
 588                        cmd->unsolicited_data = 0;
 589                }
 590        } else {
 591                if (conn->sess->sess_ops->DataSequenceInOrder) {
 592                        if ((cmd->next_burst_len + payload_length) ==
 593                             conn->sess->sess_ops->MaxBurstLength) {
 594                                if (iscsit_dataout_update_r2t(cmd,
 595                                                be32_to_cpu(hdr->offset),
 596                                                payload_length) < 0)
 597                                        return DATAOUT_CANNOT_RECOVER;
 598                                send_r2t = 1;
 599                        }
 600
 601                        if (!conn->sess->sess_ops->DataPDUInOrder) {
 602                                ret = iscsit_dataout_update_datapduinorder_no(
 603                                                cmd, be32_to_cpu(hdr->datasn),
 604                                                (hdr->flags & ISCSI_FLAG_CMD_FINAL));
 605                                if (ret == DATAOUT_CANNOT_RECOVER)
 606                                        return ret;
 607                        }
 608
 609                        cmd->next_burst_len += payload_length;
 610                        cmd->data_sn++;
 611
 612                        if (send_r2t)
 613                                cmd->next_burst_len = 0;
 614                } else {
 615                        seq = cmd->seq_ptr;
 616
 617                        if ((seq->next_burst_len + payload_length) ==
 618                             seq->xfer_len) {
 619                                if (iscsit_dataout_update_r2t(cmd,
 620                                                be32_to_cpu(hdr->offset),
 621                                                payload_length) < 0)
 622                                        return DATAOUT_CANNOT_RECOVER;
 623                                send_r2t = 1;
 624                        }
 625
 626                        if (!conn->sess->sess_ops->DataPDUInOrder) {
 627                                ret = iscsit_dataout_update_datapduinorder_no(
 628                                                cmd, be32_to_cpu(hdr->datasn),
 629                                                (hdr->flags & ISCSI_FLAG_CMD_FINAL));
 630                                if (ret == DATAOUT_CANNOT_RECOVER)
 631                                        return ret;
 632                        }
 633
 634                        seq->data_sn++;
 635                        seq->offset += payload_length;
 636                        seq->next_burst_len += payload_length;
 637
 638                        if (send_r2t) {
 639                                seq->next_burst_len = 0;
 640                                seq->status = DATAOUT_SEQUENCE_COMPLETE;
 641                        }
 642                }
 643        }
 644
 645        if (send_r2t && conn->sess->sess_ops->DataSequenceInOrder)
 646                cmd->data_sn = 0;
 647
 648        cmd->write_data_done += payload_length;
 649
 650        if (cmd->write_data_done == cmd->se_cmd.data_length)
 651                return DATAOUT_SEND_TO_TRANSPORT;
 652        else if (send_r2t)
 653                return DATAOUT_SEND_R2T;
 654        else
 655                return DATAOUT_NORMAL;
 656}
 657
 658static int iscsit_dataout_post_crc_failed(
 659        struct iscsi_cmd *cmd,
 660        unsigned char *buf)
 661{
 662        struct iscsi_conn *conn = cmd->conn;
 663        struct iscsi_pdu *pdu;
 664        struct iscsi_data *hdr = (struct iscsi_data *) buf;
 665        u32 payload_length = ntoh24(hdr->dlength);
 666
 667        if (conn->sess->sess_ops->DataPDUInOrder)
 668                goto recover;
 669        /*
 670         * The rest of this function is only called when DataPDUInOrder=No.
 671         */
 672        pdu = cmd->pdu_ptr;
 673
 674        switch (pdu->status) {
 675        case ISCSI_PDU_NOT_RECEIVED:
 676                pdu->status = ISCSI_PDU_CRC_FAILED;
 677                break;
 678        case ISCSI_PDU_CRC_FAILED:
 679                break;
 680        case ISCSI_PDU_TIMED_OUT:
 681                pdu->status = ISCSI_PDU_CRC_FAILED;
 682                break;
 683        default:
 684                return DATAOUT_CANNOT_RECOVER;
 685        }
 686
 687recover:
 688        return iscsit_recover_dataout_sequence(cmd, be32_to_cpu(hdr->offset),
 689                                                payload_length);
 690}
 691
 692/*
 693 *      Called from iscsit_handle_data_out() before DataOUT Payload is received
 694 *      and CRC computed.
 695 */
 696int iscsit_check_pre_dataout(
 697        struct iscsi_cmd *cmd,
 698        unsigned char *buf)
 699{
 700        int ret;
 701        struct iscsi_conn *conn = cmd->conn;
 702
 703        ret = iscsit_dataout_within_command_recovery_check(cmd, buf);
 704        if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
 705            (ret == DATAOUT_CANNOT_RECOVER))
 706                return ret;
 707
 708        ret = iscsit_dataout_check_datasn(cmd, buf);
 709        if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
 710            (ret == DATAOUT_CANNOT_RECOVER))
 711                return ret;
 712
 713        if (cmd->unsolicited_data) {
 714                ret = iscsit_dataout_check_unsolicited_sequence(cmd, buf);
 715                if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
 716                    (ret == DATAOUT_CANNOT_RECOVER))
 717                        return ret;
 718        } else {
 719                ret = iscsit_dataout_check_sequence(cmd, buf);
 720                if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
 721                    (ret == DATAOUT_CANNOT_RECOVER))
 722                        return ret;
 723        }
 724
 725        return (conn->sess->sess_ops->DataPDUInOrder) ?
 726                iscsit_dataout_pre_datapduinorder_yes(cmd, buf) :
 727                iscsit_dataout_pre_datapduinorder_no(cmd, buf);
 728}
 729
 730/*
 731 *      Called from iscsit_handle_data_out() after DataOUT Payload is received
 732 *      and CRC computed.
 733 */
 734int iscsit_check_post_dataout(
 735        struct iscsi_cmd *cmd,
 736        unsigned char *buf,
 737        u8 data_crc_failed)
 738{
 739        struct iscsi_conn *conn = cmd->conn;
 740
 741        cmd->dataout_timeout_retries = 0;
 742
 743        if (!data_crc_failed)
 744                return iscsit_dataout_post_crc_passed(cmd, buf);
 745        else {
 746                if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
 747                        pr_err("Unable to recover from DataOUT CRC"
 748                                " failure while ERL=0, closing session.\n");
 749                        iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
 750                                        1, 0, buf, cmd);
 751                        return DATAOUT_CANNOT_RECOVER;
 752                }
 753
 754                iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR,
 755                                0, 0, buf, cmd);
 756                return iscsit_dataout_post_crc_failed(cmd, buf);
 757        }
 758}
 759
 760static void iscsit_handle_time2retain_timeout(unsigned long data)
 761{
 762        struct iscsi_session *sess = (struct iscsi_session *) data;
 763        struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
 764        struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
 765
 766        spin_lock_bh(&se_tpg->session_lock);
 767        if (sess->time2retain_timer_flags & ISCSI_TF_STOP) {
 768                spin_unlock_bh(&se_tpg->session_lock);
 769                return;
 770        }
 771        if (atomic_read(&sess->session_reinstatement)) {
 772                pr_err("Exiting Time2Retain handler because"
 773                                " session_reinstatement=1\n");
 774                spin_unlock_bh(&se_tpg->session_lock);
 775                return;
 776        }
 777        sess->time2retain_timer_flags |= ISCSI_TF_EXPIRED;
 778
 779        pr_err("Time2Retain timer expired for SID: %u, cleaning up"
 780                        " iSCSI session.\n", sess->sid);
 781        {
 782        struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
 783
 784        if (tiqn) {
 785                spin_lock(&tiqn->sess_err_stats.lock);
 786                strcpy(tiqn->sess_err_stats.last_sess_fail_rem_name,
 787                        (void *)sess->sess_ops->InitiatorName);
 788                tiqn->sess_err_stats.last_sess_failure_type =
 789                                ISCSI_SESS_ERR_CXN_TIMEOUT;
 790                tiqn->sess_err_stats.cxn_timeout_errors++;
 791                sess->conn_timeout_errors++;
 792                spin_unlock(&tiqn->sess_err_stats.lock);
 793        }
 794        }
 795
 796        spin_unlock_bh(&se_tpg->session_lock);
 797        target_put_session(sess->se_sess);
 798}
 799
 800void iscsit_start_time2retain_handler(struct iscsi_session *sess)
 801{
 802        int tpg_active;
 803        /*
 804         * Only start Time2Retain timer when the associated TPG is still in
 805         * an ACTIVE (eg: not disabled or shutdown) state.
 806         */
 807        spin_lock(&ISCSI_TPG_S(sess)->tpg_state_lock);
 808        tpg_active = (ISCSI_TPG_S(sess)->tpg_state == TPG_STATE_ACTIVE);
 809        spin_unlock(&ISCSI_TPG_S(sess)->tpg_state_lock);
 810
 811        if (!tpg_active)
 812                return;
 813
 814        if (sess->time2retain_timer_flags & ISCSI_TF_RUNNING)
 815                return;
 816
 817        pr_debug("Starting Time2Retain timer for %u seconds on"
 818                " SID: %u\n", sess->sess_ops->DefaultTime2Retain, sess->sid);
 819
 820        init_timer(&sess->time2retain_timer);
 821        sess->time2retain_timer.expires =
 822                (get_jiffies_64() + sess->sess_ops->DefaultTime2Retain * HZ);
 823        sess->time2retain_timer.data = (unsigned long)sess;
 824        sess->time2retain_timer.function = iscsit_handle_time2retain_timeout;
 825        sess->time2retain_timer_flags &= ~ISCSI_TF_STOP;
 826        sess->time2retain_timer_flags |= ISCSI_TF_RUNNING;
 827        add_timer(&sess->time2retain_timer);
 828}
 829
 830/*
 831 *      Called with spin_lock_bh(&struct se_portal_group->session_lock) held
 832 */
 833int iscsit_stop_time2retain_timer(struct iscsi_session *sess)
 834{
 835        struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
 836        struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
 837
 838        if (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)
 839                return -1;
 840
 841        if (!(sess->time2retain_timer_flags & ISCSI_TF_RUNNING))
 842                return 0;
 843
 844        sess->time2retain_timer_flags |= ISCSI_TF_STOP;
 845        spin_unlock(&se_tpg->session_lock);
 846
 847        del_timer_sync(&sess->time2retain_timer);
 848
 849        spin_lock(&se_tpg->session_lock);
 850        sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING;
 851        pr_debug("Stopped Time2Retain Timer for SID: %u\n",
 852                        sess->sid);
 853        return 0;
 854}
 855
 856void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn)
 857{
 858        spin_lock_bh(&conn->state_lock);
 859        if (atomic_read(&conn->connection_exit)) {
 860                spin_unlock_bh(&conn->state_lock);
 861                goto sleep;
 862        }
 863
 864        if (atomic_read(&conn->transport_failed)) {
 865                spin_unlock_bh(&conn->state_lock);
 866                goto sleep;
 867        }
 868        spin_unlock_bh(&conn->state_lock);
 869
 870        iscsi_thread_set_force_reinstatement(conn);
 871
 872sleep:
 873        wait_for_completion(&conn->conn_wait_rcfr_comp);
 874        complete(&conn->conn_post_wait_comp);
 875}
 876
 877void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep)
 878{
 879        spin_lock_bh(&conn->state_lock);
 880        if (atomic_read(&conn->connection_exit)) {
 881                spin_unlock_bh(&conn->state_lock);
 882                return;
 883        }
 884
 885        if (atomic_read(&conn->transport_failed)) {
 886                spin_unlock_bh(&conn->state_lock);
 887                return;
 888        }
 889
 890        if (atomic_read(&conn->connection_reinstatement)) {
 891                spin_unlock_bh(&conn->state_lock);
 892                return;
 893        }
 894
 895        if (iscsi_thread_set_force_reinstatement(conn) < 0) {
 896                spin_unlock_bh(&conn->state_lock);
 897                return;
 898        }
 899
 900        atomic_set(&conn->connection_reinstatement, 1);
 901        if (!sleep) {
 902                spin_unlock_bh(&conn->state_lock);
 903                return;
 904        }
 905
 906        atomic_set(&conn->sleep_on_conn_wait_comp, 1);
 907        spin_unlock_bh(&conn->state_lock);
 908
 909        wait_for_completion(&conn->conn_wait_comp);
 910        complete(&conn->conn_post_wait_comp);
 911}
 912
 913void iscsit_fall_back_to_erl0(struct iscsi_session *sess)
 914{
 915        pr_debug("Falling back to ErrorRecoveryLevel=0 for SID:"
 916                        " %u\n", sess->sid);
 917
 918        atomic_set(&sess->session_fall_back_to_erl0, 1);
 919}
 920
 921static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn)
 922{
 923        struct iscsi_session *sess = conn->sess;
 924
 925        if ((sess->sess_ops->ErrorRecoveryLevel == 2) &&
 926            !atomic_read(&sess->session_reinstatement) &&
 927            !atomic_read(&sess->session_fall_back_to_erl0))
 928                iscsit_connection_recovery_transport_reset(conn);
 929        else {
 930                pr_debug("Performing cleanup for failed iSCSI"
 931                        " Connection ID: %hu from %s\n", conn->cid,
 932                        sess->sess_ops->InitiatorName);
 933                iscsit_close_connection(conn);
 934        }
 935}
 936
 937void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
 938{
 939        spin_lock_bh(&conn->state_lock);
 940        if (atomic_read(&conn->connection_exit)) {
 941                spin_unlock_bh(&conn->state_lock);
 942                return;
 943        }
 944        atomic_set(&conn->connection_exit, 1);
 945
 946        if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
 947                spin_unlock_bh(&conn->state_lock);
 948                iscsit_close_connection(conn);
 949                return;
 950        }
 951
 952        if (conn->conn_state == TARG_CONN_STATE_CLEANUP_WAIT) {
 953                spin_unlock_bh(&conn->state_lock);
 954                return;
 955        }
 956
 957        pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
 958        conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
 959        spin_unlock_bh(&conn->state_lock);
 960
 961        iscsit_handle_connection_cleanup(conn);
 962}
 963
 964/*
 965 *      This is the simple function that makes the magic of
 966 *      sync and steering happen in the follow paradoxical order:
 967 *
 968 *      0) Receive conn->of_marker (bytes left until next OFMarker)
 969 *         bytes into an offload buffer.  When we pass the exact number
 970 *         of bytes in conn->of_marker, iscsit_dump_data_payload() and hence
 971 *         rx_data() will automatically receive the identical u32 marker
 972 *         values and store it in conn->of_marker_offset;
 973 *      1) Now conn->of_marker_offset will contain the offset to the start
 974 *         of the next iSCSI PDU.  Dump these remaining bytes into another
 975 *         offload buffer.
 976 *      2) We are done!
 977 *         Next byte in the TCP stream will contain the next iSCSI PDU!
 978 *         Cool Huh?!
 979 */
 980int iscsit_recover_from_unknown_opcode(struct iscsi_conn *conn)
 981{
 982        /*
 983         * Make sure the remaining bytes to next maker is a sane value.
 984         */
 985        if (conn->of_marker > (conn->conn_ops->OFMarkInt * 4)) {
 986                pr_err("Remaining bytes to OFMarker: %u exceeds"
 987                        " OFMarkInt bytes: %u.\n", conn->of_marker,
 988                                conn->conn_ops->OFMarkInt * 4);
 989                return -1;
 990        }
 991
 992        pr_debug("Advancing %u bytes in TCP stream to get to the"
 993                        " next OFMarker.\n", conn->of_marker);
 994
 995        if (iscsit_dump_data_payload(conn, conn->of_marker, 0) < 0)
 996                return -1;
 997
 998        /*
 999         * Make sure the offset marker we retrived is a valid value.
1000         */
1001        if (conn->of_marker_offset > (ISCSI_HDR_LEN + (ISCSI_CRC_LEN * 2) +
1002            conn->conn_ops->MaxRecvDataSegmentLength)) {
1003                pr_err("OfMarker offset value: %u exceeds limit.\n",
1004                        conn->of_marker_offset);
1005                return -1;
1006        }
1007
1008        pr_debug("Discarding %u bytes of TCP stream to get to the"
1009                        " next iSCSI Opcode.\n", conn->of_marker_offset);
1010
1011        if (iscsit_dump_data_payload(conn, conn->of_marker_offset, 0) < 0)
1012                return -1;
1013
1014        return 0;
1015}
1016