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 "iscsi_target_core.h"
24 #include "iscsi_target_util.h"
25 #include "iscsi_target_tpg.h"
26 #include "iscsi_target_seq_pdu_list.h"
28 #define OFFLOAD_BUF_SIZE 32768
31 static void iscsit_dump_seq_list(struct iscsi_cmd
*cmd
)
34 struct iscsi_seq
*seq
;
36 pr_debug("Dumping Sequence List for ITT: 0x%08x:\n",
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
,
49 static void iscsit_dump_pdu_list(struct iscsi_cmd
*cmd
)
52 struct iscsi_pdu
*pdu
;
54 pr_debug("Dumping PDU List for ITT: 0x%08x:\n",
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
);
65 static void iscsit_dump_seq_list(struct iscsi_cmd
*cmd
) {}
66 static void iscsit_dump_pdu_list(struct iscsi_cmd
*cmd
) {}
69 static void iscsit_ordered_seq_lists(
70 struct iscsi_cmd
*cmd
,
75 for (i
= 0; i
< cmd
->seq_count
; i
++) {
76 if (cmd
->seq_list
[i
].type
!= SEQTYPE_NORMAL
)
78 cmd
->seq_list
[i
].seq_send_order
= seq_count
++;
82 static void iscsit_ordered_pdu_lists(
83 struct iscsi_cmd
*cmd
,
86 u32 i
, pdu_send_order
= 0, seq_no
= 0;
88 for (i
= 0; i
< cmd
->pdu_count
; i
++) {
90 if (cmd
->pdu_list
[i
].seq_no
== seq_no
) {
91 cmd
->pdu_list
[i
].pdu_send_order
= pdu_send_order
++;
101 * Generate count random values into array.
102 * Use 0x80000000 to mark generates valued in array[].
104 static void iscsit_create_random_array(u32
*array
, u32 count
)
113 for (i
= 0; i
< count
; i
++) {
115 get_random_bytes(&j
, sizeof(u32
));
116 j
= (1 + (int) (9999 + 1) - j
) % count
;
117 for (k
= 0; k
< i
+ 1; k
++) {
119 if ((array
[k
] & 0x80000000) && (array
[k
] == j
))
125 for (i
= 0; i
< count
; i
++)
126 array
[i
] &= ~0x80000000;
129 static int iscsit_randomize_pdu_lists(
130 struct iscsi_cmd
*cmd
,
134 u32
*array
, pdu_count
, seq_count
= 0, seq_no
= 0, seq_offset
= 0;
136 for (pdu_count
= 0; pdu_count
< cmd
->pdu_count
; pdu_count
++) {
138 if (cmd
->pdu_list
[pdu_count
].seq_no
== seq_no
) {
142 array
= kcalloc(seq_count
, sizeof(u32
), GFP_KERNEL
);
144 pr_err("Unable to allocate memory"
145 " for random array.\n");
148 iscsit_create_random_array(array
, seq_count
);
150 for (i
= 0; i
< seq_count
; i
++)
151 cmd
->pdu_list
[seq_offset
+i
].pdu_send_order
= array
[i
];
155 seq_offset
+= seq_count
;
162 array
= kcalloc(seq_count
, sizeof(u32
), GFP_KERNEL
);
164 pr_err("Unable to allocate memory for"
168 iscsit_create_random_array(array
, seq_count
);
170 for (i
= 0; i
< seq_count
; i
++)
171 cmd
->pdu_list
[seq_offset
+i
].pdu_send_order
= array
[i
];
179 static int iscsit_randomize_seq_lists(
180 struct iscsi_cmd
*cmd
,
184 u32
*array
, seq_count
= cmd
->seq_count
;
186 if ((type
== PDULIST_IMMEDIATE
) || (type
== PDULIST_UNSOLICITED
))
188 else if (type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
)
194 array
= kcalloc(seq_count
, sizeof(u32
), GFP_KERNEL
);
196 pr_err("Unable to allocate memory for random array.\n");
199 iscsit_create_random_array(array
, seq_count
);
201 for (i
= 0; i
< cmd
->seq_count
; i
++) {
202 if (cmd
->seq_list
[i
].type
!= SEQTYPE_NORMAL
)
204 cmd
->seq_list
[i
].seq_send_order
= array
[j
++];
211 static void iscsit_determine_counts_for_list(
212 struct iscsi_cmd
*cmd
,
213 struct iscsi_build_list
*bl
,
217 int check_immediate
= 0;
218 u32 burstlength
= 0, offset
= 0;
219 u32 unsolicited_data_length
= 0;
221 struct iscsi_conn
*conn
= cmd
->conn
;
223 if (cmd
->se_cmd
.data_direction
== DMA_TO_DEVICE
)
224 mdsl
= cmd
->conn
->conn_ops
->MaxXmitDataSegmentLength
;
226 mdsl
= cmd
->conn
->conn_ops
->MaxRecvDataSegmentLength
;
228 if ((bl
->type
== PDULIST_IMMEDIATE
) ||
229 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
232 if ((bl
->type
== PDULIST_UNSOLICITED
) ||
233 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
234 unsolicited_data_length
= min(cmd
->se_cmd
.data_length
,
235 conn
->sess
->sess_ops
->FirstBurstLength
);
237 while (offset
< cmd
->se_cmd
.data_length
) {
240 if (check_immediate
) {
242 offset
+= bl
->immediate_data_length
;
244 if (unsolicited_data_length
)
245 unsolicited_data_length
-=
246 bl
->immediate_data_length
;
249 if (unsolicited_data_length
> 0) {
250 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
251 unsolicited_data_length
-=
252 (cmd
->se_cmd
.data_length
- offset
);
253 offset
+= (cmd
->se_cmd
.data_length
- offset
);
257 >= conn
->sess
->sess_ops
->FirstBurstLength
) {
258 unsolicited_data_length
-=
259 (conn
->sess
->sess_ops
->FirstBurstLength
-
261 offset
+= (conn
->sess
->sess_ops
->FirstBurstLength
-
269 unsolicited_data_length
-= mdsl
;
272 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
273 offset
+= (cmd
->se_cmd
.data_length
- offset
);
276 if ((burstlength
+ mdsl
) >=
277 conn
->sess
->sess_ops
->MaxBurstLength
) {
278 offset
+= (conn
->sess
->sess_ops
->MaxBurstLength
-
292 * Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
293 * or DataPDUInOrder=No.
295 static int iscsit_do_build_pdu_and_seq_lists(
296 struct iscsi_cmd
*cmd
,
297 struct iscsi_build_list
*bl
)
299 int check_immediate
= 0, datapduinorder
, datasequenceinorder
;
300 u32 burstlength
= 0, offset
= 0, i
= 0, mdsl
;
301 u32 pdu_count
= 0, seq_no
= 0, unsolicited_data_length
= 0;
302 struct iscsi_conn
*conn
= cmd
->conn
;
303 struct iscsi_pdu
*pdu
= cmd
->pdu_list
;
304 struct iscsi_seq
*seq
= cmd
->seq_list
;
306 if (cmd
->se_cmd
.data_direction
== DMA_TO_DEVICE
)
307 mdsl
= cmd
->conn
->conn_ops
->MaxXmitDataSegmentLength
;
309 mdsl
= cmd
->conn
->conn_ops
->MaxRecvDataSegmentLength
;
311 datapduinorder
= conn
->sess
->sess_ops
->DataPDUInOrder
;
312 datasequenceinorder
= conn
->sess
->sess_ops
->DataSequenceInOrder
;
314 if ((bl
->type
== PDULIST_IMMEDIATE
) ||
315 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
318 if ((bl
->type
== PDULIST_UNSOLICITED
) ||
319 (bl
->type
== PDULIST_IMMEDIATE_AND_UNSOLICITED
))
320 unsolicited_data_length
= min(cmd
->se_cmd
.data_length
,
321 conn
->sess
->sess_ops
->FirstBurstLength
);
323 while (offset
< cmd
->se_cmd
.data_length
) {
325 if (!datapduinorder
) {
326 pdu
[i
].offset
= offset
;
327 pdu
[i
].seq_no
= seq_no
;
329 if (!datasequenceinorder
&& (pdu_count
== 1)) {
330 seq
[seq_no
].pdu_start
= i
;
331 seq
[seq_no
].seq_no
= seq_no
;
332 seq
[seq_no
].offset
= offset
;
333 seq
[seq_no
].orig_offset
= offset
;
336 if (check_immediate
) {
338 if (!datapduinorder
) {
339 pdu
[i
].type
= PDUTYPE_IMMEDIATE
;
340 pdu
[i
++].length
= bl
->immediate_data_length
;
342 if (!datasequenceinorder
) {
343 seq
[seq_no
].type
= SEQTYPE_IMMEDIATE
;
344 seq
[seq_no
].pdu_count
= 1;
345 seq
[seq_no
].xfer_len
=
346 bl
->immediate_data_length
;
348 offset
+= bl
->immediate_data_length
;
351 if (unsolicited_data_length
)
352 unsolicited_data_length
-=
353 bl
->immediate_data_length
;
356 if (unsolicited_data_length
> 0) {
357 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
358 if (!datapduinorder
) {
359 pdu
[i
].type
= PDUTYPE_UNSOLICITED
;
361 (cmd
->se_cmd
.data_length
- offset
);
363 if (!datasequenceinorder
) {
364 seq
[seq_no
].type
= SEQTYPE_UNSOLICITED
;
365 seq
[seq_no
].pdu_count
= pdu_count
;
366 seq
[seq_no
].xfer_len
= (burstlength
+
367 (cmd
->se_cmd
.data_length
- offset
));
369 unsolicited_data_length
-=
370 (cmd
->se_cmd
.data_length
- offset
);
371 offset
+= (cmd
->se_cmd
.data_length
- offset
);
374 if ((offset
+ mdsl
) >=
375 conn
->sess
->sess_ops
->FirstBurstLength
) {
376 if (!datapduinorder
) {
377 pdu
[i
].type
= PDUTYPE_UNSOLICITED
;
379 (conn
->sess
->sess_ops
->FirstBurstLength
-
382 if (!datasequenceinorder
) {
383 seq
[seq_no
].type
= SEQTYPE_UNSOLICITED
;
384 seq
[seq_no
].pdu_count
= pdu_count
;
385 seq
[seq_no
].xfer_len
= (burstlength
+
386 (conn
->sess
->sess_ops
->FirstBurstLength
-
389 unsolicited_data_length
-=
390 (conn
->sess
->sess_ops
->FirstBurstLength
-
392 offset
+= (conn
->sess
->sess_ops
->FirstBurstLength
-
400 if (!datapduinorder
) {
401 pdu
[i
].type
= PDUTYPE_UNSOLICITED
;
402 pdu
[i
++].length
= mdsl
;
406 unsolicited_data_length
-= mdsl
;
409 if ((offset
+ mdsl
) >= cmd
->se_cmd
.data_length
) {
410 if (!datapduinorder
) {
411 pdu
[i
].type
= PDUTYPE_NORMAL
;
412 pdu
[i
].length
= (cmd
->se_cmd
.data_length
- offset
);
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
));
420 offset
+= (cmd
->se_cmd
.data_length
- offset
);
423 if ((burstlength
+ mdsl
) >=
424 conn
->sess
->sess_ops
->MaxBurstLength
) {
425 if (!datapduinorder
) {
426 pdu
[i
].type
= PDUTYPE_NORMAL
;
428 (conn
->sess
->sess_ops
->MaxBurstLength
-
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
-
438 offset
+= (conn
->sess
->sess_ops
->MaxBurstLength
-
446 if (!datapduinorder
) {
447 pdu
[i
].type
= PDUTYPE_NORMAL
;
448 pdu
[i
++].length
= mdsl
;
454 if (!datasequenceinorder
) {
455 if (bl
->data_direction
& ISCSI_PDU_WRITE
) {
456 if (bl
->randomize
& RANDOM_R2T_OFFSETS
) {
457 if (iscsit_randomize_seq_lists(cmd
, bl
->type
)
461 iscsit_ordered_seq_lists(cmd
, bl
->type
);
462 } else if (bl
->data_direction
& ISCSI_PDU_READ
) {
463 if (bl
->randomize
& RANDOM_DATAIN_SEQ_OFFSETS
) {
464 if (iscsit_randomize_seq_lists(cmd
, bl
->type
)
468 iscsit_ordered_seq_lists(cmd
, bl
->type
);
471 iscsit_dump_seq_list(cmd
);
473 if (!datapduinorder
) {
474 if (bl
->data_direction
& ISCSI_PDU_WRITE
) {
475 if (bl
->randomize
& RANDOM_DATAOUT_PDU_OFFSETS
) {
476 if (iscsit_randomize_pdu_lists(cmd
, bl
->type
)
480 iscsit_ordered_pdu_lists(cmd
, bl
->type
);
481 } else if (bl
->data_direction
& ISCSI_PDU_READ
) {
482 if (bl
->randomize
& RANDOM_DATAIN_PDU_OFFSETS
) {
483 if (iscsit_randomize_pdu_lists(cmd
, bl
->type
)
487 iscsit_ordered_pdu_lists(cmd
, bl
->type
);
490 iscsit_dump_pdu_list(cmd
);
496 int iscsit_build_pdu_and_seq_lists(
497 struct iscsi_cmd
*cmd
,
498 u32 immediate_data_length
)
500 struct iscsi_build_list bl
;
501 u32 pdu_count
= 0, seq_count
= 1;
502 struct iscsi_conn
*conn
= cmd
->conn
;
503 struct iscsi_pdu
*pdu
= NULL
;
504 struct iscsi_seq
*seq
= NULL
;
506 struct iscsi_session
*sess
= conn
->sess
;
507 struct iscsi_node_attrib
*na
;
510 * Do nothing if no OOO shenanigans
512 if (sess
->sess_ops
->DataSequenceInOrder
&&
513 sess
->sess_ops
->DataPDUInOrder
)
516 if (cmd
->data_direction
== DMA_NONE
)
519 na
= iscsit_tpg_get_node_attrib(sess
);
520 memset(&bl
, 0, sizeof(struct iscsi_build_list
));
522 if (cmd
->data_direction
== DMA_FROM_DEVICE
) {
523 bl
.data_direction
= ISCSI_PDU_READ
;
524 bl
.type
= PDULIST_NORMAL
;
525 if (na
->random_datain_pdu_offsets
)
526 bl
.randomize
|= RANDOM_DATAIN_PDU_OFFSETS
;
527 if (na
->random_datain_seq_offsets
)
528 bl
.randomize
|= RANDOM_DATAIN_SEQ_OFFSETS
;
530 bl
.data_direction
= ISCSI_PDU_WRITE
;
531 bl
.immediate_data_length
= immediate_data_length
;
532 if (na
->random_r2t_offsets
)
533 bl
.randomize
|= RANDOM_R2T_OFFSETS
;
535 if (!cmd
->immediate_data
&& !cmd
->unsolicited_data
)
536 bl
.type
= PDULIST_NORMAL
;
537 else if (cmd
->immediate_data
&& !cmd
->unsolicited_data
)
538 bl
.type
= PDULIST_IMMEDIATE
;
539 else if (!cmd
->immediate_data
&& cmd
->unsolicited_data
)
540 bl
.type
= PDULIST_UNSOLICITED
;
541 else if (cmd
->immediate_data
&& cmd
->unsolicited_data
)
542 bl
.type
= PDULIST_IMMEDIATE_AND_UNSOLICITED
;
545 iscsit_determine_counts_for_list(cmd
, &bl
, &seq_count
, &pdu_count
);
547 if (!conn
->sess
->sess_ops
->DataSequenceInOrder
) {
548 seq
= kcalloc(seq_count
, sizeof(struct iscsi_seq
), GFP_ATOMIC
);
550 pr_err("Unable to allocate struct iscsi_seq list\n");
554 cmd
->seq_count
= seq_count
;
557 if (!conn
->sess
->sess_ops
->DataPDUInOrder
) {
558 pdu
= kcalloc(pdu_count
, sizeof(struct iscsi_pdu
), GFP_ATOMIC
);
560 pr_err("Unable to allocate struct iscsi_pdu list.\n");
565 cmd
->pdu_count
= pdu_count
;
568 return iscsit_do_build_pdu_and_seq_lists(cmd
, &bl
);
571 struct iscsi_pdu
*iscsit_get_pdu_holder(
572 struct iscsi_cmd
*cmd
,
577 struct iscsi_pdu
*pdu
= NULL
;
579 if (!cmd
->pdu_list
) {
580 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
584 pdu
= &cmd
->pdu_list
[0];
586 for (i
= 0; i
< cmd
->pdu_count
; i
++)
587 if ((pdu
[i
].offset
== offset
) && (pdu
[i
].length
== length
))
590 pr_err("Unable to locate PDU holder for ITT: 0x%08x, Offset:"
591 " %u, Length: %u\n", cmd
->init_task_tag
, offset
, length
);
595 struct iscsi_pdu
*iscsit_get_pdu_holder_for_seq(
596 struct iscsi_cmd
*cmd
,
597 struct iscsi_seq
*seq
)
600 struct iscsi_conn
*conn
= cmd
->conn
;
601 struct iscsi_pdu
*pdu
= NULL
;
603 if (!cmd
->pdu_list
) {
604 pr_err("struct iscsi_cmd->pdu_list is NULL!\n");
608 if (conn
->sess
->sess_ops
->DataSequenceInOrder
) {
610 pdu
= &cmd
->pdu_list
[cmd
->pdu_start
];
612 for (i
= 0; pdu
[i
].seq_no
!= cmd
->seq_no
; i
++) {
613 pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
614 "_send_order: %d, pdu[i].offset: %d,"
615 " pdu[i].length: %d\n", pdu
[i
].seq_no
,
616 pdu
[i
].pdu_send_order
, pdu
[i
].offset
,
619 if (pdu
[i
].pdu_send_order
== cmd
->pdu_send_order
) {
620 cmd
->pdu_send_order
++;
625 cmd
->pdu_start
+= cmd
->pdu_send_order
;
626 cmd
->pdu_send_order
= 0;
629 if (cmd
->pdu_start
< cmd
->pdu_count
)
632 pr_err("Command ITT: 0x%08x unable to locate"
633 " struct iscsi_pdu for cmd->pdu_send_order: %u.\n",
634 cmd
->init_task_tag
, cmd
->pdu_send_order
);
638 pr_err("struct iscsi_seq is NULL!\n");
642 pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
643 " seq->seq_no: %d\n", seq
->pdu_start
, seq
->pdu_count
,
646 pdu
= &cmd
->pdu_list
[seq
->pdu_start
];
648 if (seq
->pdu_send_order
== seq
->pdu_count
) {
649 pr_err("Command ITT: 0x%08x seq->pdu_send"
650 "_order: %u equals seq->pdu_count: %u\n",
651 cmd
->init_task_tag
, seq
->pdu_send_order
,
656 for (i
= 0; i
< seq
->pdu_count
; i
++) {
657 if (pdu
[i
].pdu_send_order
== seq
->pdu_send_order
) {
658 seq
->pdu_send_order
++;
663 pr_err("Command ITT: 0x%08x unable to locate iscsi"
664 "_pdu_t for seq->pdu_send_order: %u.\n",
665 cmd
->init_task_tag
, seq
->pdu_send_order
);
672 struct iscsi_seq
*iscsit_get_seq_holder(
673 struct iscsi_cmd
*cmd
,
679 if (!cmd
->seq_list
) {
680 pr_err("struct iscsi_cmd->seq_list is NULL!\n");
684 for (i
= 0; i
< cmd
->seq_count
; i
++) {
685 pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
686 "xfer_len: %d, seq_list[i].seq_no %u\n",
687 cmd
->seq_list
[i
].orig_offset
, cmd
->seq_list
[i
].xfer_len
,
688 cmd
->seq_list
[i
].seq_no
);
690 if ((cmd
->seq_list
[i
].orig_offset
+
691 cmd
->seq_list
[i
].xfer_len
) >=
693 return &cmd
->seq_list
[i
];
696 pr_err("Unable to locate Sequence holder for ITT: 0x%08x,"
697 " Offset: %u, Length: %u\n", cmd
->init_task_tag
, offset
,