lkml.org 
[lkml]   [2015]   [Nov]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2/2] s390/mm: allow gmap code to retry on faulting in guest memory
    Date
    The userfaultfd does need FAULT_FLAG_ALLOW_RETRY to not return
    VM_FAULT_SIGBUS. So we improve the gmap code to handle one
    VM_FAULT_RETRY.

    Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
    ---
    arch/s390/mm/pgtable.c | 28 ++++++++++++++++++++++++----
    1 file changed, 24 insertions(+), 4 deletions(-)

    diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
    index 54ef3bc..8a0025d 100644
    --- a/arch/s390/mm/pgtable.c
    +++ b/arch/s390/mm/pgtable.c
    @@ -577,15 +577,22 @@ int gmap_fault(struct gmap *gmap, unsigned long gaddr,
    unsigned int fault_flags)
    {
    unsigned long vmaddr;
    - int rc;
    + int rc, fault;

    + fault_flags |= FAULT_FLAG_ALLOW_RETRY;
    +retry:
    down_read(&gmap->mm->mmap_sem);
    vmaddr = __gmap_translate(gmap, gaddr);
    if (IS_ERR_VALUE(vmaddr)) {
    rc = vmaddr;
    goto out_up;
    }
    - if (fixup_user_fault(current, gmap->mm, vmaddr, fault_flags)) {
    + fault = fixup_user_fault(current, gmap->mm, vmaddr, fault_flags);
    + if (fault & VM_FAULT_RETRY) {
    + fault_flags &= ~FAULT_FLAG_ALLOW_RETRY;
    + fault_flags |= FAULT_FLAG_TRIED;
    + goto retry;
    + } else if (fault) {
    rc = -EFAULT;
    goto out_up;
    }
    @@ -717,10 +724,13 @@ int gmap_ipte_notify(struct gmap *gmap, unsigned long gaddr, unsigned long len)
    spinlock_t *ptl;
    pte_t *ptep, entry;
    pgste_t pgste;
    + int fault, fault_flags;
    int rc = 0;

    + fault_flags = FAULT_FLAG_WRITE | FAULT_FLAG_ALLOW_RETRY;
    if ((gaddr & ~PAGE_MASK) || (len & ~PAGE_MASK))
    return -EINVAL;
    +retry:
    down_read(&gmap->mm->mmap_sem);
    while (len) {
    /* Convert gmap address and connect the page tables */
    @@ -730,7 +740,12 @@ int gmap_ipte_notify(struct gmap *gmap, unsigned long gaddr, unsigned long len)
    break;
    }
    /* Get the page mapped */
    - if (fixup_user_fault(current, gmap->mm, addr, FAULT_FLAG_WRITE)) {
    + fault = fixup_user_fault(current, gmap->mm, addr, fault_flags);
    + if (fault & VM_FAULT_RETRY) {
    + fault_flags &= ~FAULT_FLAG_ALLOW_RETRY;
    + fault_flags |= FAULT_FLAG_TRIED;
    + goto retry;
    + } else if (fault) {
    rc = -EFAULT;
    break;
    }
    @@ -794,7 +809,9 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
    spinlock_t *ptl;
    pgste_t old, new;
    pte_t *ptep;
    + int fault, fault_flags;

    + fault_flags = FAULT_FLAG_WRITE | FAULT_FLAG_ALLOW_RETRY;
    down_read(&mm->mmap_sem);
    retry:
    ptep = get_locked_pte(mm, addr, &ptl);
    @@ -805,10 +822,13 @@ retry:
    if (!(pte_val(*ptep) & _PAGE_INVALID) &&
    (pte_val(*ptep) & _PAGE_PROTECT)) {
    pte_unmap_unlock(ptep, ptl);
    - if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) {
    + fault = fixup_user_fault(current, mm, addr, fault_flags);
    + if (fault && !(fault & VM_FAULT_RETRY)) {
    up_read(&mm->mmap_sem);
    return -EFAULT;
    }
    + fault_flags &= ~FAULT_FLAG_ALLOW_RETRY;
    + fault_flags |= FAULT_FLAG_TRIED;
    goto retry;
    }

    --
    2.3.9


    \
     
     \ /
      Last update: 2015-11-19 01:21    [W:4.811 / U:1.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site