iscsi_target_seq_pdu_list.c 17 KB

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