diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
| -rw-r--r-- | drivers/scsi/iscsi_tcp.c | 209 |
1 files changed, 79 insertions, 130 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 848fb2aa4ca3..058f094f945a 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
| @@ -43,13 +43,10 @@ | |||
| 43 | 43 | ||
| 44 | #include "iscsi_tcp.h" | 44 | #include "iscsi_tcp.h" |
| 45 | 45 | ||
| 46 | #define ISCSI_TCP_VERSION "1.0-595" | ||
| 47 | |||
| 48 | MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, " | 46 | MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, " |
| 49 | "Alex Aizman <itn780@yahoo.com>"); | 47 | "Alex Aizman <itn780@yahoo.com>"); |
| 50 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); | 48 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); |
| 51 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
| 52 | MODULE_VERSION(ISCSI_TCP_VERSION); | ||
| 53 | /* #define DEBUG_TCP */ | 50 | /* #define DEBUG_TCP */ |
| 54 | #define DEBUG_ASSERT | 51 | #define DEBUG_ASSERT |
| 55 | 52 | ||
| @@ -185,11 +182,19 @@ iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn) | |||
| 185 | * must be called with session lock | 182 | * must be called with session lock |
| 186 | */ | 183 | */ |
| 187 | static void | 184 | static void |
| 188 | __iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 185 | iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
| 189 | { | 186 | { |
| 190 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 187 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
| 188 | struct iscsi_r2t_info *r2t; | ||
| 191 | struct scsi_cmnd *sc; | 189 | struct scsi_cmnd *sc; |
| 192 | 190 | ||
| 191 | /* flush ctask's r2t queues */ | ||
| 192 | while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { | ||
| 193 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, | ||
| 194 | sizeof(void*)); | ||
| 195 | debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n"); | ||
| 196 | } | ||
| 197 | |||
| 193 | sc = ctask->sc; | 198 | sc = ctask->sc; |
| 194 | if (unlikely(!sc)) | 199 | if (unlikely(!sc)) |
| 195 | return; | 200 | return; |
| @@ -374,6 +379,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 374 | spin_unlock(&session->lock); | 379 | spin_unlock(&session->lock); |
| 375 | return 0; | 380 | return 0; |
| 376 | } | 381 | } |
| 382 | |||
| 377 | rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); | 383 | rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); |
| 378 | BUG_ON(!rc); | 384 | BUG_ON(!rc); |
| 379 | 385 | ||
| @@ -399,7 +405,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 399 | tcp_ctask->exp_r2tsn = r2tsn + 1; | 405 | tcp_ctask->exp_r2tsn = r2tsn + 1; |
| 400 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR; | 406 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR; |
| 401 | __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); | 407 | __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); |
| 402 | __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); | 408 | list_move_tail(&ctask->running, &conn->xmitqueue); |
| 403 | 409 | ||
| 404 | scsi_queue_work(session->host, &conn->xmitwork); | 410 | scsi_queue_work(session->host, &conn->xmitwork); |
| 405 | conn->r2t_pdus_cnt++; | 411 | conn->r2t_pdus_cnt++; |
| @@ -477,6 +483,8 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) | |||
| 477 | case ISCSI_OP_SCSI_DATA_IN: | 483 | case ISCSI_OP_SCSI_DATA_IN: |
| 478 | tcp_conn->in.ctask = session->cmds[itt]; | 484 | tcp_conn->in.ctask = session->cmds[itt]; |
| 479 | rc = iscsi_data_rsp(conn, tcp_conn->in.ctask); | 485 | rc = iscsi_data_rsp(conn, tcp_conn->in.ctask); |
| 486 | if (rc) | ||
| 487 | return rc; | ||
| 480 | /* fall through */ | 488 | /* fall through */ |
| 481 | case ISCSI_OP_SCSI_CMD_RSP: | 489 | case ISCSI_OP_SCSI_CMD_RSP: |
| 482 | tcp_conn->in.ctask = session->cmds[itt]; | 490 | tcp_conn->in.ctask = session->cmds[itt]; |
| @@ -484,7 +492,7 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) | |||
| 484 | goto copy_hdr; | 492 | goto copy_hdr; |
| 485 | 493 | ||
| 486 | spin_lock(&session->lock); | 494 | spin_lock(&session->lock); |
| 487 | __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); | 495 | iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask); |
| 488 | rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); | 496 | rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); |
| 489 | spin_unlock(&session->lock); | 497 | spin_unlock(&session->lock); |
| 490 | break; | 498 | break; |
| @@ -500,13 +508,28 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) | |||
| 500 | break; | 508 | break; |
| 501 | case ISCSI_OP_LOGIN_RSP: | 509 | case ISCSI_OP_LOGIN_RSP: |
| 502 | case ISCSI_OP_TEXT_RSP: | 510 | case ISCSI_OP_TEXT_RSP: |
| 503 | case ISCSI_OP_LOGOUT_RSP: | ||
| 504 | case ISCSI_OP_NOOP_IN: | ||
| 505 | case ISCSI_OP_REJECT: | 511 | case ISCSI_OP_REJECT: |
| 506 | case ISCSI_OP_ASYNC_EVENT: | 512 | case ISCSI_OP_ASYNC_EVENT: |
| 513 | /* | ||
| 514 | * It is possible that we could get a PDU with a buffer larger | ||
| 515 | * than 8K, but there are no targets that currently do this. | ||
| 516 | * For now we fail until we find a vendor that needs it | ||
| 517 | */ | ||
| 518 | if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH < | ||
| 519 | tcp_conn->in.datalen) { | ||
| 520 | printk(KERN_ERR "iscsi_tcp: received buffer of len %u " | ||
| 521 | "but conn buffer is only %u (opcode %0x)\n", | ||
| 522 | tcp_conn->in.datalen, | ||
| 523 | DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode); | ||
| 524 | rc = ISCSI_ERR_PROTO; | ||
| 525 | break; | ||
| 526 | } | ||
| 527 | |||
| 507 | if (tcp_conn->in.datalen) | 528 | if (tcp_conn->in.datalen) |
| 508 | goto copy_hdr; | 529 | goto copy_hdr; |
| 509 | /* fall through */ | 530 | /* fall through */ |
| 531 | case ISCSI_OP_LOGOUT_RSP: | ||
| 532 | case ISCSI_OP_NOOP_IN: | ||
| 510 | case ISCSI_OP_SCSI_TMFUNC_RSP: | 533 | case ISCSI_OP_SCSI_TMFUNC_RSP: |
| 511 | rc = iscsi_complete_pdu(conn, hdr, NULL, 0); | 534 | rc = iscsi_complete_pdu(conn, hdr, NULL, 0); |
| 512 | break; | 535 | break; |
| @@ -523,7 +546,7 @@ copy_hdr: | |||
| 523 | * skbs to complete the command then we have to copy the header | 546 | * skbs to complete the command then we have to copy the header |
| 524 | * for later use | 547 | * for later use |
| 525 | */ | 548 | */ |
| 526 | if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy < | 549 | if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <= |
| 527 | (tcp_conn->in.datalen + tcp_conn->in.padding + | 550 | (tcp_conn->in.datalen + tcp_conn->in.padding + |
| 528 | (conn->datadgst_en ? 4 : 0))) { | 551 | (conn->datadgst_en ? 4 : 0))) { |
| 529 | debug_tcp("Copying header for later use. in.copy %d in.datalen" | 552 | debug_tcp("Copying header for later use. in.copy %d in.datalen" |
| @@ -614,9 +637,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, | |||
| 614 | * byte counters. | 637 | * byte counters. |
| 615 | **/ | 638 | **/ |
| 616 | static inline int | 639 | static inline int |
| 617 | iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) | 640 | iscsi_tcp_copy(struct iscsi_conn *conn) |
| 618 | { | 641 | { |
| 619 | void *buf = tcp_conn->data; | 642 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 620 | int buf_size = tcp_conn->in.datalen; | 643 | int buf_size = tcp_conn->in.datalen; |
| 621 | int buf_left = buf_size - tcp_conn->data_copied; | 644 | int buf_left = buf_size - tcp_conn->data_copied; |
| 622 | int size = min(tcp_conn->in.copy, buf_left); | 645 | int size = min(tcp_conn->in.copy, buf_left); |
| @@ -627,7 +650,7 @@ iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) | |||
| 627 | BUG_ON(size <= 0); | 650 | BUG_ON(size <= 0); |
| 628 | 651 | ||
| 629 | rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, | 652 | rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, |
| 630 | (char*)buf + tcp_conn->data_copied, size); | 653 | (char*)conn->data + tcp_conn->data_copied, size); |
| 631 | BUG_ON(rc); | 654 | BUG_ON(rc); |
| 632 | 655 | ||
| 633 | tcp_conn->in.offset += size; | 656 | tcp_conn->in.offset += size; |
| @@ -745,10 +768,11 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) | |||
| 745 | done: | 768 | done: |
| 746 | /* check for non-exceptional status */ | 769 | /* check for non-exceptional status */ |
| 747 | if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) { | 770 | if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) { |
| 748 | debug_scsi("done [sc %lx res %d itt 0x%x]\n", | 771 | debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n", |
| 749 | (long)sc, sc->result, ctask->itt); | 772 | (long)sc, sc->result, ctask->itt, |
| 773 | tcp_conn->in.hdr->flags); | ||
| 750 | spin_lock(&conn->session->lock); | 774 | spin_lock(&conn->session->lock); |
| 751 | __iscsi_ctask_cleanup(conn, ctask); | 775 | iscsi_tcp_cleanup_ctask(conn, ctask); |
| 752 | __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); | 776 | __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); |
| 753 | spin_unlock(&conn->session->lock); | 777 | spin_unlock(&conn->session->lock); |
| 754 | } | 778 | } |
| @@ -769,26 +793,25 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
| 769 | break; | 793 | break; |
| 770 | case ISCSI_OP_SCSI_CMD_RSP: | 794 | case ISCSI_OP_SCSI_CMD_RSP: |
| 771 | spin_lock(&conn->session->lock); | 795 | spin_lock(&conn->session->lock); |
| 772 | __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); | 796 | iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask); |
| 773 | spin_unlock(&conn->session->lock); | 797 | spin_unlock(&conn->session->lock); |
| 774 | case ISCSI_OP_TEXT_RSP: | 798 | case ISCSI_OP_TEXT_RSP: |
| 775 | case ISCSI_OP_LOGIN_RSP: | 799 | case ISCSI_OP_LOGIN_RSP: |
| 776 | case ISCSI_OP_NOOP_IN: | ||
| 777 | case ISCSI_OP_ASYNC_EVENT: | 800 | case ISCSI_OP_ASYNC_EVENT: |
| 778 | case ISCSI_OP_REJECT: | 801 | case ISCSI_OP_REJECT: |
| 779 | /* | 802 | /* |
| 780 | * Collect data segment to the connection's data | 803 | * Collect data segment to the connection's data |
| 781 | * placeholder | 804 | * placeholder |
| 782 | */ | 805 | */ |
| 783 | if (iscsi_tcp_copy(tcp_conn)) { | 806 | if (iscsi_tcp_copy(conn)) { |
| 784 | rc = -EAGAIN; | 807 | rc = -EAGAIN; |
| 785 | goto exit; | 808 | goto exit; |
| 786 | } | 809 | } |
| 787 | 810 | ||
| 788 | rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data, | 811 | rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, conn->data, |
| 789 | tcp_conn->in.datalen); | 812 | tcp_conn->in.datalen); |
| 790 | if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) | 813 | if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) |
| 791 | iscsi_recv_digest_update(tcp_conn, tcp_conn->data, | 814 | iscsi_recv_digest_update(tcp_conn, conn->data, |
| 792 | tcp_conn->in.datalen); | 815 | tcp_conn->in.datalen); |
| 793 | break; | 816 | break; |
| 794 | default: | 817 | default: |
| @@ -843,7 +866,7 @@ more: | |||
| 843 | if (rc == -EAGAIN) | 866 | if (rc == -EAGAIN) |
| 844 | goto nomore; | 867 | goto nomore; |
| 845 | else { | 868 | else { |
| 846 | iscsi_conn_failure(conn, rc); | 869 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
| 847 | return 0; | 870 | return 0; |
| 848 | } | 871 | } |
| 849 | } | 872 | } |
| @@ -897,7 +920,7 @@ more: | |||
| 897 | if (rc) { | 920 | if (rc) { |
| 898 | if (rc == -EAGAIN) | 921 | if (rc == -EAGAIN) |
| 899 | goto again; | 922 | goto again; |
| 900 | iscsi_conn_failure(conn, rc); | 923 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
| 901 | return 0; | 924 | return 0; |
| 902 | } | 925 | } |
| 903 | tcp_conn->in.copy -= tcp_conn->in.padding; | 926 | tcp_conn->in.copy -= tcp_conn->in.padding; |
| @@ -1028,9 +1051,8 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn) | |||
| 1028 | } | 1051 | } |
| 1029 | 1052 | ||
| 1030 | static void | 1053 | static void |
| 1031 | iscsi_conn_restore_callbacks(struct iscsi_conn *conn) | 1054 | iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn) |
| 1032 | { | 1055 | { |
| 1033 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
| 1034 | struct sock *sk = tcp_conn->sock->sk; | 1056 | struct sock *sk = tcp_conn->sock->sk; |
| 1035 | 1057 | ||
| 1036 | /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */ | 1058 | /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */ |
| @@ -1308,7 +1330,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) | |||
| 1308 | ctask->imm_count - | 1330 | ctask->imm_count - |
| 1309 | ctask->unsol_count; | 1331 | ctask->unsol_count; |
| 1310 | 1332 | ||
| 1311 | debug_scsi("cmd [itt %x total %d imm %d imm_data %d " | 1333 | debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d " |
| 1312 | "r2t_data %d]\n", | 1334 | "r2t_data %d]\n", |
| 1313 | ctask->itt, ctask->total_length, ctask->imm_count, | 1335 | ctask->itt, ctask->total_length, ctask->imm_count, |
| 1314 | ctask->unsol_count, tcp_ctask->r2t_data_count); | 1336 | ctask->unsol_count, tcp_ctask->r2t_data_count); |
| @@ -1636,7 +1658,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 1636 | } | 1658 | } |
| 1637 | solicit_again: | 1659 | solicit_again: |
| 1638 | /* | 1660 | /* |
| 1639 | * send Data-Out whitnin this R2T sequence. | 1661 | * send Data-Out within this R2T sequence. |
| 1640 | */ | 1662 | */ |
| 1641 | if (!r2t->data_count) | 1663 | if (!r2t->data_count) |
| 1642 | goto data_out_done; | 1664 | goto data_out_done; |
| @@ -1731,7 +1753,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
| 1731 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1753 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
| 1732 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1754 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
| 1733 | struct iscsi_data_task *dtask = tcp_ctask->dtask; | 1755 | struct iscsi_data_task *dtask = tcp_ctask->dtask; |
| 1734 | int sent, rc; | 1756 | int sent = 0, rc; |
| 1735 | 1757 | ||
| 1736 | tcp_ctask->xmstate &= ~XMSTATE_W_PAD; | 1758 | tcp_ctask->xmstate &= ~XMSTATE_W_PAD; |
| 1737 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, | 1759 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, |
| @@ -1900,27 +1922,32 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
| 1900 | tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; | 1922 | tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; |
| 1901 | /* initial operational parameters */ | 1923 | /* initial operational parameters */ |
| 1902 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); | 1924 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); |
| 1903 | tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; | ||
| 1904 | |||
| 1905 | /* allocate initial PDU receive place holder */ | ||
| 1906 | if (tcp_conn->data_size <= PAGE_SIZE) | ||
| 1907 | tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL); | ||
| 1908 | else | ||
| 1909 | tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL, | ||
| 1910 | get_order(tcp_conn->data_size)); | ||
| 1911 | if (!tcp_conn->data) | ||
| 1912 | goto max_recv_dlenght_alloc_fail; | ||
| 1913 | 1925 | ||
| 1914 | return cls_conn; | 1926 | return cls_conn; |
| 1915 | 1927 | ||
| 1916 | max_recv_dlenght_alloc_fail: | ||
| 1917 | kfree(tcp_conn); | ||
| 1918 | tcp_conn_alloc_fail: | 1928 | tcp_conn_alloc_fail: |
| 1919 | iscsi_conn_teardown(cls_conn); | 1929 | iscsi_conn_teardown(cls_conn); |
| 1920 | return NULL; | 1930 | return NULL; |
| 1921 | } | 1931 | } |
| 1922 | 1932 | ||
| 1923 | static void | 1933 | static void |
| 1934 | iscsi_tcp_release_conn(struct iscsi_conn *conn) | ||
| 1935 | { | ||
| 1936 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
| 1937 | |||
| 1938 | if (!tcp_conn->sock) | ||
| 1939 | return; | ||
| 1940 | |||
| 1941 | sock_hold(tcp_conn->sock->sk); | ||
| 1942 | iscsi_conn_restore_callbacks(tcp_conn); | ||
| 1943 | sock_put(tcp_conn->sock->sk); | ||
| 1944 | |||
| 1945 | sock_release(tcp_conn->sock); | ||
| 1946 | tcp_conn->sock = NULL; | ||
| 1947 | conn->recv_lock = NULL; | ||
| 1948 | } | ||
| 1949 | |||
| 1950 | static void | ||
| 1924 | iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) | 1951 | iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) |
| 1925 | { | 1952 | { |
| 1926 | struct iscsi_conn *conn = cls_conn->dd_data; | 1953 | struct iscsi_conn *conn = cls_conn->dd_data; |
| @@ -1930,6 +1957,7 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) | |||
| 1930 | if (conn->hdrdgst_en || conn->datadgst_en) | 1957 | if (conn->hdrdgst_en || conn->datadgst_en) |
| 1931 | digest = 1; | 1958 | digest = 1; |
| 1932 | 1959 | ||
| 1960 | iscsi_tcp_release_conn(conn); | ||
| 1933 | iscsi_conn_teardown(cls_conn); | 1961 | iscsi_conn_teardown(cls_conn); |
| 1934 | 1962 | ||
| 1935 | /* now free tcp_conn */ | 1963 | /* now free tcp_conn */ |
| @@ -1944,15 +1972,18 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) | |||
| 1944 | crypto_free_tfm(tcp_conn->data_rx_tfm); | 1972 | crypto_free_tfm(tcp_conn->data_rx_tfm); |
| 1945 | } | 1973 | } |
| 1946 | 1974 | ||
| 1947 | /* free conn->data, size = MaxRecvDataSegmentLength */ | ||
| 1948 | if (tcp_conn->data_size <= PAGE_SIZE) | ||
| 1949 | kfree(tcp_conn->data); | ||
| 1950 | else | ||
| 1951 | free_pages((unsigned long)tcp_conn->data, | ||
| 1952 | get_order(tcp_conn->data_size)); | ||
| 1953 | kfree(tcp_conn); | 1975 | kfree(tcp_conn); |
| 1954 | } | 1976 | } |
| 1955 | 1977 | ||
| 1978 | static void | ||
| 1979 | iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | ||
| 1980 | { | ||
| 1981 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
| 1982 | |||
| 1983 | iscsi_conn_stop(cls_conn, flag); | ||
| 1984 | iscsi_tcp_release_conn(conn); | ||
| 1985 | } | ||
| 1986 | |||
| 1956 | static int | 1987 | static int |
| 1957 | iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | 1988 | iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, |
| 1958 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, | 1989 | struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, |
| @@ -2001,52 +2032,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, | |||
| 2001 | return 0; | 2032 | return 0; |
| 2002 | } | 2033 | } |
| 2003 | 2034 | ||
| 2004 | static void | ||
| 2005 | iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | ||
| 2006 | { | ||
| 2007 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | ||
| 2008 | struct iscsi_r2t_info *r2t; | ||
| 2009 | |||
| 2010 | /* flush ctask's r2t queues */ | ||
| 2011 | while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) | ||
| 2012 | __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, | ||
| 2013 | sizeof(void*)); | ||
| 2014 | |||
| 2015 | __iscsi_ctask_cleanup(conn, ctask); | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | static void | ||
| 2019 | iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn) | ||
| 2020 | { | ||
| 2021 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
| 2022 | struct sock *sk; | ||
| 2023 | |||
| 2024 | if (!tcp_conn->sock) | ||
| 2025 | return; | ||
| 2026 | |||
| 2027 | sk = tcp_conn->sock->sk; | ||
| 2028 | write_lock_bh(&sk->sk_callback_lock); | ||
| 2029 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); | ||
| 2030 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 2031 | } | ||
| 2032 | |||
| 2033 | static void | ||
| 2034 | iscsi_tcp_terminate_conn(struct iscsi_conn *conn) | ||
| 2035 | { | ||
| 2036 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | ||
| 2037 | |||
| 2038 | if (!tcp_conn->sock) | ||
| 2039 | return; | ||
| 2040 | |||
| 2041 | sock_hold(tcp_conn->sock->sk); | ||
| 2042 | iscsi_conn_restore_callbacks(conn); | ||
| 2043 | sock_put(tcp_conn->sock->sk); | ||
| 2044 | |||
| 2045 | sock_release(tcp_conn->sock); | ||
| 2046 | tcp_conn->sock = NULL; | ||
| 2047 | conn->recv_lock = NULL; | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | /* called with host lock */ | 2035 | /* called with host lock */ |
| 2051 | static void | 2036 | static void |
| 2052 | iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, | 2037 | iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, |
| @@ -2057,6 +2042,7 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, | |||
| 2057 | iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, | 2042 | iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, |
| 2058 | sizeof(struct iscsi_hdr)); | 2043 | sizeof(struct iscsi_hdr)); |
| 2059 | tcp_mtask->xmstate = XMSTATE_IMM_HDR; | 2044 | tcp_mtask->xmstate = XMSTATE_IMM_HDR; |
| 2045 | tcp_mtask->sent = 0; | ||
| 2060 | 2046 | ||
| 2061 | if (mtask->data_count) | 2047 | if (mtask->data_count) |
| 2062 | iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, | 2048 | iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, |
| @@ -2138,39 +2124,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, | |||
| 2138 | int value; | 2124 | int value; |
| 2139 | 2125 | ||
| 2140 | switch(param) { | 2126 | switch(param) { |
| 2141 | case ISCSI_PARAM_MAX_RECV_DLENGTH: { | ||
| 2142 | char *saveptr = tcp_conn->data; | ||
| 2143 | gfp_t flags = GFP_KERNEL; | ||
| 2144 | |||
| 2145 | sscanf(buf, "%d", &value); | ||
| 2146 | if (tcp_conn->data_size >= value) { | ||
| 2147 | iscsi_set_param(cls_conn, param, buf, buflen); | ||
| 2148 | break; | ||
| 2149 | } | ||
| 2150 | |||
| 2151 | spin_lock_bh(&session->lock); | ||
| 2152 | if (conn->stop_stage == STOP_CONN_RECOVER) | ||
| 2153 | flags = GFP_ATOMIC; | ||
| 2154 | spin_unlock_bh(&session->lock); | ||
| 2155 | |||
| 2156 | if (value <= PAGE_SIZE) | ||
| 2157 | tcp_conn->data = kmalloc(value, flags); | ||
| 2158 | else | ||
| 2159 | tcp_conn->data = (void*)__get_free_pages(flags, | ||
| 2160 | get_order(value)); | ||
| 2161 | if (tcp_conn->data == NULL) { | ||
| 2162 | tcp_conn->data = saveptr; | ||
| 2163 | return -ENOMEM; | ||
| 2164 | } | ||
| 2165 | if (tcp_conn->data_size <= PAGE_SIZE) | ||
| 2166 | kfree(saveptr); | ||
| 2167 | else | ||
| 2168 | free_pages((unsigned long)saveptr, | ||
| 2169 | get_order(tcp_conn->data_size)); | ||
| 2170 | iscsi_set_param(cls_conn, param, buf, buflen); | ||
| 2171 | tcp_conn->data_size = value; | ||
| 2172 | break; | ||
| 2173 | } | ||
| 2174 | case ISCSI_PARAM_HDRDGST_EN: | 2127 | case ISCSI_PARAM_HDRDGST_EN: |
| 2175 | iscsi_set_param(cls_conn, param, buf, buflen); | 2128 | iscsi_set_param(cls_conn, param, buf, buflen); |
| 2176 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); | 2129 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); |
| @@ -2361,8 +2314,7 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) | |||
| 2361 | } | 2314 | } |
| 2362 | 2315 | ||
| 2363 | static struct scsi_host_template iscsi_sht = { | 2316 | static struct scsi_host_template iscsi_sht = { |
| 2364 | .name = "iSCSI Initiator over TCP/IP, v" | 2317 | .name = "iSCSI Initiator over TCP/IP", |
| 2365 | ISCSI_TCP_VERSION, | ||
| 2366 | .queuecommand = iscsi_queuecommand, | 2318 | .queuecommand = iscsi_queuecommand, |
| 2367 | .change_queue_depth = iscsi_change_queue_depth, | 2319 | .change_queue_depth = iscsi_change_queue_depth, |
| 2368 | .can_queue = ISCSI_XMIT_CMDS_MAX - 1, | 2320 | .can_queue = ISCSI_XMIT_CMDS_MAX - 1, |
| @@ -2414,10 +2366,7 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
| 2414 | .get_conn_param = iscsi_tcp_conn_get_param, | 2366 | .get_conn_param = iscsi_tcp_conn_get_param, |
| 2415 | .get_session_param = iscsi_session_get_param, | 2367 | .get_session_param = iscsi_session_get_param, |
| 2416 | .start_conn = iscsi_conn_start, | 2368 | .start_conn = iscsi_conn_start, |
| 2417 | .stop_conn = iscsi_conn_stop, | 2369 | .stop_conn = iscsi_tcp_conn_stop, |
| 2418 | /* these are called as part of conn recovery */ | ||
| 2419 | .suspend_conn_recv = iscsi_tcp_suspend_conn_rx, | ||
| 2420 | .terminate_conn = iscsi_tcp_terminate_conn, | ||
| 2421 | /* IO */ | 2370 | /* IO */ |
| 2422 | .send_pdu = iscsi_conn_send_pdu, | 2371 | .send_pdu = iscsi_conn_send_pdu, |
| 2423 | .get_stats = iscsi_conn_get_stats, | 2372 | .get_stats = iscsi_conn_get_stats, |
