From 52e04267038cb71a693df12b70d0a99f7b149368 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 28 Jan 2014 04:13:12 +0000 Subject: [PATCH] [PATCH 2/9] iscsi: Move TCP code over to transport API Replace iscsi-tcp specific calls with transport API calls in order to be able to override them with iser implementation specifics. Make iscsi-tcp specific debug print into a general print Refactor conn close code to work with isert Only allocate RX data in NOP for iscsi-tcp In case of iser, the data is already received Signed-off-by: Yan Burman git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/iser@5230 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/conn.c | 90 +++++------- iscsi-scst/kernel/iscsi.c | 273 +++++++++++++++++++++++++----------- iscsi-scst/kernel/iscsi.h | 9 +- iscsi-scst/kernel/nthread.c | 42 +++--- iscsi-scst/kernel/target.c | 9 ++ 5 files changed, 269 insertions(+), 154 deletions(-) diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index 3e14fe82c..e3396ddd5 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -21,6 +21,7 @@ #include "iscsi.h" #include "digest.h" +#include "iscsit_transport.h" #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) #if defined(CONFIG_LOCKDEP) && !defined(CONFIG_SCST_PROC) @@ -158,42 +159,7 @@ struct kobj_type iscsi_conn_ktype = { static ssize_t iscsi_get_initiator_ip(struct iscsi_conn *conn, char *buf, int size) { - int pos; - struct sock *sk; - - TRACE_ENTRY(); - - sk = conn->sock->sk; - switch (sk->sk_family) { - case AF_INET: - pos = scnprintf(buf, size, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr)); -#else - "%pI4", &inet_sk(sk)->inet_daddr); -#endif - break; - case AF_INET6: -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - pos = scnprintf(buf, size, - "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]", - NIP6(inet6_sk(sk)->daddr)); -#else -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) - pos = scnprintf(buf, size, "[%p6]", &inet6_sk(sk)->daddr); -#else - pos = scnprintf(buf, size, "[%p6]", &sk->sk_v6_daddr); -#endif -#endif - break; - default: - pos = scnprintf(buf, size, "Unknown family %d", - sk->sk_family); - break; - } - - TRACE_EXIT_RES(pos); - return pos; + return conn->transport->iscsit_get_initiator_ip(conn, buf, size); } static ssize_t iscsi_conn_ip_show(struct kobject *kobj, @@ -431,7 +397,7 @@ void iscsi_make_conn_wr_active(struct iscsi_conn *conn) return; } -void __mark_conn_closed(struct iscsi_conn *conn, int flags) +void iscsi_tcp_mark_conn_closed(struct iscsi_conn *conn, int flags) { spin_lock_bh(&conn->conn_thr_pool->rd_lock); conn->closing = 1; @@ -444,6 +410,11 @@ void __mark_conn_closed(struct iscsi_conn *conn, int flags) iscsi_make_conn_rd_active(conn); } +void __mark_conn_closed(struct iscsi_conn *conn, int flags) +{ + conn->transport->iscsit_mark_conn_closed(conn, flags); +} + void mark_conn_closed(struct iscsi_conn *conn) { __mark_conn_closed(conn, ISCSI_CONN_ACTIVE_CLOSE); @@ -746,7 +717,7 @@ void conn_reinst_finished(struct iscsi_conn *conn) return; } -static void conn_activate(struct iscsi_conn *conn) +int conn_activate(struct iscsi_conn *conn) { TRACE_MGMT_DBG("Enabling conn %p", conn); @@ -772,7 +743,7 @@ static void conn_activate(struct iscsi_conn *conn) */ __iscsi_state_change(conn->sock->sk); - return; + return 0; } /* @@ -814,8 +785,19 @@ out: return res; } +void iscsi_tcp_conn_free(struct iscsi_conn *conn) +{ + fput(conn->file); + conn->file = NULL; + conn->sock = NULL; + + free_page((unsigned long)conn->read_iov); + + kmem_cache_free(iscsi_conn_cache, conn); +} + /* target_mutex supposed to be locked */ -int conn_free(struct iscsi_conn *conn) +void conn_free(struct iscsi_conn *conn) { struct iscsi_session *session = conn->session; @@ -856,25 +838,18 @@ int conn_free(struct iscsi_conn *conn) list_del(&conn->conn_list_entry); - fput(conn->file); - conn->file = NULL; - conn->sock = NULL; - - free_page((unsigned long)conn->read_iov); - - kmem_cache_free(iscsi_conn_cache, conn); + conn->transport->iscsit_conn_free(conn); if (list_empty(&session->conn_list)) { sBUG_ON(session->sess_reinst_successor != NULL); session_free(session, true); } - - return 0; } /* target_mutex supposed to be locked */ -static int iscsi_conn_alloc(struct iscsi_session *session, - struct iscsi_kern_conn_info *info, struct iscsi_conn **new_conn) +int iscsi_conn_alloc(struct iscsi_session *session, + struct iscsi_kern_conn_info *info, struct iscsi_conn **new_conn, + struct iscsit_transport *t) { struct iscsi_conn *conn; int res = 0; @@ -892,6 +867,8 @@ static int iscsi_conn_alloc(struct iscsi_session *session, TRACE_MGMT_DBG("Creating connection %p for sid %#Lx, cid %u", conn, (long long unsigned int)session->sid, info->cid); + conn->transport = t; + /* Changing it, change ISCSI_CONN_IOV_MAX as well !! */ conn->read_iov = (struct iovec *)get_zeroed_page(GFP_KERNEL); if (conn->read_iov == NULL) { @@ -986,6 +963,7 @@ int __add_conn(struct iscsi_session *session, struct iscsi_kern_conn_info *info) struct iscsi_conn *conn, *new_conn = NULL; int err; bool reinstatement = false; + struct iscsit_transport *t; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) lockdep_assert_held(&session->target->target_mutex); @@ -1001,7 +979,13 @@ int __add_conn(struct iscsi_session *session, struct iscsi_kern_conn_info *info) goto out; } - err = iscsi_conn_alloc(session, info, &new_conn); + t = iscsit_get_transport(ISCSI_TCP); + if (!t) { + err = -ENOENT; + goto out; + } + + err = t->iscsit_conn_alloc(session, info, &new_conn, t); if (err != 0) goto out; @@ -1013,7 +997,7 @@ int __add_conn(struct iscsi_session *session, struct iscsi_kern_conn_info *info) __mark_conn_closed(conn, 0); } - conn_activate(new_conn); + err = t->iscsit_conn_activate(new_conn); out: return err; diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index b85a215db..10d876715 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -27,6 +27,7 @@ #include "iscsi.h" #include "digest.h" +#include "iscsit_transport.h" #ifndef GENERATING_UPSTREAM_PATCH #if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) @@ -242,7 +243,7 @@ static struct iscsi_cmnd *iscsi_create_tm_clone(struct iscsi_cmnd *cmnd) TRACE_ENTRY(); - tm_clone = cmnd_alloc(cmnd->conn, NULL); + tm_clone = cmnd->conn->transport->iscsit_alloc_cmd(cmnd->conn, NULL); if (tm_clone != NULL) { set_bit(ISCSI_CMD_ABORTED, &tm_clone->prelim_compl_flags); tm_clone->pdu = cmnd->pdu; @@ -496,10 +497,10 @@ void cmnd_done(struct iscsi_cmnd *cmnd) list_for_each_entry_safe(rsp, t, &cmnd->rsp_cmd_list, rsp_cmd_list_entry) { - cmnd_free(rsp); + cmnd->conn->transport->iscsit_free_cmd(rsp); } - cmnd_free(cmnd); + cmnd->conn->transport->iscsit_free_cmd(cmnd); } else { struct iscsi_cmnd *parent = cmnd->parent_req; @@ -735,7 +736,7 @@ static struct iscsi_cmnd *iscsi_alloc_rsp(struct iscsi_cmnd *parent) TRACE_ENTRY(); - rsp = cmnd_alloc(parent->conn, parent); + rsp = parent->conn->transport->iscsit_alloc_cmd(parent->conn, parent); TRACE_DBG("Adding rsp %p to parent %p", rsp, parent); list_add_tail(&rsp->rsp_cmd_list_entry, &parent->rsp_cmd_list); @@ -797,7 +798,7 @@ static void iscsi_cmnds_init_write(struct list_head *send, int flags) spin_unlock_bh(&conn->write_list_lock); if (flags & ISCSI_INIT_WRITE_WAKE) - iscsi_make_conn_wr_active(conn); + conn->transport->iscsit_make_conn_wr_active(conn); return; } @@ -992,12 +993,25 @@ static void send_data_rsp(struct iscsi_cmnd *req, u8 status, int send_status) return; } +static void iscsi_tcp_set_sense_data(struct iscsi_cmnd *rsp, + const u8 *sense_buf, int sense_len) +{ + struct scatterlist *sg; + + sg = rsp->sg = rsp->rsp_sg; + rsp->sg_cnt = 2; + rsp->own_sg = 1; + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], &rsp->sense_hdr, sizeof(rsp->sense_hdr)); + sg_set_buf(&sg[1], sense_buf, sense_len); +} + static void iscsi_init_status_rsp(struct iscsi_cmnd *rsp, int status, const u8 *sense_buf, int sense_len) { struct iscsi_cmnd *req = rsp->parent_req; struct iscsi_scsi_rsp_hdr *rsp_hdr; - struct scatterlist *sg; TRACE_ENTRY(); @@ -1011,16 +1025,11 @@ static void iscsi_init_status_rsp(struct iscsi_cmnd *rsp, if (scst_sense_valid(sense_buf)) { TRACE_DBG("%s", "SENSE VALID"); - sg = rsp->sg = rsp->rsp_sg; - rsp->sg_cnt = 2; - rsp->own_sg = 1; - - sg_init_table(sg, 2); - sg_set_buf(&sg[0], &rsp->sense_hdr, sizeof(rsp->sense_hdr)); - sg_set_buf(&sg[1], sense_buf, sense_len); - rsp->sense_hdr.length = cpu_to_be16(sense_len); + rsp->conn->transport->iscsit_set_sense_data(rsp, sense_buf, + sense_len); + rsp->pdu.datasize = sizeof(rsp->sense_hdr) + sense_len; rsp->bufflen = rsp->pdu.datasize; } else { @@ -1049,6 +1058,25 @@ static inline struct iscsi_cmnd *create_status_rsp(struct iscsi_cmnd *req, return rsp; } +static void iscsi_tcp_send_data_rsp(struct iscsi_cmnd *req, u8 *sense, + int sense_len, u8 status, + int is_send_status) +{ + if ((status != SAM_STAT_CHECK_CONDITION) && + ((cmnd_hdr(req)->flags & (ISCSI_CMD_WRITE|ISCSI_CMD_READ)) != + (ISCSI_CMD_WRITE|ISCSI_CMD_READ))) { + send_data_rsp(req, status, is_send_status); + } else { + struct iscsi_cmnd *rsp; + send_data_rsp(req, 0, 0); + if (is_send_status) { + rsp = create_status_rsp(req, status, sense, + sense_len); + iscsi_cmnd_init_write(rsp, 0); + } + } +} + /* * Initializes data receive fields. Can be called only when they have not been * initialized yet. @@ -1737,7 +1765,7 @@ static int nop_out_start(struct iscsi_cmnd *cmnd) size = cmnd->pdu.datasize; - if (size) { + if (size && !conn->session->sess_params.rdma_extensions) { conn->read_msg.msg_iov = conn->read_iov; if (cmnd->pdu.bhs.itt != ISCSI_RESERVED_TAG) { struct scatterlist *sg; @@ -1978,7 +2006,8 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req) scst_cmd_set_expected_out_transfer_len(scst_cmd, be32_to_cpu(req_hdr->data_length)); #if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) - scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd); + if (conn->transport->need_alloc_write_buf) + scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd); #endif } } else if (req_hdr->flags & ISCSI_CMD_READ) { @@ -1986,7 +2015,8 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req) scst_cmd_set_expected(scst_cmd, dir, be32_to_cpu(req_hdr->data_length)); #if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) - scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd); + if (conn->transport->need_alloc_write_buf) + scst_cmd_set_tgt_need_alloc_data_buf(scst_cmd); #endif } else if (req_hdr->flags & ISCSI_CMD_WRITE) { dir = SCST_DATA_WRITE; @@ -2053,7 +2083,7 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req) scst_cmd_init_stage1_done(scst_cmd, SCST_CONTEXT_DIRECT, 0); if (req->scst_state != ISCSI_CMD_STATE_RX_CMD) - res = cmnd_rx_continue(req); + res = req->conn->transport->iscsit_receive_cmnd_data(req); else { TRACE_DBG("Delaying req %p post processing (scst_state %d)", req, req->scst_state); @@ -2664,6 +2694,14 @@ reject: return; } +static void iscsi_tcp_set_req_data(struct iscsi_cmnd *req, + struct iscsi_cmnd *rsp) +{ + rsp->sg = req->sg; + rsp->sg_cnt = req->sg_cnt; + rsp->bufflen = req->bufflen; +} + static void nop_out_exec(struct iscsi_cmnd *req) { struct iscsi_cmnd *rsp; @@ -2687,11 +2725,8 @@ static void nop_out_exec(struct iscsi_cmnd *req) else sBUG_ON(req->sg != NULL); - if (req->sg) { - rsp->sg = req->sg; - rsp->sg_cnt = req->sg_cnt; - rsp->bufflen = req->bufflen; - } + if (req->bufflen) + req->conn->transport->iscsit_set_req_data(req, rsp); /* We already checked it in check_segment_length() */ sBUG_ON(get_pgcnt(req->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX); @@ -3176,6 +3211,47 @@ out: return; } +static ssize_t iscsi_tcp_get_initiator_ip(struct iscsi_conn *conn, + char *buf, int size) +{ + int pos; + struct sock *sk; + + TRACE_ENTRY(); + + sk = conn->sock->sk; + switch (sk->sk_family) { + case AF_INET: + pos = scnprintf(buf, size, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) + "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr)); +#else + "%pI4", &inet_sk(sk)->inet_daddr); +#endif + break; + case AF_INET6: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) + pos = scnprintf(buf, size, + "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]", + NIP6(inet6_sk(sk)->daddr)); +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) + pos = scnprintf(buf, size, "[%p6]", &inet6_sk(sk)->daddr); +#else + pos = scnprintf(buf, size, "[%p6]", &sk->sk_v6_daddr); +#endif +#endif + break; + default: + pos = scnprintf(buf, size, "Unknown family %d", + sk->sk_family); + break; + } + + TRACE_EXIT_RES(pos); + return pos; +} + #if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) static int iscsi_alloc_data_buf(struct scst_cmd *cmd) { @@ -3192,11 +3268,8 @@ static int iscsi_alloc_data_buf(struct scst_cmd *cmd) } #endif -static void iscsi_preprocessing_done(struct scst_cmd *scst_cmd) +static void iscsi_tcp_preprocessing_done(struct iscsi_cmnd *req) { - struct iscsi_cmnd *req = (struct iscsi_cmnd *) - scst_cmd_get_tgt_priv(scst_cmd); - TRACE_DBG("req %p", req); if (req->conn->rx_task == current) @@ -3223,8 +3296,14 @@ static void iscsi_preprocessing_done(struct scst_cmd *scst_cmd) } cmnd_put(req); } +} - return; +static void iscsi_preprocessing_done(struct scst_cmd *scst_cmd) +{ + struct iscsi_cmnd *req = (struct iscsi_cmnd *) + scst_cmd_get_tgt_priv(scst_cmd); + + req->conn->transport->iscsit_preprocessing_done(req); } /* No locks */ @@ -3285,6 +3364,52 @@ static void iscsi_try_local_processing(struct iscsi_cmnd *req) return; } +static int iscsi_tcp_send_locally(struct iscsi_cmnd *req, + unsigned int cmd_count) +{ + struct iscsi_conn *conn = req->conn; + struct iscsi_cmnd *wr_rsp, *our_rsp; + int ret = 0; + + /* + * There's no need for protection, since we are not going to + * dereference them. + */ + wr_rsp = list_first_entry(&conn->write_list, struct iscsi_cmnd, + write_list_entry); + our_rsp = list_first_entry(&req->rsp_cmd_list, struct iscsi_cmnd, + rsp_cmd_list_entry); + if (wr_rsp == our_rsp) { + /* + * This is our rsp, so let's try to process it locally to + * decrease latency. We need to call pre_release before + * processing to handle some error recovery cases. + */ + if (cmd_count <= 2) { + req_cmnd_pre_release(req); + iscsi_try_local_processing(req); + cmnd_put(req); + } else { + /* + * There's too much backend activity, so it could be + * better to push it to the write thread. + */ + ret = 1; + } + } else + ret = 1; + + return ret; +} + +static void iscsi_tcp_conn_close(struct iscsi_conn *conn, int flags) +{ + if (!flags) + conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0); + else + conn->sock->ops->shutdown(conn->sock, flags); +} + static int iscsi_xmit_response(struct scst_cmd *scst_cmd) { int is_send_status = scst_cmd_get_is_send_status(scst_cmd); @@ -3294,7 +3419,6 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd) int status = scst_cmd_get_status(scst_cmd); u8 *sense = scst_cmd_get_sense_buffer(scst_cmd); int sense_len = scst_cmd_get_sense_buffer_len(scst_cmd); - struct iscsi_cmnd *wr_rsp, *our_rsp; EXTRACHECKS_BUG_ON(scst_cmd_atomic(scst_cmd)); @@ -3369,19 +3493,9 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd) * so status is valid here, but in future that could change. * ToDo */ - if ((status != SAM_STAT_CHECK_CONDITION) && - ((cmnd_hdr(req)->flags & (ISCSI_CMD_WRITE|ISCSI_CMD_READ)) != - (ISCSI_CMD_WRITE|ISCSI_CMD_READ))) { - send_data_rsp(req, status, is_send_status); - } else { - struct iscsi_cmnd *rsp; - send_data_rsp(req, 0, 0); - if (is_send_status) { - rsp = create_status_rsp(req, status, sense, - sense_len); - iscsi_cmnd_init_write(rsp, 0); - } - } + req->conn->transport->iscsit_send_data_rsp(req, sense, + sense_len, status, + is_send_status); } else if (is_send_status) { struct iscsi_cmnd *rsp; rsp = create_status_rsp(req, status, sense, sense_len); @@ -3392,32 +3506,7 @@ static int iscsi_xmit_response(struct scst_cmd *scst_cmd) sBUG(); #endif - /* - * There's no need for protection, since we are not going to - * dereference them. - */ - wr_rsp = list_first_entry(&conn->write_list, struct iscsi_cmnd, - write_list_entry); - our_rsp = list_first_entry(&req->rsp_cmd_list, struct iscsi_cmnd, - rsp_cmd_list_entry); - if (wr_rsp == our_rsp) { - /* - * This is our rsp, so let's try to process it locally to - * decrease latency. We need to call pre_release before - * processing to handle some error recovery cases. - */ - if (scst_get_active_cmd_count(scst_cmd) <= 2) { - req_cmnd_pre_release(req); - iscsi_try_local_processing(req); - cmnd_put(req); - } else { - /* - * There's too much backend activity, so it could be - * better to push it to the write thread. - */ - goto out_push_to_wr_thread; - } - } else + if (conn->transport->iscsit_send_locally(req, scst_get_active_cmd_count(scst_cmd))) goto out_push_to_wr_thread; out: @@ -3426,7 +3515,7 @@ out: out_push_to_wr_thread: TRACE_DBG("Waking up write thread (conn %p)", conn); req_cmnd_release(req); - iscsi_make_conn_wr_active(conn); + conn->transport->iscsit_make_conn_wr_active(conn); goto out; } @@ -3610,7 +3699,6 @@ static int iscsi_scsi_aen(struct scst_aen *aen) bool found; struct iscsi_cmnd *fake_req, *rsp; struct iscsi_async_msg_hdr *rsp_hdr; - struct scatterlist *sg; TRACE_ENTRY(); @@ -3633,7 +3721,7 @@ static int iscsi_scsi_aen(struct scst_aen *aen) } /* Create a fake request */ - fake_req = cmnd_alloc(conn, NULL); + fake_req = conn->transport->iscsit_alloc_cmd(conn, NULL); if (fake_req == NULL) { PRINT_ERROR("%s", "Unable to alloc fake AEN request"); goto out_err_unlock; @@ -3658,15 +3746,10 @@ static int iscsi_scsi_aen(struct scst_aen *aen) rsp_hdr->ffffffff = cpu_to_be32(0xffffffff); rsp_hdr->async_event = ISCSI_ASYNC_SCSI; - sg = rsp->sg = rsp->rsp_sg; - rsp->sg_cnt = 2; - rsp->own_sg = 1; - - sg_init_table(sg, 2); - sg_set_buf(&sg[0], &rsp->sense_hdr, sizeof(rsp->sense_hdr)); - sg_set_buf(&sg[1], sense, sense_len); - rsp->sense_hdr.length = cpu_to_be16(sense_len); + + rsp->conn->transport->iscsit_set_sense_data(rsp, sense, sense_len); + rsp->pdu.datasize = sizeof(rsp->sense_hdr) + sense_len; rsp->bufflen = rsp->pdu.datasize; @@ -3788,7 +3871,7 @@ void iscsi_send_nop_in(struct iscsi_conn *conn) TRACE_ENTRY(); - req = cmnd_alloc(conn, NULL); + req = conn->transport->iscsit_alloc_cmd(conn, NULL); if (req == NULL) { PRINT_ERROR("%s", "Unable to alloc fake Nop-In request"); goto out_err; @@ -3930,6 +4013,30 @@ struct scst_tgt_template iscsi_template = { .get_scsi_transport_version = iscsi_get_scsi_transport_version, }; +static struct iscsit_transport iscsi_tcp_transport = { + .owner = THIS_MODULE, + .name = "iSCSI-TCP", + .transport_type = ISCSI_TCP, +#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) + .need_alloc_write_buf = 1, +#endif + .iscsit_conn_alloc = iscsi_conn_alloc, + .iscsit_conn_activate = conn_activate, + .iscsit_conn_free = iscsi_tcp_conn_free, + .iscsit_alloc_cmd = cmnd_alloc, + .iscsit_free_cmd = cmnd_free, + .iscsit_preprocessing_done = iscsi_tcp_preprocessing_done, + .iscsit_send_data_rsp = iscsi_tcp_send_data_rsp, + .iscsit_make_conn_wr_active = iscsi_make_conn_wr_active, + .iscsit_mark_conn_closed = iscsi_tcp_mark_conn_closed, + .iscsit_conn_close = iscsi_tcp_conn_close, + .iscsit_get_initiator_ip = iscsi_tcp_get_initiator_ip, + .iscsit_send_locally = iscsi_tcp_send_locally, + .iscsit_set_sense_data = iscsi_tcp_set_sense_data, + .iscsit_set_req_data = iscsi_tcp_set_req_data, + .iscsit_receive_cmnd_data = cmnd_rx_continue, +}; + static void __iscsi_threads_pool_put(struct iscsi_thread_pool *p) { struct iscsi_thread *t, *tt; @@ -4110,6 +4217,10 @@ static int __init iscsi_init(void) PRINT_INFO("iSCSI SCST Target - version %s", ISCSI_VERSION_STRING); + err = iscsit_register_transport(&iscsi_tcp_transport); + if (err) + goto out; + dummy_page = alloc_pages(GFP_KERNEL, 0); if (dummy_page == NULL) { PRINT_ERROR("%s", "Dummy page allocation failed"); @@ -4260,6 +4371,8 @@ static void __exit iscsi_exit(void) scst_unregister_target_template(&iscsi_template); + iscsit_unregister_transport(&iscsi_tcp_transport); + #if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) net_set_get_put_page_callbacks(NULL, NULL); #endif diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index 38f975a14..4ca1c988f 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -555,7 +555,7 @@ extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16); extern void conn_reinst_finished(struct iscsi_conn *); extern int __add_conn(struct iscsi_session *, struct iscsi_kern_conn_info *); extern int __del_conn(struct iscsi_session *, struct iscsi_kern_conn_info *); -extern int conn_free(struct iscsi_conn *); +extern void conn_free(struct iscsi_conn *); extern void iscsi_make_conn_rd_active(struct iscsi_conn *conn); #define ISCSI_CONN_ACTIVE_CLOSE 1 #define ISCSI_CONN_DELETING 2 @@ -829,4 +829,11 @@ static inline void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn) {} static inline void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn) {} #endif +extern int iscsi_conn_alloc(struct iscsi_session *session, + struct iscsi_kern_conn_info *info, struct iscsi_conn **new_conn, + struct iscsit_transport *t); + +extern int conn_activate(struct iscsi_conn *conn); +extern void iscsi_tcp_mark_conn_closed(struct iscsi_conn *conn, int flags); +extern void iscsi_tcp_conn_free(struct iscsi_conn *conn); #endif /* __ISCSI_H__ */ diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 2d4314b6b..404de998e 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -24,6 +24,7 @@ #include "iscsi.h" #include "digest.h" +#include "iscsit_transport.h" /* Read data states */ enum rx_state { @@ -408,10 +409,10 @@ static void close_conn(struct iscsi_conn *conn) if (conn->active_close) { /* We want all our already send operations to complete */ - conn->sock->ops->shutdown(conn->sock, RCV_SHUTDOWN); + conn->transport->iscsit_conn_close(conn, RCV_SHUTDOWN); } else { - conn->sock->ops->shutdown(conn->sock, - RCV_SHUTDOWN|SEND_SHUTDOWN); + conn->transport->iscsit_conn_close(conn, + RCV_SHUTDOWN|SEND_SHUTDOWN); } mutex_lock(&session->target->target_mutex); @@ -487,15 +488,13 @@ static void close_conn(struct iscsi_conn *conn) } } - iscsi_make_conn_wr_active(conn); + conn->transport->iscsit_make_conn_wr_active(conn); /* That's for active close only, actually */ if (time_after(jiffies, start_waiting + CONN_WAIT_TIMEOUT) && !wait_expired) { - TRACE_CONN_CLOSE("Wait time expired (conn %p, " - "sk_state %d)", - conn, conn->sock->sk->sk_state); - conn->sock->ops->shutdown(conn->sock, SEND_SHUTDOWN); + TRACE_CONN_CLOSE("Wait time expired (conn %p)", conn); + conn->transport->iscsit_conn_close(conn, SEND_SHUTDOWN); wait_expired = 1; shut_start_waiting = jiffies; } @@ -505,9 +504,8 @@ static void close_conn(struct iscsi_conn *conn) conn->deleting ? CONN_DEL_SHUT_TIMEOUT : CONN_REG_SHUT_TIMEOUT)) { TRACE_CONN_CLOSE("Wait time after shutdown expired " - "(conn %p, sk_state %d)", conn, - conn->sock->sk->sk_state); - conn->sock->sk->sk_prot->disconnect(conn->sock->sk, 0); + "(conn %p)", conn); + conn->transport->iscsit_conn_close(conn, 0); shut_expired = 1; } @@ -523,17 +521,21 @@ static void close_conn(struct iscsi_conn *conn) trace_conn_close(conn); - /* It might never be called for being closed conn */ - __iscsi_write_space_ready(conn); + if (!conn->session->sess_params.rdma_extensions) { + /* It might never be called for being closed conn */ + __iscsi_write_space_ready(conn); - iscsi_check_closewait(conn); + iscsi_check_closewait(conn); + } } - write_lock_bh(&conn->sock->sk->sk_callback_lock); - conn->sock->sk->sk_state_change = conn->old_state_change; - conn->sock->sk->sk_data_ready = conn->old_data_ready; - conn->sock->sk->sk_write_space = conn->old_write_space; - write_unlock_bh(&conn->sock->sk->sk_callback_lock); + if (!conn->session->sess_params.rdma_extensions) { + write_lock_bh(&conn->sock->sk->sk_callback_lock); + conn->sock->sk->sk_state_change = conn->old_state_change; + conn->sock->sk->sk_data_ready = conn->old_data_ready; + conn->sock->sk->sk_write_space = conn->old_write_space; + write_unlock_bh(&conn->sock->sk->sk_callback_lock); + } while (1) { bool t; @@ -832,7 +834,7 @@ static int process_read_io(struct iscsi_conn *conn, int *closed) switch (conn->read_state) { case RX_INIT_BHS: EXTRACHECKS_BUG_ON(conn->read_cmnd != NULL); - cmnd = cmnd_alloc(conn, NULL); + cmnd = conn->transport->iscsit_alloc_cmd(conn, NULL); conn->read_cmnd = cmnd; iscsi_conn_init_read(cmnd->conn, (void __force __user *)&cmnd->pdu.bhs, diff --git a/iscsi-scst/kernel/target.c b/iscsi-scst/kernel/target.c index 848c4c981..bef604c3d 100644 --- a/iscsi-scst/kernel/target.c +++ b/iscsi-scst/kernel/target.c @@ -349,6 +349,7 @@ void target_del_all_sess(struct iscsi_target *target, int flags) void target_del_all(void) { + struct iscsit_transport *transport; struct iscsi_target *target, *t; bool first = true; @@ -356,6 +357,14 @@ void target_del_all(void) TRACE_MGMT_DBG("%s", "Deleting all targets"); + transport = iscsit_get_transport(ISCSI_TCP); + if (transport && transport->iscsit_close_all_portals) + transport->iscsit_close_all_portals(); + + transport = iscsit_get_transport(ISCSI_RDMA); + if (transport && transport->iscsit_close_all_portals) + transport->iscsit_close_all_portals(); + /* Not the best, ToDo */ while (1) { mutex_lock(&target_mgmt_mutex);