Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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