[Devel] [PATCH rh7 4/9] tcache: Make tcache_lru_isolate() keep ni->lock less

Andrey Ryabinin aryabinin at virtuozzo.com
Tue Aug 15 16:01:38 MSK 2017


On 08/15/2017 02:23 PM, Kirill Tkhai wrote:
> Grab pool using RCU technics, and do not use ni->lock.
> This refactors the function and will be used in further.
> 
> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
>  mm/tcache.c |   36 ++++++++++++++++++++++++++++--------
>  1 file changed, 28 insertions(+), 8 deletions(-)
> 
> diff --git a/mm/tcache.c b/mm/tcache.c
> index f2a9f439afb..cecaf02b365 100644
> --- a/mm/tcache.c
> +++ b/mm/tcache.c
> @@ -1031,31 +1031,51 @@ tcache_lru_isolate(int nid, struct page **pages, int nr_to_isolate)
>  	int nr, nr_isolated = 0;
>  	struct rb_node *rbn;
>  
> -	spin_lock_irq(&ni->lock);
> +	rcu_read_lock();

I don't get this. RCU lock can't protect from concurrent rb_erase(),
how is this supposed to work?

>  again:
>  	rbn = rb_first(&ni->reclaim_tree);
> -	if (!rbn)
> +	if (!rbn) {
> +		rcu_read_unlock();
>  		goto out;
> -
> -	rb_erase(rbn, &ni->reclaim_tree);
> -	RB_CLEAR_NODE(rbn);
> +	}
>  
>  	pni = rb_entry(rbn, struct tcache_pool_nodeinfo, reclaim_node);
> -	if (!tcache_grab_pool(pni->pool))
> +	if (!tcache_grab_pool(pni->pool)) {
> +		spin_lock_irq(&ni->lock);
> +		if (!RB_EMPTY_NODE(rbn) && list_empty(&pni->lru)) {
> +			rb_erase(rbn, &ni->reclaim_tree);
> +			RB_CLEAR_NODE(rbn);
> +		}
> +		spin_unlock_irq(&ni->lock);
>  		goto again;
> +	}
> +	rcu_read_unlock();
>  
> +	spin_lock_irq(&ni->lock);
>  	spin_lock(&pni->lock);
>  	nr = __tcache_lru_isolate(pni, pages, nr_to_isolate);
> -	ni->nr_pages -= nr;
>  	nr_isolated += nr;
>  
> +	if (!nr) {
> +		spin_unlock(&pni->lock);
> +		spin_unlock_irq(&ni->lock);
> +		goto out_put;
> +	}
> +
> +	ni->nr_pages -= nr;
> +
> +	if (!RB_EMPTY_NODE(rbn)) {
> +		rb_erase(rbn, &ni->reclaim_tree);
> +		RB_CLEAR_NODE(rbn);
> +	}
>  	if (!list_empty(&pni->lru))
>  		__tcache_insert_reclaim_node(ni, pni);
>  
>  	spin_unlock(&pni->lock);
> +	spin_unlock_irq(&ni->lock);
> +out_put:
>  	tcache_put_pool(pni->pool);
>  out:
> -	spin_unlock_irq(&ni->lock);
>  	return nr_isolated;
>  }
>  
> 


More information about the Devel mailing list