1 /******************************************************************************* 2 * This file contains the iSCSI Target DataIN value generation functions. 3 * 4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 5 * 6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2. 7 * 8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 9 * 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. 14 * 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 ******************************************************************************/ 20 21 #include <scsi/iscsi_proto.h> 22 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" 29 30 struct iscsi_datain_req *iscsit_allocate_datain_req(void) 31 { 32 struct iscsi_datain_req *dr; 33 34 dr = kmem_cache_zalloc(lio_dr_cache, GFP_ATOMIC); 35 if (!dr) { 36 pr_err("Unable to allocate memory for" 37 " struct iscsi_datain_req\n"); 38 return NULL; 39 } 40 INIT_LIST_HEAD(&dr->cmd_datain_node); 41 42 return dr; 43 } 44 45 void iscsit_attach_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr) 46 { 47 spin_lock(&cmd->datain_lock); 48 list_add_tail(&dr->cmd_datain_node, &cmd->datain_list); 49 spin_unlock(&cmd->datain_lock); 50 } 51 52 void iscsit_free_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr) 53 { 54 spin_lock(&cmd->datain_lock); 55 list_del(&dr->cmd_datain_node); 56 spin_unlock(&cmd->datain_lock); 57 58 kmem_cache_free(lio_dr_cache, dr); 59 } 60 61 void iscsit_free_all_datain_reqs(struct iscsi_cmd *cmd) 62 { 63 struct iscsi_datain_req *dr, *dr_tmp; 64 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); 69 } 70 spin_unlock(&cmd->datain_lock); 71 } 72 73 struct iscsi_datain_req *iscsit_get_datain_req(struct iscsi_cmd *cmd) 74 { 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); 78 return NULL; 79 } 80 81 return list_first_entry(&cmd->datain_list, struct iscsi_datain_req, 82 cmd_datain_node); 83 } 84 85 /* 86 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=Yes. 87 */ 88 static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_yes( 89 struct iscsi_cmd *cmd, 90 struct iscsi_datain *datain) 91 { 92 u32 next_burst_len, read_data_done, read_data_left; 93 struct iscsi_conn *conn = cmd->conn; 94 struct iscsi_datain_req *dr; 95 96 dr = iscsit_get_datain_req(cmd); 97 if (!dr) 98 return NULL; 99 100 if (dr->recovery && dr->generate_recovery_values) { 101 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes( 102 cmd, dr) < 0) 103 return NULL; 104 105 dr->generate_recovery_values = 0; 106 } 107 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; 112 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", 116 cmd->init_task_tag); 117 return NULL; 118 } 119 120 if ((read_data_left <= conn->conn_ops->MaxRecvDataSegmentLength) && 121 (read_data_left <= (conn->sess->sess_ops->MaxBurstLength - 122 next_burst_len))) { 123 datain->length = read_data_left; 124 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; 128 } else { 129 if ((next_burst_len + 130 conn->conn_ops->MaxRecvDataSegmentLength) < 131 conn->sess->sess_ops->MaxBurstLength) { 132 datain->length = 133 conn->conn_ops->MaxRecvDataSegmentLength; 134 next_burst_len += datain->length; 135 } else { 136 datain->length = (conn->sess->sess_ops->MaxBurstLength - 137 next_burst_len); 138 next_burst_len = 0; 139 140 datain->flags |= ISCSI_FLAG_CMD_FINAL; 141 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0) 142 datain->flags |= ISCSI_FLAG_DATA_ACK; 143 } 144 } 145 146 datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++; 147 datain->offset = read_data_done; 148 149 if (!dr->recovery) { 150 cmd->next_burst_len = next_burst_len; 151 cmd->read_data_done += datain->length; 152 } else { 153 dr->next_burst_len = next_burst_len; 154 dr->read_data_done += datain->length; 155 } 156 157 if (!dr->recovery) { 158 if (datain->flags & ISCSI_FLAG_DATA_STATUS) 159 dr->dr_complete = DATAIN_COMPLETE_NORMAL; 160 161 return dr; 162 } 163 164 if (!dr->runlength) { 165 if (datain->flags & ISCSI_FLAG_DATA_STATUS) { 166 dr->dr_complete = 167 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 168 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 169 DATAIN_COMPLETE_CONNECTION_RECOVERY; 170 } 171 } else { 172 if ((dr->begrun + dr->runlength) == dr->data_sn) { 173 dr->dr_complete = 174 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 175 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 176 DATAIN_COMPLETE_CONNECTION_RECOVERY; 177 } 178 } 179 180 return dr; 181 } 182 183 /* 184 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=Yes. 185 */ 186 static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes( 187 struct iscsi_cmd *cmd, 188 struct iscsi_datain *datain) 189 { 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; 194 195 dr = iscsit_get_datain_req(cmd); 196 if (!dr) 197 return NULL; 198 199 if (dr->recovery && dr->generate_recovery_values) { 200 if (iscsit_create_recovery_datain_values_datasequenceinorder_no( 201 cmd, dr) < 0) 202 return NULL; 203 204 dr->generate_recovery_values = 0; 205 } 206 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; 211 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", 215 cmd->init_task_tag); 216 return NULL; 217 } 218 219 seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order); 220 if (!seq) 221 return NULL; 222 223 seq->sent = 1; 224 225 if (!dr->recovery && !seq->next_burst_len) 226 seq->first_datasn = cmd->data_sn; 227 228 offset = (seq->offset + seq->next_burst_len); 229 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; 234 235 datain->flags |= ISCSI_FLAG_CMD_FINAL; 236 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0) 237 datain->flags |= ISCSI_FLAG_DATA_ACK; 238 239 seq->next_burst_len = 0; 240 seq_send_order++; 241 } else { 242 if ((seq->next_burst_len + 243 conn->conn_ops->MaxRecvDataSegmentLength) < 244 conn->sess->sess_ops->MaxBurstLength) { 245 datain->length = 246 conn->conn_ops->MaxRecvDataSegmentLength; 247 datain->offset = (seq->offset + seq->next_burst_len); 248 249 seq->next_burst_len += datain->length; 250 } else { 251 datain->length = (conn->sess->sess_ops->MaxBurstLength - 252 seq->next_burst_len); 253 datain->offset = (seq->offset + seq->next_burst_len); 254 255 datain->flags |= ISCSI_FLAG_CMD_FINAL; 256 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0) 257 datain->flags |= ISCSI_FLAG_DATA_ACK; 258 259 seq->next_burst_len = 0; 260 seq_send_order++; 261 } 262 } 263 264 if ((read_data_done + datain->length) == cmd->se_cmd.data_length) 265 datain->flags |= ISCSI_FLAG_DATA_STATUS; 266 267 datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++; 268 if (!dr->recovery) { 269 cmd->seq_send_order = seq_send_order; 270 cmd->read_data_done += datain->length; 271 } else { 272 dr->seq_send_order = seq_send_order; 273 dr->read_data_done += datain->length; 274 } 275 276 if (!dr->recovery) { 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; 281 282 return dr; 283 } 284 285 if (!dr->runlength) { 286 if (datain->flags & ISCSI_FLAG_DATA_STATUS) { 287 dr->dr_complete = 288 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 289 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 290 DATAIN_COMPLETE_CONNECTION_RECOVERY; 291 } 292 } else { 293 if ((dr->begrun + dr->runlength) == dr->data_sn) { 294 dr->dr_complete = 295 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 296 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 297 DATAIN_COMPLETE_CONNECTION_RECOVERY; 298 } 299 } 300 301 return dr; 302 } 303 304 /* 305 * For Normal and Recovery DataSequenceInOrder=Yes and DataPDUInOrder=No. 306 */ 307 static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no( 308 struct iscsi_cmd *cmd, 309 struct iscsi_datain *datain) 310 { 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; 315 316 dr = iscsit_get_datain_req(cmd); 317 if (!dr) 318 return NULL; 319 320 if (dr->recovery && dr->generate_recovery_values) { 321 if (iscsit_create_recovery_datain_values_datasequenceinorder_yes( 322 cmd, dr) < 0) 323 return NULL; 324 325 dr->generate_recovery_values = 0; 326 } 327 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; 332 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", 336 cmd->init_task_tag); 337 return dr; 338 } 339 340 pdu = iscsit_get_pdu_holder_for_seq(cmd, NULL); 341 if (!pdu) 342 return dr; 343 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; 348 349 next_burst_len = 0; 350 } else { 351 if ((next_burst_len + conn->conn_ops->MaxRecvDataSegmentLength) < 352 conn->sess->sess_ops->MaxBurstLength) 353 next_burst_len += pdu->length; 354 else { 355 pdu->flags |= ISCSI_FLAG_CMD_FINAL; 356 if (conn->sess->sess_ops->ErrorRecoveryLevel > 0) 357 pdu->flags |= ISCSI_FLAG_DATA_ACK; 358 359 next_burst_len = 0; 360 } 361 } 362 363 pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++; 364 if (!dr->recovery) { 365 cmd->next_burst_len = next_burst_len; 366 cmd->read_data_done += pdu->length; 367 } else { 368 dr->next_burst_len = next_burst_len; 369 dr->read_data_done += pdu->length; 370 } 371 372 datain->flags = pdu->flags; 373 datain->length = pdu->length; 374 datain->offset = pdu->offset; 375 datain->data_sn = pdu->data_sn; 376 377 if (!dr->recovery) { 378 if (datain->flags & ISCSI_FLAG_DATA_STATUS) 379 dr->dr_complete = DATAIN_COMPLETE_NORMAL; 380 381 return dr; 382 } 383 384 if (!dr->runlength) { 385 if (datain->flags & ISCSI_FLAG_DATA_STATUS) { 386 dr->dr_complete = 387 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 388 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 389 DATAIN_COMPLETE_CONNECTION_RECOVERY; 390 } 391 } else { 392 if ((dr->begrun + dr->runlength) == dr->data_sn) { 393 dr->dr_complete = 394 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 395 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 396 DATAIN_COMPLETE_CONNECTION_RECOVERY; 397 } 398 } 399 400 return dr; 401 } 402 403 /* 404 * For Normal and Recovery DataSequenceInOrder=No and DataPDUInOrder=No. 405 */ 406 static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no( 407 struct iscsi_cmd *cmd, 408 struct iscsi_datain *datain) 409 { 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; 415 416 dr = iscsit_get_datain_req(cmd); 417 if (!dr) 418 return NULL; 419 420 if (dr->recovery && dr->generate_recovery_values) { 421 if (iscsit_create_recovery_datain_values_datasequenceinorder_no( 422 cmd, dr) < 0) 423 return NULL; 424 425 dr->generate_recovery_values = 0; 426 } 427 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; 432 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", 436 cmd->init_task_tag); 437 return NULL; 438 } 439 440 seq = iscsit_get_seq_holder_for_datain(cmd, seq_send_order); 441 if (!seq) 442 return NULL; 443 444 seq->sent = 1; 445 446 if (!dr->recovery && !seq->next_burst_len) 447 seq->first_datasn = cmd->data_sn; 448 449 pdu = iscsit_get_pdu_holder_for_seq(cmd, seq); 450 if (!pdu) 451 return NULL; 452 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; 457 458 seq->next_burst_len = 0; 459 seq_send_order++; 460 } else 461 seq->next_burst_len += pdu->length; 462 463 if ((read_data_done + pdu->length) == cmd->se_cmd.data_length) 464 pdu->flags |= ISCSI_FLAG_DATA_STATUS; 465 466 pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++; 467 if (!dr->recovery) { 468 cmd->seq_send_order = seq_send_order; 469 cmd->read_data_done += pdu->length; 470 } else { 471 dr->seq_send_order = seq_send_order; 472 dr->read_data_done += pdu->length; 473 } 474 475 datain->flags = pdu->flags; 476 datain->length = pdu->length; 477 datain->offset = pdu->offset; 478 datain->data_sn = pdu->data_sn; 479 480 if (!dr->recovery) { 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; 485 486 return dr; 487 } 488 489 if (!dr->runlength) { 490 if (datain->flags & ISCSI_FLAG_DATA_STATUS) { 491 dr->dr_complete = 492 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 493 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 494 DATAIN_COMPLETE_CONNECTION_RECOVERY; 495 } 496 } else { 497 if ((dr->begrun + dr->runlength) == dr->data_sn) { 498 dr->dr_complete = 499 (dr->recovery == DATAIN_WITHIN_COMMAND_RECOVERY) ? 500 DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY : 501 DATAIN_COMPLETE_CONNECTION_RECOVERY; 502 } 503 } 504 505 return dr; 506 } 507 508 struct iscsi_datain_req *iscsit_get_datain_values( 509 struct iscsi_cmd *cmd, 510 struct iscsi_datain *datain) 511 { 512 struct iscsi_conn *conn = cmd->conn; 513 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); 526 527 return NULL; 528 } 529