diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 0dd73b0..afa6ad3 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -257,12 +257,9 @@ struct iscsi_pdu { struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode); -struct iscsi_pdu *iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, - enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode, - uint32_t itt, - uint32_t flags); + enum iscsi_opcode response_opcode, + uint32_t itt, + uint32_t flags); void iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); void iscsi_pdu_set_pduflags(struct iscsi_pdu *pdu, unsigned char flags); void iscsi_pdu_set_immediate(struct iscsi_pdu *pdu); @@ -279,7 +276,6 @@ void iscsi_pdu_set_bufferoffset(struct iscsi_pdu *pdu, uint32_t bufferoffset); int iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, unsigned char *dptr, int dsize); int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); -int iscsi_send_unsolicited_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); int iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data, unsigned char *dptr, int dsize, int pdualignment); @@ -328,6 +324,7 @@ void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, struct scsi_iovector *iscsi_get_scsi_task_iovector_in(struct iscsi_context *iscsi, struct iscsi_in_pdu *in); struct scsi_iovector *iscsi_get_scsi_task_iovector_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); +void scsi_task_reset_iov(struct scsi_iovector *iovector); void* iscsi_malloc(struct iscsi_context *iscsi, size_t size); void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size); diff --git a/lib/connect.c b/lib/connect.c index a132243..204d0b2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -343,37 +343,29 @@ try_again: if (pdu->flags & ISCSI_PDU_DROP_ON_RECONNECT) { /* - * We don't want to requeue NOPs or DATA-OUT PDUs. - * In case of DATA-OUT PDUs that are part of the - * initial unsolicited data we have to regenerate - * them forther down so that we end the re-queued - * WRITE + DATA-OUT train with a PDU with the F bit. - */ + * We only want to re-queue SCSI COMMAND PDUs. + * All other PDUs are discarded at this point. + * This includes DATA-OUT, NOP and task management. + */ iscsi_free_pdu(old_iscsi, pdu); continue; } - pdu->itt = iscsi_itt_post_increment(iscsi); - iscsi_pdu_set_itt(pdu, pdu->itt); + scsi_task_reset_iov(&pdu->scsi_cbdata.task->iovector_in); + scsi_task_reset_iov(&pdu->scsi_cbdata.task->iovector_out); - /* do not increase cmdsn for PDUs marked for immediate delivery - * this will result in a protocol error */ - pdu->cmdsn = (pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE)?iscsi->cmdsn:iscsi->cmdsn++; - iscsi_pdu_set_cmdsn(pdu, pdu->cmdsn); - - iscsi_pdu_set_expstatsn(pdu, iscsi->statsn); - iscsi->statsn++; - - pdu->outdata_written = 0; - pdu->payload_written = 0; - iscsi_queue_pdu(iscsi, pdu); - /* Requeue any unsolicited data-out for the command PDU we - * just re-queued. These are commands that write data to the - * device but does not have the F bit set. + /* We pass NULL as 'd' since any databuffer has already + * been converted to a task-> iovector first time this + * PDU was sent. */ - if ((pdu->outdata.data[1] & (ISCSI_PDU_SCSI_WRITE | ISCSI_PDU_SCSI_FINAL)) == ISCSI_PDU_SCSI_WRITE) { - iscsi_send_unsolicited_data_out(iscsi, pdu); + if (iscsi_scsi_command_async(iscsi, pdu->lun, + pdu->scsi_cbdata.task, + pdu->scsi_cbdata.callback, + NULL, + pdu->scsi_cbdata.private_data)) { + /* not much we can really do at this point */ } + iscsi_free_pdu(old_iscsi, pdu); } if (dup2(iscsi->fd, old_iscsi->fd) == -1) { diff --git a/lib/discovery.c b/lib/discovery.c index a8f7432..f44d58e 100644 --- a/lib/discovery.c +++ b/lib/discovery.c @@ -46,7 +46,9 @@ iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb, } pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_TEXT_REQUEST, - ISCSI_PDU_TEXT_RESPONSE); + ISCSI_PDU_TEXT_RESPONSE, + iscsi_itt_post_increment(iscsi), + ISCSI_PDU_DROP_ON_RECONNECT); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate " "text pdu."); diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index 4ba5a55..7877b0d 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -78,10 +78,11 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, len = MIN(len, iscsi->target_max_recv_data_segment_length); - pdu = iscsi_allocate_pdu_with_itt_flags(iscsi, ISCSI_PDU_DATA_OUT, - ISCSI_PDU_NO_PDU, - cmd_pdu->itt, - ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK); + pdu = iscsi_allocate_pdu(iscsi, + ISCSI_PDU_DATA_OUT, + ISCSI_PDU_NO_PDU, + cmd_pdu->itt, + ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate " "scsi data out pdu."); @@ -188,7 +189,7 @@ iscsi_timeout_scan(struct iscsi_context *iscsi) } } -int +static int iscsi_send_unsolicited_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { uint32_t len = MIN(pdu->expxferlen, iscsi->first_burst_length) - pdu->payload_len; @@ -235,8 +236,11 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, scsi_task_set_iov_out(task, iov, 1); } - pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_REQUEST, - ISCSI_PDU_SCSI_RESPONSE); + pdu = iscsi_allocate_pdu(iscsi, + ISCSI_PDU_SCSI_REQUEST, + ISCSI_PDU_SCSI_RESPONSE, + iscsi_itt_post_increment(iscsi), + 0); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory, Failed to allocate " "scsi pdu."); diff --git a/lib/login.c b/lib/login.c index 59c55d2..ffbce98 100644 --- a/lib/login.c +++ b/lib/login.c @@ -730,10 +730,11 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb, return -1; } - pdu = iscsi_allocate_pdu_with_itt_flags(iscsi, - ISCSI_PDU_LOGIN_REQUEST, - ISCSI_PDU_LOGIN_RESPONSE, - iscsi->itt, 0); + pdu = iscsi_allocate_pdu(iscsi, + ISCSI_PDU_LOGIN_REQUEST, + ISCSI_PDU_LOGIN_RESPONSE, + iscsi->itt, + ISCSI_PDU_DROP_ON_RECONNECT); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate " "login pdu."); @@ -1122,8 +1123,11 @@ iscsi_logout_async_internal(struct iscsi_context *iscsi, iscsi_command_cb cb, return -1; } - pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_LOGOUT_REQUEST, - ISCSI_PDU_LOGOUT_RESPONSE); + pdu = iscsi_allocate_pdu(iscsi, + ISCSI_PDU_LOGOUT_REQUEST, + ISCSI_PDU_LOGOUT_RESPONSE, + iscsi_itt_post_increment(iscsi), + ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_CORK_WHEN_SENT|flags); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate " "logout pdu."); @@ -1145,7 +1149,6 @@ iscsi_logout_async_internal(struct iscsi_context *iscsi, iscsi_command_cb cb, pdu->callback = cb; pdu->private_data = private_data; - pdu->flags |= ISCSI_PDU_CORK_WHEN_SENT | flags; if (iscsi_queue_pdu(iscsi, pdu) != 0) { iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi " diff --git a/lib/nop.c b/lib/nop.c index f228017..1729d1b 100644 --- a/lib/nop.c +++ b/lib/nop.c @@ -36,15 +36,16 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb, return -1; } - pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_NOP_OUT, ISCSI_PDU_NOP_IN); + pdu = iscsi_allocate_pdu(iscsi, + ISCSI_PDU_NOP_OUT, + ISCSI_PDU_NOP_IN, + iscsi_itt_post_increment(iscsi), + ISCSI_PDU_DROP_ON_RECONNECT); if (pdu == NULL) { iscsi_set_error(iscsi, "Failed to allocate nop-out pdu"); return -1; } - /* We don't want to requeue these on reconnect */ - pdu->flags |= ISCSI_PDU_DROP_ON_RECONNECT; - /* immediate flag */ iscsi_pdu_set_immediate(pdu); @@ -91,8 +92,11 @@ iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt) { struct iscsi_pdu *pdu; - pdu = iscsi_allocate_pdu_with_itt_flags(iscsi, ISCSI_PDU_NOP_OUT, ISCSI_PDU_NO_PDU, - 0xffffffff,ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK); + pdu = iscsi_allocate_pdu(iscsi, + ISCSI_PDU_NOP_OUT, + ISCSI_PDU_NO_PDU, + 0xffffffff, + ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK); if (pdu == NULL) { iscsi_set_error(iscsi, "Failed to allocate nop-out pdu"); return -1; diff --git a/lib/pdu.c b/lib/pdu.c index 21b3549..3d0b5c4 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -104,8 +104,9 @@ void iscsi_dump_pdu_header(struct iscsi_context *iscsi, unsigned char *data) { } struct iscsi_pdu * -iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode, uint32_t itt, uint32_t flags) +iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode, + enum iscsi_opcode response_opcode, uint32_t itt, + uint32_t flags) { struct iscsi_pdu *pdu; @@ -143,13 +144,6 @@ iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode return pdu; } -struct iscsi_pdu * -iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode, - enum iscsi_opcode response_opcode) -{ - return iscsi_allocate_pdu_with_itt_flags(iscsi, opcode, response_opcode, iscsi_itt_post_increment(iscsi), 0); -} - void iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) { @@ -371,7 +365,7 @@ int iscsi_process_reject(struct iscsi_context *iscsi, if (reason == ISCSI_REJECT_WAITING_FOR_LOGOUT) { ISCSI_LOG(iscsi, 1, "target rejects request with reason: %s", iscsi_reject_reason_str(reason)); - iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_URGENT_DELIVERY); + iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_URGENT_DELIVERY); return 0; } @@ -441,7 +435,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in) ISCSI_LOG(iscsi, 2, "dropping connection to fix errors with broken DELL Equallogic firmware 7.x"); return -1; } - iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_URGENT_DELIVERY); + iscsi_logout_async_internal(iscsi, iscsi_reconnect_after_logout, NULL, ISCSI_PDU_URGENT_DELIVERY); return 0; case 0x2: ISCSI_LOG(iscsi, 2, "target will drop this connection. Time2Wait is %u seconds", param2); diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index f8cb71a..c41c95b 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -3817,6 +3817,14 @@ scsi_task_set_iov_in(struct scsi_task *task, struct scsi_iovec *iov, int niov) task->iovector_in.niov = niov; } +void +scsi_task_reset_iov(struct scsi_iovector *iovector) +{ + iovector->nalloc = 0; + iovector->offset = 0; + iovector->consumed = 0; +} + #define IOVECTOR_INITAL_ALLOC (16) static int diff --git a/lib/task_mgmt.c b/lib/task_mgmt.c index 7a3d749..0847103 100644 --- a/lib/task_mgmt.c +++ b/lib/task_mgmt.c @@ -49,8 +49,11 @@ iscsi_task_mgmt_async(struct iscsi_context *iscsi, return -1; } - pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_TASK_MANAGEMENT_REQUEST, - ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE); + pdu = iscsi_allocate_pdu(iscsi, + ISCSI_PDU_SCSI_TASK_MANAGEMENT_REQUEST, + ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE, + iscsi_itt_post_increment(iscsi), + ISCSI_PDU_DROP_ON_RECONNECT); if (pdu == NULL) { iscsi_set_error(iscsi, "Failed to allocate task mgmt pdu"); return -1;