Merge pull request #332 from bytedance/fix_cancellation_handling

Fix cancellation handling
This commit is contained in:
Bart Van Assche
2020-07-18 20:04:29 -07:00
committed by GitHub
4 changed files with 57 additions and 14 deletions

View File

@@ -271,7 +271,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
iscsi_pdu_set_expxferlen(pdu, task->expxferlen);
/* cmdsn */
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn++);
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
/* cdb */
iscsi_pdu_set_cdb(pdu, task);
@@ -285,6 +285,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
iscsi->drv->free_pdu(iscsi, pdu);
return -1;
}
iscsi->cmdsn++;
/* The F flag is not set. This means we haven't sent all the unsolicited
* data yet. Sent as much as we are allowed as a train of DATA-OUT PDUs.
@@ -2667,6 +2668,9 @@ iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
struct scsi_task *task)
{
struct iscsi_pdu *pdu;
struct iscsi_pdu *next_pdu;
uint32_t cmdsn_gap = 0;
int ret = -1;
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
if (pdu->itt == task->itt) {
@@ -2679,22 +2683,45 @@ iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
return 0;
}
}
for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
next_pdu = pdu->next;
if (cmdsn_gap > 0) {
iscsi_pdu_set_cmdsn(pdu, pdu->cmdsn - cmdsn_gap);
}
if (pdu->itt == task->itt) {
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
if (pdu->callback) {
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
pdu->private_data);
}
if (!(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE) &&
(pdu->outdata.data[0] & 0x3f) != ISCSI_PDU_DATA_OUT) {
iscsi->cmdsn--;
cmdsn_gap++;
}
iscsi->drv->free_pdu(iscsi, pdu);
return 0;
ret = 0;
if (!cmdsn_gap) {
break;
}
}
}
return -1;
if (iscsi->old_iscsi) {
return iscsi_scsi_cancel_task(iscsi->old_iscsi, task);
}
return ret;
}
void
iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
{
iscsi_cancel_pdus(iscsi);
if (iscsi->old_iscsi) {
iscsi_cancel_pdus(iscsi->old_iscsi);
}
}

View File

@@ -64,7 +64,7 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
iscsi_pdu_set_lun(pdu, 0);
/* cmdsn */
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn++);
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
pdu->callback = cb;
pdu->private_data = private_data;
@@ -83,6 +83,7 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
return -1;
}
iscsi->cmdsn++;
iscsi->nops_in_flight++;
ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6,
"NOP Out Send (nops_in_flight: %d, pdu->cmdsn %08x, pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x)",

View File

@@ -719,10 +719,14 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
struct iscsi_pdu *pdu;
struct iscsi_pdu *next_pdu;
time_t t = time(NULL);
uint32_t cmdsn_gap = 0;
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
next_pdu = pdu->next;
if (cmdsn_gap > 0) {
iscsi_pdu_set_cmdsn(pdu, pdu->cmdsn - cmdsn_gap);
}
if (pdu->scsi_timeout == 0) {
/* no timeout for this pdu */
continue;
@@ -731,6 +735,11 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
/* not expired yet */
continue;
}
if (!(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE) &&
(pdu->outdata.data[0] & 0x3f) != ISCSI_PDU_DATA_OUT) {
iscsi->cmdsn--;
cmdsn_gap++;
}
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
iscsi_set_error(iscsi, "command timed out");
iscsi_dump_pdu_header(iscsi, pdu->outdata.data);
@@ -775,21 +784,21 @@ iscsi_cancel_pdus(struct iscsi_context *iscsi)
while ((pdu = iscsi->outqueue)) {
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
if (iscsi->is_loggedin && pdu->callback) {
/* If an error happened during connect/login,
we don't want to call any of the callbacks.
*/
if (pdu->callback) {
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
NULL, pdu->private_data);
}
iscsi->drv->free_pdu(iscsi, pdu);
if (!(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE) &&
(pdu->outdata.data[0] & 0x3f) != ISCSI_PDU_DATA_OUT) {
iscsi->cmdsn--;
}
}
while ((pdu = iscsi->waitpdu)) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
if (iscsi->is_loggedin && pdu->callback) {
/* If an error happened during connect/login,
we don't want to call any of the callbacks.
*/
if (pdu->callback) {
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
NULL, pdu->private_data);
}

View File

@@ -913,7 +913,7 @@ iscsi_tcp_service(struct iscsi_context *iscsi, int revents)
return iscsi_reconnect(iscsi);
} else {
if (iscsi->old_iscsi) {
return 0;
goto check_timeout;
}
}
}
@@ -999,8 +999,14 @@ iscsi_tcp_service(struct iscsi_context *iscsi, int revents)
return iscsi_service_reconnect_if_loggedin(iscsi);
}
}
check_timeout:
iscsi_timeout_scan(iscsi);
if (iscsi->old_iscsi) {
iscsi_timeout_scan(iscsi->old_iscsi);
}
return 0;
}