]> git.ipfire.org Git - people/ms/linux.git/commitdiff
iser-target: Fix implicit termination of connections
authorSagi Grimberg <sagig@mellanox.com>
Tue, 2 Dec 2014 14:57:29 +0000 (16:57 +0200)
committerJiri Slaby <jslaby@suse.cz>
Thu, 29 Jan 2015 14:44:52 +0000 (15:44 +0100)
commit b02efbfc9a051b41e71fe8f94ddf967260e024a6 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: Slava Shwartsman <valyushash@gmail.com>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h

index 65dca0051d519c3b57f7d02ba86429f2419e8bad..60a3ed9f0624e47bd1db41858f39d840344ca445 100644 (file)
@@ -40,6 +40,7 @@ static DEFINE_MUTEX(device_list_mutex);
 static LIST_HEAD(device_list);
 static struct workqueue_struct *isert_rx_wq;
 static struct workqueue_struct *isert_comp_wq;
+static struct workqueue_struct *isert_release_wq;
 
 static void
 isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn);
@@ -2812,6 +2813,24 @@ isert_free_np(struct iscsi_np *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)
 {
        struct isert_conn *isert_conn = conn->context;
@@ -2831,14 +2850,9 @@ static void isert_wait_conn(struct iscsi_conn *conn)
        mutex_unlock(&isert_conn->conn_mutex);
 
        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);
-       isert_put_conn(isert_conn);
+       INIT_WORK(&isert_conn->release_work, isert_release_work);
+       queue_work(isert_release_wq, &isert_conn->release_work);
 }
 
 static void isert_free_conn(struct iscsi_conn *conn)
@@ -2884,10 +2898,21 @@ static int __init isert_init(void)
                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);
-       pr_debug("iSER_TARGET[0] - Loaded iser_target_transport\n");
+       pr_info("iSER_TARGET[0] - Loaded iser_target_transport\n");
+
        return 0;
 
+destroy_comp_wq:
+       destroy_workqueue(isert_comp_wq);
 destroy_rx_wq:
        destroy_workqueue(isert_rx_wq);
        return ret;
@@ -2896,6 +2921,7 @@ destroy_rx_wq:
 static void __exit isert_exit(void)
 {
        flush_scheduled_work();
+       destroy_workqueue(isert_release_wq);
        destroy_workqueue(isert_comp_wq);
        destroy_workqueue(isert_rx_wq);
        iscsit_unregister_transport(&iser_target_transport);
index d29970536828e25549cee2b92e16d07506ca97ab..1ea527974bebbac06b49e77d5decdd7237a5e0c0 100644 (file)
@@ -123,6 +123,7 @@ struct isert_conn {
        int                     conn_frwr_pool_size;
        /* lock to protect frwr_pool */
        spinlock_t              conn_lock;
+       struct work_struct      release_work;
 };
 
 #define ISERT_MAX_CQ 64