Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1720719 > unrolled thread
| Started by | "Kirill A. Shutemov" <kirill@shutemov.name> |
|---|---|
| First post | 2017-08-27 02:20 +0200 |
| Last post | 2017-08-30 11:00 +0200 |
| Articles | 20 on this page of 22 — 6 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure "Kirill A. Shutemov" <kirill@shutemov.name> - 2017-08-27 02:20 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-28 11:40 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Benjamin Herrenschmidt <benh@kernel.crashing.org> - 2017-08-28 23:30 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Andi Kleen <ak@linux.intel.com> - 2017-08-29 00:40 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-29 10:20 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-29 10:40 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-29 13:30 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Benjamin Herrenschmidt <benh@kernel.crashing.org> - 2017-08-30 00:00 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-30 08:20 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Laurent Dufour <ldufour@linux.vnet.ibm.com> - 2017-08-29 10:00 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-29 14:10 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Laurent Dufour <ldufour@linux.vnet.ibm.com> - 2017-08-29 15:20 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-29 15:50 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Anshuman Khandual <khandual@linux.vnet.ibm.com> - 2017-08-30 07:10 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-30 08:00 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Laurent Dufour <ldufour@linux.vnet.ibm.com> - 2017-08-30 11:40 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Anshuman Khandual <khandual@linux.vnet.ibm.com> - 2017-08-31 09:00 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Peter Zijlstra <peterz@infradead.org> - 2017-08-31 09:40 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Laurent Dufour <ldufour@linux.vnet.ibm.com> - 2017-08-30 12:00 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Anshuman Khandual <khandual@linux.vnet.ibm.com> - 2017-08-30 05:50 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Anshuman Khandual <khandual@linux.vnet.ibm.com> - 2017-08-30 07:30 +0200
Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure Laurent Dufour <ldufour@linux.vnet.ibm.com> - 2017-08-30 11:00 +0200
Page 1 of 2 [1] 2 Next page →
| From | "Kirill A. Shutemov" <kirill@shutemov.name> |
|---|---|
| Date | 2017-08-27 02:20 +0200 |
| Subject | Re: [PATCH v2 14/20] mm: Provide speculative fault infrastructure |
| Message-ID | <uiTsZ-8fp-1@gated-at.bofh.it> |
On Fri, Aug 18, 2017 at 12:05:13AM +0200, Laurent Dufour wrote:
> +/*
> + * vm_normal_page() adds some processing which should be done while
> + * hodling the mmap_sem.
> + */
> +int handle_speculative_fault(struct mm_struct *mm, unsigned long address,
> + unsigned int flags)
> +{
> + struct vm_fault vmf = {
> + .address = address,
> + };
> + pgd_t *pgd;
> + p4d_t *p4d;
> + pud_t *pud;
> + pmd_t *pmd;
> + int dead, seq, idx, ret = VM_FAULT_RETRY;
> + struct vm_area_struct *vma;
> + struct mempolicy *pol;
> +
> + /* Clear flags that may lead to release the mmap_sem to retry */
> + flags &= ~(FAULT_FLAG_ALLOW_RETRY|FAULT_FLAG_KILLABLE);
> + flags |= FAULT_FLAG_SPECULATIVE;
> +
> + idx = srcu_read_lock(&vma_srcu);
> + vma = find_vma_srcu(mm, address);
> + if (!vma)
> + goto unlock;
> +
> + /*
> + * Validate the VMA found by the lockless lookup.
> + */
> + dead = RB_EMPTY_NODE(&vma->vm_rb);
> + seq = raw_read_seqcount(&vma->vm_sequence); /* rmb <-> seqlock,vma_rb_erase() */
> + if ((seq & 1) || dead)
> + goto unlock;
> +
> + /*
> + * Can't call vm_ops service has we don't know what they would do
> + * with the VMA.
> + * This include huge page from hugetlbfs.
> + */
> + if (vma->vm_ops)
> + goto unlock;
I think we need to have a way to white-list safe ->vm_ops.
> +
> + if (unlikely(!vma->anon_vma))
> + goto unlock;
It deserves a comment.
> +
> + vmf.vma_flags = READ_ONCE(vma->vm_flags);
> + vmf.vma_page_prot = READ_ONCE(vma->vm_page_prot);
> +
> + /* Can't call userland page fault handler in the speculative path */
> + if (unlikely(vmf.vma_flags & VM_UFFD_MISSING))
> + goto unlock;
> +
> + /*
> + * MPOL_INTERLEAVE implies additional check in mpol_misplaced() which
> + * are not compatible with the speculative page fault processing.
> + */
> + pol = __get_vma_policy(vma, address);
> + if (!pol)
> + pol = get_task_policy(current);
> + if (pol && pol->mode == MPOL_INTERLEAVE)
> + goto unlock;
> +
> + if (vmf.vma_flags & VM_GROWSDOWN || vmf.vma_flags & VM_GROWSUP)
> + /*
> + * This could be detected by the check address against VMA's
> + * boundaries but we want to trace it as not supported instead
> + * of changed.
> + */
> + goto unlock;
> +
> + if (address < READ_ONCE(vma->vm_start)
> + || READ_ONCE(vma->vm_end) <= address)
> + goto unlock;
> +
> + /*
> + * The three following checks are copied from access_error from
> + * arch/x86/mm/fault.c
> + */
> + if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
> + flags & FAULT_FLAG_INSTRUCTION,
> + flags & FAULT_FLAG_REMOTE))
> + goto unlock;
> +
> + /* This is one is required to check that the VMA has write access set */
> + if (flags & FAULT_FLAG_WRITE) {
> + if (unlikely(!(vmf.vma_flags & VM_WRITE)))
> + goto unlock;
> + } else {
> + if (unlikely(!(vmf.vma_flags & (VM_READ | VM_EXEC | VM_WRITE))))
> + goto unlock;
> + }
> +
> + /*
> + * Do a speculative lookup of the PTE entry.
> + */
> + local_irq_disable();
> + pgd = pgd_offset(mm, address);
> + if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
> + goto out_walk;
> +
> + p4d = p4d_alloc(mm, pgd, address);
> + if (p4d_none(*p4d) || unlikely(p4d_bad(*p4d)))
> + goto out_walk;
> +
> + pud = pud_alloc(mm, p4d, address);
> + if (pud_none(*pud) || unlikely(pud_bad(*pud)))
> + goto out_walk;
> +
> + pmd = pmd_offset(pud, address);
> + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
> + goto out_walk;
> +
> + /*
> + * The above does not allocate/instantiate page-tables because doing so
> + * would lead to the possibility of instantiating page-tables after
> + * free_pgtables() -- and consequently leaking them.
> + *
> + * The result is that we take at least one !speculative fault per PMD
> + * in order to instantiate it.
> + */
Doing all this job and just give up because we cannot allocate page tables
looks very wasteful to me.
Have you considered to look how we can hand over from speculative to
non-speculative path without starting from scratch (when possible)?
> + /* Transparent huge pages are not supported. */
> + if (unlikely(pmd_trans_huge(*pmd)))
> + goto out_walk;
That's looks like a blocker to me.
Is there any problem with making it supported (besides plain coding)?
> +
> + vmf.vma = vma;
> + vmf.pmd = pmd;
> + vmf.pgoff = linear_page_index(vma, address);
> + vmf.gfp_mask = __get_fault_gfp_mask(vma);
> + vmf.sequence = seq;
> + vmf.flags = flags;
> +
> + local_irq_enable();
> +
> + /*
> + * We need to re-validate the VMA after checking the bounds, otherwise
> + * we might have a false positive on the bounds.
> + */
> + if (read_seqcount_retry(&vma->vm_sequence, seq))
> + goto unlock;
> +
> + ret = handle_pte_fault(&vmf);
> +
> +unlock:
> + srcu_read_unlock(&vma_srcu, idx);
> + return ret;
> +
> +out_walk:
> + local_irq_enable();
> + goto unlock;
> +}
> +#endif /* __HAVE_ARCH_CALL_SPF */
> +
> /*
> * By the time we get here, we already hold the mm semaphore
> *
> --
> 2.7.4
>
--
Kirill A. Shutemov
[toc] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-28 11:40 +0200 |
| Message-ID | <ujoGu-3Tj-25@gated-at.bofh.it> |
| In reply to | #1720719 |
On Sun, Aug 27, 2017 at 03:18:23AM +0300, Kirill A. Shutemov wrote:
> On Fri, Aug 18, 2017 at 12:05:13AM +0200, Laurent Dufour wrote:
> > + /*
> > + * Can't call vm_ops service has we don't know what they would do
> > + * with the VMA.
> > + * This include huge page from hugetlbfs.
> > + */
> > + if (vma->vm_ops)
> > + goto unlock;
>
> I think we need to have a way to white-list safe ->vm_ops.
Either that, or simply teach all ->fault() callbacks about speculative
faults. Shouldn't be too hard, just 'work'.
> > +
> > + if (unlikely(!vma->anon_vma))
> > + goto unlock;
>
> It deserves a comment.
Yes, that was very much not intended. It wrecks most of the fun. This
really _should_ work for file maps too.
> > + /*
> > + * Do a speculative lookup of the PTE entry.
> > + */
> > + local_irq_disable();
> > + pgd = pgd_offset(mm, address);
> > + if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
> > + goto out_walk;
> > +
> > + p4d = p4d_alloc(mm, pgd, address);
> > + if (p4d_none(*p4d) || unlikely(p4d_bad(*p4d)))
> > + goto out_walk;
> > +
> > + pud = pud_alloc(mm, p4d, address);
> > + if (pud_none(*pud) || unlikely(pud_bad(*pud)))
> > + goto out_walk;
> > +
> > + pmd = pmd_offset(pud, address);
> > + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
> > + goto out_walk;
> > +
> > + /*
> > + * The above does not allocate/instantiate page-tables because doing so
> > + * would lead to the possibility of instantiating page-tables after
> > + * free_pgtables() -- and consequently leaking them.
> > + *
> > + * The result is that we take at least one !speculative fault per PMD
> > + * in order to instantiate it.
> > + */
>
>
> Doing all this job and just give up because we cannot allocate page tables
> looks very wasteful to me.
>
> Have you considered to look how we can hand over from speculative to
> non-speculative path without starting from scratch (when possible)?
So we _can_ in fact allocate and install page-tables, but we have to be
very careful about it. The interesting case is where we race with
free_pgtables() and install a page that was just taken out.
But since we already have the VMA I think we can do something like:
if (p*g_none()) {
p*d_t *new = p*d_alloc_one(mm, address);
spin_lock(&mm->page_table_lock);
if (!vma_changed_or_dead(vma,seq)) {
if (p*d_none())
p*d_populate(mm, p*d, new);
else
p*d_free(new);
new = NULL;
}
spin_unlock(&mm->page_table_lock);
if (new) {
p*d_free(new);
goto out_walk;
}
}
I just never bothered with that, figured we ought to get the basics
working before trying to be clever.
> > + /* Transparent huge pages are not supported. */
> > + if (unlikely(pmd_trans_huge(*pmd)))
> > + goto out_walk;
>
> That's looks like a blocker to me.
>
> Is there any problem with making it supported (besides plain coding)?
Not that I can remember, but I never really looked at THP, I don't think
we even had that when I did the first versions.
[toc] | [prev] | [next] | [standalone]
| From | Benjamin Herrenschmidt <benh@kernel.crashing.org> |
|---|---|
| Date | 2017-08-28 23:30 +0200 |
| Message-ID | <ujzLA-2eP-17@gated-at.bofh.it> |
| In reply to | #1721437 |
On Mon, 2017-08-28 at 11:37 +0200, Peter Zijlstra wrote: > > Doing all this job and just give up because we cannot allocate page tables > > looks very wasteful to me. > > > > Have you considered to look how we can hand over from speculative to > > non-speculative path without starting from scratch (when possible)? > > So we _can_ in fact allocate and install page-tables, but we have to be > very careful about it. The interesting case is where we race with > free_pgtables() and install a page that was just taken out. > > But since we already have the VMA I think we can do something like: That makes me extremely nervous... there could be all sort of assumptions esp. in arch code about the fact that we never populate the tree without the mm sem. We'd have to audit archs closely. Things like the page walk cache flushing on power etc... I don't mind the "retry" .. .we've brought stuff in the L1 cache already which I would expect to be the bulk of the overhead, and the allocation case isn't that common. Do we have numbers to show how destrimental this is today ? Cheers, Ben.
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <ak@linux.intel.com> |
|---|---|
| Date | 2017-08-29 00:40 +0200 |
| Message-ID | <ujARj-2QC-13@gated-at.bofh.it> |
| In reply to | #1721975 |
> That makes me extremely nervous... there could be all sort of > assumptions esp. in arch code about the fact that we never populate the > tree without the mm sem. > > We'd have to audit archs closely. Things like the page walk cache > flushing on power etc... Yes the whole thing is quite risky. Probably will need some kind of per architecture opt-in scheme? -Andi
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-29 10:20 +0200 |
| Message-ID | <ujJUB-bY-7@gated-at.bofh.it> |
| In reply to | #1722034 |
On Mon, Aug 28, 2017 at 03:35:11PM -0700, Andi Kleen wrote: > Yes the whole thing is quite risky. Probably will need some > kind of per architecture opt-in scheme? See patch 19/20, that not enough for you?
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-29 10:40 +0200 |
| Message-ID | <ujKdY-i4-5@gated-at.bofh.it> |
| In reply to | #1721975 |
On Tue, Aug 29, 2017 at 07:14:37AM +1000, Benjamin Herrenschmidt wrote: > On Mon, 2017-08-28 at 11:37 +0200, Peter Zijlstra wrote: > > > Doing all this job and just give up because we cannot allocate page tables > > > looks very wasteful to me. > > > > > > Have you considered to look how we can hand over from speculative to > > > non-speculative path without starting from scratch (when possible)? > > > > So we _can_ in fact allocate and install page-tables, but we have to be > > very careful about it. The interesting case is where we race with > > free_pgtables() and install a page that was just taken out. > > > > But since we already have the VMA I think we can do something like: > > That makes me extremely nervous... there could be all sort of > assumptions esp. in arch code about the fact that we never populate the > tree without the mm sem. That _would_ be somewhat dodgy, because that means it needs to rely on taking mmap_sem for _writing_ to undo things and arch/powerpc/ doesn't have many down_write.*mmap_sem: $ git grep "down_write.*mmap_sem" arch/powerpc/ arch/powerpc/kernel/vdso.c: if (down_write_killable(&mm->mmap_sem)) arch/powerpc/kvm/book3s_64_vio.c: down_write(¤t->mm->mmap_sem); arch/powerpc/mm/mmu_context_iommu.c: down_write(&mm->mmap_sem); arch/powerpc/mm/subpage-prot.c: down_write(&mm->mmap_sem); arch/powerpc/mm/subpage-prot.c: down_write(&mm->mmap_sem); arch/powerpc/mm/subpage-prot.c: down_write(&mm->mmap_sem); Then again, I suppose it could be relying on the implicit down_write from things like munmap() and the like.. And things _ought_ to be ordered by the various PTLs (mm->page_table_lock and pmd->lock) which of course doesn't mean something accidentally snuck through. > We'd have to audit archs closely. Things like the page walk cache > flushing on power etc... If you point me where to look, I'll have a poke around. I'm not quite sure what you mean with pagewalk cache flushing. Your hash thing flushes everything inside the PTL IIRC and the radix code appears fairly 'normal'. > I don't mind the "retry" .. .we've brought stuff in the L1 cache > already which I would expect to be the bulk of the overhead, and the > allocation case isn't that common. Do we have numbers to show how > destrimental this is today ? No numbers, afaik. And like I said, I didn't consider this an actual problem when I did these patches. But since Kirill asked ;-)
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-29 13:30 +0200 |
| Message-ID | <ujMSu-1Zf-25@gated-at.bofh.it> |
| In reply to | #1722223 |
On Tue, Aug 29, 2017 at 10:33:52AM +0200, Peter Zijlstra wrote: > On Tue, Aug 29, 2017 at 07:14:37AM +1000, Benjamin Herrenschmidt wrote: > > We'd have to audit archs closely. Things like the page walk cache > > flushing on power etc... > > If you point me where to look, I'll have a poke around. I'm not > quite sure what you mean with pagewalk cache flushing. Your hash thing > flushes everything inside the PTL IIRC and the radix code appears fairly > 'normal'. mpe helped me out and explained that is the PWC hint to TBLIE. So, you set need_flush_all when you unhook pud/pmd/pte which you then use to set PWC. So free_pgtables() will do the PWC when it unhooks higher level pages. But you're right that there's some issues, free_pgtables() itself doesn't seem to use mm->page_table_lock,pmd->lock _AT_ALL_ to unhook the pages. If it were to do that, things should work fine since those locks would then serialize against the speculative faults, we would never install a page if the VMA would be under tear-down and it would thus not be visible to your caches either.
[toc] | [prev] | [next] | [standalone]
| From | Benjamin Herrenschmidt <benh@kernel.crashing.org> |
|---|---|
| Date | 2017-08-30 00:00 +0200 |
| Message-ID | <ujWIb-84B-47@gated-at.bofh.it> |
| In reply to | #1722368 |
On Tue, 2017-08-29 at 13:27 +0200, Peter Zijlstra wrote: > mpe helped me out and explained that is the PWC hint to TBLIE. > > So, you set need_flush_all when you unhook pud/pmd/pte which you then > use to set PWC. So free_pgtables() will do the PWC when it unhooks > higher level pages. > > But you're right that there's some issues, free_pgtables() itself > doesn't seem to use mm->page_table_lock,pmd->lock _AT_ALL_ to unhook the > pages. > > If it were to do that, things should work fine since those locks would > then serialize against the speculative faults, we would never install a > page if the VMA would be under tear-down and it would thus not be > visible to your caches either. That's one case. I don't remember of *all* the cases to be honest, but I do remember several times over the past few years thinking "ah we are fine because the mm sem taken for writing protects us from any concurrent tree structure change" :-) Cheers, Ben.
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-30 08:20 +0200 |
| Message-ID | <uk4w2-4Jz-15@gated-at.bofh.it> |
| In reply to | #1722884 |
On Wed, Aug 30, 2017 at 07:19:30AM +1000, Benjamin Herrenschmidt wrote: > On Tue, 2017-08-29 at 13:27 +0200, Peter Zijlstra wrote: > > mpe helped me out and explained that is the PWC hint to TBLIE. > > > > So, you set need_flush_all when you unhook pud/pmd/pte which you then > > use to set PWC. So free_pgtables() will do the PWC when it unhooks > > higher level pages. > > > > But you're right that there's some issues, free_pgtables() itself > > doesn't seem to use mm->page_table_lock,pmd->lock _AT_ALL_ to unhook the > > pages. > > > > If it were to do that, things should work fine since those locks would > > then serialize against the speculative faults, we would never install a > > page if the VMA would be under tear-down and it would thus not be > > visible to your caches either. > > That's one case. I don't remember of *all* the cases to be honest, but > I do remember several times over the past few years thinking "ah we are > fine because the mm sem taken for writing protects us from any > concurrent tree structure change" :-) Well, installing always seems to use the locks (it needs to, because its always done with down_read()), that only leaves removal, and the only place I know that removes stuff is free_pgtables(). But I think I found another fun place, copy_page_range(). While it (pointlessly) takes all the PTLs on the dst mm it walks the src page tables without any PTLs. This means that if we have a multi-threaded process doing fork() a thread of the src mm could instantiate page-tables that will not be copied over. Of course, this is highly dubious behaviour to begin with, and I don't think there's anything fundamentally wrong with missing those pages but we should document this stuff.
[toc] | [prev] | [next] | [standalone]
| From | Laurent Dufour <ldufour@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-08-29 10:00 +0200 |
| Message-ID | <ujJBg-8hK-9@gated-at.bofh.it> |
| In reply to | #1720719 |
On 27/08/2017 02:18, Kirill A. Shutemov wrote:
> On Fri, Aug 18, 2017 at 12:05:13AM +0200, Laurent Dufour wrote:
>> +/*
>> + * vm_normal_page() adds some processing which should be done while
>> + * hodling the mmap_sem.
>> + */
>> +int handle_speculative_fault(struct mm_struct *mm, unsigned long address,
>> + unsigned int flags)
>> +{
>> + struct vm_fault vmf = {
>> + .address = address,
>> + };
>> + pgd_t *pgd;
>> + p4d_t *p4d;
>> + pud_t *pud;
>> + pmd_t *pmd;
>> + int dead, seq, idx, ret = VM_FAULT_RETRY;
>> + struct vm_area_struct *vma;
>> + struct mempolicy *pol;
>> +
>> + /* Clear flags that may lead to release the mmap_sem to retry */
>> + flags &= ~(FAULT_FLAG_ALLOW_RETRY|FAULT_FLAG_KILLABLE);
>> + flags |= FAULT_FLAG_SPECULATIVE;
>> +
>> + idx = srcu_read_lock(&vma_srcu);
>> + vma = find_vma_srcu(mm, address);
>> + if (!vma)
>> + goto unlock;
>> +
>> + /*
>> + * Validate the VMA found by the lockless lookup.
>> + */
>> + dead = RB_EMPTY_NODE(&vma->vm_rb);
>> + seq = raw_read_seqcount(&vma->vm_sequence); /* rmb <-> seqlock,vma_rb_erase() */
>> + if ((seq & 1) || dead)
>> + goto unlock;
>> +
>> + /*
>> + * Can't call vm_ops service has we don't know what they would do
>> + * with the VMA.
>> + * This include huge page from hugetlbfs.
>> + */
>> + if (vma->vm_ops)
>> + goto unlock;
>
> I think we need to have a way to white-list safe ->vm_ops.
Hi Kirill,
Yes this would be a good optimization done in a next step.
>> +
>> + if (unlikely(!vma->anon_vma))
>> + goto unlock;
>
> It deserves a comment.
You're right I'll add it in the next version.
For the record, the root cause is that __anon_vma_prepare() requires the
mmap_sem to be held because vm_next and vm_prev must be safe.
>> +
>> + vmf.vma_flags = READ_ONCE(vma->vm_flags);
>> + vmf.vma_page_prot = READ_ONCE(vma->vm_page_prot);
>> +
>> + /* Can't call userland page fault handler in the speculative path */
>> + if (unlikely(vmf.vma_flags & VM_UFFD_MISSING))
>> + goto unlock;
>> +
>> + /*
>> + * MPOL_INTERLEAVE implies additional check in mpol_misplaced() which
>> + * are not compatible with the speculative page fault processing.
>> + */
>> + pol = __get_vma_policy(vma, address);
>> + if (!pol)
>> + pol = get_task_policy(current);
>> + if (pol && pol->mode == MPOL_INTERLEAVE)
>> + goto unlock;
>> +
>> + if (vmf.vma_flags & VM_GROWSDOWN || vmf.vma_flags & VM_GROWSUP)
>> + /*
>> + * This could be detected by the check address against VMA's
>> + * boundaries but we want to trace it as not supported instead
>> + * of changed.
>> + */
>> + goto unlock;
>> +
>> + if (address < READ_ONCE(vma->vm_start)
>> + || READ_ONCE(vma->vm_end) <= address)
>> + goto unlock;
>> +
>> + /*
>> + * The three following checks are copied from access_error from
>> + * arch/x86/mm/fault.c
>> + */
>> + if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
>> + flags & FAULT_FLAG_INSTRUCTION,
>> + flags & FAULT_FLAG_REMOTE))
>> + goto unlock;
>> +
>> + /* This is one is required to check that the VMA has write access set */
>> + if (flags & FAULT_FLAG_WRITE) {
>> + if (unlikely(!(vmf.vma_flags & VM_WRITE)))
>> + goto unlock;
>> + } else {
>> + if (unlikely(!(vmf.vma_flags & (VM_READ | VM_EXEC | VM_WRITE))))
>> + goto unlock;
>> + }
>> +
>> + /*
>> + * Do a speculative lookup of the PTE entry.
>> + */
>> + local_irq_disable();
>> + pgd = pgd_offset(mm, address);
>> + if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
>> + goto out_walk;
>> +
>> + p4d = p4d_alloc(mm, pgd, address);
>> + if (p4d_none(*p4d) || unlikely(p4d_bad(*p4d)))
>> + goto out_walk;
>> +
>> + pud = pud_alloc(mm, p4d, address);
>> + if (pud_none(*pud) || unlikely(pud_bad(*pud)))
>> + goto out_walk;
>> +
>> + pmd = pmd_offset(pud, address);
>> + if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
>> + goto out_walk;
>> +
>> + /*
>> + * The above does not allocate/instantiate page-tables because doing so
>> + * would lead to the possibility of instantiating page-tables after
>> + * free_pgtables() -- and consequently leaking them.
>> + *
>> + * The result is that we take at least one !speculative fault per PMD
>> + * in order to instantiate it.
>> + */
>
>
> Doing all this job and just give up because we cannot allocate page tables
> looks very wasteful to me.
>
> Have you considered to look how we can hand over from speculative to
> non-speculative path without starting from scratch (when possible)?
Not really, but as mentioned by Benjamin and Andy, this will require care
from the architecture code.
This may be a future optimization, but it will require guarantee from the
architecture code as well.
>> + /* Transparent huge pages are not supported. */
>> + if (unlikely(pmd_trans_huge(*pmd)))
>> + goto out_walk;
>
> That's looks like a blocker to me.
>
> Is there any problem with making it supported (besides plain coding)?
To be honest, I can't remember why I added such a check, may be for safety
reason, but I need to double check that again. I'll do so and come back
later with a statement.
Thanks,
Laurent.
>> +
>> + vmf.vma = vma;
>> + vmf.pmd = pmd;
>> + vmf.pgoff = linear_page_index(vma, address);
>> + vmf.gfp_mask = __get_fault_gfp_mask(vma);
>> + vmf.sequence = seq;
>> + vmf.flags = flags;
>> +
>> + local_irq_enable();
>> +
>> + /*
>> + * We need to re-validate the VMA after checking the bounds, otherwise
>> + * we might have a false positive on the bounds.
>> + */
>> + if (read_seqcount_retry(&vma->vm_sequence, seq))
>> + goto unlock;
>> +
>> + ret = handle_pte_fault(&vmf);
>> +
>> +unlock:
>> + srcu_read_unlock(&vma_srcu, idx);
>> + return ret;
>> +
>> +out_walk:
>> + local_irq_enable();
>> + goto unlock;
>> +}
>> +#endif /* __HAVE_ARCH_CALL_SPF */
>> +
>> /*
>> * By the time we get here, we already hold the mm semaphore
>> *
>> --
>> 2.7.4
>>
>
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-29 14:10 +0200 |
| Message-ID | <ujNvc-2sE-23@gated-at.bofh.it> |
| In reply to | #1722206 |
On Tue, Aug 29, 2017 at 09:59:30AM +0200, Laurent Dufour wrote: > On 27/08/2017 02:18, Kirill A. Shutemov wrote: > >> + > >> + if (unlikely(!vma->anon_vma)) > >> + goto unlock; > > > > It deserves a comment. > > You're right I'll add it in the next version. > For the record, the root cause is that __anon_vma_prepare() requires the > mmap_sem to be held because vm_next and vm_prev must be safe. But should that test not be: if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) goto unlock; Because !anon vmas will never have ->anon_vma set and you don't want to exclude those.
[toc] | [prev] | [next] | [standalone]
| From | Laurent Dufour <ldufour@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-08-29 15:20 +0200 |
| Message-ID | <ujOAW-37c-7@gated-at.bofh.it> |
| In reply to | #1722422 |
On 29/08/2017 14:04, Peter Zijlstra wrote: > On Tue, Aug 29, 2017 at 09:59:30AM +0200, Laurent Dufour wrote: >> On 27/08/2017 02:18, Kirill A. Shutemov wrote: >>>> + >>>> + if (unlikely(!vma->anon_vma)) >>>> + goto unlock; >>> >>> It deserves a comment. >> >> You're right I'll add it in the next version. >> For the record, the root cause is that __anon_vma_prepare() requires the >> mmap_sem to be held because vm_next and vm_prev must be safe. > > But should that test not be: > > if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) > goto unlock; > > Because !anon vmas will never have ->anon_vma set and you don't want to > exclude those. Yes in the case we later allow non anonymous vmas to be handled. Currently only anonymous vmas are supported so the check is good enough, isn't it ?
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-29 15:50 +0200 |
| Message-ID | <ujP3X-3gG-3@gated-at.bofh.it> |
| In reply to | #1722462 |
On Tue, Aug 29, 2017 at 03:18:25PM +0200, Laurent Dufour wrote: > On 29/08/2017 14:04, Peter Zijlstra wrote: > > On Tue, Aug 29, 2017 at 09:59:30AM +0200, Laurent Dufour wrote: > >> On 27/08/2017 02:18, Kirill A. Shutemov wrote: > >>>> + > >>>> + if (unlikely(!vma->anon_vma)) > >>>> + goto unlock; > >>> > >>> It deserves a comment. > >> > >> You're right I'll add it in the next version. > >> For the record, the root cause is that __anon_vma_prepare() requires the > >> mmap_sem to be held because vm_next and vm_prev must be safe. > > > > But should that test not be: > > > > if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) > > goto unlock; > > > > Because !anon vmas will never have ->anon_vma set and you don't want to > > exclude those. > > Yes in the case we later allow non anonymous vmas to be handled. > Currently only anonymous vmas are supported so the check is good enough, > isn't it ? That wasn't at all clear from reading the code. This makes it clear ->anon_vma is only ever looked at for anonymous. And like Kirill says, we _really_ should start allowing some (if not all) vm_ops. Large file based mappings aren't particularly rare. I'm not sure we want to introduce a white-list or just bite the bullet and audit all ->fault() implementations. But either works and isn't terribly difficult, auditing all is more work though.
[toc] | [prev] | [next] | [standalone]
| From | Anshuman Khandual <khandual@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-08-30 07:10 +0200 |
| Message-ID | <uk3qh-44H-3@gated-at.bofh.it> |
| In reply to | #1722500 |
On 08/29/2017 07:15 PM, Peter Zijlstra wrote:
> On Tue, Aug 29, 2017 at 03:18:25PM +0200, Laurent Dufour wrote:
>> On 29/08/2017 14:04, Peter Zijlstra wrote:
>>> On Tue, Aug 29, 2017 at 09:59:30AM +0200, Laurent Dufour wrote:
>>>> On 27/08/2017 02:18, Kirill A. Shutemov wrote:
>>>>>> +
>>>>>> + if (unlikely(!vma->anon_vma))
>>>>>> + goto unlock;
>>>>>
>>>>> It deserves a comment.
>>>>
>>>> You're right I'll add it in the next version.
>>>> For the record, the root cause is that __anon_vma_prepare() requires the
>>>> mmap_sem to be held because vm_next and vm_prev must be safe.
>>>
>>> But should that test not be:
>>>
>>> if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma))
>>> goto unlock;
>>>
>>> Because !anon vmas will never have ->anon_vma set and you don't want to
>>> exclude those.
>>
>> Yes in the case we later allow non anonymous vmas to be handled.
>> Currently only anonymous vmas are supported so the check is good enough,
>> isn't it ?
>
> That wasn't at all clear from reading the code. This makes it clear
> ->anon_vma is only ever looked at for anonymous.
>
> And like Kirill says, we _really_ should start allowing some (if not
> all) vm_ops. Large file based mappings aren't particularly rare.
>
> I'm not sure we want to introduce a white-list or just bite the bullet
> and audit all ->fault() implementations. But either works and isn't
> terribly difficult, auditing all is more work though.
filemap_fault() is used as vma-vm_ops->fault() for most of the file
systems. Changing it can enable speculative fault support for all of
them. It will still exclude other driver based vma-vm_ops->fault()
implementation. AFAICS, __lock_page_or_retry() function can drop
mm->mmap_sem if the page could not be locked right away. As suggested
by Peterz, making it understand FAULT_FLAG_SPECULATIVE should be good
enough. The patch is lightly tested for file mappings on top of this
series.
diff --git a/mm/filemap.c b/mm/filemap.c
index a497024..08f3042 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1181,6 +1181,18 @@ int __lock_page_killable(struct page *__page)
int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
unsigned int flags)
{
+ if (flags & FAULT_FLAG_SPECULATIVE) {
+ if (flags & FAULT_FLAG_KILLABLE) {
+ int ret;
+
+ ret = __lock_page_killable(page);
+ if (ret)
+ return 0;
+ } else
+ __lock_page(page);
+ return 1;
+ }
+
if (flags & FAULT_FLAG_ALLOW_RETRY) {
/*
* CAUTION! In this case, mmap_sem is not released
diff --git a/mm/memory.c b/mm/memory.c
index 549d235..02347f3 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3836,8 +3836,6 @@ static int handle_pte_fault(struct vm_fault *vmf)
if (!vmf->pte) {
if (vma_is_anonymous(vmf->vma))
return do_anonymous_page(vmf);
- else if (vmf->flags & FAULT_FLAG_SPECULATIVE)
- return VM_FAULT_RETRY;
else
return do_fault(vmf);
}
@@ -4012,17 +4010,7 @@ int handle_speculative_fault(struct mm_struct *mm, unsigned long address,
goto unlock;
}
- /*
- * Can't call vm_ops service has we don't know what they would do
- * with the VMA.
- * This include huge page from hugetlbfs.
- */
- if (vma->vm_ops) {
- trace_spf_vma_notsup(_RET_IP_, vma, address);
- goto unlock;
- }
-
- if (unlikely(!vma->anon_vma)) {
+ if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) {
trace_spf_vma_notsup(_RET_IP_, vma, address);
goto unlock;
}
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-30 08:00 +0200 |
| Message-ID | <uk4cH-4mT-11@gated-at.bofh.it> |
| In reply to | #1723022 |
On Wed, Aug 30, 2017 at 10:33:50AM +0530, Anshuman Khandual wrote:
> diff --git a/mm/filemap.c b/mm/filemap.c
> index a497024..08f3042 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -1181,6 +1181,18 @@ int __lock_page_killable(struct page *__page)
> int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
> unsigned int flags)
> {
> + if (flags & FAULT_FLAG_SPECULATIVE) {
> + if (flags & FAULT_FLAG_KILLABLE) {
> + int ret;
> +
> + ret = __lock_page_killable(page);
> + if (ret)
> + return 0;
> + } else
> + __lock_page(page);
> + return 1;
> + }
> +
> if (flags & FAULT_FLAG_ALLOW_RETRY) {
> /*
> * CAUTION! In this case, mmap_sem is not released
Yeah, that looks right.
> @@ -4012,17 +4010,7 @@ int handle_speculative_fault(struct mm_struct *mm, unsigned long address,
> goto unlock;
> }
>
> + if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) {
> trace_spf_vma_notsup(_RET_IP_, vma, address);
> goto unlock;
> }
As riel pointed out on IRC slightly later, private file maps also need
->anon_vma and those actually have ->vm_ops IIRC so the condition needs
to be slightly more complicated.
[toc] | [prev] | [next] | [standalone]
| From | Laurent Dufour <ldufour@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-08-30 11:40 +0200 |
| Message-ID | <uk7Dz-6yY-5@gated-at.bofh.it> |
| In reply to | #1723043 |
On 30/08/2017 07:58, Peter Zijlstra wrote:
> On Wed, Aug 30, 2017 at 10:33:50AM +0530, Anshuman Khandual wrote:
>> diff --git a/mm/filemap.c b/mm/filemap.c
>> index a497024..08f3042 100644
>> --- a/mm/filemap.c
>> +++ b/mm/filemap.c
>> @@ -1181,6 +1181,18 @@ int __lock_page_killable(struct page *__page)
>> int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
>> unsigned int flags)
>> {
>> + if (flags & FAULT_FLAG_SPECULATIVE) {
>> + if (flags & FAULT_FLAG_KILLABLE) {
>> + int ret;
>> +
>> + ret = __lock_page_killable(page);
>> + if (ret)
>> + return 0;
>> + } else
>> + __lock_page(page);
>> + return 1;
>> + }
>> +
>> if (flags & FAULT_FLAG_ALLOW_RETRY) {
>> /*
>> * CAUTION! In this case, mmap_sem is not released
>
> Yeah, that looks right.
Hum, I'm wondering if FAULT_FLAG_RETRY_NOWAIT should be forced in the
speculative path in that case to match the semantics of
__lock_page_or_retry().
>
>> @@ -4012,17 +4010,7 @@ int handle_speculative_fault(struct mm_struct *mm, unsigned long address,
>> goto unlock;
>> }
>>
>> + if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) {
>> trace_spf_vma_notsup(_RET_IP_, vma, address);
>> goto unlock;
>> }
>
> As riel pointed out on IRC slightly later, private file maps also need
> ->anon_vma and those actually have ->vm_ops IIRC so the condition needs
> to be slightly more complicated.
Yes I read again the code and lead to the same conclusion.
[toc] | [prev] | [next] | [standalone]
| From | Anshuman Khandual <khandual@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-08-31 09:00 +0200 |
| Message-ID | <ukrCi-2fq-7@gated-at.bofh.it> |
| In reply to | #1723156 |
On 08/30/2017 03:02 PM, Laurent Dufour wrote:
> On 30/08/2017 07:58, Peter Zijlstra wrote:
>> On Wed, Aug 30, 2017 at 10:33:50AM +0530, Anshuman Khandual wrote:
>>> diff --git a/mm/filemap.c b/mm/filemap.c
>>> index a497024..08f3042 100644
>>> --- a/mm/filemap.c
>>> +++ b/mm/filemap.c
>>> @@ -1181,6 +1181,18 @@ int __lock_page_killable(struct page *__page)
>>> int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
>>> unsigned int flags)
>>> {
>>> + if (flags & FAULT_FLAG_SPECULATIVE) {
>>> + if (flags & FAULT_FLAG_KILLABLE) {
>>> + int ret;
>>> +
>>> + ret = __lock_page_killable(page);
>>> + if (ret)
>>> + return 0;
>>> + } else
>>> + __lock_page(page);
>>> + return 1;
>>> + }
>>> +
>>> if (flags & FAULT_FLAG_ALLOW_RETRY) {
>>> /*
>>> * CAUTION! In this case, mmap_sem is not released
>>
>> Yeah, that looks right.
>
> Hum, I'm wondering if FAULT_FLAG_RETRY_NOWAIT should be forced in the
> speculative path in that case to match the semantics of
> __lock_page_or_retry().
Doing that would force us to have another retry through classic fault
path wasting all the work done till now through SPF. Hence it may be
better to just wait, get the lock here and complete the fault. Peterz,
would you agree ? Or we should do as suggested by Laurent. More over,
forcing FAULT_FLAG_RETRY_NOWAIT on FAULT_FLAG_SPECULTIVE at this point
would look like a hack.
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-08-31 09:40 +0200 |
| Message-ID | <uksf2-2Jn-49@gated-at.bofh.it> |
| In reply to | #1723876 |
On Thu, Aug 31, 2017 at 12:25:16PM +0530, Anshuman Khandual wrote:
> On 08/30/2017 03:02 PM, Laurent Dufour wrote:
> > On 30/08/2017 07:58, Peter Zijlstra wrote:
> >> On Wed, Aug 30, 2017 at 10:33:50AM +0530, Anshuman Khandual wrote:
> >>> diff --git a/mm/filemap.c b/mm/filemap.c
> >>> index a497024..08f3042 100644
> >>> --- a/mm/filemap.c
> >>> +++ b/mm/filemap.c
> >>> @@ -1181,6 +1181,18 @@ int __lock_page_killable(struct page *__page)
> >>> int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
> >>> unsigned int flags)
> >>> {
> >>> + if (flags & FAULT_FLAG_SPECULATIVE) {
> >>> + if (flags & FAULT_FLAG_KILLABLE) {
> >>> + int ret;
> >>> +
> >>> + ret = __lock_page_killable(page);
> >>> + if (ret)
> >>> + return 0;
> >>> + } else
> >>> + __lock_page(page);
> >>> + return 1;
> >>> + }
> >>> +
> >>> if (flags & FAULT_FLAG_ALLOW_RETRY) {
> >>> /*
> >>> * CAUTION! In this case, mmap_sem is not released
> >>
> >> Yeah, that looks right.
> >
> > Hum, I'm wondering if FAULT_FLAG_RETRY_NOWAIT should be forced in the
> > speculative path in that case to match the semantics of
> > __lock_page_or_retry().
>
> Doing that would force us to have another retry through classic fault
> path wasting all the work done till now through SPF. Hence it may be
> better to just wait, get the lock here and complete the fault. Peterz,
> would you agree ? Or we should do as suggested by Laurent. More over,
> forcing FAULT_FLAG_RETRY_NOWAIT on FAULT_FLAG_SPECULTIVE at this point
> would look like a hack.
Is there ever a situation where SPECULATIVE and NOWAIT are used
together? That seems like something to avoid.
A git-grep seems to suggest gup() can set it, but gup() will not be
doing speculative faults. s390 also sets it, but then again, they don't
have speculative fault support yet and when they do they can avoid
setting them together.
So maybe put in a WARN_ON_ONCE() on having both of them, it is not
something that makes sense to me, but maybe someone sees a rationale for
it?
[toc] | [prev] | [next] | [standalone]
| From | Laurent Dufour <ldufour@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-08-30 12:00 +0200 |
| Message-ID | <uk7WW-6Hb-19@gated-at.bofh.it> |
| In reply to | #1723022 |
On 30/08/2017 07:03, Anshuman Khandual wrote:
> On 08/29/2017 07:15 PM, Peter Zijlstra wrote:
>> On Tue, Aug 29, 2017 at 03:18:25PM +0200, Laurent Dufour wrote:
>>> On 29/08/2017 14:04, Peter Zijlstra wrote:
>>>> On Tue, Aug 29, 2017 at 09:59:30AM +0200, Laurent Dufour wrote:
>>>>> On 27/08/2017 02:18, Kirill A. Shutemov wrote:
>>>>>>> +
>>>>>>> + if (unlikely(!vma->anon_vma))
>>>>>>> + goto unlock;
>>>>>>
>>>>>> It deserves a comment.
>>>>>
>>>>> You're right I'll add it in the next version.
>>>>> For the record, the root cause is that __anon_vma_prepare() requires the
>>>>> mmap_sem to be held because vm_next and vm_prev must be safe.
>>>>
>>>> But should that test not be:
>>>>
>>>> if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma))
>>>> goto unlock;
>>>>
>>>> Because !anon vmas will never have ->anon_vma set and you don't want to
>>>> exclude those.
>>>
>>> Yes in the case we later allow non anonymous vmas to be handled.
>>> Currently only anonymous vmas are supported so the check is good enough,
>>> isn't it ?
>>
>> That wasn't at all clear from reading the code. This makes it clear
>> ->anon_vma is only ever looked at for anonymous.
>>
>> And like Kirill says, we _really_ should start allowing some (if not
>> all) vm_ops. Large file based mappings aren't particularly rare.
>>
>> I'm not sure we want to introduce a white-list or just bite the bullet
>> and audit all ->fault() implementations. But either works and isn't
>> terribly difficult, auditing all is more work though.
>
> filemap_fault() is used as vma-vm_ops->fault() for most of the file
> systems. Changing it can enable speculative fault support for all of
> them. It will still exclude other driver based vma-vm_ops->fault()
> implementation. AFAICS, __lock_page_or_retry() function can drop
> mm->mmap_sem if the page could not be locked right away. As suggested
> by Peterz, making it understand FAULT_FLAG_SPECULATIVE should be good
> enough. The patch is lightly tested for file mappings on top of this
> series.
Hi Anshuman,
This sounds pretty good, except for the FAULT_FLAG_RETRY_NOWAIT's case I
mentioned in another mail.
The next step would be to find a way to discriminate between the vm_fault()
functions. Any idea ?
Thanks,
Laurent.
>
> diff --git a/mm/filemap.c b/mm/filemap.c
> index a497024..08f3042 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -1181,6 +1181,18 @@ int __lock_page_killable(struct page *__page)
> int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
> unsigned int flags)
> {
> + if (flags & FAULT_FLAG_SPECULATIVE) {
> + if (flags & FAULT_FLAG_KILLABLE) {
> + int ret;
> +
> + ret = __lock_page_killable(page);
> + if (ret)
> + return 0;
> + } else
> + __lock_page(page);
> + return 1;
> + }
> +
> if (flags & FAULT_FLAG_ALLOW_RETRY) {
> /*
> * CAUTION! In this case, mmap_sem is not released
> diff --git a/mm/memory.c b/mm/memory.c
> index 549d235..02347f3 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -3836,8 +3836,6 @@ static int handle_pte_fault(struct vm_fault *vmf)
> if (!vmf->pte) {
> if (vma_is_anonymous(vmf->vma))
> return do_anonymous_page(vmf);
> - else if (vmf->flags & FAULT_FLAG_SPECULATIVE)
> - return VM_FAULT_RETRY;
> else
> return do_fault(vmf);
> }
> @@ -4012,17 +4010,7 @@ int handle_speculative_fault(struct mm_struct *mm, unsigned long address,
> goto unlock;
> }
>
> - /*
> - * Can't call vm_ops service has we don't know what they would do
> - * with the VMA.
> - * This include huge page from hugetlbfs.
> - */
> - if (vma->vm_ops) {
> - trace_spf_vma_notsup(_RET_IP_, vma, address);
> - goto unlock;
> - }
> -
> - if (unlikely(!vma->anon_vma)) {
> + if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) {
> trace_spf_vma_notsup(_RET_IP_, vma, address);
> goto unlock;
> }
>
[toc] | [prev] | [next] | [standalone]
| From | Anshuman Khandual <khandual@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-08-30 05:50 +0200 |
| Message-ID | <uk2aR-38o-3@gated-at.bofh.it> |
| In reply to | #1722422 |
On 08/29/2017 05:34 PM, Peter Zijlstra wrote: > On Tue, Aug 29, 2017 at 09:59:30AM +0200, Laurent Dufour wrote: >> On 27/08/2017 02:18, Kirill A. Shutemov wrote: >>>> + >>>> + if (unlikely(!vma->anon_vma)) >>>> + goto unlock; >>> It deserves a comment. >> You're right I'll add it in the next version. >> For the record, the root cause is that __anon_vma_prepare() requires the >> mmap_sem to be held because vm_next and vm_prev must be safe. > But should that test not be: > > if (unlikely(vma_is_anonymous(vma) && !vma->anon_vma)) > goto unlock; This makes more sense. We are backing off from speculative path because struct anon_vma has not been created for this anonymous vma and we cannot do that without holding mmap_sem. This should have nothing to do with vma->vm_ops availability.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web