> Are you sure that only one thread at a time will invoke a CM callback ? As
> far as I can see cm_recv_handler() queues work without checking whether
> any other work is ongoing. From drivers/infiniband/core/cm.c:

All callbacks for a single ID should be serialized.  (I think the listen ID is 
an exception, which would allow reporting multiple connection requests.)

cm_work_handler dispatches work to specific handlers based on the type of CM 
message.  The serialization doesn't occur until we know which ID we're dealing 
with and its state.  See the cm_*_handler(work) calls.
 
> What I have noticed could be explained by the following sequence of events:
> * IB CM core receives a connection request and invokes the callback for event
>   IB_CM_REQ_RECEIVED.

The flow should be: cm_work_handler() -> cm_req_handler() -> cm_match_req(), 
which increments work_count (to 1 in this case).

> * That callback adds connection information to a global list (and keeps
> running).

Do you mean that the callback doesn't return to the CM?

> * User requests shutdown and hence from another thread ib_send_cm_dreq() is
> invoked.

ib_send_cm_dreq() at this point should fail with EINVAL, as the connection 
state is not yet established.  So, I don't think I'm quite following the 
operation yet.

> * IB CM core receives a DREP message and invokes the callback for event
>   IB_CM_DREP_RECEIVED. That callback function gets confused because of the
>   concurrent connection state manipulations by the IB_CM_REQ_RECEIVED handler
>   (which is still running).

The cm_drep_handler() code increments work_count and checks the result.  If 
work_count was non-zero, then the DREP event should be queued on the id's 
work_list.  The thread which set work_count to 1, will eventually invoke the 
callback for that event.

- Sean

Reply via email to