Use the general page fault accounting by passing regs into handle_mm_fault(). It naturally solve the issue of multiple page fault accounting when page fault retry happened. Fix PERF_COUNT_SW_PAGE_FAULTS perf event manually for page fault retries, by moving it before taking mmap_sem.
Unified · Split
| @@ -121,6 +121,8 @@ void do_page_fault(unsigned long entry, unsigned long addr, · 120 unmodified lines | ||
| 121 | 121 | if (unlikely(faulthandler_disabled() || !mm)) |
| 122 | 122 | goto no_context; |
| 123 | 123 | |
| 124 | + perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); | |
| 125 | + | |
| 124 | 126 | /* |
| 125 | 127 | * As per x86, we may deadlock here. However, since the kernel only |
| 126 | 128 | * validly references user space from well defined areas of the code, |
| @@ -206,7 +208,7 @@ good_area: · 79 unmodified lines | ||
| 206 | 208 | * the fault. |
| 207 | 209 | */ |
| 208 | 210 | |
| 209 | − fault = handle_mm_fault(vma, addr, flags, NULL); | |
| 211 | + fault = handle_mm_fault(vma, addr, flags, regs); | |
| 210 | 212 | |
| 211 | 213 | /* |
| 212 | 214 | * If we need to retry but a fatal signal is pending, handle the |
| @@ -228,22 +230,7 @@ good_area: · 15 unmodified lines | ||
| 228 | 230 | goto bad_area; |
| 229 | 231 | } |
| 230 | 232 | |
| 231 | − /* | |
| 232 | − * Major/minor page fault accounting is only done on the initial | |
| 233 | − * attempt. If we go through a retry, it is extremely likely that the | |
| 234 | − * page will be found in page cache at that point. | |
| 235 | − */ | |
| 236 | − perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); | |
| 237 | 233 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
| 238 | − if (fault & VM_FAULT_MAJOR) { | |
| 239 | − tsk->maj_flt++; | |
| 240 | − perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, | |
| 241 | − 1, regs, addr); | |
| 242 | − } else { | |
| 243 | − tsk->min_flt++; | |
| 244 | − perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, | |
| 245 | − 1, regs, addr); | |
| 246 | − } | |
| 247 | 234 | if (fault & VM_FAULT_RETRY) { |
| 248 | 235 | flags |= FAULT_FLAG_TRIED; |
| 249 | 236 | |