diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
| -rw-r--r-- | drivers/scsi/iscsi_tcp.c | 90 |
1 files changed, 56 insertions, 34 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 23808dfe22ba..518dbd91df85 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
| @@ -48,13 +48,6 @@ MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, " | |||
| 48 | "Alex Aizman <itn780@yahoo.com>"); | 48 | "Alex Aizman <itn780@yahoo.com>"); |
| 49 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); | 49 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); |
| 50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
| 51 | #undef DEBUG_TCP | ||
| 52 | |||
| 53 | #ifdef DEBUG_TCP | ||
| 54 | #define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt) | ||
| 55 | #else | ||
| 56 | #define debug_tcp(fmt...) | ||
| 57 | #endif | ||
| 58 | 51 | ||
| 59 | static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport; | 52 | static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport; |
| 60 | static struct scsi_host_template iscsi_sw_tcp_sht; | 53 | static struct scsi_host_template iscsi_sw_tcp_sht; |
| @@ -63,6 +56,21 @@ static struct iscsi_transport iscsi_sw_tcp_transport; | |||
| 63 | static unsigned int iscsi_max_lun = 512; | 56 | static unsigned int iscsi_max_lun = 512; |
| 64 | module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); | 57 | module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); |
| 65 | 58 | ||
| 59 | static int iscsi_sw_tcp_dbg; | ||
| 60 | module_param_named(debug_iscsi_tcp, iscsi_sw_tcp_dbg, int, | ||
| 61 | S_IRUGO | S_IWUSR); | ||
| 62 | MODULE_PARM_DESC(debug_iscsi_tcp, "Turn on debugging for iscsi_tcp module " | ||
| 63 | "Set to 1 to turn on, and zero to turn off. Default is off."); | ||
| 64 | |||
| 65 | #define ISCSI_SW_TCP_DBG(_conn, dbg_fmt, arg...) \ | ||
| 66 | do { \ | ||
| 67 | if (iscsi_sw_tcp_dbg) \ | ||
| 68 | iscsi_conn_printk(KERN_INFO, _conn, \ | ||
| 69 | "%s " dbg_fmt, \ | ||
| 70 | __func__, ##arg); \ | ||
| 71 | } while (0); | ||
| 72 | |||
| 73 | |||
| 66 | /** | 74 | /** |
| 67 | * iscsi_sw_tcp_recv - TCP receive in sendfile fashion | 75 | * iscsi_sw_tcp_recv - TCP receive in sendfile fashion |
| 68 | * @rd_desc: read descriptor | 76 | * @rd_desc: read descriptor |
| @@ -77,7 +85,7 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, | |||
| 77 | unsigned int consumed, total_consumed = 0; | 85 | unsigned int consumed, total_consumed = 0; |
| 78 | int status; | 86 | int status; |
| 79 | 87 | ||
| 80 | debug_tcp("in %d bytes\n", skb->len - offset); | 88 | ISCSI_SW_TCP_DBG(conn, "in %d bytes\n", skb->len - offset); |
| 81 | 89 | ||
| 82 | do { | 90 | do { |
| 83 | status = 0; | 91 | status = 0; |
| @@ -86,7 +94,8 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, | |||
| 86 | total_consumed += consumed; | 94 | total_consumed += consumed; |
| 87 | } while (consumed != 0 && status != ISCSI_TCP_SKB_DONE); | 95 | } while (consumed != 0 && status != ISCSI_TCP_SKB_DONE); |
| 88 | 96 | ||
| 89 | debug_tcp("read %d bytes status %d\n", skb->len - offset, status); | 97 | ISCSI_SW_TCP_DBG(conn, "read %d bytes status %d\n", |
| 98 | skb->len - offset, status); | ||
| 90 | return total_consumed; | 99 | return total_consumed; |
| 91 | } | 100 | } |
| 92 | 101 | ||
| @@ -131,7 +140,8 @@ static void iscsi_sw_tcp_state_change(struct sock *sk) | |||
| 131 | if ((sk->sk_state == TCP_CLOSE_WAIT || | 140 | if ((sk->sk_state == TCP_CLOSE_WAIT || |
| 132 | sk->sk_state == TCP_CLOSE) && | 141 | sk->sk_state == TCP_CLOSE) && |
| 133 | !atomic_read(&sk->sk_rmem_alloc)) { | 142 | !atomic_read(&sk->sk_rmem_alloc)) { |
| 134 | debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n"); | 143 | ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_state_change: " |
| 144 | "TCP_CLOSE|TCP_CLOSE_WAIT\n"); | ||
| 135 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 145 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
| 136 | } | 146 | } |
| 137 | 147 | ||
| @@ -155,8 +165,8 @@ static void iscsi_sw_tcp_write_space(struct sock *sk) | |||
| 155 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; | 165 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; |
| 156 | 166 | ||
| 157 | tcp_sw_conn->old_write_space(sk); | 167 | tcp_sw_conn->old_write_space(sk); |
| 158 | debug_tcp("iscsi_write_space: cid %d\n", conn->id); | 168 | ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n"); |
| 159 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 169 | iscsi_conn_queue_work(conn); |
| 160 | } | 170 | } |
| 161 | 171 | ||
| 162 | 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) |
| @@ -243,8 +253,6 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, | |||
| 243 | 253 | ||
| 244 | if (r < 0) { | 254 | if (r < 0) { |
| 245 | iscsi_tcp_segment_unmap(segment); | 255 | iscsi_tcp_segment_unmap(segment); |
| 246 | if (copied || r == -EAGAIN) | ||
| 247 | break; | ||
| 248 | return r; | 256 | return r; |
| 249 | } | 257 | } |
| 250 | copied += r; | 258 | copied += r; |
| @@ -265,11 +273,17 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) | |||
| 265 | 273 | ||
| 266 | while (1) { | 274 | while (1) { |
| 267 | rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment); | 275 | rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment); |
| 268 | if (rc < 0) { | 276 | /* |
| 277 | * We may not have been able to send data because the conn | ||
| 278 | * is getting stopped. libiscsi will know so propogate err | ||
| 279 | * for it to do the right thing. | ||
| 280 | */ | ||
| 281 | if (rc == -EAGAIN) | ||
| 282 | return rc; | ||
| 283 | else if (rc < 0) { | ||
| 269 | rc = ISCSI_ERR_XMIT_FAILED; | 284 | rc = ISCSI_ERR_XMIT_FAILED; |
| 270 | goto error; | 285 | goto error; |
| 271 | } | 286 | } else if (rc == 0) |
| 272 | if (rc == 0) | ||
| 273 | break; | 287 | break; |
| 274 | 288 | ||
| 275 | consumed += rc; | 289 | consumed += rc; |
| @@ -283,7 +297,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) | |||
| 283 | } | 297 | } |
| 284 | } | 298 | } |
| 285 | 299 | ||
| 286 | debug_tcp("xmit %d bytes\n", consumed); | 300 | ISCSI_SW_TCP_DBG(conn, "xmit %d bytes\n", consumed); |
| 287 | 301 | ||
| 288 | conn->txdata_octets += consumed; | 302 | conn->txdata_octets += consumed; |
| 289 | return consumed; | 303 | return consumed; |
| @@ -291,7 +305,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) | |||
| 291 | error: | 305 | error: |
| 292 | /* Transmit error. We could initiate error recovery | 306 | /* Transmit error. We could initiate error recovery |
| 293 | * here. */ | 307 | * here. */ |
| 294 | debug_tcp("Error sending PDU, errno=%d\n", rc); | 308 | ISCSI_SW_TCP_DBG(conn, "Error sending PDU, errno=%d\n", rc); |
| 295 | iscsi_conn_failure(conn, rc); | 309 | iscsi_conn_failure(conn, rc); |
| 296 | return -EIO; | 310 | return -EIO; |
| 297 | } | 311 | } |
| @@ -334,9 +348,10 @@ static int iscsi_sw_tcp_send_hdr_done(struct iscsi_tcp_conn *tcp_conn, | |||
| 334 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; | 348 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; |
| 335 | 349 | ||
| 336 | tcp_sw_conn->out.segment = tcp_sw_conn->out.data_segment; | 350 | tcp_sw_conn->out.segment = tcp_sw_conn->out.data_segment; |
| 337 | debug_tcp("Header done. Next segment size %u total_size %u\n", | 351 | ISCSI_SW_TCP_DBG(tcp_conn->iscsi_conn, |
| 338 | tcp_sw_conn->out.segment.size, | 352 | "Header done. Next segment size %u total_size %u\n", |
| 339 | tcp_sw_conn->out.segment.total_size); | 353 | tcp_sw_conn->out.segment.size, |
| 354 | tcp_sw_conn->out.segment.total_size); | ||
| 340 | return 0; | 355 | return 0; |
| 341 | } | 356 | } |
| 342 | 357 | ||
| @@ -346,8 +361,8 @@ static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, | |||
| 346 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 361 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 347 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; | 362 | struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; |
| 348 | 363 | ||
| 349 | debug_tcp("%s(%p%s)\n", __func__, tcp_conn, | 364 | ISCSI_SW_TCP_DBG(conn, "%s\n", conn->hdrdgst_en ? |
| 350 | conn->hdrdgst_en? ", digest enabled" : ""); | 365 | "digest enabled" : "digest disabled"); |
| 351 | 366 | ||
| 352 | /* Clear the data segment - needs to be filled in by the | 367 | /* Clear the data segment - needs to be filled in by the |
| 353 | * caller using iscsi_tcp_send_data_prep() */ | 368 | * caller using iscsi_tcp_send_data_prep() */ |
| @@ -389,9 +404,9 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg, | |||
| 389 | struct hash_desc *tx_hash = NULL; | 404 | struct hash_desc *tx_hash = NULL; |
| 390 | unsigned int hdr_spec_len; | 405 | unsigned int hdr_spec_len; |
| 391 | 406 | ||
| 392 | debug_tcp("%s(%p, offset=%d, datalen=%d%s)\n", __func__, | 407 | ISCSI_SW_TCP_DBG(conn, "offset=%d, datalen=%d %s\n", offset, len, |
| 393 | tcp_conn, offset, len, | 408 | conn->datadgst_en ? |
| 394 | conn->datadgst_en? ", digest enabled" : ""); | 409 | "digest enabled" : "digest disabled"); |
| 395 | 410 | ||
| 396 | /* Make sure the datalen matches what the caller | 411 | /* Make sure the datalen matches what the caller |
| 397 | said he would send. */ | 412 | said he would send. */ |
| @@ -415,8 +430,8 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data, | |||
| 415 | struct hash_desc *tx_hash = NULL; | 430 | struct hash_desc *tx_hash = NULL; |
| 416 | unsigned int hdr_spec_len; | 431 | unsigned int hdr_spec_len; |
| 417 | 432 | ||
| 418 | debug_tcp("%s(%p, datalen=%d%s)\n", __func__, tcp_conn, len, | 433 | ISCSI_SW_TCP_DBG(conn, "datalen=%zd %s\n", len, conn->datadgst_en ? |
| 419 | conn->datadgst_en? ", digest enabled" : ""); | 434 | "digest enabled" : "digest disabled"); |
| 420 | 435 | ||
| 421 | /* Make sure the datalen matches what the caller | 436 | /* Make sure the datalen matches what the caller |
| 422 | said he would send. */ | 437 | said he would send. */ |
| @@ -452,7 +467,7 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task, | |||
| 452 | } | 467 | } |
| 453 | 468 | ||
| 454 | if (err) { | 469 | if (err) { |
| 455 | iscsi_conn_failure(conn, err); | 470 | /* got invalid offset/len */ |
| 456 | return -EIO; | 471 | return -EIO; |
| 457 | } | 472 | } |
| 458 | return 0; | 473 | return 0; |
| @@ -754,8 +769,7 @@ iscsi_sw_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn, | |||
| 754 | 769 | ||
| 755 | static struct iscsi_cls_session * | 770 | static struct iscsi_cls_session * |
| 756 | iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | 771 | iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, |
| 757 | uint16_t qdepth, uint32_t initial_cmdsn, | 772 | uint16_t qdepth, uint32_t initial_cmdsn) |
| 758 | uint32_t *hostno) | ||
| 759 | { | 773 | { |
| 760 | struct iscsi_cls_session *cls_session; | 774 | struct iscsi_cls_session *cls_session; |
| 761 | struct iscsi_session *session; | 775 | struct iscsi_session *session; |
| @@ -766,10 +780,11 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | |||
| 766 | return NULL; | 780 | return NULL; |
| 767 | } | 781 | } |
| 768 | 782 | ||
| 769 | shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth); | 783 | shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1); |
| 770 | if (!shost) | 784 | if (!shost) |
| 771 | return NULL; | 785 | return NULL; |
| 772 | shost->transportt = iscsi_sw_tcp_scsi_transport; | 786 | shost->transportt = iscsi_sw_tcp_scsi_transport; |
| 787 | shost->cmd_per_lun = qdepth; | ||
| 773 | shost->max_lun = iscsi_max_lun; | 788 | shost->max_lun = iscsi_max_lun; |
| 774 | shost->max_id = 0; | 789 | shost->max_id = 0; |
| 775 | shost->max_channel = 0; | 790 | shost->max_channel = 0; |
| @@ -777,7 +792,6 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | |||
| 777 | 792 | ||
| 778 | if (iscsi_host_add(shost, NULL)) | 793 | if (iscsi_host_add(shost, NULL)) |
| 779 | goto free_host; | 794 | goto free_host; |
| 780 | *hostno = shost->host_no; | ||
| 781 | 795 | ||
| 782 | cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost, | 796 | cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost, |
| 783 | cmds_max, | 797 | cmds_max, |
| @@ -813,6 +827,12 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session) | |||
| 813 | iscsi_host_free(shost); | 827 | iscsi_host_free(shost); |
| 814 | } | 828 | } |
| 815 | 829 | ||
| 830 | static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev) | ||
| 831 | { | ||
| 832 | set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags); | ||
| 833 | return 0; | ||
| 834 | } | ||
| 835 | |||
| 816 | static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev) | 836 | static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev) |
| 817 | { | 837 | { |
| 818 | blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY); | 838 | blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY); |
| @@ -833,7 +853,9 @@ static struct scsi_host_template iscsi_sw_tcp_sht = { | |||
| 833 | .eh_device_reset_handler= iscsi_eh_device_reset, | 853 | .eh_device_reset_handler= iscsi_eh_device_reset, |
| 834 | .eh_target_reset_handler= iscsi_eh_target_reset, | 854 | .eh_target_reset_handler= iscsi_eh_target_reset, |
| 835 | .use_clustering = DISABLE_CLUSTERING, | 855 | .use_clustering = DISABLE_CLUSTERING, |
| 856 | .slave_alloc = iscsi_sw_tcp_slave_alloc, | ||
| 836 | .slave_configure = iscsi_sw_tcp_slave_configure, | 857 | .slave_configure = iscsi_sw_tcp_slave_configure, |
| 858 | .target_alloc = iscsi_target_alloc, | ||
| 837 | .proc_name = "iscsi_tcp", | 859 | .proc_name = "iscsi_tcp", |
| 838 | .this_id = -1, | 860 | .this_id = -1, |
| 839 | }; | 861 | }; |
