All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roman Gushchin <guro@fb.com>
To: "Tobin C. Harding" <tobin@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Christoph Lameter <cl@linux.com>,
	Pekka Enberg <penberg@kernel.org>,
	David Rientjes <rientjes@google.com>,
	Joonsoo Kim <iamjoonsoo.kim@lge.com>,
	Matthew Wilcox <willy@infradead.org>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v5 2/7] slob: Respect list_head abstraction layer
Date: Wed, 3 Apr 2019 18:00:30 +0000	[thread overview]
Message-ID: <20190403180026.GC6778@tower.DHCP.thefacebook.com> (raw)
In-Reply-To: <20190402230545.2929-3-tobin@kernel.org>

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@kernel.org>
> ---
>  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".

Thanks!

>  {
>  	slob_t *prev, *cur, *aligned = NULL;
>  	int delta = 0, units = SLOB_UNITS(size);
>  
> +	*page_removed_from_list = false;
>  	for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) {
>  		slobidx_t avail = slob_units(cur);
>  
> @@ -254,8 +267,10 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align)
>  			}
>  
>  			sp->units -= units;
> -			if (!sp->units)
> +			if (!sp->units) {
>  				clear_slob_page_free(sp);
> +				*page_removed_from_list = true;
> +			}
>  			return cur;
>  		}
>  		if (slob_last(cur))
> @@ -269,10 +284,10 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align)
>  static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
>  {
>  	struct page *sp;
> -	struct list_head *prev;
>  	struct list_head *slob_list;
>  	slob_t *b = NULL;
>  	unsigned long flags;
> +	bool _unused;
>  
>  	if (size < SLOB_BREAK1)
>  		slob_list = &free_slob_small;
> @@ -284,6 +299,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
>  	spin_lock_irqsave(&slob_lock, flags);
>  	/* Iterate through each partially free page, try to find room */
>  	list_for_each_entry(sp, slob_list, lru) {
> +		bool page_removed_from_list = false;
>  #ifdef CONFIG_NUMA
>  		/*
>  		 * If there's a node specification, search for a partial
> @@ -296,18 +312,25 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
>  		if (sp->units < SLOB_UNITS(size))
>  			continue;
>  
> -		/* Attempt to alloc */
> -		prev = sp->lru.prev;
> -		b = slob_page_alloc(sp, size, align);
> +		b = slob_page_alloc(sp, size, align, &page_removed_from_list);
>  		if (!b)
>  			continue;
>  
> -		/* Improve fragment distribution and reduce our average
> -		 * search time by starting our next search here. (see
> -		 * Knuth vol 1, sec 2.5, pg 449) */
> -		if (prev != slob_list->prev &&
> -				slob_list->next != prev->next)
> -			list_move_tail(slob_list, prev->next);
> +		/*
> +		 * If slob_page_alloc() removed sp from the list then we
> +		 * cannot call list functions on sp.  If so allocation
> +		 * did not fragment the page anyway so optimisation is
> +		 * unnecessary.
> +		 */
> +		if (!page_removed_from_list) {
> +			/*
> +			 * Improve fragment distribution and reduce our average
> +			 * search time by starting our next search here. (see
> +			 * Knuth vol 1, sec 2.5, pg 449)
> +			 */
> +			if (!list_is_first(&sp->lru, slob_list))
> +				list_rotate_to_front(&sp->lru, slob_list);
> +		}
>  		break;
>  	}
>  	spin_unlock_irqrestore(&slob_lock, flags);
> @@ -326,7 +349,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
>  		INIT_LIST_HEAD(&sp->lru);
>  		set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
>  		set_slob_page_free(sp, slob_list);
> -		b = slob_page_alloc(sp, size, align);
> +		b = slob_page_alloc(sp, size, align, &_unused);
>  		BUG_ON(!b);
>  		spin_unlock_irqrestore(&slob_lock, flags);
>  	}
> -- 
> 2.21.0
> 

  parent reply	other threads:[~2019-04-03 18:00 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-02 23:05 [PATCH v5 0/7] mm: Use slab_list list_head instead of lru Tobin C. Harding
2019-04-02 23:05 ` [PATCH v5 1/7] list: Add function list_rotate_to_front() Tobin C. Harding
2019-04-03 15:46   ` Christopher Lameter
2019-04-03 15:46     ` Christopher Lameter
2019-04-03 17:57   ` Roman Gushchin
2019-04-02 23:05 ` [PATCH v5 2/7] slob: Respect list_head abstraction layer Tobin C. Harding
2019-04-03 15:45   ` Christopher Lameter
2019-04-03 15:45     ` Christopher Lameter
2019-04-03 18:00   ` Roman Gushchin [this message]
2019-04-03 21:03     ` Tobin C. Harding
2019-04-03 21:23       ` Roman Gushchin
2019-04-03 22:14         ` Tobin C. Harding
2019-04-03 21:13     ` Tobin C. Harding
2019-04-09 12:59       ` Vlastimil Babka
2019-04-09 20:06         ` Tobin C. Harding
2019-04-09 22:25           ` Andrew Morton
2019-04-02 23:05 ` [PATCH v5 3/7] slob: Use slab_list instead of lru Tobin C. Harding
2019-04-03 15:47   ` Christopher Lameter
2019-04-03 15:47     ` Christopher Lameter
2019-04-02 23:05 ` [PATCH v5 4/7] slub: Add comments to endif pre-processor macros Tobin C. Harding
2019-04-03 18:42   ` Roman Gushchin
2019-04-02 23:05 ` [PATCH v5 5/7] slub: Use slab_list instead of lru Tobin C. Harding
2019-04-03 18:43   ` Roman Gushchin
2019-04-02 23:05 ` [PATCH v5 6/7] slab: " Tobin C. Harding
2019-04-03 15:48   ` Christopher Lameter
2019-04-03 15:48     ` Christopher Lameter
2019-04-03 18:44   ` Roman Gushchin
2019-04-02 23:05 ` [PATCH v5 7/7] mm: Remove stale comment from page struct Tobin C. Harding
2019-04-03 18:45   ` Roman Gushchin
2019-04-09 13:07 ` [PATCH v5 0/7] mm: Use slab_list list_head instead of lru Vlastimil Babka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190403180026.GC6778@tower.DHCP.thefacebook.com \
    --to=guro@fb.com \
    --cc=akpm@linux-foundation.org \
    --cc=cl@linux.com \
    --cc=iamjoonsoo.kim@lge.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=penberg@kernel.org \
    --cc=rientjes@google.com \
    --cc=tobin@kernel.org \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.