Commit 2371e5da authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Nicholas Bellinger

iser-target: Parallelize CM connection establishment

There is no point in accepting a new CM request only
when we are completely done with the last iscsi login.
Instead we accept immediately, this will also cause the
CM connection to reach connected state and the initiator
is allowed to send the first login. We mark that we got
the initial login and let iscsi layer pick it up when it
gets there.

This reduces the parallel login sequence by a factor of
more then 4 (and more for multi-login) and also prevents
the initiator (who does all logins in parallel) from
giving up on login timeout expiration.

In order to support multiple login requests sequence (CHAP)
we call isert_rx_login_req from isert_rx_completion insead
of letting isert_get_login_rx call it.

Squashed:

iser-target: Use kref_get_unless_zero in connected_handler
iser-target: Acquire conn_mutex when changing connection state
iser-target: Reject connect request in failure path
Signed-off-by: default avatarSagi Grimberg <sagig@mellanox.com>
Cc: <stable@vger.kernel.org> # v3.10+
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 128e9cc8
...@@ -54,6 +54,10 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ...@@ -54,6 +54,10 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
struct isert_rdma_wr *wr); struct isert_rdma_wr *wr);
static int static int
isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd); isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd);
static int
isert_rdma_post_recvl(struct isert_conn *isert_conn);
static int
isert_rdma_accept(struct isert_conn *isert_conn);
static void static void
isert_qp_event_callback(struct ib_event *e, void *context) isert_qp_event_callback(struct ib_event *e, void *context)
...@@ -590,6 +594,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -590,6 +594,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
isert_conn->state = ISER_CONN_INIT; isert_conn->state = ISER_CONN_INIT;
INIT_LIST_HEAD(&isert_conn->conn_accept_node); INIT_LIST_HEAD(&isert_conn->conn_accept_node);
init_completion(&isert_conn->conn_login_comp); init_completion(&isert_conn->conn_login_comp);
init_completion(&isert_conn->login_req_comp);
init_completion(&isert_conn->conn_wait); init_completion(&isert_conn->conn_wait);
init_completion(&isert_conn->conn_wait_comp_err); init_completion(&isert_conn->conn_wait_comp_err);
kref_init(&isert_conn->conn_kref); kref_init(&isert_conn->conn_kref);
...@@ -681,6 +686,14 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -681,6 +686,14 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
if (ret) if (ret)
goto out_conn_dev; goto out_conn_dev;
ret = isert_rdma_post_recvl(isert_conn);
if (ret)
goto out_conn_dev;
ret = isert_rdma_accept(isert_conn);
if (ret)
goto out_conn_dev;
mutex_lock(&isert_np->np_accept_mutex); mutex_lock(&isert_np->np_accept_mutex);
list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list); list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list);
mutex_unlock(&isert_np->np_accept_mutex); mutex_unlock(&isert_np->np_accept_mutex);
...@@ -705,6 +718,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -705,6 +718,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
kfree(isert_conn->login_buf); kfree(isert_conn->login_buf);
out: out:
kfree(isert_conn); kfree(isert_conn);
rdma_reject(cma_id, NULL, 0);
return ret; return ret;
} }
...@@ -758,8 +772,15 @@ isert_connected_handler(struct rdma_cm_id *cma_id) ...@@ -758,8 +772,15 @@ isert_connected_handler(struct rdma_cm_id *cma_id)
pr_info("conn %p\n", isert_conn); pr_info("conn %p\n", isert_conn);
isert_conn->state = ISER_CONN_UP; if (!kref_get_unless_zero(&isert_conn->conn_kref)) {
kref_get(&isert_conn->conn_kref); pr_warn("conn %p connect_release is running\n", isert_conn);
return;
}
mutex_lock(&isert_conn->conn_mutex);
if (isert_conn->state != ISER_CONN_FULL_FEATURE)
isert_conn->state = ISER_CONN_UP;
mutex_unlock(&isert_conn->conn_mutex);
} }
static void static void
...@@ -1118,7 +1139,9 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, ...@@ -1118,7 +1139,9 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
return ret; return ret;
/* Now we are in FULL_FEATURE phase */ /* Now we are in FULL_FEATURE phase */
mutex_lock(&isert_conn->conn_mutex);
isert_conn->state = ISER_CONN_FULL_FEATURE; isert_conn->state = ISER_CONN_FULL_FEATURE;
mutex_unlock(&isert_conn->conn_mutex);
goto post_send; goto post_send;
} }
...@@ -1135,18 +1158,17 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, ...@@ -1135,18 +1158,17 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
} }
static void static void
isert_rx_login_req(struct iser_rx_desc *rx_desc, int rx_buflen, isert_rx_login_req(struct isert_conn *isert_conn)
struct isert_conn *isert_conn)
{ {
struct iser_rx_desc *rx_desc = (void *)isert_conn->login_req_buf;
int rx_buflen = isert_conn->login_req_len;
struct iscsi_conn *conn = isert_conn->conn; struct iscsi_conn *conn = isert_conn->conn;
struct iscsi_login *login = conn->conn_login; struct iscsi_login *login = conn->conn_login;
int size; int size;
if (!login) { pr_info("conn %p\n", isert_conn);
pr_err("conn->conn_login is NULL\n");
dump_stack(); WARN_ON_ONCE(!login);
return;
}
if (login->first_request) { if (login->first_request) {
struct iscsi_login_req *login_req = struct iscsi_login_req *login_req =
...@@ -1509,11 +1531,20 @@ isert_rx_completion(struct iser_rx_desc *desc, struct isert_conn *isert_conn, ...@@ -1509,11 +1531,20 @@ isert_rx_completion(struct iser_rx_desc *desc, struct isert_conn *isert_conn,
hdr->opcode, hdr->itt, hdr->flags, hdr->opcode, hdr->itt, hdr->flags,
(int)(xfer_len - ISER_HEADERS_LEN)); (int)(xfer_len - ISER_HEADERS_LEN));
if ((char *)desc == isert_conn->login_req_buf) if ((char *)desc == isert_conn->login_req_buf) {
isert_rx_login_req(desc, xfer_len - ISER_HEADERS_LEN, isert_conn->login_req_len = xfer_len - ISER_HEADERS_LEN;
isert_conn); if (isert_conn->conn) {
else struct iscsi_login *login = isert_conn->conn->conn_login;
if (login && !login->first_request)
isert_rx_login_req(isert_conn);
}
mutex_lock(&isert_conn->conn_mutex);
complete(&isert_conn->login_req_comp);
mutex_unlock(&isert_conn->conn_mutex);
} else {
isert_rx_do_work(desc, isert_conn); isert_rx_do_work(desc, isert_conn);
}
ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen, ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
...@@ -3120,7 +3151,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) ...@@ -3120,7 +3151,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login)
struct isert_conn *isert_conn = (struct isert_conn *)conn->context; struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
int ret; int ret;
pr_debug("isert_get_login_rx before conn_login_comp conn: %p\n", conn); pr_info("before login_req comp conn: %p\n", isert_conn);
ret = wait_for_completion_interruptible(&isert_conn->login_req_comp);
if (ret) {
pr_err("isert_conn %p interrupted before got login req\n",
isert_conn);
return ret;
}
reinit_completion(&isert_conn->login_req_comp);
/* /*
* For login requests after the first PDU, isert_rx_login_req() will * For login requests after the first PDU, isert_rx_login_req() will
* kick schedule_delayed_work(&conn->login_work) as the packet is * kick schedule_delayed_work(&conn->login_work) as the packet is
...@@ -3130,11 +3169,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) ...@@ -3130,11 +3169,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login)
if (!login->first_request) if (!login->first_request)
return 0; return 0;
isert_rx_login_req(isert_conn);
pr_info("before conn_login_comp conn: %p\n", conn);
ret = wait_for_completion_interruptible(&isert_conn->conn_login_comp); ret = wait_for_completion_interruptible(&isert_conn->conn_login_comp);
if (ret) if (ret)
return ret; return ret;
pr_debug("isert_get_login_rx processing login->req: %p\n", login->req); pr_info("processing login->req: %p\n", login->req);
return 0; return 0;
} }
...@@ -3212,17 +3255,10 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) ...@@ -3212,17 +3255,10 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
isert_conn->conn = conn; isert_conn->conn = conn;
max_accept = 0; max_accept = 0;
ret = isert_rdma_post_recvl(isert_conn);
if (ret)
return ret;
ret = isert_rdma_accept(isert_conn);
if (ret)
return ret;
isert_set_conn_info(np, conn, isert_conn); isert_set_conn_info(np, conn, isert_conn);
pr_debug("Processing isert_accept_np: isert_conn: %p\n", isert_conn); pr_debug("Processing isert_conn: %p\n", isert_conn);
return 0; return 0;
} }
......
...@@ -126,6 +126,7 @@ struct isert_conn { ...@@ -126,6 +126,7 @@ struct isert_conn {
char *login_req_buf; char *login_req_buf;
char *login_rsp_buf; char *login_rsp_buf;
u64 login_req_dma; u64 login_req_dma;
int login_req_len;
u64 login_rsp_dma; u64 login_rsp_dma;
unsigned int conn_rx_desc_head; unsigned int conn_rx_desc_head;
struct iser_rx_desc *conn_rx_descs; struct iser_rx_desc *conn_rx_descs;
...@@ -133,6 +134,7 @@ struct isert_conn { ...@@ -133,6 +134,7 @@ struct isert_conn {
struct iscsi_conn *conn; struct iscsi_conn *conn;
struct list_head conn_accept_node; struct list_head conn_accept_node;
struct completion conn_login_comp; struct completion conn_login_comp;
struct completion login_req_comp;
struct iser_tx_desc conn_login_tx_desc; struct iser_tx_desc conn_login_tx_desc;
struct rdma_cm_id *conn_cm_id; struct rdma_cm_id *conn_cm_id;
struct ib_pd *conn_pd; struct ib_pd *conn_pd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment