This patch solves a race between elements in work queues that are 
carried out after an event occurs. When SM address handle becomes i
nvalid and needs an update it is set to NULL and until update_sm_ah() 
is called, any request that needs sm_ah is replied with -EAGAIN return 
status.

Signed-off-by: Moni Levy  <[EMAIL PROTECTED]>
Signed-off-by: Moni Shoua <[EMAIL PROTECTED]>

---

 drivers/infiniband/core/sa_query.c |   28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/core/sa_query.c 
b/drivers/infiniband/core/sa_query.c
index cf474ec..19439d8 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -407,15 +407,27 @@ static void update_sm_ah(struct work_str
 
 static void ib_sa_event(struct ib_event_handler *handler, struct ib_event 
*event)
 {
+
        if (event->event == IB_EVENT_PORT_ERR    ||
            event->event == IB_EVENT_PORT_ACTIVE ||
            event->event == IB_EVENT_LID_CHANGE  ||
            event->event == IB_EVENT_PKEY_CHANGE ||
            event->event == IB_EVENT_SM_CHANGE   ||
            event->event == IB_EVENT_CLIENT_REREGISTER) {
-               struct ib_sa_device *sa_dev;
-               sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
-
+               unsigned long flags;
+               struct ib_sa_device *sa_dev =
+                       container_of(handler, typeof(*sa_dev), event_handler);
+               struct ib_sa_port *port =
+                       &sa_dev->port[event->element.port_num - 
sa_dev->start_port];
+               struct ib_sa_sm_ah *sm_ah;
+
+               spin_lock_irqsave(&port->ah_lock, flags);
+               sm_ah = port->sm_ah;
+               port->sm_ah = NULL;
+               spin_unlock_irqrestore(&port->ah_lock, flags);
+
+               if (sm_ah)
+                       kref_put(&sm_ah->ref, free_sm_ah);
                schedule_work(&sa_dev->port[event->element.port_num -
                                            sa_dev->start_port].update_task);
        }
@@ -780,6 +792,10 @@ int ib_sa_service_rec_query(struct ib_sa
                return -ENODEV;
 
        port  = &sa_dev->port[port_num - sa_dev->start_port];
+       if (!port->sm_ah) {
+               return  -EAGAIN;
+       }
+
        agent = port->agent;
 
        if (method != IB_MGMT_METHOD_GET &&
@@ -877,8 +893,12 @@ int ib_sa_mcmember_rec_query(struct ib_s
                return -ENODEV;
 
        port  = &sa_dev->port[port_num - sa_dev->start_port];
-       agent = port->agent;
+       if (!port->sm_ah) {
+               return  -EAGAIN;
+       }
 
+       agent = port->agent;
+       
        query = kmalloc(sizeof *query, gfp_mask);
        if (!query)
                return -ENOMEM;
_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to