1// SPDX-License-Identifier: GPL-2.0-or-later
2/******************************************************************************
3 * This file contains error recovery level zero functions used by
4 * the iSCSI Target driver.
5 *
6 * (c) Copyright 2007-2013 Datera, Inc.
7 *
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9 *
10 ******************************************************************************/
11
12#include <linux/sched/signal.h>
13
14#include <scsi/iscsi_proto.h>
15#include <target/target_core_base.h>
16#include <target/target_core_fabric.h>
17
18#include <target/iscsi/iscsi_target_core.h>
19#include "iscsi_target_seq_pdu_list.h"
20#include "iscsi_target_erl0.h"
21#include "iscsi_target_erl1.h"
22#include "iscsi_target_erl2.h"
23#include "iscsi_target_util.h"
24#include "iscsi_target.h"
25
26/*
27 * Used to set values in struct iscsit_cmd that iscsit_dataout_check_sequence()
28 * checks against to determine a PDU's Offset+Length is within the current
29 * DataOUT Sequence. Used for DataSequenceInOrder=Yes only.
30 */
31void iscsit_set_dataout_sequence_values(
32 struct iscsit_cmd *cmd)
33{
34 struct iscsit_conn *conn = cmd->conn;
35 /*
36 * Still set seq_start_offset and seq_end_offset for Unsolicited
37 * DataOUT, even if DataSequenceInOrder=No.
38 */
39 if (cmd->unsolicited_data) {
40 cmd->seq_start_offset = cmd->write_data_done;
41 cmd->seq_end_offset = min(cmd->se_cmd.data_length,
42 conn->sess->sess_ops->FirstBurstLength);
43 return;
44 }
45
46 if (!conn->sess->sess_ops->DataSequenceInOrder)
47 return;
48
49 if (!cmd->seq_start_offset && !cmd->seq_end_offset) {
50 cmd->seq_start_offset = cmd->write_data_done;
51 cmd->seq_end_offset = (cmd->se_cmd.data_length >
52 conn->sess->sess_ops->MaxBurstLength) ?
53 (cmd->write_data_done +
54 conn->sess->sess_ops->MaxBurstLength) : cmd->se_cmd.data_length;
55 } else {
56 cmd->seq_start_offset = cmd->seq_end_offset;
57 cmd->seq_end_offset = ((cmd->seq_end_offset +
58 conn->sess->sess_ops->MaxBurstLength) >=
59 cmd->se_cmd.data_length) ? cmd->se_cmd.data_length :
60 (cmd->seq_end_offset +
61 conn->sess->sess_ops->MaxBurstLength);
62 }
63}
64
65static int iscsit_dataout_within_command_recovery_check(
66 struct iscsit_cmd *cmd,
67 unsigned char *buf)
68{
69 struct iscsit_conn *conn = cmd->conn;
70 struct iscsi_data *hdr = (struct iscsi_data *) buf;
71 u32 payload_length = ntoh24(hdr->dlength);
72
73 /*
74 * We do the within-command recovery checks here as it is
75 * the first function called in iscsi_check_pre_dataout().
76 * Basically, if we are in within-command recovery and
77 * the PDU does not contain the offset the sequence needs,
78 * dump the payload.
79 *
80 * This only applies to DataPDUInOrder=Yes, for
81 * DataPDUInOrder=No we only re-request the failed PDU
82 * and check that all PDUs in a sequence are received
83 * upon end of sequence.
84 */
85 if (conn->sess->sess_ops->DataSequenceInOrder) {
86 if ((cmd->cmd_flags & ICF_WITHIN_COMMAND_RECOVERY) &&
87 cmd->write_data_done != be32_to_cpu(hdr->offset))
88 goto dump;
89
90 cmd->cmd_flags &= ~ICF_WITHIN_COMMAND_RECOVERY;
91 } else {
92 struct iscsi_seq *seq;
93
94 seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
95 payload_length);
96 if (!seq)
97 return DATAOUT_CANNOT_RECOVER;
98 /*
99 * Set the struct iscsi_seq pointer to reuse later.
100 */
101 cmd->seq_ptr = seq;
102
103 if (conn->sess->sess_ops->DataPDUInOrder) {
104 if (seq->status ==
105 DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
106 (seq->offset != be32_to_cpu(hdr->offset) ||
107 seq->data_sn != be32_to_cpu(hdr->datasn)))
108 goto dump;
109 } else {
110 if (seq->status ==
111 DATAOUT_SEQUENCE_WITHIN_COMMAND_RECOVERY &&
112 seq->data_sn != be32_to_cpu(hdr->datasn))
113 goto dump;
114 }
115
116 if (seq->status == DATAOUT_SEQUENCE_COMPLETE)
117 goto dump;
118
119 if (seq->status != DATAOUT_SEQUENCE_COMPLETE)
120 seq->status = 0;
121 }
122
123 return DATAOUT_NORMAL;
124
125dump:
126 pr_err("Dumping DataOUT PDU Offset: %u Length: %d DataSN:"
127 " 0x%08x\n", hdr->offset, payload_length, hdr->datasn);
128 return iscsit_dump_data_payload(conn, payload_length, 1);
129}
130
131static int iscsit_dataout_check_unsolicited_sequence(
132 struct iscsit_cmd *cmd,
133 unsigned char *buf)
134{
135 u32 first_burst_len;
136 struct iscsit_conn *conn = cmd->conn;
137 struct iscsi_data *hdr = (struct iscsi_data *) buf;
138 u32 payload_length = ntoh24(hdr->dlength);
139
140
141 if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
142 ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
143 pr_err("Command ITT: 0x%08x with Offset: %u,"
144 " Length: %u outside of Unsolicited Sequence %u:%u while"
145 " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
146 be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
147 cmd->seq_end_offset);
148 return DATAOUT_CANNOT_RECOVER;
149 }
150
151 first_burst_len = (cmd->first_burst_len + payload_length);
152
153 if (first_burst_len > conn->sess->sess_ops->FirstBurstLength) {
154 pr_err("Total %u bytes exceeds FirstBurstLength: %u"
155 " for this Unsolicited DataOut Burst.\n",
156 first_burst_len, conn->sess->sess_ops->FirstBurstLength);
157 transport_send_check_condition_and_sense(&cmd->se_cmd,
158 TCM_INCORRECT_AMOUNT_OF_DATA, 0);
159 return DATAOUT_CANNOT_RECOVER;
160 }
161
162 /*
163 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
164 * checks for the current Unsolicited DataOUT Sequence.
165 */
166 if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
167 /*
168 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
169 * sequence checks are handled in
170 * iscsit_dataout_datapduinorder_no_fbit().
171 */
172 if (!conn->sess->sess_ops->DataPDUInOrder)
173 goto out;
174
175 if ((first_burst_len != cmd->se_cmd.data_length) &&
176 (first_burst_len != conn->sess->sess_ops->FirstBurstLength)) {
177 pr_err("Unsolicited non-immediate data"
178 " received %u does not equal FirstBurstLength: %u, and"
179 " does not equal ExpXferLen %u.\n", first_burst_len,
180 conn->sess->sess_ops->FirstBurstLength,
181 cmd->se_cmd.data_length);
182 transport_send_check_condition_and_sense(&cmd->se_cmd,
183 TCM_INCORRECT_AMOUNT_OF_DATA, 0);
184 return DATAOUT_CANNOT_RECOVER;
185 }
186 } else {
187 if (first_burst_len == conn->sess->sess_ops->FirstBurstLength) {
188 pr_err("Command ITT: 0x%08x reached"
189 " FirstBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
190 " error.\n", cmd->init_task_tag,
191 conn->sess->sess_ops->FirstBurstLength);
192 return DATAOUT_CANNOT_RECOVER;
193 }
194 if (first_burst_len == cmd->se_cmd.data_length) {
195 pr_err("Command ITT: 0x%08x reached"
196 " ExpXferLen: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
197 " error.\n", cmd->init_task_tag, cmd->se_cmd.data_length);
198 return DATAOUT_CANNOT_RECOVER;
199 }
200 }
201
202out:
203 return DATAOUT_NORMAL;
204}
205
206static int iscsit_dataout_check_sequence(
207 struct iscsit_cmd *cmd,
208 unsigned char *buf)
209{
210 u32 next_burst_len;
211 struct iscsit_conn *conn = cmd->conn;
212 struct iscsi_seq *seq = NULL;
213 struct iscsi_data *hdr = (struct iscsi_data *) buf;
214 u32 payload_length = ntoh24(hdr->dlength);
215
216 /*
217 * For DataSequenceInOrder=Yes: Check that the offset and offset+length
218 * is within range as defined by iscsi_set_dataout_sequence_values().
219 *
220 * For DataSequenceInOrder=No: Check that an struct iscsi_seq exists for
221 * offset+length tuple.
222 */
223 if (conn->sess->sess_ops->DataSequenceInOrder) {
224 /*
225 * Due to possibility of recovery DataOUT sent by the initiator
226 * fullfilling an Recovery R2T, it's best to just dump the
227 * payload here, instead of erroring out.
228 */
229 if ((be32_to_cpu(hdr->offset) < cmd->seq_start_offset) ||
230 ((be32_to_cpu(hdr->offset) + payload_length) > cmd->seq_end_offset)) {
231 pr_err("Command ITT: 0x%08x with Offset: %u,"
232 " Length: %u outside of Sequence %u:%u while"
233 " DataSequenceInOrder=Yes.\n", cmd->init_task_tag,
234 be32_to_cpu(hdr->offset), payload_length, cmd->seq_start_offset,
235 cmd->seq_end_offset);
236
237 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
238 return DATAOUT_CANNOT_RECOVER;
239 return DATAOUT_WITHIN_COMMAND_RECOVERY;
240 }
241
242 next_burst_len = (cmd->next_burst_len + payload_length);
243 } else {
244 seq = iscsit_get_seq_holder(cmd, be32_to_cpu(hdr->offset),
245 payload_length);
246 if (!seq)
247 return DATAOUT_CANNOT_RECOVER;
248 /*
249 * Set the struct iscsi_seq pointer to reuse later.
250 */
251 cmd->seq_ptr = seq;
252
253 if (seq->status == DATAOUT_SEQUENCE_COMPLETE) {
254 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
255 return DATAOUT_CANNOT_RECOVER;
256 return DATAOUT_WITHIN_COMMAND_RECOVERY;
257 }
258
259 next_burst_len = (seq->next_burst_len + payload_length);
260 }
261
262 if (next_burst_len > conn->sess->sess_ops->MaxBurstLength) {
263 pr_err("Command ITT: 0x%08x, NextBurstLength: %u and"
264 " Length: %u exceeds MaxBurstLength: %u. protocol"
265 " error.\n", cmd->init_task_tag,
266 (next_burst_len - payload_length),
267 payload_length, conn->sess->sess_ops->MaxBurstLength);
268 return DATAOUT_CANNOT_RECOVER;
269 }
270
271 /*
272 * Perform various MaxBurstLength and ISCSI_FLAG_CMD_FINAL sanity
273 * checks for the current DataOUT Sequence.
274 */
275 if (hdr->flags & ISCSI_FLAG_CMD_FINAL) {
276 /*
277 * Ignore ISCSI_FLAG_CMD_FINAL checks while DataPDUInOrder=No, end of
278 * sequence checks are handled in
279 * iscsit_dataout_datapduinorder_no_fbit().
280 */
281 if (!conn->sess->sess_ops->DataPDUInOrder)
282 goto out;
283
284 if (conn->sess->sess_ops->DataSequenceInOrder) {
285 if ((next_burst_len <
286 conn->sess->sess_ops->MaxBurstLength) &&
287 ((cmd->write_data_done + payload_length) <
288 cmd->se_cmd.data_length)) {
289 pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
290 " before end of DataOUT sequence, protocol"
291 " error.\n", cmd->init_task_tag);
292 return DATAOUT_CANNOT_RECOVER;
293 }
294 } else {
295 if (next_burst_len < seq->xfer_len) {
296 pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
297 " before end of DataOUT sequence, protocol"
298 " error.\n", cmd->init_task_tag);
299 return DATAOUT_CANNOT_RECOVER;
300 }
301 }
302 } else {
303 if (conn->sess->sess_ops->DataSequenceInOrder) {
304 if (next_burst_len ==
305 conn->sess->sess_ops->MaxBurstLength) {
306 pr_err("Command ITT: 0x%08x reached"
307 " MaxBurstLength: %u, but ISCSI_FLAG_CMD_FINAL is"
308 " not set, protocol error.", cmd->init_task_tag,
309 conn->sess->sess_ops->MaxBurstLength);
310 return DATAOUT_CANNOT_RECOVER;
311 }
312 if ((cmd->write_data_done + payload_length) ==
313 cmd->se_cmd.data_length) {
314 pr_err("Command ITT: 0x%08x reached"
315 " last DataOUT PDU in sequence but ISCSI_FLAG_"
316 "CMD_FINAL is not set, protocol error.\n",
317 cmd->init_task_tag);
318 return DATAOUT_CANNOT_RECOVER;
319 }
320 } else {
321 if (next_burst_len == seq->xfer_len) {
322 pr_err("Command ITT: 0x%08x reached"
323 " last DataOUT PDU in sequence but ISCSI_FLAG_"
324 "CMD_FINAL is not set, protocol error.\n",
325 cmd->init_task_tag);
326 return DATAOUT_CANNOT_RECOVER;
327 }
328 }
329 }
330
331out:
332 return DATAOUT_NORMAL;
333}
334
335static int iscsit_dataout_check_datasn(
336 struct iscsit_cmd *cmd,
337 unsigned char *buf)
338{
339 u32 data_sn = 0;
340 struct iscsit_conn *conn = cmd->conn;
341 struct iscsi_data *hdr = (struct iscsi_data *) buf;
342 u32 payload_length = ntoh24(hdr->dlength);
343
344 /*
345 * Considering the target has no method of re-requesting DataOUT
346 * by DataSN, if we receieve a greater DataSN than expected we
347 * assume the functions for DataPDUInOrder=[Yes,No] below will
348 * handle it.
349 *
350 * If the DataSN is less than expected, dump the payload.
351 */
352 if (conn->sess->sess_ops->DataSequenceInOrder)
353 data_sn = cmd->data_sn;
354 else {
355 struct iscsi_seq *seq = cmd->seq_ptr;
356 data_sn = seq->data_sn;
357 }
358
359 if (be32_to_cpu(hdr->datasn) > data_sn) {
360 pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
361 " higher than expected 0x%08x.\n", cmd->init_task_tag,
362 be32_to_cpu(hdr->datasn), data_sn);
363 goto recover;
364 } else if (be32_to_cpu(hdr->datasn) < data_sn) {
365 pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
366 " lower than expected 0x%08x, discarding payload.\n",
367 cmd->init_task_tag, be32_to_cpu(hdr->datasn), data_sn);
368 goto dump;
369 }
370
371 return DATAOUT_NORMAL;
372
373recover:
374 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
375 pr_err("Unable to perform within-command recovery"
376 " while ERL=0.\n");
377 return DATAOUT_CANNOT_RECOVER;
378 }
379dump:
380 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
381 return DATAOUT_CANNOT_RECOVER;
382
383 return DATAOUT_WITHIN_COMMAND_RECOVERY;
384}
385
386static int iscsit_dataout_pre_datapduinorder_yes(
387 struct iscsit_cmd *cmd,
388 unsigned char *buf)
389{
390 int dump = 0, recovery = 0;
391 struct iscsit_conn *conn = cmd->conn;
392 struct iscsi_data *hdr = (struct iscsi_data *) buf;
393 u32 payload_length = ntoh24(hdr->dlength);
394
395 /*
396 * For DataSequenceInOrder=Yes: If the offset is greater than the global
397 * DataPDUInOrder=Yes offset counter in struct iscsit_cmd a protcol error has
398 * occurred and fail the connection.
399 *
400 * For DataSequenceInOrder=No: If the offset is greater than the per
401 * sequence DataPDUInOrder=Yes offset counter in struct iscsi_seq a protocol
402 * error has occurred and fail the connection.
403 */
404 if (conn->sess->sess_ops->DataSequenceInOrder) {
405 if (be32_to_cpu(hdr->offset) != cmd->write_data_done) {
406 pr_err("Command ITT: 0x%08x, received offset"
407 " %u different than expected %u.\n", cmd->init_task_tag,
408 be32_to_cpu(hdr->offset), cmd->write_data_done);
409 recovery = 1;
410 goto recover;
411 }
412 } else {
413 struct iscsi_seq *seq = cmd->seq_ptr;
414
415 if (be32_to_cpu(hdr->offset) > seq->offset) {
416 pr_err("Command ITT: 0x%08x, received offset"
417 " %u greater than expected %u.\n", cmd->init_task_tag,
418 be32_to_cpu(hdr->offset), seq->offset);
419 recovery = 1;
420 goto recover;
421 } else if (be32_to_cpu(hdr->offset) < seq->offset) {
422 pr_err("Command ITT: 0x%08x, received offset"
423 " %u less than expected %u, discarding payload.\n",
424 cmd->init_task_tag, be32_to_cpu(hdr->offset),
425 seq->offset);
426 dump = 1;
427 goto dump;
428 }
429 }
430
431 return DATAOUT_NORMAL;
432
433recover:
434 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
435 pr_err("Unable to perform within-command recovery"
436 " while ERL=0.\n");
437 return DATAOUT_CANNOT_RECOVER;
438 }
439dump:
440 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
441 return DATAOUT_CANNOT_RECOVER;
442
443 return (recovery) ? iscsit_recover_dataout_sequence(cmd,
444 be32_to_cpu(hdr->offset), payload_length) :
445 (dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY : DATAOUT_NORMAL;
446}
447
448static int iscsit_dataout_pre_datapduinorder_no(
449 struct iscsit_cmd *cmd,
450 unsigned char *buf)
451{
452 struct iscsi_pdu *pdu;
453 struct iscsi_data *hdr = (struct iscsi_data *) buf;
454 u32 payload_length = ntoh24(hdr->dlength);
455
456 pdu = iscsit_get_pdu_holder(cmd, be32_to_cpu(hdr->offset),
457 payload_length);
458 if (!pdu)
459 return DATAOUT_CANNOT_RECOVER;
460
461 cmd->pdu_ptr = pdu;
462
463 switch (pdu->status) {
464 case ISCSI_PDU_NOT_RECEIVED:
465 case ISCSI_PDU_CRC_FAILED:
466 case ISCSI_PDU_TIMED_OUT:
467 break;
468 case ISCSI_PDU_RECEIVED_OK:
469 pr_err("Command ITT: 0x%08x received already gotten"
470 " Offset: %u, Length: %u\n", cmd->init_task_tag,
471 be32_to_cpu(hdr->offset), payload_length);
472 return iscsit_dump_data_payload(cmd->conn, payload_length, 1);
473 default:
474 return DATAOUT_CANNOT_RECOVER;
475 }
476
477 return DATAOUT_NORMAL;
478}
479
480static int iscsit_dataout_update_r2t(struct iscsit_cmd *cmd, u32 offset, u32 length)
481{
482 struct iscsi_r2t *r2t;
483
484 if (cmd->unsolicited_data)
485 return 0;
486
487 r2t = iscsit_get_r2t_for_eos(cmd, offset, length);
488 if (!r2t)
489 return -1;
490
491 spin_lock_bh(lock: &cmd->r2t_lock);
492 r2t->seq_complete = 1;
493 cmd->outstanding_r2ts--;
494 spin_unlock_bh(lock: &cmd->r2t_lock);
495
496 return 0;
497}
498
499static int iscsit_dataout_update_datapduinorder_no(
500 struct iscsit_cmd *cmd,
501 u32 data_sn,
502 int f_bit)
503{
504 int ret = 0;
505 struct iscsi_pdu *pdu = cmd->pdu_ptr;
506
507 pdu->data_sn = data_sn;
508
509 switch (pdu->status) {
510 case ISCSI_PDU_NOT_RECEIVED:
511 pdu->status = ISCSI_PDU_RECEIVED_OK;
512 break;
513 case ISCSI_PDU_CRC_FAILED:
514 pdu->status = ISCSI_PDU_RECEIVED_OK;
515 break;
516 case ISCSI_PDU_TIMED_OUT:
517 pdu->status = ISCSI_PDU_RECEIVED_OK;
518 break;
519 default:
520 return DATAOUT_CANNOT_RECOVER;
521 }
522
523 if (f_bit) {
524 ret = iscsit_dataout_datapduinorder_no_fbit(cmd, pdu);
525 if (ret == DATAOUT_CANNOT_RECOVER)
526 return ret;
527 }
528
529 return DATAOUT_NORMAL;
530}
531
532static int iscsit_dataout_post_crc_passed(
533 struct iscsit_cmd *cmd,
534 unsigned char *buf)
535{
536 int ret, send_r2t = 0;
537 struct iscsit_conn *conn = cmd->conn;
538 struct iscsi_seq *seq = NULL;
539 struct iscsi_data *hdr = (struct iscsi_data *) buf;
540 u32 payload_length = ntoh24(hdr->dlength);
541
542 if (cmd->unsolicited_data) {
543 if ((cmd->first_burst_len + payload_length) ==
544 conn->sess->sess_ops->FirstBurstLength) {
545 if (iscsit_dataout_update_r2t(cmd, be32_to_cpu(hdr->offset),
546 length: payload_length) < 0)
547 return DATAOUT_CANNOT_RECOVER;
548 send_r2t = 1;
549 }
550
551 if (!conn->sess->sess_ops->DataPDUInOrder) {
552 ret = iscsit_dataout_update_datapduinorder_no(cmd,
553 be32_to_cpu(hdr->datasn),
554 f_bit: (hdr->flags & ISCSI_FLAG_CMD_FINAL));
555 if (ret == DATAOUT_CANNOT_RECOVER)
556 return ret;
557 }
558
559 cmd->first_burst_len += payload_length;
560
561 if (conn->sess->sess_ops->DataSequenceInOrder)
562 cmd->data_sn++;
563 else {
564 seq = cmd->seq_ptr;
565 seq->data_sn++;
566 seq->offset += payload_length;
567 }
568
569 if (send_r2t) {
570 if (seq)
571 seq->status = DATAOUT_SEQUENCE_COMPLETE;
572 cmd->first_burst_len = 0;
573 cmd->unsolicited_data = 0;
574 }
575 } else {
576 if (conn->sess->sess_ops->DataSequenceInOrder) {
577 if ((cmd->next_burst_len + payload_length) ==
578 conn->sess->sess_ops->MaxBurstLength) {
579 if (iscsit_dataout_update_r2t(cmd,
580 be32_to_cpu(hdr->offset),
581 length: payload_length) < 0)
582 return DATAOUT_CANNOT_RECOVER;
583 send_r2t = 1;
584 }
585
586 if (!conn->sess->sess_ops->DataPDUInOrder) {
587 ret = iscsit_dataout_update_datapduinorder_no(
588 cmd, be32_to_cpu(hdr->datasn),
589 f_bit: (hdr->flags & ISCSI_FLAG_CMD_FINAL));
590 if (ret == DATAOUT_CANNOT_RECOVER)
591 return ret;
592 }
593
594 cmd->next_burst_len += payload_length;
595 cmd->data_sn++;
596
597 if (send_r2t)
598 cmd->next_burst_len = 0;
599 } else {
600 seq = cmd->seq_ptr;
601
602 if ((seq->next_burst_len + payload_length) ==
603 seq->xfer_len) {
604 if (iscsit_dataout_update_r2t(cmd,
605 be32_to_cpu(hdr->offset),
606 length: payload_length) < 0)
607 return DATAOUT_CANNOT_RECOVER;
608 send_r2t = 1;
609 }
610
611 if (!conn->sess->sess_ops->DataPDUInOrder) {
612 ret = iscsit_dataout_update_datapduinorder_no(
613 cmd, be32_to_cpu(hdr->datasn),
614 f_bit: (hdr->flags & ISCSI_FLAG_CMD_FINAL));
615 if (ret == DATAOUT_CANNOT_RECOVER)
616 return ret;
617 }
618
619 seq->data_sn++;
620 seq->offset += payload_length;
621 seq->next_burst_len += payload_length;
622
623 if (send_r2t) {
624 seq->next_burst_len = 0;
625 seq->status = DATAOUT_SEQUENCE_COMPLETE;
626 }
627 }
628 }
629
630 if (send_r2t && conn->sess->sess_ops->DataSequenceInOrder)
631 cmd->data_sn = 0;
632
633 cmd->write_data_done += payload_length;
634
635 if (cmd->write_data_done == cmd->se_cmd.data_length)
636 return DATAOUT_SEND_TO_TRANSPORT;
637 else if (send_r2t)
638 return DATAOUT_SEND_R2T;
639 else
640 return DATAOUT_NORMAL;
641}
642
643static int iscsit_dataout_post_crc_failed(
644 struct iscsit_cmd *cmd,
645 unsigned char *buf)
646{
647 struct iscsit_conn *conn = cmd->conn;
648 struct iscsi_pdu *pdu;
649 struct iscsi_data *hdr = (struct iscsi_data *) buf;
650 u32 payload_length = ntoh24(hdr->dlength);
651
652 if (conn->sess->sess_ops->DataPDUInOrder)
653 goto recover;
654 /*
655 * The rest of this function is only called when DataPDUInOrder=No.
656 */
657 pdu = cmd->pdu_ptr;
658
659 switch (pdu->status) {
660 case ISCSI_PDU_NOT_RECEIVED:
661 pdu->status = ISCSI_PDU_CRC_FAILED;
662 break;
663 case ISCSI_PDU_CRC_FAILED:
664 break;
665 case ISCSI_PDU_TIMED_OUT:
666 pdu->status = ISCSI_PDU_CRC_FAILED;
667 break;
668 default:
669 return DATAOUT_CANNOT_RECOVER;
670 }
671
672recover:
673 return iscsit_recover_dataout_sequence(cmd, be32_to_cpu(hdr->offset),
674 payload_length);
675}
676
677/*
678 * Called from iscsit_handle_data_out() before DataOUT Payload is received
679 * and CRC computed.
680 */
681int iscsit_check_pre_dataout(
682 struct iscsit_cmd *cmd,
683 unsigned char *buf)
684{
685 int ret;
686 struct iscsit_conn *conn = cmd->conn;
687
688 ret = iscsit_dataout_within_command_recovery_check(cmd, buf);
689 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
690 (ret == DATAOUT_CANNOT_RECOVER))
691 return ret;
692
693 ret = iscsit_dataout_check_datasn(cmd, buf);
694 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
695 (ret == DATAOUT_CANNOT_RECOVER))
696 return ret;
697
698 if (cmd->unsolicited_data) {
699 ret = iscsit_dataout_check_unsolicited_sequence(cmd, buf);
700 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
701 (ret == DATAOUT_CANNOT_RECOVER))
702 return ret;
703 } else {
704 ret = iscsit_dataout_check_sequence(cmd, buf);
705 if ((ret == DATAOUT_WITHIN_COMMAND_RECOVERY) ||
706 (ret == DATAOUT_CANNOT_RECOVER))
707 return ret;
708 }
709
710 return (conn->sess->sess_ops->DataPDUInOrder) ?
711 iscsit_dataout_pre_datapduinorder_yes(cmd, buf) :
712 iscsit_dataout_pre_datapduinorder_no(cmd, buf);
713}
714
715/*
716 * Called from iscsit_handle_data_out() after DataOUT Payload is received
717 * and CRC computed.
718 */
719int iscsit_check_post_dataout(
720 struct iscsit_cmd *cmd,
721 unsigned char *buf,
722 u8 data_crc_failed)
723{
724 struct iscsit_conn *conn = cmd->conn;
725
726 cmd->dataout_timeout_retries = 0;
727
728 if (!data_crc_failed)
729 return iscsit_dataout_post_crc_passed(cmd, buf);
730 else {
731 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
732 pr_err("Unable to recover from DataOUT CRC"
733 " failure while ERL=0, closing session.\n");
734 iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR,
735 buf);
736 return DATAOUT_CANNOT_RECOVER;
737 }
738
739 iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf);
740 return iscsit_dataout_post_crc_failed(cmd, buf);
741 }
742}
743
744void iscsit_handle_time2retain_timeout(struct timer_list *t)
745{
746 struct iscsit_session *sess = from_timer(sess, t, time2retain_timer);
747 struct iscsi_portal_group *tpg = sess->tpg;
748 struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
749
750 spin_lock_bh(lock: &se_tpg->session_lock);
751 if (sess->time2retain_timer_flags & ISCSI_TF_STOP) {
752 spin_unlock_bh(lock: &se_tpg->session_lock);
753 return;
754 }
755 if (atomic_read(v: &sess->session_reinstatement)) {
756 pr_err("Exiting Time2Retain handler because"
757 " session_reinstatement=1\n");
758 spin_unlock_bh(lock: &se_tpg->session_lock);
759 return;
760 }
761 sess->time2retain_timer_flags |= ISCSI_TF_EXPIRED;
762
763 pr_err("Time2Retain timer expired for SID: %u, cleaning up"
764 " iSCSI session.\n", sess->sid);
765
766 iscsit_fill_cxn_timeout_err_stats(sess);
767 spin_unlock_bh(lock: &se_tpg->session_lock);
768 iscsit_close_session(sess, can_sleep: false);
769}
770
771void iscsit_start_time2retain_handler(struct iscsit_session *sess)
772{
773 int tpg_active;
774 /*
775 * Only start Time2Retain timer when the associated TPG is still in
776 * an ACTIVE (eg: not disabled or shutdown) state.
777 */
778 spin_lock(lock: &sess->tpg->tpg_state_lock);
779 tpg_active = (sess->tpg->tpg_state == TPG_STATE_ACTIVE);
780 spin_unlock(lock: &sess->tpg->tpg_state_lock);
781
782 if (!tpg_active)
783 return;
784
785 if (sess->time2retain_timer_flags & ISCSI_TF_RUNNING)
786 return;
787
788 pr_debug("Starting Time2Retain timer for %u seconds on"
789 " SID: %u\n", sess->sess_ops->DefaultTime2Retain, sess->sid);
790
791 sess->time2retain_timer_flags &= ~ISCSI_TF_STOP;
792 sess->time2retain_timer_flags |= ISCSI_TF_RUNNING;
793 mod_timer(timer: &sess->time2retain_timer,
794 expires: jiffies + sess->sess_ops->DefaultTime2Retain * HZ);
795}
796
797int iscsit_stop_time2retain_timer(struct iscsit_session *sess)
798{
799 struct iscsi_portal_group *tpg = sess->tpg;
800 struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
801
802 lockdep_assert_held(&se_tpg->session_lock);
803
804 if (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)
805 return -1;
806
807 if (!(sess->time2retain_timer_flags & ISCSI_TF_RUNNING))
808 return 0;
809
810 sess->time2retain_timer_flags |= ISCSI_TF_STOP;
811 spin_unlock(lock: &se_tpg->session_lock);
812
813 del_timer_sync(timer: &sess->time2retain_timer);
814
815 spin_lock(lock: &se_tpg->session_lock);
816 sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING;
817 pr_debug("Stopped Time2Retain Timer for SID: %u\n",
818 sess->sid);
819 return 0;
820}
821
822void iscsit_connection_reinstatement_rcfr(struct iscsit_conn *conn)
823{
824 spin_lock_bh(lock: &conn->state_lock);
825 if (atomic_read(v: &conn->connection_exit)) {
826 spin_unlock_bh(lock: &conn->state_lock);
827 goto sleep;
828 }
829
830 if (atomic_read(v: &conn->transport_failed)) {
831 spin_unlock_bh(lock: &conn->state_lock);
832 goto sleep;
833 }
834 spin_unlock_bh(lock: &conn->state_lock);
835
836 if (conn->tx_thread && conn->tx_thread_active)
837 send_sig(SIGINT, conn->tx_thread, 1);
838 if (conn->rx_thread && conn->rx_thread_active)
839 send_sig(SIGINT, conn->rx_thread, 1);
840
841sleep:
842 wait_for_completion(&conn->conn_wait_rcfr_comp);
843 complete(&conn->conn_post_wait_comp);
844}
845
846void iscsit_cause_connection_reinstatement(struct iscsit_conn *conn, int sleep)
847{
848 spin_lock_bh(lock: &conn->state_lock);
849 if (atomic_read(v: &conn->connection_exit)) {
850 spin_unlock_bh(lock: &conn->state_lock);
851 return;
852 }
853
854 if (atomic_read(v: &conn->transport_failed)) {
855 spin_unlock_bh(lock: &conn->state_lock);
856 return;
857 }
858
859 if (atomic_read(v: &conn->connection_reinstatement)) {
860 spin_unlock_bh(lock: &conn->state_lock);
861 return;
862 }
863
864 if (conn->tx_thread && conn->tx_thread_active)
865 send_sig(SIGINT, conn->tx_thread, 1);
866 if (conn->rx_thread && conn->rx_thread_active)
867 send_sig(SIGINT, conn->rx_thread, 1);
868
869 atomic_set(v: &conn->connection_reinstatement, i: 1);
870 if (!sleep) {
871 spin_unlock_bh(lock: &conn->state_lock);
872 return;
873 }
874
875 atomic_set(v: &conn->sleep_on_conn_wait_comp, i: 1);
876 spin_unlock_bh(lock: &conn->state_lock);
877
878 wait_for_completion(&conn->conn_wait_comp);
879 complete(&conn->conn_post_wait_comp);
880}
881EXPORT_SYMBOL(iscsit_cause_connection_reinstatement);
882
883void iscsit_fall_back_to_erl0(struct iscsit_session *sess)
884{
885 pr_debug("Falling back to ErrorRecoveryLevel=0 for SID:"
886 " %u\n", sess->sid);
887
888 atomic_set(v: &sess->session_fall_back_to_erl0, i: 1);
889}
890
891static void iscsit_handle_connection_cleanup(struct iscsit_conn *conn)
892{
893 struct iscsit_session *sess = conn->sess;
894
895 if ((sess->sess_ops->ErrorRecoveryLevel == 2) &&
896 !atomic_read(v: &sess->session_reinstatement) &&
897 !atomic_read(v: &sess->session_fall_back_to_erl0))
898 iscsit_connection_recovery_transport_reset(conn);
899 else {
900 pr_debug("Performing cleanup for failed iSCSI"
901 " Connection ID: %hu from %s\n", conn->cid,
902 sess->sess_ops->InitiatorName);
903 iscsit_close_connection(conn);
904 }
905}
906
907void iscsit_take_action_for_connection_exit(struct iscsit_conn *conn, bool *conn_freed)
908{
909 *conn_freed = false;
910
911 spin_lock_bh(lock: &conn->state_lock);
912 if (atomic_read(v: &conn->connection_exit)) {
913 spin_unlock_bh(lock: &conn->state_lock);
914 return;
915 }
916 atomic_set(v: &conn->connection_exit, i: 1);
917
918 if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
919 spin_unlock_bh(lock: &conn->state_lock);
920 iscsit_close_connection(conn);
921 *conn_freed = true;
922 return;
923 }
924
925 if (conn->conn_state == TARG_CONN_STATE_CLEANUP_WAIT) {
926 spin_unlock_bh(lock: &conn->state_lock);
927 return;
928 }
929
930 pr_debug("Moving to TARG_CONN_STATE_CLEANUP_WAIT.\n");
931 conn->conn_state = TARG_CONN_STATE_CLEANUP_WAIT;
932 spin_unlock_bh(lock: &conn->state_lock);
933
934 iscsit_handle_connection_cleanup(conn);
935 *conn_freed = true;
936}
937

source code of linux/drivers/target/iscsi/iscsi_target_erl0.c