aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-03-07 00:54:13 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2013-04-25 04:05:26 -0400
commitbaa4d64b147a4064626f6597646ae8a330d9e2ed (patch)
tree5d017ffcfc1372d112f3f54ccd8621f703c91f25
parent3f99306337ba1871afc8568e8b36004ce3cee039 (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.c35
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h15
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c416
-rw-r--r--drivers/target/iscsi/iscsi_target_login.h6
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c167
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.h11
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c12
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c27
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
52static LIST_HEAD(g_tiqn_list); 54static LIST_HEAD(g_tiqn_list);
53static LIST_HEAD(g_np_list); 55static LIST_HEAD(g_np_list);
54static DEFINE_SPINLOCK(tiqn_lock); 56static 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
444static int iscsit_del_np_comm(struct iscsi_np *np) 445static 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
451int iscsit_del_np(struct iscsi_np *np) 451int 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
485static 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
484static int __init iscsi_target_init_module(void) 496static 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
63enum tpg_np_network_transport_table { 63enum 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
679struct iscsi_node_attrib { 686struct 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
42static int iscsi_login_init_conn(struct iscsi_conn *conn) 42#include <target/iscsi/iscsi_transport.h>
43
44static 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
102out_conn_ops:
103 kfree(conn->conn_ops);
104out_rsp_buf:
105 kfree(login->rsp_buf);
106out_req_buf:
107 kfree(login->req_buf);
108out_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
574static void iscsi_post_login_start_timers(struct iscsi_conn *conn) 616static 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
582static int iscsi_post_login_handler( 627static 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
764int iscsi_target_setup_login_socket( 815int 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
857fail: 907fail:
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
914int 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
937int 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
993int 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
1039int 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
1048static int
1049iscsit_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
864static int __iscsi_target_login_thread(struct iscsi_np *np) 1068static 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 1335exit:
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 @@
4extern int iscsi_login_setup_crypto(struct iscsi_conn *); 4extern int iscsi_login_setup_crypto(struct iscsi_conn *);
5extern int iscsi_check_for_session_reinstatement(struct iscsi_conn *); 5extern int iscsi_check_for_session_reinstatement(struct iscsi_conn *);
6extern int iscsi_login_post_auth_non_zero_tsih(struct iscsi_conn *, u16, u32); 6extern int iscsi_login_post_auth_non_zero_tsih(struct iscsi_conn *, u16, u32);
7extern int iscsit_setup_np(struct iscsi_np *,
8 struct __kernel_sockaddr_storage *);
7extern int iscsi_target_setup_login_socket(struct iscsi_np *, 9extern int iscsi_target_setup_login_socket(struct iscsi_np *,
8 struct __kernel_sockaddr_storage *); 10 struct __kernel_sockaddr_storage *);
11extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
12extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
13extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
14extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *);
9extern int iscsi_target_login_thread(void *); 15extern int iscsi_target_login_thread(void *);
10extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *); 16extern 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
172static int iscsi_target_check_login_request( 173int 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
371static 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
402static int iscsi_target_do_login_io(struct iscsi_conn *conn, struct iscsi_login *login) 369static 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
413static 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 */
739static int iscsi_target_locate_portal( 678int 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
959struct 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;
1003out:
1004 kfree(login->req);
1005 kfree(login->req_buf);
1006 kfree(login);
1007
1008 return NULL;
1009}
1010
1011int iscsi_target_start_negotiation( 900int 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);
1038out:
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
1046void iscsi_target_nego_release( 914void 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 @@
7extern void convert_null_to_semi(char *, int); 7extern void convert_null_to_semi(char *, int);
8extern int extract_param(const char *, const char *, unsigned int, char *, 8extern int extract_param(const char *, const char *, unsigned int, char *,
9 unsigned char *); 9 unsigned char *);
10extern struct iscsi_login *iscsi_target_init_negotiation( 10extern int iscsi_target_check_login_request(struct iscsi_conn *,
11 struct iscsi_np *, struct iscsi_conn *, char *); 11 struct iscsi_login *);
12extern int iscsi_target_get_initial_payload(struct iscsi_conn *,
13 struct iscsi_login *);
14extern int iscsi_target_locate_portal(struct iscsi_np *, struct iscsi_conn *,
15 struct iscsi_login *);
12extern int iscsi_target_start_negotiation( 16extern int iscsi_target_start_negotiation(
13 struct iscsi_login *, struct iscsi_conn *); 17 struct iscsi_login *, struct iscsi_conn *);
14extern void iscsi_target_nego_release( 18extern 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
34struct iscsi_portal_group *iscsit_alloc_portal_group(struct iscsi_tiqn *tiqn, u16 tpgt) 36struct 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 */
1227int iscsit_tx_login_rsp(struct iscsi_conn *conn, u8 status_class, u8 status_detail) 1228int 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
1259void iscsit_print_session_params(struct iscsi_session *sess) 1245void 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();