struct list_head *pagelist;
        unsigned long flags;
        nodemask_t *nmask;
-       struct vm_area_struct *prev;
+       unsigned long start;
+       unsigned long end;
+       struct vm_area_struct *first;
 };
 
 /*
        unsigned long flags = qp->flags;
 
        /* range check first */
-       if (!(flags & MPOL_MF_DISCONTIG_OK)) {
-               if (!vma->vm_next && vma->vm_end < end)
-                       return -EFAULT;
-               if (qp->prev && qp->prev->vm_end < vma->vm_start)
+       VM_BUG_ON((vma->vm_start > start) || (vma->vm_end < end));
+
+       if (!qp->first) {
+               qp->first = vma;
+               if (!(flags & MPOL_MF_DISCONTIG_OK) &&
+                       (qp->start < vma->vm_start))
+                       /* hole at head side of range */
                        return -EFAULT;
        }
-
-       qp->prev = vma;
+       if (!(flags & MPOL_MF_DISCONTIG_OK) &&
+               ((vma->vm_end < qp->end) &&
+               (!vma->vm_next || vma->vm_end < vma->vm_next->vm_start)))
+               /* hole at middle or tail of range */
+               return -EFAULT;
 
        /*
         * Need check MPOL_MF_STRICT to return -EIO if possible
 
        if (endvma > end)
                endvma = end;
-       if (vma->vm_start > start)
-               start = vma->vm_start;
 
        if (flags & MPOL_MF_LAZY) {
                /* Similar to task_numa_work, skip inaccessible VMAs */
                nodemask_t *nodes, unsigned long flags,
                struct list_head *pagelist)
 {
+       int err;
        struct queue_pages qp = {
                .pagelist = pagelist,
                .flags = flags,
                .nmask = nodes,
-               .prev = NULL,
+               .start = start,
+               .end = end,
+               .first = NULL,
        };
 
-       return walk_page_range(mm, start, end, &queue_pages_walk_ops, &qp);
+       err = walk_page_range(mm, start, end, &queue_pages_walk_ops, &qp);
+
+       if (!qp.first)
+               /* whole range in hole */
+               err = -EFAULT;
+
+       return err;
 }
 
 /*
        unsigned long vmend;
 
        vma = find_vma(mm, start);
-       if (!vma || vma->vm_start > start)
-               return -EFAULT;
+       VM_BUG_ON(!vma);
 
        prev = vma->vm_prev;
        if (start > vma->vm_start)