Commit 63dff7ee authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Luis Henriques

iser-target: Fix implicit termination of connections

commit b02efbfc upstream.

In situations such as bond failover, The new session establishment
implicitly invokes the termination of the old connection.

So, we don't want to wait for the old connection wait_conn to completely
terminate before we accept the new connection and post a login response.

The solution is to deffer the comp_wait completion and the conn_put to
a work so wait_conn will effectively be non-blocking (flush errors are
assumed to come very fast).

We allocate isert_release_wq with WQ_UNBOUND and WQ_UNBOUND_MAX_ACTIVE
to spread the concurrency of release works.
Reported-by: default avatarSlava Shwartsman <valyushash@gmail.com>
Signed-off-by: default avatarSagi Grimberg <sagig@mellanox.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 868d84f1
...@@ -41,6 +41,7 @@ static DEFINE_MUTEX(device_list_mutex); ...@@ -41,6 +41,7 @@ static DEFINE_MUTEX(device_list_mutex);
static LIST_HEAD(device_list); static LIST_HEAD(device_list);
static struct workqueue_struct *isert_rx_wq; static struct workqueue_struct *isert_rx_wq;
static struct workqueue_struct *isert_comp_wq; static struct workqueue_struct *isert_comp_wq;
static struct workqueue_struct *isert_release_wq;
static void static void
isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn);
...@@ -3338,6 +3339,24 @@ isert_free_np(struct iscsi_np *np) ...@@ -3338,6 +3339,24 @@ isert_free_np(struct iscsi_np *np)
kfree(isert_np); kfree(isert_np);
} }
static void isert_release_work(struct work_struct *work)
{
struct isert_conn *isert_conn = container_of(work,
struct isert_conn,
release_work);
pr_info("Starting release conn %p\n", isert_conn);
wait_for_completion(&isert_conn->conn_wait);
mutex_lock(&isert_conn->conn_mutex);
isert_conn->state = ISER_CONN_DOWN;
mutex_unlock(&isert_conn->conn_mutex);
pr_info("Destroying conn %p\n", isert_conn);
isert_put_conn(isert_conn);
}
static void isert_wait_conn(struct iscsi_conn *conn) static void isert_wait_conn(struct iscsi_conn *conn)
{ {
struct isert_conn *isert_conn = conn->context; struct isert_conn *isert_conn = conn->context;
...@@ -3357,14 +3376,9 @@ static void isert_wait_conn(struct iscsi_conn *conn) ...@@ -3357,14 +3376,9 @@ static void isert_wait_conn(struct iscsi_conn *conn)
mutex_unlock(&isert_conn->conn_mutex); mutex_unlock(&isert_conn->conn_mutex);
wait_for_completion(&isert_conn->conn_wait_comp_err); wait_for_completion(&isert_conn->conn_wait_comp_err);
wait_for_completion(&isert_conn->conn_wait);
mutex_lock(&isert_conn->conn_mutex);
isert_conn->state = ISER_CONN_DOWN;
mutex_unlock(&isert_conn->conn_mutex);
pr_info("Destroying conn %p\n", isert_conn); INIT_WORK(&isert_conn->release_work, isert_release_work);
isert_put_conn(isert_conn); queue_work(isert_release_wq, &isert_conn->release_work);
} }
static void isert_free_conn(struct iscsi_conn *conn) static void isert_free_conn(struct iscsi_conn *conn)
...@@ -3412,10 +3426,21 @@ static int __init isert_init(void) ...@@ -3412,10 +3426,21 @@ static int __init isert_init(void)
goto destroy_rx_wq; goto destroy_rx_wq;
} }
isert_release_wq = alloc_workqueue("isert_release_wq", WQ_UNBOUND,
WQ_UNBOUND_MAX_ACTIVE);
if (!isert_release_wq) {
pr_err("Unable to allocate isert_release_wq\n");
ret = -ENOMEM;
goto destroy_comp_wq;
}
iscsit_register_transport(&iser_target_transport); iscsit_register_transport(&iser_target_transport);
pr_debug("iSER_TARGET[0] - Loaded iser_target_transport\n"); pr_info("iSER_TARGET[0] - Loaded iser_target_transport\n");
return 0; return 0;
destroy_comp_wq:
destroy_workqueue(isert_comp_wq);
destroy_rx_wq: destroy_rx_wq:
destroy_workqueue(isert_rx_wq); destroy_workqueue(isert_rx_wq);
return ret; return ret;
...@@ -3424,6 +3449,7 @@ static int __init isert_init(void) ...@@ -3424,6 +3449,7 @@ static int __init isert_init(void)
static void __exit isert_exit(void) static void __exit isert_exit(void)
{ {
flush_scheduled_work(); flush_scheduled_work();
destroy_workqueue(isert_release_wq);
destroy_workqueue(isert_comp_wq); destroy_workqueue(isert_comp_wq);
destroy_workqueue(isert_rx_wq); destroy_workqueue(isert_rx_wq);
iscsit_unregister_transport(&iser_target_transport); iscsit_unregister_transport(&iser_target_transport);
......
...@@ -149,6 +149,7 @@ struct isert_conn { ...@@ -149,6 +149,7 @@ struct isert_conn {
int conn_fr_pool_size; int conn_fr_pool_size;
/* lock to protect fastreg pool */ /* lock to protect fastreg pool */
spinlock_t conn_lock; spinlock_t conn_lock;
struct work_struct release_work;
#define ISERT_COMP_BATCH_COUNT 8 #define ISERT_COMP_BATCH_COUNT 8
int conn_comp_batch; int conn_comp_batch;
struct llist_head conn_comp_llist; struct llist_head conn_comp_llist;
......
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