[Intel-gfx] [PATCH] drm: Release reference from blob lookup after replacing property

Chris Wilson chris at chris-wilson.co.uk
Tue Oct 25 21:45:19 UTC 2016


On Tue, Oct 25, 2016 at 05:27:21PM -0400, Sean Paul wrote:
> On Tue, Oct 25, 2016 at 3:46 PM, Chris Wilson <chris at chris-wilson.co.uk> wrote:
> > drm_property_lookup_blob() returns a reference to the returned blob, and
> > drm_atomic_replace_property_blob() takes a references to the blob it
> > stores, so afterwards we are left owning a reference to the new_blob that
> > we never release, and thus leak memory every time we update a property
> > such as during drm_atomic_helper_legacy_gamma_set().
> >
> > Based on a patch by Felix Monninger <felix.monninger at gmail.com>
> >
> > Reported-by: Felix Monninger <felix.monninger at gmail.com>
> > References: https://bugs.freedesktop.org/show_bug.cgi?id=98420
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > ---
> >  drivers/gpu/drm/drm_atomic.c | 11 ++++++++---
> >  1 file changed, 8 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> > index 1b5a32df9a9a..3b35ab793100 100644
> > --- a/drivers/gpu/drm/drm_atomic.c
> > +++ b/drivers/gpu/drm/drm_atomic.c
> > @@ -416,19 +416,24 @@ drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc,
> >                                          ssize_t expected_size,
> >                                          bool *replaced)
> >  {
> > -       struct drm_device *dev = crtc->dev;
> >         struct drm_property_blob *new_blob = NULL;
> >
> >         if (blob_id != 0) {
> > -               new_blob = drm_property_lookup_blob(dev, blob_id);
> > +               new_blob = drm_property_lookup_blob(crtc->dev, blob_id);
> 
> I think this could be further simplified by making use of
> drm_property_lookup_blob() returning NULL for blob_id == 0
> 
> Then you could do something like:
> 
> static int
> drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc,
>                                          struct drm_property_blob **old_blob,
>                                          uint64_t blob_id,
>                                          ssize_t expected_size,
>                                          bool *replaced)
> {
>         struct drm_property_blob *blob = NULL;
>         int ret = 0;
> 
>         blob = drm_property_lookup_blob(crtc->dev, blob_id);

Not sure. I think the orignal code would have been clearer as

blob = NULL;
if (id) {
	blob = drm_property_lookup_blob(dev, id);
	if (!blob)
		return -ENOENT;

	if (blob->length != expected_size)
		return -EINVAL;
}

i.e. the code currently reports if the blob_id doesn't match an existing
blob, and only removes the current blob if passed in 0.

Otherwise it becomes like:

        struct drm_property_blob *blob;
        int ret = -EINVAL;

        blob = drm_property_lookup_blob(crtc->dev, blob_id);
        if (!blob_id || 
            (blob && (expected_size == 0 || expected_size == blob->length))) {
                drm_atomic_replace_property_blob(old_blob, blob, replaced);
                ret = 0;
        }
        drm_property_unreference_blob(blob);

for which I'm actually favouring the existing code for the extra whitespace.

If we insisted on a single return path:

        struct drm_property_blob *new_blob = NULL;
        int ret = -EINVAL;

        if (blob_id != 0) {
                new_blob = drm_property_lookup_blob(crtc->dev, blob_id);
                if (new_blob == NULL)
                        goto out;

                if (expected_size > 0 && expected_size != new_blob->length)
                        goto out;
        }

        drm_atomic_replace_property_blob(blob, new_blob, replaced);
        ret = 0;

out:
        drm_property_unreference_blob(new_blob);
        return ret;

-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the dri-devel mailing list