Re: [PATCH for-rc] RDMA/qder: Fix memory leak of iwcm pointer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 4/23/19 5:24 PM, Jason Gunthorpe wrote:
> On Tue, Apr 23, 2019 at 04:51:12PM +0300, Kamal Heib wrote:
>>
>>
>> On 4/23/19 3:31 PM, Jason Gunthorpe wrote:
>>> On Tue, Apr 23, 2019 at 09:24:07AM +0300, Kamal Heib wrote:
>>>>
>>>>
>>>> On 4/22/19 6:40 PM, Jason Gunthorpe wrote:
>>>>> On Mon, Apr 22, 2019 at 05:00:19PM +0300, Kamal Heib wrote:
>>>>>> Make sure to release the iwcm pointer that is allocated in
>>>>>> qedr_iw_register_device() but never released.
>>>>>>
>>>>>> Fixes: e6a38c54faf3 ("RDMA/qedr: Add support for registering an iWARP device")
>>>>>> Signed-off-by: Kamal Heib <kamalheib1@xxxxxxxxx>
>>>>>>  drivers/infiniband/hw/qedr/main.c | 10 +++++++++-
>>>>>>  1 file changed, 9 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
>>>>>> index 996d9ecd93e0..567f55178379 100644
>>>>>> +++ b/drivers/infiniband/hw/qedr/main.c
>>>>>> @@ -293,7 +293,13 @@ static int qedr_register_device(struct qedr_dev *dev)
>>>>>>  	ib_set_device_ops(&dev->ibdev, &qedr_dev_ops);
>>>>>>  
>>>>>>  	dev->ibdev.driver_id = RDMA_DRIVER_QEDR;
>>>>>> -	return ib_register_device(&dev->ibdev, "qedr%d");
>>>>>> +	rc = ib_register_device(&dev->ibdev, "qedr%d");
>>>>>> +	if (rc) {
>>>>>> +		if (IS_IWARP(dev))
>>>>>> +			kfree(dev->ibdev.iwcm);
>>>>>> +	}
>>>>>> +
>>>>>> +	return rc;
>>>>>>  }
>>>>>>  
>>>>>>  /* This function allocates fast-path status block memory */
>>>>>> @@ -937,6 +943,8 @@ static void qedr_remove(struct qedr_dev *dev)
>>>>>>  	 * of the registered clients.
>>>>>>  	 */
>>>>>>  	ib_unregister_device(&dev->ibdev);
>>>>>> +	if (IS_IWARP(dev))
>>>>>> +		kfree(dev->ibdev.iwcm);
>>>>>
>>>>> This should probably just be in a dealloc_driver callback instead of
>>>>> duplicated
>>>>>
>>>>> Jason
>>>>>
>>>>
>>>> I don't think so
>>>
>>> Why? That is is the defined place to free memory linked to the struct
>>> ib_device
>>>
>>
>> dealloc_driver() is something that introduced recently and I'm interested in
>> backport this fix to RHEL versions that don't include the dealloc_driver(),
>> that's why I'm targeting this fix to for-rc.
> 
> Distro constraints are not really a reason to do something sub optimal
> upstream... 
> 

OK, What about -stable upstream versions?

> for-rc has the dealloc_driver flow, so you should use it instead of
> duplicated code like this.
> 

Do you mean modify all the iWarp providers to implement dealloc_driver()
callback which will free the iwcm pointer?

>>>> I think that we need to define a new interface in the core (iwcm.c)
>>>> for the IWARP devices to use when {allocate, setting ops to,
>>>> release} iwcm, what do you think?
>>>
>>> Why?
>>>
>>
>> 1- Avoid bugs like this.
>> 2- Reduce code duplication in the providers.
>> 3- Make the providers code more cleaner.
>>
>> I'm suggesting to introduce the following two functions and modify the IWARP
>> providers to use them.
>>
>> int iw_cm_register_device(struct ib_device *ibdev, char *ifname,
>> 			  const struct iw_cm_ops *ops)
>> {
>> 	ibdev->iw_cm_dev = kzalloc(sizeof(*ibdev->iw_cm_dev), GFP_KERNEL);
>> 	if (!ibdev->iw_cm_dev)
>> 		return -ENOMEM;
>>
>> 	ibdev->iw_cm_dev->ops = ops;
>> 	memcpy(ibdev->iw_cm_dev->ifname, ifname,
>> 	       sizeof(ibdev->iw_cm_dev->ifname));
> 
> Why not just have this as part of the normal register process and pass
> the iw_cm_ops through the existing ops structure?
> 

Do you mean to pass the ifname as a parameter to ib_register_device() and modify
the ib_device_ops to include the following callbacks from iw_cm_verbs?

If that is the case then we can add the "ifname" & "driver_flags" to the
ib_device struct and remove the iw_cm_verbs struct, which will mean that no need
to implement the dealloc_driver() callback, because the iwcm pointer isn't
allocated.

struct iw_cm_verbs {
	void		(*add_ref)(struct ib_qp *qp);

	void		(*rem_ref)(struct ib_qp *qp);

	struct ib_qp *	(*get_qp)(struct ib_device *device,
				  int qpn);

	int		(*connect)(struct iw_cm_id *cm_id,
				   struct iw_cm_conn_param *conn_param);

	int		(*accept)(struct iw_cm_id *cm_id,
				  struct iw_cm_conn_param *conn_param);

	int		(*reject)(struct iw_cm_id *cm_id,
				  const void *pdata, u8 pdata_len);

	int		(*create_listen)(struct iw_cm_id *cm_id,
					 int backlog);

	int		(*destroy_listen)(struct iw_cm_id *cm_id);
	char		ifname[IFNAMSIZ];
	enum iw_flags	driver_flags;
};

Thanks,
Kamal





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux