[openib-general] Re: [PATCH] CMA and iWARP

Sean Hefty mshefty at ichips.intel.com
Thu Jan 26 11:24:46 PST 2006


Tom Tucker wrote:
> +/* Handles an inbound connect request. The function creates a new
> + * iw_cm_id to represent the new connection and inherits the client
> + * callback function and other attributes from the listening parent. 
> + * 
> + * The work item contains a pointer to the listen_cm_id and the event. The
> + * listen_cm_id contains the client cm_handler, context and device. These are
> + * copied when the device is cloned. The event contains the new four tuple.

Does the code take a reference on the listen_cm_id before scheduling the work item?

> + */
> +static int cm_conn_req_handler(struct iwcm_work* work)
> +{
> +	struct iw_cm_id* cm_id;
> +	struct iwcm_id_private* cm_id_priv;
> +	int rc;
> +
> +	/* If the status was not successful, ignore request */
> +	if (work->event.status) {
> +		printk(KERN_ERR "%s:%d Bad status=%d for connection request ... "
> +		       "should be filtered by provider\n",
> +		       __FUNCTION__, __LINE__,
> +		       work->event.status);
> +		return work->event.status;
> +	}
> +	cm_id = iw_create_cm_id(work->cm_id->id.device,	work->cm_id->id.cm_handler,
> +				work->cm_id->id.context);
> +	if (IS_ERR(cm_id)) 
> +		return PTR_ERR(cm_id);
> +
> +	cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +	cm_id_priv->id.local_addr = work->event.local_addr;
> +	cm_id_priv->id.remote_addr = work->event.remote_addr;
> +	cm_id_priv->id.provider_id = work->event.provider_id;
> +	cm_id_priv->id.state = IW_CM_STATE_CONN_RECV;
> +
> +	/* Call the client CM handler */
> +	rc = cm_id->cm_handler(cm_id, &work->event);
> +	if (rc) {
> +		cm_id->state = IW_CM_STATE_IDLE;
> +		iw_destroy_cm_id(cm_id);
> +	}
> +	kfree(work);
> +	return 0;
> +}

> +
> +/*
> + * Handles the transition to established state on the passive side.
> + */
> +static int cm_conn_est_handler(struct iwcm_work* work)
> +{

{snip}

> +	/* Call the client CM handler */
> +	ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->event);

A reference needs to be taken on the cm_id_priv before invoking the callback to 
block destruction.  (I didn't see that a reference was released...)

> +static int cm_conn_rep_handler(struct iwcm_work* work)
> +{
> +	struct iwcm_id_private* cm_id_priv;
> +	unsigned long flags;
> +	int ret = 0;

{snip}

> +
> +	/* Call the client CM handler */
> +	ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->event);
> +	if (ret) {
> +		cm_id_priv->id.state = IW_CM_STATE_IDLE;
> +		iw_destroy_cm_id(&cm_id_priv->id);
> +	}

Same here - a reference is needed to block destruction before invoking the callback.

> +static int cm_disconnect_handler(struct iwcm_work* work) 
> +{
> +	struct iwcm_id_private* cm_id_priv;
> +	int ret = 0;
> +	
> +	cm_id_priv = work->cm_id;
> +
> +	cm_id_priv->id.state = IW_CM_STATE_IDLE;
> +
> +	/* Call the client CM handler */
> +	ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, &work->event);
> +	if (ret)
> +		iw_destroy_cm_id(&cm_id_priv->id);

And here...

> +static void cm_event_handler(struct iw_cm_id* cm_id,
> +			     struct iw_cm_event* event) 
> +{
> +	struct iwcm_work *work;
> +	struct iwcm_id_private* cm_id_priv;
> +
> +	work = kmalloc(sizeof *work, GFP_ATOMIC);
> +	if (!work)
> +		return;
> +
> +	cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
> +	INIT_WORK(&work->work, cm_work_handler, work);
> +	work->cm_id = cm_id_priv;

Reference the cm_id before queuing the work item.  It needs to be released after 
processing any callbacks.

- Sean



More information about the general mailing list