@@ -4065,7 +4065,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
4065
4065
long follow_hugetlb_page (struct mm_struct * mm , struct vm_area_struct * vma ,
4066
4066
struct page * * pages , struct vm_area_struct * * vmas ,
4067
4067
unsigned long * position , unsigned long * nr_pages ,
4068
- long i , unsigned int flags )
4068
+ long i , unsigned int flags , int * nonblocking )
4069
4069
{
4070
4070
unsigned long pfn_offset ;
4071
4071
unsigned long vaddr = * position ;
@@ -4128,16 +4128,43 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
4128
4128
((flags & FOLL_WRITE ) &&
4129
4129
!huge_pte_write (huge_ptep_get (pte )))) {
4130
4130
int ret ;
4131
+ unsigned int fault_flags = 0 ;
4131
4132
4132
4133
if (pte )
4133
4134
spin_unlock (ptl );
4134
- ret = hugetlb_fault (mm , vma , vaddr ,
4135
- (flags & FOLL_WRITE ) ? FAULT_FLAG_WRITE : 0 );
4136
- if (!(ret & VM_FAULT_ERROR ))
4137
- continue ;
4138
-
4139
- remainder = 0 ;
4140
- break ;
4135
+ if (flags & FOLL_WRITE )
4136
+ fault_flags |= FAULT_FLAG_WRITE ;
4137
+ if (nonblocking )
4138
+ fault_flags |= FAULT_FLAG_ALLOW_RETRY ;
4139
+ if (flags & FOLL_NOWAIT )
4140
+ fault_flags |= FAULT_FLAG_ALLOW_RETRY |
4141
+ FAULT_FLAG_RETRY_NOWAIT ;
4142
+ if (flags & FOLL_TRIED ) {
4143
+ VM_WARN_ON_ONCE (fault_flags &
4144
+ FAULT_FLAG_ALLOW_RETRY );
4145
+ fault_flags |= FAULT_FLAG_TRIED ;
4146
+ }
4147
+ ret = hugetlb_fault (mm , vma , vaddr , fault_flags );
4148
+ if (ret & VM_FAULT_ERROR ) {
4149
+ remainder = 0 ;
4150
+ break ;
4151
+ }
4152
+ if (ret & VM_FAULT_RETRY ) {
4153
+ if (nonblocking )
4154
+ * nonblocking = 0 ;
4155
+ * nr_pages = 0 ;
4156
+ /*
4157
+ * VM_FAULT_RETRY must not return an
4158
+ * error, it will return zero
4159
+ * instead.
4160
+ *
4161
+ * No need to update "position" as the
4162
+ * caller will not check it after
4163
+ * *nr_pages is set to 0.
4164
+ */
4165
+ return i ;
4166
+ }
4167
+ continue ;
4141
4168
}
4142
4169
4143
4170
pfn_offset = (vaddr & ~huge_page_mask (h )) >> PAGE_SHIFT ;
@@ -4166,6 +4193,11 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
4166
4193
spin_unlock (ptl );
4167
4194
}
4168
4195
* nr_pages = remainder ;
4196
+ /*
4197
+ * setting position is actually required only if remainder is
4198
+ * not zero but it's faster not to add a "if (remainder)"
4199
+ * branch.
4200
+ */
4169
4201
* position = vaddr ;
4170
4202
4171
4203
return i ? i : - EFAULT ;
0 commit comments