diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c index 444342a..8b4ea54 100644 --- a/examples/iscsiclient.c +++ b/examples/iscsiclient.c @@ -62,12 +62,15 @@ void write10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, struct scsi_task *task = command_data; if (status == SCSI_STATUS_CHECK_CONDITION) { - printf("Write10 failed with sense key:%d ascq:%04x\n", task->sense.key, task->sense.ascq); exit(10); } + if (status != SCSI_STATUS_GOOD) { + printf("Write10 failed with %s\n", iscsi_get_error(iscsi)); + exit(10); + } - printf("Write successful\n"); + printf("Write successful :%d\n", status); exit(10); } diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 69d9071..3b54c9f 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -147,6 +147,7 @@ enum iscsi_opcode { ISCSI_PDU_TEXT_RESPONSE = 0x24, ISCSI_PDU_DATA_IN = 0x25, ISCSI_PDU_LOGOUT_RESPONSE = 0x26, + ISCSI_PDU_R2T = 0x31, ISCSI_PDU_NO_PDU = 0xff }; @@ -228,11 +229,8 @@ int iscsi_process_scsi_data_in(struct iscsi_context *iscsi, int iscsi_process_nop_out_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, struct iscsi_in_pdu *in); - -int iscsi_send_data_out(struct iscsi_context *iscsi, - struct iscsi_pdu *pdu, - uint32_t offset, - uint32_t len); +int iscsi_process_r2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, + struct iscsi_in_pdu *in); void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, ...); diff --git a/lib/pdu.c b/lib/pdu.c index 93739c7..06af47a 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -213,6 +213,14 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in) expected_response = ISCSI_PDU_DATA_IN; } + /* Another special case is if we get a R2T. + * In this case we should find the original request and just send an additional + * DATAOUT segment for this task. + */ + if (opcode == ISCSI_PDU_R2T) { + expected_response = ISCSI_PDU_R2T; + } + if (opcode != expected_response) { iscsi_set_error(iscsi, "Got wrong opcode back for " "itt:%d got:%d expected %d", @@ -274,9 +282,19 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in) return -1; } break; + case ISCSI_PDU_R2T: + if (iscsi_process_r2t(iscsi, pdu, in) != 0) { + SLIST_REMOVE(&iscsi->waitpdu, pdu); + iscsi_free_pdu(iscsi, pdu); + iscsi_set_error(iscsi, "iscsi r2t " + "failed"); + return -1; + } + is_finished = 0; + break; default: iscsi_set_error(iscsi, "Dont know how to handle " - "opcode %d", opcode); + "opcode 0x%02x", opcode); return -1; } diff --git a/lib/scsi-command.c b/lib/scsi-command.c index 4c431cd..8a2a98e 100644 --- a/lib/scsi-command.c +++ b/lib/scsi-command.c @@ -80,9 +80,9 @@ iscsi_scsi_response_cb(struct iscsi_context *iscsi, int status, } } -int +static int iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, - uint32_t offset, uint32_t tot_len) + uint32_t ttt, uint32_t offset, uint32_t tot_len) { while (tot_len > 0) { uint32_t len = tot_len; @@ -122,7 +122,7 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, iscsi_pdu_set_lun(pdu, cmd_pdu->lun); /* ttt */ - iscsi_pdu_set_ttt(pdu, 0xffffffff); + iscsi_pdu_set_ttt(pdu, ttt); /* exp statsn */ iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1); @@ -176,6 +176,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, struct iscsi_pdu *pdu; struct iscsi_scsi_cbdata *scsi_cbdata; struct iscsi_data data; + uint32_t offset = 0; int flags; @@ -300,7 +301,12 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, /* Can we send some unsolicited data ? */ if (pdu->nidata.size != 0 && iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO) { - iscsi_send_data_out(iscsi, pdu, 0, pdu->nidata.size); + uint32_t len = pdu->nidata.size - offset; + + if (len > iscsi->first_burst_length) { + len = iscsi->first_burst_length; + } + iscsi_send_data_out(iscsi, pdu, 0xffffffff, offset, len); } return 0; @@ -444,8 +450,19 @@ iscsi_process_scsi_data_in(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, return 0; } +int +iscsi_process_r2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, + struct iscsi_in_pdu *in) +{ + uint32_t ttt, offset, len; + ttt = ntohl(*(uint32_t *)&in->hdr[20]); + offset = ntohl(*(uint32_t *)&in->hdr[40]); + len = ntohl(*(uint32_t *)&in->hdr[44]); + iscsi_send_data_out(iscsi, pdu, ttt, offset, len); + return 0; +} /* * SCSI commands