Merge pull request #332 from bytedance/fix_cancellation_handling
Fix cancellation handling
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)",
|
||||
|
||||
25
lib/pdu.c
25
lib/pdu.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user