[ofa-general] [PATCH] IB/core: handle race between elements in qork queues after event
Moni Shoua
monis at Voltaire.COM
Wed Apr 30 07:12:42 PDT 2008
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 <monil at voltaire.com>
Signed-off-by: Moni Shoua <monis at voltaire.com>
---
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;
More information about the general
mailing list