libiscsi: Avoid discontinuities in cmdsn ordering in some cases

We should plug the cmdsn gap in order to continue
to use the session when the pdus is cancelled before
sending out.

Signed-off-by: Xie Yongji <xieyongji@bytedance.com>
This commit is contained in:
Xie Yongji
2020-06-02 20:15:50 +08:00
parent 7258fbfd83
commit 10868c491d
3 changed files with 39 additions and 5 deletions

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);
@@ -783,6 +792,12 @@ iscsi_cancel_pdus(struct iscsi_context *iscsi)
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);