Protect outqueue and waitpdu with a spinlock
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
@@ -170,11 +170,10 @@ struct iscsi_context {
|
|||||||
iscsi_command_cb socket_status_cb;
|
iscsi_command_cb socket_status_cb;
|
||||||
void *connect_data;
|
void *connect_data;
|
||||||
|
|
||||||
struct iscsi_pdu *outqueue; // multithreading todo: may need mutex
|
struct iscsi_pdu *outqueue; /* Protected by iscsi_lock */
|
||||||
struct iscsi_pdu *outqueue_current; // multithreading todo: may need mutex
|
struct iscsi_pdu *outqueue_current; /* Protected by iscsi_lock */
|
||||||
struct iscsi_pdu *waitpdu; // multithreading todo: may need mutex
|
struct iscsi_pdu *waitpdu; /* Protected by iscsi_lock */
|
||||||
|
struct iscsi_in_pdu *incoming; /* Protected by iscsi_lock */
|
||||||
struct iscsi_in_pdu *incoming; // multithreading todo: may need mutex
|
|
||||||
|
|
||||||
uint32_t max_burst_length;
|
uint32_t max_burst_length;
|
||||||
uint32_t first_burst_length;
|
uint32_t first_burst_length;
|
||||||
|
|||||||
+10
-3
@@ -280,6 +280,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi, int status,
|
|||||||
void *command_data, void *private_data)
|
void *command_data, void *private_data)
|
||||||
{
|
{
|
||||||
struct iscsi_context *old_iscsi;
|
struct iscsi_context *old_iscsi;
|
||||||
|
struct iscsi_pdu *tmp = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (status != SCSI_STATUS_GOOD) {
|
if (status != SCSI_STATUS_GOOD) {
|
||||||
@@ -305,16 +306,20 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi, int status,
|
|||||||
old_iscsi = iscsi->old_iscsi;
|
old_iscsi = iscsi->old_iscsi;
|
||||||
iscsi->old_iscsi = NULL;
|
iscsi->old_iscsi = NULL;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
while (old_iscsi->outqueue) {
|
while (old_iscsi->outqueue) {
|
||||||
struct iscsi_pdu *pdu = old_iscsi->outqueue;
|
struct iscsi_pdu *pdu = old_iscsi->outqueue;
|
||||||
ISCSI_LIST_REMOVE(&old_iscsi->outqueue, pdu);
|
ISCSI_LIST_REMOVE(&old_iscsi->outqueue, pdu);
|
||||||
ISCSI_LIST_ADD_END(&old_iscsi->waitpdu, pdu);
|
ISCSI_LIST_ADD_END(&old_iscsi->waitpdu, pdu);
|
||||||
}
|
}
|
||||||
|
tmp = old_iscsi->waitpdu;
|
||||||
|
old_iscsi->waitpdu = NULL;
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
while (old_iscsi->waitpdu) {
|
while (tmp) {
|
||||||
struct iscsi_pdu *pdu = old_iscsi->waitpdu;
|
struct iscsi_pdu *pdu = tmp;
|
||||||
|
|
||||||
ISCSI_LIST_REMOVE(&old_iscsi->waitpdu, pdu);
|
ISCSI_LIST_REMOVE(&tmp, pdu);
|
||||||
if (pdu->itt == 0xffffffff) {
|
if (pdu->itt == 0xffffffff) {
|
||||||
iscsi->drv->free_pdu(old_iscsi, pdu);
|
iscsi->drv->free_pdu(old_iscsi, pdu);
|
||||||
continue;
|
continue;
|
||||||
@@ -351,6 +356,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi, int status,
|
|||||||
iscsi->drv->free_pdu(old_iscsi, pdu);
|
iscsi->drv->free_pdu(old_iscsi, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
if (old_iscsi->incoming != NULL) {
|
if (old_iscsi->incoming != NULL) {
|
||||||
iscsi_free_iscsi_in_pdu(old_iscsi, old_iscsi->incoming);
|
iscsi_free_iscsi_in_pdu(old_iscsi, old_iscsi->incoming);
|
||||||
}
|
}
|
||||||
@@ -358,6 +364,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi, int status,
|
|||||||
if (old_iscsi->outqueue_current != NULL && old_iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
|
if (old_iscsi->outqueue_current != NULL && old_iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
|
||||||
iscsi->drv->free_pdu(old_iscsi, old_iscsi->outqueue_current);
|
iscsi->drv->free_pdu(old_iscsi, old_iscsi->outqueue_current);
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
iscsi_free(old_iscsi, old_iscsi->opaque);
|
iscsi_free(old_iscsi, old_iscsi->opaque);
|
||||||
|
|
||||||
|
|||||||
@@ -407,6 +407,7 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
|
|||||||
|
|
||||||
iscsi_cancel_pdus(iscsi);
|
iscsi_cancel_pdus(iscsi);
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
if (iscsi->outqueue_current != NULL && iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
|
if (iscsi->outqueue_current != NULL && iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
|
||||||
iscsi->drv->free_pdu(iscsi, iscsi->outqueue_current);
|
iscsi->drv->free_pdu(iscsi, iscsi->outqueue_current);
|
||||||
}
|
}
|
||||||
@@ -414,6 +415,7 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
|
|||||||
if (iscsi->incoming != NULL) {
|
if (iscsi->incoming != NULL) {
|
||||||
iscsi_free_iscsi_in_pdu(iscsi, iscsi->incoming);
|
iscsi_free_iscsi_in_pdu(iscsi, iscsi->incoming);
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
iscsi->connect_data = NULL;
|
iscsi->connect_data = NULL;
|
||||||
|
|
||||||
|
|||||||
+32
-16
@@ -136,8 +136,10 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
ISCSI_LIST_REMOVE(&iscsi->outqueue, cmd_pdu);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, cmd_pdu);
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, cmd_pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, cmd_pdu);
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
if (cmd_pdu->callback) {
|
if (cmd_pdu->callback) {
|
||||||
cmd_pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
|
cmd_pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
|
||||||
cmd_pdu->private_data);
|
cmd_pdu->private_data);
|
||||||
@@ -2406,11 +2408,13 @@ iscsi_get_scsi_task_iovector_in(struct iscsi_context *iscsi, struct iscsi_in_pdu
|
|||||||
}
|
}
|
||||||
|
|
||||||
itt = scsi_get_uint32(&in->hdr[16]);
|
itt = scsi_get_uint32(&in->hdr[16]);
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
||||||
if (pdu->itt == itt) {
|
if (pdu->itt == itt) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
if (pdu == NULL) {
|
if (pdu == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2669,11 +2673,14 @@ int iscsi_scsi_is_task_in_outqueue(struct iscsi_context *iscsi, struct scsi_task
|
|||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
|
||||||
if (pdu->itt == task->itt) {
|
if (pdu->itt == task->itt) {
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2682,13 +2689,15 @@ int
|
|||||||
iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
|
iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
|
||||||
struct scsi_task *task)
|
struct scsi_task *task)
|
||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu, *tmp;
|
||||||
struct iscsi_pdu *next_pdu;
|
struct iscsi_pdu *next_pdu;
|
||||||
uint32_t cmdsn_gap = 0;
|
uint32_t cmdsn_gap = 0;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
||||||
if (pdu->itt == task->itt) {
|
if (pdu->itt == task->itt) {
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
if (pdu->callback) {
|
if (pdu->callback) {
|
||||||
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
|
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
|
||||||
@@ -2698,6 +2707,8 @@ iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tmp = NULL;
|
||||||
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
|
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
|
||||||
next_pdu = pdu->next;
|
next_pdu = pdu->next;
|
||||||
|
|
||||||
@@ -2707,22 +2718,27 @@ iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
|
|||||||
|
|
||||||
if (pdu->itt == task->itt) {
|
if (pdu->itt == task->itt) {
|
||||||
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
||||||
if (pdu->callback) {
|
ISCSI_LIST_ADD_END(&tmp, pdu);
|
||||||
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
|
}
|
||||||
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
for (pdu = tmp; pdu; pdu = next_pdu) {
|
||||||
|
ISCSI_LIST_REMOVE(&tmp, pdu);
|
||||||
|
if (pdu->callback) {
|
||||||
|
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
|
||||||
pdu->private_data);
|
pdu->private_data);
|
||||||
}
|
}
|
||||||
if (!(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE) &&
|
if (!(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE) &&
|
||||||
(pdu->outdata.data[0] & 0x3f) != ISCSI_PDU_DATA_OUT) {
|
(pdu->outdata.data[0] & 0x3f) != ISCSI_PDU_DATA_OUT) {
|
||||||
iscsi->cmdsn--;
|
iscsi->cmdsn--;
|
||||||
cmdsn_gap++;
|
cmdsn_gap++;
|
||||||
}
|
}
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (!cmdsn_gap) {
|
if (!cmdsn_gap) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (iscsi->old_iscsi) {
|
if (iscsi->old_iscsi) {
|
||||||
return iscsi_scsi_cancel_task(iscsi->old_iscsi, task);
|
return iscsi_scsi_cancel_task(iscsi->old_iscsi, task);
|
||||||
|
|||||||
+16
-4
@@ -334,6 +334,7 @@ iser_free_queued_pdu_tx_desc(struct iscsi_context *iscsi)
|
|||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
struct iser_pdu *iser_pdu;
|
struct iser_pdu *iser_pdu;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
||||||
iser_pdu = container_of(pdu, struct iser_pdu, iscsi_pdu);
|
iser_pdu = container_of(pdu, struct iser_pdu, iscsi_pdu);
|
||||||
if (iser_pdu->desc) {
|
if (iser_pdu->desc) {
|
||||||
@@ -349,6 +350,7 @@ iser_free_queued_pdu_tx_desc(struct iscsi_context *iscsi)
|
|||||||
iser_pdu->desc = NULL;
|
iser_pdu->desc = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -576,9 +578,11 @@ iscsi_iser_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
|||||||
|
|
||||||
pdu->indata.data = NULL;
|
pdu->indata.data = NULL;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
if (iscsi->outqueue_current == pdu) {
|
if (iscsi->outqueue_current == pdu) {
|
||||||
iscsi->outqueue_current = NULL;
|
iscsi->outqueue_current = NULL;
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
iscsi_sfree(iscsi, iser_pdu);
|
iscsi_sfree(iscsi, iser_pdu);
|
||||||
}
|
}
|
||||||
@@ -920,8 +924,10 @@ iscsi_iser_send_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) {
|
|||||||
iser_pdu = container_of(pdu, struct iser_pdu, iscsi_pdu);
|
iser_pdu = container_of(pdu, struct iser_pdu, iscsi_pdu);
|
||||||
opcode = pdu->outdata.data[0];
|
opcode = pdu->outdata.data[0];
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn + 1);
|
iscsi_pdu_set_expstatsn(pdu, iscsi->statsn + 1);
|
||||||
ISCSI_LIST_ADD_END(&iscsi->waitpdu, pdu);
|
ISCSI_LIST_ADD_END(&iscsi->waitpdu, pdu);
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* because of async reconnection, before reconnecting successfully,
|
* because of async reconnection, before reconnecting successfully,
|
||||||
@@ -954,16 +960,20 @@ static int
|
|||||||
iscsi_iser_revive_queued_pdus(struct iscsi_context *iscsi) {
|
iscsi_iser_revive_queued_pdus(struct iscsi_context *iscsi) {
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
|
|
||||||
while (iscsi->outqueue != NULL) {
|
while (iscsi->outqueue) {
|
||||||
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) > 0) {
|
if (iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) > 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
pdu = iscsi->outqueue;
|
pdu = iscsi->outqueue;
|
||||||
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
if (iscsi_iser_send_pdu(iscsi, pdu) < 0) {
|
if (iscsi_iser_send_pdu(iscsi, pdu) < 0) {
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
ISCSI_LIST_ADD(&iscsi->outqueue, pdu);
|
ISCSI_LIST_ADD(&iscsi->outqueue, pdu);
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -995,7 +1005,7 @@ iscsi_iser_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iscsi->outqueue != NULL ||
|
if (iscsi->outqueue ||
|
||||||
(iscsi_serial32_compare(pdu->cmdsn, iscsi->maxcmdsn) > 0
|
(iscsi_serial32_compare(pdu->cmdsn, iscsi->maxcmdsn) > 0
|
||||||
&& !(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE))) {
|
&& !(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE))) {
|
||||||
iscsi_add_to_outqueue(iscsi, pdu);
|
iscsi_add_to_outqueue(iscsi, pdu);
|
||||||
@@ -1308,6 +1318,8 @@ iser_rcv_completion(struct iser_rx_desc *rx_desc,
|
|||||||
struct iscsi_in_pdu in;
|
struct iscsi_in_pdu in;
|
||||||
int empty, err;
|
int empty, err;
|
||||||
struct iscsi_context *iscsi = iser_conn->cma_id->context;
|
struct iscsi_context *iscsi = iser_conn->cma_id->context;
|
||||||
|
struct iscsi_pdu *iscsi_pdu;
|
||||||
|
struct iser_pdu *iser_pdu;
|
||||||
|
|
||||||
in.hdr = (unsigned char*)rx_desc->iscsi_header;
|
in.hdr = (unsigned char*)rx_desc->iscsi_header;
|
||||||
in.data_pos = iscsi_get_pdu_data_size(&in.hdr[0]);
|
in.data_pos = iscsi_get_pdu_data_size(&in.hdr[0]);
|
||||||
@@ -1322,12 +1334,12 @@ iser_rcv_completion(struct iser_rx_desc *rx_desc,
|
|||||||
if (opcode == ISCSI_PDU_ASYNC_MSG)
|
if (opcode == ISCSI_PDU_ASYNC_MSG)
|
||||||
goto no_waitpdu;
|
goto no_waitpdu;
|
||||||
|
|
||||||
struct iscsi_pdu *iscsi_pdu;
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
struct iser_pdu *iser_pdu;
|
|
||||||
for (iscsi_pdu = iscsi->waitpdu ; iscsi_pdu ; iscsi_pdu = iscsi_pdu->next) {
|
for (iscsi_pdu = iscsi->waitpdu ; iscsi_pdu ; iscsi_pdu = iscsi_pdu->next) {
|
||||||
if(iscsi_pdu->itt == itt)
|
if(iscsi_pdu->itt == itt)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
iser_pdu = container_of(iscsi_pdu, struct iser_pdu, iscsi_pdu);
|
iser_pdu = container_of(iscsi_pdu, struct iser_pdu, iscsi_pdu);
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ iscsi_process_nop_out_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
|||||||
{
|
{
|
||||||
struct iscsi_data data;
|
struct iscsi_data data;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6,
|
ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6,
|
||||||
"NOP-In received (pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x, iscsi->statsn %08x)",
|
"NOP-In received (pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x, iscsi->statsn %08x)",
|
||||||
pdu->itt, 0xffffffff, iscsi->maxcmdsn, iscsi->expcmdsn, iscsi->statsn);
|
pdu->itt, 0xffffffff, iscsi->maxcmdsn, iscsi->expcmdsn, iscsi->statsn);
|
||||||
@@ -147,6 +148,7 @@ iscsi_process_nop_out_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
|
|||||||
iscsi->nops_in_flight = 0;
|
iscsi->nops_in_flight = 0;
|
||||||
}
|
}
|
||||||
iscsi->min_cmdsn_waiting = iscsi->waitpdu->cmdsn;
|
iscsi->min_cmdsn_waiting = iscsi->waitpdu->cmdsn;
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
if (pdu->callback == NULL) {
|
if (pdu->callback == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -458,11 +458,13 @@ int iscsi_process_reject(struct iscsi_context *iscsi,
|
|||||||
|
|
||||||
iscsi_dump_pdu_header(iscsi, in->data);
|
iscsi_dump_pdu_header(iscsi, in->data);
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
||||||
if (pdu->itt == itt) {
|
if (pdu->itt == itt) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
if (pdu == NULL) {
|
if (pdu == NULL) {
|
||||||
iscsi_set_error(iscsi, "Can not match REJECT with"
|
iscsi_set_error(iscsi, "Can not match REJECT with"
|
||||||
@@ -476,7 +478,9 @@ int iscsi_process_reject(struct iscsi_context *iscsi,
|
|||||||
pdu->private_data);
|
pdu->private_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -525,6 +529,8 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
|
|||||||
enum iscsi_opcode opcode = in->hdr[0] & 0x3f;
|
enum iscsi_opcode opcode = in->hdr[0] & 0x3f;
|
||||||
uint8_t ahslen = in->hdr[4];
|
uint8_t ahslen = in->hdr[4];
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
|
enum iscsi_opcode expected_response;
|
||||||
|
int is_finished = 1;
|
||||||
|
|
||||||
/* verify header checksum */
|
/* verify header checksum */
|
||||||
if (iscsi->header_digest != ISCSI_HEADER_DIGEST_NONE) {
|
if (iscsi->header_digest != ISCSI_HEADER_DIGEST_NONE) {
|
||||||
@@ -623,125 +629,148 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
|
||||||
enum iscsi_opcode expected_response = pdu->response_opcode;
|
if (pdu->itt == itt) {
|
||||||
int is_finished = 1;
|
break;
|
||||||
|
|
||||||
if (pdu->itt != itt) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
if (pdu == NULL) {
|
||||||
|
iscsi_set_error(iscsi, "Got unsolicited response with "
|
||||||
|
"itt:%d",
|
||||||
|
itt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* we have a special case with scsi-command opcodes,
|
/* we have a special case with scsi-command opcodes,
|
||||||
* they are replied to by either a scsi-response
|
* they are replied to by either a scsi-response
|
||||||
* or a data-in, or a combination of both.
|
* or a data-in, or a combination of both.
|
||||||
*/
|
*/
|
||||||
if (opcode == ISCSI_PDU_DATA_IN
|
expected_response = pdu->response_opcode;
|
||||||
&& expected_response == ISCSI_PDU_SCSI_RESPONSE) {
|
if (opcode == ISCSI_PDU_DATA_IN
|
||||||
expected_response = ISCSI_PDU_DATA_IN;
|
&& expected_response == ISCSI_PDU_SCSI_RESPONSE) {
|
||||||
}
|
expected_response = ISCSI_PDU_DATA_IN;
|
||||||
|
}
|
||||||
|
|
||||||
/* Another special case is if we get a R2T.
|
/* Another special case is if we get a R2T.
|
||||||
* In this case we should find the original request and just send an additional
|
* In this case we should find the original request and just send an additional
|
||||||
* DATAOUT segment for this task.
|
* DATAOUT segment for this task.
|
||||||
*/
|
*/
|
||||||
if (opcode == ISCSI_PDU_R2T) {
|
if (opcode == ISCSI_PDU_R2T) {
|
||||||
expected_response = ISCSI_PDU_R2T;
|
expected_response = ISCSI_PDU_R2T;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode != expected_response) {
|
if (opcode != expected_response) {
|
||||||
iscsi_set_error(iscsi, "Got wrong opcode back for "
|
iscsi_set_error(iscsi, "Got wrong opcode back for "
|
||||||
"itt:%d got:%d expected %d",
|
"itt:%d got:%d expected %d",
|
||||||
itt, opcode, pdu->response_opcode);
|
itt, opcode, pdu->response_opcode);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case ISCSI_PDU_LOGIN_RESPONSE:
|
case ISCSI_PDU_LOGIN_RESPONSE:
|
||||||
if (iscsi_process_login_reply(iscsi, pdu, in) != 0) {
|
if (iscsi_process_login_reply(iscsi, pdu, in) != 0) {
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
iscsi_set_error(iscsi, "iscsi login reply "
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
"failed");
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
return -1;
|
iscsi_set_error(iscsi, "iscsi login reply "
|
||||||
}
|
"failed");
|
||||||
break;
|
return -1;
|
||||||
case ISCSI_PDU_TEXT_RESPONSE:
|
}
|
||||||
if (iscsi_process_text_reply(iscsi, pdu, in) != 0) {
|
break;
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
case ISCSI_PDU_TEXT_RESPONSE:
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
if (iscsi_process_text_reply(iscsi, pdu, in) != 0) {
|
||||||
iscsi_set_error(iscsi, "iscsi text reply "
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
"failed");
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
return -1;
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
}
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
break;
|
iscsi_set_error(iscsi, "iscsi text reply "
|
||||||
case ISCSI_PDU_LOGOUT_RESPONSE:
|
"failed");
|
||||||
if (iscsi_process_logout_reply(iscsi, pdu, in) != 0) {
|
return -1;
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
}
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
break;
|
||||||
iscsi_set_error(iscsi, "iscsi logout reply "
|
case ISCSI_PDU_LOGOUT_RESPONSE:
|
||||||
"failed");
|
if (iscsi_process_logout_reply(iscsi, pdu, in) != 0) {
|
||||||
return -1;
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
}
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
break;
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
case ISCSI_PDU_SCSI_RESPONSE:
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
if (iscsi_process_scsi_reply(iscsi, pdu, in) != 0) {
|
iscsi_set_error(iscsi, "iscsi logout reply "
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
"failed");
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
return -1;
|
||||||
iscsi_set_error(iscsi, "iscsi response reply "
|
}
|
||||||
"failed");
|
break;
|
||||||
return -1;
|
case ISCSI_PDU_SCSI_RESPONSE:
|
||||||
}
|
if (iscsi_process_scsi_reply(iscsi, pdu, in) != 0) {
|
||||||
break;
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
case ISCSI_PDU_DATA_IN:
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
if (iscsi_process_scsi_data_in(iscsi, pdu, in,
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
&is_finished) != 0) {
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
iscsi_set_error(iscsi, "iscsi response reply "
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
"failed");
|
||||||
iscsi_set_error(iscsi, "iscsi data in "
|
return -1;
|
||||||
"failed");
|
}
|
||||||
return -1;
|
break;
|
||||||
}
|
case ISCSI_PDU_DATA_IN:
|
||||||
break;
|
if (iscsi_process_scsi_data_in(iscsi, pdu, in,
|
||||||
case ISCSI_PDU_NOP_IN:
|
&is_finished) != 0) {
|
||||||
if (iscsi_process_nop_out_reply(iscsi, pdu, in) != 0) {
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
iscsi_set_error(iscsi, "iscsi nop-in failed");
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
return -1;
|
iscsi_set_error(iscsi, "iscsi data in "
|
||||||
}
|
"failed");
|
||||||
break;
|
return -1;
|
||||||
case ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE:
|
}
|
||||||
if (iscsi_process_task_mgmt_reply(iscsi, pdu,
|
break;
|
||||||
in) != 0) {
|
case ISCSI_PDU_NOP_IN:
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
if (iscsi_process_nop_out_reply(iscsi, pdu, in) != 0) {
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
iscsi_set_error(iscsi, "iscsi task-mgmt failed");
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
return -1;
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
}
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
break;
|
iscsi_set_error(iscsi, "iscsi nop-in failed");
|
||||||
case ISCSI_PDU_R2T:
|
return -1;
|
||||||
if (iscsi_process_r2t(iscsi, pdu, in) != 0) {
|
}
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
break;
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
case ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE:
|
||||||
iscsi_set_error(iscsi, "iscsi r2t "
|
if (iscsi_process_task_mgmt_reply(iscsi, pdu,
|
||||||
"failed");
|
in) != 0) {
|
||||||
return -1;
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
}
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
is_finished = 0;
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
break;
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
default:
|
iscsi_set_error(iscsi, "iscsi task-mgmt failed");
|
||||||
iscsi_set_error(iscsi, "Don't know how to handle "
|
return -1;
|
||||||
"opcode 0x%02x", opcode);
|
}
|
||||||
return -1;
|
break;
|
||||||
}
|
case ISCSI_PDU_R2T:
|
||||||
|
if (iscsi_process_r2t(iscsi, pdu, in) != 0) {
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
|
iscsi_set_error(iscsi, "iscsi r2t "
|
||||||
|
"failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
is_finished = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
iscsi_set_error(iscsi, "Don't know how to handle "
|
||||||
|
"opcode 0x%02x", opcode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_finished && iscsi->waitpdu != NULL) {
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
if (is_finished && iscsi->waitpdu != NULL) {
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
}
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
return 0;
|
}
|
||||||
}
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -842,6 +871,7 @@ static int iscsi_pdu_data_out_inprocess(struct iscsi_context *iscsi, struct iscs
|
|||||||
{
|
{
|
||||||
struct iscsi_pdu *tmp_pdu, *next_pdu;
|
struct iscsi_pdu *tmp_pdu, *next_pdu;
|
||||||
enum scsi_opcode opcode = pdu->outdata.data[32];
|
enum scsi_opcode opcode = pdu->outdata.data[32];
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
/* only care DATA OUT command here */
|
/* only care DATA OUT command here */
|
||||||
if ((pdu->outdata.data[0] & 0x3f) != ISCSI_PDU_SCSI_REQUEST) {
|
if ((pdu->outdata.data[0] & 0x3f) != ISCSI_PDU_SCSI_REQUEST) {
|
||||||
@@ -857,9 +887,10 @@ static int iscsi_pdu_data_out_inprocess(struct iscsi_context *iscsi, struct iscs
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
/* current outgoing one is part of the PDU? */
|
/* current outgoing one is part of the PDU? */
|
||||||
if (iscsi->outqueue_current && (iscsi->outqueue_current->scsi_cbdata.task == pdu->scsi_cbdata.task)) {
|
if (iscsi->outqueue_current && (iscsi->outqueue_current->scsi_cbdata.task == pdu->scsi_cbdata.task)) {
|
||||||
return 1;
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* any child DATAOUT PDU in outqueue? */
|
/* any child DATAOUT PDU in outqueue? */
|
||||||
@@ -867,21 +898,26 @@ static int iscsi_pdu_data_out_inprocess(struct iscsi_context *iscsi, struct iscs
|
|||||||
next_pdu = tmp_pdu->next;
|
next_pdu = tmp_pdu->next;
|
||||||
|
|
||||||
if (tmp_pdu->scsi_cbdata.task == pdu->scsi_cbdata.task) {
|
if (tmp_pdu->scsi_cbdata.task == pdu->scsi_cbdata.task) {
|
||||||
return 1;
|
goto finished;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ret = 0;
|
||||||
|
finished:
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
iscsi_timeout_scan(struct iscsi_context *iscsi)
|
iscsi_timeout_scan(struct iscsi_context *iscsi)
|
||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu, *tmp;
|
||||||
struct iscsi_pdu *next_pdu;
|
struct iscsi_pdu *next_pdu;
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
uint32_t cmdsn_gap = 0;
|
uint32_t cmdsn_gap = 0;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
|
tmp = NULL;
|
||||||
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
|
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
|
||||||
next_pdu = pdu->next;
|
next_pdu = pdu->next;
|
||||||
|
|
||||||
@@ -904,6 +940,11 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
||||||
|
ISCSI_LIST_ADD_END(&tmp, pdu);
|
||||||
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
for (pdu = tmp; pdu; pdu = next_pdu) {
|
||||||
|
ISCSI_LIST_REMOVE(&tmp, pdu);
|
||||||
iscsi_set_error(iscsi, "command timed out from outqueue");
|
iscsi_set_error(iscsi, "command timed out from outqueue");
|
||||||
iscsi_dump_pdu_header(iscsi, pdu->outdata.data);
|
iscsi_dump_pdu_header(iscsi, pdu->outdata.data);
|
||||||
if (pdu->callback) {
|
if (pdu->callback) {
|
||||||
@@ -912,6 +953,9 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
|
|||||||
}
|
}
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
|
tmp = NULL;
|
||||||
for (pdu = iscsi->waitpdu; pdu; pdu = next_pdu) {
|
for (pdu = iscsi->waitpdu; pdu; pdu = next_pdu) {
|
||||||
next_pdu = pdu->next;
|
next_pdu = pdu->next;
|
||||||
|
|
||||||
@@ -927,6 +971,11 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
|
ISCSI_LIST_ADD_END(&tmp, pdu);
|
||||||
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
for (pdu = tmp; pdu; pdu = next_pdu) {
|
||||||
|
ISCSI_LIST_REMOVE(&tmp, pdu);
|
||||||
iscsi_set_error(iscsi, "command timed out from waitqueue");
|
iscsi_set_error(iscsi, "command timed out from waitqueue");
|
||||||
iscsi_dump_pdu_header(iscsi, pdu->outdata.data);
|
iscsi_dump_pdu_header(iscsi, pdu->outdata.data);
|
||||||
if (pdu->callback) {
|
if (pdu->callback) {
|
||||||
@@ -946,8 +995,9 @@ iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
|||||||
void
|
void
|
||||||
iscsi_cancel_pdus(struct iscsi_context *iscsi)
|
iscsi_cancel_pdus(struct iscsi_context *iscsi)
|
||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu, *tmp;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
while ((pdu = iscsi->outqueue)) {
|
while ((pdu = iscsi->outqueue)) {
|
||||||
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
||||||
if (pdu->callback) {
|
if (pdu->callback) {
|
||||||
@@ -960,8 +1010,12 @@ iscsi_cancel_pdus(struct iscsi_context *iscsi)
|
|||||||
}
|
}
|
||||||
iscsi->drv->free_pdu(iscsi, pdu);
|
iscsi->drv->free_pdu(iscsi, pdu);
|
||||||
}
|
}
|
||||||
while ((pdu = iscsi->waitpdu)) {
|
tmp = iscsi->waitpdu;
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
iscsi->waitpdu = NULL;
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
|
while ((pdu = tmp)) {
|
||||||
|
ISCSI_LIST_REMOVE(&tmp, pdu);
|
||||||
if (pdu->callback) {
|
if (pdu->callback) {
|
||||||
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
|
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
|
||||||
NULL, pdu->private_data);
|
NULL, pdu->private_data);
|
||||||
@@ -973,11 +1027,13 @@ iscsi_cancel_pdus(struct iscsi_context *iscsi)
|
|||||||
void
|
void
|
||||||
iscsi_cancel_lun_pdus(struct iscsi_context *iscsi, uint32_t lun)
|
iscsi_cancel_lun_pdus(struct iscsi_context *iscsi, uint32_t lun)
|
||||||
{
|
{
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu, *tmp;
|
||||||
struct iscsi_pdu *next_pdu;
|
struct iscsi_pdu *next_pdu;
|
||||||
uint32_t cmdsn_gap = 0;
|
uint32_t cmdsn_gap = 0;
|
||||||
struct scsi_task * task = NULL;
|
struct scsi_task * task = NULL;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
|
tmp = NULL;
|
||||||
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
|
for (pdu = iscsi->outqueue; pdu; pdu = next_pdu) {
|
||||||
next_pdu = pdu->next;
|
next_pdu = pdu->next;
|
||||||
task = iscsi_scsi_get_task_from_pdu(pdu);
|
task = iscsi_scsi_get_task_from_pdu(pdu);
|
||||||
@@ -994,6 +1050,11 @@ iscsi_cancel_lun_pdus(struct iscsi_context *iscsi, uint32_t lun)
|
|||||||
cmdsn_gap++;
|
cmdsn_gap++;
|
||||||
}
|
}
|
||||||
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
||||||
|
ISCSI_LIST_ADD_END(&tmp, pdu);
|
||||||
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
for (pdu = tmp; pdu; pdu = next_pdu) {
|
||||||
|
ISCSI_LIST_REMOVE(&tmp, pdu);
|
||||||
iscsi_set_error(iscsi, "command cancelled");
|
iscsi_set_error(iscsi, "command cancelled");
|
||||||
if (pdu->callback) {
|
if (pdu->callback) {
|
||||||
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
|
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
|
||||||
|
|||||||
+19
-9
@@ -101,7 +101,7 @@ iscsi_add_to_outqueue(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
|||||||
pdu->scsi_timeout = 0;
|
pdu->scsi_timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
iscsi_mt_mutex_lock(&iscsi->iscsi_mutex);
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
current = iscsi->outqueue;
|
current = iscsi->outqueue;
|
||||||
if (iscsi->outqueue == NULL) {
|
if (iscsi->outqueue == NULL) {
|
||||||
@@ -133,22 +133,22 @@ iscsi_add_to_outqueue(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
|
|||||||
(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE && !(current->outdata.data[0] & ISCSI_PDU_IMMEDIATE))) {
|
(pdu->outdata.data[0] & ISCSI_PDU_IMMEDIATE && !(current->outdata.data[0] & ISCSI_PDU_IMMEDIATE))) {
|
||||||
/* insert PDU before the current */
|
/* insert PDU before the current */
|
||||||
if (last != NULL) {
|
if (last != NULL) {
|
||||||
last->next=pdu;
|
last->next = pdu;
|
||||||
} else {
|
} else {
|
||||||
iscsi->outqueue=pdu;
|
iscsi->outqueue = pdu;
|
||||||
}
|
}
|
||||||
pdu->next = current;
|
pdu->next = current;
|
||||||
goto finished;
|
goto finished;
|
||||||
}
|
}
|
||||||
last=current;
|
last = current;
|
||||||
current=current->next;
|
current = current->next;
|
||||||
} while (current != NULL);
|
} while (current != NULL);
|
||||||
|
|
||||||
last->next = pdu;
|
last->next = pdu;
|
||||||
pdu->next = NULL;
|
pdu->next = NULL;
|
||||||
|
|
||||||
finished:
|
finished:
|
||||||
iscsi_mt_mutex_unlock(&iscsi->iscsi_mutex);
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
/* TODO QQQ need to immediately send for the non multithreading case too
|
/* TODO QQQ need to immediately send for the non multithreading case too
|
||||||
* and for the Windows API too */
|
* and for the Windows API too */
|
||||||
@@ -491,14 +491,16 @@ iscsi_tcp_which_events(struct iscsi_context *iscsi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iscsi->outqueue_current != NULL ||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
(iscsi->outqueue != NULL && !iscsi->is_corked &&
|
if (iscsi->outqueue_current ||
|
||||||
|
(iscsi->outqueue && !iscsi->is_corked &&
|
||||||
(iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) <= 0 ||
|
(iscsi_serial32_compare(iscsi->outqueue->cmdsn, iscsi->maxcmdsn) <= 0 ||
|
||||||
iscsi->outqueue->outdata.data[0] & ISCSI_PDU_IMMEDIATE)
|
iscsi->outqueue->outdata.data[0] & ISCSI_PDU_IMMEDIATE)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
events |= POLLOUT;
|
events |= POLLOUT;
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,6 +516,7 @@ iscsi_queue_length(struct iscsi_context *iscsi)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -523,6 +526,7 @@ iscsi_queue_length(struct iscsi_context *iscsi)
|
|||||||
if (iscsi->is_connected == 0) {
|
if (iscsi->is_connected == 0) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@@ -533,9 +537,11 @@ iscsi_out_queue_length(struct iscsi_context *iscsi)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
struct iscsi_pdu *pdu;
|
struct iscsi_pdu *pdu;
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
|
for (pdu = iscsi->outqueue; pdu; pdu = pdu->next) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@@ -830,7 +836,7 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (iscsi->outqueue != NULL || iscsi->outqueue_current != NULL) {
|
while (iscsi->outqueue || iscsi->outqueue_current) {
|
||||||
if (iscsi->outqueue_current == NULL) {
|
if (iscsi->outqueue_current == NULL) {
|
||||||
if (iscsi->is_corked) {
|
if (iscsi->is_corked) {
|
||||||
/* connection is corked we are not allowed to send
|
/* connection is corked we are not allowed to send
|
||||||
@@ -855,6 +861,8 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
|
|||||||
iscsi->outqueue->cmdsn, iscsi->expcmdsn, iscsi->outqueue->outdata.data[0] & 0x3f);
|
iscsi->outqueue->cmdsn, iscsi->expcmdsn, iscsi->outqueue->outdata.data[0] & 0x3f);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
iscsi->outqueue_current = iscsi->outqueue;
|
iscsi->outqueue_current = iscsi->outqueue;
|
||||||
|
|
||||||
/* set exp statsn */
|
/* set exp statsn */
|
||||||
@@ -863,6 +871,7 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
|
|||||||
/* calculate header checksum */
|
/* calculate header checksum */
|
||||||
if (iscsi->header_digest != ISCSI_HEADER_DIGEST_NONE &&
|
if (iscsi->header_digest != ISCSI_HEADER_DIGEST_NONE &&
|
||||||
iscsi_pdu_update_headerdigest(iscsi, iscsi->outqueue_current) != 0) {
|
iscsi_pdu_update_headerdigest(iscsi, iscsi->outqueue_current) != 0) {
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,6 +883,7 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
|
|||||||
cmd PDU the R2T might get lost otherwise. */
|
cmd PDU the R2T might get lost otherwise. */
|
||||||
ISCSI_LIST_ADD_END(&iscsi->waitpdu, iscsi->outqueue_current);
|
ISCSI_LIST_ADD_END(&iscsi->waitpdu, iscsi->outqueue_current);
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
pdu = iscsi->outqueue_current;
|
pdu = iscsi->outqueue_current;
|
||||||
|
|||||||
@@ -561,6 +561,7 @@ wait_until_test_finished(struct iscsi_context *iscsi, struct iscsi_async_state *
|
|||||||
state->finished = 1;
|
state->finished = 1;
|
||||||
state->status = SCSI_STATUS_CANCELLED;
|
state->status = SCSI_STATUS_CANCELLED;
|
||||||
state->task->status = SCSI_STATUS_CANCELLED;
|
state->task->status = SCSI_STATUS_CANCELLED;
|
||||||
|
iscsi_mt_spin_lock(&iscsi->iscsi_lock);
|
||||||
/* this may leak memory since we don't free the pdu */
|
/* this may leak memory since we don't free the pdu */
|
||||||
while ((pdu = iscsi->outqueue)) {
|
while ((pdu = iscsi->outqueue)) {
|
||||||
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
|
||||||
@@ -568,6 +569,7 @@ wait_until_test_finished(struct iscsi_context *iscsi, struct iscsi_async_state *
|
|||||||
while ((pdu = iscsi->waitpdu)) {
|
while ((pdu = iscsi->waitpdu)) {
|
||||||
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
|
||||||
}
|
}
|
||||||
|
iscsi_mt_spin_unlock(&iscsi->iscsi_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user