[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <d8d65544-1844-b4c3-f246-27572ab6dee2@linux.vnet.ibm.com>
Date: Wed, 28 Mar 2018 19:58:59 +0200
From: Laurent Dufour <ldufour@...ux.vnet.ibm.com>
To: David Rientjes <rientjes@...gle.com>
Cc: paulmck@...ux.vnet.ibm.com, peterz@...radead.org,
akpm@...ux-foundation.org, kirill@...temov.name,
ak@...ux.intel.com, mhocko@...nel.org, dave@...olabs.net,
jack@...e.cz, Matthew Wilcox <willy@...radead.org>,
benh@...nel.crashing.org, mpe@...erman.id.au, paulus@...ba.org,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>, hpa@...or.com,
Will Deacon <will.deacon@....com>,
Sergey Senozhatsky <sergey.senozhatsky@...il.com>,
Andrea Arcangeli <aarcange@...hat.com>,
Alexei Starovoitov <alexei.starovoitov@...il.com>,
kemi.wang@...el.com, sergey.senozhatsky.work@...il.com,
Daniel Jordan <daniel.m.jordan@...cle.com>,
linux-kernel@...r.kernel.org, linux-mm@...ck.org,
haren@...ux.vnet.ibm.com, khandual@...ux.vnet.ibm.com,
npiggin@...il.com, bsingharora@...il.com,
Tim Chen <tim.c.chen@...ux.intel.com>,
linuxppc-dev@...ts.ozlabs.org, x86@...nel.org
Subject: Re: [PATCH v9 07/24] mm: VMA sequence count
On 27/03/2018 23:30, David Rientjes wrote:
> On Tue, 13 Mar 2018, Laurent Dufour wrote:
>
>> diff --git a/mm/mmap.c b/mm/mmap.c
>> index faf85699f1a1..5898255d0aeb 100644
>> --- a/mm/mmap.c
>> +++ b/mm/mmap.c
>> @@ -558,6 +558,10 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
>> else
>> mm->highest_vm_end = vm_end_gap(vma);
>>
>> +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
>> + seqcount_init(&vma->vm_sequence);
>> +#endif
>> +
>> /*
>> * vma->vm_prev wasn't known when we followed the rbtree to find the
>> * correct insertion point for that vma. As a result, we could not
>> @@ -692,6 +696,30 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
>> long adjust_next = 0;
>> int remove_next = 0;
>>
>> + /*
>> + * Why using vm_raw_write*() functions here to avoid lockdep's warning ?
>> + *
>> + * Locked is complaining about a theoretical lock dependency, involving
>> + * 3 locks:
>> + * mapping->i_mmap_rwsem --> vma->vm_sequence --> fs_reclaim
>> + *
>> + * Here are the major path leading to this dependency :
>> + * 1. __vma_adjust() mmap_sem -> vm_sequence -> i_mmap_rwsem
>> + * 2. move_vmap() mmap_sem -> vm_sequence -> fs_reclaim
>> + * 3. __alloc_pages_nodemask() fs_reclaim -> i_mmap_rwsem
>> + * 4. unmap_mapping_range() i_mmap_rwsem -> vm_sequence
>> + *
>> + * So there is no way to solve this easily, especially because in
>> + * unmap_mapping_range() the i_mmap_rwsem is grab while the impacted
>> + * VMAs are not yet known.
>> + * However, the way the vm_seq is used is guarantying that we will
>> + * never block on it since we just check for its value and never wait
>> + * for it to move, see vma_has_changed() and handle_speculative_fault().
>> + */
>> + vm_raw_write_begin(vma);
>> + if (next)
>> + vm_raw_write_begin(next);
>> +
>> if (next && !insert) {
>> struct vm_area_struct *exporter = NULL, *importer = NULL;
>>
>
> Eek, what about later on:
>
> /*
> * Easily overlooked: when mprotect shifts the boundary,
> * make sure the expanding vma has anon_vma set if the
> * shrinking vma had, to cover any anon pages imported.
> */
> if (exporter && exporter->anon_vma && !importer->anon_vma) {
> int error;
>
> importer->anon_vma = exporter->anon_vma;
> error = anon_vma_clone(importer, exporter);
> if (error)
> return error;
> }
>
> This needs
>
> if (error) {
> if (next && next != vma)
> vm_raw_write_end(next);
> vm_raw_write_end(vma);
> return error;
> }
Nice catch !
Thanks,
Laurent.
Powered by blists - more mailing lists