[Devel] [PATCH] tcache: Repeat invalidation in tcache_invalidate_node_pages()

Kirill Tkhai ktkhai at virtuozzo.com
Thu Nov 30 19:22:06 MSK 2017


tcache_shrink_scan()                                   tcache_destroy_pool
   tcache_lru_isolate()                                
      tcache_grab_pool()
      ...
      page_cache_get_speculative() -->cnt == 2

      ...
      tcache_put_pool() --> pool cnt zero
      ...                                                  wait_for_completion(&pool->completion);
   tcache_reclaim_pages                                    tcache_invalidate_node_pages()
      __tcache_reclaim_page()                                  tcache_lookup()
                                                                  page_cache_get_speculative  --> cnt == 3
                                                               __tcache_page_tree_delete
        page_ref_freeze(2) -->fail                                page_ref_freeze(2) -->fail


On 30.11.2017 19:02, Kirill Tkhai wrote:
> When there are more than 2 users of a page,  __tcache_page_tree_delete()
> fails to freeze it. We skip it and never try to freeze the page again.
> 
> In this case the page remains not invalidated, and tcache_node->nr_pages
> never decremented. Later, we catch WARN_ON() reporting about this.
> 
> The patch fixes the problem. In case of we failed to invalidate a page,
> we remember that, and return to such pages after others are invalidated.
> 
> https://jira.sw.ru/browse/PSBM-78354
> 
> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
>  mm/tcache.c |   13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/mm/tcache.c b/mm/tcache.c
> index d1a2c53e11a..cbc50d4b8bc 100644
> --- a/mm/tcache.c
> +++ b/mm/tcache.c
> @@ -903,13 +903,15 @@ tcache_invalidate_node_pages(struct tcache_node *node)
>  	struct page *pages[TCACHE_PAGEVEC_SIZE];
>  	pgoff_t index = 0;
>  	unsigned nr_pages;
> +	bool repeat;
>  	int i;
>  
>  	/*
>  	 * First forbid new page insertions - see tcache_page_tree_replace.
>  	 */
>  	node->invalidated = true;
> -
> +again:
> +	repeat = false;
>  	while ((nr_pages = tcache_lookup(pages, node, index,
>  						TCACHE_PAGEVEC_SIZE, indices))) {
>  		for (i = 0; i < nr_pages; i++) {
> @@ -925,13 +927,20 @@ tcache_invalidate_node_pages(struct tcache_node *node)
>  				tcache_lru_del(node->pool, page, false);
>  				local_irq_enable();
>  				tcache_put_page(page);
> -			} else
> +			} else {
>  				local_irq_enable();
> +				repeat = true;
> +			}
>  		}
>  		cond_resched();
>  		index++;
>  	}
>  
> +	if (repeat) {
> +		index = 0;
> +		goto again;
> +	}
> +
>  	WARN_ON(node->nr_pages != 0);
>  }
>  
> 


More information about the Devel mailing list