On Mon, Jun 24, 2024 at 10:26 AM Usama Arif <usamaarif642@xxxxxxxxx> wrote: > > > On 24/06/2024 19:56, Yosry Ahmed wrote: > > [..] > >>>> - p->zeromap = bitmap_zalloc(maxpages, GFP_KERNEL); > >>>> + p->zeromap = kvzalloc(DIV_ROUND_UP(maxpages, 8), GFP_KERNEL); > >>> No, 8 is not right for 32-bit kernels. I think you want > >>> p->zeromap = kvzalloc(BITS_TO_LONGS(maxpages), GFP_KERNEL); > >>> but please check it carefully, I'm easily confused by such conversions. > >>> > >>> Hugh > >> Ah yes, didnt take into account 32-bit kernel. I think its supposed to be > >> > >> p->zeromap = kvzalloc(BITS_TO_LONGS(maxpages) * sizeof(unsigned long), > >> GFP_KERNEL); > > You can do something similar to bitmap_zalloc() and use: > > > > kvmalloc_array(BITS_TO_LONGS(nbits), sizeof(unsigned long), GFP_KERNEL > > | __GFP_ZERO) > > > > I don't see a kvzalloc_array() variant to use directly, but it should > > be trivial to add it. I can see other users of kvmalloc_array() that > > pass in __GFP_ZERO (e.g. fs/ntfs3/bitmap.c). > > > > , or you could take it a step further and add bitmap_kvzalloc(), > > assuming the maintainers are open to that. > > Thanks! bitmap_kvzalloc makes most sense to me. It doesnt make sense > that bitmap should only be limited to MAX_PAGE_ORDER size. I can add > this patch below at the start of the series and use it in the patch for > zeropage swap optimization. > > > bitmap: add support for virtually contiguous bitmap > > The current bitmap_zalloc API limits the allocation to MAX_PAGE_ORDER, > which prevents larger order bitmap allocations. Introduce > bitmap_kvzalloc that will allow larger allocations of bitmap. > kvmalloc_array still attempts to allocate physically contiguous memory, > but upon failure, falls back to non-contiguous (vmalloc) allocation. > > Suggested-by: Yosry Ahmed <yosryahmed@xxxxxxxxxx> > Signed-off-by: Usama Arif <usamaarif642@xxxxxxxxx> > LGTM with a small fix below. > diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h > index 8c4768c44a01..881c2ff2e834 100644 > --- a/include/linux/bitmap.h > +++ b/include/linux/bitmap.h > @@ -131,9 +131,11 @@ struct device; > */ > unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags); > unsigned long *bitmap_zalloc(unsigned int nbits, gfp_t flags); > +unsigned long *bitmap_kvzalloc(unsigned int nbits, gfp_t flags); > unsigned long *bitmap_alloc_node(unsigned int nbits, gfp_t flags, int > node); > unsigned long *bitmap_zalloc_node(unsigned int nbits, gfp_t flags, int > node); > void bitmap_free(const unsigned long *bitmap); > +void bitmap_kvfree(const unsigned long *bitmap); > > DEFINE_FREE(bitmap, unsigned long *, if (_T) bitmap_free(_T)) > > diff --git a/lib/bitmap.c b/lib/bitmap.c > index b97692854966..eabbfb85fb45 100644 > --- a/lib/bitmap.c > +++ b/lib/bitmap.c > @@ -727,6 +727,13 @@ unsigned long *bitmap_zalloc(unsigned int nbits, > gfp_t flags) > } > EXPORT_SYMBOL(bitmap_zalloc); > > +unsigned long *bitmap_kvzalloc(unsigned int nbits, gfp_t flags) > +{ > + return kvmalloc_array(BITS_TO_LONGS(nbits), sizeof(unsigned long), > + flags | __GFP_ZERO); > +} > +EXPORT_SYMBOL(bitmap_zalloc); EXPORT_SYMBOL(bitmap_kvzalloc)*