1 /*******************************************************************************
2 * This file contains main functions related to iSCSI DataSequenceInOrder=No
3 * and DataPDUInOrder=No.
5 * (c) Copyright 2007-2013 Datera, Inc.
7 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
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.
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 ******************************************************************************/
20 #include <linux/slab.h>
21 #include <linux/random.h>
23 #include <target/iscsi/iscsi_target_core.h>
24 #include "iscsi_target_util.h"
25 #include "iscsi_target_tpg.h"
26 #include "iscsi_target_seq_pdu_list.h"
29 static void iscsit_dump_seq_list(struct iscsi_cmd
*cmd
)
32 struct iscsi_seq
*seq
;
34 pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
37 for (i
= 0; i
< cmd
->seq_count
; i
++) {
38 seq
= &cmd
->seq_list
[i
];
39 pr_debug("i: %d, pdu_start: %d, pdu_count: %d,"
40 " offset: %d, xfer_len: %d, seq_send_order: %d,"
41 " seq_no: %d\n", i
, seq
->pdu_start
, seq
->pdu_count
,
42 seq
->offset
, seq
->xfer_len
, seq
->seq_send_order
,
47 static void iscsit_dump_pdu_list(struct iscsi_cmd
*cmd
)
50 struct iscsi_pdu
*pdu
;
52 pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
55 for (i
= 0; i
< cmd
->pdu_count
; i
++) {
56 pdu
= &cmd
->pdu_list
[i
];
57 pr_debug("i: %d, offset: %d, length: %d,"
58 " pdu_send_order: %d, seq_no: %d\n", i
, pdu
->offset
,
59 pdu
->length
, pdu
->pdu_send_order
, pdu
->seq_no
);
63 static void iscsit_dump_seq_list(struct iscsi_cmd
*cmd
) {}
64 static void iscsit_dump_pdu_list(struct iscsi_cmd
*cmd
) {}
67 static void iscsit_ordered_seq_lists(
68 struct iscsi_cmd
*cmd
,
73 for (i
= 0; i
< cmd
->seq_count
; i
++) {
74 if (cmd
->seq_list
[i
].type
!= SEQTYPE_NORMAL
)
76 cmd
->seq_list
[i
].seq_send_order
= seq_count
++;
80 static void iscsit_ordered_pdu_lists(
81 struct iscsi_cmd
*cmd
,
84 u32 i
, pdu_send_order
= 0, seq_no
= 0;
86 for (i
= 0; i
< cmd
->pdu_count
; i
++) {
88 if (cmd
->pdu_list
[i
].seq_no
== seq_no
) {
89 cmd
->pdu_list
[i
].pdu_send_order
= pdu_send_order
++;
99 * Generate count random values into array.
100 * Use 0x80000000 to mark generates valued in array[].
102 static void iscsit_create_random_array(u32
*array
, u32 count
)
111 for (i
= 0; i
< count
; i
++) {
113 get_random_bytes(&j
, sizeof(u32
));
114 j
= (1 + (int) (9999 + 1) - j
) % count
;
115 for (k
= 0; k
< i
+ 1; k
++) {
117 if ((array
[k
] & 0x80000000) && (array
[k
] == j
))
123 for (i
= 0; i
< count
; i
++)
124 array
[i
] &= ~0x80000000;
127 static int iscsit_randomize_pdu_lists(
128 struct iscsi_cmd
*cmd
,
132 u32
*array
, pdu_count
, seq_count
= 0, seq_no
= 0, seq_offset
= 0;
134 for (pdu_count
= 0; pdu_count
< cmd
->pdu_count
; pdu_count
++) {
136 if (cmd
->pdu_list
[pdu_count
].seq_no
== seq_no
) {
140 array
= kcalloc(seq_count
, sizeof(u32
), GFP_KERNEL
);
142 pr_err("Unable to allocate memory"
143 " for random array.\n");
146 iscsit_create_random_array(array
, seq_count
);
148 for (i
= 0; i
< seq_count
; i
++)
149 cmd
->pdu_list
[seq_offset
+i
].pdu_send_order
= array
[i
];
153 seq_offset
+= seq_count
;
160 array
= kcalloc(seq_count
, sizeof(u32
), GFP_KERNEL
);
162 pr_err("Unable to allocate memory for"
166 iscsit_create_random_array(array
, seq_count
);
168 for (i
= 0; i
< seq_count
; i
++)
169 cmd
->pdu_list
[seq_offset
+i
].pdu_send_order
= array
[i
];
177 static int iscsit_randomize_seq_lists(
178 struct iscsi_cmd
*cmd
,
182 u32
*array
, seq_count
= cmd
->seq_count
;
184 if ((type
== PDULIST_IMMEDIATE
) || (type
== PDULIST_UNSOLICITED
))
186 else if (type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
)
192 array
= kcalloc(seq_count
, sizeof(u32
), GFP_KERNEL
);
194 pr_err("Unable to allocate memory for random array.\n");
197 iscsit_create_random_array(array
, seq_count
);
199 for (i
= 0; i
< cmd
->seq_count
; i
++) {
200 if (cmd
->seq_list
[i
].type
!= SEQTYPE_NORMAL
)
202 cmd
->seq_list
[i
].seq_send_order
= array
[j
++];
209 static void iscsit_determine_counts_for_list(
210 struct iscsi_cmd
*cmd
,
211 struct iscsi_build_list
*bl
,
215 int check_immediate
= 0;
216 u32 burstlength
= 0, offset
= 0;
217 u32 unsolicited_data_length
= 0;
219 struct iscsi_conn
*conn
= cmd
->conn
;
221 if (cmd
->se_cmd
.data_direction
== DMA_TO_DEVICE
)
222 mdsl
= cmd
->conn
->conn_ops
->MaxXmitDataSegmentLength
;
224 mdsl
= cmd
->conn
->conn_ops
->MaxRecvDataSegmentLength
;
226 if ((bl
->type
== PDULIST_IMMEDIATE
) ||
227 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
230 if ((bl
->type
== PDULIST_UNSOLICITED
) ||
231 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
232 unsolicited_data_length
= min(cmd
->se_cmd
.data_length
,
233 conn
->sess
->sess_ops
->FirstBurstLength
);
235 while (offset
< cmd
->se_cmd
.data_length
) {
238 if (check_immediate
) {
240 offset
+= bl
->immediate_data_length
;
242 if (unsolicited_data_length
)
243 unsolicited_data_length
-=
244 bl
->immediate_data_length
;
247 if (unsolicited_data_length
> 0) {
248 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
249 unsolicited_data_length
-=
250 (cmd
->se_cmd
.data_length
- offset
);
251 offset
+= (cmd
->se_cmd
.data_length
- offset
);
255 >= conn
->sess
->sess_ops
->FirstBurstLength
) {
256 unsolicited_data_length
-=
257 (conn
->sess
->sess_ops
->FirstBurstLength
-
259 offset
+= (conn
->sess
->sess_ops
->FirstBurstLength
-
267 unsolicited_data_length
-= mdsl
;
270 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
271 offset
+= (cmd
->se_cmd
.data_length
- offset
);
274 if ((burstlength
+ mdsl
) >=
275 conn
->sess
->sess_ops
->MaxBurstLength
) {
276 offset
+= (conn
->sess
->sess_ops
->MaxBurstLength
-
290 * Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
291 * or DataPDUInOrder=No.
293 static int iscsit_do_build_pdu_and_seq_lists(
294 struct iscsi_cmd
*cmd
,
295 struct iscsi_build_list
*bl
)
297 int check_immediate
= 0, datapduinorder
, datasequenceinorder
;
298 u32 burstlength
= 0, offset
= 0, i
= 0, mdsl
;
299 u32 pdu_count
= 0, seq_no
= 0, unsolicited_data_length
= 0;
300 struct iscsi_conn
*conn
= cmd
->conn
;
301 struct iscsi_pdu
*pdu
= cmd
->pdu_list
;
302 struct iscsi_seq
*seq
= cmd
->seq_list
;
304 if (cmd
->se_cmd
.data_direction
== DMA_TO_DEVICE
)
305 mdsl
= cmd
->conn
->conn_ops
->MaxXmitDataSegmentLength
;
307 mdsl
= cmd
->conn
->conn_ops
->MaxRecvDataSegmentLength
;
309 datapduinorder
= conn
->sess
->sess_ops
->DataPDUInOrder
;
310 datasequenceinorder
= conn
->sess
->sess_ops
->DataSequenceInOrder
;
312 if ((bl
->type
== PDULIST_IMMEDIATE
) ||
313 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
316 if ((bl
->type
== PDULIST_UNSOLICITED
) ||
317 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
318 unsolicited_data_length
= min(cmd
->se_cmd
.data_length
,
319 conn
->sess
->sess_ops
->FirstBurstLength
);
321 while (offset
< cmd
->se_cmd
.data_length
) {
323 if (!datapduinorder
) {
324 pdu
[i
].offset
= offset
;
325 pdu
[i
].seq_no
= seq_no
;
327 if (!datasequenceinorder
&& (pdu_count
== 1)) {
328 seq
[seq_no
].pdu_start
= i
;
329 seq
[seq_no
].seq_no
= seq_no
;
330 seq
[seq_no
].offset
= offset
;
331 seq
[seq_no
].orig_offset
= offset
;
334 if (check_immediate
) {
336 if (!datapduinorder
) {
337 pdu
[i
].type
= PDUTYPE_IMMEDIATE
;
338 pdu
[i
++].length
= bl
->immediate_data_length
;
340 if (!datasequenceinorder
) {
341 seq
[seq_no
].type
= SEQTYPE_IMMEDIATE
;
342 seq
[seq_no
].pdu_count
= 1;
343 seq
[seq_no
].xfer_len
=
344 bl
->immediate_data_length
;
346 offset
+= bl
->immediate_data_length
;
349 if (unsolicited_data_length
)
350 unsolicited_data_length
-=
351 bl
->immediate_data_length
;
354 if (unsolicited_data_length
> 0) {
355 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
356 if (!datapduinorder
) {
357 pdu
[i
].type
= PDUTYPE_UNSOLICITED
;
359 (cmd
->se_cmd
.data_length
- offset
);
361 if (!datasequenceinorder
) {
362 seq
[seq_no
].type
= SEQTYPE_UNSOLICITED
;
363 seq
[seq_no
].pdu_count
= pdu_count
;
364 seq
[seq_no
].xfer_len
= (burstlength
+
365 (cmd
->se_cmd
.data_length
- offset
));
367 unsolicited_data_length
-=
368 (cmd
->se_cmd
.data_length
- offset
);
369 offset
+= (cmd
->se_cmd
.data_length
- offset
);
372 if ((offset
+ mdsl
) >=
373 conn
->sess
->sess_ops
->FirstBurstLength
) {
374 if (!datapduinorder
) {
375 pdu
[i
].type
= PDUTYPE_UNSOLICITED
;
377 (conn
->sess
->sess_ops
->FirstBurstLength
-
380 if (!datasequenceinorder
) {
381 seq
[seq_no
].type
= SEQTYPE_UNSOLICITED
;
382 seq
[seq_no
].pdu_count
= pdu_count
;
383 seq
[seq_no
].xfer_len
= (burstlength
+
384 (conn
->sess
->sess_ops
->FirstBurstLength
-
387 unsolicited_data_length
-=
388 (conn
->sess
->sess_ops
->FirstBurstLength
-
390 offset
+= (conn
->sess
->sess_ops
->FirstBurstLength
-
398 if (!datapduinorder
) {
399 pdu
[i
].type
= PDUTYPE_UNSOLICITED
;
400 pdu
[i
++].length
= mdsl
;
404 unsolicited_data_length
-= mdsl
;
407 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
408 if (!datapduinorder
) {
409 pdu
[i
].type
= PDUTYPE_NORMAL
;
410 pdu
[i
].length
= (cmd
->se_cmd
.data_length
- offset
);
412 if (!datasequenceinorder
) {
413 seq
[seq_no
].type
= SEQTYPE_NORMAL
;
414 seq
[seq_no
].pdu_count
= pdu_count
;
415 seq
[seq_no
].xfer_len
= (burstlength
+
416 (cmd
->se_cmd
.data_length
- offset
));
418 offset
+= (cmd
->se_cmd
.data_length
- offset
);
421 if ((burstlength
+ mdsl
) >=
422 conn
->sess
->sess_ops
->MaxBurstLength
) {
423 if (!datapduinorder
) {
424 pdu
[i
].type
= PDUTYPE_NORMAL
;
426 (conn
->sess
->sess_ops
->MaxBurstLength
-
429 if (!datasequenceinorder
) {
430 seq
[seq_no
].type
= SEQTYPE_NORMAL
;
431 seq
[seq_no
].pdu_count
= pdu_count
;
432 seq
[seq_no
].xfer_len
= (burstlength
+
433 (conn
->sess
->sess_ops
->MaxBurstLength
-
436 offset
+= (conn
->sess
->sess_ops
->MaxBurstLength
-
444 if (!datapduinorder
) {
445 pdu
[i
].type
= PDUTYPE_NORMAL
;
446 pdu
[i
++].length
= mdsl
;
452 if (!datasequenceinorder
) {
453 if (bl
->data_direction
& ISCSI_PDU_WRITE
) {
454 if (bl
->randomize
& RANDOM_R2T_OFFSETS
) {
455 if (iscsit_randomize_seq_lists(cmd
, bl
->type
)
459 iscsit_ordered_seq_lists(cmd
, bl
->type
);
460 } else if (bl
->data_direction
& ISCSI_PDU_READ
) {
461 if (bl
->randomize
& RANDOM_DATAIN_SEQ_OFFSETS
) {
462 if (iscsit_randomize_seq_lists(cmd
, bl
->type
)
466 iscsit_ordered_seq_lists(cmd
, bl
->type
);
469 iscsit_dump_seq_list(cmd
);
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
)
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
)
485 iscsit_ordered_pdu_lists(cmd
, bl
->type
);
488 iscsit_dump_pdu_list(cmd
);
494 int iscsit_build_pdu_and_seq_lists(
495 struct iscsi_cmd
*cmd
,
496 u32 immediate_data_length
)
498 struct iscsi_build_list bl
;
499 u32 pdu_count
= 0, seq_count
= 1;
500 struct iscsi_conn
*conn
= cmd
->conn
;
501 struct iscsi_pdu
*pdu
= NULL
;
502 struct iscsi_seq
*seq
= NULL
;
504 struct iscsi_session
*sess
= conn
->sess
;
505 struct iscsi_node_attrib
*na
;
508 * Do nothing if no OOO shenanigans
510 if (sess
->sess_ops
->DataSequenceInOrder
&&
511 sess
->sess_ops
->DataPDUInOrder
)
514 if (cmd
->data_direction
== DMA_NONE
)
517 na
= iscsit_tpg_get_node_attrib(sess
);
518 memset(&bl
, 0, sizeof(struct iscsi_build_list
));
520 if (cmd
->data_direction
== DMA_FROM_DEVICE
) {
521 bl
.data_direction
= ISCSI_PDU_READ
;
522 bl
.type
= PDULIST_NORMAL
;
523 if (na
->random_datain_pdu_offsets
)
524 bl
.randomize
|= RANDOM_DATAIN_PDU_OFFSETS
;
525 if (na
->random_datain_seq_offsets
)
526 bl
.randomize
|= RANDOM_DATAIN_SEQ_OFFSETS
;
528 bl
.data_direction
= ISCSI_PDU_WRITE
;
529 bl
.immediate_data_length
= immediate_data_length
;
530 if (na
->random_r2t_offsets
)
531 bl
.randomize
|= RANDOM_R2T_OFFSETS
;
533 if (!cmd
->immediate_data
&& !cmd
->unsolicited_data
)
534 bl
.type
= PDULIST_NORMAL
;
535 else if (cmd
->immediate_data
&& !cmd
->unsolicited_data
)
536 bl
.type
= PDULIST_IMMEDIATE
;
537 else if (!cmd
->immediate_data
&& cmd
->unsolicited_data
)
538 bl
.type
= PDULIST_UNSOLICITED
;
539 else if (cmd
->immediate_data
&& cmd
->unsolicited_data
)
540 bl
.type
= PDULIST_IMMEDIATE_AND_UNSOLICITED
;
543 iscsit_determine_counts_for_list(cmd
, &bl
, &seq_count
, &pdu_count
);
545 if (!conn
->sess
->sess_ops
->DataSequenceInOrder
) {
546 seq
= kcalloc(seq_count
, sizeof(struct iscsi_seq
), GFP_ATOMIC
);
548 pr_err("Unable to allocate struct iscsi_seq list\n");
552 cmd
->seq_count
= seq_count
;
555 if (!conn
->sess
->sess_ops
->DataPDUInOrder
) {
556 pdu
= kcalloc(pdu_count
, sizeof(struct iscsi_pdu
), GFP_ATOMIC
);
558 pr_err("Unable to allocate struct iscsi_pdu list.\n");
563 cmd
->pdu_count
= pdu_count
;
566 return iscsit_do_build_pdu_and_seq_lists(cmd
, &bl
);
569 struct iscsi_pdu
*iscsit_get_pdu_holder(
570 struct iscsi_cmd
*cmd
,
575 struct iscsi_pdu
*pdu
= NULL
;
577 if (!cmd
->pdu_list
) {
578 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
582 pdu
= &cmd
->pdu_list
[0];
584 for (i
= 0; i
< cmd
->pdu_count
; i
++)
585 if ((pdu
[i
].offset
== offset
) && (pdu
[i
].length
== length
))
588 pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
589 " %u, Length: %u\n", cmd
->init_task_tag
, offset
, length
);
593 struct iscsi_pdu
*iscsit_get_pdu_holder_for_seq(
594 struct iscsi_cmd
*cmd
,
595 struct iscsi_seq
*seq
)
598 struct iscsi_conn
*conn
= cmd
->conn
;
599 struct iscsi_pdu
*pdu
= NULL
;
601 if (!cmd
->pdu_list
) {
602 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
606 if (conn
->sess
->sess_ops
->DataSequenceInOrder
) {
608 pdu
= &cmd
->pdu_list
[cmd
->pdu_start
];
610 for (i
= 0; pdu
[i
].seq_no
!= cmd
->seq_no
; i
++) {
611 pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
612 "_send_order: %d, pdu[i].offset: %d,"
613 " pdu[i].length: %d\n", pdu
[i
].seq_no
,
614 pdu
[i
].pdu_send_order
, pdu
[i
].offset
,
617 if (pdu
[i
].pdu_send_order
== cmd
->pdu_send_order
) {
618 cmd
->pdu_send_order
++;
623 cmd
->pdu_start
+= cmd
->pdu_send_order
;
624 cmd
->pdu_send_order
= 0;
627 if (cmd
->pdu_start
< cmd
->pdu_count
)
630 pr_err("Command ITT: 0x%08x unable to locate"
631 " struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
632 cmd
->init_task_tag
, cmd
->pdu_send_order
);
636 pr_err("struct iscsi_seq is NULL!\n");
640 pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
641 " seq->seq_no: %d\n", seq
->pdu_start
, seq
->pdu_count
,
644 pdu
= &cmd
->pdu_list
[seq
->pdu_start
];
646 if (seq
->pdu_send_order
== seq
->pdu_count
) {
647 pr_err("Command ITT: 0x%08x seq->pdu_send"
648 "_order: %u equals seq->pdu_count: %u\n",
649 cmd
->init_task_tag
, seq
->pdu_send_order
,
654 for (i
= 0; i
< seq
->pdu_count
; i
++) {
655 if (pdu
[i
].pdu_send_order
== seq
->pdu_send_order
) {
656 seq
->pdu_send_order
++;
661 pr_err("Command ITT: 0x%08x unable to locate iscsi"
662 "_pdu_t for seq->pdu_send_order: %u.\n",
663 cmd
->init_task_tag
, seq
->pdu_send_order
);
670 struct iscsi_seq
*iscsit_get_seq_holder(
671 struct iscsi_cmd
*cmd
,
677 if (!cmd
->seq_list
) {
678 pr_err("struct iscsi_cmd->seq_list is NULL!\n");
682 for (i
= 0; i
< cmd
->seq_count
; i
++) {
683 pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
684 "xfer_len: %d, seq_list[i].seq_no %u\n",
685 cmd
->seq_list
[i
].orig_offset
, cmd
->seq_list
[i
].xfer_len
,
686 cmd
->seq_list
[i
].seq_no
);
688 if ((cmd
->seq_list
[i
].orig_offset
+
689 cmd
->seq_list
[i
].xfer_len
) >=
691 return &cmd
->seq_list
[i
];
694 pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
695 " Offset: %u, Length: %u\n", cmd
->init_task_tag
, offset
,