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
->dr_list
);
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
->dr_list
, &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
->dr_list
);
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
, dr_list
) {
67 list_del(&dr
->dr_list
);
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 struct iscsi_datain_req
*dr
;
77 if (list_empty(&cmd
->datain_list
)) {
78 pr_err("cmd->datain_list is empty for ITT:"
79 " 0x%08x\n", cmd
->init_task_tag
);
82 list_for_each_entry(dr
, &cmd
->datain_list
, dr_list
)
89 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=Yes.
91 static struct iscsi_datain_req
*iscsit_set_datain_values_yes_and_yes(
92 struct iscsi_cmd
*cmd
,
93 struct iscsi_datain
*datain
)
95 u32 next_burst_len
, read_data_done
, read_data_left
;
96 struct iscsi_conn
*conn
= cmd
->conn
;
97 struct iscsi_datain_req
*dr
;
99 dr
= iscsit_get_datain_req(cmd
);
103 if (dr
->recovery
&& dr
->generate_recovery_values
) {
104 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
108 dr
->generate_recovery_values
= 0;
111 next_burst_len
= (!dr
->recovery
) ?
112 cmd
->next_burst_len
: dr
->next_burst_len
;
113 read_data_done
= (!dr
->recovery
) ?
114 cmd
->read_data_done
: dr
->read_data_done
;
116 read_data_left
= (cmd
->data_length
- read_data_done
);
117 if (!read_data_left
) {
118 pr_err("ITT: 0x%08x read_data_left is zero!\n",
123 if ((read_data_left
<= conn
->conn_ops
->MaxRecvDataSegmentLength
) &&
124 (read_data_left
<= (conn
->sess
->sess_ops
->MaxBurstLength
-
126 datain
->length
= read_data_left
;
128 datain
->flags
|= (ISCSI_FLAG_CMD_FINAL
| ISCSI_FLAG_DATA_STATUS
);
129 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
130 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
132 if ((next_burst_len
+
133 conn
->conn_ops
->MaxRecvDataSegmentLength
) <
134 conn
->sess
->sess_ops
->MaxBurstLength
) {
136 conn
->conn_ops
->MaxRecvDataSegmentLength
;
137 next_burst_len
+= datain
->length
;
139 datain
->length
= (conn
->sess
->sess_ops
->MaxBurstLength
-
143 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
144 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
145 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
149 datain
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
150 datain
->offset
= read_data_done
;
153 cmd
->next_burst_len
= next_burst_len
;
154 cmd
->read_data_done
+= datain
->length
;
156 dr
->next_burst_len
= next_burst_len
;
157 dr
->read_data_done
+= datain
->length
;
161 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
162 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
167 if (!dr
->runlength
) {
168 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
170 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
171 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
172 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
175 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
177 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
178 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
179 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
187 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=Yes.
189 static struct iscsi_datain_req
*iscsit_set_datain_values_no_and_yes(
190 struct iscsi_cmd
*cmd
,
191 struct iscsi_datain
*datain
)
193 u32 offset
, read_data_done
, read_data_left
, seq_send_order
;
194 struct iscsi_conn
*conn
= cmd
->conn
;
195 struct iscsi_datain_req
*dr
;
196 struct iscsi_seq
*seq
;
198 dr
= iscsit_get_datain_req(cmd
);
202 if (dr
->recovery
&& dr
->generate_recovery_values
) {
203 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
207 dr
->generate_recovery_values
= 0;
210 read_data_done
= (!dr
->recovery
) ?
211 cmd
->read_data_done
: dr
->read_data_done
;
212 seq_send_order
= (!dr
->recovery
) ?
213 cmd
->seq_send_order
: dr
->seq_send_order
;
215 read_data_left
= (cmd
->data_length
- read_data_done
);
216 if (!read_data_left
) {
217 pr_err("ITT: 0x%08x read_data_left is zero!\n",
222 seq
= iscsit_get_seq_holder_for_datain(cmd
, seq_send_order
);
228 if (!dr
->recovery
&& !seq
->next_burst_len
)
229 seq
->first_datasn
= cmd
->data_sn
;
231 offset
= (seq
->offset
+ seq
->next_burst_len
);
233 if ((offset
+ conn
->conn_ops
->MaxRecvDataSegmentLength
) >=
235 datain
->length
= (cmd
->data_length
- offset
);
236 datain
->offset
= offset
;
238 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
239 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
240 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
242 seq
->next_burst_len
= 0;
245 if ((seq
->next_burst_len
+
246 conn
->conn_ops
->MaxRecvDataSegmentLength
) <
247 conn
->sess
->sess_ops
->MaxBurstLength
) {
249 conn
->conn_ops
->MaxRecvDataSegmentLength
;
250 datain
->offset
= (seq
->offset
+ seq
->next_burst_len
);
252 seq
->next_burst_len
+= datain
->length
;
254 datain
->length
= (conn
->sess
->sess_ops
->MaxBurstLength
-
255 seq
->next_burst_len
);
256 datain
->offset
= (seq
->offset
+ seq
->next_burst_len
);
258 datain
->flags
|= ISCSI_FLAG_CMD_FINAL
;
259 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
260 datain
->flags
|= ISCSI_FLAG_DATA_ACK
;
262 seq
->next_burst_len
= 0;
267 if ((read_data_done
+ datain
->length
) == cmd
->data_length
)
268 datain
->flags
|= ISCSI_FLAG_DATA_STATUS
;
270 datain
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
272 cmd
->seq_send_order
= seq_send_order
;
273 cmd
->read_data_done
+= datain
->length
;
275 dr
->seq_send_order
= seq_send_order
;
276 dr
->read_data_done
+= datain
->length
;
280 if (datain
->flags
& ISCSI_FLAG_CMD_FINAL
)
281 seq
->last_datasn
= datain
->data_sn
;
282 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
283 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
288 if (!dr
->runlength
) {
289 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
291 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
292 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
293 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
296 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
298 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
299 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
300 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
308 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=No.
310 static struct iscsi_datain_req
*iscsit_set_datain_values_yes_and_no(
311 struct iscsi_cmd
*cmd
,
312 struct iscsi_datain
*datain
)
314 u32 next_burst_len
, read_data_done
, read_data_left
;
315 struct iscsi_conn
*conn
= cmd
->conn
;
316 struct iscsi_datain_req
*dr
;
317 struct iscsi_pdu
*pdu
;
319 dr
= iscsit_get_datain_req(cmd
);
323 if (dr
->recovery
&& dr
->generate_recovery_values
) {
324 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
328 dr
->generate_recovery_values
= 0;
331 next_burst_len
= (!dr
->recovery
) ?
332 cmd
->next_burst_len
: dr
->next_burst_len
;
333 read_data_done
= (!dr
->recovery
) ?
334 cmd
->read_data_done
: dr
->read_data_done
;
336 read_data_left
= (cmd
->data_length
- read_data_done
);
337 if (!read_data_left
) {
338 pr_err("ITT: 0x%08x read_data_left is zero!\n",
343 pdu
= iscsit_get_pdu_holder_for_seq(cmd
, NULL
);
347 if ((read_data_done
+ pdu
->length
) == cmd
->data_length
) {
348 pdu
->flags
|= (ISCSI_FLAG_CMD_FINAL
| ISCSI_FLAG_DATA_STATUS
);
349 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
350 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
354 if ((next_burst_len
+ conn
->conn_ops
->MaxRecvDataSegmentLength
) <
355 conn
->sess
->sess_ops
->MaxBurstLength
)
356 next_burst_len
+= pdu
->length
;
358 pdu
->flags
|= ISCSI_FLAG_CMD_FINAL
;
359 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
360 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
366 pdu
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
368 cmd
->next_burst_len
= next_burst_len
;
369 cmd
->read_data_done
+= pdu
->length
;
371 dr
->next_burst_len
= next_burst_len
;
372 dr
->read_data_done
+= pdu
->length
;
375 datain
->flags
= pdu
->flags
;
376 datain
->length
= pdu
->length
;
377 datain
->offset
= pdu
->offset
;
378 datain
->data_sn
= pdu
->data_sn
;
381 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
382 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
387 if (!dr
->runlength
) {
388 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
390 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
391 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
392 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
395 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
397 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
398 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
399 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
407 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=No.
409 static struct iscsi_datain_req
*iscsit_set_datain_values_no_and_no(
410 struct iscsi_cmd
*cmd
,
411 struct iscsi_datain
*datain
)
413 u32 read_data_done
, read_data_left
, seq_send_order
;
414 struct iscsi_conn
*conn
= cmd
->conn
;
415 struct iscsi_datain_req
*dr
;
416 struct iscsi_pdu
*pdu
;
417 struct iscsi_seq
*seq
= NULL
;
419 dr
= iscsit_get_datain_req(cmd
);
423 if (dr
->recovery
&& dr
->generate_recovery_values
) {
424 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
428 dr
->generate_recovery_values
= 0;
431 read_data_done
= (!dr
->recovery
) ?
432 cmd
->read_data_done
: dr
->read_data_done
;
433 seq_send_order
= (!dr
->recovery
) ?
434 cmd
->seq_send_order
: dr
->seq_send_order
;
436 read_data_left
= (cmd
->data_length
- read_data_done
);
437 if (!read_data_left
) {
438 pr_err("ITT: 0x%08x read_data_left is zero!\n",
443 seq
= iscsit_get_seq_holder_for_datain(cmd
, seq_send_order
);
449 if (!dr
->recovery
&& !seq
->next_burst_len
)
450 seq
->first_datasn
= cmd
->data_sn
;
452 pdu
= iscsit_get_pdu_holder_for_seq(cmd
, seq
);
456 if (seq
->pdu_send_order
== seq
->pdu_count
) {
457 pdu
->flags
|= ISCSI_FLAG_CMD_FINAL
;
458 if (conn
->sess
->sess_ops
->ErrorRecoveryLevel
> 0)
459 pdu
->flags
|= ISCSI_FLAG_DATA_ACK
;
461 seq
->next_burst_len
= 0;
464 seq
->next_burst_len
+= pdu
->length
;
466 if ((read_data_done
+ pdu
->length
) == cmd
->data_length
)
467 pdu
->flags
|= ISCSI_FLAG_DATA_STATUS
;
469 pdu
->data_sn
= (!dr
->recovery
) ? cmd
->data_sn
++ : dr
->data_sn
++;
471 cmd
->seq_send_order
= seq_send_order
;
472 cmd
->read_data_done
+= pdu
->length
;
474 dr
->seq_send_order
= seq_send_order
;
475 dr
->read_data_done
+= pdu
->length
;
478 datain
->flags
= pdu
->flags
;
479 datain
->length
= pdu
->length
;
480 datain
->offset
= pdu
->offset
;
481 datain
->data_sn
= pdu
->data_sn
;
484 if (datain
->flags
& ISCSI_FLAG_CMD_FINAL
)
485 seq
->last_datasn
= datain
->data_sn
;
486 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
)
487 dr
->dr_complete
= DATAIN_COMPLETE_NORMAL
;
492 if (!dr
->runlength
) {
493 if (datain
->flags
& ISCSI_FLAG_DATA_STATUS
) {
495 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
496 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
497 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
500 if ((dr
->begrun
+ dr
->runlength
) == dr
->data_sn
) {
502 (dr
->recovery
== DATAIN_WITHIN_COMMAND_RECOVERY
) ?
503 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY
:
504 DATAIN_COMPLETE_CONNECTION_RECOVERY
;
511 struct iscsi_datain_req
*iscsit_get_datain_values(
512 struct iscsi_cmd
*cmd
,
513 struct iscsi_datain
*datain
)
515 struct iscsi_conn
*conn
= cmd
->conn
;
517 if (conn
->sess
->sess_ops
->DataSequenceInOrder
&&
518 conn
->sess
->sess_ops
->DataPDUInOrder
)
519 return iscsit_set_datain_values_yes_and_yes(cmd
, datain
);
520 else if (!conn
->sess
->sess_ops
->DataSequenceInOrder
&&
521 conn
->sess
->sess_ops
->DataPDUInOrder
)
522 return iscsit_set_datain_values_no_and_yes(cmd
, datain
);
523 else if (conn
->sess
->sess_ops
->DataSequenceInOrder
&&
524 !conn
->sess
->sess_ops
->DataPDUInOrder
)
525 return iscsit_set_datain_values_yes_and_no(cmd
, datain
);
526 else if (!conn
->sess
->sess_ops
->DataSequenceInOrder
&&
527 !conn
->sess
->sess_ops
->DataPDUInOrder
)
528 return iscsit_set_datain_values_no_and_no(cmd
, datain
);