[Intel-gfx] [PATCH 7/9] drm/i915/gt: Fix memory leaks in per-gt sysfs

Dixit, Ashutosh ashutosh.dixit at intel.com
Tue May 3 04:29:10 UTC 2022


On Sun, 01 May 2022 23:22:02 -0700, Andrzej Hajda wrote:
> On 29.04.2022 06:25, Dixit, Ashutosh wrote:
> > On Thu, 28 Apr 2022 07:36:14 -0700, Andrzej Hajda wrote:
> >> See [1], it is quite old, so maybe it is not valid anymore, but I see no
> >> code proving sth has changed.
> > Hi Andrzej,
> >
> > A lot has changed since that article from 2003 (for 2.5 kernel). For
> > instance there is kernfs (as I mention above):
> >
> >	https://lwn.net/Articles/571590/
> >
> > A process having a sysfs file open today in my view will result in the
> > following:
> > * It will take a reference on kernfs_node (not on kobject as was the case
> >    in kernel 2.5 in [1])
> > * An open file will prevent the module from being unloaded (not the kernel
> >    crashing as in 2.5 in [1])
>
> Thats nice, but kernfs_node->priv still points to kobject so their
> lifetimes are bounded.

Yes, of course there has to be some connection between the kernfs and kobject.

> > So this is what I would expect with today's kernel. I am not seeing
> > anything we've done here which violates anything in [1] or [2].
> >> Also current doc says also [2] similar things, especially:
> >> "Once you registered your kobject via kobject_add(), you must never use
> >> kfree() to free it directly"
> > Correct, we are using kobject_put(), not kfree'ing the kobject.
>
> That I wouldn't agree. kobject_put is called, then the object in which
> kobject is embedded is kfree'd somewhere later on driver removal, without
> awareness of this kobject.  According to your analysis it should have 0
> refs, but this is analysis of the current code, even if it is true now it
> could change in the future.

Yes but we cannot anticipate all changes which can happen in the future,
(though we should handle and make any changes which we can anticipate at
present). This is also basically what the kernel philosophy is, don't make
unnecessary generalizations and try to handle unforseen situations which
can happen in the future.

Let me add some explanations about the patch before addressing your next
point.

1. We are adding 'struct kobject sysfs_gt' to 'struct intel_gt'. We are
   adding the kobject directly, not pointer to kobject. This allows us to
   "reach" 'struct intel_gt' from the kobject using a simple container_of:
   see kobj_to_gt().

2. Because the kobject is not kmalloc'd it cannot be kfree'd so the release
   method has to be empty (or NULL). 'struct intel_gt' is kmalloc'd
   separately elsewhere and memory for the kobject will be freed as part of
   intel_gt.

3. To provide a NULL or empty release method we need to provide a 'struct
   kobj_type kobj_gt_type' associated with the sysfs_gt kobject. This works
   nicely because we were anyway need one for .default_groups (we may add
   other attributes to 'id_groups' in the future). Note that the kobject is
   initialized and added to sysfs using kobject_init_and_add().

4. The only reason for providing an empty release method rather than a NULL
   release method is the following pr_debug in kobject_cleanup():

           if (t && !t->release)
                pr_debug("kobject: '%s' (%p): does not have a release() function, it is broken and must be fixed. See Documentation/core-api/kobject.rst.\n",
                         kobject_name(kobj), kobj);

  This statement could possibly be removed because the release method is
  not needed in the case I just described above, maybe I'll send a patch to
  suggest removing it. Though I think what they will say is that since NULL
  release methods are uncommon maybe just provide an empty release method
  when you need a NULL release method (which is what I have done in the
  patch).

  Also note that, as described below, there are several other cases in the
  kernel which either have NULL or an empty release methods. See below.

> And IMO it is against docs[2]:
> - "One important point cannot be overstated: every kobject must have a
> release() method, and the kobject must persist (in a consistent state)
> until that method is called. If these constraints are not met, the code is
> flawed." - empty release method means clearly it is against the docs.
> -"The end result is that a structure protected by a kobject cannot be freed
> before its reference count goes to zero. The reference count is not under
> the direct control of the code which created the kobject.".
>
> So either docs and part of kobject code were not updated to reflect
> changes you are assuming, either your assumption is incorrect.

In my view the doc is a general introduction to kobjects and simplifies
things. As shown below there are numerous examples in the kernel of both
NULL and empty release methods. I just went with the empty method because
of the reason mentioned above.

> Looking at other users of kobject it seems they follow docs, their
> release method either frees memory directly either kref_put on containing
> struct, it was just quick scan so I could overlooked sth.
>
> >> [1]: https://lwn.net/Articles/36850/
> >> [2]:
> >> https://elixir.bootlin.com/linux/v5.18-rc4/source/Documentation/core-api/kobject.rst#L246

From my comments above, the trick to finding NULL or empty methods is to
search for the following construct:

        kobject_init_and_add(&xyz, ...)

If we do this we find the following:

NULL release method:
	procfs_queue_type
	integrity_ktype
	cppc_ktype
	acpi_hotplug_profile_ktype
	rnbd_dev_ktype
	ioat_ktype
	ab8500_fg_ktype

Empty release method:
	blk_ia_range_sysfs_nop_release()

I hope these examples should be sufficient to show that the release method
can be both NULL or empty.

So I still haven't found any reason to make changes to the v2 patch which I
have previously shown works correctly and without issues.

Thanks.
--
Ashutosh


More information about the Intel-gfx mailing list