Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=1d426d6418d1914b592c9c307c02e488d9182fa8
Commit:     1d426d6418d1914b592c9c307c02e488d9182fa8
Parent:     58e949139014a852a83b5ef071136b1f50c86ad1
Author:     Erez Zilber <[EMAIL PROTECTED]>
AuthorDate: Sun Apr 1 12:53:43 2007 +0200
Committer:  Roland Dreier <[EMAIL PROTECTED]>
CommitDate: Thu Apr 5 09:46:04 2007 -0700

    IB/iser: Don't defer connection failure notification to workqueue
    
    When a connection is terminated asynchronously from the iSCSI layer's
    perspective, iSER needs to notify the iSCSI layer that the connection
    has failed.  This is done using a workqueue (switched to from the iSER
    tasklet context).  Meanwhile, the connection object (that holds the
    work struct) is released.  If the workqueue function wasn't called
    yet, it will be called later with a NULL pointer, which will crash the
    kernel.
    
    The context switch (tasklet to workqueue) is not required, and
    everything can be done from the iSER tasklet. This eliminates the NULL
    work struct bug (and simplifies the code).
    
    Signed-off-by: Erez Zilber <[EMAIL PROTECTED]>
    Signed-off-by: Roland Dreier <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/iser/iscsi_iser.h |    1 -
 drivers/infiniband/ulp/iser/iser_verbs.c |   40 ++++++++++++------------------
 2 files changed, 16 insertions(+), 25 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h 
b/drivers/infiniband/ulp/iser/iscsi_iser.h
index cae8c96..8960196 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -245,7 +245,6 @@ struct iser_conn {
        wait_queue_head_t            wait;          /* waitq for conn/disconn  
*/
        atomic_t                     post_recv_buf_count; /* posted rx count   
*/
        atomic_t                     post_send_buf_count; /* posted tx count   
*/
-       struct work_struct           comperror_work; /* conn term sleepable 
ctx*/
        char                         name[ISER_OBJECT_NAME_SIZE];
        struct iser_page_vec         *page_vec;     /* represents SG to fmr 
maps*
                                                     * maps serialized as tx 
is*/
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c 
b/drivers/infiniband/ulp/iser/iser_verbs.c
index 693b770..1fc9674 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -48,7 +48,6 @@
 
 static void iser_cq_tasklet_fn(unsigned long data);
 static void iser_cq_callback(struct ib_cq *cq, void *cq_context);
-static void iser_comp_error_worker(struct work_struct *work);
 
 static void iser_cq_event_callback(struct ib_event *cause, void *context)
 {
@@ -480,7 +479,6 @@ int iser_conn_init(struct iser_conn **ibconn)
        init_waitqueue_head(&ib_conn->wait);
        atomic_set(&ib_conn->post_recv_buf_count, 0);
        atomic_set(&ib_conn->post_send_buf_count, 0);
-       INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker);
        INIT_LIST_HEAD(&ib_conn->conn_list);
        spin_lock_init(&ib_conn->lock);
 
@@ -753,26 +751,6 @@ int iser_post_send(struct iser_desc *tx_desc)
        return ret_val;
 }
 
-static void iser_comp_error_worker(struct work_struct *work)
-{
-       struct iser_conn *ib_conn =
-               container_of(work, struct iser_conn, comperror_work);
-
-       /* getting here when the state is UP means that the conn is being *
-        * terminated asynchronously from the iSCSI layer's perspective.  */
-       if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
-                                     ISER_CONN_TERMINATING))
-               iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
-                                       ISCSI_ERR_CONN_FAILED);
-
-       /* complete the termination process if disconnect event was delivered *
-        * note there are no more non completed posts to the QP               */
-       if (ib_conn->disc_evt_flag) {
-               ib_conn->state = ISER_CONN_DOWN;
-               wake_up_interruptible(&ib_conn->wait);
-       }
-}
-
 static void iser_handle_comp_error(struct iser_desc *desc)
 {
        struct iser_dto  *dto     = &desc->dto;
@@ -791,8 +769,22 @@ static void iser_handle_comp_error(struct iser_desc *desc)
        }
 
        if (atomic_read(&ib_conn->post_recv_buf_count) == 0 &&
-           atomic_read(&ib_conn->post_send_buf_count) == 0)
-               schedule_work(&ib_conn->comperror_work);
+           atomic_read(&ib_conn->post_send_buf_count) == 0) {
+               /* getting here when the state is UP means that the conn is *
+                * being terminated asynchronously from the iSCSI layer's   *
+                * perspective.                                             */
+               if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
+                   ISER_CONN_TERMINATING))
+                       iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
+                                          ISCSI_ERR_CONN_FAILED);
+
+               /* complete the termination process if disconnect event was 
delivered *
+                * note there are no more non completed posts to the QP         
      */
+               if (ib_conn->disc_evt_flag) {
+                       ib_conn->state = ISER_CONN_DOWN;
+                       wake_up_interruptible(&ib_conn->wait);
+               }
+       }
 }
 
 static void iser_cq_tasklet_fn(unsigned long data)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to