Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*******************************************************************************
0003  * This file contains main functions related to iSCSI DataSequenceInOrder=No
0004  * and DataPDUInOrder=No.
0005  *
0006  * (c) Copyright 2007-2013 Datera, Inc.
0007  *
0008  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
0009  *
0010  ******************************************************************************/
0011 
0012 #include <linux/slab.h>
0013 #include <linux/random.h>
0014 
0015 #include <target/iscsi/iscsi_target_core.h>
0016 #include "iscsi_target_util.h"
0017 #include "iscsi_target_tpg.h"
0018 #include "iscsi_target_seq_pdu_list.h"
0019 
0020 #ifdef DEBUG
0021 static void iscsit_dump_seq_list(struct iscsit_cmd *cmd)
0022 {
0023     int i;
0024     struct iscsi_seq *seq;
0025 
0026     pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
0027             cmd->init_task_tag);
0028 
0029     for (i = 0; i < cmd->seq_count; i++) {
0030         seq = &cmd->seq_list[i];
0031         pr_debug("i: %d, pdu_start: %d, pdu_count: %d,"
0032             " offset: %d, xfer_len: %d, seq_send_order: %d,"
0033             " seq_no: %d\n", i, seq->pdu_start, seq->pdu_count,
0034             seq->offset, seq->xfer_len, seq->seq_send_order,
0035             seq->seq_no);
0036     }
0037 }
0038 
0039 static void iscsit_dump_pdu_list(struct iscsit_cmd *cmd)
0040 {
0041     int i;
0042     struct iscsi_pdu *pdu;
0043 
0044     pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
0045             cmd->init_task_tag);
0046 
0047     for (i = 0; i < cmd->pdu_count; i++) {
0048         pdu = &cmd->pdu_list[i];
0049         pr_debug("i: %d, offset: %d, length: %d,"
0050             " pdu_send_order: %d, seq_no: %d\n", i, pdu->offset,
0051             pdu->length, pdu->pdu_send_order, pdu->seq_no);
0052     }
0053 }
0054 #else
0055 static void iscsit_dump_seq_list(struct iscsit_cmd *cmd) {}
0056 static void iscsit_dump_pdu_list(struct iscsit_cmd *cmd) {}
0057 #endif
0058 
0059 static void iscsit_ordered_seq_lists(
0060     struct iscsit_cmd *cmd,
0061     u8 type)
0062 {
0063     u32 i, seq_count = 0;
0064 
0065     for (i = 0; i < cmd->seq_count; i++) {
0066         if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
0067             continue;
0068         cmd->seq_list[i].seq_send_order = seq_count++;
0069     }
0070 }
0071 
0072 static void iscsit_ordered_pdu_lists(
0073     struct iscsit_cmd *cmd,
0074     u8 type)
0075 {
0076     u32 i, pdu_send_order = 0, seq_no = 0;
0077 
0078     for (i = 0; i < cmd->pdu_count; i++) {
0079 redo:
0080         if (cmd->pdu_list[i].seq_no == seq_no) {
0081             cmd->pdu_list[i].pdu_send_order = pdu_send_order++;
0082             continue;
0083         }
0084         seq_no++;
0085         pdu_send_order = 0;
0086         goto redo;
0087     }
0088 }
0089 
0090 /*
0091  *  Generate count random values into array.
0092  *  Use 0x80000000 to mark generates valued in array[].
0093  */
0094 static void iscsit_create_random_array(u32 *array, u32 count)
0095 {
0096     int i, j, k;
0097 
0098     if (count == 1) {
0099         array[0] = 0;
0100         return;
0101     }
0102 
0103     for (i = 0; i < count; i++) {
0104 redo:
0105         get_random_bytes(&j, sizeof(u32));
0106         j = (1 + (int) (9999 + 1) - j) % count;
0107         for (k = 0; k < i + 1; k++) {
0108             j |= 0x80000000;
0109             if ((array[k] & 0x80000000) && (array[k] == j))
0110                 goto redo;
0111         }
0112         array[i] = j;
0113     }
0114 
0115     for (i = 0; i < count; i++)
0116         array[i] &= ~0x80000000;
0117 }
0118 
0119 static int iscsit_randomize_pdu_lists(
0120     struct iscsit_cmd *cmd,
0121     u8 type)
0122 {
0123     int i = 0;
0124     u32 *array, pdu_count, seq_count = 0, seq_no = 0, seq_offset = 0;
0125 
0126     for (pdu_count = 0; pdu_count < cmd->pdu_count; pdu_count++) {
0127 redo:
0128         if (cmd->pdu_list[pdu_count].seq_no == seq_no) {
0129             seq_count++;
0130             continue;
0131         }
0132         array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
0133         if (!array) {
0134             pr_err("Unable to allocate memory"
0135                 " for random array.\n");
0136             return -ENOMEM;
0137         }
0138         iscsit_create_random_array(array, seq_count);
0139 
0140         for (i = 0; i < seq_count; i++)
0141             cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
0142 
0143         kfree(array);
0144 
0145         seq_offset += seq_count;
0146         seq_count = 0;
0147         seq_no++;
0148         goto redo;
0149     }
0150 
0151     if (seq_count) {
0152         array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
0153         if (!array) {
0154             pr_err("Unable to allocate memory for"
0155                 " random array.\n");
0156             return -ENOMEM;
0157         }
0158         iscsit_create_random_array(array, seq_count);
0159 
0160         for (i = 0; i < seq_count; i++)
0161             cmd->pdu_list[seq_offset+i].pdu_send_order = array[i];
0162 
0163         kfree(array);
0164     }
0165 
0166     return 0;
0167 }
0168 
0169 static int iscsit_randomize_seq_lists(
0170     struct iscsit_cmd *cmd,
0171     u8 type)
0172 {
0173     int i, j = 0;
0174     u32 *array, seq_count = cmd->seq_count;
0175 
0176     if ((type == PDULIST_IMMEDIATE) || (type == PDULIST_UNSOLICITED))
0177         seq_count--;
0178     else if (type == PDULIST_IMMEDIATE_AND_UNSOLICITED)
0179         seq_count -= 2;
0180 
0181     if (!seq_count)
0182         return 0;
0183 
0184     array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
0185     if (!array) {
0186         pr_err("Unable to allocate memory for random array.\n");
0187         return -ENOMEM;
0188     }
0189     iscsit_create_random_array(array, seq_count);
0190 
0191     for (i = 0; i < cmd->seq_count; i++) {
0192         if (cmd->seq_list[i].type != SEQTYPE_NORMAL)
0193             continue;
0194         cmd->seq_list[i].seq_send_order = array[j++];
0195     }
0196 
0197     kfree(array);
0198     return 0;
0199 }
0200 
0201 static void iscsit_determine_counts_for_list(
0202     struct iscsit_cmd *cmd,
0203     struct iscsi_build_list *bl,
0204     u32 *seq_count,
0205     u32 *pdu_count)
0206 {
0207     int check_immediate = 0;
0208     u32 burstlength = 0, offset = 0;
0209     u32 unsolicited_data_length = 0;
0210     u32 mdsl;
0211     struct iscsit_conn *conn = cmd->conn;
0212 
0213     if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
0214         mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
0215     else
0216         mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
0217 
0218     if ((bl->type == PDULIST_IMMEDIATE) ||
0219         (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0220         check_immediate = 1;
0221 
0222     if ((bl->type == PDULIST_UNSOLICITED) ||
0223         (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0224         unsolicited_data_length = min(cmd->se_cmd.data_length,
0225             conn->sess->sess_ops->FirstBurstLength);
0226 
0227     while (offset < cmd->se_cmd.data_length) {
0228         *pdu_count += 1;
0229 
0230         if (check_immediate) {
0231             check_immediate = 0;
0232             offset += bl->immediate_data_length;
0233             *seq_count += 1;
0234             if (unsolicited_data_length)
0235                 unsolicited_data_length -=
0236                     bl->immediate_data_length;
0237             continue;
0238         }
0239         if (unsolicited_data_length > 0) {
0240             if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0241                 unsolicited_data_length -=
0242                     (cmd->se_cmd.data_length - offset);
0243                 offset += (cmd->se_cmd.data_length - offset);
0244                 continue;
0245             }
0246             if ((offset + mdsl)
0247                     >= conn->sess->sess_ops->FirstBurstLength) {
0248                 unsolicited_data_length -=
0249                     (conn->sess->sess_ops->FirstBurstLength -
0250                     offset);
0251                 offset += (conn->sess->sess_ops->FirstBurstLength -
0252                     offset);
0253                 burstlength = 0;
0254                 *seq_count += 1;
0255                 continue;
0256             }
0257 
0258             offset += mdsl;
0259             unsolicited_data_length -= mdsl;
0260             continue;
0261         }
0262         if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0263             offset += (cmd->se_cmd.data_length - offset);
0264             continue;
0265         }
0266         if ((burstlength + mdsl) >=
0267              conn->sess->sess_ops->MaxBurstLength) {
0268             offset += (conn->sess->sess_ops->MaxBurstLength -
0269                     burstlength);
0270             burstlength = 0;
0271             *seq_count += 1;
0272             continue;
0273         }
0274 
0275         burstlength += mdsl;
0276         offset += mdsl;
0277     }
0278 }
0279 
0280 
0281 /*
0282  *  Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
0283  *  or DataPDUInOrder=No.
0284  */
0285 static int iscsit_do_build_pdu_and_seq_lists(
0286     struct iscsit_cmd *cmd,
0287     struct iscsi_build_list *bl)
0288 {
0289     int check_immediate = 0, datapduinorder, datasequenceinorder;
0290     u32 burstlength = 0, offset = 0, i = 0, mdsl;
0291     u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
0292     struct iscsit_conn *conn = cmd->conn;
0293     struct iscsi_pdu *pdu = cmd->pdu_list;
0294     struct iscsi_seq *seq = cmd->seq_list;
0295 
0296     if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
0297         mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
0298     else
0299         mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
0300 
0301     datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
0302     datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
0303 
0304     if ((bl->type == PDULIST_IMMEDIATE) ||
0305         (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0306         check_immediate = 1;
0307 
0308     if ((bl->type == PDULIST_UNSOLICITED) ||
0309         (bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
0310         unsolicited_data_length = min(cmd->se_cmd.data_length,
0311             conn->sess->sess_ops->FirstBurstLength);
0312 
0313     while (offset < cmd->se_cmd.data_length) {
0314         pdu_count++;
0315         if (!datapduinorder) {
0316             pdu[i].offset = offset;
0317             pdu[i].seq_no = seq_no;
0318         }
0319         if (!datasequenceinorder && (pdu_count == 1)) {
0320             seq[seq_no].pdu_start = i;
0321             seq[seq_no].seq_no = seq_no;
0322             seq[seq_no].offset = offset;
0323             seq[seq_no].orig_offset = offset;
0324         }
0325 
0326         if (check_immediate) {
0327             check_immediate = 0;
0328             if (!datapduinorder) {
0329                 pdu[i].type = PDUTYPE_IMMEDIATE;
0330                 pdu[i++].length = bl->immediate_data_length;
0331             }
0332             if (!datasequenceinorder) {
0333                 seq[seq_no].type = SEQTYPE_IMMEDIATE;
0334                 seq[seq_no].pdu_count = 1;
0335                 seq[seq_no].xfer_len =
0336                     bl->immediate_data_length;
0337             }
0338             offset += bl->immediate_data_length;
0339             pdu_count = 0;
0340             seq_no++;
0341             if (unsolicited_data_length)
0342                 unsolicited_data_length -=
0343                     bl->immediate_data_length;
0344             continue;
0345         }
0346         if (unsolicited_data_length > 0) {
0347             if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0348                 if (!datapduinorder) {
0349                     pdu[i].type = PDUTYPE_UNSOLICITED;
0350                     pdu[i].length =
0351                         (cmd->se_cmd.data_length - offset);
0352                 }
0353                 if (!datasequenceinorder) {
0354                     seq[seq_no].type = SEQTYPE_UNSOLICITED;
0355                     seq[seq_no].pdu_count = pdu_count;
0356                     seq[seq_no].xfer_len = (burstlength +
0357                         (cmd->se_cmd.data_length - offset));
0358                 }
0359                 unsolicited_data_length -=
0360                         (cmd->se_cmd.data_length - offset);
0361                 offset += (cmd->se_cmd.data_length - offset);
0362                 continue;
0363             }
0364             if ((offset + mdsl) >=
0365                     conn->sess->sess_ops->FirstBurstLength) {
0366                 if (!datapduinorder) {
0367                     pdu[i].type = PDUTYPE_UNSOLICITED;
0368                     pdu[i++].length =
0369                        (conn->sess->sess_ops->FirstBurstLength -
0370                         offset);
0371                 }
0372                 if (!datasequenceinorder) {
0373                     seq[seq_no].type = SEQTYPE_UNSOLICITED;
0374                     seq[seq_no].pdu_count = pdu_count;
0375                     seq[seq_no].xfer_len = (burstlength +
0376                        (conn->sess->sess_ops->FirstBurstLength -
0377                         offset));
0378                 }
0379                 unsolicited_data_length -=
0380                     (conn->sess->sess_ops->FirstBurstLength -
0381                         offset);
0382                 offset += (conn->sess->sess_ops->FirstBurstLength -
0383                         offset);
0384                 burstlength = 0;
0385                 pdu_count = 0;
0386                 seq_no++;
0387                 continue;
0388             }
0389 
0390             if (!datapduinorder) {
0391                 pdu[i].type = PDUTYPE_UNSOLICITED;
0392                 pdu[i++].length = mdsl;
0393             }
0394             burstlength += mdsl;
0395             offset += mdsl;
0396             unsolicited_data_length -= mdsl;
0397             continue;
0398         }
0399         if ((offset + mdsl) >= cmd->se_cmd.data_length) {
0400             if (!datapduinorder) {
0401                 pdu[i].type = PDUTYPE_NORMAL;
0402                 pdu[i].length = (cmd->se_cmd.data_length - offset);
0403             }
0404             if (!datasequenceinorder) {
0405                 seq[seq_no].type = SEQTYPE_NORMAL;
0406                 seq[seq_no].pdu_count = pdu_count;
0407                 seq[seq_no].xfer_len = (burstlength +
0408                     (cmd->se_cmd.data_length - offset));
0409             }
0410             offset += (cmd->se_cmd.data_length - offset);
0411             continue;
0412         }
0413         if ((burstlength + mdsl) >=
0414              conn->sess->sess_ops->MaxBurstLength) {
0415             if (!datapduinorder) {
0416                 pdu[i].type = PDUTYPE_NORMAL;
0417                 pdu[i++].length =
0418                     (conn->sess->sess_ops->MaxBurstLength -
0419                         burstlength);
0420             }
0421             if (!datasequenceinorder) {
0422                 seq[seq_no].type = SEQTYPE_NORMAL;
0423                 seq[seq_no].pdu_count = pdu_count;
0424                 seq[seq_no].xfer_len = (burstlength +
0425                     (conn->sess->sess_ops->MaxBurstLength -
0426                     burstlength));
0427             }
0428             offset += (conn->sess->sess_ops->MaxBurstLength -
0429                     burstlength);
0430             burstlength = 0;
0431             pdu_count = 0;
0432             seq_no++;
0433             continue;
0434         }
0435 
0436         if (!datapduinorder) {
0437             pdu[i].type = PDUTYPE_NORMAL;
0438             pdu[i++].length = mdsl;
0439         }
0440         burstlength += mdsl;
0441         offset += mdsl;
0442     }
0443 
0444     if (!datasequenceinorder) {
0445         if (bl->data_direction & ISCSI_PDU_WRITE) {
0446             if (bl->randomize & RANDOM_R2T_OFFSETS) {
0447                 if (iscsit_randomize_seq_lists(cmd, bl->type)
0448                         < 0)
0449                     return -1;
0450             } else
0451                 iscsit_ordered_seq_lists(cmd, bl->type);
0452         } else if (bl->data_direction & ISCSI_PDU_READ) {
0453             if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) {
0454                 if (iscsit_randomize_seq_lists(cmd, bl->type)
0455                         < 0)
0456                     return -1;
0457             } else
0458                 iscsit_ordered_seq_lists(cmd, bl->type);
0459         }
0460 
0461         iscsit_dump_seq_list(cmd);
0462     }
0463     if (!datapduinorder) {
0464         if (bl->data_direction & ISCSI_PDU_WRITE) {
0465             if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) {
0466                 if (iscsit_randomize_pdu_lists(cmd, bl->type)
0467                         < 0)
0468                     return -1;
0469             } else
0470                 iscsit_ordered_pdu_lists(cmd, bl->type);
0471         } else if (bl->data_direction & ISCSI_PDU_READ) {
0472             if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) {
0473                 if (iscsit_randomize_pdu_lists(cmd, bl->type)
0474                         < 0)
0475                     return -1;
0476             } else
0477                 iscsit_ordered_pdu_lists(cmd, bl->type);
0478         }
0479 
0480         iscsit_dump_pdu_list(cmd);
0481     }
0482 
0483     return 0;
0484 }
0485 
0486 int iscsit_build_pdu_and_seq_lists(
0487     struct iscsit_cmd *cmd,
0488     u32 immediate_data_length)
0489 {
0490     struct iscsi_build_list bl;
0491     u32 pdu_count = 0, seq_count = 1;
0492     struct iscsit_conn *conn = cmd->conn;
0493     struct iscsi_pdu *pdu = NULL;
0494     struct iscsi_seq *seq = NULL;
0495 
0496     struct iscsit_session *sess = conn->sess;
0497     struct iscsi_node_attrib *na;
0498 
0499     /*
0500      * Do nothing if no OOO shenanigans
0501      */
0502     if (sess->sess_ops->DataSequenceInOrder &&
0503         sess->sess_ops->DataPDUInOrder)
0504         return 0;
0505 
0506     if (cmd->data_direction == DMA_NONE)
0507         return 0;
0508 
0509     na = iscsit_tpg_get_node_attrib(sess);
0510     memset(&bl, 0, sizeof(struct iscsi_build_list));
0511 
0512     if (cmd->data_direction == DMA_FROM_DEVICE) {
0513         bl.data_direction = ISCSI_PDU_READ;
0514         bl.type = PDULIST_NORMAL;
0515         if (na->random_datain_pdu_offsets)
0516             bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
0517         if (na->random_datain_seq_offsets)
0518             bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
0519     } else {
0520         bl.data_direction = ISCSI_PDU_WRITE;
0521         bl.immediate_data_length = immediate_data_length;
0522         if (na->random_r2t_offsets)
0523             bl.randomize |= RANDOM_R2T_OFFSETS;
0524 
0525         if (!cmd->immediate_data && !cmd->unsolicited_data)
0526             bl.type = PDULIST_NORMAL;
0527         else if (cmd->immediate_data && !cmd->unsolicited_data)
0528             bl.type = PDULIST_IMMEDIATE;
0529         else if (!cmd->immediate_data && cmd->unsolicited_data)
0530             bl.type = PDULIST_UNSOLICITED;
0531         else if (cmd->immediate_data && cmd->unsolicited_data)
0532             bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
0533     }
0534 
0535     iscsit_determine_counts_for_list(cmd, &bl, &seq_count, &pdu_count);
0536 
0537     if (!conn->sess->sess_ops->DataSequenceInOrder) {
0538         seq = kcalloc(seq_count, sizeof(struct iscsi_seq), GFP_ATOMIC);
0539         if (!seq) {
0540             pr_err("Unable to allocate struct iscsi_seq list\n");
0541             return -ENOMEM;
0542         }
0543         cmd->seq_list = seq;
0544         cmd->seq_count = seq_count;
0545     }
0546 
0547     if (!conn->sess->sess_ops->DataPDUInOrder) {
0548         pdu = kcalloc(pdu_count, sizeof(struct iscsi_pdu), GFP_ATOMIC);
0549         if (!pdu) {
0550             pr_err("Unable to allocate struct iscsi_pdu list.\n");
0551             kfree(seq);
0552             return -ENOMEM;
0553         }
0554         cmd->pdu_list = pdu;
0555         cmd->pdu_count = pdu_count;
0556     }
0557 
0558     return iscsit_do_build_pdu_and_seq_lists(cmd, &bl);
0559 }
0560 
0561 struct iscsi_pdu *iscsit_get_pdu_holder(
0562     struct iscsit_cmd *cmd,
0563     u32 offset,
0564     u32 length)
0565 {
0566     u32 i;
0567     struct iscsi_pdu *pdu = NULL;
0568 
0569     if (!cmd->pdu_list) {
0570         pr_err("struct iscsit_cmd->pdu_list is NULL!\n");
0571         return NULL;
0572     }
0573 
0574     pdu = &cmd->pdu_list[0];
0575 
0576     for (i = 0; i < cmd->pdu_count; i++)
0577         if ((pdu[i].offset == offset) && (pdu[i].length == length))
0578             return &pdu[i];
0579 
0580     pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
0581         " %u, Length: %u\n", cmd->init_task_tag, offset, length);
0582     return NULL;
0583 }
0584 
0585 struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(
0586     struct iscsit_cmd *cmd,
0587     struct iscsi_seq *seq)
0588 {
0589     u32 i;
0590     struct iscsit_conn *conn = cmd->conn;
0591     struct iscsi_pdu *pdu = NULL;
0592 
0593     if (!cmd->pdu_list) {
0594         pr_err("struct iscsit_cmd->pdu_list is NULL!\n");
0595         return NULL;
0596     }
0597 
0598     if (conn->sess->sess_ops->DataSequenceInOrder) {
0599 redo:
0600         pdu = &cmd->pdu_list[cmd->pdu_start];
0601 
0602         for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
0603             pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
0604                 "_send_order: %d, pdu[i].offset: %d,"
0605                 " pdu[i].length: %d\n", pdu[i].seq_no,
0606                 pdu[i].pdu_send_order, pdu[i].offset,
0607                 pdu[i].length);
0608 
0609             if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
0610                 cmd->pdu_send_order++;
0611                 return &pdu[i];
0612             }
0613         }
0614 
0615         cmd->pdu_start += cmd->pdu_send_order;
0616         cmd->pdu_send_order = 0;
0617         cmd->seq_no++;
0618 
0619         if (cmd->pdu_start < cmd->pdu_count)
0620             goto redo;
0621 
0622         pr_err("Command ITT: 0x%08x unable to locate"
0623             " struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
0624             cmd->init_task_tag, cmd->pdu_send_order);
0625         return NULL;
0626     } else {
0627         if (!seq) {
0628             pr_err("struct iscsi_seq is NULL!\n");
0629             return NULL;
0630         }
0631 
0632         pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
0633             " seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
0634             seq->seq_no);
0635 
0636         pdu = &cmd->pdu_list[seq->pdu_start];
0637 
0638         if (seq->pdu_send_order == seq->pdu_count) {
0639             pr_err("Command ITT: 0x%08x seq->pdu_send"
0640                 "_order: %u equals seq->pdu_count: %u\n",
0641                 cmd->init_task_tag, seq->pdu_send_order,
0642                 seq->pdu_count);
0643             return NULL;
0644         }
0645 
0646         for (i = 0; i < seq->pdu_count; i++) {
0647             if (pdu[i].pdu_send_order == seq->pdu_send_order) {
0648                 seq->pdu_send_order++;
0649                 return &pdu[i];
0650             }
0651         }
0652 
0653         pr_err("Command ITT: 0x%08x unable to locate iscsi"
0654             "_pdu_t for seq->pdu_send_order: %u.\n",
0655             cmd->init_task_tag, seq->pdu_send_order);
0656         return NULL;
0657     }
0658 
0659     return NULL;
0660 }
0661 
0662 struct iscsi_seq *iscsit_get_seq_holder(
0663     struct iscsit_cmd *cmd,
0664     u32 offset,
0665     u32 length)
0666 {
0667     u32 i;
0668 
0669     if (!cmd->seq_list) {
0670         pr_err("struct iscsit_cmd->seq_list is NULL!\n");
0671         return NULL;
0672     }
0673 
0674     for (i = 0; i < cmd->seq_count; i++) {
0675         pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
0676             "xfer_len: %d, seq_list[i].seq_no %u\n",
0677             cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
0678             cmd->seq_list[i].seq_no);
0679 
0680         if ((cmd->seq_list[i].orig_offset +
0681                 cmd->seq_list[i].xfer_len) >=
0682                 (offset + length))
0683             return &cmd->seq_list[i];
0684     }
0685 
0686     pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
0687         " Offset: %u, Length: %u\n", cmd->init_task_tag, offset,
0688         length);
0689     return NULL;
0690 }