0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/slab.h>
0012 #include <scsi/iscsi_proto.h>
0013 #include <target/iscsi/iscsi_target_core.h>
0014 #include "iscsi_target_seq_pdu_list.h"
0015 #include "iscsi_target_erl1.h"
0016 #include "iscsi_target_util.h"
0017 #include "iscsi_target.h"
0018 #include "iscsi_target_datain_values.h"
0019
0020 struct iscsi_datain_req *iscsit_allocate_datain_req(void)
0021 {
0022 struct iscsi_datain_req *dr;
0023
0024 dr = kmem_cache_zalloc(lio_dr_cache, GFP_ATOMIC);
0025 if (!dr) {
0026 pr_err("Unable to allocate memory for"
0027 " struct iscsi_datain_req\n");
0028 return NULL;
0029 }
0030 INIT_LIST_HEAD(&dr->cmd_datain_node);
0031
0032 return dr;
0033 }
0034
0035 void iscsit_attach_datain_req(struct iscsit_cmd *cmd, struct iscsi_datain_req *dr)
0036 {
0037 spin_lock(&cmd->datain_lock);
0038 list_add_tail(&dr->cmd_datain_node, &cmd->datain_list);
0039 spin_unlock(&cmd->datain_lock);
0040 }
0041
0042 void iscsit_free_datain_req(struct iscsit_cmd *cmd, struct iscsi_datain_req *dr)
0043 {
0044 spin_lock(&cmd->datain_lock);
0045 list_del(&dr->cmd_datain_node);
0046 spin_unlock(&cmd->datain_lock);
0047
0048 kmem_cache_free(lio_dr_cache, dr);
0049 }
0050
0051 void iscsit_free_all_datain_reqs(struct iscsit_cmd *cmd)
0052 {
0053 struct iscsi_datain_req *dr, *dr_tmp;
0054
0055 spin_lock(&cmd->datain_lock);
0056 list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, cmd_datain_node) {
0057 list_del(&dr->cmd_datain_node);
0058 kmem_cache_free(lio_dr_cache, dr);
0059 }
0060 spin_unlock(&cmd->datain_lock);
0061 }
0062
0063 struct iscsi_datain_req *iscsit_get_datain_req(struct iscsit_cmd *cmd)
0064 {
0065 if (list_empty(&cmd->datain_list)) {
0066 pr_err("cmd->datain_list is empty for ITT:"
0067 " 0x%08x\n", cmd->init_task_tag);
0068 return NULL;
0069 }
0070
0071 return list_first_entry(&cmd->datain_list, struct iscsi_datain_req,
0072 cmd_datain_node);
0073 }
0074
0075
0076
0077
0078 static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_yes(
0079 struct iscsit_cmd *cmd,
0080 struct iscsi_datain *datain)
0081 {
0082 u32 next_burst_len, read_data_done, read_data_left;
0083 struct iscsit_conn *conn = cmd->conn;
0084 struct iscsi_datain_req *dr;
0085
0086 dr = iscsit_get_datain_req(cmd);
0087 if (!dr)
0088 return NULL;
0089
0090 if (dr->recovery && dr->generate_recovery_values) {
0091 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
0092 cmd, dr) < 0)
0093 return NULL;
0094
0095 dr->generate_recovery_values = 0;
0096 }
0097
0098 next_burst_len = (!dr->recovery) ?
0099 cmd->next_burst_len : dr->next_burst_len;
0100 read_data_done = (!dr->recovery) ?
0101 cmd->read_data_done : dr->read_data_done;
0102
0103 read_data_left = (cmd->se_cmd.data_length - read_data_done);
0104 if (!read_data_left) {
0105 pr_err("ITT: 0x%08x read_data_left is zero!\n",
0106 cmd->init_task_tag);
0107 return NULL;
0108 }
0109
0110 if ((read_data_left <= conn->conn_ops->MaxRecvDataSegmentLength) &&
0111 (read_data_left <= (conn->sess->sess_ops->MaxBurstLength -
0112 next_burst_len))) {
0113 datain->length = read_data_left;
0114
0115 datain->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
0116 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
0117 datain->flags |= ISCSI_FLAG_DATA_ACK;
0118 } else {
0119 if ((next_burst_len +
0120 conn->conn_ops->MaxRecvDataSegmentLength) <
0121 conn->sess->sess_ops->MaxBurstLength) {
0122 datain->length =
0123 conn->conn_ops->MaxRecvDataSegmentLength;
0124 next_burst_len += datain->length;
0125 } else {
0126 datain->length = (conn->sess->sess_ops->MaxBurstLength -
0127 next_burst_len);
0128 next_burst_len = 0;
0129
0130 datain->flags |= ISCSI_FLAG_CMD_FINAL;
0131 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
0132 datain->flags |= ISCSI_FLAG_DATA_ACK;
0133 }
0134 }
0135
0136 datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
0137 datain->offset = read_data_done;
0138
0139 if (!dr->recovery) {
0140 cmd->next_burst_len = next_burst_len;
0141 cmd->read_data_done += datain->length;
0142 } else {
0143 dr->next_burst_len = next_burst_len;
0144 dr->read_data_done += datain->length;
0145 }
0146
0147 if (!dr->recovery) {
0148 if (datain->flags & ISCSI_FLAG_DATA_STATUS)
0149 dr->dr_complete = DATAIN_COMPLETE_NORMAL;
0150
0151 return dr;
0152 }
0153
0154 if (!dr->runlength) {
0155 if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
0156 dr->dr_complete =
0157 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0158 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0159 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0160 }
0161 } else {
0162 if ((dr->begrun + dr->runlength) == dr->data_sn) {
0163 dr->dr_complete =
0164 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0165 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0166 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0167 }
0168 }
0169
0170 return dr;
0171 }
0172
0173
0174
0175
0176 static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
0177 struct iscsit_cmd *cmd,
0178 struct iscsi_datain *datain)
0179 {
0180 u32 offset, read_data_done, read_data_left, seq_send_order;
0181 struct iscsit_conn *conn = cmd->conn;
0182 struct iscsi_datain_req *dr;
0183 struct iscsi_seq *seq;
0184
0185 dr = iscsit_get_datain_req(cmd);
0186 if (!dr)
0187 return NULL;
0188
0189 if (dr->recovery && dr->generate_recovery_values) {
0190 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
0191 cmd, dr) < 0)
0192 return NULL;
0193
0194 dr->generate_recovery_values = 0;
0195 }
0196
0197 read_data_done = (!dr->recovery) ?
0198 cmd->read_data_done : dr->read_data_done;
0199 seq_send_order = (!dr->recovery) ?
0200 cmd->seq_send_order : dr->seq_send_order;
0201
0202 read_data_left = (cmd->se_cmd.data_length - read_data_done);
0203 if (!read_data_left) {
0204 pr_err("ITT: 0x%08x read_data_left is zero!\n",
0205 cmd->init_task_tag);
0206 return NULL;
0207 }
0208
0209 seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
0210 if (!seq)
0211 return NULL;
0212
0213 seq->sent = 1;
0214
0215 if (!dr->recovery && !seq->next_burst_len)
0216 seq->first_datasn = cmd->data_sn;
0217
0218 offset = (seq->offset + seq->next_burst_len);
0219
0220 if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
0221 cmd->se_cmd.data_length) {
0222 datain->length = (cmd->se_cmd.data_length - offset);
0223 datain->offset = offset;
0224
0225 datain->flags |= ISCSI_FLAG_CMD_FINAL;
0226 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
0227 datain->flags |= ISCSI_FLAG_DATA_ACK;
0228
0229 seq->next_burst_len = 0;
0230 seq_send_order++;
0231 } else {
0232 if ((seq->next_burst_len +
0233 conn->conn_ops->MaxRecvDataSegmentLength) <
0234 conn->sess->sess_ops->MaxBurstLength) {
0235 datain->length =
0236 conn->conn_ops->MaxRecvDataSegmentLength;
0237 datain->offset = (seq->offset + seq->next_burst_len);
0238
0239 seq->next_burst_len += datain->length;
0240 } else {
0241 datain->length = (conn->sess->sess_ops->MaxBurstLength -
0242 seq->next_burst_len);
0243 datain->offset = (seq->offset + seq->next_burst_len);
0244
0245 datain->flags |= ISCSI_FLAG_CMD_FINAL;
0246 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
0247 datain->flags |= ISCSI_FLAG_DATA_ACK;
0248
0249 seq->next_burst_len = 0;
0250 seq_send_order++;
0251 }
0252 }
0253
0254 if ((read_data_done + datain->length) == cmd->se_cmd.data_length)
0255 datain->flags |= ISCSI_FLAG_DATA_STATUS;
0256
0257 datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
0258 if (!dr->recovery) {
0259 cmd->seq_send_order = seq_send_order;
0260 cmd->read_data_done += datain->length;
0261 } else {
0262 dr->seq_send_order = seq_send_order;
0263 dr->read_data_done += datain->length;
0264 }
0265
0266 if (!dr->recovery) {
0267 if (datain->flags & ISCSI_FLAG_CMD_FINAL)
0268 seq->last_datasn = datain->data_sn;
0269 if (datain->flags & ISCSI_FLAG_DATA_STATUS)
0270 dr->dr_complete = DATAIN_COMPLETE_NORMAL;
0271
0272 return dr;
0273 }
0274
0275 if (!dr->runlength) {
0276 if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
0277 dr->dr_complete =
0278 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0279 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0280 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0281 }
0282 } else {
0283 if ((dr->begrun + dr->runlength) == dr->data_sn) {
0284 dr->dr_complete =
0285 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0286 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0287 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0288 }
0289 }
0290
0291 return dr;
0292 }
0293
0294
0295
0296
0297 static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
0298 struct iscsit_cmd *cmd,
0299 struct iscsi_datain *datain)
0300 {
0301 u32 next_burst_len, read_data_done, read_data_left;
0302 struct iscsit_conn *conn = cmd->conn;
0303 struct iscsi_datain_req *dr;
0304 struct iscsi_pdu *pdu;
0305
0306 dr = iscsit_get_datain_req(cmd);
0307 if (!dr)
0308 return NULL;
0309
0310 if (dr->recovery && dr->generate_recovery_values) {
0311 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes(
0312 cmd, dr) < 0)
0313 return NULL;
0314
0315 dr->generate_recovery_values = 0;
0316 }
0317
0318 next_burst_len = (!dr->recovery) ?
0319 cmd->next_burst_len : dr->next_burst_len;
0320 read_data_done = (!dr->recovery) ?
0321 cmd->read_data_done : dr->read_data_done;
0322
0323 read_data_left = (cmd->se_cmd.data_length - read_data_done);
0324 if (!read_data_left) {
0325 pr_err("ITT: 0x%08x read_data_left is zero!\n",
0326 cmd->init_task_tag);
0327 return dr;
0328 }
0329
0330 pdu = iscsit_get_pdu_holder_for_seq(cmd, NULL);
0331 if (!pdu)
0332 return dr;
0333
0334 if ((read_data_done + pdu->length) == cmd->se_cmd.data_length) {
0335 pdu->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
0336 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
0337 pdu->flags |= ISCSI_FLAG_DATA_ACK;
0338
0339 next_burst_len = 0;
0340 } else {
0341 if ((next_burst_len + conn->conn_ops->MaxRecvDataSegmentLength) <
0342 conn->sess->sess_ops->MaxBurstLength)
0343 next_burst_len += pdu->length;
0344 else {
0345 pdu->flags |= ISCSI_FLAG_CMD_FINAL;
0346 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
0347 pdu->flags |= ISCSI_FLAG_DATA_ACK;
0348
0349 next_burst_len = 0;
0350 }
0351 }
0352
0353 pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
0354 if (!dr->recovery) {
0355 cmd->next_burst_len = next_burst_len;
0356 cmd->read_data_done += pdu->length;
0357 } else {
0358 dr->next_burst_len = next_burst_len;
0359 dr->read_data_done += pdu->length;
0360 }
0361
0362 datain->flags = pdu->flags;
0363 datain->length = pdu->length;
0364 datain->offset = pdu->offset;
0365 datain->data_sn = pdu->data_sn;
0366
0367 if (!dr->recovery) {
0368 if (datain->flags & ISCSI_FLAG_DATA_STATUS)
0369 dr->dr_complete = DATAIN_COMPLETE_NORMAL;
0370
0371 return dr;
0372 }
0373
0374 if (!dr->runlength) {
0375 if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
0376 dr->dr_complete =
0377 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0378 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0379 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0380 }
0381 } else {
0382 if ((dr->begrun + dr->runlength) == dr->data_sn) {
0383 dr->dr_complete =
0384 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0385 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0386 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0387 }
0388 }
0389
0390 return dr;
0391 }
0392
0393
0394
0395
0396 static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
0397 struct iscsit_cmd *cmd,
0398 struct iscsi_datain *datain)
0399 {
0400 u32 read_data_done, read_data_left, seq_send_order;
0401 struct iscsit_conn *conn = cmd->conn;
0402 struct iscsi_datain_req *dr;
0403 struct iscsi_pdu *pdu;
0404 struct iscsi_seq *seq = NULL;
0405
0406 dr = iscsit_get_datain_req(cmd);
0407 if (!dr)
0408 return NULL;
0409
0410 if (dr->recovery && dr->generate_recovery_values) {
0411 if (iscsit_create_recovery_datain_values_datasequenceinorder_no(
0412 cmd, dr) < 0)
0413 return NULL;
0414
0415 dr->generate_recovery_values = 0;
0416 }
0417
0418 read_data_done = (!dr->recovery) ?
0419 cmd->read_data_done : dr->read_data_done;
0420 seq_send_order = (!dr->recovery) ?
0421 cmd->seq_send_order : dr->seq_send_order;
0422
0423 read_data_left = (cmd->se_cmd.data_length - read_data_done);
0424 if (!read_data_left) {
0425 pr_err("ITT: 0x%08x read_data_left is zero!\n",
0426 cmd->init_task_tag);
0427 return NULL;
0428 }
0429
0430 seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order);
0431 if (!seq)
0432 return NULL;
0433
0434 seq->sent = 1;
0435
0436 if (!dr->recovery && !seq->next_burst_len)
0437 seq->first_datasn = cmd->data_sn;
0438
0439 pdu = iscsit_get_pdu_holder_for_seq(cmd, seq);
0440 if (!pdu)
0441 return NULL;
0442
0443 if (seq->pdu_send_order == seq->pdu_count) {
0444 pdu->flags |= ISCSI_FLAG_CMD_FINAL;
0445 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
0446 pdu->flags |= ISCSI_FLAG_DATA_ACK;
0447
0448 seq->next_burst_len = 0;
0449 seq_send_order++;
0450 } else
0451 seq->next_burst_len += pdu->length;
0452
0453 if ((read_data_done + pdu->length) == cmd->se_cmd.data_length)
0454 pdu->flags |= ISCSI_FLAG_DATA_STATUS;
0455
0456 pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
0457 if (!dr->recovery) {
0458 cmd->seq_send_order = seq_send_order;
0459 cmd->read_data_done += pdu->length;
0460 } else {
0461 dr->seq_send_order = seq_send_order;
0462 dr->read_data_done += pdu->length;
0463 }
0464
0465 datain->flags = pdu->flags;
0466 datain->length = pdu->length;
0467 datain->offset = pdu->offset;
0468 datain->data_sn = pdu->data_sn;
0469
0470 if (!dr->recovery) {
0471 if (datain->flags & ISCSI_FLAG_CMD_FINAL)
0472 seq->last_datasn = datain->data_sn;
0473 if (datain->flags & ISCSI_FLAG_DATA_STATUS)
0474 dr->dr_complete = DATAIN_COMPLETE_NORMAL;
0475
0476 return dr;
0477 }
0478
0479 if (!dr->runlength) {
0480 if (datain->flags & ISCSI_FLAG_DATA_STATUS) {
0481 dr->dr_complete =
0482 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0483 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0484 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0485 }
0486 } else {
0487 if ((dr->begrun + dr->runlength) == dr->data_sn) {
0488 dr->dr_complete =
0489 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ?
0490 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY :
0491 DATAIN_COMPLETE_CONNECTION_RECOVERY;
0492 }
0493 }
0494
0495 return dr;
0496 }
0497
0498 struct iscsi_datain_req *iscsit_get_datain_values(
0499 struct iscsit_cmd *cmd,
0500 struct iscsi_datain *datain)
0501 {
0502 struct iscsit_conn *conn = cmd->conn;
0503
0504 if (conn->sess->sess_ops->DataSequenceInOrder &&
0505 conn->sess->sess_ops->DataPDUInOrder)
0506 return iscsit_set_datain_values_yes_and_yes(cmd, datain);
0507 else if (!conn->sess->sess_ops->DataSequenceInOrder &&
0508 conn->sess->sess_ops->DataPDUInOrder)
0509 return iscsit_set_datain_values_no_and_yes(cmd, datain);
0510 else if (conn->sess->sess_ops->DataSequenceInOrder &&
0511 !conn->sess->sess_ops->DataPDUInOrder)
0512 return iscsit_set_datain_values_yes_and_no(cmd, datain);
0513 else if (!conn->sess->sess_ops->DataSequenceInOrder &&
0514 !conn->sess->sess_ops->DataPDUInOrder)
0515 return iscsit_set_datain_values_no_and_no(cmd, datain);
0516
0517 return NULL;
0518 }
0519 EXPORT_SYMBOL(iscsit_get_datain_values);