diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 07c08ce68d70..894b1e3ebd56 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -561,8 +561,12 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) | |||
561 | WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); | 561 | WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); |
562 | task->state = state; | 562 | task->state = state; |
563 | 563 | ||
564 | if (!list_empty(&task->running)) | 564 | spin_lock_bh(&conn->taskqueuelock); |
565 | if (!list_empty(&task->running)) { | ||
566 | pr_debug_once("%s while task on list", __func__); | ||
565 | list_del_init(&task->running); | 567 | list_del_init(&task->running); |
568 | } | ||
569 | spin_unlock_bh(&conn->taskqueuelock); | ||
566 | 570 | ||
567 | if (conn->task == task) | 571 | if (conn->task == task) |
568 | conn->task = NULL; | 572 | conn->task = NULL; |
@@ -784,7 +788,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
784 | if (session->tt->xmit_task(task)) | 788 | if (session->tt->xmit_task(task)) |
785 | goto free_task; | 789 | goto free_task; |
786 | } else { | 790 | } else { |
791 | spin_lock_bh(&conn->taskqueuelock); | ||
787 | list_add_tail(&task->running, &conn->mgmtqueue); | 792 | list_add_tail(&task->running, &conn->mgmtqueue); |
793 | spin_unlock_bh(&conn->taskqueuelock); | ||
788 | iscsi_conn_queue_work(conn); | 794 | iscsi_conn_queue_work(conn); |
789 | } | 795 | } |
790 | 796 | ||
@@ -1475,8 +1481,10 @@ void iscsi_requeue_task(struct iscsi_task *task) | |||
1475 | * this may be on the requeue list already if the xmit_task callout | 1481 | * this may be on the requeue list already if the xmit_task callout |
1476 | * is handling the r2ts while we are adding new ones | 1482 | * is handling the r2ts while we are adding new ones |
1477 | */ | 1483 | */ |
1484 | spin_lock_bh(&conn->taskqueuelock); | ||
1478 | if (list_empty(&task->running)) | 1485 | if (list_empty(&task->running)) |
1479 | list_add_tail(&task->running, &conn->requeue); | 1486 | list_add_tail(&task->running, &conn->requeue); |
1487 | spin_unlock_bh(&conn->taskqueuelock); | ||
1480 | iscsi_conn_queue_work(conn); | 1488 | iscsi_conn_queue_work(conn); |
1481 | } | 1489 | } |
1482 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); | 1490 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); |
@@ -1513,22 +1521,26 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
1513 | * only have one nop-out as a ping from us and targets should not | 1521 | * only have one nop-out as a ping from us and targets should not |
1514 | * overflow us with nop-ins | 1522 | * overflow us with nop-ins |
1515 | */ | 1523 | */ |
1524 | spin_lock_bh(&conn->taskqueuelock); | ||
1516 | check_mgmt: | 1525 | check_mgmt: |
1517 | while (!list_empty(&conn->mgmtqueue)) { | 1526 | while (!list_empty(&conn->mgmtqueue)) { |
1518 | conn->task = list_entry(conn->mgmtqueue.next, | 1527 | conn->task = list_entry(conn->mgmtqueue.next, |
1519 | struct iscsi_task, running); | 1528 | struct iscsi_task, running); |
1520 | list_del_init(&conn->task->running); | 1529 | list_del_init(&conn->task->running); |
1530 | spin_unlock_bh(&conn->taskqueuelock); | ||
1521 | if (iscsi_prep_mgmt_task(conn, conn->task)) { | 1531 | if (iscsi_prep_mgmt_task(conn, conn->task)) { |
1522 | /* regular RX path uses back_lock */ | 1532 | /* regular RX path uses back_lock */ |
1523 | spin_lock_bh(&conn->session->back_lock); | 1533 | spin_lock_bh(&conn->session->back_lock); |
1524 | __iscsi_put_task(conn->task); | 1534 | __iscsi_put_task(conn->task); |
1525 | spin_unlock_bh(&conn->session->back_lock); | 1535 | spin_unlock_bh(&conn->session->back_lock); |
1526 | conn->task = NULL; | 1536 | conn->task = NULL; |
1537 | spin_lock_bh(&conn->taskqueuelock); | ||
1527 | continue; | 1538 | continue; |
1528 | } | 1539 | } |
1529 | rc = iscsi_xmit_task(conn); | 1540 | rc = iscsi_xmit_task(conn); |
1530 | if (rc) | 1541 | if (rc) |
1531 | goto done; | 1542 | goto done; |
1543 | spin_lock_bh(&conn->taskqueuelock); | ||
1532 | } | 1544 | } |
1533 | 1545 | ||
1534 | /* process pending command queue */ | 1546 | /* process pending command queue */ |
@@ -1536,19 +1548,24 @@ check_mgmt: | |||
1536 | conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task, | 1548 | conn->task = list_entry(conn->cmdqueue.next, struct iscsi_task, |
1537 | running); | 1549 | running); |
1538 | list_del_init(&conn->task->running); | 1550 | list_del_init(&conn->task->running); |
1551 | spin_unlock_bh(&conn->taskqueuelock); | ||
1539 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1552 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { |
1540 | fail_scsi_task(conn->task, DID_IMM_RETRY); | 1553 | fail_scsi_task(conn->task, DID_IMM_RETRY); |
1554 | spin_lock_bh(&conn->taskqueuelock); | ||
1541 | continue; | 1555 | continue; |
1542 | } | 1556 | } |
1543 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); | 1557 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); |
1544 | if (rc) { | 1558 | if (rc) { |
1545 | if (rc == -ENOMEM || rc == -EACCES) { | 1559 | if (rc == -ENOMEM || rc == -EACCES) { |
1560 | spin_lock_bh(&conn->taskqueuelock); | ||
1546 | list_add_tail(&conn->task->running, | 1561 | list_add_tail(&conn->task->running, |
1547 | &conn->cmdqueue); | 1562 | &conn->cmdqueue); |
1548 | conn->task = NULL; | 1563 | conn->task = NULL; |
1564 | spin_unlock_bh(&conn->taskqueuelock); | ||
1549 | goto done; | 1565 | goto done; |
1550 | } else | 1566 | } else |
1551 | fail_scsi_task(conn->task, DID_ABORT); | 1567 | fail_scsi_task(conn->task, DID_ABORT); |
1568 | spin_lock_bh(&conn->taskqueuelock); | ||
1552 | continue; | 1569 | continue; |
1553 | } | 1570 | } |
1554 | rc = iscsi_xmit_task(conn); | 1571 | rc = iscsi_xmit_task(conn); |
@@ -1559,6 +1576,7 @@ check_mgmt: | |||
1559 | * we need to check the mgmt queue for nops that need to | 1576 | * we need to check the mgmt queue for nops that need to |
1560 | * be sent to aviod starvation | 1577 | * be sent to aviod starvation |
1561 | */ | 1578 | */ |
1579 | spin_lock_bh(&conn->taskqueuelock); | ||
1562 | if (!list_empty(&conn->mgmtqueue)) | 1580 | if (!list_empty(&conn->mgmtqueue)) |
1563 | goto check_mgmt; | 1581 | goto check_mgmt; |
1564 | } | 1582 | } |
@@ -1578,12 +1596,15 @@ check_mgmt: | |||
1578 | conn->task = task; | 1596 | conn->task = task; |
1579 | list_del_init(&conn->task->running); | 1597 | list_del_init(&conn->task->running); |
1580 | conn->task->state = ISCSI_TASK_RUNNING; | 1598 | conn->task->state = ISCSI_TASK_RUNNING; |
1599 | spin_unlock_bh(&conn->taskqueuelock); | ||
1581 | rc = iscsi_xmit_task(conn); | 1600 | rc = iscsi_xmit_task(conn); |
1582 | if (rc) | 1601 | if (rc) |
1583 | goto done; | 1602 | goto done; |
1603 | spin_lock_bh(&conn->taskqueuelock); | ||
1584 | if (!list_empty(&conn->mgmtqueue)) | 1604 | if (!list_empty(&conn->mgmtqueue)) |
1585 | goto check_mgmt; | 1605 | goto check_mgmt; |
1586 | } | 1606 | } |
1607 | spin_unlock_bh(&conn->taskqueuelock); | ||
1587 | spin_unlock_bh(&conn->session->frwd_lock); | 1608 | spin_unlock_bh(&conn->session->frwd_lock); |
1588 | return -ENODATA; | 1609 | return -ENODATA; |
1589 | 1610 | ||
@@ -1739,7 +1760,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) | |||
1739 | goto prepd_reject; | 1760 | goto prepd_reject; |
1740 | } | 1761 | } |
1741 | } else { | 1762 | } else { |
1763 | spin_lock_bh(&conn->taskqueuelock); | ||
1742 | list_add_tail(&task->running, &conn->cmdqueue); | 1764 | list_add_tail(&task->running, &conn->cmdqueue); |
1765 | spin_unlock_bh(&conn->taskqueuelock); | ||
1743 | iscsi_conn_queue_work(conn); | 1766 | iscsi_conn_queue_work(conn); |
1744 | } | 1767 | } |
1745 | 1768 | ||
@@ -2897,6 +2920,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2897 | INIT_LIST_HEAD(&conn->mgmtqueue); | 2920 | INIT_LIST_HEAD(&conn->mgmtqueue); |
2898 | INIT_LIST_HEAD(&conn->cmdqueue); | 2921 | INIT_LIST_HEAD(&conn->cmdqueue); |
2899 | INIT_LIST_HEAD(&conn->requeue); | 2922 | INIT_LIST_HEAD(&conn->requeue); |
2923 | spin_lock_init(&conn->taskqueuelock); | ||
2900 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); | 2924 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
2901 | 2925 | ||
2902 | /* allocate login_task used for the login/text sequences */ | 2926 | /* allocate login_task used for the login/text sequences */ |