1 /*******************************************************************************
2 * This file contains the iSCSI Target DataIN value generation functions.
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 ******************************************************************************/
21 #include <scsi/iscsi_proto.h>
23 #include "iscsi_target_core.h"
24 #include "iscsi_target_seq_pdu_list.h"
25 #include "iscsi_target_erl1.h"
26 #include "iscsi_target_util.h"
27 #include "iscsi_target.h"
28 #include "iscsi_target_datain_values.h"
30 struct iscsi_datain_req
*iscsit_allocate_datain_req(void)
32 struct iscsi_datain_req
*dr
;
34 dr
= kmem_cache_zalloc(lio_dr_cache
, GFP_ATOMIC
);
36 pr_err("Unable to allocate memory for"
37 " struct iscsi_datain_req\n");
40 INIT_LIST_HEAD(&dr
->cmd_datain_node
);
45 void iscsit_attach_datain_req(struct iscsi_cmd
*cmd
, struct iscsi_datain_req
*dr
)
47 spin_lock(&cmd
->datain_lock
);
48 list_add_tail(&dr
->cmd_datain_node
, &cmd
->datain_list
);
49 spin_unlock(&cmd
->datain_lock
);
52 void iscsit_free_datain_req(struct iscsi_cmd
*cmd
, struct iscsi_datain_req
*dr
)
54 spin_lock(&cmd
->datain_lock
);
55 list_del(&dr
->cmd_datain_node
);
56 spin_unlock(&cmd
->datain_lock
);
58 kmem_cache_free(lio_dr_cache
, dr
);
61 void iscsit_free_all_datain_reqs(struct iscsi_cmd
*cmd
)
63 struct iscsi_datain_req
*dr
, *dr_tmp
;
65 spin_lock(&cmd
->datain_lock
);
66 list_for_each_entry_safe(dr
, dr_tmp
, &cmd
->datain_list
, cmd_datain_node
) {
67 list_del(&dr
->cmd_datain_node
);
68 kmem_cache_free(lio_dr_cache
, dr
);
70 spin_unlock(&cmd
->datain_lock
);
73 struct iscsi_datain_req
*iscsit_get_datain_req(struct iscsi_cmd
*cmd
)
75 if (list_empty(&cmd
->datain_list
)) {
76 pr_err("cmd->datain_list is empty for ITT:"
77 " 0x%08x\n", cmd
->init_task_tag
);
81 return list_first_entry(&cmd
->datain_list
, struct iscsi_datain_req
,
86 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=Yes.
88 static struct iscsi_datain_req
*iscsit_set_datain_values_yes_and_yes(
89 struct iscsi_cmd
*cmd
,
90 struct iscsi_datain
*datain
)
92 u32 next_burst_len
, read_data_done
, read_data_left
;
93 struct iscsi_conn
*conn
= cmd
->conn
;
94 struct iscsi_datain_req
*dr
;
96 dr
= iscsit_get_datain_req(cmd
);
100 if (dr
->recovery
&& dr
->generate_recovery_values
) {
101 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
105 dr
->generate_recovery_values
= 0;
108 next_burst_len
= (!dr
->recovery
) ?
109 cmd
->next_burst_len
: dr
->next_burst_len
;
110 read_data_done
= (!dr
->recovery
) ?
111 cmd
->read_data_done
: dr
->read_data_done
;
113 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
114 if (!read_data_left
) {
115 pr_err("ITT: 0x%08x read_data_left is zero!\n",
120 if ((read_data_left
<= conn
->conn_ops
->MaxRecvDataSegmentLength
) &&
121 (read_data_left
<= (conn
->sess
->sess_ops
->MaxBurstLength
-
123 datain
->length
= read_data_left
;
125 datain
->flags
|= (ISCSI_FLAG_CMD_FINAL
| ISCSI_FLAG_DATA_STATUS
);
126 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
127 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
129 if ((next_burst_len
+
130 conn
->conn_ops
->MaxRecvDataSegmentLength
) <
131 conn
->sess
->sess_ops
->MaxBurstLength
) {
133 conn
->conn_ops
->MaxRecvDataSegmentLength
;
134 next_burst_len
+= datain
->length
;
136 datain
->length
= (conn
->sess
->sess_ops
->MaxBurstLength
-
140 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
141 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
142 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
146 datain
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
147 datain
->offset
= read_data_done
;
150 cmd
->next_burst_len
= next_burst_len
;
151 cmd
->read_data_done
+= datain
->length
;
153 dr
->next_burst_len
= next_burst_len
;
154 dr
->read_data_done
+= datain
->length
;
158 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
159 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
164 if (!dr
->runlength
) {
165 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
167 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
168 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
169 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
172 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
174 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
175 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
176 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
184 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=Yes.
186 static struct iscsi_datain_req
*iscsit_set_datain_values_no_and_yes(
187 struct iscsi_cmd
*cmd
,
188 struct iscsi_datain
*datain
)
190 u32 offset
, read_data_done
, read_data_left
, seq_send_order
;
191 struct iscsi_conn
*conn
= cmd
->conn
;
192 struct iscsi_datain_req
*dr
;
193 struct iscsi_seq
*seq
;
195 dr
= iscsit_get_datain_req(cmd
);
199 if (dr
->recovery
&& dr
->generate_recovery_values
) {
200 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
204 dr
->generate_recovery_values
= 0;
207 read_data_done
= (!dr
->recovery
) ?
208 cmd
->read_data_done
: dr
->read_data_done
;
209 seq_send_order
= (!dr
->recovery
) ?
210 cmd
->seq_send_order
: dr
->seq_send_order
;
212 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
213 if (!read_data_left
) {
214 pr_err("ITT: 0x%08x read_data_left is zero!\n",
219 seq
= iscsit_get_seq_holder_for_datain(cmd
, seq_send_order
);
225 if (!dr
->recovery
&& !seq
->next_burst_len
)
226 seq
->first_datasn
= cmd
->data_sn
;
228 offset
= (seq
->offset
+ seq
->next_burst_len
);
230 if ((offset
+ conn
->conn_ops
->MaxRecvDataSegmentLength
) >=
231 cmd
->se_cmd
.data_length
) {
232 datain
->length
= (cmd
->se_cmd
.data_length
- offset
);
233 datain
->offset
= offset
;
235 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
236 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
237 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
239 seq
->next_burst_len
= 0;
242 if ((seq
->next_burst_len
+
243 conn
->conn_ops
->MaxRecvDataSegmentLength
) <
244 conn
->sess
->sess_ops
->MaxBurstLength
) {
246 conn
->conn_ops
->MaxRecvDataSegmentLength
;
247 datain
->offset
= (seq
->offset
+ seq
->next_burst_len
);
249 seq
->next_burst_len
+= datain
->length
;
251 datain
->length
= (conn
->sess
->sess_ops
->MaxBurstLength
-
252 seq
->next_burst_len
);
253 datain
->offset
= (seq
->offset
+ seq
->next_burst_len
);
255 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
256 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
257 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
259 seq
->next_burst_len
= 0;
264 if ((read_data_done
+ datain
->length
) == cmd
->se_cmd
.data_length
)
265 datain
->flags
|= ISCSI_FLAG_DATA_STATUS
;
267 datain
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
269 cmd
->seq_send_order
= seq_send_order
;
270 cmd
->read_data_done
+= datain
->length
;
272 dr
->seq_send_order
= seq_send_order
;
273 dr
->read_data_done
+= datain
->length
;
277 if (datain
->flags
& ISCSI_FLAG_CMD_FINAL
)
278 seq
->last_datasn
= datain
->data_sn
;
279 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
280 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
285 if (!dr
->runlength
) {
286 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
288 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
289 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
290 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
293 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
295 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
296 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
297 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
305 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=No.
307 static struct iscsi_datain_req
*iscsit_set_datain_values_yes_and_no(
308 struct iscsi_cmd
*cmd
,
309 struct iscsi_datain
*datain
)
311 u32 next_burst_len
, read_data_done
, read_data_left
;
312 struct iscsi_conn
*conn
= cmd
->conn
;
313 struct iscsi_datain_req
*dr
;
314 struct iscsi_pdu
*pdu
;
316 dr
= iscsit_get_datain_req(cmd
);
320 if (dr
->recovery
&& dr
->generate_recovery_values
) {
321 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
325 dr
->generate_recovery_values
= 0;
328 next_burst_len
= (!dr
->recovery
) ?
329 cmd
->next_burst_len
: dr
->next_burst_len
;
330 read_data_done
= (!dr
->recovery
) ?
331 cmd
->read_data_done
: dr
->read_data_done
;
333 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
334 if (!read_data_left
) {
335 pr_err("ITT: 0x%08x read_data_left is zero!\n",
340 pdu
= iscsit_get_pdu_holder_for_seq(cmd
, NULL
);
344 if ((read_data_done
+ pdu
->length
) == cmd
->se_cmd
.data_length
) {
345 pdu
->flags
|= (ISCSI_FLAG_CMD_FINAL
| ISCSI_FLAG_DATA_STATUS
);
346 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
347 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
351 if ((next_burst_len
+ conn
->conn_ops
->MaxRecvDataSegmentLength
) <
352 conn
->sess
->sess_ops
->MaxBurstLength
)
353 next_burst_len
+= pdu
->length
;
355 pdu
->flags
|= ISCSI_FLAG_CMD_FINAL
;
356 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
357 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
363 pdu
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
365 cmd
->next_burst_len
= next_burst_len
;
366 cmd
->read_data_done
+= pdu
->length
;
368 dr
->next_burst_len
= next_burst_len
;
369 dr
->read_data_done
+= pdu
->length
;
372 datain
->flags
= pdu
->flags
;
373 datain
->length
= pdu
->length
;
374 datain
->offset
= pdu
->offset
;
375 datain
->data_sn
= pdu
->data_sn
;
378 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
379 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
384 if (!dr
->runlength
) {
385 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
387 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
388 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
389 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
392 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
394 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
395 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
396 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
404 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=No.
406 static struct iscsi_datain_req
*iscsit_set_datain_values_no_and_no(
407 struct iscsi_cmd
*cmd
,
408 struct iscsi_datain
*datain
)
410 u32 read_data_done
, read_data_left
, seq_send_order
;
411 struct iscsi_conn
*conn
= cmd
->conn
;
412 struct iscsi_datain_req
*dr
;
413 struct iscsi_pdu
*pdu
;
414 struct iscsi_seq
*seq
= NULL
;
416 dr
= iscsit_get_datain_req(cmd
);
420 if (dr
->recovery
&& dr
->generate_recovery_values
) {
421 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
425 dr
->generate_recovery_values
= 0;
428 read_data_done
= (!dr
->recovery
) ?
429 cmd
->read_data_done
: dr
->read_data_done
;
430 seq_send_order
= (!dr
->recovery
) ?
431 cmd
->seq_send_order
: dr
->seq_send_order
;
433 read_data_left
= (cmd
->se_cmd
.data_length
- read_data_done
);
434 if (!read_data_left
) {
435 pr_err("ITT: 0x%08x read_data_left is zero!\n",
440 seq
= iscsit_get_seq_holder_for_datain(cmd
, seq_send_order
);
446 if (!dr
->recovery
&& !seq
->next_burst_len
)
447 seq
->first_datasn
= cmd
->data_sn
;
449 pdu
= iscsit_get_pdu_holder_for_seq(cmd
, seq
);
453 if (seq
->pdu_send_order
== seq
->pdu_count
) {
454 pdu
->flags
|= ISCSI_FLAG_CMD_FINAL
;
455 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
456 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
458 seq
->next_burst_len
= 0;
461 seq
->next_burst_len
+= pdu
->length
;
463 if ((read_data_done
+ pdu
->length
) == cmd
->se_cmd
.data_length
)
464 pdu
->flags
|= ISCSI_FLAG_DATA_STATUS
;
466 pdu
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
468 cmd
->seq_send_order
= seq_send_order
;
469 cmd
->read_data_done
+= pdu
->length
;
471 dr
->seq_send_order
= seq_send_order
;
472 dr
->read_data_done
+= pdu
->length
;
475 datain
->flags
= pdu
->flags
;
476 datain
->length
= pdu
->length
;
477 datain
->offset
= pdu
->offset
;
478 datain
->data_sn
= pdu
->data_sn
;
481 if (datain
->flags
& ISCSI_FLAG_CMD_FINAL
)
482 seq
->last_datasn
= datain
->data_sn
;
483 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
484 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
489 if (!dr
->runlength
) {
490 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
492 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
493 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
494 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
497 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
499 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
500 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
501 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
508 struct iscsi_datain_req
*iscsit_get_datain_values(
509 struct iscsi_cmd
*cmd
,
510 struct iscsi_datain
*datain
)
512 struct iscsi_conn
*conn
= cmd
->conn
;
514 if (conn
->sess
->sess_ops
->DataSequenceInOrder
&&
515 conn
->sess
->sess_ops
->DataPDUInOrder
)
516 return iscsit_set_datain_values_yes_and_yes(cmd
, datain
);
517 else if (!conn
->sess
->sess_ops
->DataSequenceInOrder
&&
518 conn
->sess
->sess_ops
->DataPDUInOrder
)
519 return iscsit_set_datain_values_no_and_yes(cmd
, datain
);
520 else if (conn
->sess
->sess_ops
->DataSequenceInOrder
&&
521 !conn
->sess
->sess_ops
->DataPDUInOrder
)
522 return iscsit_set_datain_values_yes_and_no(cmd
, datain
);
523 else if (!conn
->sess
->sess_ops
->DataSequenceInOrder
&&
524 !conn
->sess
->sess_ops
->DataPDUInOrder
)
525 return iscsit_set_datain_values_no_and_no(cmd
, datain
);