On Thu, Jun 18, 2020 at 11:37:51AM -0700, Matthew Wilcox wrote: > On Thu, Jun 18, 2020 at 08:23:33PM +0200, Uladzislau Rezki wrote: > > > +void vfree_bulk(size_t count, void **addrs) > > > +{ > > > + unsigned int i; > > > + > > > + BUG_ON(in_nmi()); > > > + might_sleep_if(!in_interrupt()); > > > + > > > + for (i = 0; i < count; i++) { > > > + void *addr = addrs[i]; > > > + kmemleak_free(addr); > > > + if (addr) > > > + __vfree(addr); > > > + } > > > +} > > > +EXPORT_SYMBOL(vfree_bulk); > > > + > > > > > Can we just do addrs[i] all over the loop? > > > > Also, we can just call vfree() instead that has all checking we > > need: NMI, kmemleak, might_sleep. > > Of course we _can_. But would we want to? This way, we only do these > checks once instead of once per pointer, which is rather the point > of batching. > Ahh, right. I briefly looked at it and missed that point. Right you are we do not want the vfree() here! > > I might actually go further and hoist the in_interrupt() check into > this function ... > Why do you need it? Just to inline below code: <snip> if (unlikely(in_interrupt())) __vfree_deferred(addr); else __vunmap(addr, 1); <snip> and bypass the __vfree() call(that is not marked as inline one)? I mean to inline above into vfree_bulk(). > > I suspect the RCU code always runs in_interrupt() > and so we always call vfree_deferred(). > No. We release the memory from workqueue context. -- Vlad Rezki