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