On Thu, Apr 04, 2019 at 08:03:27AM +1100, Tobin C. Harding wrote: > On Wed, Apr 03, 2019 at 06:00:30PM +0000, Roman Gushchin wrote: > > On Wed, Apr 03, 2019 at 10:05:40AM +1100, Tobin C. Harding wrote: > > > Currently we reach inside the list_head. This is a violation of the > > > layer of abstraction provided by the list_head. It makes the code > > > fragile. More importantly it makes the code wicked hard to understand. > > > > > > The code reaches into the list_head structure to counteract the fact > > > that the list _may_ have been changed during slob_page_alloc(). Instead > > > of this we can add a return parameter to slob_page_alloc() to signal > > > that the list was modified (list_del() called with page->lru to remove > > > page from the freelist). > > > > > > This code is concerned with an optimisation that counters the tendency > > > for first fit allocation algorithm to fragment memory into many small > > > chunks at the front of the memory pool. Since the page is only removed > > > from the list when an allocation uses _all_ the remaining memory in the > > > page then in this special case fragmentation does not occur and we > > > therefore do not need the optimisation. > > > > > > Add a return parameter to slob_page_alloc() to signal that the > > > allocation used up the whole page and that the page was removed from the > > > free list. After calling slob_page_alloc() check the return value just > > > added and only attempt optimisation if the page is still on the list. > > > > > > Use list_head API instead of reaching into the list_head structure to > > > check if sp is at the front of the list. > > > > > > Signed-off-by: Tobin C. Harding <tobin@xxxxxxxxxx> > > > --- > > > mm/slob.c | 51 +++++++++++++++++++++++++++++++++++++-------------- > > > 1 file changed, 37 insertions(+), 14 deletions(-) > > > > > > diff --git a/mm/slob.c b/mm/slob.c > > > index 307c2c9feb44..07356e9feaaa 100644 > > > --- a/mm/slob.c > > > +++ b/mm/slob.c > > > @@ -213,13 +213,26 @@ static void slob_free_pages(void *b, int order) > > > } > > > > > > /* > > > - * Allocate a slob block within a given slob_page sp. > > > + * slob_page_alloc() - Allocate a slob block within a given slob_page sp. > > > + * @sp: Page to look in. > > > + * @size: Size of the allocation. > > > + * @align: Allocation alignment. > > > + * @page_removed_from_list: Return parameter. > > > + * > > > + * Tries to find a chunk of memory at least @size bytes big within @page. > > > + * > > > + * Return: Pointer to memory if allocated, %NULL otherwise. If the > > > + * allocation fills up @page then the page is removed from the > > > + * freelist, in this case @page_removed_from_list will be set to > > > + * true (set to false otherwise). > > > */ > > > -static void *slob_page_alloc(struct page *sp, size_t size, int align) > > > +static void *slob_page_alloc(struct page *sp, size_t size, int align, > > > + bool *page_removed_from_list) > > > > Hi Tobin! > > > > Isn't it better to make slob_page_alloc() return a bool value? > > Then it's easier to ignore the returned value, no need to introduce "_unused". > > We need a pointer to the memory allocated also so AFAICS its either a > return parameter for the memory pointer or a return parameter to > indicate the boolean value? Open to any other ideas I'm missing. > > In a previous crack at this I used a double pointer to the page struct > then set that to null to indicate the boolean value. I think the > explicit boolean parameter is cleaner. Yeah, sorry, it's my fault. Please, ignore this comment. Bool* argument is perfectly fine here. Thanks!