|
@@ -560,8 +560,12 @@ static void iscsi_complete_task(struct iscsi_task *task, int state)
|
|
|
WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
|
|
|
task->state = state;
|
|
|
|
|
|
- if (!list_empty(&task->running))
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
+ if (!list_empty(&task->running)) {
|
|
|
+ pr_debug_once("%s while task on list", __func__);
|
|
|
list_del_init(&task->running);
|
|
|
+ }
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
|
|
|
if (conn->task == task)
|
|
|
conn->task = NULL;
|
|
@@ -783,7 +787,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
|
|
if (session->tt->xmit_task(task))
|
|
|
goto free_task;
|
|
|
} else {
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
list_add_tail(&task->running, &conn->mgmtqueue);
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
iscsi_conn_queue_work(conn);
|
|
|
}
|
|
|
|
|
@@ -1474,8 +1480,10 @@ void iscsi_requeue_task(struct iscsi_task *task)
|
|
|
* this may be on the requeue list already if the xmit_task callout
|
|
|
* is handling the r2ts while we are adding new ones
|
|
|
*/
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
if (list_empty(&task->running))
|
|
|
list_add_tail(&task->running, &conn->requeue);
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
iscsi_conn_queue_work(conn);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(iscsi_requeue_task);
|
|
@@ -1512,22 +1520,26 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
|
|
|
* only have one nop-out as a ping from us and targets should not
|
|
|
* overflow us with nop-ins
|
|
|
*/
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
check_mgmt:
|
|
|
while (!list_empty(&conn->mgmtqueue)) {
|
|
|
conn->task = list_entry(conn->mgmtqueue.next,
|
|
|
struct iscsi_task, running);
|
|
|
list_del_init(&conn->task->running);
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
if (iscsi_prep_mgmt_task(conn, conn->task)) {
|
|
|
/* regular RX path uses back_lock */
|
|
|
spin_lock_bh(&conn->session->back_lock);
|
|
|
__iscsi_put_task(conn->task);
|
|
|
spin_unlock_bh(&conn->session->back_lock);
|
|
|
conn->task = NULL;
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
continue;
|
|
|
}
|
|
|
rc = iscsi_xmit_task(conn);
|
|
|
if (rc)
|
|
|
goto done;
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
}
|
|
|
|
|
|
/* process pending command queue */
|
|
@@ -1535,19 +1547,24 @@ check_mgmt:
|
|
|
conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task,
|
|
|
running);
|
|
|
list_del_init(&conn->task->running);
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
|
|
|
fail_scsi_task(conn->task, DID_IMM_RETRY);
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
continue;
|
|
|
}
|
|
|
rc = iscsi_prep_scsi_cmd_pdu(conn->task);
|
|
|
if (rc) {
|
|
|
if (rc == -ENOMEM || rc == -EACCES) {
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
list_add_tail(&conn->task->running,
|
|
|
&conn->cmdqueue);
|
|
|
conn->task = NULL;
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
goto done;
|
|
|
} else
|
|
|
fail_scsi_task(conn->task, DID_ABORT);
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
continue;
|
|
|
}
|
|
|
rc = iscsi_xmit_task(conn);
|
|
@@ -1558,6 +1575,7 @@ check_mgmt:
|
|
|
* we need to check the mgmt queue for nops that need to
|
|
|
* be sent to aviod starvation
|
|
|
*/
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
if (!list_empty(&conn->mgmtqueue))
|
|
|
goto check_mgmt;
|
|
|
}
|
|
@@ -1577,12 +1595,15 @@ check_mgmt:
|
|
|
conn->task = task;
|
|
|
list_del_init(&conn->task->running);
|
|
|
conn->task->state = ISCSI_TASK_RUNNING;
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
rc = iscsi_xmit_task(conn);
|
|
|
if (rc)
|
|
|
goto done;
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
if (!list_empty(&conn->mgmtqueue))
|
|
|
goto check_mgmt;
|
|
|
}
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
spin_unlock_bh(&conn->session->frwd_lock);
|
|
|
return -ENODATA;
|
|
|
|
|
@@ -1738,7 +1759,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
|
|
|
goto prepd_reject;
|
|
|
}
|
|
|
} else {
|
|
|
+ spin_lock_bh(&conn->taskqueuelock);
|
|
|
list_add_tail(&task->running, &conn->cmdqueue);
|
|
|
+ spin_unlock_bh(&conn->taskqueuelock);
|
|
|
iscsi_conn_queue_work(conn);
|
|
|
}
|
|
|
|
|
@@ -2896,6 +2919,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size,
|
|
|
INIT_LIST_HEAD(&conn->mgmtqueue);
|
|
|
INIT_LIST_HEAD(&conn->cmdqueue);
|
|
|
INIT_LIST_HEAD(&conn->requeue);
|
|
|
+ spin_lock_init(&conn->taskqueuelock);
|
|
|
INIT_WORK(&conn->xmitwork, iscsi_xmitworker);
|
|
|
|
|
|
/* allocate login_task used for the login/text sequences */
|