linux/drivers/target/iscsi/iscsi_target_seq_pdu_list.c
<<
>>
Prefs
   1/*******************************************************************************
   2 * This file contains main functions related to iSCSI DataSequenceInOrder=No
   3 * and DataPDUInOrder=No.
   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 <linux/slab.h>
  23#include <linux/random.h>
  24
  25#include "iscsi_target_core.h"
  26#include "iscsi_target_util.h"
  27#include "iscsi_target_seq_pdu_list.h"
  28
  29#define OFFLOAD_BUF_SIZE        32768
  30
  31void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
  32{
  33        int i;
  34        struct iscsi_seq *seq;
  35
  36        pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
  37                        cmd->init_task_tag);
  38
  39        for (i = 0; i < cmd->seq_count; i++) {
  40                seq = &cmd->seq_list[i];
  41                pr_debug("i: %d, pdu_start: %d, pdu_count: %d,"
  42                        " offset: %d, xfer_len: %d, seq_send_order: %d,"
  43                        " seq_no: %d\n", i, seq->pdu_start, seq->pdu_count,
  44                        seq->offset, seq->xfer_len, seq->seq_send_order,
  45                        seq->seq_no);
  46        }
  47}
  48
  49void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
  50{
  51        int i;
  52        struct iscsi_pdu *pdu;
  53
  54        pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
  55                        cmd->init_task_tag);
  56
  57        for (i = 0; i < cmd->pdu_count; i++) {
  58                pdu = &cmd->pdu_list[i];
  59                pr_debug("i: %d, offset: %d, length: %d,"
  60                        " pdu_send_order: %d, seq_no: %d\n", i, pdu->offset,
  61                        pdu->length, pdu->pdu_send_order, pdu->seq_no);
  62        }
  63}
  64
  65static void iscsit_ordered_seq_lists(
  66        struct iscsi_cmd *cmd,
  67        u8 type)
  68{
  69        u32 i, seq_count = 0;
  70
  71        for (i = 0; i < cmd->seq_count; i++) {
  72                if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
  73                        continue;
  74                cmd->seq_list[i].seq_send_order = seq_count++;
  75        }
  76}
  77
  78static void iscsit_ordered_pdu_lists(
  79        struct iscsi_cmd *cmd,
  80        u8 type)
  81{
  82        u32 i, pdu_send_order = 0, seq_no = 0;
  83
  84        for (i = 0; i < cmd->pdu_count; i++) {
  85redo:
  86                if (cmd->pdu_list[i].seq_no == seq_no) {
  87                        cmd->pdu_list[i].pdu_send_order = pdu_send_order++;
  88                        continue;
  89                }
  90                seq_no++;
  91                pdu_send_order = 0;
  92                goto redo;
  93        }
  94}
  95
  96/*
  97 *      Generate count random values into array.
  98 *      Use 0x80000000 to mark generates valued in array[].
  99 */
 100static void iscsit_create_random_array(u32 *array, u32 count)
 101{
 102        int i, j, k;
 103
 104        if (count == 1) {
 105                array[0] = 0;
 106                return;
 107        }
 108
 109        for (i = 0; i < count; i++) {
 110redo:
 111                get_random_bytes(&j, sizeof(u32));
 112                j = (1 + (int) (9999 + 1) - j) % count;
 113                for (k = 0; k < i + 1; k++) {
 114                        j |= 0x80000000;
 115                        if ((array[k] & 0x80000000) && (array[k] == j))
 116                                goto redo;
 117                }
 118                array[i] = j;
 119        }
 120
 121        for (i = 0; i < count; i++)
 122                array[i] &= ~0x80000000;
 123}
 124
 125static int iscsit_randomize_pdu_lists(
 126        struct iscsi_cmd *cmd,
 127        u8 type)
 128{
 129        int i = 0;
 130        u32 *array, pdu_count, seq_count = 0, seq_no = 0, seq_offset = 0;
 131
 132        for (pdu_count = 0; pdu_count < cmd->pdu_count; pdu_count++) {
 133redo:
 134                if (cmd->pdu_list[pdu_count].seq_no == seq_no) {
 135                        seq_count++;
 136                        continue;
 137                }
 138                array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
 139                if (!array) {
 140                        pr_err("Unable to allocate memory"
 141                                " for random array.\n");
 142                        return -1;
 143                }
 144                iscsit_create_random_array(array, seq_count);
 145
 146                for (i = 0; i < seq_count; i++)
 147                        cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
 148
 149                kfree(array);
 150
 151                seq_offset += seq_count;
 152                seq_count = 0;
 153                seq_no++;
 154                goto redo;
 155        }
 156
 157        if (seq_count) {
 158                array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
 159                if (!array) {
 160                        pr_err("Unable to allocate memory for"
 161                                " random array.\n");
 162                        return -1;
 163                }
 164                iscsit_create_random_array(array, seq_count);
 165
 166                for (i = 0; i < seq_count; i++)
 167                        cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
 168
 169                kfree(array);
 170        }
 171
 172        return 0;
 173}
 174
 175static int iscsit_randomize_seq_lists(
 176        struct iscsi_cmd *cmd,
 177        u8 type)
 178{
 179        int i, j = 0;
 180        u32 *array, seq_count = cmd->seq_count;
 181
 182        if ((type == PDULIST_IMMEDIATE) || (type == PDULIST_UNSOLICITED))
 183                seq_count--;
 184        else if (type == PDULIST_IMMEDIATE_AND_UNSOLICITED)
 185                seq_count -= 2;
 186
 187        if (!seq_count)
 188                return 0;
 189
 190        array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
 191        if (!array) {
 192                pr_err("Unable to allocate memory for random array.\n");
 193                return -1;
 194        }
 195        iscsit_create_random_array(array, seq_count);
 196
 197        for (i = 0; i < cmd->seq_count; i++) {
 198                if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
 199                        continue;
 200                cmd->seq_list[i].seq_send_order = array[j++];
 201        }
 202
 203        kfree(array);
 204        return 0;
 205}
 206
 207static void iscsit_determine_counts_for_list(
 208        struct iscsi_cmd *cmd,
 209        struct iscsi_build_list *bl,
 210        u32 *seq_count,
 211        u32 *pdu_count)
 212{
 213        int check_immediate = 0;
 214        u32 burstlength = 0, offset = 0;
 215        u32 unsolicited_data_length = 0;
 216        struct iscsi_conn *conn = cmd->conn;
 217
 218        if ((bl->type == PDULIST_IMMEDIATE) ||
 219            (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
 220                check_immediate = 1;
 221
 222        if ((bl->type == PDULIST_UNSOLICITED) ||
 223            (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
 224                unsolicited_data_length = (cmd->data_length >
 225                        conn->sess->sess_ops->FirstBurstLength) ?
 226                        conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
 227
 228        while (offset < cmd->data_length) {
 229                *pdu_count += 1;
 230
 231                if (check_immediate) {
 232                        check_immediate = 0;
 233                        offset += bl->immediate_data_length;
 234                        *seq_count += 1;
 235                        if (unsolicited_data_length)
 236                                unsolicited_data_length -=
 237                                        bl->immediate_data_length;
 238                        continue;
 239                }
 240                if (unsolicited_data_length > 0) {
 241                        if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
 242                                        >= cmd->data_length) {
 243                                unsolicited_data_length -=
 244                                        (cmd->data_length - offset);
 245                                offset += (cmd->data_length - offset);
 246                                continue;
 247                        }
 248                        if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
 249                                        >= conn->sess->sess_ops->FirstBurstLength) {
 250                                unsolicited_data_length -=
 251                                        (conn->sess->sess_ops->FirstBurstLength -
 252                                        offset);
 253                                offset += (conn->sess->sess_ops->FirstBurstLength -
 254                                        offset);
 255                                burstlength = 0;
 256                                *seq_count += 1;
 257                                continue;
 258                        }
 259
 260                        offset += conn->conn_ops->MaxRecvDataSegmentLength;
 261                        unsolicited_data_length -=
 262                                conn->conn_ops->MaxRecvDataSegmentLength;
 263                        continue;
 264                }
 265                if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
 266                     cmd->data_length) {
 267                        offset += (cmd->data_length - offset);
 268                        continue;
 269                }
 270                if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
 271                     conn->sess->sess_ops->MaxBurstLength) {
 272                        offset += (conn->sess->sess_ops->MaxBurstLength -
 273                                        burstlength);
 274                        burstlength = 0;
 275                        *seq_count += 1;
 276                        continue;
 277                }
 278
 279                burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
 280                offset += conn->conn_ops->MaxRecvDataSegmentLength;
 281        }
 282}
 283
 284
 285/*
 286 *      Builds PDU and/or Sequence list,  called while DataSequenceInOrder=No
 287 *      and DataPDUInOrder=No.
 288 */
 289static int iscsit_build_pdu_and_seq_list(
 290        struct iscsi_cmd *cmd,
 291        struct iscsi_build_list *bl)
 292{
 293        int check_immediate = 0, datapduinorder, datasequenceinorder;
 294        u32 burstlength = 0, offset = 0, i = 0;
 295        u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
 296        struct iscsi_conn *conn = cmd->conn;
 297        struct iscsi_pdu *pdu = cmd->pdu_list;
 298        struct iscsi_seq *seq = cmd->seq_list;
 299
 300        datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
 301        datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
 302
 303        if ((bl->type == PDULIST_IMMEDIATE) ||
 304            (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
 305                check_immediate = 1;
 306
 307        if ((bl->type == PDULIST_UNSOLICITED) ||
 308            (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
 309                unsolicited_data_length = (cmd->data_length >
 310                        conn->sess->sess_ops->FirstBurstLength) ?
 311                        conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
 312
 313        while (offset < cmd->data_length) {
 314                pdu_count++;
 315                if (!datapduinorder) {
 316                        pdu[i].offset = offset;
 317                        pdu[i].seq_no = seq_no;
 318                }
 319                if (!datasequenceinorder && (pdu_count == 1)) {
 320                        seq[seq_no].pdu_start = i;
 321                        seq[seq_no].seq_no = seq_no;
 322                        seq[seq_no].offset = offset;
 323                        seq[seq_no].orig_offset = offset;
 324                }
 325
 326                if (check_immediate) {
 327                        check_immediate = 0;
 328                        if (!datapduinorder) {
 329                                pdu[i].type = PDUTYPE_IMMEDIATE;
 330                                pdu[i++].length = bl->immediate_data_length;
 331                        }
 332                        if (!datasequenceinorder) {
 333                                seq[seq_no].type = SEQTYPE_IMMEDIATE;
 334                                seq[seq_no].pdu_count = 1;
 335                                seq[seq_no].xfer_len =
 336                                        bl->immediate_data_length;
 337                        }
 338                        offset += bl->immediate_data_length;
 339                        pdu_count = 0;
 340                        seq_no++;
 341                        if (unsolicited_data_length)
 342                                unsolicited_data_length -=
 343                                        bl->immediate_data_length;
 344                        continue;
 345                }
 346                if (unsolicited_data_length > 0) {
 347                        if ((offset +
 348                             conn->conn_ops->MaxRecvDataSegmentLength) >=
 349                             cmd->data_length) {
 350                                if (!datapduinorder) {
 351                                        pdu[i].type = PDUTYPE_UNSOLICITED;
 352                                        pdu[i].length =
 353                                                (cmd->data_length - offset);
 354                                }
 355                                if (!datasequenceinorder) {
 356                                        seq[seq_no].type = SEQTYPE_UNSOLICITED;
 357                                        seq[seq_no].pdu_count = pdu_count;
 358                                        seq[seq_no].xfer_len = (burstlength +
 359                                                (cmd->data_length - offset));
 360                                }
 361                                unsolicited_data_length -=
 362                                                (cmd->data_length - offset);
 363                                offset += (cmd->data_length - offset);
 364                                continue;
 365                        }
 366                        if ((offset +
 367                             conn->conn_ops->MaxRecvDataSegmentLength) >=
 368                                        conn->sess->sess_ops->FirstBurstLength) {
 369                                if (!datapduinorder) {
 370                                        pdu[i].type = PDUTYPE_UNSOLICITED;
 371                                        pdu[i++].length =
 372                                           (conn->sess->sess_ops->FirstBurstLength -
 373                                                offset);
 374                                }
 375                                if (!datasequenceinorder) {
 376                                        seq[seq_no].type = SEQTYPE_UNSOLICITED;
 377                                        seq[seq_no].pdu_count = pdu_count;
 378                                        seq[seq_no].xfer_len = (burstlength +
 379                                           (conn->sess->sess_ops->FirstBurstLength -
 380                                                offset));
 381                                }
 382                                unsolicited_data_length -=
 383                                        (conn->sess->sess_ops->FirstBurstLength -
 384                                                offset);
 385                                offset += (conn->sess->sess_ops->FirstBurstLength -
 386                                                offset);
 387                                burstlength = 0;
 388                                pdu_count = 0;
 389                                seq_no++;
 390                                continue;
 391                        }
 392
 393                        if (!datapduinorder) {
 394                                pdu[i].type = PDUTYPE_UNSOLICITED;
 395                                pdu[i++].length =
 396                                     conn->conn_ops->MaxRecvDataSegmentLength;
 397                        }
 398                        burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
 399                        offset += conn->conn_ops->MaxRecvDataSegmentLength;
 400                        unsolicited_data_length -=
 401                                conn->conn_ops->MaxRecvDataSegmentLength;
 402                        continue;
 403                }
 404                if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
 405                     cmd->data_length) {
 406                        if (!datapduinorder) {
 407                                pdu[i].type = PDUTYPE_NORMAL;
 408                                pdu[i].length = (cmd->data_length - offset);
 409                        }
 410                        if (!datasequenceinorder) {
 411                                seq[seq_no].type = SEQTYPE_NORMAL;
 412                                seq[seq_no].pdu_count = pdu_count;
 413                                seq[seq_no].xfer_len = (burstlength +
 414                                        (cmd->data_length - offset));
 415                        }
 416                        offset += (cmd->data_length - offset);
 417                        continue;
 418                }
 419                if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
 420                     conn->sess->sess_ops->MaxBurstLength) {
 421                        if (!datapduinorder) {
 422                                pdu[i].type = PDUTYPE_NORMAL;
 423                                pdu[i++].length =
 424                                        (conn->sess->sess_ops->MaxBurstLength -
 425                                                burstlength);
 426                        }
 427                        if (!datasequenceinorder) {
 428                                seq[seq_no].type = SEQTYPE_NORMAL;
 429                                seq[seq_no].pdu_count = pdu_count;
 430                                seq[seq_no].xfer_len = (burstlength +
 431                                        (conn->sess->sess_ops->MaxBurstLength -
 432                                        burstlength));
 433                        }
 434                        offset += (conn->sess->sess_ops->MaxBurstLength -
 435                                        burstlength);
 436                        burstlength = 0;
 437                        pdu_count = 0;
 438                        seq_no++;
 439                        continue;
 440                }
 441
 442                if (!datapduinorder) {
 443                        pdu[i].type = PDUTYPE_NORMAL;
 444                        pdu[i++].length =
 445                                conn->conn_ops->MaxRecvDataSegmentLength;
 446                }
 447                burstlength += conn->conn_ops->MaxRecvDataSegmentLength;
 448                offset += conn->conn_ops->MaxRecvDataSegmentLength;
 449        }
 450
 451        if (!datasequenceinorder) {
 452                if (bl->data_direction & ISCSI_PDU_WRITE) {
 453                        if (bl->randomize & RANDOM_R2T_OFFSETS) {
 454                                if (iscsit_randomize_seq_lists(cmd, bl->type)
 455                                                < 0)
 456                                        return -1;
 457                        } else
 458                                iscsit_ordered_seq_lists(cmd, bl->type);
 459                } else if (bl->data_direction & ISCSI_PDU_READ) {
 460                        if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) {
 461                                if (iscsit_randomize_seq_lists(cmd, bl->type)
 462                                                < 0)
 463                                        return -1;
 464                        } else
 465                                iscsit_ordered_seq_lists(cmd, bl->type);
 466                }
 467#if 0
 468                iscsit_dump_seq_list(cmd);
 469#endif
 470        }
 471        if (!datapduinorder) {
 472                if (bl->data_direction & ISCSI_PDU_WRITE) {
 473                        if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) {
 474                                if (iscsit_randomize_pdu_lists(cmd, bl->type)
 475                                                < 0)
 476                                        return -1;
 477                        } else
 478                                iscsit_ordered_pdu_lists(cmd, bl->type);
 479                } else if (bl->data_direction & ISCSI_PDU_READ) {
 480                        if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) {
 481                                if (iscsit_randomize_pdu_lists(cmd, bl->type)
 482                                                < 0)
 483                                        return -1;
 484                        } else
 485                                iscsit_ordered_pdu_lists(cmd, bl->type);
 486                }
 487#if 0
 488                iscsit_dump_pdu_list(cmd);
 489#endif
 490        }
 491
 492        return 0;
 493}
 494
 495/*
 496 *      Only called while DataSequenceInOrder=No or DataPDUInOrder=No.
 497 */
 498int iscsit_do_build_list(
 499        struct iscsi_cmd *cmd,
 500        struct iscsi_build_list *bl)
 501{
 502        u32 pdu_count = 0, seq_count = 1;
 503        struct iscsi_conn *conn = cmd->conn;
 504        struct iscsi_pdu *pdu = NULL;
 505        struct iscsi_seq *seq = NULL;
 506
 507        iscsit_determine_counts_for_list(cmd, bl, &seq_count, &pdu_count);
 508
 509        if (!conn->sess->sess_ops->DataSequenceInOrder) {
 510                seq = kzalloc(seq_count * sizeof(struct iscsi_seq), GFP_ATOMIC);
 511                if (!seq) {
 512                        pr_err("Unable to allocate struct iscsi_seq list\n");
 513                        return -1;
 514                }
 515                cmd->seq_list = seq;
 516                cmd->seq_count = seq_count;
 517        }
 518
 519        if (!conn->sess->sess_ops->DataPDUInOrder) {
 520                pdu = kzalloc(pdu_count * sizeof(struct iscsi_pdu), GFP_ATOMIC);
 521                if (!pdu) {
 522                        pr_err("Unable to allocate struct iscsi_pdu list.\n");
 523                        kfree(seq);
 524                        return -1;
 525                }
 526                cmd->pdu_list = pdu;
 527                cmd->pdu_count = pdu_count;
 528        }
 529
 530        return iscsit_build_pdu_and_seq_list(cmd, bl);
 531}
 532
 533struct iscsi_pdu *iscsit_get_pdu_holder(
 534        struct iscsi_cmd *cmd,
 535        u32 offset,
 536        u32 length)
 537{
 538        u32 i;
 539        struct iscsi_pdu *pdu = NULL;
 540
 541        if (!cmd->pdu_list) {
 542                pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
 543                return NULL;
 544        }
 545
 546        pdu = &cmd->pdu_list[0];
 547
 548        for (i = 0; i < cmd->pdu_count; i++)
 549                if ((pdu[i].offset == offset) && (pdu[i].length == length))
 550                        return &pdu[i];
 551
 552        pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
 553                " %u, Length: %u\n", cmd->init_task_tag, offset, length);
 554        return NULL;
 555}
 556
 557struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
 558        struct iscsi_cmd *cmd,
 559        struct iscsi_seq *seq)
 560{
 561        u32 i;
 562        struct iscsi_conn *conn = cmd->conn;
 563        struct iscsi_pdu *pdu = NULL;
 564
 565        if (!cmd->pdu_list) {
 566                pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
 567                return NULL;
 568        }
 569
 570        if (conn->sess->sess_ops->DataSequenceInOrder) {
 571redo:
 572                pdu = &cmd->pdu_list[cmd->pdu_start];
 573
 574                for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
 575#if 0
 576                        pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
 577                                "_send_order: %d, pdu[i].offset: %d,"
 578                                " pdu[i].length: %d\n", pdu[i].seq_no,
 579                                pdu[i].pdu_send_order, pdu[i].offset,
 580                                pdu[i].length);
 581#endif
 582                        if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
 583                                cmd->pdu_send_order++;
 584                                return &pdu[i];
 585                        }
 586                }
 587
 588                cmd->pdu_start += cmd->pdu_send_order;
 589                cmd->pdu_send_order = 0;
 590                cmd->seq_no++;
 591
 592                if (cmd->pdu_start < cmd->pdu_count)
 593                        goto redo;
 594
 595                pr_err("Command ITT: 0x%08x unable to locate"
 596                        " struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
 597                        cmd->init_task_tag, cmd->pdu_send_order);
 598                return NULL;
 599        } else {
 600                if (!seq) {
 601                        pr_err("struct iscsi_seq is NULL!\n");
 602                        return NULL;
 603                }
 604#if 0
 605                pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
 606                        " seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
 607                        seq->seq_no);
 608#endif
 609                pdu = &cmd->pdu_list[seq->pdu_start];
 610
 611                if (seq->pdu_send_order == seq->pdu_count) {
 612                        pr_err("Command ITT: 0x%08x seq->pdu_send"
 613                                "_order: %u equals seq->pdu_count: %u\n",
 614                                cmd->init_task_tag, seq->pdu_send_order,
 615                                seq->pdu_count);
 616                        return NULL;
 617                }
 618
 619                for (i = 0; i < seq->pdu_count; i++) {
 620                        if (pdu[i].pdu_send_order == seq->pdu_send_order) {
 621                                seq->pdu_send_order++;
 622                                return &pdu[i];
 623                        }
 624                }
 625
 626                pr_err("Command ITT: 0x%08x unable to locate iscsi"
 627                        "_pdu_t for seq->pdu_send_order: %u.\n",
 628                        cmd->init_task_tag, seq->pdu_send_order);
 629                return NULL;
 630        }
 631
 632        return NULL;
 633}
 634
 635struct iscsi_seq *iscsit_get_seq_holder(
 636        struct iscsi_cmd *cmd,
 637        u32 offset,
 638        u32 length)
 639{
 640        u32 i;
 641
 642        if (!cmd->seq_list) {
 643                pr_err("struct iscsi_cmd->seq_list is NULL!\n");
 644                return NULL;
 645        }
 646
 647        for (i = 0; i < cmd->seq_count; i++) {
 648#if 0
 649                pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
 650                        "xfer_len: %d, seq_list[i].seq_no %u\n",
 651                        cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
 652                        cmd->seq_list[i].seq_no);
 653#endif
 654                if ((cmd->seq_list[i].orig_offset +
 655                                cmd->seq_list[i].xfer_len) >=
 656                                (offset + length))
 657                        return &cmd->seq_list[i];
 658        }
 659
 660        pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
 661                " Offset: %u, Length: %u\n", cmd->init_task_tag, offset,
 662                length);
 663        return NULL;
 664}
 665