diff options
| author | Shaohua Li <shli@kernel.org> | 2012-10-08 19:32:19 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:22:47 -0400 |
| commit | 45cac65b0fcd287ebb877b141d40ba9bbe8e5da7 (patch) | |
| tree | 30ed25c91aaeed153de51a78d171cb14582e383f | |
| parent | e79bee24fd6134f90af4228cfebd010136d67631 (diff) | |
readahead: fault retry breaks mmap file read random detection
.fault now can retry. The retry can break state machine of .fault. In
filemap_fault, if page is miss, ra->mmap_miss is increased. In the second
try, since the page is in page cache now, ra->mmap_miss is decreased. And
these are done in one fault, so we can't detect random mmap file access.
Add a new flag to indicate .fault is tried once. In the second try, skip
ra->mmap_miss decreasing. The filemap_fault state machine is ok with it.
I only tested x86, didn't test other archs, but looks the change for other
archs is obvious, but who knows :)
Signed-off-by: Shaohua Li <shaohua.li@fusionio.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | arch/arm/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/avr32/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/cris/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/hexagon/mm/vm_fault.c | 1 | ||||
| -rw-r--r-- | arch/ia64/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/m68k/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/microblaze/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/mips/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/openrisc/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/s390/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/sh/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/sparc/mm/fault_32.c | 1 | ||||
| -rw-r--r-- | arch/sparc/mm/fault_64.c | 1 | ||||
| -rw-r--r-- | arch/tile/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/um/kernel/trap.c | 1 | ||||
| -rw-r--r-- | arch/x86/mm/fault.c | 1 | ||||
| -rw-r--r-- | arch/xtensa/mm/fault.c | 1 | ||||
| -rw-r--r-- | include/linux/mm.h | 1 | ||||
| -rw-r--r-- | mm/filemap.c | 4 |
20 files changed, 21 insertions, 2 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index c3bd8345022..5dbf13f954f 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
| @@ -336,6 +336,7 @@ retry: | |||
| 336 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | 336 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk |
| 337 | * of starvation. */ | 337 | * of starvation. */ |
| 338 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 338 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 339 | flags |= FAULT_FLAG_TRIED; | ||
| 339 | goto retry; | 340 | goto retry; |
| 340 | } | 341 | } |
| 341 | } | 342 | } |
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index b92e6095861..b2f2d2d6684 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c | |||
| @@ -152,6 +152,7 @@ good_area: | |||
| 152 | tsk->min_flt++; | 152 | tsk->min_flt++; |
| 153 | if (fault & VM_FAULT_RETRY) { | 153 | if (fault & VM_FAULT_RETRY) { |
| 154 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 154 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 155 | flags |= FAULT_FLAG_TRIED; | ||
| 155 | 156 | ||
| 156 | /* | 157 | /* |
| 157 | * No need to up_read(&mm->mmap_sem) as we would have | 158 | * No need to up_read(&mm->mmap_sem) as we would have |
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index 45fd542cf17..73312ab6c69 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c | |||
| @@ -186,6 +186,7 @@ retry: | |||
| 186 | tsk->min_flt++; | 186 | tsk->min_flt++; |
| 187 | if (fault & VM_FAULT_RETRY) { | 187 | if (fault & VM_FAULT_RETRY) { |
| 188 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 188 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 189 | flags |= FAULT_FLAG_TRIED; | ||
| 189 | 190 | ||
| 190 | /* | 191 | /* |
| 191 | * No need to up_read(&mm->mmap_sem) as we would | 192 | * No need to up_read(&mm->mmap_sem) as we would |
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c index 06695cc4fe5..513b74cb397 100644 --- a/arch/hexagon/mm/vm_fault.c +++ b/arch/hexagon/mm/vm_fault.c | |||
| @@ -113,6 +113,7 @@ good_area: | |||
| 113 | current->min_flt++; | 113 | current->min_flt++; |
| 114 | if (fault & VM_FAULT_RETRY) { | 114 | if (fault & VM_FAULT_RETRY) { |
| 115 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 115 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 116 | flags |= FAULT_FLAG_TRIED; | ||
| 116 | goto retry; | 117 | goto retry; |
| 117 | } | 118 | } |
| 118 | } | 119 | } |
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 8443daf4f51..6cf0341f978 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c | |||
| @@ -184,6 +184,7 @@ retry: | |||
| 184 | current->min_flt++; | 184 | current->min_flt++; |
| 185 | if (fault & VM_FAULT_RETRY) { | 185 | if (fault & VM_FAULT_RETRY) { |
| 186 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 186 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 187 | flags |= FAULT_FLAG_TRIED; | ||
| 187 | 188 | ||
| 188 | /* No need to up_read(&mm->mmap_sem) as we would | 189 | /* No need to up_read(&mm->mmap_sem) as we would |
| 189 | * have already released it in __lock_page_or_retry | 190 | * have already released it in __lock_page_or_retry |
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index aeebbb7b30f..a563727806b 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c | |||
| @@ -170,6 +170,7 @@ good_area: | |||
| 170 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | 170 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk |
| 171 | * of starvation. */ | 171 | * of starvation. */ |
| 172 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 172 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 173 | flags |= FAULT_FLAG_TRIED; | ||
| 173 | 174 | ||
| 174 | /* | 175 | /* |
| 175 | * No need to up_read(&mm->mmap_sem) as we would | 176 | * No need to up_read(&mm->mmap_sem) as we would |
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c index eb365d6795f..714b35a9c4f 100644 --- a/arch/microblaze/mm/fault.c +++ b/arch/microblaze/mm/fault.c | |||
| @@ -233,6 +233,7 @@ good_area: | |||
| 233 | current->min_flt++; | 233 | current->min_flt++; |
| 234 | if (fault & VM_FAULT_RETRY) { | 234 | if (fault & VM_FAULT_RETRY) { |
| 235 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 235 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 236 | flags |= FAULT_FLAG_TRIED; | ||
| 236 | 237 | ||
| 237 | /* | 238 | /* |
| 238 | * No need to up_read(&mm->mmap_sem) as we would | 239 | * No need to up_read(&mm->mmap_sem) as we would |
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index c14f6dfed99..9f513486af1 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c | |||
| @@ -171,6 +171,7 @@ good_area: | |||
| 171 | } | 171 | } |
| 172 | if (fault & VM_FAULT_RETRY) { | 172 | if (fault & VM_FAULT_RETRY) { |
| 173 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 173 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 174 | flags |= FAULT_FLAG_TRIED; | ||
| 174 | 175 | ||
| 175 | /* | 176 | /* |
| 176 | * No need to up_read(&mm->mmap_sem) as we would | 177 | * No need to up_read(&mm->mmap_sem) as we would |
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c index 40f850e9766..e2bfafce66c 100644 --- a/arch/openrisc/mm/fault.c +++ b/arch/openrisc/mm/fault.c | |||
| @@ -183,6 +183,7 @@ good_area: | |||
| 183 | tsk->min_flt++; | 183 | tsk->min_flt++; |
| 184 | if (fault & VM_FAULT_RETRY) { | 184 | if (fault & VM_FAULT_RETRY) { |
| 185 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 185 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 186 | flags |= FAULT_FLAG_TRIED; | ||
| 186 | 187 | ||
| 187 | /* No need to up_read(&mm->mmap_sem) as we would | 188 | /* No need to up_read(&mm->mmap_sem) as we would |
| 188 | * have already released it in __lock_page_or_retry | 189 | * have already released it in __lock_page_or_retry |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 5495ebe983a..0a6b28336eb 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -451,6 +451,7 @@ good_area: | |||
| 451 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | 451 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk |
| 452 | * of starvation. */ | 452 | * of starvation. */ |
| 453 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 453 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 454 | flags |= FAULT_FLAG_TRIED; | ||
| 454 | goto retry; | 455 | goto retry; |
| 455 | } | 456 | } |
| 456 | } | 457 | } |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index ac9122ca115..04ad4001a28 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
| @@ -367,6 +367,7 @@ retry: | |||
| 367 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | 367 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk |
| 368 | * of starvation. */ | 368 | * of starvation. */ |
| 369 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 369 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 370 | flags |= FAULT_FLAG_TRIED; | ||
| 370 | down_read(&mm->mmap_sem); | 371 | down_read(&mm->mmap_sem); |
| 371 | goto retry; | 372 | goto retry; |
| 372 | } | 373 | } |
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 3bdc1ad9a34..cbbdcad8fcb 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c | |||
| @@ -504,6 +504,7 @@ good_area: | |||
| 504 | } | 504 | } |
| 505 | if (fault & VM_FAULT_RETRY) { | 505 | if (fault & VM_FAULT_RETRY) { |
| 506 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 506 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 507 | flags |= FAULT_FLAG_TRIED; | ||
| 507 | 508 | ||
| 508 | /* | 509 | /* |
| 509 | * No need to up_read(&mm->mmap_sem) as we would | 510 | * No need to up_read(&mm->mmap_sem) as we would |
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index 77ac917be15..e98bfda205a 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c | |||
| @@ -265,6 +265,7 @@ good_area: | |||
| 265 | } | 265 | } |
| 266 | if (fault & VM_FAULT_RETRY) { | 266 | if (fault & VM_FAULT_RETRY) { |
| 267 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 267 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 268 | flags |= FAULT_FLAG_TRIED; | ||
| 268 | 269 | ||
| 269 | /* No need to up_read(&mm->mmap_sem) as we would | 270 | /* No need to up_read(&mm->mmap_sem) as we would |
| 270 | * have already released it in __lock_page_or_retry | 271 | * have already released it in __lock_page_or_retry |
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 1fe0429b631..413d2926330 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
| @@ -452,6 +452,7 @@ good_area: | |||
| 452 | } | 452 | } |
| 453 | if (fault & VM_FAULT_RETRY) { | 453 | if (fault & VM_FAULT_RETRY) { |
| 454 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 454 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 455 | flags |= FAULT_FLAG_TRIED; | ||
| 455 | 456 | ||
| 456 | /* No need to up_read(&mm->mmap_sem) as we would | 457 | /* No need to up_read(&mm->mmap_sem) as we would |
| 457 | * have already released it in __lock_page_or_retry | 458 | * have already released it in __lock_page_or_retry |
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index 84ce7abbf5a..fe811fa5f1b 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c | |||
| @@ -454,6 +454,7 @@ good_area: | |||
| 454 | tsk->min_flt++; | 454 | tsk->min_flt++; |
| 455 | if (fault & VM_FAULT_RETRY) { | 455 | if (fault & VM_FAULT_RETRY) { |
| 456 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 456 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 457 | flags |= FAULT_FLAG_TRIED; | ||
| 457 | 458 | ||
| 458 | /* | 459 | /* |
| 459 | * No need to up_read(&mm->mmap_sem) as we would | 460 | * No need to up_read(&mm->mmap_sem) as we would |
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 0353b98ae35..0f00e9c8208 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
| @@ -89,6 +89,7 @@ good_area: | |||
| 89 | current->min_flt++; | 89 | current->min_flt++; |
| 90 | if (fault & VM_FAULT_RETRY) { | 90 | if (fault & VM_FAULT_RETRY) { |
| 91 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 91 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 92 | flags |= FAULT_FLAG_TRIED; | ||
| 92 | 93 | ||
| 93 | goto retry; | 94 | goto retry; |
| 94 | } | 95 | } |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index a530b230e7d..8e13ecb41be 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -1220,6 +1220,7 @@ good_area: | |||
| 1220 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | 1220 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk |
| 1221 | * of starvation. */ | 1221 | * of starvation. */ |
| 1222 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 1222 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 1223 | flags |= FAULT_FLAG_TRIED; | ||
| 1223 | goto retry; | 1224 | goto retry; |
| 1224 | } | 1225 | } |
| 1225 | } | 1226 | } |
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index 5a74c53bc69..2c2f710ed1d 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c | |||
| @@ -126,6 +126,7 @@ good_area: | |||
| 126 | current->min_flt++; | 126 | current->min_flt++; |
| 127 | if (fault & VM_FAULT_RETRY) { | 127 | if (fault & VM_FAULT_RETRY) { |
| 128 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 128 | flags &= ~FAULT_FLAG_ALLOW_RETRY; |
| 129 | flags |= FAULT_FLAG_TRIED; | ||
| 129 | 130 | ||
| 130 | /* No need to up_read(&mm->mmap_sem) as we would | 131 | /* No need to up_read(&mm->mmap_sem) as we would |
| 131 | * have already released it in __lock_page_or_retry | 132 | * have already released it in __lock_page_or_retry |
diff --git a/include/linux/mm.h b/include/linux/mm.h index b01e585ab4b..bcaab4e6fe9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -161,6 +161,7 @@ extern pgprot_t protection_map[16]; | |||
| 161 | #define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */ | 161 | #define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */ |
| 162 | #define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */ | 162 | #define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */ |
| 163 | #define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */ | 163 | #define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */ |
| 164 | #define FAULT_FLAG_TRIED 0x40 /* second try */ | ||
| 164 | 165 | ||
| 165 | /* | 166 | /* |
| 166 | * vm_fault is filled by the the pagefault handler and passed to the vma's | 167 | * vm_fault is filled by the the pagefault handler and passed to the vma's |
diff --git a/mm/filemap.c b/mm/filemap.c index a9827b42556..83efee76a5c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -1607,13 +1607,13 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 1607 | * Do we have something in the page cache already? | 1607 | * Do we have something in the page cache already? |
| 1608 | */ | 1608 | */ |
| 1609 | page = find_get_page(mapping, offset); | 1609 | page = find_get_page(mapping, offset); |
| 1610 | if (likely(page)) { | 1610 | if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) { |
| 1611 | /* | 1611 | /* |
| 1612 | * We found the page, so try async readahead before | 1612 | * We found the page, so try async readahead before |
| 1613 | * waiting for the lock. | 1613 | * waiting for the lock. |
| 1614 | */ | 1614 | */ |
| 1615 | do_async_mmap_readahead(vma, ra, file, page, offset); | 1615 | do_async_mmap_readahead(vma, ra, file, page, offset); |
| 1616 | } else { | 1616 | } else if (!page) { |
| 1617 | /* No page in the page cache at all */ | 1617 | /* No page in the page cache at all */ |
| 1618 | do_sync_mmap_readahead(vma, ra, file, offset); | 1618 | do_sync_mmap_readahead(vma, ra, file, offset); |
| 1619 | count_vm_event(PGMAJFAULT); | 1619 | count_vm_event(PGMAJFAULT); |
