1 /*******************************************************************************
2 * This file contains the iSCSI Target DataIN value generation functions.
4 * (c) Copyright 2007-2013 Datera, Inc.
6 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 ******************************************************************************/
19 #include <linux/slab.h>
20 #include <scsi/iscsi_proto.h>
21 #include <target/iscsi/iscsi_target_core.h>
22 #include "iscsi_target_seq_pdu_list.h"
23 #include "iscsi_target_erl1.h"
24 #include "iscsi_target_util.h"
25 #include "iscsi_target.h"
26 #include "iscsi_target_datain_values.h"
28 struct iscsi_datain_req
*iscsit_allocate_datain_req(void)
30 struct iscsi_datain_req
*dr
;
32 dr
= kmem_cache_zalloc(lio_dr_cache
, GFP_ATOMIC
);
34 pr_err("Unable to allocate memory for"
35 " struct iscsi_datain_req\n");
38 INIT_LIST_HEAD(&dr
->cmd_datain_node
);
43 void iscsit_attach_datain_req(struct iscsi_cmd
*cmd
, struct iscsi_datain_req
*dr
)
45 spin_lock(&cmd
->datain_lock
);
46 list_add_tail(&dr
->cmd_datain_node
, &cmd
->datain_list
);
47 spin_unlock(&cmd
->datain_lock
);
50 void iscsit_free_datain_req(struct iscsi_cmd
*cmd
, struct iscsi_datain_req
*dr
)
52 spin_lock(&cmd
->datain_lock
);
53 list_del(&dr
->cmd_datain_node
);
54 spin_unlock(&cmd
->datain_lock
);
56 kmem_cache_free(lio_dr_cache
, dr
);
59 void iscsit_free_all_datain_reqs(struct iscsi_cmd
*cmd
)
61 struct iscsi_datain_req
*dr
, *dr_tmp
;
63 spin_lock(&cmd
->datain_lock
);
64 list_for_each_entry_safe(dr
, dr_tmp
, &cmd
->datain_list
, cmd_datain_node
) {
65 list_del(&dr
->cmd_datain_node
);
66 kmem_cache_free(lio_dr_cache
, dr
);
68 spin_unlock(&cmd
->datain_lock
);
71 struct iscsi_datain_req
*iscsit_get_datain_req(struct iscsi_cmd
*cmd
)
73 if (list_empty(&cmd
->datain_list
)) {
74 pr_err("cmd->datain_list is empty for ITT:"
75 " 0x%08x\n", cmd
->init_task_tag
);
79 return list_first_entry(&cmd
->datain_list
, struct iscsi_datain_req
,
84 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=Yes.
86 static struct iscsi_datain_req
*iscsit_set_datain_values_yes_and_yes(
87 struct iscsi_cmd
*cmd
,
88 struct iscsi_datain
*datain
)
90 u32 next_burst_len
, read_data_done
, read_data_left
;
91 struct iscsi_conn
*conn
= cmd
->conn
;
92 struct iscsi_datain_req
*dr
;
94 dr
= iscsit_get_datain_req(cmd
);
98 if (dr
->recovery
&& dr
->generate_recovery_values
) {
99 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
103 dr
->generate_recovery_values
= 0;
106 next_burst_len
= (!dr
->recovery
) ?
107 cmd
->next_burst_len
: dr
->next_burst_len
;
108 read_data_done
= (!dr
->recovery
) ?
109 cmd
->read_data_done
: dr
->read_data_done
;
111 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
112 if (!read_data_left
) {
113 pr_err("ITT: 0x%08x read_data_left is zero!\n",
118 if ((read_data_left
<= conn
->conn_ops
->MaxRecvDataSegmentLength
) &&
119 (read_data_left
<= (conn
->sess
->sess_ops
->MaxBurstLength
-
121 datain
->length
= read_data_left
;
123 datain
->flags
|= (ISCSI_FLAG_CMD_FINAL
| ISCSI_FLAG_DATA_STATUS
);
124 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
125 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
127 if ((next_burst_len
+
128 conn
->conn_ops
->MaxRecvDataSegmentLength
) <
129 conn
->sess
->sess_ops
->MaxBurstLength
) {
131 conn
->conn_ops
->MaxRecvDataSegmentLength
;
132 next_burst_len
+= datain
->length
;
134 datain
->length
= (conn
->sess
->sess_ops
->MaxBurstLength
-
138 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
139 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
140 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
144 datain
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
145 datain
->offset
= read_data_done
;
148 cmd
->next_burst_len
= next_burst_len
;
149 cmd
->read_data_done
+= datain
->length
;
151 dr
->next_burst_len
= next_burst_len
;
152 dr
->read_data_done
+= datain
->length
;
156 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
157 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
162 if (!dr
->runlength
) {
163 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
165 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
166 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
167 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
170 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
172 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
173 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
174 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
182 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=Yes.
184 static struct iscsi_datain_req
*iscsit_set_datain_values_no_and_yes(
185 struct iscsi_cmd
*cmd
,
186 struct iscsi_datain
*datain
)
188 u32 offset
, read_data_done
, read_data_left
, seq_send_order
;
189 struct iscsi_conn
*conn
= cmd
->conn
;
190 struct iscsi_datain_req
*dr
;
191 struct iscsi_seq
*seq
;
193 dr
= iscsit_get_datain_req(cmd
);
197 if (dr
->recovery
&& dr
->generate_recovery_values
) {
198 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
202 dr
->generate_recovery_values
= 0;
205 read_data_done
= (!dr
->recovery
) ?
206 cmd
->read_data_done
: dr
->read_data_done
;
207 seq_send_order
= (!dr
->recovery
) ?
208 cmd
->seq_send_order
: dr
->seq_send_order
;
210 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
211 if (!read_data_left
) {
212 pr_err("ITT: 0x%08x read_data_left is zero!\n",
217 seq
= iscsit_get_seq_holder_for_datain(cmd
, seq_send_order
);
223 if (!dr
->recovery
&& !seq
->next_burst_len
)
224 seq
->first_datasn
= cmd
->data_sn
;
226 offset
= (seq
->offset
+ seq
->next_burst_len
);
228 if ((offset
+ conn
->conn_ops
->MaxRecvDataSegmentLength
) >=
229 cmd
->se_cmd
.data_length
) {
230 datain
->length
= (cmd
->se_cmd
.data_length
- offset
);
231 datain
->offset
= offset
;
233 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
234 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
235 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
237 seq
->next_burst_len
= 0;
240 if ((seq
->next_burst_len
+
241 conn
->conn_ops
->MaxRecvDataSegmentLength
) <
242 conn
->sess
->sess_ops
->MaxBurstLength
) {
244 conn
->conn_ops
->MaxRecvDataSegmentLength
;
245 datain
->offset
= (seq
->offset
+ seq
->next_burst_len
);
247 seq
->next_burst_len
+= datain
->length
;
249 datain
->length
= (conn
->sess
->sess_ops
->MaxBurstLength
-
250 seq
->next_burst_len
);
251 datain
->offset
= (seq
->offset
+ seq
->next_burst_len
);
253 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
254 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
255 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
257 seq
->next_burst_len
= 0;
262 if ((read_data_done
+ datain
->length
) == cmd
->se_cmd
.data_length
)
263 datain
->flags
|= ISCSI_FLAG_DATA_STATUS
;
265 datain
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
267 cmd
->seq_send_order
= seq_send_order
;
268 cmd
->read_data_done
+= datain
->length
;
270 dr
->seq_send_order
= seq_send_order
;
271 dr
->read_data_done
+= datain
->length
;
275 if (datain
->flags
& ISCSI_FLAG_CMD_FINAL
)
276 seq
->last_datasn
= datain
->data_sn
;
277 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
278 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
283 if (!dr
->runlength
) {
284 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
286 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
287 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
288 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
291 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
293 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
294 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
295 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
303 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=No.
305 static struct iscsi_datain_req
*iscsit_set_datain_values_yes_and_no(
306 struct iscsi_cmd
*cmd
,
307 struct iscsi_datain
*datain
)
309 u32 next_burst_len
, read_data_done
, read_data_left
;
310 struct iscsi_conn
*conn
= cmd
->conn
;
311 struct iscsi_datain_req
*dr
;
312 struct iscsi_pdu
*pdu
;
314 dr
= iscsit_get_datain_req(cmd
);
318 if (dr
->recovery
&& dr
->generate_recovery_values
) {
319 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
323 dr
->generate_recovery_values
= 0;
326 next_burst_len
= (!dr
->recovery
) ?
327 cmd
->next_burst_len
: dr
->next_burst_len
;
328 read_data_done
= (!dr
->recovery
) ?
329 cmd
->read_data_done
: dr
->read_data_done
;
331 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
332 if (!read_data_left
) {
333 pr_err("ITT: 0x%08x read_data_left is zero!\n",
338 pdu
= iscsit_get_pdu_holder_for_seq(cmd
, NULL
);
342 if ((read_data_done
+ pdu
->length
) == cmd
->se_cmd
.data_length
) {
343 pdu
->flags
|= (ISCSI_FLAG_CMD_FINAL
| ISCSI_FLAG_DATA_STATUS
);
344 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
345 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
349 if ((next_burst_len
+ conn
->conn_ops
->MaxRecvDataSegmentLength
) <
350 conn
->sess
->sess_ops
->MaxBurstLength
)
351 next_burst_len
+= pdu
->length
;
353 pdu
->flags
|= ISCSI_FLAG_CMD_FINAL
;
354 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
355 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
361 pdu
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
363 cmd
->next_burst_len
= next_burst_len
;
364 cmd
->read_data_done
+= pdu
->length
;
366 dr
->next_burst_len
= next_burst_len
;
367 dr
->read_data_done
+= pdu
->length
;
370 datain
->flags
= pdu
->flags
;
371 datain
->length
= pdu
->length
;
372 datain
->offset
= pdu
->offset
;
373 datain
->data_sn
= pdu
->data_sn
;
376 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
377 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
382 if (!dr
->runlength
) {
383 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
385 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
386 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
387 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
390 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
392 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
393 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
394 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
402 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=No.
404 static struct iscsi_datain_req
*iscsit_set_datain_values_no_and_no(
405 struct iscsi_cmd
*cmd
,
406 struct iscsi_datain
*datain
)
408 u32 read_data_done
, read_data_left
, seq_send_order
;
409 struct iscsi_conn
*conn
= cmd
->conn
;
410 struct iscsi_datain_req
*dr
;
411 struct iscsi_pdu
*pdu
;
412 struct iscsi_seq
*seq
= NULL
;
414 dr
= iscsit_get_datain_req(cmd
);
418 if (dr
->recovery
&& dr
->generate_recovery_values
) {
419 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
423 dr
->generate_recovery_values
= 0;
426 read_data_done
= (!dr
->recovery
) ?
427 cmd
->read_data_done
: dr
->read_data_done
;
428 seq_send_order
= (!dr
->recovery
) ?
429 cmd
->seq_send_order
: dr
->seq_send_order
;
431 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
432 if (!read_data_left
) {
433 pr_err("ITT: 0x%08x read_data_left is zero!\n",
438 seq
= iscsit_get_seq_holder_for_datain(cmd
, seq_send_order
);
444 if (!dr
->recovery
&& !seq
->next_burst_len
)
445 seq
->first_datasn
= cmd
->data_sn
;
447 pdu
= iscsit_get_pdu_holder_for_seq(cmd
, seq
);
451 if (seq
->pdu_send_order
== seq
->pdu_count
) {
452 pdu
->flags
|= ISCSI_FLAG_CMD_FINAL
;
453 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
454 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
456 seq
->next_burst_len
= 0;
459 seq
->next_burst_len
+= pdu
->length
;
461 if ((read_data_done
+ pdu
->length
) == cmd
->se_cmd
.data_length
)
462 pdu
->flags
|= ISCSI_FLAG_DATA_STATUS
;
464 pdu
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
466 cmd
->seq_send_order
= seq_send_order
;
467 cmd
->read_data_done
+= pdu
->length
;
469 dr
->seq_send_order
= seq_send_order
;
470 dr
->read_data_done
+= pdu
->length
;
473 datain
->flags
= pdu
->flags
;
474 datain
->length
= pdu
->length
;
475 datain
->offset
= pdu
->offset
;
476 datain
->data_sn
= pdu
->data_sn
;
479 if (datain
->flags
& ISCSI_FLAG_CMD_FINAL
)
480 seq
->last_datasn
= datain
->data_sn
;
481 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
482 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
487 if (!dr
->runlength
) {
488 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
490 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
491 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
492 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
495 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
497 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
498 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
499 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
506 struct iscsi_datain_req
*iscsit_get_datain_values(
507 struct iscsi_cmd
*cmd
,
508 struct iscsi_datain
*datain
)
510 struct iscsi_conn
*conn
= cmd
->conn
;
512 if (conn
->sess
->sess_ops
->DataSequenceInOrder
&&
513 conn
->sess
->sess_ops
->DataPDUInOrder
)
514 return iscsit_set_datain_values_yes_and_yes(cmd
, datain
);
515 else if (!conn
->sess
->sess_ops
->DataSequenceInOrder
&&
516 conn
->sess
->sess_ops
->DataPDUInOrder
)
517 return iscsit_set_datain_values_no_and_yes(cmd
, datain
);
518 else if (conn
->sess
->sess_ops
->DataSequenceInOrder
&&
519 !conn
->sess
->sess_ops
->DataPDUInOrder
)
520 return iscsit_set_datain_values_yes_and_no(cmd
, datain
);
521 else if (!conn
->sess
->sess_ops
->DataSequenceInOrder
&&
522 !conn
->sess
->sess_ops
->DataPDUInOrder
)
523 return iscsit_set_datain_values_no_and_no(cmd
, datain
);
527 EXPORT_SYMBOL(iscsit_get_datain_values
);