RE: [net-next 1/9] Implementation of Virtual Bus

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

 



> -----Original Message-----
> From: Jason Gunthorpe <jgg@xxxxxxxx>
> Sent: Monday, April 20, 2020 5:45 PM
> To: Ertman, David M <david.m.ertman@xxxxxxxxx>
> Cc: Kirsher, Jeffrey T <jeffrey.t.kirsher@xxxxxxxxx>; davem@xxxxxxxxxxxxx;
> gregkh@xxxxxxxxxxxxxxxxxxx; netdev@xxxxxxxxxxxxxxx; linux-
> rdma@xxxxxxxxxxxxxxx; nhorman@xxxxxxxxxx; sassmann@xxxxxxxxxx;
> parav@xxxxxxxxxxxx; galpress@xxxxxxxxxx;
> selvin.xavier@xxxxxxxxxxxx; sriharsha.basavapatna@xxxxxxxxxxxx;
> benve@xxxxxxxxx; bharat@xxxxxxxxxxx; xavier.huwei@xxxxxxxxxx;
> yishaih@xxxxxxxxxxxx; leonro@xxxxxxxxxxxx; mkalderon@xxxxxxxxxxx;
> aditr@xxxxxxxxxx; ranjani.sridharan@xxxxxxxxxxxxxxx; pierre-
> louis.bossart@xxxxxxxxxxxxxxx; Patil, Kiran <kiran.patil@xxxxxxxxx>; Bowers,
> AndrewX <andrewx.bowers@xxxxxxxxx>
> Subject: Re: [net-next 1/9] Implementation of Virtual Bus
> 
> On Mon, Apr 20, 2020 at 11:16:38PM +0000, Ertman, David M wrote:
> > > > +/**
> > > > + * virtbus_register_device - add a virtual bus device
> > > > + * @vdev: virtual bus device to add
> > > > + */
> > > > +int virtbus_register_device(struct virtbus_device *vdev)
> > > > +{
> > > > +	int ret;
> > > > +
> > > > +	/* Do this first so that all error paths perform a put_device */
> > > > +	device_initialize(&vdev->dev);
> > > > +
> > > > +	if (!vdev->release) {
> > > > +		ret = -EINVAL;
> > > > +		dev_err(&vdev->dev, "virtbus_device MUST have a .release
> > > callback that does something.\n");
> > > > +		goto device_pre_err;
> > >
> > > This does put_device but the release() hasn't been set yet. Doesn't it
> > > leak memory?
> >
> > The KO registering the virtbus_device is responsible for allocating
> > and freeing the memory for the virtbus_device (which should be done
> > in the release() function).  If there is no release function
> > defined, then the originating KO needs to handle this.  We are
> > trying to not recreate the platform_bus, so the design philosophy
> > behind virtual_bus is minimalist.
> 
> Oh, a precondition assertion should just be written as something like:
> 
>    if (WARN_ON(!vdev->release))
>        return -EINVAL;
> 
> And done before device_initialize
> 
> But I wouldn't bother, things will just reliably crash on null pointer
> exceptions if a driver mis-uses the API.
> 

Done.

> > > > +	}
> > > > +
> > > > +	/* All device IDs are automatically allocated */
> > > > +	ret = ida_simple_get(&virtbus_dev_ida, 0, 0, GFP_KERNEL);
> > > > +	if (ret < 0) {
> > > > +		dev_err(&vdev->dev, "get IDA idx for virtbus device
> failed!\n");
> > > > +		goto device_pre_err;
> > >
> > > Do this before device_initialize()
> >
> > The memory for virtbus device is allocated by the KO registering the
> > virtbus_device before it calls virtbus_register_device().  If this
> > function is exiting on an error, then we have to do a put_device()
> > so that the release is called (if it exists) to clean up the memory.
> 
> put_device() must call virtbus_release_device(), which does
> ida_simple_remove() on vdev->id which hasn't been set yet.
> 
> Also ->release wasn't initialized at this point so its leaks memory..

->release assignment moved to before ida_simple_get evaluation,
and added a define for VIRTBUS_INVALID_ID and a check in release
to not do ida_simple_remove for an invalid ID.

> 
> > The ida_simple_get is not used until later in the function when
> > setting the vdev->id.  It doesn't matter what IDA it is used, as
> > long as it is unique.  So, since we cannot have the error state
> > before the device_initialize, there is no reason to have the
> > ida_sinple_get before the device_initialization.
> 
> I was a bit wrong on this advice because no matter what you have to do
> put_device(), so you need to add some kind of flag that the vdev->id
> is not valid.
> 

Did just that 😊

> It is ugly. It is nicer to arrange thing so initialization is done
> after kalloc but before device_initialize. For instance look how
> vdpa_alloc_device() and vdpa_register() work, very clean, very simple
> goto error unwinds everywhere.
> 
> > GregKH was pretty insistent that all error paths out of this
> > function go through a put_device() when possible.
> 
> After device_initialize() is called all error paths must go through
> put_device.
> 
> > > Can't understand why vdev->name is being passed in with the struct,
> > > why not just a function argument?
> >
> > This avoids having the calling KO have to manage a separate piece of
> memory
> > to hold the name during the call to virtbus_device_regsiter.  It is a cleaner
> > memory model to just store it once in the virtbus_device itself.  This name
> is
> > the abbreviated name without the ID appended on the end, which will be
> used
> > for matching drivers and devices.
> 
> Your other explanation was better. This would be less confusing if it
> was called match_name/device_label/driver_key or something, as it is
> not the 'name'.
> 

changing the vdev->name to vdev->match_name

> > > > + * virtbus_unregister_device - remove a virtual bus device
> > > > + * @vdev: virtual bus device we are removing
> > > > + */
> > > > +void virtbus_unregister_device(struct virtbus_device *vdev)
> > > > +{
> > > > +	device_del(&vdev->dev);
> > > > +	put_device(&vdev->dev);
> > > > +}
> > > > +EXPORT_SYMBOL_GPL(virtbus_unregister_device);
> > >
> > > Just inline this as wrapper around device_unregister
> >
> > I thought that EXPORT_SYMBOL makes inline meaningless?
> > But, putting device_unregister here is a good catch.
> 
> I mean move it to the header file and inline it

Done.

> 
> Jason

-DaveE




[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