diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 63ea17d..4a06658 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -304,6 +304,7 @@ void iscsi_pdu_set_ritt(struct iscsi_pdu *pdu, uint32_t ritt); void iscsi_pdu_set_datasn(struct iscsi_pdu *pdu, uint32_t datasn); void iscsi_pdu_set_bufferoffset(struct iscsi_pdu *pdu, uint32_t bufferoffset); void iscsi_cancel_pdus(struct iscsi_context *iscsi); +void iscsi_cancel_lun_pdus(struct iscsi_context *iscsi, uint32_t lun); int iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, const unsigned char *dptr, int dsize); int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); diff --git a/lib/pdu.c b/lib/pdu.c index 3ef9871..be0a646 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -969,3 +969,36 @@ iscsi_cancel_pdus(struct iscsi_context *iscsi) iscsi->drv->free_pdu(iscsi, pdu); } } + +void +iscsi_cancel_lun_pdus(struct iscsi_context *iscsi, uint32_t lun) +{ + struct iscsi_pdu *pdu; + struct iscsi_pdu *next_pdu; + uint32_t cmdsn_gap = 0; + struct scsi_task * task = NULL; + + for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) { + next_pdu = pdu->next; + task = iscsi_scsi_get_task_from_pdu(pdu); + + if (cmdsn_gap > 0) { + iscsi_pdu_set_cmdsn(pdu, pdu->cmdsn - cmdsn_gap); + } + if (task == NULL || task->lun != lun) { + 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 cancelled"); + if (pdu->callback) { + pdu->callback(iscsi, SCSI_STATUS_CANCELLED, + NULL, pdu->private_data); + } + iscsi->drv->free_pdu(iscsi, pdu); + } +} diff --git a/lib/task_mgmt.c b/lib/task_mgmt.c index b0ad251..f3e6824 100644 --- a/lib/task_mgmt.c +++ b/lib/task_mgmt.c @@ -130,7 +130,7 @@ iscsi_task_mgmt_lun_reset_async(struct iscsi_context *iscsi, uint32_t lun, iscsi_command_cb cb, void *private_data) { - iscsi_scsi_cancel_all_tasks(iscsi); + iscsi_cancel_lun_pdus(iscsi, lun); return iscsi_task_mgmt_async(iscsi, lun, ISCSI_TM_LUN_RESET,