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 | |
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>
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/ulp/iser/iser_initiator.c | 2 | ||||
-rw-r--r-- | drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 2 | ||||
-rw-r--r-- | drivers/scsi/cxgb3i/cxgb3i_pdu.c | 2 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 4 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 45 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 7 |
7 files changed, 48 insertions, 16 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 5f79c0a5faf3..a50cd53e2753 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c | |||
@@ -404,7 +404,7 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep, | |||
404 | struct Scsi_Host *shost; | 404 | struct Scsi_Host *shost; |
405 | struct iser_conn *ib_conn; | 405 | struct iser_conn *ib_conn; |
406 | 406 | ||
407 | shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN); | 407 | shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISER_DEF_CMD_PER_LUN, 1); |
408 | if (!shost) | 408 | if (!shost) |
409 | return NULL; | 409 | return NULL; |
410 | shost->transportt = iscsi_iser_scsi_transport; | 410 | shost->transportt = iscsi_iser_scsi_transport; |
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index e209cb8dd948..9de640200ad3 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c | |||
@@ -661,7 +661,7 @@ void iser_snd_completion(struct iser_desc *tx_desc) | |||
661 | 661 | ||
662 | if (resume_tx) { | 662 | if (resume_tx) { |
663 | iser_dbg("%ld resuming tx\n",jiffies); | 663 | iser_dbg("%ld resuming tx\n",jiffies); |
664 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 664 | iscsi_conn_queue_work(conn); |
665 | } | 665 | } |
666 | 666 | ||
667 | if (tx_desc->type == ISCSI_TX_CONTROL) { | 667 | if (tx_desc->type == ISCSI_TX_CONTROL) { |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index fa2a44f37b36..f6ed9c62efb0 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
@@ -171,7 +171,7 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic, | |||
171 | 171 | ||
172 | shost = iscsi_host_alloc(&cxgb3i_host_template, | 172 | shost = iscsi_host_alloc(&cxgb3i_host_template, |
173 | sizeof(struct cxgb3i_hba), | 173 | sizeof(struct cxgb3i_hba), |
174 | CXGB3I_SCSI_QDEPTH_DFLT); | 174 | CXGB3I_SCSI_QDEPTH_DFLT, 1); |
175 | if (!shost) { | 175 | if (!shost) { |
176 | cxgb3i_log_info("iscsi_host_alloc failed.\n"); | 176 | cxgb3i_log_info("iscsi_host_alloc failed.\n"); |
177 | return NULL; | 177 | return NULL; |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c index 17115c230d65..7eebc9a7cb35 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c | |||
@@ -479,7 +479,7 @@ void cxgb3i_conn_tx_open(struct s3_conn *c3cn) | |||
479 | cxgb3i_tx_debug("cn 0x%p.\n", c3cn); | 479 | cxgb3i_tx_debug("cn 0x%p.\n", c3cn); |
480 | if (conn) { | 480 | if (conn) { |
481 | cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id); | 481 | cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id); |
482 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 482 | iscsi_conn_queue_work(conn); |
483 | } | 483 | } |
484 | } | 484 | } |
485 | 485 | ||
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 9c2e52792bdc..79a706a94c68 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -166,7 +166,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk) | |||
166 | 166 | ||
167 | tcp_sw_conn->old_write_space(sk); | 167 | tcp_sw_conn->old_write_space(sk); |
168 | ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n"); | 168 | ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n"); |
169 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 169 | iscsi_conn_queue_work(conn); |
170 | } | 170 | } |
171 | 171 | ||
172 | static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn) | 172 | static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn) |
@@ -777,7 +777,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | |||
777 | return NULL; | 777 | return NULL; |
778 | } | 778 | } |
779 | 779 | ||
780 | shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth); | 780 | shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth, 1); |
781 | if (!shost) | 781 | if (!shost) |
782 | return NULL; | 782 | return NULL; |
783 | shost->transportt = iscsi_sw_tcp_scsi_transport; | 783 | shost->transportt = iscsi_sw_tcp_scsi_transport; |
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 | ||
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 898de4a73727..b0b8a6992497 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -318,6 +318,9 @@ struct iscsi_host { | |||
318 | spinlock_t lock; | 318 | spinlock_t lock; |
319 | int num_sessions; | 319 | int num_sessions; |
320 | int state; | 320 | int state; |
321 | |||
322 | struct workqueue_struct *workq; | ||
323 | char workq_name[20]; | ||
321 | }; | 324 | }; |
322 | 325 | ||
323 | /* | 326 | /* |
@@ -343,7 +346,8 @@ extern int iscsi_host_get_param(struct Scsi_Host *shost, | |||
343 | enum iscsi_host_param param, char *buf); | 346 | enum iscsi_host_param param, char *buf); |
344 | extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); | 347 | extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev); |
345 | extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, | 348 | extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, |
346 | int dd_data_size, uint16_t qdepth); | 349 | int dd_data_size, uint16_t qdepth, |
350 | bool xmit_can_sleep); | ||
347 | extern void iscsi_host_remove(struct Scsi_Host *shost); | 351 | extern void iscsi_host_remove(struct Scsi_Host *shost); |
348 | extern void iscsi_host_free(struct Scsi_Host *shost); | 352 | extern void iscsi_host_free(struct Scsi_Host *shost); |
349 | 353 | ||
@@ -379,6 +383,7 @@ extern void iscsi_session_failure(struct iscsi_cls_session *cls_session, | |||
379 | extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | 383 | extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, |
380 | enum iscsi_param param, char *buf); | 384 | enum iscsi_param param, char *buf); |
381 | extern void iscsi_suspend_tx(struct iscsi_conn *conn); | 385 | extern void iscsi_suspend_tx(struct iscsi_conn *conn); |
386 | extern void iscsi_conn_queue_work(struct iscsi_conn *conn); | ||
382 | 387 | ||
383 | #define iscsi_conn_printk(prefix, _c, fmt, a...) \ | 388 | #define iscsi_conn_printk(prefix, _c, fmt, a...) \ |
384 | iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ | 389 | iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ |