On Thu, 14 Oct 2004 13:33:08 -0400
Hal Rosenstock <[EMAIL PROTECTED]> wrote:

>       /* Validate MAD registration request if supplied */
>       if (mad_reg_req) {
> -             if (!recv_handler ||
> -                 mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION) {
> +             if (mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION) {
>                       ret = ERR_PTR(-EINVAL);
>                       goto error1;
>               }
> +             if (!bitmap_empty(mad_reg_req->method_mask,
> +                               IB_MGMT_MAX_METHODS)) {
> +                     if (!recv_handler) {
> +                             ret = ERR_PTR(-EINVAL);
> +                             goto error1;
> +                     }
> +             } else {
> +                     if (!send_handler) {
> +                             ret = ERR_PTR(-EINVAL);
> +                             goto error1;
> +                     }
> +             }

I'm not quite understanding this change.  If the user has provided a mad_reg_req, they 
are indicating that they want to receive unsolicited MADs.  A recv_handler should be 
required.  Am I missing something?

>       /* Validate device and port */
> @@ -842,7 +854,9 @@
>               spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
>  
>               /* Defined behavior is to complete response before request */
> -             mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
> +             if (mad_agent_priv->agent.recv_handler)
> +                     mad_agent_priv->agent.recv_handler(
> +                                             &mad_agent_priv->agent,
>                                               &recv->header.recv_wc);
>               atomic_dec(&mad_agent_priv->refcount);

If I understand this change, a client sent a MAD, expecting a response, got one, but 
didn't register with a receive handler.  As a side thought, I'm wondering how much 
protection we need to build into the code to handle kernel clients that don't provide 
all of the necessary parameters, but we can discuss this.

The only real problem with this change is that the receive buffer needs to be released 
if it is not given to a client.  We should probably change the send status as well, 
since no response was delivered.

> @@ -851,7 +865,9 @@
>               mad_send_wc.wr_id = mad_send_wr->wr_id;
>               ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
>       } else {
> -             mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent,
> +             if (mad_agent_priv->agent.recv_handler)
> +                     mad_agent_priv->agent.recv_handler(
> +                                             &mad_agent_priv->agent,
>                                               &recv->header.recv_wc);

Need to free the receive buffer here as well if not delivered.

> -     if (!mad_agent) { 
> +     if (!mad_agent || !mad_agent->agent.recv_handler) { 

This appears to be where the receive buffer would have been freed, but...
We can't safely walk into the mad_agent structure after calling 
ib_mad_complete_recv().  Immediately above this code a reference is taken on the 
mad_agent.  That reference is released in ib_mad_complete_recv(), which would allow 
the user to destroy the mad_agent before returning back to this call and the if 
statement above.

I'm more in favor of removing checks for a recv_handler completely, but if we want to 
keep it, we can move it into find_mad_agent(), and just not report a mad_agent if it 
doesn't have a recv_handler.

>       if (mad_send_wr->status != IB_WC_SUCCESS )
>               mad_send_wc->status = mad_send_wr->status;
> -     mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
> mad_send_wc);
> +     if (mad_agent_priv->agent.send_handler)
> +             mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
> +                                                 mad_send_wc);

This has similar problems to the receive handling.  If a client issued a send, but 
doesn't have a send_handler, there's nothing we can do with the send buffer, which 
needs to be freed.  I think that a client who does this is causing more problems then 
we can deal with in the access layer.

A possible fix for this is to check that mad_agent has a send_handler when the send is 
posted, rather than waiting until it completes.

>       /* Release reference on agent taken when sending */
>       if (atomic_dec_and_test(&mad_agent_priv->refcount))
> @@ -1135,7 +1153,9 @@
>       list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr,
>                                &cancel_list, agent_list) {
>               mad_send_wc.wr_id = mad_send_wr->wr_id;
> -             mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
> +             if (mad_agent_priv->agent.send_handler)
> +                     mad_agent_priv->agent.send_handler(
> +                                                &mad_agent_priv->agent,
>                                                  &mad_send_wc);

Same issue as above.
  
>               list_del(&mad_send_wr->agent_list);
> @@ -1196,8 +1216,9 @@
>       mad_send_wc.status = IB_WC_WR_FLUSH_ERR;
>       mad_send_wc.vendor_err = 0;
>       mad_send_wc.wr_id = mad_send_wr->wr_id;
> -     mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
> -                                        &mad_send_wc);
> +     if (mad_agent_priv->agent.send_handler)
> +             mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
> +                                                &mad_send_wc);

Ditto.
_______________________________________________
openib-general mailing list
[EMAIL PROTECTED]
http://openib.org/mailman/listinfo/openib-general

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

Reply via email to