HI Alexandre!

On Wed, Oct 14, 2026 at 4:04 AM Alexandre Courbot <[email protected]> wrote:
>
> Hi Burak,
>
> On Sat Oct 10, 2026 at 3:48 AM JST, Burak Emir wrote:
> > On Fri, Oct 9, 2026 at 4:07 PM Alexandre Courbot <[email protected]> 
> > wrote:
> >>
> >> On Fri Oct 9, 2026 at 12:47 AM JST, Yury Norov wrote:
> >
> >> > If you still think that you need 0-length bitmaps in Rust, can you please
> >> > give the clear and thorough explanation why rust needs those 0-length
> >> > bitmaps. Are there any in-kernel examples? Any language concepts 
> >> > requiring
> >> > it? If not, it's still a NAK.
> >>
> >> I don't know of an in-kernel example, but please look at the
> >> `bitmap_vec_new` test which has been here since the API was initially
> >> merged last year: the first thing it does is create a zero-sized bitmap.
> >
> > Well, yeah: I wanted the behavior that the implementation rounds up
> > documented so it can be recognized as intentional.
> > Later, the `new_inline` method was added, which is a clearer way to
> > get the largest non-allocating BitmapVec.
> >
> > I think the problem in this discussion is that we want to treat
> > capacity like length, which is maybe suggested by the BitmapVec name
> > and its len method.
> >
> > With the minimum capacity behavior documented, it is as if we have a
> > specification right now that no IdPool instances can ever have less
> > capacity than BitmapVec::MAX_INLINE_LEN bits. This patch here proposes
> > to change that.
> >
> > It is not clear though why client code would be happy about *less capacity*?
> >
> > In other words, why should the client of the IdPool have the right to
> > control the *exact* initial capacity, even if it is below documented,
> > free-of-charge minimum capacity?
>
> The ID pool is used in Nova to track the number of hardware channels, of
> which we have an exact, fixed number. For this use-case rounding up is
> not "free-of-charge", it just allows to allocate IDs that are invalid as
> there is no hardware resource to back them up.

This makes sense, and I'm glad you can reuse the code.
The origin of the bitmap IdPool to isolate the Binder-specific
spin-lock-compatible resizing functionality.
In the Binder use cases, an "allocated ID" corresponds to a bit that
is set to 1.

> >
> > The IdPool, despite being backed by a BitmapVec, is not meant to be
> > used like a vector: it does not grow by itself but client code calls
> > grow and shrink explicitly, and client code has no control over how
> > much that growing and shrinking happens.
> >
> > Like, you cannot grow to 65 and expect to get a capacity 65. So why
> > insist on exact small sizes?
>
> Actually with the current code you can call `IdPool::with_capacity(65)`
> and you will get exactly 65 IDs. And if you call grow the new capacity
> will be `65 * 2`.

Touche, I was too anchored in my "IdPool is just for resizing" thinking.
I meant, when starting from a no-allocation size that one only gets
multiples of word length.

However, I do understand that you would like IdPool to track for sizes
below 64, so ChannelIdPool does not have to.

> The point being that in the current code the initial capacity is exact
> for every value *except* those below `MAX_INLINE_LEN`, which doesn't
> come across as consistent. All this patch does is remove that exception
> for which I don't see a justification.
> I think we are conflating capacity with length to some degree. Actually
> the code does exactly that:
>
>   impl IdPool {
>       pub fn capacity(&self) -> usize {
>           self.map.len()
>       }
>   }
>

Yes, the original IdPool is "conflated by design", since for Binder ID
allocation means something different.
- "length" for BitmapVec is length of the underlying bitmap in bits.
- "capacity" in (binder-specific...) IdPool means "we can allocate
this many IDs in total without resizing.

> >
> >> It is also easy to imagine a user starting with an empty pool and
> >> growing it on-demand. Having the ability to create a zero-sized pool is
> >> convenient to avoid special-casing user code, and in this case I'd say
> >> expected, just like you can create a zero-sized vector. Again a size of
> >> zero does not trigger anything that a larger capacity cannot trigger, so
> >> I don't see a reason to forbid it.
> >
> > With an initial capacity of minimum MAX_INLINE_LEN capacity, it is not
> > about forbidding, it is that the added capacity already comes for
> > free.
> > You could say "not enabling" instead of "forbidding", but pretending
> > that the capacity is somehow not there does not seem to buy us
> > anything.
>
> The capacity is not necessarily there when allocating IDs for finite
> resources. I suspect that's where the misunderstanding stems from, as
> Nova is using the ID pool for a new use-case. But I think we can agree
> that this use-case is not particularly specific and matches what one can
> expect from an ID allocator, so it makes sense to support it, especially
> as it doesn't affect other users (`with_capacity` has no caller in the
> tree at the moment).

It makes complete sense to support it.
IMO it is less of a misunderstanding, but a design decision to juggle
the requirements.
This IdPool thing was not meant as a general-purpose ID allocator.
But I do see the appeal to generality.

> >
> > Do the other patches in this series need this, or can we just drop this 
> > patch?
> > If they do, maybe a demonstration of how significant the special-case
> > handling is that can be avoided with the exact small capacity could be
> > part of the commit message?
>
> The next patch in this series needs this to implement `ChannelIdPool`.
> The alternative would be to track the actual length of the pool and
> return an error if `IdPool` returns an ID after that value, which is
> what v5 [1] was doing (see `num_chids` in the v5 code).
>
> That's the special-case handling that this patch is designed to avoid,
> and I hope we can agree that it isn't a satisfying workaround,
> especially when the backing `BitmapVec` *does* support exact sizes and
> that artificial limitation is introduced by `IdPool` itself.
>
> [1] https://lore.kernel.org/all/[email protected]/

Thanks for the link.
To me, having IdPool support exact size seems nice-to-have.

We are changing the design in light of different requirements, it is a
defensible but not critical generalization.
I was worried that we may need to have proper separate length and
capacity fields (which contradicts the binder use case), but that is
not the case.

I checked the grow_request and grow dance now, it seems that even with
exact small sizes we avoid allocating a bitmap.
So I am not opposed. Like Yury, I find the 0 case slightly odd, but
unlike Yury, I find that tolerable.

The phrasing as "dropping an artificial limitation" does not
adequately reflect that IdPool was done for a specific use case where
the design made sense and is not actually a limitation.

I wanted to highlight this perspective, because notwithstanding the
name, IdPool was not meant to join the set of kernel's dedicated
supported ID allocation mechanisms.

cheers,
Burak

Reply via email to