Re: [PATCH 0/3] ipc subsystem refcounter conversions
From: Peter Zijlstra
Date: Mon May 29 2017 - 11:44:07 EST
On Mon, May 29, 2017 at 02:23:16PM +0200, Peter Zijlstra wrote:
> On Mon, May 29, 2017 at 06:39:44AM -0500, Eric W. Biederman wrote:
> > I failed to see that there is a refcount_inc. Too much noise in
> > the header file I suppose.
> >
> > But implementing refcount_inc in terms of refcount_inc_not_zero is
> > totally broken. The two operations are not the same and the go to
> > different assumptions the code is making.
> >
> > That explains why you think refcount_inc_not_zero should lie because
> > you are implementing refcount_inc with it. They are semantically very
> > different operations. Please separate them.
>
> There has been much debate about this. And the best I'll do is add a
> comment and/or retain these exact semantics.
>
> What is done is:
>
> refcount_inc() := WARN_ON(!refcount_inc_not_zero())
>
> Because incrementing a zero reference count is a use-after-free and
> something we should not do ever.
>
> This is where the whole usage count vs reference count pain comes from.
>
> Once there are no more _references_ to an object, a reference count
> frees the object. Therefore a zero reference count means a dead object
> and incrementing from that is fail.
>
> The usage count model otoh counts how many (active) users there are of
> an object, and no active users is a good and expected situation. But it
> is very explicitly not a reference count. Because even in the no users
> case do we have a reference to the object (we've not leaked it after
> all, we just don't track all references).
>
>
> Similarly, refcount_dec() is implemented using dec_and_test() and will
> WARN when it hits 0, because this is a leak and we don't want those
> either.
>
> A usage count variant otoh would be fine with hitting 0.
A typical pattern for the usage count is caches, where objects are kept
in a data structure (hash/tree and/or list) and we count how many users
there are of said objects. A GC or shrinker will then iterate the
structure and prune those objects that have 0 users.
It is fairly straight forward to convert those to refcount_t by adding
one reference for the data structure itself. The GC/shrinker will then
have to use something like refcount_dec_if_one() to drop the reference
from 1->0 (and we could easily add something like dec_and_lock_if_one if
so desired).
Not all of them mind you, but simple cases can certainly be done without
too much pain.
But clearly there have been conversions of less than desired quality /
clarity though ...