From 3c11c3598b129ab0ed04ff0b81bfc3406c3d189c Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Mon, 19 Sep 2011 21:21:40 +1000 Subject: [PATCH] Add a function to cancel a scsi task from libiscsi. --- include/iscsi.h | 11 +++++++++++ lib/libiscsi.def | 1 + lib/scsi-lowlevel.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/include/iscsi.h b/include/iscsi.h index e5b835c..4582ffd 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -656,5 +656,16 @@ iscsi_synchronizecache10_sync(struct iscsi_context *iscsi, int lun, int lba, */ EXTERN int scsi_task_add_data_in_buffer(struct scsi_task *task, int len, unsigned char *buf); +/* + * This function is used when you want to cancel a iscsi task. + * The task will be immeidately cancelled and the callback for the task will + * never be invoked. + * The cancellation is only local in libiscsi. If the tast is already in-flight + * this call will not cancel the task at the target. + * To cancel the task also a the target you need to call the task management functions. + */ +EXTERN int +iscsi_scsi_task_cancel(struct iscsi_context *iscsi, + struct scsi_task *task); #endif /* __iscsi_h__ */ diff --git a/lib/libiscsi.def b/lib/libiscsi.def index 0965f63..0aae019 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -56,6 +56,7 @@ iscsi_readcapacity10_sync iscsi_synchronizecache10_sync iscsi_read6_sync iscsi_read10_sync +iscsi_task_cancel poll scsi_task_add_data_in_buffer scsi_sense_key_str diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index 2450849..0aff97a 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -1130,3 +1130,34 @@ scsi_task_get_data_in_buffer(struct scsi_task *task, uint32_t pos, ssize_t *coun return &sdb->data[pos]; } + +int +iscsi_scsi_task_cancel(struct iscsi_context *iscsi, + struct scsi_task *task) +{ + struct iscsi_pdu *pdu; + + for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) { + if (pdu->itt == task->itt) { + while(task->in_buffers != NULL) { + struct scsi_data_buffer *ptr = task->in_buffers; + SLIST_REMOVE(&task->in_buffers, ptr); + } + SLIST_REMOVE(&iscsi->waitpdu, pdu); + iscsi_free_pdu(iscsi, pdu); + return 0; + } + } + for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) { + if (pdu->itt == task->itt) { + while(task->in_buffers != NULL) { + struct scsi_data_buffer *ptr = task->in_buffers; + SLIST_REMOVE(&task->in_buffers, ptr); + } + SLIST_REMOVE(&iscsi->outqueue, pdu); + iscsi_free_pdu(iscsi, pdu); + return 0; + } + } + return -1; +}