diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2009-03-05 15:46:03 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-03-13 16:28:37 -0400 |
commit | 32ae763e3fce4192cd008956a340353a2e5c3192 (patch) | |
tree | af13b359c4e54fe60c8eb76c8927b41468dcbe57 /drivers/scsi/libiscsi.c | |
parent | 06d25af4edb60f9e9c7e74d342a6963a32e3392f (diff) |
[SCSI] iscsi lib: have lib create work queue for transmitting IO
We were using the shost work queue which ended up being
a little akward since all iscsi hosts need a thread for
scanning, but only drivers hooked into libiscsi need
a workqueue for transmitting. So this patch moves the
xmit workqueue to the lib.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index a5168a673503..ff891543df22 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -76,6 +76,15 @@ static int iscsi_sna_lte(u32 n1, u32 n2) | |||
76 | (n1 > n2 && (n2 - n1 < SNA32_CHECK))); | 76 | (n1 > n2 && (n2 - n1 < SNA32_CHECK))); |
77 | } | 77 | } |
78 | 78 | ||
79 | inline void iscsi_conn_queue_work(struct iscsi_conn *conn) | ||
80 | { | ||
81 | struct Scsi_Host *shost = conn->session->host; | ||
82 | struct iscsi_host *ihost = shost_priv(shost); | ||
83 | |||
84 | queue_work(ihost->workq, &conn->xmitwork); | ||
85 | } | ||
86 | EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); | ||
87 | |||
79 | void | 88 | void |
80 | iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | 89 | iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) |
81 | { | 90 | { |
@@ -103,8 +112,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
103 | if (!list_empty(&session->leadconn->xmitqueue) || | 112 | if (!list_empty(&session->leadconn->xmitqueue) || |
104 | !list_empty(&session->leadconn->mgmtqueue)) { | 113 | !list_empty(&session->leadconn->mgmtqueue)) { |
105 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 114 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
106 | scsi_queue_work(session->host, | 115 | iscsi_conn_queue_work(session->leadconn); |
107 | &session->leadconn->xmitwork); | ||
108 | } | 116 | } |
109 | } | 117 | } |
110 | } | 118 | } |
@@ -586,7 +594,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
586 | goto free_task; | 594 | goto free_task; |
587 | 595 | ||
588 | } else | 596 | } else |
589 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 597 | iscsi_conn_queue_work(conn); |
590 | 598 | ||
591 | return task; | 599 | return task; |
592 | 600 | ||
@@ -1160,7 +1168,7 @@ void iscsi_requeue_task(struct iscsi_task *task) | |||
1160 | struct iscsi_conn *conn = task->conn; | 1168 | struct iscsi_conn *conn = task->conn; |
1161 | 1169 | ||
1162 | list_move_tail(&task->running, &conn->requeue); | 1170 | list_move_tail(&task->running, &conn->requeue); |
1163 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 1171 | iscsi_conn_queue_work(conn); |
1164 | } | 1172 | } |
1165 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); | 1173 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); |
1166 | 1174 | ||
@@ -1413,7 +1421,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1413 | goto prepd_reject; | 1421 | goto prepd_reject; |
1414 | } | 1422 | } |
1415 | } else | 1423 | } else |
1416 | scsi_queue_work(session->host, &conn->xmitwork); | 1424 | iscsi_conn_queue_work(conn); |
1417 | 1425 | ||
1418 | session->queued_cmdsn++; | 1426 | session->queued_cmdsn++; |
1419 | spin_unlock(&session->lock); | 1427 | spin_unlock(&session->lock); |
@@ -1631,9 +1639,12 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | |||
1631 | 1639 | ||
1632 | void iscsi_suspend_tx(struct iscsi_conn *conn) | 1640 | void iscsi_suspend_tx(struct iscsi_conn *conn) |
1633 | { | 1641 | { |
1642 | struct Scsi_Host *shost = conn->session->host; | ||
1643 | struct iscsi_host *ihost = shost_priv(shost); | ||
1644 | |||
1634 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1645 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1635 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 1646 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
1636 | scsi_flush_work(conn->session->host); | 1647 | flush_workqueue(ihost->workq); |
1637 | } | 1648 | } |
1638 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); | 1649 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); |
1639 | 1650 | ||
@@ -1641,7 +1652,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn) | |||
1641 | { | 1652 | { |
1642 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1653 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1643 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) | 1654 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
1644 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 1655 | iscsi_conn_queue_work(conn); |
1645 | } | 1656 | } |
1646 | 1657 | ||
1647 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | 1658 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) |
@@ -2046,12 +2057,14 @@ EXPORT_SYMBOL_GPL(iscsi_host_add); | |||
2046 | * @sht: scsi host template | 2057 | * @sht: scsi host template |
2047 | * @dd_data_size: driver host data size | 2058 | * @dd_data_size: driver host data size |
2048 | * @qdepth: default device queue depth | 2059 | * @qdepth: default device queue depth |
2060 | * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue | ||
2049 | * | 2061 | * |
2050 | * This should be called by partial offload and software iscsi drivers. | 2062 | * This should be called by partial offload and software iscsi drivers. |
2051 | * To access the driver specific memory use the iscsi_host_priv() macro. | 2063 | * To access the driver specific memory use the iscsi_host_priv() macro. |
2052 | */ | 2064 | */ |
2053 | struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, | 2065 | struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, |
2054 | int dd_data_size, uint16_t qdepth) | 2066 | int dd_data_size, uint16_t qdepth, |
2067 | bool xmit_can_sleep) | ||
2055 | { | 2068 | { |
2056 | struct Scsi_Host *shost; | 2069 | struct Scsi_Host *shost; |
2057 | struct iscsi_host *ihost; | 2070 | struct iscsi_host *ihost; |
@@ -2063,13 +2076,25 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, | |||
2063 | if (qdepth == 0) | 2076 | if (qdepth == 0) |
2064 | qdepth = ISCSI_DEF_CMD_PER_LUN; | 2077 | qdepth = ISCSI_DEF_CMD_PER_LUN; |
2065 | shost->cmd_per_lun = qdepth; | 2078 | shost->cmd_per_lun = qdepth; |
2066 | |||
2067 | ihost = shost_priv(shost); | 2079 | ihost = shost_priv(shost); |
2080 | |||
2081 | if (xmit_can_sleep) { | ||
2082 | snprintf(ihost->workq_name, sizeof(ihost->workq_name), | ||
2083 | "iscsi_q_%d", shost->host_no); | ||
2084 | ihost->workq = create_singlethread_workqueue(ihost->workq_name); | ||
2085 | if (!ihost->workq) | ||
2086 | goto free_host; | ||
2087 | } | ||
2088 | |||
2068 | spin_lock_init(&ihost->lock); | 2089 | spin_lock_init(&ihost->lock); |
2069 | ihost->state = ISCSI_HOST_SETUP; | 2090 | ihost->state = ISCSI_HOST_SETUP; |
2070 | ihost->num_sessions = 0; | 2091 | ihost->num_sessions = 0; |
2071 | init_waitqueue_head(&ihost->session_removal_wq); | 2092 | init_waitqueue_head(&ihost->session_removal_wq); |
2072 | return shost; | 2093 | return shost; |
2094 | |||
2095 | free_host: | ||
2096 | scsi_host_put(shost); | ||
2097 | return NULL; | ||
2073 | } | 2098 | } |
2074 | EXPORT_SYMBOL_GPL(iscsi_host_alloc); | 2099 | EXPORT_SYMBOL_GPL(iscsi_host_alloc); |
2075 | 2100 | ||
@@ -2101,6 +2126,8 @@ void iscsi_host_remove(struct Scsi_Host *shost) | |||
2101 | flush_signals(current); | 2126 | flush_signals(current); |
2102 | 2127 | ||
2103 | scsi_remove_host(shost); | 2128 | scsi_remove_host(shost); |
2129 | if (ihost->workq) | ||
2130 | destroy_workqueue(ihost->workq); | ||
2104 | } | 2131 | } |
2105 | EXPORT_SYMBOL_GPL(iscsi_host_remove); | 2132 | EXPORT_SYMBOL_GPL(iscsi_host_remove); |
2106 | 2133 | ||