From 2f5d21b09c6ad78c54f78b732abc4ba558a4b787 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Fri, 20 Feb 2015 20:51:14 -0800 Subject: [PATCH] iscsi-command.c: Use common function to write unsolicited data-out pdus. We write unsolicited data-out PDUs from two places; when we originally write the command in iscsi_scsi_command_async() but also when we re-queue the PDUs during a session reconnect. The re-queuing during the session re-connect was recently (almost) fixed but was still buggy in that it did not correctly clamp the amount of written data as per first burst length restriction. This attempts to fix that. Signed-off-by: Ronnie Sahlberg --- include/iscsi-private.h | 3 ++- lib/connect.c | 19 +++++++++---------- lib/iscsi-command.c | 21 +++++++++++++-------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 7d1ec75..145c58f 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -271,7 +271,8 @@ void iscsi_pdu_set_datasn(struct iscsi_pdu *pdu, uint32_t datasn); 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); -EXTERN int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); +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); diff --git a/lib/connect.c b/lib/connect.c index 4f4e2d0..a132243 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -242,10 +242,6 @@ void iscsi_defer_reconnect(struct iscsi_context *iscsi) } } -int -iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, - uint32_t ttt, uint32_t offset, uint32_t tot_len); - int iscsi_reconnect(struct iscsi_context *old_iscsi) { struct iscsi_context *iscsi; @@ -347,7 +343,11 @@ try_again: if (pdu->flags & ISCSI_PDU_DROP_ON_RECONNECT) { /* - * We don't want to requeue NOPs. + * 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. */ iscsi_free_pdu(old_iscsi, pdu); continue; @@ -367,13 +367,12 @@ try_again: pdu->outdata_written = 0; pdu->payload_written = 0; iscsi_queue_pdu(iscsi, pdu); - /* All PDUs that write data and do not have final set - * needs some additional data-out to be requeued. + /* 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. */ if ((pdu->outdata.data[1] & (ISCSI_PDU_SCSI_WRITE | ISCSI_PDU_SCSI_FINAL)) == ISCSI_PDU_SCSI_WRITE) { - iscsi_send_data_out(iscsi, pdu, 0xffffffff, - pdu->payload_len, - pdu->expxferlen - pdu->payload_len); + iscsi_send_unsolicited_data_out(iscsi, pdu); } } diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index 22a7284..c874d9a 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -67,7 +67,7 @@ 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 ttt, uint32_t offset, uint32_t tot_len) { @@ -190,6 +190,17 @@ iscsi_timeout_scan(struct iscsi_context *iscsi) } } +int +iscsi_send_unsolicited_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) +{ + uint32_t len = pdu->expxferlen - pdu->payload_len; + + if (len > iscsi->first_burst_length) { + len = iscsi->first_burst_length; + } + return iscsi_send_data_out(iscsi, pdu, 0xffffffff, + pdu->payload_len, len); +} /* Using 'struct iscsi_data *d' for data-out is optional * and will be converted into a one element data-out iovector. @@ -326,13 +337,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, * subtract from first_burst_length. */ if (!(flags & ISCSI_PDU_SCSI_FINAL)) { - uint32_t len = pdu->expxferlen - pdu->payload_len; - - if (len > iscsi->first_burst_length) { - len = iscsi->first_burst_length; - } - iscsi_send_data_out(iscsi, pdu, 0xffffffff, - pdu->payload_len, len); + iscsi_send_unsolicited_data_out(iscsi, pdu); } /* remember cmdsn and itt so we can use task management */