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

Re: [PATCH v2 1/1] mm: fix folio_pte_batch() on XEN PV



On Fri,  2 May 2025 23:50:19 +0200 Petr Vaněk <arkamar@xxxxxxxx> wrote:

> On XEN PV, folio_pte_batch() can incorrectly batch beyond the end of a
> folio due to a corner case in pte_advance_pfn(). Specifically, when the
> PFN following the folio maps to an invalidated MFN,
> 
>       expected_pte = pte_advance_pfn(expected_pte, nr);
> 
> produces a pte_none(). If the actual next PTE in memory is also
> pte_none(), the pte_same() succeeds,
> 
>       if (!pte_same(pte, expected_pte))
>               break;
> 
> the loop is not broken, and batching continues into unrelated memory.
> 
> ...

Looks OK for now I guess but it looks like we should pay some attention
to what types we're using.

> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -248,11 +248,9 @@ static inline int folio_pte_batch(struct folio *folio, 
> unsigned long addr,
>               pte_t *start_ptep, pte_t pte, int max_nr, fpb_t flags,
>               bool *any_writable, bool *any_young, bool *any_dirty)
>  {
> -     unsigned long folio_end_pfn = folio_pfn(folio) + folio_nr_pages(folio);
> -     const pte_t *end_ptep = start_ptep + max_nr;
>       pte_t expected_pte, *ptep;
>       bool writable, young, dirty;
> -     int nr;
> +     int nr, cur_nr;
>  
>       if (any_writable)
>               *any_writable = false;
> @@ -265,11 +263,15 @@ static inline int folio_pte_batch(struct folio *folio, 
> unsigned long addr,
>       VM_WARN_ON_FOLIO(!folio_test_large(folio) || max_nr < 1, folio);
>       VM_WARN_ON_FOLIO(page_folio(pfn_to_page(pte_pfn(pte))) != folio, folio);
>  
> +     /* Limit max_nr to the actual remaining PFNs in the folio we could 
> batch. */
> +     max_nr = min_t(unsigned long, max_nr,
> +                    folio_pfn(folio) + folio_nr_pages(folio) - pte_pfn(pte));
> +

Methinks max_nr really wants to be unsigned long.  That will permit the
cleanup of quite a bit of truncation, extension, signedness conversion
and general type chaos in folio_pte_batch()'s various callers.

And...

Why does folio_nr_pages() return a signed quantity?  It's a count.

And why the heck is folio_pte_batch() inlined?  It's larger then my
first hard disk and it has five callsites!




 


Rackspace

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