[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2 2/9] mm: Place unscrubbed pages at the end of pagelist



>>> On 03.04.17 at 18:50, <boris.ostrovsky@xxxxxxxxxx> wrote:
> @@ -856,6 +874,7 @@ static int reserve_offlined_page(struct page_info *head)
>      int zone = page_to_zone(head), i, head_order = PFN_ORDER(head), count = 
> 0;
>      struct page_info *cur_head;
>      int cur_order;
> +    bool_t need_scrub = !!test_bit(_PGC_need_scrub, &head->count_info);

With our use of plain bool now there's no need for !! here anymore.

> @@ -897,8 +916,8 @@ static int reserve_offlined_page(struct page_info *head)
>              {
>              merge:
>                  /* We don't consider merging outside the head_order. */
> -                page_list_add_tail(cur_head, &heap(node, zone, cur_order));
>                  PFN_ORDER(cur_head) = cur_order;
> +                page_list_add_scrub(cur_head, node, zone, cur_order, 
> need_scrub);

With this re-arrangement, what's the point of also passing a
separate order argument to the function?

> @@ -933,6 +952,10 @@ static bool_t can_merge(struct page_info *buddy, 
> unsigned int node,
>           (phys_to_nid(page_to_maddr(buddy)) != node) )
>          return false;
>  
> +    if ( need_scrub !=
> +         !!test_bit(_PGC_need_scrub, &buddy->count_info) )
> +        return false;

I don't think leaving the tree in a state where larger order chunks
don't become available for allocation right away is going to be
acceptable. Hence with this issue being dealt with only in patch 7
as it seems, you should state clearly and visibly that (at least)
patches 2...7 should only be committed together.

> @@ -952,9 +977,10 @@ static struct page_info *merge_chunks(struct page_info 
> *pg, unsigned int node,
>          {
>              /* Merge with predecessor block? */
>              buddy = pg - mask;
> -            if ( !can_merge(buddy, node, order) )
> +            if ( !can_merge(buddy, node, order, need_scrub) )
>                  break;
>  
> +            pg->count_info &= ~PGC_need_scrub;
>              pg = buddy;
>              page_list_del(pg, &heap(node, zone, order));
>          }
> @@ -962,9 +988,10 @@ static struct page_info *merge_chunks(struct page_info 
> *pg, unsigned int node,
>          {
>              /* Merge with successor block? */
>              buddy = pg + mask;
> -            if ( !can_merge(buddy, node, order) )
> +            if ( !can_merge(buddy, node, order, need_scrub) )
>                  break;
>  
> +            buddy->count_info &= ~PGC_need_scrub;
>              page_list_del(buddy, &heap(node, zone, order));
>          }

For both of these, how come you can / want to clear the need-scrub
flag? Wouldn't it be better for each individual page to retain it, so
when encountering a higher-order one you know which pages need
scrubbing and which don't? Couldn't that also be used to avoid
suppressing their merging here right away?

> +static void scrub_free_pages(unsigned int node)
> +{
> +    struct page_info *pg;
> +    unsigned int i, zone;
> +    int order;

There are no negative orders.

> +    ASSERT(spin_is_locked(&heap_lock));
> +
> +    if ( !node_need_scrub[node] )
> +        return;
> +
> +    for ( zone = 0; zone < NR_ZONES; zone++ )
> +    {
> +        for ( order = MAX_ORDER; order >= 0; order-- )
> +        {
> +            while ( !page_list_empty(&heap(node, zone, order)) )
> +            {
> +                /* Unscrubbed pages are always at the end of the list. */
> +                pg = page_list_last(&heap(node, zone, order));
> +                if ( !test_bit(_PGC_need_scrub, &pg->count_info) )
> +                    break;
> +
> +                for ( i = 0; i < (1UL << order); i++)

Types of loop variable and upper bound do not match.

> +                    scrub_one_page(&pg[i]);
> +
> +                pg->count_info &= ~PGC_need_scrub;
> +
> +                page_list_del(pg, &heap(node, zone, order));
> +                (void)merge_chunks(pg, node, zone, order);

Pointless cast.

> +                node_need_scrub[node] -= (1UL << order);

Perhaps worth returning right away if the new value is zero?

> +            }
> +        }
> +    }
> + }
> +
> +

Stray double blank lines

> @@ -1253,7 +1326,7 @@ unsigned int online_page(unsigned long mfn, uint32_t 
> *status)
>      spin_unlock(&heap_lock);
>  
>      if ( (y & PGC_state) == PGC_state_offlined )
> -        free_heap_pages(pg, 0);
> +        free_heap_pages(pg, 0, 0);

false (also elsewhere, and similarly when passing true)

> --- a/xen/include/asm-x86/mm.h
> +++ b/xen/include/asm-x86/mm.h
> @@ -233,6 +233,10 @@ struct page_info
>  #define PGC_count_width   PG_shift(9)
>  #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
>  
> +/* Page needs to be scrubbed */
> +#define _PGC_need_scrub   PG_shift(10)
> +#define PGC_need_scrub    PG_mask(1, 10)

So why not a new PGC_state_dirty instead of this independent
flag? Pages other than PGC_state_free should never make it
to the scrubber, so the flag is meaningless for all other
PGC_state_*.

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.