diff options
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 83 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.h | 2 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 10 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 8 |
4 files changed, 38 insertions, 65 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index b6c68be6b866..aa20adc79f02 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -511,13 +511,28 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) | |||
511 | break; | 511 | break; |
512 | case ISCSI_OP_LOGIN_RSP: | 512 | case ISCSI_OP_LOGIN_RSP: |
513 | case ISCSI_OP_TEXT_RSP: | 513 | case ISCSI_OP_TEXT_RSP: |
514 | case ISCSI_OP_LOGOUT_RSP: | ||
515 | case ISCSI_OP_NOOP_IN: | ||
516 | case ISCSI_OP_REJECT: | 514 | case ISCSI_OP_REJECT: |
517 | case ISCSI_OP_ASYNC_EVENT: | 515 | case ISCSI_OP_ASYNC_EVENT: |
516 | /* | ||
517 | * It is possible that we could get a PDU with a buffer larger | ||
518 | * than 8K, but there are no targets that currently do this. | ||
519 | * For now we fail until we find a vendor that needs it | ||
520 | */ | ||
521 | if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH < | ||
522 | tcp_conn->in.datalen) { | ||
523 | printk(KERN_ERR "iscsi_tcp: received buffer of len %u " | ||
524 | "but conn buffer is only %u (opcode %0x)\n", | ||
525 | tcp_conn->in.datalen, | ||
526 | DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode); | ||
527 | rc = ISCSI_ERR_PROTO; | ||
528 | break; | ||
529 | } | ||
530 | |||
518 | if (tcp_conn->in.datalen) | 531 | if (tcp_conn->in.datalen) |
519 | goto copy_hdr; | 532 | goto copy_hdr; |
520 | /* fall through */ | 533 | /* fall through */ |
534 | case ISCSI_OP_LOGOUT_RSP: | ||
535 | case ISCSI_OP_NOOP_IN: | ||
521 | case ISCSI_OP_SCSI_TMFUNC_RSP: | 536 | case ISCSI_OP_SCSI_TMFUNC_RSP: |
522 | rc = iscsi_complete_pdu(conn, hdr, NULL, 0); | 537 | rc = iscsi_complete_pdu(conn, hdr, NULL, 0); |
523 | break; | 538 | break; |
@@ -625,9 +640,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, | |||
625 | * byte counters. | 640 | * byte counters. |
626 | **/ | 641 | **/ |
627 | static inline int | 642 | static inline int |
628 | iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) | 643 | iscsi_tcp_copy(struct iscsi_conn *conn) |
629 | { | 644 | { |
630 | void *buf = tcp_conn->data; | 645 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
631 | int buf_size = tcp_conn->in.datalen; | 646 | int buf_size = tcp_conn->in.datalen; |
632 | int buf_left = buf_size - tcp_conn->data_copied; | 647 | int buf_left = buf_size - tcp_conn->data_copied; |
633 | int size = min(tcp_conn->in.copy, buf_left); | 648 | int size = min(tcp_conn->in.copy, buf_left); |
@@ -638,7 +653,7 @@ iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) | |||
638 | BUG_ON(size <= 0); | 653 | BUG_ON(size <= 0); |
639 | 654 | ||
640 | rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, | 655 | rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, |
641 | (char*)buf + tcp_conn->data_copied, size); | 656 | (char*)conn->data + tcp_conn->data_copied, size); |
642 | BUG_ON(rc); | 657 | BUG_ON(rc); |
643 | 658 | ||
644 | tcp_conn->in.offset += size; | 659 | tcp_conn->in.offset += size; |
@@ -785,22 +800,21 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
785 | spin_unlock(&conn->session->lock); | 800 | spin_unlock(&conn->session->lock); |
786 | case ISCSI_OP_TEXT_RSP: | 801 | case ISCSI_OP_TEXT_RSP: |
787 | case ISCSI_OP_LOGIN_RSP: | 802 | case ISCSI_OP_LOGIN_RSP: |
788 | case ISCSI_OP_NOOP_IN: | ||
789 | case ISCSI_OP_ASYNC_EVENT: | 803 | case ISCSI_OP_ASYNC_EVENT: |
790 | case ISCSI_OP_REJECT: | 804 | case ISCSI_OP_REJECT: |
791 | /* | 805 | /* |
792 | * Collect data segment to the connection's data | 806 | * Collect data segment to the connection's data |
793 | * placeholder | 807 | * placeholder |
794 | */ | 808 | */ |
795 | if (iscsi_tcp_copy(tcp_conn)) { | 809 | if (iscsi_tcp_copy(conn)) { |
796 | rc = -EAGAIN; | 810 | rc = -EAGAIN; |
797 | goto exit; | 811 | goto exit; |
798 | } | 812 | } |
799 | 813 | ||
800 | rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data, | 814 | rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, conn->data, |
801 | tcp_conn->in.datalen); | 815 | tcp_conn->in.datalen); |
802 | if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) | 816 | if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) |
803 | iscsi_recv_digest_update(tcp_conn, tcp_conn->data, | 817 | iscsi_recv_digest_update(tcp_conn, conn->data, |
804 | tcp_conn->in.datalen); | 818 | tcp_conn->in.datalen); |
805 | break; | 819 | break; |
806 | default: | 820 | default: |
@@ -1911,21 +1925,9 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1911 | tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; | 1925 | tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; |
1912 | /* initial operational parameters */ | 1926 | /* initial operational parameters */ |
1913 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); | 1927 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); |
1914 | tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; | ||
1915 | |||
1916 | /* allocate initial PDU receive place holder */ | ||
1917 | if (tcp_conn->data_size <= PAGE_SIZE) | ||
1918 | tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL); | ||
1919 | else | ||
1920 | tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL, | ||
1921 | get_order(tcp_conn->data_size)); | ||
1922 | if (!tcp_conn->data) | ||
1923 | goto max_recv_dlenght_alloc_fail; | ||
1924 | 1928 | ||
1925 | return cls_conn; | 1929 | return cls_conn; |
1926 | 1930 | ||
1927 | max_recv_dlenght_alloc_fail: | ||
1928 | kfree(tcp_conn); | ||
1929 | tcp_conn_alloc_fail: | 1931 | tcp_conn_alloc_fail: |
1930 | iscsi_conn_teardown(cls_conn); | 1932 | iscsi_conn_teardown(cls_conn); |
1931 | return NULL; | 1933 | return NULL; |
@@ -1973,12 +1975,6 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) | |||
1973 | crypto_free_tfm(tcp_conn->data_rx_tfm); | 1975 | crypto_free_tfm(tcp_conn->data_rx_tfm); |
1974 | } | 1976 | } |
1975 | 1977 | ||
1976 | /* free conn->data, size = MaxRecvDataSegmentLength */ | ||
1977 | if (tcp_conn->data_size <= PAGE_SIZE) | ||
1978 | kfree(tcp_conn->data); | ||
1979 | else | ||
1980 | free_pages((unsigned long)tcp_conn->data, | ||
1981 | get_order(tcp_conn->data_size)); | ||
1982 | kfree(tcp_conn); | 1978 | kfree(tcp_conn); |
1983 | } | 1979 | } |
1984 | 1980 | ||
@@ -2131,39 +2127,6 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, | |||
2131 | int value; | 2127 | int value; |
2132 | 2128 | ||
2133 | switch(param) { | 2129 | switch(param) { |
2134 | case ISCSI_PARAM_MAX_RECV_DLENGTH: { | ||
2135 | char *saveptr = tcp_conn->data; | ||
2136 | gfp_t flags = GFP_KERNEL; | ||
2137 | |||
2138 | sscanf(buf, "%d", &value); | ||
2139 | if (tcp_conn->data_size >= value) { | ||
2140 | iscsi_set_param(cls_conn, param, buf, buflen); | ||
2141 | break; | ||
2142 | } | ||
2143 | |||
2144 | spin_lock_bh(&session->lock); | ||
2145 | if (conn->stop_stage == STOP_CONN_RECOVER) | ||
2146 | flags = GFP_ATOMIC; | ||
2147 | spin_unlock_bh(&session->lock); | ||
2148 | |||
2149 | if (value <= PAGE_SIZE) | ||
2150 | tcp_conn->data = kmalloc(value, flags); | ||
2151 | else | ||
2152 | tcp_conn->data = (void*)__get_free_pages(flags, | ||
2153 | get_order(value)); | ||
2154 | if (tcp_conn->data == NULL) { | ||
2155 | tcp_conn->data = saveptr; | ||
2156 | return -ENOMEM; | ||
2157 | } | ||
2158 | if (tcp_conn->data_size <= PAGE_SIZE) | ||
2159 | kfree(saveptr); | ||
2160 | else | ||
2161 | free_pages((unsigned long)saveptr, | ||
2162 | get_order(tcp_conn->data_size)); | ||
2163 | iscsi_set_param(cls_conn, param, buf, buflen); | ||
2164 | tcp_conn->data_size = value; | ||
2165 | break; | ||
2166 | } | ||
2167 | case ISCSI_PARAM_HDRDGST_EN: | 2130 | case ISCSI_PARAM_HDRDGST_EN: |
2168 | iscsi_set_param(cls_conn, param, buf, buflen); | 2131 | iscsi_set_param(cls_conn, param, buf, buflen); |
2169 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); | 2132 | tcp_conn->hdr_size = sizeof(struct iscsi_hdr); |
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 808302832e68..6a4ee704e46e 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h | |||
@@ -78,8 +78,6 @@ struct iscsi_tcp_conn { | |||
78 | char hdrext[4*sizeof(__u16) + | 78 | char hdrext[4*sizeof(__u16) + |
79 | sizeof(__u32)]; | 79 | sizeof(__u32)]; |
80 | int data_copied; | 80 | int data_copied; |
81 | char *data; /* data placeholder */ | ||
82 | int data_size; /* actual recv_dlength */ | ||
83 | int stop_stage; /* conn_stop() flag: * | 81 | int stop_stage; /* conn_stop() flag: * |
84 | * stop to recover, * | 82 | * stop to recover, * |
85 | * stop to terminate */ | 83 | * stop to terminate */ |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c989bc6180b3..03b3dee49009 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -360,6 +360,10 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
360 | 360 | ||
361 | switch(opcode) { | 361 | switch(opcode) { |
362 | case ISCSI_OP_LOGOUT_RSP: | 362 | case ISCSI_OP_LOGOUT_RSP: |
363 | if (datalen) { | ||
364 | rc = ISCSI_ERR_PROTO; | ||
365 | break; | ||
366 | } | ||
363 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 367 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
364 | /* fall through */ | 368 | /* fall through */ |
365 | case ISCSI_OP_LOGIN_RSP: | 369 | case ISCSI_OP_LOGIN_RSP: |
@@ -383,7 +387,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
383 | iscsi_tmf_rsp(conn, hdr); | 387 | iscsi_tmf_rsp(conn, hdr); |
384 | break; | 388 | break; |
385 | case ISCSI_OP_NOOP_IN: | 389 | case ISCSI_OP_NOOP_IN: |
386 | if (hdr->ttt != ISCSI_RESERVED_TAG) { | 390 | if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) { |
387 | rc = ISCSI_ERR_PROTO; | 391 | rc = ISCSI_ERR_PROTO; |
388 | break; | 392 | break; |
389 | } | 393 | } |
@@ -1405,7 +1409,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1405 | data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); | 1409 | data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); |
1406 | if (!data) | 1410 | if (!data) |
1407 | goto login_mtask_data_alloc_fail; | 1411 | goto login_mtask_data_alloc_fail; |
1408 | conn->login_mtask->data = data; | 1412 | conn->login_mtask->data = conn->data = data; |
1409 | 1413 | ||
1410 | init_timer(&conn->tmabort_timer); | 1414 | init_timer(&conn->tmabort_timer); |
1411 | mutex_init(&conn->xmitmutex); | 1415 | mutex_init(&conn->xmitmutex); |
@@ -1477,7 +1481,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1477 | } | 1481 | } |
1478 | 1482 | ||
1479 | spin_lock_bh(&session->lock); | 1483 | spin_lock_bh(&session->lock); |
1480 | kfree(conn->login_mtask->data); | 1484 | kfree(conn->data); |
1481 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 1485 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, |
1482 | sizeof(void*)); | 1486 | sizeof(void*)); |
1483 | list_del(&conn->item); | 1487 | list_del(&conn->item); |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 3f69f7e58f89..41904f611d12 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -135,6 +135,14 @@ struct iscsi_conn { | |||
135 | int id; /* CID */ | 135 | int id; /* CID */ |
136 | struct list_head item; /* maintains list of conns */ | 136 | struct list_head item; /* maintains list of conns */ |
137 | int c_stage; /* connection state */ | 137 | int c_stage; /* connection state */ |
138 | /* | ||
139 | * Preallocated buffer for pdus that have data but do not | ||
140 | * originate from scsi-ml. We never have two pdus using the | ||
141 | * buffer at the same time. It is only allocated to | ||
142 | * the default max recv size because the pdus we support | ||
143 | * should always fit in this buffer | ||
144 | */ | ||
145 | char *data; | ||
138 | struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ | 146 | struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ |
139 | struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ | 147 | struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ |
140 | struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ | 148 | struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ |