diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-03-07 00:54:13 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-04-25 04:05:26 -0400 |
commit | baa4d64b147a4064626f6597646ae8a330d9e2ed (patch) | |
tree | 5d017ffcfc1372d112f3f54ccd8621f703c91f25 | |
parent | 3f99306337ba1871afc8568e8b36004ce3cee039 (diff) |
iscsi-target: Initial traditional TCP conversion to iscsit_transport
This patch performs the initial conversion of existing traditional iscsi
to use iscsit_transport API callers. This includes:
- iscsi-np cleanups for iscsit_transport_type
- Add iscsi-np transport calls w/ ->iscsit_setup_up() and ->iscsit_free_np()
- Convert login thread process context to use ->iscsit_accept_np() for
connections with pre-allocated struct iscsi_conn
- Convert existing socket accept code to iscsit_accept_np()
- Convert login RX/TX callers to use ->iscsit_get_login_rx() and
->iscsit_put_login_tx() to exchange request/response PDUs
- Convert existing socket login RX/TX calls into iscsit_get_login_rx()
and iscsit_put_login_tx()
- Change iscsit_close_connection() to invoke ->iscsit_free_conn() +
iscsit_put_transport() calls.
- Add iscsit_register_transport() + iscsit_unregister_transport() calls
to module init/exit
v4 changes:
- Add missing iscsit_put_transport() call in iscsi_target_setup_login_socket()
failure case
v2 changes:
- Update module init/exit to use register_transport() + unregister_transport()
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 35 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 15 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 416 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_login.h | 6 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_nego.c | 167 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_nego.h | 11 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_parameters.c | 12 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_tpg.c | 6 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 27 |
9 files changed, 380 insertions, 315 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 7ea246a07731..8203bf3de848 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -49,6 +49,8 @@ | |||
49 | #include "iscsi_target_device.h" | 49 | #include "iscsi_target_device.h" |
50 | #include "iscsi_target_stat.h" | 50 | #include "iscsi_target_stat.h" |
51 | 51 | ||
52 | #include <target/iscsi/iscsi_transport.h> | ||
53 | |||
52 | static LIST_HEAD(g_tiqn_list); | 54 | static LIST_HEAD(g_tiqn_list); |
53 | static LIST_HEAD(g_np_list); | 55 | static LIST_HEAD(g_np_list); |
54 | static DEFINE_SPINLOCK(tiqn_lock); | 56 | static DEFINE_SPINLOCK(tiqn_lock); |
@@ -401,8 +403,7 @@ struct iscsi_np *iscsit_add_np( | |||
401 | spin_unlock_bh(&np_lock); | 403 | spin_unlock_bh(&np_lock); |
402 | 404 | ||
403 | pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n", | 405 | pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n", |
404 | np->np_ip, np->np_port, (np->np_network_transport == ISCSI_TCP) ? | 406 | np->np_ip, np->np_port, np->np_transport->name); |
405 | "TCP" : "SCTP"); | ||
406 | 407 | ||
407 | return np; | 408 | return np; |
408 | } | 409 | } |
@@ -441,11 +442,10 @@ int iscsit_reset_np_thread( | |||
441 | return 0; | 442 | return 0; |
442 | } | 443 | } |
443 | 444 | ||
444 | static int iscsit_del_np_comm(struct iscsi_np *np) | 445 | static void iscsit_free_np(struct iscsi_np *np) |
445 | { | 446 | { |
446 | if (np->np_socket) | 447 | if (np->np_socket) |
447 | sock_release(np->np_socket); | 448 | sock_release(np->np_socket); |
448 | return 0; | ||
449 | } | 449 | } |
450 | 450 | ||
451 | int iscsit_del_np(struct iscsi_np *np) | 451 | int iscsit_del_np(struct iscsi_np *np) |
@@ -467,20 +467,32 @@ int iscsit_del_np(struct iscsi_np *np) | |||
467 | send_sig(SIGINT, np->np_thread, 1); | 467 | send_sig(SIGINT, np->np_thread, 1); |
468 | kthread_stop(np->np_thread); | 468 | kthread_stop(np->np_thread); |
469 | } | 469 | } |
470 | iscsit_del_np_comm(np); | 470 | |
471 | np->np_transport->iscsit_free_np(np); | ||
471 | 472 | ||
472 | spin_lock_bh(&np_lock); | 473 | spin_lock_bh(&np_lock); |
473 | list_del(&np->np_list); | 474 | list_del(&np->np_list); |
474 | spin_unlock_bh(&np_lock); | 475 | spin_unlock_bh(&np_lock); |
475 | 476 | ||
476 | pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n", | 477 | pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n", |
477 | np->np_ip, np->np_port, (np->np_network_transport == ISCSI_TCP) ? | 478 | np->np_ip, np->np_port, np->np_transport->name); |
478 | "TCP" : "SCTP"); | ||
479 | 479 | ||
480 | iscsit_put_transport(np->np_transport); | ||
480 | kfree(np); | 481 | kfree(np); |
481 | return 0; | 482 | return 0; |
482 | } | 483 | } |
483 | 484 | ||
485 | static struct iscsit_transport iscsi_target_transport = { | ||
486 | .name = "iSCSI/TCP", | ||
487 | .transport_type = ISCSI_TCP, | ||
488 | .owner = NULL, | ||
489 | .iscsit_setup_np = iscsit_setup_np, | ||
490 | .iscsit_accept_np = iscsit_accept_np, | ||
491 | .iscsit_free_np = iscsit_free_np, | ||
492 | .iscsit_get_login_rx = iscsit_get_login_rx, | ||
493 | .iscsit_put_login_tx = iscsit_put_login_tx, | ||
494 | }; | ||
495 | |||
484 | static int __init iscsi_target_init_module(void) | 496 | static int __init iscsi_target_init_module(void) |
485 | { | 497 | { |
486 | int ret = 0; | 498 | int ret = 0; |
@@ -557,6 +569,8 @@ static int __init iscsi_target_init_module(void) | |||
557 | goto ooo_out; | 569 | goto ooo_out; |
558 | } | 570 | } |
559 | 571 | ||
572 | iscsit_register_transport(&iscsi_target_transport); | ||
573 | |||
560 | if (iscsit_load_discovery_tpg() < 0) | 574 | if (iscsit_load_discovery_tpg() < 0) |
561 | goto r2t_out; | 575 | goto r2t_out; |
562 | 576 | ||
@@ -587,6 +601,7 @@ static void __exit iscsi_target_cleanup_module(void) | |||
587 | iscsi_deallocate_thread_sets(); | 601 | iscsi_deallocate_thread_sets(); |
588 | iscsi_thread_set_free(); | 602 | iscsi_thread_set_free(); |
589 | iscsit_release_discovery_tpg(); | 603 | iscsit_release_discovery_tpg(); |
604 | iscsit_unregister_transport(&iscsi_target_transport); | ||
590 | kmem_cache_destroy(lio_cmd_cache); | 605 | kmem_cache_destroy(lio_cmd_cache); |
591 | kmem_cache_destroy(lio_qr_cache); | 606 | kmem_cache_destroy(lio_qr_cache); |
592 | kmem_cache_destroy(lio_dr_cache); | 607 | kmem_cache_destroy(lio_dr_cache); |
@@ -4053,6 +4068,12 @@ int iscsit_close_connection( | |||
4053 | 4068 | ||
4054 | if (conn->sock) | 4069 | if (conn->sock) |
4055 | sock_release(conn->sock); | 4070 | sock_release(conn->sock); |
4071 | |||
4072 | if (conn->conn_transport->iscsit_free_conn) | ||
4073 | conn->conn_transport->iscsit_free_conn(conn); | ||
4074 | |||
4075 | iscsit_put_transport(conn->conn_transport); | ||
4076 | |||
4056 | conn->thread_set = NULL; | 4077 | conn->thread_set = NULL; |
4057 | 4078 | ||
4058 | pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); | 4079 | pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); |
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 7a333d28d9a2..258767776090 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h | |||
@@ -60,7 +60,7 @@ | |||
60 | 60 | ||
61 | #define ISCSI_IOV_DATA_BUFFER 5 | 61 | #define ISCSI_IOV_DATA_BUFFER 5 |
62 | 62 | ||
63 | enum tpg_np_network_transport_table { | 63 | enum iscsit_transport_type { |
64 | ISCSI_TCP = 0, | 64 | ISCSI_TCP = 0, |
65 | ISCSI_SCTP_TCP = 1, | 65 | ISCSI_SCTP_TCP = 1, |
66 | ISCSI_SCTP_UDP = 2, | 66 | ISCSI_SCTP_UDP = 2, |
@@ -503,6 +503,7 @@ struct iscsi_conn { | |||
503 | u16 login_port; | 503 | u16 login_port; |
504 | u16 local_port; | 504 | u16 local_port; |
505 | int net_size; | 505 | int net_size; |
506 | int login_family; | ||
506 | u32 auth_id; | 507 | u32 auth_id; |
507 | u32 conn_flags; | 508 | u32 conn_flags; |
508 | /* Used for iscsi_tx_login_rsp() */ | 509 | /* Used for iscsi_tx_login_rsp() */ |
@@ -562,9 +563,12 @@ struct iscsi_conn { | |||
562 | struct list_head immed_queue_list; | 563 | struct list_head immed_queue_list; |
563 | struct list_head response_queue_list; | 564 | struct list_head response_queue_list; |
564 | struct iscsi_conn_ops *conn_ops; | 565 | struct iscsi_conn_ops *conn_ops; |
566 | struct iscsi_login *conn_login; | ||
567 | struct iscsit_transport *conn_transport; | ||
565 | struct iscsi_param_list *param_list; | 568 | struct iscsi_param_list *param_list; |
566 | /* Used for per connection auth state machine */ | 569 | /* Used for per connection auth state machine */ |
567 | void *auth_protocol; | 570 | void *auth_protocol; |
571 | void *context; | ||
568 | struct iscsi_login_thread_s *login_thread; | 572 | struct iscsi_login_thread_s *login_thread; |
569 | struct iscsi_portal_group *tpg; | 573 | struct iscsi_portal_group *tpg; |
570 | /* Pointer to parent session */ | 574 | /* Pointer to parent session */ |
@@ -663,6 +667,8 @@ struct iscsi_login { | |||
663 | u8 first_request; | 667 | u8 first_request; |
664 | u8 version_min; | 668 | u8 version_min; |
665 | u8 version_max; | 669 | u8 version_max; |
670 | u8 login_complete; | ||
671 | u8 login_failed; | ||
666 | char isid[6]; | 672 | char isid[6]; |
667 | u32 cmd_sn; | 673 | u32 cmd_sn; |
668 | itt_t init_task_tag; | 674 | itt_t init_task_tag; |
@@ -670,10 +676,11 @@ struct iscsi_login { | |||
670 | u32 rsp_length; | 676 | u32 rsp_length; |
671 | u16 cid; | 677 | u16 cid; |
672 | u16 tsih; | 678 | u16 tsih; |
673 | char *req; | 679 | char req[ISCSI_HDR_LEN]; |
674 | char *rsp; | 680 | char rsp[ISCSI_HDR_LEN]; |
675 | char *req_buf; | 681 | char *req_buf; |
676 | char *rsp_buf; | 682 | char *rsp_buf; |
683 | struct iscsi_conn *conn; | ||
677 | } ____cacheline_aligned; | 684 | } ____cacheline_aligned; |
678 | 685 | ||
679 | struct iscsi_node_attrib { | 686 | struct iscsi_node_attrib { |
@@ -754,6 +761,8 @@ struct iscsi_np { | |||
754 | struct task_struct *np_thread; | 761 | struct task_struct *np_thread; |
755 | struct timer_list np_login_timer; | 762 | struct timer_list np_login_timer; |
756 | struct iscsi_portal_group *np_login_tpg; | 763 | struct iscsi_portal_group *np_login_tpg; |
764 | void *np_context; | ||
765 | struct iscsit_transport *np_transport; | ||
757 | struct list_head np_list; | 766 | struct list_head np_list; |
758 | } ____cacheline_aligned; | 767 | } ____cacheline_aligned; |
759 | 768 | ||
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 2535d4d46c0e..0de5c47d1c81 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
@@ -39,8 +39,39 @@ | |||
39 | #include "iscsi_target.h" | 39 | #include "iscsi_target.h" |
40 | #include "iscsi_target_parameters.h" | 40 | #include "iscsi_target_parameters.h" |
41 | 41 | ||
42 | static int iscsi_login_init_conn(struct iscsi_conn *conn) | 42 | #include <target/iscsi/iscsi_transport.h> |
43 | |||
44 | static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn) | ||
43 | { | 45 | { |
46 | struct iscsi_login *login; | ||
47 | |||
48 | login = kzalloc(sizeof(struct iscsi_login), GFP_KERNEL); | ||
49 | if (!login) { | ||
50 | pr_err("Unable to allocate memory for struct iscsi_login.\n"); | ||
51 | return NULL; | ||
52 | } | ||
53 | login->conn = conn; | ||
54 | login->first_request = 1; | ||
55 | |||
56 | login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL); | ||
57 | if (!login->req_buf) { | ||
58 | pr_err("Unable to allocate memory for response buffer.\n"); | ||
59 | goto out_login; | ||
60 | } | ||
61 | |||
62 | login->rsp_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL); | ||
63 | if (!login->rsp_buf) { | ||
64 | pr_err("Unable to allocate memory for request buffer.\n"); | ||
65 | goto out_req_buf; | ||
66 | } | ||
67 | |||
68 | conn->conn_ops = kzalloc(sizeof(struct iscsi_conn_ops), GFP_KERNEL); | ||
69 | if (!conn->conn_ops) { | ||
70 | pr_err("Unable to allocate memory for" | ||
71 | " struct iscsi_conn_ops.\n"); | ||
72 | goto out_rsp_buf; | ||
73 | } | ||
74 | |||
44 | init_waitqueue_head(&conn->queues_wq); | 75 | init_waitqueue_head(&conn->queues_wq); |
45 | INIT_LIST_HEAD(&conn->conn_list); | 76 | INIT_LIST_HEAD(&conn->conn_list); |
46 | INIT_LIST_HEAD(&conn->conn_cmd_list); | 77 | INIT_LIST_HEAD(&conn->conn_cmd_list); |
@@ -62,10 +93,21 @@ static int iscsi_login_init_conn(struct iscsi_conn *conn) | |||
62 | 93 | ||
63 | if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) { | 94 | if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) { |
64 | pr_err("Unable to allocate conn->conn_cpumask\n"); | 95 | pr_err("Unable to allocate conn->conn_cpumask\n"); |
65 | return -ENOMEM; | 96 | goto out_conn_ops; |
66 | } | 97 | } |
98 | conn->conn_login = login; | ||
67 | 99 | ||
68 | return 0; | 100 | return login; |
101 | |||
102 | out_conn_ops: | ||
103 | kfree(conn->conn_ops); | ||
104 | out_rsp_buf: | ||
105 | kfree(login->rsp_buf); | ||
106 | out_req_buf: | ||
107 | kfree(login->req_buf); | ||
108 | out_login: | ||
109 | kfree(login); | ||
110 | return NULL; | ||
69 | } | 111 | } |
70 | 112 | ||
71 | /* | 113 | /* |
@@ -573,10 +615,13 @@ int iscsi_login_post_auth_non_zero_tsih( | |||
573 | 615 | ||
574 | static void iscsi_post_login_start_timers(struct iscsi_conn *conn) | 616 | static void iscsi_post_login_start_timers(struct iscsi_conn *conn) |
575 | { | 617 | { |
618 | #warning FIXME: Reenable iscsit_start_nopin_timer | ||
619 | #if 0 | ||
576 | struct iscsi_session *sess = conn->sess; | 620 | struct iscsi_session *sess = conn->sess; |
577 | 621 | ||
578 | if (!sess->sess_ops->SessionType) | 622 | if (!sess->sess_ops->SessionType) |
579 | iscsit_start_nopin_timer(conn); | 623 | iscsit_start_nopin_timer(conn); |
624 | #endif | ||
580 | } | 625 | } |
581 | 626 | ||
582 | static int iscsi_post_login_handler( | 627 | static int iscsi_post_login_handler( |
@@ -632,7 +677,13 @@ static int iscsi_post_login_handler( | |||
632 | spin_unlock_bh(&sess->conn_lock); | 677 | spin_unlock_bh(&sess->conn_lock); |
633 | 678 | ||
634 | iscsi_post_login_start_timers(conn); | 679 | iscsi_post_login_start_timers(conn); |
635 | iscsi_activate_thread_set(conn, ts); | 680 | |
681 | if (conn->conn_transport == ISCSI_TCP) { | ||
682 | iscsi_activate_thread_set(conn, ts); | ||
683 | } else { | ||
684 | printk("Not calling iscsi_activate_thread_set....\n"); | ||
685 | dump_stack(); | ||
686 | } | ||
636 | /* | 687 | /* |
637 | * Determine CPU mask to ensure connection's RX and TX kthreads | 688 | * Determine CPU mask to ensure connection's RX and TX kthreads |
638 | * are scheduled on the same CPU. | 689 | * are scheduled on the same CPU. |
@@ -761,11 +812,11 @@ static void iscsi_stop_login_thread_timer(struct iscsi_np *np) | |||
761 | spin_unlock_bh(&np->np_thread_lock); | 812 | spin_unlock_bh(&np->np_thread_lock); |
762 | } | 813 | } |
763 | 814 | ||
764 | int iscsi_target_setup_login_socket( | 815 | int iscsit_setup_np( |
765 | struct iscsi_np *np, | 816 | struct iscsi_np *np, |
766 | struct __kernel_sockaddr_storage *sockaddr) | 817 | struct __kernel_sockaddr_storage *sockaddr) |
767 | { | 818 | { |
768 | struct socket *sock; | 819 | struct socket *sock = NULL; |
769 | int backlog = 5, ret, opt = 0, len; | 820 | int backlog = 5, ret, opt = 0, len; |
770 | 821 | ||
771 | switch (np->np_network_transport) { | 822 | switch (np->np_network_transport) { |
@@ -781,15 +832,15 @@ int iscsi_target_setup_login_socket( | |||
781 | np->np_ip_proto = IPPROTO_SCTP; | 832 | np->np_ip_proto = IPPROTO_SCTP; |
782 | np->np_sock_type = SOCK_SEQPACKET; | 833 | np->np_sock_type = SOCK_SEQPACKET; |
783 | break; | 834 | break; |
784 | case ISCSI_IWARP_TCP: | ||
785 | case ISCSI_IWARP_SCTP: | ||
786 | case ISCSI_INFINIBAND: | ||
787 | default: | 835 | default: |
788 | pr_err("Unsupported network_transport: %d\n", | 836 | pr_err("Unsupported network_transport: %d\n", |
789 | np->np_network_transport); | 837 | np->np_network_transport); |
790 | return -EINVAL; | 838 | return -EINVAL; |
791 | } | 839 | } |
792 | 840 | ||
841 | np->np_ip_proto = IPPROTO_TCP; | ||
842 | np->np_sock_type = SOCK_STREAM; | ||
843 | |||
793 | ret = sock_create(sockaddr->ss_family, np->np_sock_type, | 844 | ret = sock_create(sockaddr->ss_family, np->np_sock_type, |
794 | np->np_ip_proto, &sock); | 845 | np->np_ip_proto, &sock); |
795 | if (ret < 0) { | 846 | if (ret < 0) { |
@@ -853,7 +904,6 @@ int iscsi_target_setup_login_socket( | |||
853 | } | 904 | } |
854 | 905 | ||
855 | return 0; | 906 | return 0; |
856 | |||
857 | fail: | 907 | fail: |
858 | np->np_socket = NULL; | 908 | np->np_socket = NULL; |
859 | if (sock) | 909 | if (sock) |
@@ -861,21 +911,170 @@ fail: | |||
861 | return ret; | 911 | return ret; |
862 | } | 912 | } |
863 | 913 | ||
914 | int iscsi_target_setup_login_socket( | ||
915 | struct iscsi_np *np, | ||
916 | struct __kernel_sockaddr_storage *sockaddr) | ||
917 | { | ||
918 | struct iscsit_transport *t; | ||
919 | int rc; | ||
920 | |||
921 | t = iscsit_get_transport(np->np_network_transport); | ||
922 | if (!t) | ||
923 | return -EINVAL; | ||
924 | |||
925 | rc = t->iscsit_setup_np(np, sockaddr); | ||
926 | if (rc < 0) { | ||
927 | iscsit_put_transport(t); | ||
928 | return rc; | ||
929 | } | ||
930 | |||
931 | np->np_transport = t; | ||
932 | printk("Set np->np_transport to %p -> %s\n", np->np_transport, | ||
933 | np->np_transport->name); | ||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) | ||
938 | { | ||
939 | struct socket *new_sock, *sock = np->np_socket; | ||
940 | struct sockaddr_in sock_in; | ||
941 | struct sockaddr_in6 sock_in6; | ||
942 | int rc, err; | ||
943 | |||
944 | rc = kernel_accept(sock, &new_sock, 0); | ||
945 | if (rc < 0) | ||
946 | return rc; | ||
947 | |||
948 | conn->sock = new_sock; | ||
949 | conn->login_family = np->np_sockaddr.ss_family; | ||
950 | printk("iSCSI/TCP: Setup conn->sock from new_sock: %p\n", new_sock); | ||
951 | |||
952 | if (np->np_sockaddr.ss_family == AF_INET6) { | ||
953 | memset(&sock_in6, 0, sizeof(struct sockaddr_in6)); | ||
954 | |||
955 | rc = conn->sock->ops->getname(conn->sock, | ||
956 | (struct sockaddr *)&sock_in6, &err, 1); | ||
957 | if (!rc) { | ||
958 | snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", | ||
959 | &sock_in6.sin6_addr.in6_u); | ||
960 | conn->login_port = ntohs(sock_in6.sin6_port); | ||
961 | } | ||
962 | |||
963 | rc = conn->sock->ops->getname(conn->sock, | ||
964 | (struct sockaddr *)&sock_in6, &err, 0); | ||
965 | if (!rc) { | ||
966 | snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", | ||
967 | &sock_in6.sin6_addr.in6_u); | ||
968 | conn->local_port = ntohs(sock_in6.sin6_port); | ||
969 | } | ||
970 | } else { | ||
971 | memset(&sock_in, 0, sizeof(struct sockaddr_in)); | ||
972 | |||
973 | rc = conn->sock->ops->getname(conn->sock, | ||
974 | (struct sockaddr *)&sock_in, &err, 1); | ||
975 | if (!rc) { | ||
976 | sprintf(conn->login_ip, "%pI4", | ||
977 | &sock_in.sin_addr.s_addr); | ||
978 | conn->login_port = ntohs(sock_in.sin_port); | ||
979 | } | ||
980 | |||
981 | rc = conn->sock->ops->getname(conn->sock, | ||
982 | (struct sockaddr *)&sock_in, &err, 0); | ||
983 | if (!rc) { | ||
984 | sprintf(conn->local_ip, "%pI4", | ||
985 | &sock_in.sin_addr.s_addr); | ||
986 | conn->local_port = ntohs(sock_in.sin_port); | ||
987 | } | ||
988 | } | ||
989 | |||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | int iscsit_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) | ||
994 | { | ||
995 | struct iscsi_login_req *login_req; | ||
996 | u32 padding = 0, payload_length; | ||
997 | |||
998 | if (iscsi_login_rx_data(conn, login->req, ISCSI_HDR_LEN) < 0) | ||
999 | return -1; | ||
1000 | |||
1001 | login_req = (struct iscsi_login_req *)login->req; | ||
1002 | payload_length = ntoh24(login_req->dlength); | ||
1003 | padding = ((-payload_length) & 3); | ||
1004 | |||
1005 | pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x," | ||
1006 | " CmdSN: 0x%08x, ExpStatSN: 0x%08x, CID: %hu, Length: %u\n", | ||
1007 | login_req->flags, login_req->itt, login_req->cmdsn, | ||
1008 | login_req->exp_statsn, login_req->cid, payload_length); | ||
1009 | /* | ||
1010 | * Setup the initial iscsi_login values from the leading | ||
1011 | * login request PDU. | ||
1012 | */ | ||
1013 | if (login->first_request) { | ||
1014 | login_req = (struct iscsi_login_req *)login->req; | ||
1015 | login->leading_connection = (!login_req->tsih) ? 1 : 0; | ||
1016 | login->current_stage = | ||
1017 | (login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2; | ||
1018 | login->version_min = login_req->min_version; | ||
1019 | login->version_max = login_req->max_version; | ||
1020 | memcpy(login->isid, login_req->isid, 6); | ||
1021 | login->cmd_sn = be32_to_cpu(login_req->cmdsn); | ||
1022 | login->init_task_tag = login_req->itt; | ||
1023 | login->initial_exp_statsn = be32_to_cpu(login_req->exp_statsn); | ||
1024 | login->cid = be16_to_cpu(login_req->cid); | ||
1025 | login->tsih = be16_to_cpu(login_req->tsih); | ||
1026 | } | ||
1027 | |||
1028 | if (iscsi_target_check_login_request(conn, login) < 0) | ||
1029 | return -1; | ||
1030 | |||
1031 | memset(login->req_buf, 0, MAX_KEY_VALUE_PAIRS); | ||
1032 | if (iscsi_login_rx_data(conn, login->req_buf, | ||
1033 | payload_length + padding) < 0) | ||
1034 | return -1; | ||
1035 | |||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | int iscsit_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, | ||
1040 | u32 length) | ||
1041 | { | ||
1042 | if (iscsi_login_tx_data(conn, login->rsp, login->rsp_buf, length) < 0) | ||
1043 | return -1; | ||
1044 | |||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | static int | ||
1049 | iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t) | ||
1050 | { | ||
1051 | int rc; | ||
1052 | |||
1053 | if (!t->owner) { | ||
1054 | conn->conn_transport = t; | ||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
1058 | rc = try_module_get(t->owner); | ||
1059 | if (!rc) { | ||
1060 | pr_err("try_module_get() failed for %s\n", t->name); | ||
1061 | return -EINVAL; | ||
1062 | } | ||
1063 | |||
1064 | conn->conn_transport = t; | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
864 | static int __iscsi_target_login_thread(struct iscsi_np *np) | 1068 | static int __iscsi_target_login_thread(struct iscsi_np *np) |
865 | { | 1069 | { |
866 | u8 buffer[ISCSI_HDR_LEN], iscsi_opcode, zero_tsih = 0; | 1070 | u8 *buffer, zero_tsih = 0; |
867 | int err, ret = 0, stop; | 1071 | int ret = 0, rc, stop; |
868 | struct iscsi_conn *conn = NULL; | 1072 | struct iscsi_conn *conn = NULL; |
869 | struct iscsi_login *login; | 1073 | struct iscsi_login *login; |
870 | struct iscsi_portal_group *tpg = NULL; | 1074 | struct iscsi_portal_group *tpg = NULL; |
871 | struct socket *new_sock, *sock; | ||
872 | struct kvec iov; | ||
873 | struct iscsi_login_req *pdu; | 1075 | struct iscsi_login_req *pdu; |
874 | struct sockaddr_in sock_in; | ||
875 | struct sockaddr_in6 sock_in6; | ||
876 | 1076 | ||
877 | flush_signals(current); | 1077 | flush_signals(current); |
878 | sock = np->np_socket; | ||
879 | 1078 | ||
880 | spin_lock_bh(&np->np_thread_lock); | 1079 | spin_lock_bh(&np->np_thread_lock); |
881 | if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { | 1080 | if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { |
@@ -886,75 +1085,76 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) | |||
886 | } | 1085 | } |
887 | spin_unlock_bh(&np->np_thread_lock); | 1086 | spin_unlock_bh(&np->np_thread_lock); |
888 | 1087 | ||
889 | if (kernel_accept(sock, &new_sock, 0) < 0) { | ||
890 | spin_lock_bh(&np->np_thread_lock); | ||
891 | if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { | ||
892 | spin_unlock_bh(&np->np_thread_lock); | ||
893 | complete(&np->np_restart_comp); | ||
894 | /* Get another socket */ | ||
895 | return 1; | ||
896 | } | ||
897 | spin_unlock_bh(&np->np_thread_lock); | ||
898 | goto out; | ||
899 | } | ||
900 | iscsi_start_login_thread_timer(np); | ||
901 | |||
902 | conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL); | 1088 | conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL); |
903 | if (!conn) { | 1089 | if (!conn) { |
904 | pr_err("Could not allocate memory for" | 1090 | pr_err("Could not allocate memory for" |
905 | " new connection\n"); | 1091 | " new connection\n"); |
906 | sock_release(new_sock); | ||
907 | /* Get another socket */ | 1092 | /* Get another socket */ |
908 | return 1; | 1093 | return 1; |
909 | } | 1094 | } |
910 | |||
911 | pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); | 1095 | pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); |
912 | conn->conn_state = TARG_CONN_STATE_FREE; | 1096 | conn->conn_state = TARG_CONN_STATE_FREE; |
913 | conn->sock = new_sock; | ||
914 | 1097 | ||
915 | pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n"); | 1098 | if (iscsit_conn_set_transport(conn, np->np_transport) < 0) { |
916 | conn->conn_state = TARG_CONN_STATE_XPT_UP; | 1099 | kfree(conn); |
1100 | return 1; | ||
1101 | } | ||
917 | 1102 | ||
918 | /* | 1103 | rc = np->np_transport->iscsit_accept_np(np, conn); |
919 | * Allocate conn->conn_ops early as a failure calling | 1104 | if (rc == -ENOSYS) { |
920 | * iscsit_tx_login_rsp() below will call tx_data(). | 1105 | complete(&np->np_restart_comp); |
921 | */ | 1106 | iscsit_put_transport(conn->conn_transport); |
922 | conn->conn_ops = kzalloc(sizeof(struct iscsi_conn_ops), GFP_KERNEL); | 1107 | kfree(conn); |
923 | if (!conn->conn_ops) { | 1108 | conn = NULL; |
924 | pr_err("Unable to allocate memory for" | 1109 | goto exit; |
925 | " struct iscsi_conn_ops.\n"); | 1110 | } else if (rc < 0) { |
926 | goto new_sess_out; | 1111 | spin_lock_bh(&np->np_thread_lock); |
1112 | if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { | ||
1113 | spin_unlock_bh(&np->np_thread_lock); | ||
1114 | complete(&np->np_restart_comp); | ||
1115 | if (ret == -ENODEV) { | ||
1116 | iscsit_put_transport(conn->conn_transport); | ||
1117 | kfree(conn); | ||
1118 | conn = NULL; | ||
1119 | goto out; | ||
1120 | } | ||
1121 | /* Get another socket */ | ||
1122 | return 1; | ||
1123 | } | ||
1124 | spin_unlock_bh(&np->np_thread_lock); | ||
1125 | iscsit_put_transport(conn->conn_transport); | ||
1126 | kfree(conn); | ||
1127 | conn = NULL; | ||
1128 | goto out; | ||
927 | } | 1129 | } |
928 | /* | 1130 | /* |
929 | * Perform the remaining iSCSI connection initialization items.. | 1131 | * Perform the remaining iSCSI connection initialization items.. |
930 | */ | 1132 | */ |
931 | if (iscsi_login_init_conn(conn) < 0) | 1133 | login = iscsi_login_init_conn(conn); |
932 | goto new_sess_out; | 1134 | if (!login) { |
933 | |||
934 | memset(buffer, 0, ISCSI_HDR_LEN); | ||
935 | memset(&iov, 0, sizeof(struct kvec)); | ||
936 | iov.iov_base = buffer; | ||
937 | iov.iov_len = ISCSI_HDR_LEN; | ||
938 | |||
939 | if (rx_data(conn, &iov, 1, ISCSI_HDR_LEN) <= 0) { | ||
940 | pr_err("rx_data() returned an error.\n"); | ||
941 | goto new_sess_out; | 1135 | goto new_sess_out; |
942 | } | 1136 | } |
943 | 1137 | ||
944 | iscsi_opcode = (buffer[0] & ISCSI_OPCODE_MASK); | 1138 | iscsi_start_login_thread_timer(np); |
945 | if (!(iscsi_opcode & ISCSI_OP_LOGIN)) { | ||
946 | pr_err("First opcode is not login request," | ||
947 | " failing login request.\n"); | ||
948 | goto new_sess_out; | ||
949 | } | ||
950 | 1139 | ||
951 | pdu = (struct iscsi_login_req *) buffer; | 1140 | pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n"); |
1141 | conn->conn_state = TARG_CONN_STATE_XPT_UP; | ||
1142 | /* | ||
1143 | * This will process the first login request + payload.. | ||
1144 | */ | ||
1145 | rc = np->np_transport->iscsit_get_login_rx(conn, login); | ||
1146 | if (rc == 1) | ||
1147 | return 1; | ||
1148 | else if (rc < 0) | ||
1149 | goto new_sess_out; | ||
952 | 1150 | ||
1151 | buffer = &login->req[0]; | ||
1152 | pdu = (struct iscsi_login_req *)buffer; | ||
953 | /* | 1153 | /* |
954 | * Used by iscsit_tx_login_rsp() for Login Resonses PDUs | 1154 | * Used by iscsit_tx_login_rsp() for Login Resonses PDUs |
955 | * when Status-Class != 0. | 1155 | * when Status-Class != 0. |
956 | */ | 1156 | */ |
957 | conn->login_itt = pdu->itt; | 1157 | conn->login_itt = pdu->itt; |
958 | 1158 | ||
959 | spin_lock_bh(&np->np_thread_lock); | 1159 | spin_lock_bh(&np->np_thread_lock); |
960 | if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) { | 1160 | if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) { |
@@ -967,61 +1167,11 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) | |||
967 | } | 1167 | } |
968 | spin_unlock_bh(&np->np_thread_lock); | 1168 | spin_unlock_bh(&np->np_thread_lock); |
969 | 1169 | ||
970 | if (np->np_sockaddr.ss_family == AF_INET6) { | ||
971 | memset(&sock_in6, 0, sizeof(struct sockaddr_in6)); | ||
972 | |||
973 | if (conn->sock->ops->getname(conn->sock, | ||
974 | (struct sockaddr *)&sock_in6, &err, 1) < 0) { | ||
975 | pr_err("sock_ops->getname() failed.\n"); | ||
976 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
977 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | ||
978 | goto new_sess_out; | ||
979 | } | ||
980 | snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", | ||
981 | &sock_in6.sin6_addr.in6_u); | ||
982 | conn->login_port = ntohs(sock_in6.sin6_port); | ||
983 | |||
984 | if (conn->sock->ops->getname(conn->sock, | ||
985 | (struct sockaddr *)&sock_in6, &err, 0) < 0) { | ||
986 | pr_err("sock_ops->getname() failed.\n"); | ||
987 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
988 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | ||
989 | goto new_sess_out; | ||
990 | } | ||
991 | snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", | ||
992 | &sock_in6.sin6_addr.in6_u); | ||
993 | conn->local_port = ntohs(sock_in6.sin6_port); | ||
994 | |||
995 | } else { | ||
996 | memset(&sock_in, 0, sizeof(struct sockaddr_in)); | ||
997 | |||
998 | if (conn->sock->ops->getname(conn->sock, | ||
999 | (struct sockaddr *)&sock_in, &err, 1) < 0) { | ||
1000 | pr_err("sock_ops->getname() failed.\n"); | ||
1001 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
1002 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | ||
1003 | goto new_sess_out; | ||
1004 | } | ||
1005 | sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr); | ||
1006 | conn->login_port = ntohs(sock_in.sin_port); | ||
1007 | |||
1008 | if (conn->sock->ops->getname(conn->sock, | ||
1009 | (struct sockaddr *)&sock_in, &err, 0) < 0) { | ||
1010 | pr_err("sock_ops->getname() failed.\n"); | ||
1011 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
1012 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | ||
1013 | goto new_sess_out; | ||
1014 | } | ||
1015 | sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr); | ||
1016 | conn->local_port = ntohs(sock_in.sin_port); | ||
1017 | } | ||
1018 | |||
1019 | conn->network_transport = np->np_network_transport; | 1170 | conn->network_transport = np->np_network_transport; |
1020 | 1171 | ||
1021 | pr_debug("Received iSCSI login request from %s on %s Network" | 1172 | pr_debug("Received iSCSI login request from %s on %s Network" |
1022 | " Portal %s:%hu\n", conn->login_ip, | 1173 | " Portal %s:%hu\n", conn->login_ip, np->np_transport->name, |
1023 | (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP", | 1174 | conn->local_ip, conn->local_port); |
1024 | conn->local_ip, conn->local_port); | ||
1025 | 1175 | ||
1026 | pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n"); | 1176 | pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n"); |
1027 | conn->conn_state = TARG_CONN_STATE_IN_LOGIN; | 1177 | conn->conn_state = TARG_CONN_STATE_IN_LOGIN; |
@@ -1050,13 +1200,17 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) | |||
1050 | if (iscsi_login_non_zero_tsih_s1(conn, buffer) < 0) | 1200 | if (iscsi_login_non_zero_tsih_s1(conn, buffer) < 0) |
1051 | goto new_sess_out; | 1201 | goto new_sess_out; |
1052 | } | 1202 | } |
1053 | |||
1054 | /* | 1203 | /* |
1055 | * This will process the first login request, and call | 1204 | * SessionType: Discovery |
1056 | * iscsi_target_locate_portal(), and return a valid struct iscsi_login. | 1205 | * |
1206 | * Locates Default Portal | ||
1207 | * | ||
1208 | * SessionType: Normal | ||
1209 | * | ||
1210 | * Locates Target Portal from NP -> Target IQN | ||
1057 | */ | 1211 | */ |
1058 | login = iscsi_target_init_negotiation(np, conn, buffer); | 1212 | rc = iscsi_target_locate_portal(np, conn, login); |
1059 | if (!login) { | 1213 | if (rc < 0) { |
1060 | tpg = conn->tpg; | 1214 | tpg = conn->tpg; |
1061 | goto new_sess_out; | 1215 | goto new_sess_out; |
1062 | } | 1216 | } |
@@ -1068,15 +1222,11 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) | |||
1068 | } | 1222 | } |
1069 | 1223 | ||
1070 | if (zero_tsih) { | 1224 | if (zero_tsih) { |
1071 | if (iscsi_login_zero_tsih_s2(conn) < 0) { | 1225 | if (iscsi_login_zero_tsih_s2(conn) < 0) |
1072 | iscsi_target_nego_release(login, conn); | ||
1073 | goto new_sess_out; | 1226 | goto new_sess_out; |
1074 | } | ||
1075 | } else { | 1227 | } else { |
1076 | if (iscsi_login_non_zero_tsih_s2(conn, buffer) < 0) { | 1228 | if (iscsi_login_non_zero_tsih_s2(conn, buffer) < 0) |
1077 | iscsi_target_nego_release(login, conn); | ||
1078 | goto old_sess_out; | 1229 | goto old_sess_out; |
1079 | } | ||
1080 | } | 1230 | } |
1081 | 1231 | ||
1082 | if (iscsi_target_start_negotiation(login, conn) < 0) | 1232 | if (iscsi_target_start_negotiation(login, conn) < 0) |
@@ -1153,8 +1303,18 @@ old_sess_out: | |||
1153 | iscsi_release_param_list(conn->param_list); | 1303 | iscsi_release_param_list(conn->param_list); |
1154 | conn->param_list = NULL; | 1304 | conn->param_list = NULL; |
1155 | } | 1305 | } |
1156 | if (conn->sock) | 1306 | iscsi_target_nego_release(conn); |
1307 | |||
1308 | if (conn->sock) { | ||
1157 | sock_release(conn->sock); | 1309 | sock_release(conn->sock); |
1310 | conn->sock = NULL; | ||
1311 | } | ||
1312 | |||
1313 | if (conn->conn_transport->iscsit_free_conn) | ||
1314 | conn->conn_transport->iscsit_free_conn(conn); | ||
1315 | |||
1316 | iscsit_put_transport(conn->conn_transport); | ||
1317 | |||
1158 | kfree(conn); | 1318 | kfree(conn); |
1159 | 1319 | ||
1160 | if (tpg) { | 1320 | if (tpg) { |
@@ -1172,11 +1332,13 @@ out: | |||
1172 | /* Wait for another socket.. */ | 1332 | /* Wait for another socket.. */ |
1173 | if (!stop) | 1333 | if (!stop) |
1174 | return 1; | 1334 | return 1; |
1175 | 1335 | exit: | |
1176 | iscsi_stop_login_thread_timer(np); | 1336 | iscsi_stop_login_thread_timer(np); |
1177 | spin_lock_bh(&np->np_thread_lock); | 1337 | spin_lock_bh(&np->np_thread_lock); |
1178 | np->np_thread_state = ISCSI_NP_THREAD_EXIT; | 1338 | np->np_thread_state = ISCSI_NP_THREAD_EXIT; |
1339 | np->np_thread = NULL; | ||
1179 | spin_unlock_bh(&np->np_thread_lock); | 1340 | spin_unlock_bh(&np->np_thread_lock); |
1341 | |||
1180 | return 0; | 1342 | return 0; |
1181 | } | 1343 | } |
1182 | 1344 | ||
diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h index 091dcae2532b..63efd2878451 100644 --- a/drivers/target/iscsi/iscsi_target_login.h +++ b/drivers/target/iscsi/iscsi_target_login.h | |||
@@ -4,8 +4,14 @@ | |||
4 | extern int iscsi_login_setup_crypto(struct iscsi_conn *); | 4 | extern int iscsi_login_setup_crypto(struct iscsi_conn *); |
5 | extern int iscsi_check_for_session_reinstatement(struct iscsi_conn *); | 5 | extern int iscsi_check_for_session_reinstatement(struct iscsi_conn *); |
6 | extern int iscsi_login_post_auth_non_zero_tsih(struct iscsi_conn *, u16, u32); | 6 | extern int iscsi_login_post_auth_non_zero_tsih(struct iscsi_conn *, u16, u32); |
7 | extern int iscsit_setup_np(struct iscsi_np *, | ||
8 | struct __kernel_sockaddr_storage *); | ||
7 | extern int iscsi_target_setup_login_socket(struct iscsi_np *, | 9 | extern int iscsi_target_setup_login_socket(struct iscsi_np *, |
8 | struct __kernel_sockaddr_storage *); | 10 | struct __kernel_sockaddr_storage *); |
11 | extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *); | ||
12 | extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); | ||
13 | extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); | ||
14 | extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); | ||
9 | extern int iscsi_target_login_thread(void *); | 15 | extern int iscsi_target_login_thread(void *); |
10 | extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *); | 16 | extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *); |
11 | 17 | ||
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 3cbdccd77e0b..879a0cb44bc3 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <scsi/iscsi_proto.h> | 22 | #include <scsi/iscsi_proto.h> |
23 | #include <target/target_core_base.h> | 23 | #include <target/target_core_base.h> |
24 | #include <target/target_core_fabric.h> | 24 | #include <target/target_core_fabric.h> |
25 | #include <target/iscsi/iscsi_transport.h> | ||
25 | 26 | ||
26 | #include "iscsi_target_core.h" | 27 | #include "iscsi_target_core.h" |
27 | #include "iscsi_target_parameters.h" | 28 | #include "iscsi_target_parameters.h" |
@@ -169,7 +170,7 @@ static void iscsi_remove_failed_auth_entry(struct iscsi_conn *conn) | |||
169 | kfree(conn->auth_protocol); | 170 | kfree(conn->auth_protocol); |
170 | } | 171 | } |
171 | 172 | ||
172 | static int iscsi_target_check_login_request( | 173 | int iscsi_target_check_login_request( |
173 | struct iscsi_conn *conn, | 174 | struct iscsi_conn *conn, |
174 | struct iscsi_login *login) | 175 | struct iscsi_login *login) |
175 | { | 176 | { |
@@ -352,11 +353,8 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log | |||
352 | 353 | ||
353 | padding = ((-login->rsp_length) & 3); | 354 | padding = ((-login->rsp_length) & 3); |
354 | 355 | ||
355 | if (iscsi_login_tx_data( | 356 | if (conn->conn_transport->iscsit_put_login_tx(conn, login, |
356 | conn, | 357 | login->rsp_length + padding) < 0) |
357 | login->rsp, | ||
358 | login->rsp_buf, | ||
359 | login->rsp_length + padding) < 0) | ||
360 | return -1; | 358 | return -1; |
361 | 359 | ||
362 | login->rsp_length = 0; | 360 | login->rsp_length = 0; |
@@ -368,72 +366,12 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log | |||
368 | return 0; | 366 | return 0; |
369 | } | 367 | } |
370 | 368 | ||
371 | static int iscsi_target_do_rx_login_io(struct iscsi_conn *conn, struct iscsi_login *login) | ||
372 | { | ||
373 | u32 padding = 0, payload_length; | ||
374 | struct iscsi_login_req *login_req; | ||
375 | |||
376 | if (iscsi_login_rx_data(conn, login->req, ISCSI_HDR_LEN) < 0) | ||
377 | return -1; | ||
378 | |||
379 | login_req = (struct iscsi_login_req *) login->req; | ||
380 | payload_length = ntoh24(login_req->dlength); | ||
381 | |||
382 | pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x," | ||
383 | " CmdSN: 0x%08x, ExpStatSN: 0x%08x, CID: %hu, Length: %u\n", | ||
384 | login_req->flags, login_req->itt, login_req->cmdsn, | ||
385 | login_req->exp_statsn, login_req->cid, payload_length); | ||
386 | |||
387 | if (iscsi_target_check_login_request(conn, login) < 0) | ||
388 | return -1; | ||
389 | |||
390 | padding = ((-payload_length) & 3); | ||
391 | memset(login->req_buf, 0, MAX_KEY_VALUE_PAIRS); | ||
392 | |||
393 | if (iscsi_login_rx_data( | ||
394 | conn, | ||
395 | login->req_buf, | ||
396 | payload_length + padding) < 0) | ||
397 | return -1; | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int iscsi_target_do_login_io(struct iscsi_conn *conn, struct iscsi_login *login) | 369 | static int iscsi_target_do_login_io(struct iscsi_conn *conn, struct iscsi_login *login) |
403 | { | 370 | { |
404 | if (iscsi_target_do_tx_login_io(conn, login) < 0) | 371 | if (iscsi_target_do_tx_login_io(conn, login) < 0) |
405 | return -1; | 372 | return -1; |
406 | 373 | ||
407 | if (iscsi_target_do_rx_login_io(conn, login) < 0) | 374 | if (conn->conn_transport->iscsit_get_login_rx(conn, login) < 0) |
408 | return -1; | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int iscsi_target_get_initial_payload( | ||
414 | struct iscsi_conn *conn, | ||
415 | struct iscsi_login *login) | ||
416 | { | ||
417 | u32 padding = 0, payload_length; | ||
418 | struct iscsi_login_req *login_req; | ||
419 | |||
420 | login_req = (struct iscsi_login_req *) login->req; | ||
421 | payload_length = ntoh24(login_req->dlength); | ||
422 | |||
423 | pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x," | ||
424 | " CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n", | ||
425 | login_req->flags, login_req->itt, login_req->cmdsn, | ||
426 | login_req->exp_statsn, payload_length); | ||
427 | |||
428 | if (iscsi_target_check_login_request(conn, login) < 0) | ||
429 | return -1; | ||
430 | |||
431 | padding = ((-payload_length) & 3); | ||
432 | |||
433 | if (iscsi_login_rx_data( | ||
434 | conn, | ||
435 | login->req_buf, | ||
436 | payload_length + padding) < 0) | ||
437 | return -1; | 375 | return -1; |
438 | 376 | ||
439 | return 0; | 377 | return 0; |
@@ -693,6 +631,7 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo | |||
693 | return -1; | 631 | return -1; |
694 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { | 632 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { |
695 | login->tsih = conn->sess->tsih; | 633 | login->tsih = conn->sess->tsih; |
634 | login->login_complete = 1; | ||
696 | if (iscsi_target_do_tx_login_io(conn, | 635 | if (iscsi_target_do_tx_login_io(conn, |
697 | login) < 0) | 636 | login) < 0) |
698 | return -1; | 637 | return -1; |
@@ -736,7 +675,7 @@ static void iscsi_initiatorname_tolower( | |||
736 | /* | 675 | /* |
737 | * Processes the first Login Request.. | 676 | * Processes the first Login Request.. |
738 | */ | 677 | */ |
739 | static int iscsi_target_locate_portal( | 678 | int iscsi_target_locate_portal( |
740 | struct iscsi_np *np, | 679 | struct iscsi_np *np, |
741 | struct iscsi_conn *conn, | 680 | struct iscsi_conn *conn, |
742 | struct iscsi_login *login) | 681 | struct iscsi_login *login) |
@@ -798,6 +737,8 @@ static int iscsi_target_locate_portal( | |||
798 | start += strlen(key) + strlen(value) + 2; | 737 | start += strlen(key) + strlen(value) + 2; |
799 | } | 738 | } |
800 | 739 | ||
740 | printk("i_buf: %s, s_buf: %s, t_buf: %s\n", i_buf, s_buf, t_buf); | ||
741 | |||
801 | /* | 742 | /* |
802 | * See 5.3. Login Phase. | 743 | * See 5.3. Login Phase. |
803 | */ | 744 | */ |
@@ -956,100 +897,30 @@ out: | |||
956 | return ret; | 897 | return ret; |
957 | } | 898 | } |
958 | 899 | ||
959 | struct iscsi_login *iscsi_target_init_negotiation( | ||
960 | struct iscsi_np *np, | ||
961 | struct iscsi_conn *conn, | ||
962 | char *login_pdu) | ||
963 | { | ||
964 | struct iscsi_login *login; | ||
965 | |||
966 | login = kzalloc(sizeof(struct iscsi_login), GFP_KERNEL); | ||
967 | if (!login) { | ||
968 | pr_err("Unable to allocate memory for struct iscsi_login.\n"); | ||
969 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
970 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | ||
971 | return NULL; | ||
972 | } | ||
973 | |||
974 | login->req = kmemdup(login_pdu, ISCSI_HDR_LEN, GFP_KERNEL); | ||
975 | if (!login->req) { | ||
976 | pr_err("Unable to allocate memory for Login Request.\n"); | ||
977 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
978 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | ||
979 | goto out; | ||
980 | } | ||
981 | |||
982 | login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL); | ||
983 | if (!login->req_buf) { | ||
984 | pr_err("Unable to allocate memory for response buffer.\n"); | ||
985 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
986 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | ||
987 | goto out; | ||
988 | } | ||
989 | /* | ||
990 | * SessionType: Discovery | ||
991 | * | ||
992 | * Locates Default Portal | ||
993 | * | ||
994 | * SessionType: Normal | ||
995 | * | ||
996 | * Locates Target Portal from NP -> Target IQN | ||
997 | */ | ||
998 | if (iscsi_target_locate_portal(np, conn, login) < 0) { | ||
999 | goto out; | ||
1000 | } | ||
1001 | |||
1002 | return login; | ||
1003 | out: | ||
1004 | kfree(login->req); | ||
1005 | kfree(login->req_buf); | ||
1006 | kfree(login); | ||
1007 | |||
1008 | return NULL; | ||
1009 | } | ||
1010 | |||
1011 | int iscsi_target_start_negotiation( | 900 | int iscsi_target_start_negotiation( |
1012 | struct iscsi_login *login, | 901 | struct iscsi_login *login, |
1013 | struct iscsi_conn *conn) | 902 | struct iscsi_conn *conn) |
1014 | { | 903 | { |
1015 | int ret = -1; | 904 | int ret; |
1016 | |||
1017 | login->rsp = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL); | ||
1018 | if (!login->rsp) { | ||
1019 | pr_err("Unable to allocate memory for" | ||
1020 | " Login Response.\n"); | ||
1021 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
1022 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | ||
1023 | ret = -1; | ||
1024 | goto out; | ||
1025 | } | ||
1026 | |||
1027 | login->rsp_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL); | ||
1028 | if (!login->rsp_buf) { | ||
1029 | pr_err("Unable to allocate memory for" | ||
1030 | " request buffer.\n"); | ||
1031 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | ||
1032 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | ||
1033 | ret = -1; | ||
1034 | goto out; | ||
1035 | } | ||
1036 | 905 | ||
1037 | ret = iscsi_target_do_login(conn, login); | 906 | ret = iscsi_target_do_login(conn, login); |
1038 | out: | ||
1039 | if (ret != 0) | 907 | if (ret != 0) |
1040 | iscsi_remove_failed_auth_entry(conn); | 908 | iscsi_remove_failed_auth_entry(conn); |
1041 | 909 | ||
1042 | iscsi_target_nego_release(login, conn); | 910 | iscsi_target_nego_release(conn); |
1043 | return ret; | 911 | return ret; |
1044 | } | 912 | } |
1045 | 913 | ||
1046 | void iscsi_target_nego_release( | 914 | void iscsi_target_nego_release(struct iscsi_conn *conn) |
1047 | struct iscsi_login *login, | ||
1048 | struct iscsi_conn *conn) | ||
1049 | { | 915 | { |
1050 | kfree(login->req); | 916 | struct iscsi_login *login = conn->conn_login; |
1051 | kfree(login->rsp); | 917 | |
918 | if (!login) | ||
919 | return; | ||
920 | |||
1052 | kfree(login->req_buf); | 921 | kfree(login->req_buf); |
1053 | kfree(login->rsp_buf); | 922 | kfree(login->rsp_buf); |
1054 | kfree(login); | 923 | kfree(login); |
924 | |||
925 | conn->conn_login = NULL; | ||
1055 | } | 926 | } |
diff --git a/drivers/target/iscsi/iscsi_target_nego.h b/drivers/target/iscsi/iscsi_target_nego.h index 92e133a5158f..f021cbd330e5 100644 --- a/drivers/target/iscsi/iscsi_target_nego.h +++ b/drivers/target/iscsi/iscsi_target_nego.h | |||
@@ -7,11 +7,14 @@ | |||
7 | extern void convert_null_to_semi(char *, int); | 7 | extern void convert_null_to_semi(char *, int); |
8 | extern int extract_param(const char *, const char *, unsigned int, char *, | 8 | extern int extract_param(const char *, const char *, unsigned int, char *, |
9 | unsigned char *); | 9 | unsigned char *); |
10 | extern struct iscsi_login *iscsi_target_init_negotiation( | 10 | extern int iscsi_target_check_login_request(struct iscsi_conn *, |
11 | struct iscsi_np *, struct iscsi_conn *, char *); | 11 | struct iscsi_login *); |
12 | extern int iscsi_target_get_initial_payload(struct iscsi_conn *, | ||
13 | struct iscsi_login *); | ||
14 | extern int iscsi_target_locate_portal(struct iscsi_np *, struct iscsi_conn *, | ||
15 | struct iscsi_login *); | ||
12 | extern int iscsi_target_start_negotiation( | 16 | extern int iscsi_target_start_negotiation( |
13 | struct iscsi_login *, struct iscsi_conn *); | 17 | struct iscsi_login *, struct iscsi_conn *); |
14 | extern void iscsi_target_nego_release( | 18 | extern void iscsi_target_nego_release(struct iscsi_conn *); |
15 | struct iscsi_login *, struct iscsi_conn *); | ||
16 | 19 | ||
17 | #endif /* ISCSI_TARGET_NEGO_H */ | 20 | #endif /* ISCSI_TARGET_NEGO_H */ |
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index ca2be406f141..84ce94a14948 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c | |||
@@ -59,7 +59,7 @@ int iscsi_login_tx_data( | |||
59 | char *text_buf, | 59 | char *text_buf, |
60 | int text_length) | 60 | int text_length) |
61 | { | 61 | { |
62 | int length, tx_sent; | 62 | int length, tx_sent, iov_cnt = 1; |
63 | struct kvec iov[2]; | 63 | struct kvec iov[2]; |
64 | 64 | ||
65 | length = (ISCSI_HDR_LEN + text_length); | 65 | length = (ISCSI_HDR_LEN + text_length); |
@@ -67,8 +67,12 @@ int iscsi_login_tx_data( | |||
67 | memset(&iov[0], 0, 2 * sizeof(struct kvec)); | 67 | memset(&iov[0], 0, 2 * sizeof(struct kvec)); |
68 | iov[0].iov_len = ISCSI_HDR_LEN; | 68 | iov[0].iov_len = ISCSI_HDR_LEN; |
69 | iov[0].iov_base = pdu_buf; | 69 | iov[0].iov_base = pdu_buf; |
70 | iov[1].iov_len = text_length; | 70 | |
71 | iov[1].iov_base = text_buf; | 71 | if (text_buf && text_length) { |
72 | iov[1].iov_len = text_length; | ||
73 | iov[1].iov_base = text_buf; | ||
74 | iov_cnt++; | ||
75 | } | ||
72 | 76 | ||
73 | /* | 77 | /* |
74 | * Initial Marker-less Interval. | 78 | * Initial Marker-less Interval. |
@@ -77,7 +81,7 @@ int iscsi_login_tx_data( | |||
77 | */ | 81 | */ |
78 | conn->if_marker += length; | 82 | conn->if_marker += length; |
79 | 83 | ||
80 | tx_sent = tx_data(conn, &iov[0], 2, length); | 84 | tx_sent = tx_data(conn, &iov[0], iov_cnt, length); |
81 | if (tx_sent != length) { | 85 | if (tx_sent != length) { |
82 | pr_err("tx_data returned %d, expecting %d.\n", | 86 | pr_err("tx_data returned %d, expecting %d.\n", |
83 | tx_sent, length); | 87 | tx_sent, length); |
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index ee8f8c66248d..439260b7d87f 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include "iscsi_target.h" | 31 | #include "iscsi_target.h" |
32 | #include "iscsi_target_parameters.h" | 32 | #include "iscsi_target_parameters.h" |
33 | 33 | ||
34 | #include <target/iscsi/iscsi_transport.h> | ||
35 | |||
34 | struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *tiqn, u16 tpgt) | 36 | struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *tiqn, u16 tpgt) |
35 | { | 37 | { |
36 | struct iscsi_portal_group *tpg; | 38 | struct iscsi_portal_group *tpg; |
@@ -508,7 +510,7 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal( | |||
508 | 510 | ||
509 | pr_debug("CORE[%s] - Added Network Portal: %s:%hu,%hu on %s\n", | 511 | pr_debug("CORE[%s] - Added Network Portal: %s:%hu,%hu on %s\n", |
510 | tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt, | 512 | tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt, |
511 | (np->np_network_transport == ISCSI_TCP) ? "TCP" : "SCTP"); | 513 | np->np_transport->name); |
512 | 514 | ||
513 | return tpg_np; | 515 | return tpg_np; |
514 | } | 516 | } |
@@ -522,7 +524,7 @@ static int iscsit_tpg_release_np( | |||
522 | 524 | ||
523 | pr_debug("CORE[%s] - Removed Network Portal: %s:%hu,%hu on %s\n", | 525 | pr_debug("CORE[%s] - Removed Network Portal: %s:%hu,%hu on %s\n", |
524 | tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt, | 526 | tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt, |
525 | (np->np_network_transport == ISCSI_TCP) ? "TCP" : "SCTP"); | 527 | np->np_transport->name); |
526 | 528 | ||
527 | tpg_np->tpg_np = NULL; | 529 | tpg_np->tpg_np = NULL; |
528 | tpg_np->tpg = NULL; | 530 | tpg_np->tpg = NULL; |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 7ce350578c82..4cf1e7f94ac3 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <target/target_core_base.h> | 24 | #include <target/target_core_base.h> |
25 | #include <target/target_core_fabric.h> | 25 | #include <target/target_core_fabric.h> |
26 | #include <target/target_core_configfs.h> | 26 | #include <target/target_core_configfs.h> |
27 | #include <target/iscsi/iscsi_transport.h> | ||
27 | 28 | ||
28 | #include "iscsi_target_core.h" | 29 | #include "iscsi_target_core.h" |
29 | #include "iscsi_target_parameters.h" | 30 | #include "iscsi_target_parameters.h" |
@@ -1226,34 +1227,19 @@ send_datacrc: | |||
1226 | */ | 1227 | */ |
1227 | int iscsit_tx_login_rsp(struct iscsi_conn *conn, u8 status_class, u8 status_detail) | 1228 | int iscsit_tx_login_rsp(struct iscsi_conn *conn, u8 status_class, u8 status_detail) |
1228 | { | 1229 | { |
1229 | u8 iscsi_hdr[ISCSI_HDR_LEN]; | ||
1230 | int err; | ||
1231 | struct kvec iov; | ||
1232 | struct iscsi_login_rsp *hdr; | 1230 | struct iscsi_login_rsp *hdr; |
1231 | struct iscsi_login *login = conn->conn_login; | ||
1233 | 1232 | ||
1233 | login->login_failed = 1; | ||
1234 | iscsit_collect_login_stats(conn, status_class, status_detail); | 1234 | iscsit_collect_login_stats(conn, status_class, status_detail); |
1235 | 1235 | ||
1236 | memset(&iov, 0, sizeof(struct kvec)); | 1236 | hdr = (struct iscsi_login_rsp *)&login->rsp[0]; |
1237 | memset(&iscsi_hdr, 0x0, ISCSI_HDR_LEN); | ||
1238 | |||
1239 | hdr = (struct iscsi_login_rsp *)&iscsi_hdr; | ||
1240 | hdr->opcode = ISCSI_OP_LOGIN_RSP; | 1237 | hdr->opcode = ISCSI_OP_LOGIN_RSP; |
1241 | hdr->status_class = status_class; | 1238 | hdr->status_class = status_class; |
1242 | hdr->status_detail = status_detail; | 1239 | hdr->status_detail = status_detail; |
1243 | hdr->itt = conn->login_itt; | 1240 | hdr->itt = conn->login_itt; |
1244 | 1241 | ||
1245 | iov.iov_base = &iscsi_hdr; | 1242 | return conn->conn_transport->iscsit_put_login_tx(conn, login, 0); |
1246 | iov.iov_len = ISCSI_HDR_LEN; | ||
1247 | |||
1248 | PRINT_BUFF(iscsi_hdr, ISCSI_HDR_LEN); | ||
1249 | |||
1250 | err = tx_data(conn, &iov, 1, ISCSI_HDR_LEN); | ||
1251 | if (err != ISCSI_HDR_LEN) { | ||
1252 | pr_err("tx_data returned less than expected\n"); | ||
1253 | return -1; | ||
1254 | } | ||
1255 | |||
1256 | return 0; | ||
1257 | } | 1243 | } |
1258 | 1244 | ||
1259 | void iscsit_print_session_params(struct iscsi_session *sess) | 1245 | void iscsit_print_session_params(struct iscsi_session *sess) |
@@ -1432,7 +1418,8 @@ void iscsit_collect_login_stats( | |||
1432 | strcpy(ls->last_intr_fail_name, | 1418 | strcpy(ls->last_intr_fail_name, |
1433 | (intrname ? intrname->value : "Unknown")); | 1419 | (intrname ? intrname->value : "Unknown")); |
1434 | 1420 | ||
1435 | ls->last_intr_fail_ip_family = conn->sock->sk->sk_family; | 1421 | ls->last_intr_fail_ip_family = conn->login_family; |
1422 | |||
1436 | snprintf(ls->last_intr_fail_ip_addr, IPV6_ADDRESS_SPACE, | 1423 | snprintf(ls->last_intr_fail_ip_addr, IPV6_ADDRESS_SPACE, |
1437 | "%s", conn->login_ip); | 1424 | "%s", conn->login_ip); |
1438 | ls->last_fail_time = get_jiffies_64(); | 1425 | ls->last_fail_time = get_jiffies_64(); |