Re: [External] Re: [PATCH v4 05/21] mm/hugetlb: Introduce pgtable allocation/freeing helpers

From: Mike Kravetz
Date: Thu Nov 19 2020 - 18:24:32 EST


On 11/18/20 10:17 PM, Muchun Song wrote:
> On Tue, Nov 17, 2020 at 11:06 PM Oscar Salvador <osalvador@xxxxxxx> wrote:
>>
>> On Fri, Nov 13, 2020 at 06:59:36PM +0800, Muchun Song wrote:
>>> +#define page_huge_pte(page) ((page)->pmd_huge_pte)
>>
>> Seems you do not need this one anymore.
>>
>>> +void vmemmap_pgtable_free(struct page *page)
>>> +{
>>> + struct page *pte_page, *t_page;
>>> +
>>> + list_for_each_entry_safe(pte_page, t_page, &page->lru, lru) {
>>> + list_del(&pte_page->lru);
>>> + pte_free_kernel(&init_mm, page_to_virt(pte_page));
>>> + }
>>> +}
>>> +
>>> +int vmemmap_pgtable_prealloc(struct hstate *h, struct page *page)
>>> +{
>>> + unsigned int nr = pgtable_pages_to_prealloc_per_hpage(h);
>>> +
>>> + /* Store preallocated pages on huge page lru list */
>>> + INIT_LIST_HEAD(&page->lru);
>>> +
>>> + while (nr--) {
>>> + pte_t *pte_p;
>>> +
>>> + pte_p = pte_alloc_one_kernel(&init_mm);
>>> + if (!pte_p)
>>> + goto out;
>>> + list_add(&virt_to_page(pte_p)->lru, &page->lru);
>>> + }
>>
>> Definetely this looks better and easier to handle.
>> Btw, did you explore Matthew's hint about instead of allocating a new page,
>> using one of the ones you are going to free to store the ptes?
>> I am not sure whether it is feasible at all though.
>
> Hi Oscar and Matthew,
>
> I have started an investigation about this. Finally, I think that it
> may not be feasible. If we use a vmemmap page frame as a
> page table when we split the PMD table firstly, in this stage,
> we need to set 512 pte entry to the vmemmap page frame. If
> someone reads the tail struct page struct of the HugeTLB,
> it can get the arbitrary value (I am not sure it actually exists,
> maybe the memory compaction module can do this). So on
> the safe side, I think that allocating a new page is a good
> choice.

Thanks for looking into this.

If I understand correctly, the issue is that you need the pte page to set
up the new mappings. In your current code, this is done before removing
the pages of struct pages. This keeps everything 'consistent' as things
are remapped.

If you want to use one of the 'pages of struct pages' for the new pte
page, then there will be a period of time when things are inconsistent.
Before setting up the mapping, some code could potentially access that
pages of struct pages.

I tend to agree that allocating allocating a new page is the safest thing
to do here. Or, perhaps someone can think of a way make this safe.
--
Mike Kravetz